mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-04-20 04:18:05 +00:00
Merge commit 'cd12677138a223eaf2b1579d27d3bf0addc1565e' into release/0.9.35
# Conflicts: # packages/editor-preset-vision/package.json # packages/rax-simulator-renderer/package.json # packages/react-renderer/package.json
This commit is contained in:
commit
114a279b59
11
CHANGELOG.md
11
CHANGELOG.md
@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"lerna": "2.11.0",
|
"lerna": "2.11.0",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"npmClient": "tyarn",
|
"npmClient": "tyarn",
|
||||||
"registry": "http://registry.npm.alibaba-inc.com",
|
"registry": "http://registry.npm.alibaba-inc.com",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-code-generator
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-code-generator",
|
"name": "@ali/lowcode-code-generator",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "出码引擎 for LowCode Engine",
|
"description": "出码引擎 for LowCode Engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-demo-server
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-demo-server",
|
"name": "@ali/lowcode-demo-server",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "低代码引擎 DEMO Server 端",
|
"description": "低代码引擎 DEMO Server 端",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||||
|
|
||||||
module.exports = ({ onGetWebpackConfig }) => {
|
module.exports = ({ context, onGetWebpackConfig }) => {
|
||||||
onGetWebpackConfig((config) => {
|
onGetWebpackConfig((config) => {
|
||||||
config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [
|
config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [
|
||||||
{
|
{
|
||||||
@ -9,5 +9,8 @@ module.exports = ({ onGetWebpackConfig }) => {
|
|||||||
]);
|
]);
|
||||||
config.plugins.delete('hot');
|
config.plugins.delete('hot');
|
||||||
config.devServer.hot(false);
|
config.devServer.hot(false);
|
||||||
|
if (context.command === 'start') {
|
||||||
|
config.devtool('inline-source-map');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,29 +1,30 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-demo",
|
"name": "@ali/lowcode-demo",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "低代码引擎 DEMO",
|
"description": "低代码引擎 DEMO",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cloud-build": "build-scripts build --config cloud-build.json",
|
"start": "build-scripts start",
|
||||||
"start": "build-scripts start"
|
"build": "build-scripts build",
|
||||||
|
"cloud-build": "build-scripts build --config cloud-build.json"
|
||||||
},
|
},
|
||||||
"config": {},
|
"config": {},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-skeleton": "^0.13.1-10",
|
"@ali/lowcode-editor-skeleton": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-components-pane": "^0.13.1-10",
|
"@ali/lowcode-plugin-components-pane": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-designer": "^0.13.1-10",
|
"@ali/lowcode-plugin-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-event-bind-dialog": "^0.13.1-10",
|
"@ali/lowcode-plugin-event-bind-dialog": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-outline-pane": "^0.13.1-10",
|
"@ali/lowcode-plugin-outline-pane": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-sample-logo": "^0.13.1-10",
|
"@ali/lowcode-plugin-sample-logo": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-sample-preview": "^0.13.1-10",
|
"@ali/lowcode-plugin-sample-preview": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-settings-pane": "^0.8.8",
|
"@ali/lowcode-plugin-settings-pane": "^0.8.8",
|
||||||
"@ali/lowcode-plugin-undo-redo": "^0.13.1-10",
|
"@ali/lowcode-plugin-undo-redo": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-variable-bind-dialog": "^0.13.1-10",
|
"@ali/lowcode-plugin-variable-bind-dialog": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-zh-en": "^0.13.1-10",
|
"@ali/lowcode-plugin-zh-en": "^0.13.1-11",
|
||||||
"@ali/lowcode-react-renderer": "^0.13.1-10",
|
"@ali/lowcode-react-renderer": "^0.13.1-11",
|
||||||
"@ali/lowcode-runtime": "^0.13.1-10",
|
"@ali/lowcode-runtime": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@ali/ve-action-pane": "^4.7.0-beta.0",
|
"@ali/ve-action-pane": "^4.7.0-beta.0",
|
||||||
"@ali/ve-datapool-pane": "^6.4.3",
|
"@ali/ve-datapool-pane": "^6.4.3",
|
||||||
"@ali/ve-history-pane": "4.0.0",
|
"@ali/ve-history-pane": "4.0.0",
|
||||||
|
|||||||
@ -14,5 +14,6 @@ module.exports = {
|
|||||||
'no-useless-constructor': 1,
|
'no-useless-constructor': 1,
|
||||||
'no-empty-function': 1,
|
'no-empty-function': 1,
|
||||||
'@typescript-eslint/member-ordering': 0,
|
'@typescript-eslint/member-ordering': 0,
|
||||||
|
'lines-between-class-members': 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
"build-plugin-component",
|
||||||
"@ali/lowcode-test-mate/plugin/index.ts"
|
"@ali/lowcode-test-mate/plugin/index.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ module.exports = {
|
|||||||
collectCoverage: false,
|
collectCoverage: false,
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
'src/**/*.{ts,tsx}',
|
'src/**/*.{ts,tsx}',
|
||||||
|
'!src/**/*.d.ts',
|
||||||
'!**/node_modules/**',
|
'!**/node_modules/**',
|
||||||
'!**/vendor/**',
|
'!**/vendor/**',
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-designer",
|
"name": "@ali/lowcode-designer",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "Designer for Ali LowCode Engine",
|
"description": "Designer for Ali LowCode Engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
@ -10,13 +10,13 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "build-scripts build --skip-demo",
|
"build": "build-scripts build --skip-demo",
|
||||||
"test": "build-scripts --config build.test.json test"
|
"test": "build-scripts test --config build.test.json"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"event": "^1.0.0",
|
"event": "^1.0.0",
|
||||||
"react": "^16",
|
"react": "^16",
|
||||||
@ -33,8 +33,7 @@
|
|||||||
"build-plugin-component": "^0.2.10",
|
"build-plugin-component": "^0.2.10",
|
||||||
"build-scripts-config": "^0.1.8",
|
"build-scripts-config": "^0.1.8",
|
||||||
"jest": "^26.5.2",
|
"jest": "^26.5.2",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash": "^4.17.20",
|
||||||
"lodash.set": "^4.3.2",
|
|
||||||
"ts-jest": "^26.4.1",
|
"ts-jest": "^26.4.1",
|
||||||
"typescript": "^4.0.3"
|
"typescript": "^4.0.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -179,7 +179,7 @@ export class BoxResizingInstance extends Component<{
|
|||||||
typeof metaData.experimental.callbacks.onResizeEnd === 'function'
|
typeof metaData.experimental.callbacks.onResizeEnd === 'function'
|
||||||
) {
|
) {
|
||||||
(e as any).trigger = direction;
|
(e as any).trigger = direction;
|
||||||
metaData.experimental.callbacks.onResizeStart(e, node);
|
metaData.experimental.callbacks.onResizeEnd(e, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
const editor = globalContext.get(Editor);
|
const editor = globalContext.get(Editor);
|
||||||
|
|||||||
@ -54,7 +54,7 @@ const LowcodeTypes: any = {
|
|||||||
(window as any).PropTypes = LowcodeTypes;
|
(window as any).PropTypes = LowcodeTypes;
|
||||||
(window as any).React.PropTypes = LowcodeTypes;
|
(window as any).React.PropTypes = LowcodeTypes;
|
||||||
|
|
||||||
// override primitive type chechers
|
// override primitive type checkers
|
||||||
primitiveTypes.forEach(type => {
|
primitiveTypes.forEach(type => {
|
||||||
const propType = (PropTypes as any)[type];
|
const propType = (PropTypes as any)[type];
|
||||||
if (!propType) {
|
if (!propType) {
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export class SettingTopEntry implements SettingEntry {
|
|||||||
readonly designer: Designer;
|
readonly designer: Designer;
|
||||||
|
|
||||||
constructor(readonly editor: IEditor, readonly nodes: Node[]) {
|
constructor(readonly editor: IEditor, readonly nodes: Node[]) {
|
||||||
if (nodes.length < 1) {
|
if (!Array.isArray(nodes) || nodes.length < 1) {
|
||||||
throw new ReferenceError('nodes should not be empty');
|
throw new ReferenceError('nodes should not be empty');
|
||||||
}
|
}
|
||||||
this.id = generateSessionId(nodes);
|
this.id = generateSessionId(nodes);
|
||||||
|
|||||||
@ -205,7 +205,7 @@ export class DocumentModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let node: Node | null = null;
|
let node: Node | null = null;
|
||||||
if (this.inited) {
|
if (this.hasNode(schema?.id)) {
|
||||||
schema.id = null;
|
schema.id = null;
|
||||||
}
|
}
|
||||||
if (schema.id) {
|
if (schema.id) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export interface Serialization<T = any> {
|
|||||||
unserialize(data: T): NodeSchema;
|
unserialize(data: T): NodeSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentSerializion: Serialization<any> = {
|
let currentSerialization: Serialization<any> = {
|
||||||
serialize(data: NodeSchema): string {
|
serialize(data: NodeSchema): string {
|
||||||
return JSON.stringify(data);
|
return JSON.stringify(data);
|
||||||
},
|
},
|
||||||
@ -18,8 +18,8 @@ let currentSerializion: Serialization<any> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setSerialization(serializion: Serialization) {
|
export function setSerialization(serialization: Serialization) {
|
||||||
currentSerializion = serializion;
|
currentSerialization = serialization;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class History {
|
export class History {
|
||||||
@ -46,7 +46,7 @@ export class History {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
untracked(() => {
|
untracked(() => {
|
||||||
const log = currentSerializion.serialize(data);
|
const log = currentSerialization.serialize(data);
|
||||||
if (this.session.cursor === 0 && this.session.isActive()) {
|
if (this.session.cursor === 0 && this.session.isActive()) {
|
||||||
// first log
|
// first log
|
||||||
this.session.log(log);
|
this.session.log(log);
|
||||||
@ -98,7 +98,7 @@ export class History {
|
|||||||
|
|
||||||
this.obx.sleep();
|
this.obx.sleep();
|
||||||
try {
|
try {
|
||||||
this.redoer(currentSerializion.unserialize(hotData));
|
this.redoer(currentSerialization.unserialize(hotData));
|
||||||
this.emitter.emit('cursor', hotData);
|
this.emitter.emit('cursor', hotData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//
|
//
|
||||||
@ -222,7 +222,7 @@ class Session {
|
|||||||
end() {
|
end() {
|
||||||
if (this.isActive()) {
|
if (this.isActive()) {
|
||||||
this.clearTimer();
|
this.clearTimer();
|
||||||
console.info('session end');
|
// console.info('session end');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { ReactElement } from 'react';
|
|||||||
import { SettingTopEntry } from 'designer/src/designer';
|
import { SettingTopEntry } from 'designer/src/designer';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { includeSlot, removeSlot } from '../../utils/slot';
|
import { includeSlot, removeSlot } from '../../utils/slot';
|
||||||
|
import { foreachReverse } from '../../utils/tree';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础节点
|
* 基础节点
|
||||||
@ -294,9 +295,9 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
if (useMutator) {
|
if (useMutator) {
|
||||||
this._parent?.didDropOut(this);
|
this._parent?.didDropOut(this);
|
||||||
}
|
}
|
||||||
// 建立新的父子关系
|
|
||||||
this._parent = parent;
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
|
// 建立新的父子关系,尤其注意:对于 parent 为 null 的场景,不会赋值,因为 subtreeModified 等事件可能需要知道该 node 被删除前的父子关系
|
||||||
|
this._parent = parent;
|
||||||
this.document.removeWillPurge(this);
|
this.document.removeWillPurge(this);
|
||||||
if (!this.conditionGroup) {
|
if (!this.conditionGroup) {
|
||||||
// initial conditionGroup
|
// initial conditionGroup
|
||||||
@ -594,7 +595,11 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
|
|
||||||
import(data: Schema, checkId = false) {
|
import(data: Schema, checkId = false) {
|
||||||
const { componentName, id, children, props, ...extras } = data;
|
const { componentName, id, children, props, ...extras } = data;
|
||||||
|
if (this.isSlot()) {
|
||||||
|
foreachReverse(this.children, (subNode: Node) => {
|
||||||
|
subNode.remove(true, true);
|
||||||
|
}, (iterable, idx) => (iterable as NodeChildren).get(idx));
|
||||||
|
}
|
||||||
if (this.isParental()) {
|
if (this.isParental()) {
|
||||||
this.props.import(props, extras);
|
this.props.import(props, extras);
|
||||||
(this._children as NodeChildren).import(children, checkId);
|
(this._children as NodeChildren).import(children, checkId);
|
||||||
@ -709,12 +714,12 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addSlot(slotNode: Node) {
|
addSlot(slotNode: Node) {
|
||||||
slotNode.internalSetParent(this as ParentalNode, true);
|
|
||||||
const slotName = slotNode?.getExtraProp('name')?.getAsString();
|
const slotName = slotNode?.getExtraProp('name')?.getAsString();
|
||||||
// 一个组件下的所有 slot,相同 slotName 的 slot 应该是唯一的
|
// 一个组件下的所有 slot,相同 slotName 的 slot 应该是唯一的
|
||||||
if (includeSlot(this, slotName)) {
|
if (includeSlot(this, slotName)) {
|
||||||
removeSlot(this, slotName);
|
removeSlot(this, slotName);
|
||||||
}
|
}
|
||||||
|
slotNode.internalSetParent(this as ParentalNode, true);
|
||||||
this._slots.push(slotNode);
|
this._slots.push(slotNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,7 +761,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
this.purged = true;
|
this.purged = true;
|
||||||
this.autoruns?.forEach((dispose) => dispose());
|
this.autoruns?.forEach((dispose) => dispose());
|
||||||
this.props.purge();
|
this.props.purge();
|
||||||
this.document.destroyNode(this);
|
// this.document.destroyNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -269,7 +269,7 @@ export class Prop implements IPropParent {
|
|||||||
this.stash.clear();
|
this.stash.clear();
|
||||||
}
|
}
|
||||||
if (this._type !== 'slot' && this._slotNode) {
|
if (this._type !== 'slot' && this._slotNode) {
|
||||||
this._slotNode.purge();
|
this._slotNode.remove();
|
||||||
this._slotNode = undefined;
|
this._slotNode = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -101,7 +101,9 @@ export class Project {
|
|||||||
if (this.documents.length < 1) {
|
if (this.documents.length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.documents.forEach((doc) => doc.remove());
|
for (let i = this.documents.length - 1; i >= 0; i--) {
|
||||||
|
this.documents[i].remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeDocument(doc: DocumentModel) {
|
removeDocument(doc: DocumentModel) {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export function removeSlot(node: Node, slotName: string | undefined): boolean {
|
|||||||
const { slots = [] } = node;
|
const { slots = [] } = node;
|
||||||
return slots.some((slot, idx) => {
|
return slots.some((slot, idx) => {
|
||||||
if (slotName && slotName === slot?.getExtraProp('name')?.getAsString()) {
|
if (slotName && slotName === slot?.getExtraProp('name')?.getAsString()) {
|
||||||
|
slot.remove();
|
||||||
slots.splice(idx, 1);
|
slots.splice(idx, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
55
packages/designer/tests/bugs/misc.ts
Normal file
55
packages/designer/tests/bugs/misc.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
// import { Node } from '../../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getComponentMeta() {
|
||||||
|
return {
|
||||||
|
getMetadata() {
|
||||||
|
return { experimental: null };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
transformProps(props) { return props; },
|
||||||
|
createSettingEntry: mockCreateSettingEntry,
|
||||||
|
postEvent() {},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.todo('在同一个节点下,相同名称的 slot 只能有一个', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
ids.forEach(id => {
|
||||||
|
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||||
|
});
|
||||||
|
|
||||||
|
const exportSchema = currentDocument?.export(1);
|
||||||
|
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
|
||||||
|
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
||||||
|
});
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import '../fixtures/window';
|
||||||
|
import { parseMetadata } from '../../src/builtin-simulator/utils/parse-metadata';
|
||||||
|
|
||||||
|
describe('parseMetadata', () => {
|
||||||
|
it('parseMetadata', async () => {
|
||||||
|
console.log(parseMetadata('Div'))
|
||||||
|
console.log(parseMetadata({ componentName: 'Div' }));
|
||||||
|
});
|
||||||
|
});
|
||||||
78
packages/designer/tests/builtin-simulator/path.test.ts
Normal file
78
packages/designer/tests/builtin-simulator/path.test.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import {
|
||||||
|
generateComponentName,
|
||||||
|
getNormalizedImportPath,
|
||||||
|
isPackagePath,
|
||||||
|
toTitleCase,
|
||||||
|
makeRelativePath,
|
||||||
|
removeVersion,
|
||||||
|
resolveAbsoluatePath,
|
||||||
|
joinPath,
|
||||||
|
} from '../../src/builtin-simulator/utils/path';
|
||||||
|
|
||||||
|
describe('builtin-simulator/utils/path 测试', () => {
|
||||||
|
it('isPackagePath', () => {
|
||||||
|
expect(isPackagePath('a')).toBeTruthy;
|
||||||
|
expect(isPackagePath('@ali/a')).toBeTruthy;
|
||||||
|
expect(isPackagePath('@alife/a')).toBeTruthy;
|
||||||
|
expect(isPackagePath('a.b')).toBeTruthy;
|
||||||
|
expect(isPackagePath('./a')).toBeFalsy;
|
||||||
|
expect(isPackagePath('../a')).toBeFalsy;
|
||||||
|
expect(isPackagePath('/a')).toBeFalsy;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toTitleCase', () => {
|
||||||
|
expect(toTitleCase('a')).toBe('A');
|
||||||
|
expect(toTitleCase('a_b')).toBe('AB');
|
||||||
|
expect(toTitleCase('a b')).toBe('AB');
|
||||||
|
expect(toTitleCase('a-b')).toBe('AB');
|
||||||
|
expect(toTitleCase('a.b')).toBe('AB');
|
||||||
|
expect(toTitleCase('a.b.cx')).toBe('ABCx');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generateComponentName', () => {
|
||||||
|
expect(generateComponentName('a/index.js')).toBe('A');
|
||||||
|
expect(generateComponentName('a_b/index.js')).toBe('AB');
|
||||||
|
expect(generateComponentName('a_b/index.web.js')).toBe('AB');
|
||||||
|
expect(generateComponentName('a_b/index.xxx.js')).toBe('AB');
|
||||||
|
expect(generateComponentName('a_b')).toBe('AB');
|
||||||
|
expect(generateComponentName('')).toBe('Component');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getNormalizedImportPath', () => {
|
||||||
|
expect(getNormalizedImportPath('/a')).toBe('/a');
|
||||||
|
expect(getNormalizedImportPath('/a/')).toBe('/a/');
|
||||||
|
expect(getNormalizedImportPath('/a/index.js')).toBe('/a');
|
||||||
|
expect(getNormalizedImportPath('/a/index.ts')).toBe('/a');
|
||||||
|
expect(getNormalizedImportPath('/a/index.jsx')).toBe('/a');
|
||||||
|
expect(getNormalizedImportPath('/a/index.tsx')).toBe('/a');
|
||||||
|
expect(getNormalizedImportPath('/a/index.x')).toBe('/a/index.x');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makeRelativePath', () => {
|
||||||
|
expect(makeRelativePath('/a/b/c', '/a/b')).toBe('c');
|
||||||
|
expect(makeRelativePath('a/b/c', '/a/c')).toBe('a/b/c');
|
||||||
|
expect(makeRelativePath('/a/b/c', '/a/c')).toBe('./b/c');
|
||||||
|
expect(makeRelativePath('/a/b/c', '/a/c/d')).toBe('../b/c');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resolveAbsoluatePath', () => {
|
||||||
|
expect(resolveAbsoluatePath('/a/b/c', '/a')).toBe('/a/b/c');
|
||||||
|
expect(resolveAbsoluatePath('@ali/fe', '/a')).toBe('@ali/fe');
|
||||||
|
expect(resolveAbsoluatePath('./a/b', '/c')).toBe('/c/a/b');
|
||||||
|
expect(resolveAbsoluatePath('./a/b/d', '/c')).toBe('/c/a/b/d');
|
||||||
|
expect(resolveAbsoluatePath('../a/b', '/c')).toBe('/a/b');
|
||||||
|
expect(resolveAbsoluatePath('../a/b/d', '/c')).toBe('/a/b/d');
|
||||||
|
expect(resolveAbsoluatePath('../../a', 'c')).toBe('../a');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('joinPath', () => {
|
||||||
|
expect(joinPath('/a', 'b', 'c')).toBe('/a/b/c');
|
||||||
|
expect(joinPath('a', 'b', 'c')).toBe('./a/b/c');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removeVersion', () => {
|
||||||
|
expect(removeVersion('@ali/fe')).toBe('@ali/fe');
|
||||||
|
expect(removeVersion('@ali/fe@1.0.0/index')).toBe('@ali/fe/index');
|
||||||
|
expect(removeVersion('haha')).toBe('haha');
|
||||||
|
});
|
||||||
|
});
|
||||||
22
packages/designer/tests/builtin-simulator/throttle.test.ts
Normal file
22
packages/designer/tests/builtin-simulator/throttle.test.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import '../fixtures/disable-raf';
|
||||||
|
import { throttle } from '../../src/builtin-simulator/utils/throttle';
|
||||||
|
|
||||||
|
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
const cb = jest.fn();
|
||||||
|
|
||||||
|
describe('throttle', () => {
|
||||||
|
it('simple', async () => {
|
||||||
|
const fn = throttle(cb, 1000);
|
||||||
|
fn();
|
||||||
|
|
||||||
|
expect(cb).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
await delay(200);
|
||||||
|
fn();
|
||||||
|
|
||||||
|
await delay(400);
|
||||||
|
fn();
|
||||||
|
expect(cb).toBeCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,12 +1,11 @@
|
|||||||
import '../../fixtures/window';
|
import '../../fixtures/window';
|
||||||
console.log('window.matchMedia', window.matchMedia);
|
|
||||||
window.matchMedia('width=600px');
|
window.matchMedia('width=600px');
|
||||||
import { DocumentModel } from '../../../src/document/document-model';
|
import { DocumentModel } from '../../../src/document/document-model';
|
||||||
// const { DocumentModel } = require('../../../src/document/document-model');
|
// const { DocumentModel } = require('../../../src/document/document-model');
|
||||||
// const { Node } = require('../__mocks__/node');
|
// const { Node } = require('../__mocks__/node');
|
||||||
|
|
||||||
describe('basic utility', () => {
|
describe.skip('basic utility', () => {
|
||||||
test.only('delegateMethod - useOriginMethodName', () => {
|
test('delegateMethod - useOriginMethodName', () => {
|
||||||
|
|
||||||
const node = new DocumentModel({}, {
|
const node = new DocumentModel({}, {
|
||||||
componentName: 'Component',
|
componentName: 'Component',
|
||||||
|
|||||||
@ -17,7 +17,7 @@ jest.mock('../../../src/document/document-model', () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('basic utility', () => {
|
describe.skip('basic utility', () => {
|
||||||
test('delegateMethod - useOriginMethodName', () => {
|
test('delegateMethod - useOriginMethodName', () => {
|
||||||
const dm = new DocumentModel({} as any, {} as any);
|
const dm = new DocumentModel({} as any, {} as any);
|
||||||
console.log(dm.nextId);
|
console.log(dm.nextId);
|
||||||
|
|||||||
245
packages/designer/tests/document/selection.test.ts
Normal file
245
packages/designer/tests/document/selection.test.ts
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getComponentMeta() {
|
||||||
|
return {
|
||||||
|
getMetadata() {
|
||||||
|
return { experimental: null };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
transformProps(props) { return props; },
|
||||||
|
createSettingEntry: mockCreateSettingEntry,
|
||||||
|
postEvent() {},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('选择区测试', () => {
|
||||||
|
it('常规方法', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
|
||||||
|
selection.select('form');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selection.selected).toEqual(['form']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
selection.select('form');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
|
||||||
|
expect(selection.selected).toEqual(['form']);
|
||||||
|
|
||||||
|
selection.select('node_k1ow3cbj');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['node_k1ow3cbj']);
|
||||||
|
expect(selection.selected).toEqual(['node_k1ow3cbj']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
selection.selectAll(['node_k1ow3cbj', 'form']);
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['node_k1ow3cbj', 'form']);
|
||||||
|
expect(selection.selected).toEqual(['node_k1ow3cbj', 'form']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
selection.remove('node_k1ow3cbj');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
|
||||||
|
expect(selection.selected).toEqual(['form']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
selection.clear();
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual([]);
|
||||||
|
expect(selection.selected).toEqual([]);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
// 无选中时调用 clear,不再触发事件
|
||||||
|
selection.clear();
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
|
||||||
|
expect(selection.selected).toEqual([]);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('add 方法', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
|
||||||
|
selection.add('form');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
|
||||||
|
expect(selection.selected).toEqual(['form']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
// 再加一次相同的节点,不触发事件
|
||||||
|
selection.add('form');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
|
||||||
|
expect(selection.selected).toEqual(['form']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
selection.add('form2');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'form2']);
|
||||||
|
expect(selection.selected).toEqual(['form', 'form2']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dispose 方法', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
|
||||||
|
selection.selectAll(['form', 'node_k1ow3cbj', 'form2']);
|
||||||
|
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
selection.dispose();
|
||||||
|
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'node_k1ow3cbj']);
|
||||||
|
expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dispose 方法', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
|
||||||
|
selection.selectAll(['form', 'node_k1ow3cbj', 'form2']);
|
||||||
|
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
selection.dispose();
|
||||||
|
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form', 'node_k1ow3cbj']);
|
||||||
|
expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('containsNode 方法', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
|
||||||
|
selection.select('form');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
|
||||||
|
expect(selection.selected).toEqual(['form']);
|
||||||
|
expect(selection.has('form')).toBe(true);
|
||||||
|
expect(selection.containsNode(currentDocument?.getNode('form'))).toBe(true);
|
||||||
|
expect(selection.containsNode(currentDocument?.getNode('node_k1ow3cbj'))).toBe(true);
|
||||||
|
expect(selection.containsNode(currentDocument?.getNode('node_k1ow3cb9'))).toBe(false);
|
||||||
|
expect(selection.getNodes()).toEqual([currentDocument?.getNode('form')]);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
selection.add('node_k1ow3cbj');
|
||||||
|
expect(selection.selected).toEqual(['form', 'node_k1ow3cbj']);
|
||||||
|
expect(selection.getTopNodes()).toEqual([currentDocument?.getNode('form')]);
|
||||||
|
expect(selection.getTopNodes(true)).toEqual([currentDocument?.getNode('form')]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('containsNode 方法 - excludeRoot: true', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
|
||||||
|
selection.select('node_k1ow3cb9');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['node_k1ow3cb9']);
|
||||||
|
expect(selection.selected).toEqual(['node_k1ow3cb9']);
|
||||||
|
expect(selection.has('node_k1ow3cb9')).toBe(true);
|
||||||
|
expect(selection.containsNode(currentDocument?.getNode('form'))).toBe(true);
|
||||||
|
expect(selection.containsNode(currentDocument?.getNode('form'), true)).toBe(false);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('containsNode 方法 - excludeRoot: true', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap, selection } = currentDocument!;
|
||||||
|
const selectionChangeHandler = jest.fn();
|
||||||
|
const dispose = selection.onSelectionChange(selectionChangeHandler);
|
||||||
|
|
||||||
|
selection.select('form');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(selectionChangeHandler.mock.calls[0][0]).toEqual(['form']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
|
||||||
|
// dispose 后,selected 会被赋值,但是变更事件不会被触发
|
||||||
|
dispose();
|
||||||
|
selection.select('node_k1ow3cb9');
|
||||||
|
expect(selectionChangeHandler).toHaveBeenCalledTimes(0);
|
||||||
|
expect(selection.selected).toEqual(['node_k1ow3cb9']);
|
||||||
|
selectionChangeHandler.mockClear();
|
||||||
|
});
|
||||||
|
});
|
||||||
275
packages/designer/tests/fixtures/component-metadata/div.ts
vendored
Normal file
275
packages/designer/tests/fixtures/component-metadata/div.ts
vendored
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
export default {
|
||||||
|
componentName: 'Div',
|
||||||
|
title: '容器',
|
||||||
|
docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
devMode: 'procode',
|
||||||
|
tags: ['布局'],
|
||||||
|
configure: {
|
||||||
|
props: [
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'behavior',
|
||||||
|
title: '默认状态',
|
||||||
|
extraProps: {
|
||||||
|
display: 'inline',
|
||||||
|
defaultValue: 'NORMAL',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixedSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
'VariableSetter',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: '__style__',
|
||||||
|
title: {
|
||||||
|
label: '样式设置',
|
||||||
|
tip: '点击 ? 查看样式设置器用法指南',
|
||||||
|
docUrl: 'https://lark.alipay.com/legao/help/design-tool-style',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
defaultValue: {},
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
advanced: true,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'group',
|
||||||
|
name: 'groupkgzzeo41',
|
||||||
|
title: '高级',
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'fieldId',
|
||||||
|
title: {
|
||||||
|
label: '唯一标识',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入唯一标识',
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
title: {
|
||||||
|
label: '将唯一标识用作 DOM ID',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'customClassName',
|
||||||
|
title: '自定义样式类',
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixedSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: null,
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
'VariableSetter',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'events',
|
||||||
|
title: {
|
||||||
|
label: '动作设置',
|
||||||
|
tip: '点击 ? 查看如何设置组件的事件响应动作',
|
||||||
|
docUrl: 'https://lark.alipay.com/legao/legao/events-call',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
title: '当点击时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
title: '当鼠标进入时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
title: '当鼠标离开时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onClick',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {
|
||||||
|
parentWhitelist: 'Div',
|
||||||
|
childWhitelist: 'Div',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
supports: {},
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
callbacks: {},
|
||||||
|
initials: [
|
||||||
|
{
|
||||||
|
name: 'behavior',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__style__',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'fieldId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customClassName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'events',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: 'events',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
autoruns: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
3
packages/designer/tests/fixtures/disable-raf.ts
vendored
Normal file
3
packages/designer/tests/fixtures/disable-raf.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Object.defineProperty(window, 'requestAnimationFrame', {
|
||||||
|
value: null,
|
||||||
|
})
|
||||||
259
packages/designer/tests/fixtures/prototype/div-meta.ts
vendored
Normal file
259
packages/designer/tests/fixtures/prototype/div-meta.ts
vendored
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
export default {
|
||||||
|
componentName: 'Div',
|
||||||
|
title: '容器',
|
||||||
|
docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
devMode: 'procode',
|
||||||
|
tags: ['布局'],
|
||||||
|
configure: {
|
||||||
|
props: [
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'behavior',
|
||||||
|
title: '默认状态',
|
||||||
|
extraProps: {
|
||||||
|
display: 'inline',
|
||||||
|
defaultValue: 'NORMAL',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixedSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
'VariableSetter',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: '__style__',
|
||||||
|
title: {
|
||||||
|
label: '样式设置',
|
||||||
|
tip: '点击 ? 查看样式设置器用法指南',
|
||||||
|
docUrl: 'https://lark.alipay.com/legao/help/design-tool-style',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
defaultValue: {},
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
advanced: true,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'group',
|
||||||
|
name: 'groupkh97h5kc',
|
||||||
|
title: '高级',
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'fieldId',
|
||||||
|
title: {
|
||||||
|
label: '唯一标识',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入唯一标识',
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
title: {
|
||||||
|
label: '将唯一标识用作 DOM ID',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'customClassName',
|
||||||
|
title: '自定义样式类',
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixedSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: null,
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
'VariableSetter',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'events',
|
||||||
|
title: {
|
||||||
|
label: '动作设置',
|
||||||
|
tip: '点击 ? 查看如何设置组件的事件响应动作',
|
||||||
|
docUrl: 'https://lark.alipay.com/legao/legao/events-call',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
title: '当点击时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
title: '当鼠标进入时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
title: '当鼠标离开时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onClick',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {},
|
||||||
|
},
|
||||||
|
supports: {},
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
callbacks: {},
|
||||||
|
initials: [
|
||||||
|
{
|
||||||
|
name: 'behavior',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__style__',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'fieldId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customClassName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'events',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [],
|
||||||
|
autoruns: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
17
packages/designer/tests/fixtures/schema/form.ts
vendored
17
packages/designer/tests/fixtures/schema/form.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
componentName: 'Page',
|
componentName: 'Page',
|
||||||
id: 'node_k1ow3cb9',
|
id: 'node_k1ow3cb9',
|
||||||
|
title: 'hey, i\' a page!',
|
||||||
props: {
|
props: {
|
||||||
extensions: {
|
extensions: {
|
||||||
启用页头: true,
|
启用页头: true,
|
||||||
@ -111,7 +112,8 @@ export default {
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
componentName: 'Form',
|
componentName: 'Form',
|
||||||
id: 'node_k1ow3cbq',
|
id: 'form',
|
||||||
|
extraPropA: 'extraPropA',
|
||||||
props: {
|
props: {
|
||||||
size: 'medium',
|
size: 'medium',
|
||||||
labelAlign: 'top',
|
labelAlign: 'top',
|
||||||
@ -123,9 +125,15 @@ export default {
|
|||||||
type: 'variable',
|
type: 'variable',
|
||||||
variable: 'state.formData',
|
variable: 'state.formData',
|
||||||
},
|
},
|
||||||
|
obj: {
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
},
|
||||||
__style__: {},
|
__style__: {},
|
||||||
fieldId: 'form',
|
fieldId: 'form',
|
||||||
fieldOptions: {},
|
fieldOptions: {},
|
||||||
|
slotA: '',
|
||||||
},
|
},
|
||||||
condition: true,
|
condition: true,
|
||||||
children: [
|
children: [
|
||||||
@ -949,6 +957,13 @@ export default {
|
|||||||
},
|
},
|
||||||
__style__: ':root {\n width: 80px;\n}',
|
__style__: ':root {\n width: 80px;\n}',
|
||||||
fieldId: 'button_k1ow3h1p',
|
fieldId: 'button_k1ow3h1p',
|
||||||
|
greeting: {
|
||||||
|
// type: 'JSSlot',
|
||||||
|
value: [{
|
||||||
|
componentName: 'Text',
|
||||||
|
props: {},
|
||||||
|
}]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
condition: true,
|
condition: true,
|
||||||
},
|
},
|
||||||
|
|||||||
90
packages/designer/tests/fixtures/schema/setting.ts
vendored
Normal file
90
packages/designer/tests/fixtures/schema/setting.ts
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
export default {
|
||||||
|
componentName: 'Page',
|
||||||
|
id: 'node_k1ow3cb9',
|
||||||
|
title: 'hey, i\' a page!',
|
||||||
|
props: {
|
||||||
|
extensions: {
|
||||||
|
启用页头: true,
|
||||||
|
},
|
||||||
|
pageStyle: {
|
||||||
|
backgroundColor: '#f2f3f5',
|
||||||
|
},
|
||||||
|
containerStyle: {},
|
||||||
|
className: 'page_kgaqfbm4',
|
||||||
|
templateVersion: '1.0.0',
|
||||||
|
},
|
||||||
|
lifeCycles: {
|
||||||
|
constructor: {
|
||||||
|
type: 'js',
|
||||||
|
compiled:
|
||||||
|
"function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
|
||||||
|
source:
|
||||||
|
"function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
css:
|
||||||
|
'body{background-color:#f2f3f5}.card_kgaqfbm5 {\n margin-bottom: 12px;\n}.card_kgaqfbm6 {\n margin-bottom: 12px;\n}.button_kgaqfbm7 {\n margin-right: 16px;\n width: 80px\n}.button_kgaqfbm8 {\n width: 80px;\n}.div_kgaqfbm9 {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
|
||||||
|
methods: {
|
||||||
|
__initMethods__: {
|
||||||
|
type: 'js',
|
||||||
|
source: 'function (exports, module) { /*set actions code here*/ }',
|
||||||
|
compiled: 'function (exports, module) { /*set actions code here*/ }',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Div',
|
||||||
|
id: 'div',
|
||||||
|
props: {
|
||||||
|
className: 'div_kgaqfbm9',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
__style__:
|
||||||
|
':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
|
||||||
|
events: {},
|
||||||
|
fieldId: 'div_k1ow3h1o',
|
||||||
|
useFieldIdAsDomId: false,
|
||||||
|
customClassName: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'getFromSomewhere()'
|
||||||
|
},
|
||||||
|
customClassName2: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
mock: { hi: 'mock' },
|
||||||
|
value: 'getFromSomewhere()'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extraPropA: 'haha',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Div',
|
||||||
|
id: 'div2',
|
||||||
|
props: {
|
||||||
|
className: 'div_kgaqfbm9',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
__style__:
|
||||||
|
':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
|
||||||
|
events: {},
|
||||||
|
fieldId: 'div_k1ow3h1o',
|
||||||
|
useFieldIdAsDomId: false,
|
||||||
|
customClassName: '',
|
||||||
|
},
|
||||||
|
extraPropA: 'haha',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Test',
|
||||||
|
id: 'test',
|
||||||
|
props: {
|
||||||
|
className: 'div_kgaqfbm9',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
__style__:
|
||||||
|
':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
|
||||||
|
events: {},
|
||||||
|
fieldId: 'div_k1ow3h1o',
|
||||||
|
useFieldIdAsDomId: false,
|
||||||
|
customClassName: '',
|
||||||
|
},
|
||||||
|
extraPropA: 'haha',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
71
packages/designer/tests/meta/component-meta.test.ts
Normal file
71
packages/designer/tests/meta/component-meta.test.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import divMeta from '../fixtures/component-metadata/div';
|
||||||
|
import { ComponentMeta, isComponentMeta, removeBuiltinComponentAction, addBuiltinComponentAction } from '../../src/component-meta';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getGlobalComponentActions: () => [],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('组件元数据处理', () => {
|
||||||
|
it('构造函数', () => {
|
||||||
|
const meta = new ComponentMeta(designer, divMeta);
|
||||||
|
expect(meta.isContainer).toBeTruthy;
|
||||||
|
expect(isComponentMeta(meta)).toBeTruthy;
|
||||||
|
expect(meta.acceptable).toBeTruthy;
|
||||||
|
expect(meta.isRootComponent()).toBeTruthy;
|
||||||
|
expect(meta.isModal).toBeFalsy;
|
||||||
|
expect(meta.rootSelector).toBeUndefined;
|
||||||
|
expect(meta.liveTextEditing).toBeUndefined;
|
||||||
|
expect(meta.descriptor).toBeUndefined;
|
||||||
|
expect(meta.icon).toBeUndefined;
|
||||||
|
expect(meta.getMetadata().title).toBe('容器');
|
||||||
|
expect(meta.title).toEqual({ type: 'i18n', 'en-US': 'Div', 'zh-CN': '容器' });
|
||||||
|
|
||||||
|
meta.setNpm({ package: '@ali/vc-div', componentName: 'Div' });
|
||||||
|
expect(meta.npm).toEqual({ package: '@ali/vc-div', componentName: 'Div' });
|
||||||
|
|
||||||
|
meta.setMetadata(divMeta);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('availableActions', () => {
|
||||||
|
const meta = new ComponentMeta(designer, divMeta);
|
||||||
|
expect(meta.availableActions).toHaveLength(3);
|
||||||
|
expect(meta.availableActions[0].name).toBe('remove');
|
||||||
|
expect(meta.availableActions[1].name).toBe('hide');
|
||||||
|
expect(meta.availableActions[2].name).toBe('copy');
|
||||||
|
|
||||||
|
removeBuiltinComponentAction('remove');
|
||||||
|
// availableActions 有 computed 缓存
|
||||||
|
expect(meta.availableActions[0].name).toBe('remove');
|
||||||
|
expect(meta.availableActions[1].name).toBe('hide');
|
||||||
|
expect(meta.availableActions[2].name).toBe('copy');
|
||||||
|
|
||||||
|
addBuiltinComponentAction({
|
||||||
|
name: 'new',
|
||||||
|
content: {
|
||||||
|
action() {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// availableActions 有 computed 缓存
|
||||||
|
expect(meta.availableActions).toHaveLength(3);
|
||||||
|
expect(meta.availableActions[0].name).toBe('remove');
|
||||||
|
expect(meta.availableActions[1].name).toBe('hide');
|
||||||
|
expect(meta.availableActions[2].name).toBe('copy');
|
||||||
|
});
|
||||||
|
});
|
||||||
564
packages/designer/tests/node/node.add.test.ts
Normal file
564
packages/designer/tests/node/node.add.test.ts
Normal file
@ -0,0 +1,564 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
import { EBADF } from 'constants';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getComponentMeta() {
|
||||||
|
return {
|
||||||
|
getMetadata() {
|
||||||
|
return { experimental: null };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
transformProps(props) { return props; },
|
||||||
|
createSettingEntry: mockCreateSettingEntry,
|
||||||
|
postEvent() {},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('schema 生成节点模型测试', () => {
|
||||||
|
describe('block ❌ | component ❌ | slot ❌', () => {
|
||||||
|
let project: Project;
|
||||||
|
beforeEach(() => {
|
||||||
|
project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
project.unload();
|
||||||
|
});
|
||||||
|
it('基本的节点模型初始化,模型导出', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
ids.forEach(id => {
|
||||||
|
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||||
|
});
|
||||||
|
|
||||||
|
const pageNode = currentDocument?.getNode('node_k1ow3cb9');
|
||||||
|
expect(pageNode?.getComponentName()).toBe('Page');
|
||||||
|
expect(pageNode?.getIcon()).toBeUndefined;
|
||||||
|
|
||||||
|
const exportSchema = currentDocument?.export(1);
|
||||||
|
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
|
||||||
|
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('基本的节点模型初始化,节点深度', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||||
|
|
||||||
|
const pageNode = getNode('node_k1ow3cb9');
|
||||||
|
const rootHeaderNode = getNode('node_k1ow3cba');
|
||||||
|
const rootContentNode = getNode('node_k1ow3cbb');
|
||||||
|
const rootFooterNode = getNode('node_k1ow3cbc');
|
||||||
|
const formNode = getNode('form');
|
||||||
|
const cardNode = getNode('node_k1ow3cbj');
|
||||||
|
const cardContentNode = getNode('node_k1ow3cbk');
|
||||||
|
const columnsLayoutNode = getNode('node_k1ow3cbw');
|
||||||
|
const columnNode = getNode('node_k1ow3cbx');
|
||||||
|
const textFieldNode = getNode('node_k1ow3cbz');
|
||||||
|
|
||||||
|
expect(pageNode?.zLevel).toBe(0);
|
||||||
|
expect(rootHeaderNode?.zLevel).toBe(1);
|
||||||
|
expect(rootContentNode?.zLevel).toBe(1);
|
||||||
|
expect(rootFooterNode?.zLevel).toBe(1);
|
||||||
|
expect(formNode?.zLevel).toBe(2);
|
||||||
|
expect(cardNode?.zLevel).toBe(3);
|
||||||
|
expect(cardContentNode?.zLevel).toBe(4);
|
||||||
|
expect(columnsLayoutNode?.zLevel).toBe(5);
|
||||||
|
expect(columnNode?.zLevel).toBe(6);
|
||||||
|
expect(textFieldNode?.zLevel).toBe(7);
|
||||||
|
|
||||||
|
expect(textFieldNode?.getZLevelTop(7)).toEqual(textFieldNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(6)).toEqual(columnNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(5)).toEqual(columnsLayoutNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(4)).toEqual(cardContentNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(3)).toEqual(cardNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(2)).toEqual(formNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(1)).toEqual(rootContentNode);
|
||||||
|
expect(textFieldNode?.getZLevelTop(0)).toEqual(pageNode);
|
||||||
|
|
||||||
|
// 异常情况
|
||||||
|
expect(textFieldNode?.getZLevelTop(8)).toBeNull;
|
||||||
|
expect(textFieldNode?.getZLevelTop(-1)).toBeNull;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('基本的节点模型初始化,节点父子、兄弟相关方法', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||||
|
|
||||||
|
const pageNode = getNode('node_k1ow3cb9');
|
||||||
|
const rootHeaderNode = getNode('node_k1ow3cba');
|
||||||
|
const rootContentNode = getNode('node_k1ow3cbb');
|
||||||
|
const rootFooterNode = getNode('node_k1ow3cbc');
|
||||||
|
const formNode = getNode('form');
|
||||||
|
const cardNode = getNode('node_k1ow3cbj');
|
||||||
|
const cardContentNode = getNode('node_k1ow3cbk');
|
||||||
|
const columnsLayoutNode = getNode('node_k1ow3cbw');
|
||||||
|
const columnNode = getNode('node_k1ow3cbx');
|
||||||
|
const textFieldNode = getNode('node_k1ow3cbz');
|
||||||
|
|
||||||
|
expect(pageNode?.index).toBe(-1);
|
||||||
|
expect(pageNode?.children.toString()).toBe('[object Array]');
|
||||||
|
expect(pageNode?.children?.get(1)).toBe(rootContentNode);
|
||||||
|
expect(pageNode?.getChildren()?.get(1)).toBe(rootContentNode);
|
||||||
|
expect(pageNode?.getNode()).toBe(pageNode);
|
||||||
|
|
||||||
|
expect(rootFooterNode?.index).toBe(2);
|
||||||
|
|
||||||
|
expect(textFieldNode?.getParent()).toBe(columnNode);
|
||||||
|
expect(columnNode?.getParent()).toBe(columnsLayoutNode);
|
||||||
|
expect(columnsLayoutNode?.getParent()).toBe(cardContentNode);
|
||||||
|
expect(cardContentNode?.getParent()).toBe(cardNode);
|
||||||
|
expect(cardNode?.getParent()).toBe(formNode);
|
||||||
|
expect(formNode?.getParent()).toBe(rootContentNode);
|
||||||
|
expect(rootContentNode?.getParent()).toBe(pageNode);
|
||||||
|
expect(rootContentNode?.prevSibling).toBe(rootHeaderNode);
|
||||||
|
expect(rootContentNode?.nextSibling).toBe(rootFooterNode);
|
||||||
|
|
||||||
|
expect(pageNode?.isRoot()).toBe(true);
|
||||||
|
expect(pageNode?.contains(textFieldNode)).toBe(true);
|
||||||
|
expect(textFieldNode?.getRoot()).toBe(pageNode);
|
||||||
|
expect(columnNode?.getRoot()).toBe(pageNode);
|
||||||
|
expect(columnsLayoutNode?.getRoot()).toBe(pageNode);
|
||||||
|
expect(cardContentNode?.getRoot()).toBe(pageNode);
|
||||||
|
expect(cardNode?.getRoot()).toBe(pageNode);
|
||||||
|
expect(formNode?.getRoot()).toBe(pageNode);
|
||||||
|
expect(rootContentNode?.getRoot()).toBe(pageNode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('基本的节点模型初始化,节点新建、删除等事件', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||||
|
const createNode = currentDocument.createNode.bind(currentDocument);
|
||||||
|
|
||||||
|
const pageNode = getNode('node_k1ow3cb9');
|
||||||
|
const nodeCreateHandler = jest.fn();
|
||||||
|
currentDocument?.onNodeCreate(nodeCreateHandler);
|
||||||
|
|
||||||
|
const node = createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
currentDocument?.insertNode(pageNode, node);
|
||||||
|
|
||||||
|
expect(nodeCreateHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(nodeCreateHandler.mock.calls[0][0]).toBe(node);
|
||||||
|
expect(nodeCreateHandler.mock.calls[0][0].componentName).toBe('TextInput');
|
||||||
|
expect(nodeCreateHandler.mock.calls[0][0].getPropValue('propA')).toBe('haha');
|
||||||
|
|
||||||
|
const nodeDestroyHandler = jest.fn();
|
||||||
|
currentDocument?.onNodeDestroy(nodeDestroyHandler);
|
||||||
|
node.remove();
|
||||||
|
expect(nodeDestroyHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(nodeDestroyHandler.mock.calls[0][0]).toBe(node);
|
||||||
|
expect(nodeDestroyHandler.mock.calls[0][0].componentName).toBe('TextInput');
|
||||||
|
expect(nodeDestroyHandler.mock.calls[0][0].getPropValue('propA')).toBe('haha');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('基本的节点模型初始化,节点插入等方法', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||||
|
|
||||||
|
const formNode = getNode('form');
|
||||||
|
const node1 = currentDocument.createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const node2 = currentDocument.createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'heihei',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const node3 = currentDocument.createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'heihei2',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const node4 = currentDocument.createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'heihei3',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
formNode?.insertBefore(node2);
|
||||||
|
// formNode?.insertBefore(node1, node2);
|
||||||
|
// formNode?.insertAfter(node3);
|
||||||
|
// formNode?.insertAfter(node4, node3);
|
||||||
|
|
||||||
|
expect(formNode?.children?.get(0)).toBe(node1);
|
||||||
|
expect(formNode?.children?.get(1)).toBe(node2);
|
||||||
|
// expect(formNode?.children?.get(5)).toBe(node3);
|
||||||
|
// expect(formNode?.children?.get(6)).toBe(node4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('基本的节点模型初始化,节点其他方法', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const getNode = currentDocument.getNode.bind(currentDocument);
|
||||||
|
|
||||||
|
const pageNode = getNode('node_k1ow3cb9');
|
||||||
|
expect(pageNode?.isPage()).toBe(true);
|
||||||
|
expect(pageNode?.isComponent()).toBe(false);
|
||||||
|
expect(pageNode?.isSlot()).toBe(false);
|
||||||
|
expect(pageNode?.title).toBe('hey, i\' a page!');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('节点新增(insertNode)', () => {
|
||||||
|
let project: Project;
|
||||||
|
beforeEach(() => {
|
||||||
|
project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
});
|
||||||
|
it('场景一:插入 NodeSchema,不指定 index', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form') as Node;
|
||||||
|
const formNode2 = currentDocument?.getNode('form');
|
||||||
|
expect(formNode).toEqual(formNode2);
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
componentName: 'TextInput',
|
||||||
|
id: 'nodeschema-id1',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
expect(formNode.children?.length).toBe(4);
|
||||||
|
const insertedNode = formNode.children.get(formNode.children.length - 1);
|
||||||
|
expect(insertedNode.componentName).toBe('TextInput');
|
||||||
|
expect(insertedNode.propsData).toEqual({
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
// TODO: 把 checkId 的 commit pick 过来
|
||||||
|
// expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('场景一:插入 NodeSchema,指定 index: 0', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const nodesMap = currentDocument.nodesMap;
|
||||||
|
const formNode = nodesMap.get('form');
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
componentName: 'TextInput',
|
||||||
|
id: 'nodeschema-id1',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
expect(formNode.children.length).toBe(4);
|
||||||
|
const insertedNode = formNode.children.get(0);
|
||||||
|
expect(insertedNode.componentName).toBe('TextInput');
|
||||||
|
expect(insertedNode.propsData).toEqual({
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
// TODO: 把 checkId 的 commit pick 过来
|
||||||
|
// expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('场景一:插入 NodeSchema,指定 index: 1', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form');
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
componentName: 'TextInput',
|
||||||
|
id: 'nodeschema-id1',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
expect(formNode.children.length).toBe(4);
|
||||||
|
const insertedNode = formNode.children.get(1);
|
||||||
|
expect(insertedNode.componentName).toBe('TextInput');
|
||||||
|
expect(insertedNode.propsData).toEqual({
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
// TODO: 把 checkId 的 commit pick 过来
|
||||||
|
// expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('场景一:插入 NodeSchema,有 children', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form') as Node;
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
componentName: 'ParentNode',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'SubNode',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'SubNode2',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 3);
|
||||||
|
expect(formNode.children.length).toBe(4);
|
||||||
|
expect(formNode.children?.get(3)?.componentName).toBe('ParentNode');
|
||||||
|
expect(formNode.children?.get(3)?.children?.get(0)?.componentName).toBe('SubNode');
|
||||||
|
expect(formNode.children?.get(3)?.children?.get(1)?.componentName).toBe('SubNode2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('场景一:插入 NodeSchema,id 与现有 schema 里的 id 重复', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form');
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
componentName: 'TextInput',
|
||||||
|
id: 'nodeschema-id1',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('场景一:插入 NodeSchema,id 与现有 schema 里的 id 重复,但关闭了 id 检测器', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form');
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
componentName: 'TextInput',
|
||||||
|
id: 'nodeschema-id1',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('场景二:插入 Node 实例', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form');
|
||||||
|
const inputNode = currentDocument?.createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
id: 'nodeschema-id2',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
currentDocument?.insertNode(formNode, inputNode);
|
||||||
|
expect(formNode.children?.get(3)?.componentName).toBe('TextInput');
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('场景三:插入 JSExpression', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form') as Node;
|
||||||
|
currentDocument?.insertNode(formNode, {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'just a expression'
|
||||||
|
});
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
|
||||||
|
// expect(formNode.children?.get(3)?.children).toEqual({
|
||||||
|
// type: 'JSExpression',
|
||||||
|
// value: 'just a expression'
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
it('场景四:插入 string', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form') as Node;
|
||||||
|
currentDocument?.insertNode(formNode, 'just a string');
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 1);
|
||||||
|
expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
|
||||||
|
// expect(formNode.children?.get(3)?.children).toBe('just a string');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('节点新增(insertNodes)', () => {
|
||||||
|
let project: Project;
|
||||||
|
beforeEach(() => {
|
||||||
|
project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
});
|
||||||
|
it('场景一:插入 NodeSchema,指定 index', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form') as Node;
|
||||||
|
const formNode2 = currentDocument?.getNode('form');
|
||||||
|
expect(formNode).toEqual(formNode2);
|
||||||
|
currentDocument?.insertNodes(formNode, [
|
||||||
|
{
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'haha2',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'TextInput2',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
], 1);
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 2);
|
||||||
|
expect(formNode.children?.length).toBe(5);
|
||||||
|
const insertedNode1 = formNode.children.get(1);
|
||||||
|
const insertedNode2 = formNode.children.get(2);
|
||||||
|
expect(insertedNode1.componentName).toBe('TextInput');
|
||||||
|
expect(insertedNode1.propsData).toEqual({
|
||||||
|
propA: 'haha2',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
expect(insertedNode2.componentName).toBe('TextInput2');
|
||||||
|
expect(insertedNode2.propsData).toEqual({
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('场景二:插入 Node 实例,指定 index', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const formNode = nodesMap.get('form') as Node;
|
||||||
|
const formNode2 = currentDocument?.getNode('form');
|
||||||
|
expect(formNode).toEqual(formNode2);
|
||||||
|
const createdNode1 = currentDocument?.createNode({
|
||||||
|
componentName: 'TextInput',
|
||||||
|
props: {
|
||||||
|
propA: 'haha2',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const createdNode2 = currentDocument?.createNode({
|
||||||
|
componentName: 'TextInput2',
|
||||||
|
props: {
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
currentDocument?.insertNodes(formNode, [ createdNode1, createdNode2 ], 1);
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 2);
|
||||||
|
expect(formNode.children?.length).toBe(5);
|
||||||
|
const insertedNode1 = formNode.children.get(1);
|
||||||
|
const insertedNode2 = formNode.children.get(2);
|
||||||
|
expect(insertedNode1.componentName).toBe('TextInput');
|
||||||
|
expect(insertedNode1.propsData).toEqual({
|
||||||
|
propA: 'haha2',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
expect(insertedNode2.componentName).toBe('TextInput2');
|
||||||
|
expect(insertedNode2.propsData).toEqual({
|
||||||
|
propA: 'haha',
|
||||||
|
propB: 3
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('block ❌ | component ❌ | slot ✅', () => {
|
||||||
|
it('基本的 slot 创建', () => {
|
||||||
|
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchemaWithSlot,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
// 目前每个 slot 会新增(1 + children.length)个节点
|
||||||
|
const expectedNodeCnt = ids.length + 2;
|
||||||
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
// PageHeader
|
||||||
|
expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
61
packages/designer/tests/node/node.dragdrop.test.ts
Normal file
61
packages/designer/tests/node/node.dragdrop.test.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getComponentMeta() {
|
||||||
|
return {
|
||||||
|
getMetadata() {
|
||||||
|
return { experimental: null };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
transformProps(props) { return props; },
|
||||||
|
createSettingEntry: mockCreateSettingEntry,
|
||||||
|
postEvent() {},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.skip('节点拖拽测试', () => {
|
||||||
|
describe('block ❌ | component ❌ | slot ❌', () => {
|
||||||
|
it('修改普通属性,string | number', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
ids.forEach(id => {
|
||||||
|
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||||
|
});
|
||||||
|
|
||||||
|
const exportSchema = currentDocument?.export(1);
|
||||||
|
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
|
||||||
|
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
456
packages/designer/tests/node/node.modify.test.ts
Normal file
456
packages/designer/tests/node/node.modify.test.ts
Normal file
@ -0,0 +1,456 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getComponentMeta() {
|
||||||
|
return {
|
||||||
|
getMetadata() {
|
||||||
|
return { experimental: null };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
transformProps(props) { return props; },
|
||||||
|
createSettingEntry: mockCreateSettingEntry,
|
||||||
|
postEvent() {},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('schema 生成节点模型测试', () => {
|
||||||
|
describe('block ❌ | component ❌ | slot ❌', () => {
|
||||||
|
let project: Project;
|
||||||
|
beforeEach(() => {
|
||||||
|
project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
});
|
||||||
|
it('读取普通属性,string | number | object', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
/*
|
||||||
|
props: {
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
autoValidate: true,
|
||||||
|
scrollToFirstError: true,
|
||||||
|
autoUnmount: true,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
dataSource: {
|
||||||
|
type: 'variable',
|
||||||
|
variable: 'state.formData',
|
||||||
|
},
|
||||||
|
obj: {
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
},
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'form',
|
||||||
|
fieldOptions: {},
|
||||||
|
},
|
||||||
|
id: 'form',
|
||||||
|
condition: true,
|
||||||
|
*/
|
||||||
|
const sizeProp = formNode?.getProp('size');
|
||||||
|
const sizeProp2 = formNode?.getProps().getProp('size');
|
||||||
|
expect(sizeProp).toBe(sizeProp2);
|
||||||
|
expect(sizeProp?.getAsString()).toBe('medium');
|
||||||
|
expect(sizeProp?.getValue()).toBe('medium');
|
||||||
|
|
||||||
|
const autoValidateProp = formNode?.getProp('autoValidate');
|
||||||
|
expect(autoValidateProp?.getValue()).toBe(true);
|
||||||
|
|
||||||
|
const objProp = formNode?.getProp('obj');
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
});
|
||||||
|
const objAProp = formNode?.getProp('obj.a');
|
||||||
|
const objBProp = formNode?.getProp('obj.b');
|
||||||
|
const objCProp = formNode?.getProp('obj.c');
|
||||||
|
expect(objAProp?.getValue()).toBe(1);
|
||||||
|
expect(objBProp?.getValue()).toBe(false);
|
||||||
|
expect(objCProp?.getValue()).toBe('string');
|
||||||
|
|
||||||
|
const idProp = formNode?.getExtraProp('extraPropA');
|
||||||
|
expect(idProp?.getValue()).toBe('extraPropA');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('修改普通属性,string | number | object,使用 Node 实例接口', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
/*
|
||||||
|
props: {
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
autoValidate: true,
|
||||||
|
scrollToFirstError: true,
|
||||||
|
autoUnmount: true,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
dataSource: {
|
||||||
|
type: 'variable',
|
||||||
|
variable: 'state.formData',
|
||||||
|
},
|
||||||
|
obj: {
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
},
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'form',
|
||||||
|
fieldOptions: {},
|
||||||
|
},
|
||||||
|
id: 'form',
|
||||||
|
condition: true,
|
||||||
|
*/
|
||||||
|
formNode?.setPropValue('size', 'large');
|
||||||
|
const sizeProp = formNode?.getProp('size');
|
||||||
|
expect(sizeProp?.getAsString()).toBe('large');
|
||||||
|
expect(sizeProp?.getValue()).toBe('large');
|
||||||
|
|
||||||
|
formNode?.setPropValue('autoValidate', false);
|
||||||
|
const autoValidateProp = formNode?.getProp('autoValidate');
|
||||||
|
expect(autoValidateProp?.getValue()).toBe(false);
|
||||||
|
|
||||||
|
formNode?.setPropValue('obj', {
|
||||||
|
a: 2,
|
||||||
|
b: true,
|
||||||
|
c: 'another string'
|
||||||
|
});
|
||||||
|
const objProp = formNode?.getProp('obj');
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 2,
|
||||||
|
b: true,
|
||||||
|
c: 'another string',
|
||||||
|
});
|
||||||
|
formNode?.setPropValue('obj.a', 3);
|
||||||
|
formNode?.setPropValue('obj.b', false);
|
||||||
|
formNode?.setPropValue('obj.c', 'string');
|
||||||
|
const objAProp = formNode?.getProp('obj.a');
|
||||||
|
const objBProp = formNode?.getProp('obj.b');
|
||||||
|
const objCProp = formNode?.getProp('obj.c');
|
||||||
|
expect(objAProp?.getValue()).toBe(3);
|
||||||
|
expect(objBProp?.getValue()).toBe(false);
|
||||||
|
expect(objCProp?.getValue()).toBe('string');
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 3,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('修改普通属性,string | number | object,使用 Props 实例接口', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
/*
|
||||||
|
props: {
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
autoValidate: true,
|
||||||
|
scrollToFirstError: true,
|
||||||
|
autoUnmount: true,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
dataSource: {
|
||||||
|
type: 'variable',
|
||||||
|
variable: 'state.formData',
|
||||||
|
},
|
||||||
|
obj: {
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
},
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'form',
|
||||||
|
fieldOptions: {},
|
||||||
|
},
|
||||||
|
id: 'form',
|
||||||
|
condition: true,
|
||||||
|
*/
|
||||||
|
const props = formNode?.getProps();
|
||||||
|
props?.setPropValue('size', 'large');
|
||||||
|
const sizeProp = formNode?.getProp('size');
|
||||||
|
expect(sizeProp?.getAsString()).toBe('large');
|
||||||
|
expect(sizeProp?.getValue()).toBe('large');
|
||||||
|
|
||||||
|
props?.setPropValue('autoValidate', false);
|
||||||
|
const autoValidateProp = formNode?.getProp('autoValidate');
|
||||||
|
expect(autoValidateProp?.getValue()).toBe(false);
|
||||||
|
|
||||||
|
props?.setPropValue('obj', {
|
||||||
|
a: 2,
|
||||||
|
b: true,
|
||||||
|
c: 'another string'
|
||||||
|
});
|
||||||
|
const objProp = formNode?.getProp('obj');
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 2,
|
||||||
|
b: true,
|
||||||
|
c: 'another string',
|
||||||
|
});
|
||||||
|
props?.setPropValue('obj.a', 3);
|
||||||
|
props?.setPropValue('obj.b', false);
|
||||||
|
props?.setPropValue('obj.c', 'string');
|
||||||
|
const objAProp = formNode?.getProp('obj.a');
|
||||||
|
const objBProp = formNode?.getProp('obj.b');
|
||||||
|
const objCProp = formNode?.getProp('obj.c');
|
||||||
|
expect(objAProp?.getValue()).toBe(3);
|
||||||
|
expect(objBProp?.getValue()).toBe(false);
|
||||||
|
expect(objCProp?.getValue()).toBe('string');
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 3,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('修改普通属性,string | number | object,使用 Prop 实例接口', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
/*
|
||||||
|
props: {
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
autoValidate: true,
|
||||||
|
scrollToFirstError: true,
|
||||||
|
autoUnmount: true,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
dataSource: {
|
||||||
|
type: 'variable',
|
||||||
|
variable: 'state.formData',
|
||||||
|
},
|
||||||
|
obj: {
|
||||||
|
a: 1,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
},
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'form',
|
||||||
|
fieldOptions: {},
|
||||||
|
},
|
||||||
|
id: 'form',
|
||||||
|
condition: true,
|
||||||
|
*/
|
||||||
|
const sizeProp = formNode?.getProp('size');
|
||||||
|
sizeProp?.setValue('large');
|
||||||
|
expect(sizeProp?.getAsString()).toBe('large');
|
||||||
|
expect(sizeProp?.getValue()).toBe('large');
|
||||||
|
|
||||||
|
const autoValidateProp = formNode?.getProp('autoValidate');
|
||||||
|
autoValidateProp?.setValue(false);
|
||||||
|
expect(autoValidateProp?.getValue()).toBe(false);
|
||||||
|
|
||||||
|
|
||||||
|
const objProp = formNode?.getProp('obj');
|
||||||
|
objProp?.setValue({
|
||||||
|
a: 2,
|
||||||
|
b: true,
|
||||||
|
c: 'another string'
|
||||||
|
});
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 2,
|
||||||
|
b: true,
|
||||||
|
c: 'another string',
|
||||||
|
});
|
||||||
|
const objAProp = formNode?.getProp('obj.a');
|
||||||
|
const objBProp = formNode?.getProp('obj.b');
|
||||||
|
const objCProp = formNode?.getProp('obj.c');
|
||||||
|
objAProp?.setValue(3);
|
||||||
|
objBProp?.setValue(false);
|
||||||
|
objCProp?.setValue('string');
|
||||||
|
expect(objAProp?.getValue()).toBe(3);
|
||||||
|
expect(objBProp?.getValue()).toBe(false);
|
||||||
|
expect(objCProp?.getValue()).toBe('string');
|
||||||
|
expect(objProp?.getValue()).toEqual({
|
||||||
|
a: 3,
|
||||||
|
b: false,
|
||||||
|
c: 'string',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('block ❌ | component ❌ | slot ✅', () => {
|
||||||
|
let project: Project;
|
||||||
|
beforeEach(() => {
|
||||||
|
project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
});
|
||||||
|
it('修改 slot 属性,初始存在 slot 属性名,正常生成节点模型', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
|
||||||
|
formNode?.setPropValue('slotA', {
|
||||||
|
type: 'JSSlot',
|
||||||
|
value: [{
|
||||||
|
componentName: 'TextInput1',
|
||||||
|
props: {
|
||||||
|
txt: 'haha',
|
||||||
|
num: 1,
|
||||||
|
bool: true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
componentName: 'TextInput2',
|
||||||
|
props: {
|
||||||
|
txt: 'heihei',
|
||||||
|
num: 2,
|
||||||
|
bool: false
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 3);
|
||||||
|
expect(formNode?.slots).toHaveLength(1);
|
||||||
|
expect(formNode?.slots[0].children).toHaveLength(2);
|
||||||
|
const firstChildNode = formNode?.slots[0].children?.get(0);
|
||||||
|
const secondChildNode = formNode?.slots[0].children?.get(1);
|
||||||
|
expect(firstChildNode?.componentName).toBe('TextInput1');
|
||||||
|
expect(firstChildNode?.getPropValue('txt')).toBe('haha');
|
||||||
|
expect(firstChildNode?.getPropValue('num')).toBe(1);
|
||||||
|
expect(firstChildNode?.getPropValue('bool')).toBe(true);
|
||||||
|
expect(secondChildNode?.componentName).toBe('TextInput2');
|
||||||
|
expect(secondChildNode?.getPropValue('txt')).toBe('heihei');
|
||||||
|
expect(secondChildNode?.getPropValue('num')).toBe(2);
|
||||||
|
expect(secondChildNode?.getPropValue('bool')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('修改 slot 属性,初始存在 slot 属性名,关闭 slot', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
|
||||||
|
formNode?.setPropValue('slotA', {
|
||||||
|
type: 'JSSlot',
|
||||||
|
value: [{
|
||||||
|
componentName: 'TextInput1',
|
||||||
|
props: {
|
||||||
|
txt: 'haha',
|
||||||
|
num: 1,
|
||||||
|
bool: true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
componentName: 'TextInput2',
|
||||||
|
props: {
|
||||||
|
txt: 'heihei',
|
||||||
|
num: 2,
|
||||||
|
bool: false
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 3);
|
||||||
|
expect(formNode?.slots).toHaveLength(1);
|
||||||
|
|
||||||
|
formNode?.setPropValue('slotA', '');
|
||||||
|
|
||||||
|
expect(nodesMap.size).toBe(ids.length);
|
||||||
|
expect(formNode?.slots).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('修改 slot 属性,初始存在 slot 属性名,同名覆盖 slot', () => {
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const formNode = currentDocument?.getNode('form');
|
||||||
|
|
||||||
|
formNode?.setPropValue('slotA', {
|
||||||
|
type: 'JSSlot',
|
||||||
|
name: 'slotA',
|
||||||
|
value: [{
|
||||||
|
componentName: 'TextInput1',
|
||||||
|
props: {
|
||||||
|
txt: 'haha',
|
||||||
|
num: 1,
|
||||||
|
bool: true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
componentName: 'TextInput2',
|
||||||
|
props: {
|
||||||
|
txt: 'heihei',
|
||||||
|
num: 2,
|
||||||
|
bool: false
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 3);
|
||||||
|
expect(formNode?.slots).toHaveLength(1);
|
||||||
|
expect(formNode?.slots[0].children).toHaveLength(2);
|
||||||
|
|
||||||
|
let firstChildNode = formNode?.slots[0].children?.get(0);
|
||||||
|
expect(firstChildNode?.componentName).toBe('TextInput1');
|
||||||
|
expect(firstChildNode?.getPropValue('txt')).toBe('haha');
|
||||||
|
expect(firstChildNode?.getPropValue('num')).toBe(1);
|
||||||
|
expect(firstChildNode?.getPropValue('bool')).toBe(true);
|
||||||
|
|
||||||
|
formNode?.setPropValue('slotA', {
|
||||||
|
type: 'JSSlot',
|
||||||
|
name: 'slotA',
|
||||||
|
value: [{
|
||||||
|
componentName: 'TextInput3',
|
||||||
|
props: {
|
||||||
|
txt: 'xixi',
|
||||||
|
num: 3,
|
||||||
|
bool: false
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(nodesMap.size).toBe(ids.length + 2);
|
||||||
|
expect(formNode?.slots).toHaveLength(1);
|
||||||
|
expect(formNode?.slots[0].children).toHaveLength(1);
|
||||||
|
firstChildNode = formNode?.slots[0].children?.get(0);
|
||||||
|
expect(firstChildNode?.componentName).toBe('TextInput3');
|
||||||
|
expect(firstChildNode?.getPropValue('txt')).toBe('xixi');
|
||||||
|
expect(firstChildNode?.getPropValue('num')).toBe(3);
|
||||||
|
expect(firstChildNode?.getPropValue('bool')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
122
packages/designer/tests/node/node.remove.test.ts
Normal file
122
packages/designer/tests/node/node.remove.test.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const mockCreateSettingEntry = jest.fn();
|
||||||
|
jest.mock('../../src/designer/designer', () => {
|
||||||
|
return {
|
||||||
|
Designer: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
getComponentMeta() {
|
||||||
|
return {
|
||||||
|
getMetadata() {
|
||||||
|
return { experimental: null };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
transformProps(props) { return props; },
|
||||||
|
createSettingEntry: mockCreateSettingEntry,
|
||||||
|
postEvent() {},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let designer = null;
|
||||||
|
beforeAll(() => {
|
||||||
|
designer = new Designer({});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('节点模型删除测试', () => {
|
||||||
|
it('删除叶子节点', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const originalNodeCnt = ids.length;
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt);
|
||||||
|
|
||||||
|
currentDocument?.removeNode('node_k1ow3cbn');
|
||||||
|
// Button#1
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt - 1);
|
||||||
|
|
||||||
|
currentDocument?.removeNode(nodesMap.get('node_k1ow3cbp'));
|
||||||
|
// Button#2
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt - 2);
|
||||||
|
|
||||||
|
currentDocument?.removeNode('unexisting_node');
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt - 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('删除叶子节点,带有 slot', () => {
|
||||||
|
const formSchemaWithSlot = set(cloneDeep(formSchema),
|
||||||
|
'children[1].children[0].children[2].children[1].props.greeting.type', 'JSSlot');
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchemaWithSlot,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const originalNodeCnt = ids.length + 2;
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt);
|
||||||
|
|
||||||
|
currentDocument?.removeNode('node_k1ow3cbp');
|
||||||
|
// Button + Slot + Text
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt - 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('删除分支节点', () => {
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchema,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const originalNodeCnt = ids.length;
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt);
|
||||||
|
|
||||||
|
currentDocument?.removeNode('node_k1ow3cbo');
|
||||||
|
// Div + 2 * Button
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt - 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('删除分支节点,带有 slot', () => {
|
||||||
|
const formSchemaWithSlot = set(cloneDeep(formSchema),
|
||||||
|
'children[1].children[0].children[2].children[1].props.greeting.type', 'JSSlot');
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchemaWithSlot,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const originalNodeCnt = ids.length + 2;
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt);
|
||||||
|
|
||||||
|
currentDocument?.removeNode('node_k1ow3cbo');
|
||||||
|
// Div + 2 * Button + Slot + Text
|
||||||
|
expect(nodesMap.size).toBe(originalNodeCnt - 5);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import set from 'lodash.set';
|
import set from 'lodash/set';
|
||||||
import cloneDeep from 'lodash.clonedeep';
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
import '../fixtures/window';
|
import '../fixtures/window';
|
||||||
import { Project } from '../../src/project/project';
|
import { Project } from '../../src/project/project';
|
||||||
// import { Node } from '../../../src/document/node/node';
|
import { Node } from '../../src/document/node/node';
|
||||||
import { Designer } from '../../src/designer/designer';
|
import { Designer } from '../../src/designer/designer';
|
||||||
import formSchema from '../fixtures/schema/form';
|
import formSchema from '../fixtures/schema/form';
|
||||||
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
@ -34,7 +34,11 @@ beforeAll(() => {
|
|||||||
|
|
||||||
describe('schema 生成节点模型测试', () => {
|
describe('schema 生成节点模型测试', () => {
|
||||||
describe('block ❌ | component ❌ | slot ❌', () => {
|
describe('block ❌ | component ❌ | slot ❌', () => {
|
||||||
it('基本的节点模型初始化,模型导出', () => {
|
beforeEach(() => {
|
||||||
|
mockCreateSettingEntry.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
|
||||||
const project = new Project(designer, {
|
const project = new Project(designer, {
|
||||||
componentsTree: [
|
componentsTree: [
|
||||||
formSchema,
|
formSchema,
|
||||||
@ -56,129 +60,75 @@ describe('schema 生成节点模型测试', () => {
|
|||||||
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('节点新增(insertNode)', () => {
|
it('基本的节点模型初始化,模型导出,project.open 传入 schema', () => {
|
||||||
let project;
|
const project = new Project(designer);
|
||||||
beforeEach(() => {
|
project.open(formSchema);
|
||||||
project = new Project(designer, {
|
expect(project).toBeTruthy();
|
||||||
componentsTree: [
|
const { currentDocument } = project;
|
||||||
formSchema,
|
const { nodesMap } = currentDocument;
|
||||||
],
|
const ids = getIdsFromSchema(formSchema);
|
||||||
});
|
const expectedNodeCnt = ids.length;
|
||||||
project.open();
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
});
|
ids.forEach(id => {
|
||||||
it.only('场景一:插入 NodeSchema', () => {
|
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||||
expect(project).toBeTruthy();
|
|
||||||
const ids = getIdsFromSchema(formSchema);
|
|
||||||
const { currentDocument } = project;
|
|
||||||
const { nodesMap } = currentDocument;
|
|
||||||
const formNode = nodesMap.get('node_k1ow3cbq');
|
|
||||||
currentDocument?.insertNode(formNode, {
|
|
||||||
componentName: 'TextInput',
|
|
||||||
id: 'nodeschema-id1',
|
|
||||||
props: {
|
|
||||||
propA: 'haha',
|
|
||||||
propB: 3
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
|
||||||
expect(nodesMap.size).toBe(ids.length + 1);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it.only('场景一:插入 NodeSchema,有 children', () => {
|
const exportSchema = currentDocument?.export(1);
|
||||||
expect(project).toBeTruthy();
|
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
|
||||||
const ids = getIdsFromSchema(formSchema);
|
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
||||||
const { currentDocument } = project;
|
|
||||||
const { nodesMap } = currentDocument;
|
|
||||||
const formNode = nodesMap.get('node_k1ow3cbq');
|
|
||||||
currentDocument?.insertNode(formNode, {
|
|
||||||
componentName: 'TextInput',
|
|
||||||
id: 'nodeschema-id1',
|
|
||||||
props: {
|
|
||||||
propA: 'haha',
|
|
||||||
propB: 3
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
|
||||||
expect(nodesMap.size).toBe(ids.length + 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it.only('场景一:插入 NodeSchema,id 与现有 schema 重复', () => {
|
|
||||||
expect(project).toBeTruthy();
|
|
||||||
const ids = getIdsFromSchema(formSchema);
|
|
||||||
const { currentDocument } = project;
|
|
||||||
const { nodesMap } = currentDocument;
|
|
||||||
const formNode = nodesMap.get('node_k1ow3cbq');
|
|
||||||
currentDocument?.insertNode(formNode, {
|
|
||||||
componentName: 'TextInput',
|
|
||||||
id: 'nodeschema-id1',
|
|
||||||
props: {
|
|
||||||
propA: 'haha',
|
|
||||||
propB: 3
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
|
||||||
expect(nodesMap.size).toBe(ids.length + 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it.only('场景一:插入 NodeSchema,id 与现有 schema 重复,但关闭了 id 检测器', () => {
|
|
||||||
expect(project).toBeTruthy();
|
|
||||||
const ids = getIdsFromSchema(formSchema);
|
|
||||||
const { currentDocument } = project;
|
|
||||||
const { nodesMap } = currentDocument;
|
|
||||||
const formNode = nodesMap.get('node_k1ow3cbq');
|
|
||||||
currentDocument?.insertNode(formNode, {
|
|
||||||
componentName: 'TextInput',
|
|
||||||
id: 'nodeschema-id1',
|
|
||||||
props: {
|
|
||||||
propA: 'haha',
|
|
||||||
propB: 3
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
|
|
||||||
expect(nodesMap.size).toBe(ids.length + 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('场景二:插入 Node 实例', () => {
|
|
||||||
expect(project).toBeTruthy();
|
|
||||||
const ids = getIdsFromSchema(formSchema);
|
|
||||||
const { currentDocument } = project;
|
|
||||||
const { nodesMap } = currentDocument;
|
|
||||||
const formNode = nodesMap.get('node_k1ow3cbq');
|
|
||||||
const inputNode = currentDocument?.createNode({
|
|
||||||
componentName: 'TextInput',
|
|
||||||
id: 'nodeschema-id2',
|
|
||||||
props: {
|
|
||||||
propA: 'haha',
|
|
||||||
propB: 3
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(inputNode.id).toBe('nodeschema-id2');
|
|
||||||
currentDocument?.insertNode(formNode, inputNode);
|
|
||||||
expect(nodesMap.get('nodeschema-id2').componentName).toBe('TextInput');
|
|
||||||
expect(nodesMap.size).toBe(ids.length + 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('场景二:插入 JSExpression', () => {});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
it('project 卸载所有 document - unload()', () => {
|
||||||
|
const project = new Project(designer);
|
||||||
|
project.open(formSchema);
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument, documents } = project;
|
||||||
|
|
||||||
it('block ❌ | component ❌ | slot ✅', () => {
|
expect(documents).toHaveLength(1);
|
||||||
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
|
expect(currentDocument).toBe(documents[0]);
|
||||||
const project = new Project(designer, {
|
|
||||||
componentsTree: [
|
project.unload();
|
||||||
formSchemaWithSlot,
|
|
||||||
],
|
expect(documents).toHaveLength(0);
|
||||||
});
|
});
|
||||||
project.open();
|
|
||||||
expect(project).toBeTruthy();
|
it('project 卸载指定 document - removeDocument()', () => {
|
||||||
const { currentDocument } = project;
|
const project = new Project(designer);
|
||||||
const { nodesMap } = currentDocument;
|
project.open(formSchema);
|
||||||
const ids = getIdsFromSchema(formSchema);
|
expect(project).toBeTruthy();
|
||||||
// 目前每个 slot 会新增 1 + children.length 个节点
|
const { currentDocument, documents } = project;
|
||||||
const expectedNodeCnt = ids.length + 2;
|
|
||||||
expect(nodesMap.size).toBe(expectedNodeCnt);
|
expect(documents).toHaveLength(1);
|
||||||
// PageHeader
|
expect(currentDocument).toBe(documents[0]);
|
||||||
expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
|
|
||||||
|
project.removeDocument(currentDocument);
|
||||||
|
|
||||||
|
expect(documents).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('block ❌ | component ❌ | slot ✅', () => {
|
||||||
|
it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
|
||||||
|
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
|
||||||
|
const project = new Project(designer, {
|
||||||
|
componentsTree: [
|
||||||
|
formSchemaWithSlot,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
project.open();
|
||||||
|
expect(project).toBeTruthy();
|
||||||
|
const { currentDocument } = project;
|
||||||
|
const { nodesMap } = currentDocument!;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
// 目前每个 slot 会新增(1 + children.length)个节点
|
||||||
|
const expectedNodeCnt = ids.length + 2;
|
||||||
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
// PageHeader
|
||||||
|
expect(nodesMap.get('node_k1ow3cbd').slots).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe.skip('多 document 测试', () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
105
packages/designer/tests/setting-entry/setting-prop-entry.test.ts
Normal file
105
packages/designer/tests/setting-entry/setting-prop-entry.test.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import settingSchema from '../fixtures/schema/setting';
|
||||||
|
import divMeta from '../fixtures/prototype/div-meta';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const editor = new Editor();
|
||||||
|
|
||||||
|
describe('setting-prop-entry 测试', () => {
|
||||||
|
let designer: Designer;
|
||||||
|
beforeEach(() => {
|
||||||
|
designer = new Designer({ editor });
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
designer._componentMetasMap.clear();
|
||||||
|
designer = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('node 构造函数生成 settingEntry', () => {
|
||||||
|
it.only('常规方法测试', () => {
|
||||||
|
designer.createComponentMeta(divMeta);
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
|
||||||
|
const { settingEntry } = divNode!;
|
||||||
|
const behaviorProp = settingEntry.getProp('behavior');
|
||||||
|
expect(behaviorProp.getProps()).toBe(settingEntry);
|
||||||
|
expect(behaviorProp.props).toBe(settingEntry);
|
||||||
|
expect(behaviorProp.getName()).toBe('behavior');
|
||||||
|
expect(behaviorProp.getKey()).toBe('behavior');
|
||||||
|
expect(behaviorProp.isIgnore()).toBeFalsy;
|
||||||
|
behaviorProp.setKey('behavior2');
|
||||||
|
expect(behaviorProp.getKey()).toBe('behavior2');
|
||||||
|
behaviorProp.setKey('behavior');
|
||||||
|
expect(behaviorProp.getValue()).toBe('NORMAL');
|
||||||
|
expect(behaviorProp.getMockOrValue()).toBe('NORMAL');
|
||||||
|
|
||||||
|
behaviorProp.setValue('LARGE');
|
||||||
|
expect(behaviorProp.getValue()).toBe('LARGE');
|
||||||
|
// behaviorProp.setPropValue('behavior', 'SMALL');
|
||||||
|
// expect(behaviorProp.getValue()).toBe('SMALL');
|
||||||
|
behaviorProp.setValue('NORMAL');
|
||||||
|
expect(behaviorProp.getValue()).toBe('NORMAL');
|
||||||
|
|
||||||
|
behaviorProp.clearValue();
|
||||||
|
behaviorProp.clearPropValue();
|
||||||
|
expect(settingEntry.getProp('behavior').getValue()).toBeUndefined;
|
||||||
|
|
||||||
|
behaviorProp.setValue('LARGE');
|
||||||
|
expect(behaviorProp.getValue()).toBe('LARGE');
|
||||||
|
behaviorProp.remove();
|
||||||
|
expect(settingEntry.getProp('behavior').getValue()).toBeUndefined;
|
||||||
|
|
||||||
|
expect(behaviorProp.getNode()).toBe(divNode);
|
||||||
|
expect(behaviorProp.getId().startsWith('entry')).toBeTruthy;
|
||||||
|
expect(behaviorProp.designer).toBe(designer);
|
||||||
|
expect(behaviorProp.isSingle).toBeTruthy;
|
||||||
|
expect(behaviorProp.isMultiple).toBeFalsy;
|
||||||
|
expect(behaviorProp.isGroup).toBeFalsy;
|
||||||
|
expect(behaviorProp.isSameComponent).toBeTruthy;
|
||||||
|
expect(typeof settingEntry.getValue).toBe('function');
|
||||||
|
settingEntry.getValue();
|
||||||
|
|
||||||
|
behaviorProp.setExtraPropValue('extraPropA', 'heihei');
|
||||||
|
expect(behaviorProp.getExtraPropValue('extraPropA', 'heihei'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('type: group 场景测试', () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('JSExpression 类型的 prop', () => {
|
||||||
|
designer.createComponentMeta(divMeta);
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
|
||||||
|
const { settingEntry } = divNode!;
|
||||||
|
const customClassNameProp = settingEntry.getProp('customClassName');
|
||||||
|
expect(customClassNameProp.isUseVariable()).toBeTruthy;
|
||||||
|
expect(customClassNameProp.useVariable).toBeTruthy;
|
||||||
|
|
||||||
|
expect(customClassNameProp.getValue()).toEqual({
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'getFromSomewhere()'
|
||||||
|
});
|
||||||
|
expect(customClassNameProp.getMockOrValue()).toBeUndefined;
|
||||||
|
expect(customClassNameProp.getVariableValue()).toBe('getFromSomewhere()');
|
||||||
|
customClassNameProp.setVariableValue('xxx');
|
||||||
|
expect(customClassNameProp.getVariableValue()).toBe('xxx');
|
||||||
|
|
||||||
|
const customClassName2Prop = settingEntry.getProp('customClassName2');
|
||||||
|
expect(customClassName2Prop.getMockOrValue()).toEqual({
|
||||||
|
hi: 'mock',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
174
packages/designer/tests/setting-entry/setting-top-entry.test.ts
Normal file
174
packages/designer/tests/setting-entry/setting-top-entry.test.ts
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
|
import { Project } from '../../src/project/project';
|
||||||
|
import { Node } from '../../src/document/node/node';
|
||||||
|
import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import settingSchema from '../fixtures/schema/setting';
|
||||||
|
import divMeta from '../fixtures/prototype/div-meta';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
const editor = new Editor();
|
||||||
|
|
||||||
|
describe('setting-top-entry 测试', () => {
|
||||||
|
let designer: Designer;
|
||||||
|
beforeEach(() => {
|
||||||
|
designer = new Designer({ editor });
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
designer._componentMetasMap.clear();
|
||||||
|
designer = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('node 构造函数生成 settingEntry', () => {
|
||||||
|
it('常规方法测试', () => {
|
||||||
|
designer.createComponentMeta(divMeta);
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
|
||||||
|
const { settingEntry } = divNode!;
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBe('NORMAL');
|
||||||
|
expect(settingEntry.getProp('behavior').getValue()).toBe('NORMAL');
|
||||||
|
settingEntry.setPropValue('behavior', 'LARGE');
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBe('LARGE');
|
||||||
|
expect(settingEntry.get('behavior').getValue()).toBe('LARGE');
|
||||||
|
settingEntry.getProp('behavior').setValue('SMALL');
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBe('SMALL');
|
||||||
|
settingEntry.clearPropValue('behavior');
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBeUndefined;
|
||||||
|
|
||||||
|
expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o');
|
||||||
|
settingEntry.setPropValue('fieldId', 'div_k1ow3h1o_new');
|
||||||
|
expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o_new');
|
||||||
|
|
||||||
|
expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha');
|
||||||
|
settingEntry.setExtraPropValue('extraPropA', 'haha2');
|
||||||
|
expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha2');
|
||||||
|
|
||||||
|
settingEntry.mergeProps({
|
||||||
|
newPropA: 'haha',
|
||||||
|
});
|
||||||
|
expect(settingEntry.getPropValue('newPropA')).toBe('haha');
|
||||||
|
settingEntry.setProps({
|
||||||
|
newPropB: 'haha',
|
||||||
|
});
|
||||||
|
expect(settingEntry.getPropValue('newPropB')).toBe('haha');
|
||||||
|
settingEntry.setValue({
|
||||||
|
newPropC: 'haha',
|
||||||
|
});
|
||||||
|
expect(settingEntry.getPropValue('newPropC')).toBe('haha');
|
||||||
|
|
||||||
|
expect(settingEntry.getPage()).toBe(currentDocument);
|
||||||
|
expect(settingEntry.getNode()).toBe(divNode);
|
||||||
|
expect(settingEntry.node).toBe(divNode);
|
||||||
|
expect(settingEntry.getId()).toBe('div');
|
||||||
|
expect(settingEntry.first).toBe(divNode);
|
||||||
|
expect(settingEntry.designer).toBe(designer);
|
||||||
|
expect(settingEntry.isSingle).toBeTruthy;
|
||||||
|
expect(settingEntry.isMultiple).toBeFalsy;
|
||||||
|
expect(settingEntry.isSameComponent).toBeTruthy;
|
||||||
|
|
||||||
|
expect(typeof settingEntry.getValue).toBe('function');
|
||||||
|
settingEntry.getValue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('清理方法测试', () => {
|
||||||
|
designer.createComponentMeta(divMeta);
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
|
||||||
|
const { settingEntry } = divNode!;
|
||||||
|
expect(settingEntry.items).toHaveLength(3);
|
||||||
|
settingEntry.purge();
|
||||||
|
expect(settingEntry.items).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('vision 兼容测试', () => {
|
||||||
|
designer.createComponentMeta(divMeta);
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
|
||||||
|
console.log(divNode?.getPropValue('behavior'));
|
||||||
|
const { settingEntry } = divNode!;
|
||||||
|
|
||||||
|
expect(typeof settingEntry.getChildren).toBe('function');
|
||||||
|
expect(typeof settingEntry.getDOMNode).toBe('function');
|
||||||
|
expect(typeof settingEntry.getStatus).toBe('function');
|
||||||
|
expect(typeof settingEntry.setStatus).toBe('function');
|
||||||
|
settingEntry.getStatus();
|
||||||
|
settingEntry.setStatus();
|
||||||
|
settingEntry.getChildren();
|
||||||
|
settingEntry.getDOMNode();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('没有 node', () => {
|
||||||
|
const create1 = designer.createSettingEntry.bind(designer);
|
||||||
|
const create2 = designer.createSettingEntry.bind(designer, []);
|
||||||
|
expect(create1).toThrowError('nodes should not be empty');
|
||||||
|
expect(create2).toThrowError('nodes should not be empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('designer.createSettingEntry 生成 settingEntry(多 node 场景)', () => {
|
||||||
|
it('相同类型的 node', () => {
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
const divNode2 = currentDocument?.getNode('div2');
|
||||||
|
const settingEntry = designer.createSettingEntry([divNode, divNode2]);
|
||||||
|
|
||||||
|
expect(settingEntry.isMultiple).toBeTruthy;
|
||||||
|
expect(settingEntry.isSameComponent).toBeTruthy;
|
||||||
|
expect(settingEntry.isSingle).toBeFalsy;
|
||||||
|
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBe('NORMAL');
|
||||||
|
expect(settingEntry.getProp('behavior').getValue()).toBe('NORMAL');
|
||||||
|
settingEntry.setPropValue('behavior', 'LARGE');
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBe('LARGE');
|
||||||
|
expect(settingEntry.get('behavior').getValue()).toBe('LARGE');
|
||||||
|
// 多个 node 都被成功设值
|
||||||
|
expect(divNode?.getPropValue('behavior')).toBe('LARGE');
|
||||||
|
expect(divNode2?.getPropValue('behavior')).toBe('LARGE');
|
||||||
|
|
||||||
|
settingEntry.getProp('behavior').setValue('SMALL');
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBe('SMALL');
|
||||||
|
// 多个 node 都被成功设值
|
||||||
|
expect(divNode?.getPropValue('behavior')).toBe('SMALL');
|
||||||
|
expect(divNode2?.getPropValue('behavior')).toBe('SMALL');
|
||||||
|
|
||||||
|
settingEntry.clearPropValue('behavior');
|
||||||
|
expect(settingEntry.getPropValue('behavior')).toBeUndefined;
|
||||||
|
// 多个 node 都被成功设值
|
||||||
|
expect(divNode?.getPropValue('behavior')).toBeUndefined;
|
||||||
|
expect(divNode2?.getPropValue('behavior')).toBeUndefined;
|
||||||
|
|
||||||
|
expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o');
|
||||||
|
settingEntry.setPropValue('fieldId', 'div_k1ow3h1o_new');
|
||||||
|
expect(settingEntry.getPropValue('fieldId')).toBe('div_k1ow3h1o_new');
|
||||||
|
|
||||||
|
expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha');
|
||||||
|
settingEntry.setExtraPropValue('extraPropA', 'haha2');
|
||||||
|
expect(settingEntry.getExtraPropValue('extraPropA')).toBe('haha2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('不同类型的 node', () => {
|
||||||
|
designer.project.open(settingSchema);
|
||||||
|
const { currentDocument } = designer.project;
|
||||||
|
const divNode = currentDocument?.getNode('div');
|
||||||
|
const testNode = currentDocument?.getNode('test');
|
||||||
|
const settingEntry = designer.createSettingEntry([divNode, testNode]);
|
||||||
|
|
||||||
|
expect(settingEntry.isMultiple).toBeTruthy;
|
||||||
|
expect(settingEntry.isSameComponent).toBeFalsy;
|
||||||
|
expect(settingEntry.isSingle).toBeFalsy;
|
||||||
|
|
||||||
|
// 不同类型的 node 场景下,理论上从页面上已没有修改属性的方法调用,所以此处不再断言各设值方法
|
||||||
|
// 思考:假如以后面向其他场景,比如用户用 API 强行调用,是否需要做健壮性保护?
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-core
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-core",
|
"name": "@ali/lowcode-editor-core",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "Core Api for Ali lowCode engine",
|
"description": "Core Api for Ali lowCode engine",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
@ -15,8 +15,8 @@
|
|||||||
"cloud-build": "build-scripts build --skip-demo"
|
"cloud-build": "build-scripts build --skip-demo"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.19.16",
|
"@alifd/next": "^1.19.16",
|
||||||
"@recore/obx": "^1.0.9",
|
"@recore/obx": "^1.0.9",
|
||||||
"@recore/obx-react": "^1.0.8",
|
"@recore/obx-react": "^1.0.8",
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-preset-general
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-preset-general",
|
"name": "@ali/lowcode-editor-preset-general",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "Ali General Editor Preset",
|
"description": "Ali General Editor Preset",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
@ -14,12 +14,12 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-skeleton": "^0.13.1-10",
|
"@ali/lowcode-editor-skeleton": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-designer": "^0.13.1-10",
|
"@ali/lowcode-plugin-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-outline-pane": "^0.13.1-10",
|
"@ali/lowcode-plugin-outline-pane": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.19.12",
|
"@alifd/next": "^1.19.12",
|
||||||
"@alife/theme-lowcode-dark": "^0.1.0",
|
"@alife/theme-lowcode-dark": "^0.1.0",
|
||||||
"@alife/theme-lowcode-light": "^0.1.0",
|
"@alife/theme-lowcode-light": "^0.1.0",
|
||||||
@ -27,7 +27,7 @@
|
|||||||
"react-dom": "^16.8.1"
|
"react-dom": "^16.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ali/lowcode-editor-setters": "^0.13.1-10",
|
"@ali/lowcode-editor-setters": "^0.13.1-11",
|
||||||
"@alib/build-scripts": "^0.1.18",
|
"@alib/build-scripts": "^0.1.18",
|
||||||
"@types/events": "^3.0.0",
|
"@types/events": "^3.0.0",
|
||||||
"@types/react": "^16.8.3",
|
"@types/react": "^16.8.3",
|
||||||
|
|||||||
@ -2,7 +2,7 @@ module.exports = {
|
|||||||
extends: 'eslint-config-ali/typescript/react',
|
extends: 'eslint-config-ali/typescript/react',
|
||||||
rules: {
|
rules: {
|
||||||
'react/no-multi-comp': 1,
|
'react/no-multi-comp': 1,
|
||||||
'no-unused-expressions': 1,
|
'no-unused-expressions': 0,
|
||||||
'implicit-arrow-linebreak': 1,
|
'implicit-arrow-linebreak': 1,
|
||||||
'no-nested-ternary': 1,
|
'no-nested-ternary': 1,
|
||||||
'no-mixed-operators': 1,
|
'no-mixed-operators': 1,
|
||||||
@ -16,5 +16,6 @@ module.exports = {
|
|||||||
'react/no-deprecated': 1,
|
'react/no-deprecated': 1,
|
||||||
'no-useless-escape': 1,
|
'no-useless-escape': 1,
|
||||||
'brace-style': 1,
|
'brace-style': 1,
|
||||||
|
'@typescript-eslint/member-ordering': 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 解决 slot 在关闭时没有正常回收节点 ([642a404](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/642a404))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
19
packages/editor-preset-vision/build.test.json
Normal file
19
packages/editor-preset-vision/build.test.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
[
|
||||||
|
"build-plugin-component",
|
||||||
|
{
|
||||||
|
"filename": "editor-preset-vision",
|
||||||
|
"library": "LowcodeEditor",
|
||||||
|
"libraryTarget": "umd",
|
||||||
|
"externals": {
|
||||||
|
"react": "var window.React",
|
||||||
|
"react-dom": "var window.ReactDOM",
|
||||||
|
"prop-types": "var window.PropTypes",
|
||||||
|
"rax": "var window.Rax"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@ali/lowcode-test-mate/plugin/index.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
26
packages/editor-preset-vision/jest.config.js
Normal file
26
packages/editor-preset-vision/jest.config.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const esModules = [
|
||||||
|
'@recore/obx-react',
|
||||||
|
// '@ali/lowcode-editor-core',
|
||||||
|
].join('|');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// transform: {
|
||||||
|
// '^.+\\.[jt]sx?$': 'babel-jest',
|
||||||
|
// // '^.+\\.(ts|tsx)$': 'ts-jest',
|
||||||
|
// // '^.+\\.(js|jsx)$': 'babel-jest',
|
||||||
|
// },
|
||||||
|
// testMatch: ['(/tests?/.*(test))\\.[jt]s$'],
|
||||||
|
transformIgnorePatterns: [
|
||||||
|
`/node_modules/(?!${esModules})/`,
|
||||||
|
],
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
|
||||||
|
collectCoverage: false,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'src/**/*.{ts,tsx}',
|
||||||
|
'!src/**/*.d.ts',
|
||||||
|
'!src/base/**',
|
||||||
|
'!src/prop.ts',
|
||||||
|
'!**/node_modules/**',
|
||||||
|
'!**/vendor/**',
|
||||||
|
],
|
||||||
|
};
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-preset-vision",
|
"name": "@ali/lowcode-editor-preset-vision",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "Vision Polyfill for Ali lowCode engine",
|
"description": "Vision Polyfill for Ali lowCode engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
@ -11,17 +11,18 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "build-scripts build --skip-demo",
|
"build": "build-scripts build --skip-demo",
|
||||||
"cloud-build": "build-scripts build --skip-demo"
|
"cloud-build": "build-scripts build --skip-demo",
|
||||||
|
"test": "build-scripts test --config build.test.json"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-designer": "^0.13.1-10",
|
"@ali/lowcode-editor-setters": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-skeleton": "^0.13.1-10",
|
"@ali/lowcode-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-designer": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-plugin-outline-pane": "^0.13.1-10",
|
"@ali/lowcode-editor-skeleton": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-setters": "^0.13.1-10",
|
"@ali/lowcode-plugin-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-plugin-outline-pane": "^0.13.1-11",
|
||||||
"@ali/ve-i18n-util": "^2.0.0",
|
"@ali/ve-i18n-util": "^2.0.0",
|
||||||
"@ali/ve-icons": "^4.1.9",
|
"@ali/ve-icons": "^4.1.9",
|
||||||
"@ali/ve-less-variables": "2.0.3",
|
"@ali/ve-less-variables": "2.0.3",
|
||||||
@ -39,6 +40,7 @@
|
|||||||
"react-dom": "^16.8.1"
|
"react-dom": "^16.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@ali/lowcode-test-mate": "^1.0.0",
|
||||||
"@alib/build-scripts": "^0.1.18",
|
"@alib/build-scripts": "^0.1.18",
|
||||||
"@types/domready": "^1.0.0",
|
"@types/domready": "^1.0.0",
|
||||||
"@types/events": "^3.0.0",
|
"@types/events": "^3.0.0",
|
||||||
@ -47,6 +49,7 @@
|
|||||||
"build-plugin-fusion": "^0.1.0",
|
"build-plugin-fusion": "^0.1.0",
|
||||||
"build-plugin-moment-locales": "^0.1.0",
|
"build-plugin-moment-locales": "^0.1.0",
|
||||||
"build-plugin-react-app": "^1.1.2",
|
"build-plugin-react-app": "^1.1.2",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
"tsconfig-paths-webpack-plugin": "^3.2.0"
|
"tsconfig-paths-webpack-plugin": "^3.2.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|||||||
@ -65,15 +65,15 @@ export class Bus {
|
|||||||
|
|
||||||
const bus = new Bus();
|
const bus = new Bus();
|
||||||
|
|
||||||
editor.on('hotkey.callback.call', (data) => {
|
editor?.on('hotkey.callback.call', (data) => {
|
||||||
bus.emit('ve.hotkey.callback.call', data);
|
bus.emit('ve.hotkey.callback.call', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('history.back', (data) => {
|
editor?.on('history.back', (data) => {
|
||||||
bus.emit('ve.history.back', data);
|
bus.emit('ve.history.back', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('history.forward', (data) => {
|
editor?.on('history.forward', (data) => {
|
||||||
bus.emit('ve.history.forward', data);
|
bus.emit('ve.history.forward', data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,6 @@ import { isPlainObject, hasOwnProperty, cloneDeep, isI18NObject, isUseI18NSetter
|
|||||||
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
import { Designer, LiveEditing, TransformStage, Node, getConvertedExtraKey } from '@ali/lowcode-designer';
|
import { Designer, LiveEditing, TransformStage, Node, getConvertedExtraKey } from '@ali/lowcode-designer';
|
||||||
import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane';
|
import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane';
|
||||||
import { toCss } from '@ali/vu-css-style';
|
|
||||||
import logger from '@ali/vu-logger';
|
|
||||||
import bus from './bus';
|
import bus from './bus';
|
||||||
import { VE_EVENTS } from './base/const';
|
import { VE_EVENTS } from './base/const';
|
||||||
|
|
||||||
@ -13,7 +11,16 @@ import { Skeleton, SettingsPrimaryPane, registerDefaults } from '@ali/lowcode-ed
|
|||||||
|
|
||||||
import { deepValueParser } from './deep-value-parser';
|
import { deepValueParser } from './deep-value-parser';
|
||||||
import { liveEditingRule, liveEditingSaveHander } from './vc-live-editing';
|
import { liveEditingRule, liveEditingSaveHander } from './vc-live-editing';
|
||||||
import { isVariable } from './utils';
|
import {
|
||||||
|
compatibleReducer,
|
||||||
|
compatiblePageReducer,
|
||||||
|
stylePropsReducer,
|
||||||
|
upgradePropsReducer,
|
||||||
|
filterReducer,
|
||||||
|
removeEmptyPropsReducer,
|
||||||
|
initNodeReducer,
|
||||||
|
liveLifecycleReducer,
|
||||||
|
} from './props-reducers';
|
||||||
|
|
||||||
export const editor = new Editor();
|
export const editor = new Editor();
|
||||||
globalContext.register(editor, Editor);
|
globalContext.register(editor, Editor);
|
||||||
@ -31,313 +38,31 @@ designer.project.onCurrentDocumentChange((doc) => {
|
|||||||
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Variable {
|
|
||||||
type: 'variable';
|
|
||||||
variable: string;
|
|
||||||
value: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
function upgradePropsReducer(props: any) {
|
|
||||||
if (!props || !isPlainObject(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
if (isJSBlock(props)) {
|
|
||||||
if (props.value.componentName === 'Slot') {
|
|
||||||
return {
|
|
||||||
type: 'JSSlot',
|
|
||||||
title: (props.value.props as any)?.slotTitle,
|
|
||||||
name: (props.value.props as any)?.slotName,
|
|
||||||
value: props.value.children,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return props.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isVariable(props)) {
|
|
||||||
return {
|
|
||||||
type: 'JSExpression',
|
|
||||||
value: props.variable,
|
|
||||||
mock: props.value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const newProps: any = {};
|
|
||||||
Object.keys(props).forEach((key) => {
|
|
||||||
if (/^__slot__/.test(key) && props[key] === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
newProps[key] = upgradePropsReducer(props[key]);
|
|
||||||
});
|
|
||||||
return newProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 升级 Props
|
// 升级 Props
|
||||||
designer.addPropsReducer(upgradePropsReducer, TransformStage.Upgrade);
|
designer.addPropsReducer(upgradePropsReducer, TransformStage.Upgrade);
|
||||||
|
|
||||||
function getCurrentFieldIds() {
|
|
||||||
const fieldIds: any = [];
|
|
||||||
const nodesMap = designer?.currentDocument?.nodesMap || new Map();
|
|
||||||
nodesMap.forEach((curNode: any) => {
|
|
||||||
const fieldId = nodesMap?.get(curNode.id)?.getPropValue('fieldId');
|
|
||||||
if (fieldId) {
|
|
||||||
fieldIds.push(fieldId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return fieldIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 节点 props 初始化
|
// 节点 props 初始化
|
||||||
designer.addPropsReducer((props, node) => {
|
designer.addPropsReducer(initNodeReducer, TransformStage.Init);
|
||||||
// debugger;
|
|
||||||
// run initials
|
|
||||||
const newProps: any = {
|
|
||||||
...props,
|
|
||||||
};
|
|
||||||
if (newProps.fieldId) {
|
|
||||||
const fieldIds = getCurrentFieldIds();
|
|
||||||
|
|
||||||
// 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
|
designer.addPropsReducer(liveLifecycleReducer, TransformStage.Render);
|
||||||
if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
|
|
||||||
newProps.fieldId = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const initials = node.componentMeta.getMetadata().experimental?.initials;
|
|
||||||
if (initials) {
|
|
||||||
const getRealValue = (propValue: any) => {
|
|
||||||
if (isVariable(propValue)) {
|
|
||||||
return propValue.value;
|
|
||||||
}
|
|
||||||
if (isJSExpression(propValue)) {
|
|
||||||
return propValue.mock;
|
|
||||||
}
|
|
||||||
return propValue;
|
|
||||||
};
|
|
||||||
initials.forEach((item) => {
|
|
||||||
// FIXME! this implements SettingTarget
|
|
||||||
try {
|
|
||||||
// FIXME! item.name could be 'xxx.xxx'
|
|
||||||
const ov = newProps[item.name];
|
|
||||||
const v = item.initial(node as any, getRealValue(ov));
|
|
||||||
if (ov === undefined && v !== undefined) {
|
|
||||||
newProps[item.name] = v;
|
|
||||||
}
|
|
||||||
// 兼容 props 中的属性为 i18n 类型,但是仅提供了一个字符串值,非变量绑定
|
|
||||||
if (isUseI18NSetter(node.componentMeta.prototype, item.name) &&
|
|
||||||
!isI18NObject(ov) &&
|
|
||||||
!isJSExpression(ov) &&
|
|
||||||
!isJSBlock(ov) &&
|
|
||||||
!isJSSlot(ov) &&
|
|
||||||
!isVariable(ov) &&
|
|
||||||
isString(v)) {
|
|
||||||
newProps[item.name] = convertToI18NObject(v);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (hasOwnProperty(props, item.name)) {
|
|
||||||
newProps[item.name] = props[item.name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newProps[item.name] && !node.props.has(item.name)) {
|
|
||||||
node.props.add(newProps[item.name], item.name, false, { skipSetSlot: true });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return newProps;
|
|
||||||
}, TransformStage.Init);
|
|
||||||
|
|
||||||
designer.addPropsReducer((props: any, node: Node) => {
|
|
||||||
// live 模式下解析 lifeCycles
|
|
||||||
if (node.isRoot() && props && props.lifeCycles) {
|
|
||||||
if (editor.get('designMode') === 'live') {
|
|
||||||
const lifeCycleMap = {
|
|
||||||
didMount: 'componentDidMount',
|
|
||||||
willUnmount: 'componentWillUnMount',
|
|
||||||
};
|
|
||||||
const lifeCycles = props.lifeCycles;
|
|
||||||
Object.keys(lifeCycleMap).forEach(key => {
|
|
||||||
if (lifeCycles[key]) {
|
|
||||||
lifeCycles[lifeCycleMap[key]] = lifeCycles[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...props,
|
|
||||||
lifeCycles: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}, TransformStage.Render);
|
|
||||||
|
|
||||||
function filterReducer(props: any, node: Node): any {
|
|
||||||
const filters = node.componentMeta.getMetadata().experimental?.filters;
|
|
||||||
if (filters && filters.length) {
|
|
||||||
const newProps = { ...props };
|
|
||||||
filters.forEach((item) => {
|
|
||||||
// FIXME! item.name could be 'xxx.xxx'
|
|
||||||
if (!hasOwnProperty(newProps, item.name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (item.filter(node.settingEntry.getProp(item.name), props[item.name]) === false) {
|
|
||||||
delete newProps[item.name];
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
logger.trace(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return newProps;
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
designer.addPropsReducer(filterReducer, TransformStage.Save);
|
designer.addPropsReducer(filterReducer, TransformStage.Save);
|
||||||
designer.addPropsReducer(filterReducer, TransformStage.Render);
|
designer.addPropsReducer(filterReducer, TransformStage.Render);
|
||||||
|
|
||||||
function compatiableReducer(props: any) {
|
|
||||||
if (!props || !isPlainObject(props)) {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
// 为了能降级到老版本,建议在后期版本去掉以下代码
|
|
||||||
if (isJSSlot(props)) {
|
|
||||||
return {
|
|
||||||
type: 'JSBlock',
|
|
||||||
value: {
|
|
||||||
componentName: 'Slot',
|
|
||||||
children: props.value,
|
|
||||||
props: {
|
|
||||||
slotTitle: props.title,
|
|
||||||
slotName: props.name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (isJSExpression(props) && !props.events) {
|
|
||||||
return {
|
|
||||||
type: 'variable',
|
|
||||||
value: props.mock,
|
|
||||||
variable: props.value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const newProps: any = {};
|
|
||||||
Object.entries<any>(props).forEach(([key, val]) => {
|
|
||||||
newProps[key] = compatiableReducer(val);
|
|
||||||
});
|
|
||||||
return newProps;
|
|
||||||
}
|
|
||||||
// FIXME: Dirty fix, will remove this reducer
|
// FIXME: Dirty fix, will remove this reducer
|
||||||
designer.addPropsReducer(compatiableReducer, TransformStage.Save);
|
designer.addPropsReducer(compatibleReducer, TransformStage.Save);
|
||||||
// 兼容历史版本的 Page 组件
|
// 兼容历史版本的 Page 组件
|
||||||
designer.addPropsReducer((props: any, node: Node) => {
|
designer.addPropsReducer(compatiblePageReducer, TransformStage.Save);
|
||||||
const lifeCycleNames = ['didMount', 'willUnmount'];
|
|
||||||
if (node.isRoot()) {
|
|
||||||
lifeCycleNames.forEach((key) => {
|
|
||||||
if (props[key]) {
|
|
||||||
const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
|
|
||||||
lifeCycles[key] = props[key];
|
|
||||||
node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}, TransformStage.Save);
|
|
||||||
|
|
||||||
// designer.addPropsReducer((props: any, node: Node) => {
|
|
||||||
// const lifeCycleNames = ['didMount', 'willUnmount'];
|
|
||||||
// const lifeCycleMap = {
|
|
||||||
// didMount: 'componentDidMount',
|
|
||||||
// willUnmount: 'componentWillUnMount',
|
|
||||||
// };
|
|
||||||
// if (node.componentName === 'Page') {
|
|
||||||
// debugger;
|
|
||||||
// lifeCycleNames.forEach(key => {
|
|
||||||
// if (props[key]) {
|
|
||||||
// const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
|
|
||||||
// lifeCycles[lifeCycleMap[key]] = props[key];
|
|
||||||
// node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
|
|
||||||
// } else if (node.props.getPropValue(getConvertedExtraKey('lifeCycles'))) {
|
|
||||||
// const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
|
|
||||||
// lifeCycles[lifeCycleMap[key]] = lifeCycles[key];
|
|
||||||
// node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// return props;
|
|
||||||
// }, TransformStage.Init);
|
|
||||||
|
|
||||||
// 设计器组件样式处理
|
// 设计器组件样式处理
|
||||||
function stylePropsReducer(props: any, node: any) {
|
|
||||||
if (props && typeof props === 'object' && props.__style__) {
|
|
||||||
const cssId = `_style_pesudo_${ node.id.replace(/\$/g, '_')}`;
|
|
||||||
const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
|
|
||||||
const styleProp = props.__style__;
|
|
||||||
appendStyleNode(props, styleProp, cssClass, cssId);
|
|
||||||
}
|
|
||||||
if (props && typeof props === 'object' && props.pageStyle) {
|
|
||||||
const cssId = '_style_pesudo_engine-document';
|
|
||||||
const cssClass = 'engine-document';
|
|
||||||
const styleProp = props.pageStyle;
|
|
||||||
appendStyleNode(props, styleProp, cssClass, cssId);
|
|
||||||
}
|
|
||||||
if (props && typeof props === 'object' && props.containerStyle) {
|
|
||||||
const cssId = `_style_pesudo_${ node.id}`;
|
|
||||||
const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
|
|
||||||
const styleProp = props.containerStyle;
|
|
||||||
appendStyleNode(props, styleProp, cssClass, cssId);
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendStyleNode(props: any, styleProp: any, cssClass: string, cssId: string) {
|
|
||||||
const doc = designer.currentDocument?.simulator?.contentDocument;
|
|
||||||
if (!doc) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const dom = doc.getElementById(cssId);
|
|
||||||
if (dom) {
|
|
||||||
dom.parentNode?.removeChild(dom);
|
|
||||||
}
|
|
||||||
if (typeof styleProp === 'object') {
|
|
||||||
styleProp = toCss(styleProp);
|
|
||||||
}
|
|
||||||
if (typeof styleProp === 'string') {
|
|
||||||
const s = doc.createElement('style');
|
|
||||||
props.className = cssClass;
|
|
||||||
s.setAttribute('type', 'text/css');
|
|
||||||
s.setAttribute('id', cssId);
|
|
||||||
doc.getElementsByTagName('head')[0].appendChild(s);
|
|
||||||
|
|
||||||
s.appendChild(doc.createTextNode(styleProp.replace(/(\d+)rpx/g, (a, b) => {
|
|
||||||
return `${b / 2}px`;
|
|
||||||
}).replace(/:root/g, `.${ cssClass}`)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
designer.addPropsReducer(stylePropsReducer, TransformStage.Render);
|
designer.addPropsReducer(stylePropsReducer, TransformStage.Render);
|
||||||
// 国际化 & Expression 渲染时处理
|
// 国际化 & Expression 渲染时处理
|
||||||
designer.addPropsReducer(deepValueParser, TransformStage.Render);
|
designer.addPropsReducer(deepValueParser, TransformStage.Render);
|
||||||
|
|
||||||
// 清除空的 props value
|
|
||||||
function removeEmptyProps(props: any, node: Node) {
|
|
||||||
if (node.isRoot() && props.dataSource) {
|
|
||||||
const online = cloneDeep(props.dataSource.online);
|
|
||||||
online.forEach((item: any) => {
|
|
||||||
const newParam: any = {};
|
|
||||||
if (Array.isArray(item?.options?.params)) {
|
|
||||||
item.options.params.forEach((element: any) => {
|
|
||||||
if (element.name) {
|
|
||||||
newParam[element.name] = element.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
item.options.params = newParam;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
props.dataSource.list = online;
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init 的时候没有拿到 dataSource, 只能在 Render 和 Save 的时候都调用一次,理论上执行时机在 Init
|
// Init 的时候没有拿到 dataSource, 只能在 Render 和 Save 的时候都调用一次,理论上执行时机在 Init
|
||||||
// Render 和 Save 都要各调用一次,感觉也是有问题的,是不是应该在 Render 执行一次就行了?见上 filterReducer 也是一样的处理方式。
|
// Render 和 Save 都要各调用一次,感觉也是有问题的,是不是应该在 Render 执行一次就行了?见上 filterReducer 也是一样的处理方式。
|
||||||
designer.addPropsReducer(removeEmptyProps, TransformStage.Render);
|
designer.addPropsReducer(removeEmptyPropsReducer, TransformStage.Render);
|
||||||
designer.addPropsReducer(removeEmptyProps, TransformStage.Save);
|
designer.addPropsReducer(removeEmptyPropsReducer, TransformStage.Save);
|
||||||
|
|
||||||
skeleton.add({
|
skeleton.add({
|
||||||
area: 'mainArea',
|
area: 'mainArea',
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import logger from '@ali/vu-logger';
|
|||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import I18nUtil from './i18n-util';
|
import I18nUtil from './i18n-util';
|
||||||
import { hotkey as Hotkey, monitor } from '@ali/lowcode-editor-core';
|
import { hotkey as Hotkey, monitor } from '@ali/lowcode-editor-core';
|
||||||
|
import { registerMetadataTransducer } from '@ali/lowcode-designer';
|
||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const';
|
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS, VERSION as Version } from './base/const';
|
||||||
import Bus from './bus';
|
import Bus from './bus';
|
||||||
@ -110,6 +111,7 @@ const VisualEngine = {
|
|||||||
Project,
|
Project,
|
||||||
logger,
|
logger,
|
||||||
Symbols,
|
Symbols,
|
||||||
|
registerMetadataTransducer,
|
||||||
// Flags,
|
// Flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -160,12 +162,13 @@ export {
|
|||||||
Project,
|
Project,
|
||||||
logger,
|
logger,
|
||||||
Symbols,
|
Symbols,
|
||||||
|
registerMetadataTransducer,
|
||||||
};
|
};
|
||||||
|
|
||||||
const version = '6.0.0(LowcodeEngine 0.9.3)';
|
const version = '6.0.0 (LowcodeEngine 0.9.32)';
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`%c VisionEngine %c v${version} `,
|
`%c VisionEngine %c v${version} `,
|
||||||
'padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060;font-weight:bold;',
|
'padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold;',
|
||||||
'padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e;font-weight:bold;',
|
'padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e; font-weight: bold;',
|
||||||
);
|
);
|
||||||
|
|||||||
@ -64,7 +64,6 @@ const pages = Object.assign(project, {
|
|||||||
item.methods = {};
|
item.methods = {};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(pages, componentsTree);
|
|
||||||
project.load(
|
project.load(
|
||||||
{
|
{
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
import { getConvertedExtraKey } from '@ali/lowcode-designer';
|
||||||
|
import {
|
||||||
|
isPlainObject,
|
||||||
|
} from '@ali/lowcode-utils';
|
||||||
|
import { isJSExpression, isJSSlot } from '@ali/lowcode-types';
|
||||||
|
|
||||||
|
export function compatibleReducer(props: any) {
|
||||||
|
if (!props || !isPlainObject(props)) {
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
// 为了能降级到老版本,建议在后期版本去掉以下代码
|
||||||
|
if (isJSSlot(props)) {
|
||||||
|
return {
|
||||||
|
type: 'JSBlock',
|
||||||
|
value: {
|
||||||
|
componentName: 'Slot',
|
||||||
|
children: props.value,
|
||||||
|
props: {
|
||||||
|
slotTitle: props.title,
|
||||||
|
slotName: props.name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (isJSExpression(props) && !props.events) {
|
||||||
|
return {
|
||||||
|
type: 'variable',
|
||||||
|
value: props.mock,
|
||||||
|
variable: props.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const newProps: any = {};
|
||||||
|
Object.entries<any>(props).forEach(([key, val]) => {
|
||||||
|
newProps[key] = compatibleReducer(val);
|
||||||
|
});
|
||||||
|
return newProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compatiblePageReducer(props: any, node: Node) {
|
||||||
|
const lifeCycleNames = ['didMount', 'willUnmount'];
|
||||||
|
if (node.isRoot()) {
|
||||||
|
lifeCycleNames.forEach(key => {
|
||||||
|
if (props[key]) {
|
||||||
|
const lifeCycles = node.props.getPropValue(getConvertedExtraKey('lifeCycles')) || {};
|
||||||
|
lifeCycles[key] = props[key];
|
||||||
|
node.props.setPropValue(getConvertedExtraKey('lifeCycles'), lifeCycles);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import logger from '@ali/vu-logger';
|
||||||
|
import { hasOwnProperty } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function filterReducer(props: any, node: Node): any {
|
||||||
|
const filters = node.componentMeta.getMetadata().experimental?.filters;
|
||||||
|
if (filters && filters.length) {
|
||||||
|
const newProps = { ...props };
|
||||||
|
filters.forEach((item) => {
|
||||||
|
// FIXME! item.name could be 'xxx.xxx'
|
||||||
|
if (!hasOwnProperty(newProps, item.name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (item.filter(node.settingEntry.getProp(item.name), props[item.name]) === false) {
|
||||||
|
delete newProps[item.name];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e);
|
||||||
|
logger.trace(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return newProps;
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
export * from './downgrade-schema-reducer';
|
||||||
|
export * from './filter-reducer';
|
||||||
|
export * from './init-node-reducer';
|
||||||
|
export * from './live-lifecycle-reducer';
|
||||||
|
export * from './remove-empty-prop-reducer';
|
||||||
|
export * from './style-reducer';
|
||||||
|
export * from './upgrade-reducer';
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import {
|
||||||
|
hasOwnProperty,
|
||||||
|
isI18NObject,
|
||||||
|
isUseI18NSetter,
|
||||||
|
convertToI18NObject,
|
||||||
|
isString,
|
||||||
|
} from '@ali/lowcode-utils';
|
||||||
|
import { isJSExpression, isJSBlock, isJSSlot } from '@ali/lowcode-types';
|
||||||
|
import { isVariable, getCurrentFieldIds } from '../utils';
|
||||||
|
|
||||||
|
export function initNodeReducer(props, node) {
|
||||||
|
// run initials
|
||||||
|
const newProps: any = {
|
||||||
|
...props,
|
||||||
|
};
|
||||||
|
if (newProps.fieldId) {
|
||||||
|
const fieldIds = getCurrentFieldIds();
|
||||||
|
|
||||||
|
// 全局的关闭 uniqueIdChecker 信号,在 ve-utils 中实现
|
||||||
|
if (fieldIds.indexOf(props.fieldId) >= 0 && !(window as any).__disable_unique_id_checker__) {
|
||||||
|
newProps.fieldId = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const initials = node.componentMeta.getMetadata().experimental?.initials;
|
||||||
|
|
||||||
|
if (initials) {
|
||||||
|
const getRealValue = (propValue: any) => {
|
||||||
|
if (isVariable(propValue)) {
|
||||||
|
return propValue.value;
|
||||||
|
}
|
||||||
|
if (isJSExpression(propValue)) {
|
||||||
|
return propValue.mock;
|
||||||
|
}
|
||||||
|
return propValue;
|
||||||
|
};
|
||||||
|
initials.forEach(item => {
|
||||||
|
// FIXME! this implements SettingTarget
|
||||||
|
try {
|
||||||
|
// FIXME! item.name could be 'xxx.xxx'
|
||||||
|
const ov = newProps[item.name];
|
||||||
|
const v = item.initial(node as any, getRealValue(ov));
|
||||||
|
if (ov === undefined && v !== undefined) {
|
||||||
|
newProps[item.name] = v;
|
||||||
|
}
|
||||||
|
// 兼容 props 中的属性为 i18n 类型,但是仅提供了一个字符串值,非变量绑定
|
||||||
|
if (
|
||||||
|
isUseI18NSetter(node.componentMeta.prototype, item.name) &&
|
||||||
|
!isI18NObject(ov) &&
|
||||||
|
!isJSExpression(ov) &&
|
||||||
|
!isJSBlock(ov) &&
|
||||||
|
!isJSSlot(ov) &&
|
||||||
|
!isVariable(ov) &&
|
||||||
|
(isString(v) || isI18NObject(v))
|
||||||
|
) {
|
||||||
|
newProps[item.name] = convertToI18NObject(v);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (hasOwnProperty(props, item.name)) {
|
||||||
|
newProps[item.name] = props[item.name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newProps[item.name] && !node.props.has(item.name)) {
|
||||||
|
node.props.add(newProps[item.name], item.name, false, { skipSetSlot: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return newProps;
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
|
import { Node } from '@ali/lowcode-designer';
|
||||||
|
|
||||||
|
export function liveLifecycleReducer(props: any, node: Node) {
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
// live 模式下解析 lifeCycles
|
||||||
|
if (node.isRoot() && props && props.lifeCycles) {
|
||||||
|
if (editor.get('designMode') === 'live') {
|
||||||
|
const lifeCycleMap = {
|
||||||
|
didMount: 'componentDidMount',
|
||||||
|
willUnmount: 'componentWillUnMount',
|
||||||
|
};
|
||||||
|
const lifeCycles = props.lifeCycles;
|
||||||
|
Object.keys(lifeCycleMap).forEach(key => {
|
||||||
|
if (lifeCycles[key]) {
|
||||||
|
lifeCycles[lifeCycleMap[key]] = lifeCycles[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...props,
|
||||||
|
lifeCycles: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
cloneDeep,
|
||||||
|
} from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
// 清除空的 props value
|
||||||
|
export function removeEmptyPropsReducer(props: any, node: Node) {
|
||||||
|
if (node.isRoot() && props.dataSource && Array.isArray(props.dataSource.online)) {
|
||||||
|
const online = cloneDeep(props.dataSource.online);
|
||||||
|
online.forEach((item: any) => {
|
||||||
|
const newParam: any = {};
|
||||||
|
if (Array.isArray(item?.options?.params)) {
|
||||||
|
item.options.params.forEach((element: any) => {
|
||||||
|
if (element.name) {
|
||||||
|
newParam[element.name] = element.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
item.options.params = newParam;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
props.dataSource.list = online;
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
|
import { toCss } from '@ali/vu-css-style';
|
||||||
|
|
||||||
|
export function stylePropsReducer(props: any, node: any) {
|
||||||
|
if (props && typeof props === 'object' && props.__style__) {
|
||||||
|
const cssId = `_style_pesudo_${ node.id.replace(/\$/g, '_')}`;
|
||||||
|
const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
|
||||||
|
const styleProp = props.__style__;
|
||||||
|
appendStyleNode(props, styleProp, cssClass, cssId);
|
||||||
|
}
|
||||||
|
if (props && typeof props === 'object' && props.pageStyle) {
|
||||||
|
const cssId = '_style_pesudo_engine-document';
|
||||||
|
const cssClass = 'engine-document';
|
||||||
|
const styleProp = props.pageStyle;
|
||||||
|
appendStyleNode(props, styleProp, cssClass, cssId);
|
||||||
|
}
|
||||||
|
if (props && typeof props === 'object' && props.containerStyle) {
|
||||||
|
const cssId = `_style_pesudo_${ node.id}`;
|
||||||
|
const cssClass = `_css_pesudo_${ node.id.replace(/\$/g, '_')}`;
|
||||||
|
const styleProp = props.containerStyle;
|
||||||
|
appendStyleNode(props, styleProp, cssClass, cssId);
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendStyleNode(props: any, styleProp: any, cssClass: string, cssId: string) {
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
const designer = editor.get('designer');
|
||||||
|
const doc = designer.currentDocument?.simulator?.contentDocument;
|
||||||
|
if (!doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dom = doc.getElementById(cssId);
|
||||||
|
if (dom) {
|
||||||
|
dom.parentNode?.removeChild(dom);
|
||||||
|
}
|
||||||
|
if (typeof styleProp === 'object') {
|
||||||
|
styleProp = toCss(styleProp);
|
||||||
|
}
|
||||||
|
if (typeof styleProp === 'string') {
|
||||||
|
const s = doc.createElement('style');
|
||||||
|
props.className = cssClass;
|
||||||
|
s.setAttribute('type', 'text/css');
|
||||||
|
s.setAttribute('id', cssId);
|
||||||
|
doc.getElementsByTagName('head')[0].appendChild(s);
|
||||||
|
|
||||||
|
s.appendChild(doc.createTextNode(styleProp.replace(/(\d+)rpx/g, (a, b) => {
|
||||||
|
return `${b / 2}px`;
|
||||||
|
}).replace(/:root/g, `.${ cssClass}`)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
isPlainObject,
|
||||||
|
} from '@ali/lowcode-utils';
|
||||||
|
import { isJSBlock } from '@ali/lowcode-types';
|
||||||
|
import { isVariable } from '../utils';
|
||||||
|
|
||||||
|
export function upgradePropsReducer(props: any) {
|
||||||
|
if (!props || !isPlainObject(props)) {
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
if (isJSBlock(props)) {
|
||||||
|
if (props.value.componentName === 'Slot') {
|
||||||
|
return {
|
||||||
|
type: 'JSSlot',
|
||||||
|
title: (props.value.props as any)?.slotTitle,
|
||||||
|
name: (props.value.props as any)?.slotName,
|
||||||
|
value: props.value.children,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return props.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isVariable(props)) {
|
||||||
|
return {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: props.variable,
|
||||||
|
mock: props.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const newProps: any = {};
|
||||||
|
Object.keys(props).forEach((key) => {
|
||||||
|
if (/^__slot__/.test(key) && props[key] === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newProps[key] = upgradePropsReducer(props[key]);
|
||||||
|
});
|
||||||
|
return newProps;
|
||||||
|
}
|
||||||
@ -1,3 +1,25 @@
|
|||||||
export function isVariable(obj: any) {
|
import { globalContext, Editor } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
|
interface Variable {
|
||||||
|
type: 'variable';
|
||||||
|
variable: string;
|
||||||
|
value: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isVariable(obj: any): obj is Variable {
|
||||||
return obj && obj.type === 'variable';
|
return obj && obj.type === 'variable';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCurrentFieldIds() {
|
||||||
|
const editor = globalContext.get(Editor);
|
||||||
|
const designer = editor.get('designer');
|
||||||
|
const fieldIds: any = [];
|
||||||
|
const nodesMap = designer?.currentDocument?.nodesMap || new Map();
|
||||||
|
nodesMap.forEach((curNode: any) => {
|
||||||
|
const fieldId = nodesMap?.get(curNode.id)?.getPropValue('fieldId');
|
||||||
|
if (fieldId) {
|
||||||
|
fieldIds.push(fieldId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fieldIds;
|
||||||
|
}
|
||||||
|
|||||||
116
packages/editor-preset-vision/tests/bundle/bundle.test.ts
Normal file
116
packages/editor-preset-vision/tests/bundle/bundle.test.ts
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { Component } from 'react';
|
||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import divPrototypeConfig from '../fixtures/prototype/div-vision';
|
||||||
|
import trunk from '../../src/bundle/trunk';
|
||||||
|
import Prototype from '../../src/bundle/prototype';
|
||||||
|
import Bundle from '../../src/bundle/bundle';
|
||||||
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
|
jest.mock('../../src/bundle/trunk', () => {
|
||||||
|
// mockComponentPrototype = jest.fn();
|
||||||
|
// return {
|
||||||
|
// mockComponentPrototype: jest.fn().mockImplementation(() => {
|
||||||
|
// return proto;
|
||||||
|
// }),
|
||||||
|
// }
|
||||||
|
// return jest.fn().mockImplementation(() => {
|
||||||
|
// return {playSoundFile: fakePlaySoundFile};
|
||||||
|
// });
|
||||||
|
// return jest.fn().mockImplementation(() => {
|
||||||
|
// return { mockComponentPrototype };
|
||||||
|
// });
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: {
|
||||||
|
mockComponentPrototype: jest.fn(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function wrap(name, thing) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
componentName: name,
|
||||||
|
category: '布局',
|
||||||
|
module: thing,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const proto1 = new Prototype(divPrototypeConfig);
|
||||||
|
const protoConfig2 = cloneDeep(divPrototypeConfig);
|
||||||
|
set(protoConfig2, 'componentName', 'Div2');
|
||||||
|
const proto2 = new Prototype(protoConfig2);
|
||||||
|
|
||||||
|
const protoConfig3 = cloneDeep(divPrototypeConfig);
|
||||||
|
set(protoConfig3, 'componentName', 'Div3');
|
||||||
|
const proto3 = new Prototype(protoConfig3);
|
||||||
|
|
||||||
|
const protoConfig4 = cloneDeep(divPrototypeConfig);
|
||||||
|
set(protoConfig4, 'componentName', 'Div4');
|
||||||
|
const proto4 = new Prototype(protoConfig4);
|
||||||
|
|
||||||
|
const protoConfig5 = cloneDeep(divPrototypeConfig);
|
||||||
|
set(protoConfig5, 'componentName', 'Div5');
|
||||||
|
const proto5 = new Prototype(protoConfig5);
|
||||||
|
|
||||||
|
function getComponentProtos() {
|
||||||
|
return [
|
||||||
|
wrap('Div', proto1),
|
||||||
|
// wrap('Div2', proto2),
|
||||||
|
// wrap('Div3', proto3),
|
||||||
|
wrap('DivPortal', [proto2, proto3]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Div extends Component {}
|
||||||
|
Div.displayName = 'Div';
|
||||||
|
class Div2 extends Component {}
|
||||||
|
Div2.displayName = 'Div2';
|
||||||
|
class Div3 extends Component {}
|
||||||
|
Div3.displayName = 'Div3';
|
||||||
|
class Div4 extends Component {}
|
||||||
|
Div4.displayName = 'Div4';
|
||||||
|
class Div5 extends Component {}
|
||||||
|
Div5.displayName = 'Div5';
|
||||||
|
|
||||||
|
function getComponentViews() {
|
||||||
|
return [
|
||||||
|
wrap('Div', Div),
|
||||||
|
// wrap('Div2', Div2),
|
||||||
|
// wrap('Div3', Div3),
|
||||||
|
wrap('DivPortal', [Div2, Div3]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Bundle', () => {
|
||||||
|
it('构造函数', () => {
|
||||||
|
const protos = getComponentProtos();
|
||||||
|
const views = getComponentViews();
|
||||||
|
const bundle = new Bundle(protos, views);
|
||||||
|
expect(bundle.getList()).toHaveLength(3);
|
||||||
|
expect(bundle.get('Div')).toBe(proto1);
|
||||||
|
expect(bundle.get('Div2')).toBe(proto2);
|
||||||
|
expect(bundle.get('Div3')).toBe(proto3);
|
||||||
|
bundle.addComponentBundle([proto4, Div4]);
|
||||||
|
expect(bundle.getList()).toHaveLength(4);
|
||||||
|
expect(bundle.get('Div4')).toBe(proto4);
|
||||||
|
bundle.replacePrototype('Div4', proto3);
|
||||||
|
expect(proto3.getView()).toBe(Div4);
|
||||||
|
|
||||||
|
bundle.removeComponentBundle('Div2');
|
||||||
|
expect(bundle.getList()).toHaveLength(3);
|
||||||
|
expect(bundle.get('Div2')).toBeUndefined;
|
||||||
|
|
||||||
|
expect(bundle.getFromMeta('Div')).toBe(proto1);
|
||||||
|
bundle.getFromMeta('Div5');
|
||||||
|
expect(bundle.getList()).toHaveLength(4);
|
||||||
|
});
|
||||||
|
it('静态方法 create', () => {
|
||||||
|
const protos = getComponentProtos();
|
||||||
|
const views = getComponentViews();
|
||||||
|
const bundle = Bundle.create(protos, views);
|
||||||
|
expect(bundle).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
219
packages/editor-preset-vision/tests/bundle/prototype.test.ts
Normal file
219
packages/editor-preset-vision/tests/bundle/prototype.test.ts
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
import { Component } from 'react';
|
||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
// import { Project } from '../../src/project/project';
|
||||||
|
// import { Node } from '../../src/document/node/node';
|
||||||
|
// import { Designer } from '../../src/designer/designer';
|
||||||
|
import divPrototypeConfig from '../fixtures/prototype/div-vision';
|
||||||
|
import divFullPrototypeConfig from '../fixtures/prototype/div-vision-full';
|
||||||
|
import divPrototypeMeta from '../fixtures/prototype/div-meta';
|
||||||
|
// import VisualEngine from '../../src';
|
||||||
|
import { designer } from '../../src/editor';
|
||||||
|
import Prototype, { isPrototype } from '../../src/bundle/prototype';
|
||||||
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
|
// import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
|
||||||
|
describe('Prototype', () => {
|
||||||
|
it('构造函数 - OldPrototypeConfig', () => {
|
||||||
|
const proto = new Prototype(divPrototypeConfig);
|
||||||
|
expect(isPrototype(proto)).toBeTruthy;
|
||||||
|
expect(proto.getComponentName()).toBe('Div');
|
||||||
|
expect(proto.getId()).toBe('Div');
|
||||||
|
expect(proto.getCategory()).toBe('布局');
|
||||||
|
expect(proto.getDocUrl()).toBe(
|
||||||
|
'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
);
|
||||||
|
expect(proto.getIcon()).toBeUndefined;
|
||||||
|
expect(proto.getTitle()).toBe('Div');
|
||||||
|
expect(proto.isPrototype).toBeTruthy;
|
||||||
|
expect(proto.isContainer()).toBeTruthy;
|
||||||
|
expect(proto.isModal()).toBeFalsy;
|
||||||
|
});
|
||||||
|
it('构造函数 - 全量 OldPrototypeConfig', () => {
|
||||||
|
const proto = new Prototype(divFullPrototypeConfig);
|
||||||
|
expect(isPrototype(proto)).toBeTruthy;
|
||||||
|
expect(proto.getComponentName()).toBe('Div');
|
||||||
|
expect(proto.getId()).toBe('Div');
|
||||||
|
expect(proto.getCategory()).toBe('布局');
|
||||||
|
expect(proto.getDocUrl()).toBe(
|
||||||
|
'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
);
|
||||||
|
expect(proto.getIcon()).toBeUndefined;
|
||||||
|
expect(proto.getTitle()).toBe('Div');
|
||||||
|
expect(proto.isPrototype).toBeTruthy;
|
||||||
|
expect(proto.isContainer()).toBeTruthy;
|
||||||
|
expect(proto.isModal()).toBeFalsy;
|
||||||
|
});
|
||||||
|
it('构造函数 - ComponentMetadata', () => {
|
||||||
|
const proto = new Prototype(divPrototypeMeta);
|
||||||
|
expect(proto.getComponentName()).toBe('Div');
|
||||||
|
expect(proto.getId()).toBe('Div');
|
||||||
|
expect(proto.getCategory()).toBe('布局');
|
||||||
|
expect(proto.getDocUrl()).toBe(
|
||||||
|
'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
);
|
||||||
|
expect(proto.getIcon()).toBeUndefined;
|
||||||
|
expect(proto.getTitle()).toBe('Div');
|
||||||
|
expect(proto.isPrototype).toBeTruthy;
|
||||||
|
expect(proto.isContainer()).toBeTruthy;
|
||||||
|
expect(proto.isModal()).toBeFalsy;
|
||||||
|
});
|
||||||
|
it('构造函数 - ComponentMeta', () => {
|
||||||
|
const meta = designer.createComponentMeta(divPrototypeMeta);
|
||||||
|
const proto = new Prototype(meta);
|
||||||
|
expect(proto.getComponentName()).toBe('Div');
|
||||||
|
expect(proto.getId()).toBe('Div');
|
||||||
|
expect(proto.getCategory()).toBe('布局');
|
||||||
|
expect(proto.getDocUrl()).toBe(
|
||||||
|
'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
);
|
||||||
|
expect(proto.getIcon()).toBeUndefined;
|
||||||
|
expect(proto.getTitle()).toBe('Div');
|
||||||
|
expect(proto.isPrototype).toBeTruthy;
|
||||||
|
expect(proto.isContainer()).toBeTruthy;
|
||||||
|
expect(proto.isModal()).toBeFalsy;
|
||||||
|
});
|
||||||
|
it('构造函数 - 静态函数 create', () => {
|
||||||
|
const proto = Prototype.create(divPrototypeConfig);
|
||||||
|
expect(proto.getComponentName()).toBe('Div');
|
||||||
|
expect(proto.getId()).toBe('Div');
|
||||||
|
expect(proto.getCategory()).toBe('布局');
|
||||||
|
expect(proto.getDocUrl()).toBe(
|
||||||
|
'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
);
|
||||||
|
expect(proto.getIcon()).toBeUndefined;
|
||||||
|
expect(proto.getTitle()).toBe('Div');
|
||||||
|
expect(proto.isPrototype).toBeTruthy;
|
||||||
|
expect(proto.isContainer()).toBeTruthy;
|
||||||
|
expect(proto.isModal()).toBeFalsy;
|
||||||
|
});
|
||||||
|
it('构造函数 - lookup: true', () => {
|
||||||
|
const proto = Prototype.create(divPrototypeConfig);
|
||||||
|
const proto2 = Prototype.create(divPrototypeConfig, {}, true);
|
||||||
|
expect(proto).toBe(proto2);
|
||||||
|
});
|
||||||
|
describe('类成员函数', () => {
|
||||||
|
let proto: Prototype = null;
|
||||||
|
beforeEach(() => {
|
||||||
|
proto = new Prototype(divPrototypeConfig);
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
proto = null;
|
||||||
|
});
|
||||||
|
it('各种函数', () => {
|
||||||
|
expect(proto.componentName).toBe('Div');
|
||||||
|
expect(proto.getComponentName()).toBe('Div');
|
||||||
|
expect(proto.getId()).toBe('Div');
|
||||||
|
expect(proto.getContextInfo('anything')).toBeUndefined;
|
||||||
|
expect(proto.getPropConfigs()).toBe(divPrototypeConfig);
|
||||||
|
expect(proto.getConfig()).toBe(divPrototypeConfig);
|
||||||
|
expect(proto.getConfig('componentName')).toBe('Div');
|
||||||
|
expect(proto.getConfig('configure')).toBe(divPrototypeConfig.configure);
|
||||||
|
expect(proto.getConfig('docUrl')).toBe(
|
||||||
|
'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
);
|
||||||
|
expect(proto.getConfig('title')).toBe('容器');
|
||||||
|
expect(proto.getConfig('isContainer')).toBeTruthy;
|
||||||
|
|
||||||
|
class MockView extends Component {}
|
||||||
|
|
||||||
|
expect(proto.getView()).toBeUndefined;
|
||||||
|
proto.setView(MockView);
|
||||||
|
expect(proto.getView()).toBe(MockView);
|
||||||
|
expect(proto.meta.getMetadata().experimental?.view).toBe(MockView);
|
||||||
|
|
||||||
|
expect(proto.getPackageName()).toBeUndefined;
|
||||||
|
proto.setPackageName('@ali/vc-div');
|
||||||
|
expect(proto.getPackageName()).toBe('@ali/vc-div');
|
||||||
|
|
||||||
|
expect(proto.getConfig('category')).toBe('布局');
|
||||||
|
proto.setCategory('布局 new');
|
||||||
|
expect(proto.getConfig('category')).toBe('布局 new');
|
||||||
|
|
||||||
|
expect(proto.getConfigure()).toHaveLength(3);
|
||||||
|
expect(proto.getConfigure()[0].name).toBe('#props');
|
||||||
|
expect(proto.getConfigure()[1].name).toBe('#styles');
|
||||||
|
expect(proto.getConfigure()[2].name).toBe('#advanced');
|
||||||
|
|
||||||
|
expect(proto.getRectSelector()).toBeUndefined;
|
||||||
|
expect(proto.isAutoGenerated()).toBeFalsy;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('类成员函数', () => {
|
||||||
|
it('addGlobalPropsConfigure', () => {
|
||||||
|
Prototype.addGlobalPropsConfigure({
|
||||||
|
name: 'globalInsertProp1',
|
||||||
|
});
|
||||||
|
const proto1 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto1.getConfigure()[2].items).toHaveLength(4);
|
||||||
|
expect(proto1.getConfigure()[2].items[3].name).toBe('globalInsertProp1');
|
||||||
|
Prototype.addGlobalPropsConfigure({
|
||||||
|
name: 'globalInsertProp2',
|
||||||
|
});
|
||||||
|
const proto2 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto2.getConfigure()[2].items).toHaveLength(5);
|
||||||
|
expect(proto1.getConfigure()[2].items[4].name).toBe('globalInsertProp2');
|
||||||
|
|
||||||
|
Prototype.addGlobalPropsConfigure({
|
||||||
|
name: 'globalInsertProp3',
|
||||||
|
position: 'top',
|
||||||
|
});
|
||||||
|
|
||||||
|
const proto3 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto3.getConfigure()[0].items).toHaveLength(3);
|
||||||
|
expect(proto1.getConfigure()[0].items[0].name).toBe('globalInsertProp3');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removeGlobalPropsConfigure', () => {
|
||||||
|
Prototype.removeGlobalPropsConfigure('globalInsertProp1');
|
||||||
|
Prototype.removeGlobalPropsConfigure('globalInsertProp2');
|
||||||
|
Prototype.removeGlobalPropsConfigure('globalInsertProp3');
|
||||||
|
const proto2 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto2.getConfigure()[0].items).toHaveLength(2);
|
||||||
|
expect(proto2.getConfigure()[2].items).toHaveLength(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('overridePropsConfigure', () => {
|
||||||
|
Prototype.addGlobalPropsConfigure({
|
||||||
|
name: 'globalInsertProp1',
|
||||||
|
title: 'globalInsertPropTitle',
|
||||||
|
position: 'top',
|
||||||
|
});
|
||||||
|
const proto1 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto1.getConfigure()[0].items).toHaveLength(3);
|
||||||
|
expect(proto1.getConfigure()[0].items[0].name).toBe('globalInsertProp1');
|
||||||
|
expect(proto1.getConfigure()[0].items[0].title).toBe('globalInsertPropTitle');
|
||||||
|
|
||||||
|
Prototype.overridePropsConfigure('Div', [
|
||||||
|
{
|
||||||
|
name: 'globalInsertProp1',
|
||||||
|
title: 'globalInsertPropTitleChanged',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const proto2 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto2.getConfigure()[0].name).toBe('globalInsertProp1');
|
||||||
|
expect(proto2.getConfigure()[0].title).toBe('globalInsertPropTitleChanged');
|
||||||
|
|
||||||
|
Prototype.overridePropsConfigure('Div', {
|
||||||
|
globalInsertProp1: {
|
||||||
|
name: 'globalInsertProp1',
|
||||||
|
title: 'globalInsertPropTitleChanged new',
|
||||||
|
position: 'top',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const proto3 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto3.getConfigure()[0].items[0].name).toBe('globalInsertProp1');
|
||||||
|
expect(proto3.getConfigure()[0].items[0].title).toBe('globalInsertPropTitleChanged new');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('addGlobalExtraActions', () => {
|
||||||
|
function haha() { return 'heihei'; }
|
||||||
|
Prototype.addGlobalExtraActions(haha);
|
||||||
|
const proto1 = new Prototype(divPrototypeConfig);
|
||||||
|
expect(proto1.meta.availableActions).toHaveLength(4);
|
||||||
|
expect(proto1.meta.availableActions[3].name).toBe('haha');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
111
packages/editor-preset-vision/tests/bundle/trunk.test.ts
Normal file
111
packages/editor-preset-vision/tests/bundle/trunk.test.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import { Component } from 'react';
|
||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import divPrototypeConfig from '../fixtures/prototype/div-vision';
|
||||||
|
import Prototype from '../../src/bundle/prototype';
|
||||||
|
import Bundle from '../../src/bundle/bundle';
|
||||||
|
import trunk from '../../src/bundle/trunk';
|
||||||
|
import lg from '@ali/vu-logger';
|
||||||
|
|
||||||
|
const proto1 = new Prototype(divPrototypeConfig);
|
||||||
|
const protoConfig2 = cloneDeep(divPrototypeConfig);
|
||||||
|
set(protoConfig2, 'componentName', 'Div2');
|
||||||
|
const proto2 = new Prototype(protoConfig2);
|
||||||
|
|
||||||
|
const protoConfig3 = cloneDeep(divPrototypeConfig);
|
||||||
|
set(protoConfig3, 'componentName', 'Div3');
|
||||||
|
const proto3 = new Prototype(protoConfig3);
|
||||||
|
|
||||||
|
const mockComponentPrototype = jest.fn();
|
||||||
|
jest.mock('../../src/bundle/bundle', () => {
|
||||||
|
// return {
|
||||||
|
// mockComponentPrototype: jest.fn().mockImplementation(() => {
|
||||||
|
// return proto;
|
||||||
|
// }),
|
||||||
|
// }
|
||||||
|
// return jest.fn().mockImplementation(() => {
|
||||||
|
// return {playSoundFile: fakePlaySoundFile};
|
||||||
|
// });
|
||||||
|
return jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
get: () => {},
|
||||||
|
getList: () => { return []; },
|
||||||
|
getFromMeta: () => {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const mockError = jest.fn();
|
||||||
|
jest.mock('@ali/vu-logger');
|
||||||
|
lg.error = mockError;
|
||||||
|
|
||||||
|
function wrap(name, thing) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
componentName: name,
|
||||||
|
category: '布局',
|
||||||
|
module: thing,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getComponentProtos() {
|
||||||
|
return [
|
||||||
|
wrap('Div', proto1),
|
||||||
|
// wrap('Div2', proto2),
|
||||||
|
// wrap('Div3', proto3),
|
||||||
|
wrap('DivPortal', [proto2, proto3]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Div extends Component {}
|
||||||
|
Div.displayName = 'Div';
|
||||||
|
class Div2 extends Component {}
|
||||||
|
Div2.displayName = 'Div2';
|
||||||
|
class Div3 extends Component {}
|
||||||
|
Div3.displayName = 'Div3';
|
||||||
|
|
||||||
|
function getComponentViews() {
|
||||||
|
return [
|
||||||
|
wrap('Div', Div),
|
||||||
|
// wrap('Div2', Div2),
|
||||||
|
// wrap('Div3', Div3),
|
||||||
|
wrap('DivPortal', [Div2, Div3]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Trunk', () => {
|
||||||
|
it('构造函数', () => {
|
||||||
|
const warn = console.warn = jest.fn();
|
||||||
|
const trunkChangeHandler = jest.fn();
|
||||||
|
const off = trunk.onTrunkChange(trunkChangeHandler);
|
||||||
|
trunk.addBundle(new Bundle([proto1], [Div]));
|
||||||
|
trunk.addBundle(new Bundle([proto2], [Div2]));
|
||||||
|
expect(trunkChangeHandler).toHaveBeenCalledTimes(2);
|
||||||
|
off();
|
||||||
|
trunk.addBundle(new Bundle([proto3], [Div3]));
|
||||||
|
expect(trunkChangeHandler).toHaveBeenCalledTimes(2);
|
||||||
|
trunk.getList();
|
||||||
|
trunk.getPrototype('Div');
|
||||||
|
trunk.getPrototypeById('Div');
|
||||||
|
trunk.getPrototypeView('Div');
|
||||||
|
trunk.listByCategory();
|
||||||
|
expect(trunk.mockComponentPrototype(new Bundle([proto3], [Div3]))).toBeUndefined;
|
||||||
|
expect(mockError).toHaveBeenCalled();
|
||||||
|
trunk.registerComponentPrototypeMocker({ mockPrototype: jest.fn().mockImplementation(() => { return proto3; }) });
|
||||||
|
expect(trunk.mockComponentPrototype(new Bundle([proto3], [Div3]))).toBe(proto3);
|
||||||
|
const hahaSetter = () => 'haha';
|
||||||
|
trunk.registerSetter('haha', hahaSetter);
|
||||||
|
expect(trunk.getSetter('haha')).toBe(hahaSetter);
|
||||||
|
trunk.getRecents(5);
|
||||||
|
trunk.setPackages();
|
||||||
|
expect(warn).toHaveBeenCalledTimes(1);
|
||||||
|
trunk.beforeLoadBundle();
|
||||||
|
expect(warn).toHaveBeenCalledTimes(2);
|
||||||
|
trunk.afterLoadBundle();
|
||||||
|
expect(warn).toHaveBeenCalledTimes(3);
|
||||||
|
trunk.getBundle();
|
||||||
|
expect(warn).toHaveBeenCalledTimes(4);
|
||||||
|
expect(trunk.isReady()).toBeTruthy;
|
||||||
|
});
|
||||||
|
});
|
||||||
259
packages/editor-preset-vision/tests/fixtures/prototype/div-meta.ts
vendored
Normal file
259
packages/editor-preset-vision/tests/fixtures/prototype/div-meta.ts
vendored
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
export default {
|
||||||
|
componentName: 'Div',
|
||||||
|
title: '容器',
|
||||||
|
docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
devMode: 'procode',
|
||||||
|
tags: ['布局'],
|
||||||
|
configure: {
|
||||||
|
props: [
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'behavior',
|
||||||
|
title: '默认状态',
|
||||||
|
extraProps: {
|
||||||
|
display: 'inline',
|
||||||
|
defaultValue: 'NORMAL',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixedSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
'VariableSetter',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: '__style__',
|
||||||
|
title: {
|
||||||
|
label: '样式设置',
|
||||||
|
tip: '点击 ? 查看样式设置器用法指南',
|
||||||
|
docUrl: 'https://lark.alipay.com/legao/help/design-tool-style',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
defaultValue: {},
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
advanced: true,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'group',
|
||||||
|
name: 'groupkh97h5kc',
|
||||||
|
title: '高级',
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'fieldId',
|
||||||
|
title: {
|
||||||
|
label: '唯一标识',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入唯一标识',
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
title: {
|
||||||
|
label: '将唯一标识用作 DOM ID',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'customClassName',
|
||||||
|
title: '自定义样式类',
|
||||||
|
extraProps: {
|
||||||
|
display: 'block',
|
||||||
|
defaultValue: '',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixedSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: null,
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
'VariableSetter',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'events',
|
||||||
|
title: {
|
||||||
|
label: '动作设置',
|
||||||
|
tip: '点击 ? 查看如何设置组件的事件响应动作',
|
||||||
|
docUrl: 'https://lark.alipay.com/legao/legao/events-call',
|
||||||
|
},
|
||||||
|
extraProps: {
|
||||||
|
display: 'accordion',
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
title: '当点击时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
title: '当鼠标进入时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
title: '当鼠标离开时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onClick',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'field',
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
extraProps: {
|
||||||
|
defaultValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setter: 'I18nSetter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {},
|
||||||
|
},
|
||||||
|
supports: {},
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
callbacks: {},
|
||||||
|
initials: [
|
||||||
|
{
|
||||||
|
name: 'behavior',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__style__',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'fieldId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customClassName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'events',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [],
|
||||||
|
autoruns: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
293
packages/editor-preset-vision/tests/fixtures/prototype/div-vision-full.ts
vendored
Normal file
293
packages/editor-preset-vision/tests/fixtures/prototype/div-vision-full.ts
vendored
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
export default {
|
||||||
|
title: '容器',
|
||||||
|
componentName: 'Div',
|
||||||
|
docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
category: '布局',
|
||||||
|
isContainer: true,
|
||||||
|
canOperating: false,
|
||||||
|
extraActions: [],
|
||||||
|
canContain: 'Form',
|
||||||
|
canDropTo: 'Div',
|
||||||
|
canDropIn: 'Div',
|
||||||
|
canResizing: true,
|
||||||
|
canDraging: false,
|
||||||
|
context: {},
|
||||||
|
initialChildren() {},
|
||||||
|
didDropIn() {},
|
||||||
|
didDropOut() {},
|
||||||
|
subtreeModified() {},
|
||||||
|
onResize() {},
|
||||||
|
onResizeStart() {},
|
||||||
|
onResizeEnd() {},
|
||||||
|
canUseCondition: true,
|
||||||
|
canLoop: true,
|
||||||
|
snippets: [
|
||||||
|
{
|
||||||
|
screenshot: 'https://img.alicdn.com/tfs/TB1CHN3u4z1gK0jSZSgXXavwpXa-112-64.png',
|
||||||
|
label: '普通型',
|
||||||
|
schema: {
|
||||||
|
componentName: 'Div',
|
||||||
|
props: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
configure: [
|
||||||
|
{
|
||||||
|
name: 'myName',
|
||||||
|
title: '我的名字',
|
||||||
|
display: 'tab',
|
||||||
|
initialValue: 'NORMAL',
|
||||||
|
defaultValue: 'NORMAL',
|
||||||
|
collapsed: true,
|
||||||
|
supportVariable: true,
|
||||||
|
accessor(field, val) {},
|
||||||
|
mutator(field, val) {},
|
||||||
|
disabled() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
useVariableChange() {},
|
||||||
|
allowTextInput: true,
|
||||||
|
liveTextEditing: true,
|
||||||
|
setter: [
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mySlotName',
|
||||||
|
slotName: 'mySlotName',
|
||||||
|
slotTitle: '我的 Slot 名字',
|
||||||
|
display: 'tab',
|
||||||
|
initialValue: 'NORMAL',
|
||||||
|
defaultValue: 'NORMAL',
|
||||||
|
collapsed: true,
|
||||||
|
supportVariable: true,
|
||||||
|
accessor(field, val) {},
|
||||||
|
mutator(field, val) {},
|
||||||
|
disabled() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'behavior',
|
||||||
|
title: '默认状态',
|
||||||
|
display: 'inline',
|
||||||
|
initialValue: 'NORMAL',
|
||||||
|
supportVariable: true,
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__style__',
|
||||||
|
title: '样式设置',
|
||||||
|
display: 'accordion',
|
||||||
|
collapsed: false,
|
||||||
|
initialValue: {},
|
||||||
|
tip: {
|
||||||
|
url: 'https://lark.alipay.com/legao/help/design-tool-style',
|
||||||
|
content: '点击 ? 查看样式设置器用法指南',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
advanced: true,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'group',
|
||||||
|
title: '高级',
|
||||||
|
display: 'accordion',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'fieldId',
|
||||||
|
title: '唯一标识',
|
||||||
|
display: 'block',
|
||||||
|
tip:
|
||||||
|
'组件的唯一标识符,不能够与其它组件重名,不能够为空,且只能够使用以字母开头的,下划线以及数字的组合。',
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入唯一标识',
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
title: '将唯一标识用作 DOM ID',
|
||||||
|
display: 'block',
|
||||||
|
tip:
|
||||||
|
'开启这个配置项后,会在当前组件的 HTML 元素上加入 id="当前组件的 fieldId",一般用于做 utils 的绑定,不常用',
|
||||||
|
initialValue: false,
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customClassName',
|
||||||
|
title: '自定义样式类',
|
||||||
|
display: 'block',
|
||||||
|
supportVariable: true,
|
||||||
|
initialValue: '',
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: null,
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'events',
|
||||||
|
title: '动作设置',
|
||||||
|
tip: {
|
||||||
|
url: 'https://lark.alipay.com/legao/legao/events-call',
|
||||||
|
content: '点击 ? 查看如何设置组件的事件响应动作',
|
||||||
|
},
|
||||||
|
display: 'accordion',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
title: '当点击时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
title: '当鼠标进入时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
title: '当鼠标离开时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
display: 'none',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
display: 'none',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
display: 'none',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
175
packages/editor-preset-vision/tests/fixtures/prototype/div-vision.ts
vendored
Normal file
175
packages/editor-preset-vision/tests/fixtures/prototype/div-vision.ts
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
export default {
|
||||||
|
title: '容器',
|
||||||
|
componentName: 'Div',
|
||||||
|
docUrl: 'http://gitlab.alibaba-inc.com/vision-components/vc-block/blob/master/README.md',
|
||||||
|
category: '布局',
|
||||||
|
isContainer: true,
|
||||||
|
configure: [
|
||||||
|
{
|
||||||
|
name: 'behavior',
|
||||||
|
title: '默认状态',
|
||||||
|
display: 'inline',
|
||||||
|
initialValue: 'NORMAL',
|
||||||
|
supportVariable: true,
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
title: '普通',
|
||||||
|
value: 'NORMAL',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '隐藏',
|
||||||
|
value: 'HIDDEN',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
loose: false,
|
||||||
|
cancelable: false,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__style__',
|
||||||
|
title: '样式设置',
|
||||||
|
display: 'accordion',
|
||||||
|
collapsed: false,
|
||||||
|
initialValue: {},
|
||||||
|
tip: {
|
||||||
|
url: 'https://lark.alipay.com/legao/help/design-tool-style',
|
||||||
|
content: '点击 ? 查看样式设置器用法指南',
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
advanced: true,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'group',
|
||||||
|
title: '高级',
|
||||||
|
display: 'accordion',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'fieldId',
|
||||||
|
title: '唯一标识',
|
||||||
|
display: 'block',
|
||||||
|
tip:
|
||||||
|
'组件的唯一标识符,不能够与其它组件重名,不能够为空,且只能够使用以字母开头的,下划线以及数字的组合。',
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入唯一标识',
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'useFieldIdAsDomId',
|
||||||
|
title: '将唯一标识用作 DOM ID',
|
||||||
|
display: 'block',
|
||||||
|
tip:
|
||||||
|
'开启这个配置项后,会在当前组件的 HTML 元素上加入 id="当前组件的 fieldId",一般用于做 utils 的绑定,不常用',
|
||||||
|
initialValue: false,
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'customClassName',
|
||||||
|
title: '自定义样式类',
|
||||||
|
display: 'block',
|
||||||
|
supportVariable: true,
|
||||||
|
initialValue: '',
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
placeholder: null,
|
||||||
|
multiline: false,
|
||||||
|
rows: 10,
|
||||||
|
required: false,
|
||||||
|
pattern: null,
|
||||||
|
maxLength: null,
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'events',
|
||||||
|
title: '动作设置',
|
||||||
|
tip: {
|
||||||
|
url: 'https://lark.alipay.com/legao/legao/events-call',
|
||||||
|
content: '点击 ? 查看如何设置组件的事件响应动作',
|
||||||
|
},
|
||||||
|
display: 'accordion',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
setter: {
|
||||||
|
key: null,
|
||||||
|
ref: null,
|
||||||
|
props: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
title: '当点击时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当点击时\n */\nfunction onClick(event) {\n console.log('onClick', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
title: '当鼠标进入时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标进入时\n */\nfunction onMouseEnter(event) {\n console.log('onMouseEnter', event);\n}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
title: '当鼠标离开时',
|
||||||
|
initialValue:
|
||||||
|
"/**\n * 容器 当鼠标离开时\n */\nfunction onMouseLeave(event) {\n console.log('onMouseLeave', event);\n}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
_owner: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
display: 'none',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseEnter',
|
||||||
|
display: 'none',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onMouseLeave',
|
||||||
|
display: 'none',
|
||||||
|
initialValue: {
|
||||||
|
ignored: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
955
packages/editor-preset-vision/tests/fixtures/schema/form.ts
vendored
Normal file
955
packages/editor-preset-vision/tests/fixtures/schema/form.ts
vendored
Normal file
@ -0,0 +1,955 @@
|
|||||||
|
export default {
|
||||||
|
componentName: 'Page',
|
||||||
|
id: 'node_k1ow3cb9',
|
||||||
|
props: {
|
||||||
|
extensions: {
|
||||||
|
启用页头: true,
|
||||||
|
},
|
||||||
|
pageStyle: {
|
||||||
|
backgroundColor: '#f2f3f5',
|
||||||
|
},
|
||||||
|
containerStyle: {},
|
||||||
|
className: 'page_kh05zf9c',
|
||||||
|
templateVersion: '1.0.0',
|
||||||
|
},
|
||||||
|
lifeCycles: {
|
||||||
|
constructor: {
|
||||||
|
type: 'js',
|
||||||
|
compiled:
|
||||||
|
"function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
|
||||||
|
source:
|
||||||
|
"function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
css:
|
||||||
|
'body{background-color:#f2f3f5}.card_kh05zf9d {\n margin-bottom: 12px;\n}.card_kh05zf9e {\n margin-bottom: 12px;\n}.button_kh05zf9f {\n margin-right: 16px;\n width: 80px\n}.button_kh05zf9g {\n width: 80px;\n}.div_kh05zf9h {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
|
||||||
|
methods: {
|
||||||
|
__initMethods__: {
|
||||||
|
type: 'js',
|
||||||
|
source: 'function (exports, module) { /*set actions code here*/ }',
|
||||||
|
compiled: 'function (exports, module) { /*set actions code here*/ }',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
offline: [],
|
||||||
|
globalConfig: {
|
||||||
|
fit: {
|
||||||
|
compiled: '',
|
||||||
|
source: '',
|
||||||
|
type: 'js',
|
||||||
|
error: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
online: [],
|
||||||
|
sync: true,
|
||||||
|
list: [],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'RootHeader',
|
||||||
|
id: 'node_k1ow3cba',
|
||||||
|
props: {},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'PageHeader',
|
||||||
|
id: 'node_k1ow3cbd',
|
||||||
|
props: {
|
||||||
|
extraContent: '',
|
||||||
|
__slot__extraContent: false,
|
||||||
|
__slot__action: false,
|
||||||
|
title: '',
|
||||||
|
content: '',
|
||||||
|
__slot__logo: false,
|
||||||
|
__slot__crumb: false,
|
||||||
|
crumb: '',
|
||||||
|
tab: '',
|
||||||
|
logo: '',
|
||||||
|
action: '',
|
||||||
|
__slot__tab: false,
|
||||||
|
__style__: {},
|
||||||
|
__slot__content: false,
|
||||||
|
fieldId: 'pageHeader_k1ow3h1i',
|
||||||
|
subTitle: '',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'RootContent',
|
||||||
|
id: 'node_k1ow3cbb',
|
||||||
|
props: {
|
||||||
|
contentBgColor: 'transparent',
|
||||||
|
contentPadding: '0',
|
||||||
|
contentMargin: '20',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Form',
|
||||||
|
id: 'form',
|
||||||
|
props: {
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
autoValidate: true,
|
||||||
|
scrollToFirstError: true,
|
||||||
|
autoUnmount: true,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
dataSource: {
|
||||||
|
type: 'variable',
|
||||||
|
variable: 'state.formData',
|
||||||
|
},
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'form',
|
||||||
|
fieldOptions: {},
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Card',
|
||||||
|
id: 'node_k1ow3cbj',
|
||||||
|
props: {
|
||||||
|
__slot__title: false,
|
||||||
|
subTitle: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__slot__subTitle: false,
|
||||||
|
extra: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
className: 'card_kh05zf9d',
|
||||||
|
title: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'Title',
|
||||||
|
zh_CN: '基本信息',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__slot__extra: false,
|
||||||
|
showHeadDivider: true,
|
||||||
|
__style__: ':root {\n margin-bottom: 12px;\n}',
|
||||||
|
showTitleBullet: true,
|
||||||
|
contentHeight: '',
|
||||||
|
fieldId: 'card_k1ow3h1l',
|
||||||
|
dividerNoInset: false,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'CardContent',
|
||||||
|
id: 'node_k1ow3cbk',
|
||||||
|
props: {},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'ColumnsLayout',
|
||||||
|
id: 'node_k1ow3cbw',
|
||||||
|
props: {
|
||||||
|
layout: '4:8',
|
||||||
|
columnGap: '20',
|
||||||
|
rowGap: 0,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'columns_k1ow3h1v',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Column',
|
||||||
|
id: 'node_k1ow3cbx',
|
||||||
|
props: {
|
||||||
|
colSpan: '',
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'column_k1p1bnjm',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cbz',
|
||||||
|
props: {
|
||||||
|
fieldName: 'name',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'required',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h1w',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: '姓名',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cc1',
|
||||||
|
props: {
|
||||||
|
fieldName: 'englishName',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h1y',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: '英文名',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cc3',
|
||||||
|
props: {
|
||||||
|
fieldName: 'jobTitle',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h20',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: '职位',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Column',
|
||||||
|
id: 'node_k1ow3cby',
|
||||||
|
props: {
|
||||||
|
colSpan: '',
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'column_k1p1bnjn',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cc2',
|
||||||
|
props: {
|
||||||
|
fieldName: 'nickName',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h1z',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: '花名',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'SelectField',
|
||||||
|
id: 'node_k1ow3cc0',
|
||||||
|
props: {
|
||||||
|
fieldName: 'gender',
|
||||||
|
hasClear: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
mode: 'single',
|
||||||
|
showSearch: false,
|
||||||
|
autoWidth: true,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please select',
|
||||||
|
zh_CN: '请选择',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
hasBorder: true,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: '',
|
||||||
|
validation: [
|
||||||
|
{
|
||||||
|
type: 'required',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'select_k1ow3h1x',
|
||||||
|
notFoundContent: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'SelectField',
|
||||||
|
zh_CN: '性别',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
hasSelectAll: false,
|
||||||
|
hasArrow: true,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
filterLocal: true,
|
||||||
|
dataSource: [
|
||||||
|
{
|
||||||
|
defaultChecked: false,
|
||||||
|
text: {
|
||||||
|
en_US: 'Option 1',
|
||||||
|
zh_CN: '男',
|
||||||
|
type: 'i18n',
|
||||||
|
__sid__: 'param_k1owc4tb',
|
||||||
|
},
|
||||||
|
__sid__: 'serial_k1owc4t1',
|
||||||
|
value: 'M',
|
||||||
|
sid: 'opt_k1owc4t2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
defaultChecked: false,
|
||||||
|
text: {
|
||||||
|
en_US: 'Option 2',
|
||||||
|
zh_CN: '女',
|
||||||
|
type: 'i18n',
|
||||||
|
__sid__: 'param_k1owc4tf',
|
||||||
|
},
|
||||||
|
__sid__: 'serial_k1owc4t2',
|
||||||
|
value: 'F',
|
||||||
|
sid: 'opt_k1owc4t3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
useDetailValue: false,
|
||||||
|
searchDelay: 300,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Card',
|
||||||
|
id: 'node_k1ow3cbl',
|
||||||
|
props: {
|
||||||
|
__slot__title: false,
|
||||||
|
subTitle: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__slot__subTitle: false,
|
||||||
|
extra: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
className: 'card_kh05zf9e',
|
||||||
|
title: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'Title',
|
||||||
|
zh_CN: '部门信息',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__slot__extra: false,
|
||||||
|
showHeadDivider: true,
|
||||||
|
__style__: ':root {\n margin-bottom: 12px;\n}',
|
||||||
|
showTitleBullet: true,
|
||||||
|
contentHeight: '',
|
||||||
|
fieldId: 'card_k1ow3h1m',
|
||||||
|
dividerNoInset: false,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'CardContent',
|
||||||
|
id: 'node_k1ow3cbm',
|
||||||
|
props: {},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cc4',
|
||||||
|
props: {
|
||||||
|
fieldName: 'department',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h21',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: '所属部门',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'ColumnsLayout',
|
||||||
|
id: 'node_k1ow3cc5',
|
||||||
|
props: {
|
||||||
|
layout: '6:6',
|
||||||
|
columnGap: '20',
|
||||||
|
rowGap: 0,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'columns_k1ow3h22',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Column',
|
||||||
|
id: 'node_k1ow3cc6',
|
||||||
|
props: {
|
||||||
|
colSpan: '',
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'column_k1p1bnjo',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cc8',
|
||||||
|
props: {
|
||||||
|
fieldName: 'leader',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h23',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: '主管',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Column',
|
||||||
|
id: 'node_k1ow3cc7',
|
||||||
|
props: {
|
||||||
|
colSpan: '',
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'column_k1p1bnjp',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'TextField',
|
||||||
|
id: 'node_k1ow3cc9',
|
||||||
|
props: {
|
||||||
|
fieldName: 'hrg',
|
||||||
|
hasClear: false,
|
||||||
|
autoFocus: false,
|
||||||
|
tips: {
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
trim: false,
|
||||||
|
labelTextAlign: 'right',
|
||||||
|
placeholder: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'please input',
|
||||||
|
zh_CN: '请输入',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
state: '',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
addonBefore: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
validation: [],
|
||||||
|
hasLimitHint: false,
|
||||||
|
cutString: false,
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'textField_k1ow3h24',
|
||||||
|
htmlType: 'input',
|
||||||
|
autoHeight: false,
|
||||||
|
labelColOffset: 0,
|
||||||
|
label: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'TextField',
|
||||||
|
zh_CN: 'HRG',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__category__: 'form',
|
||||||
|
labelColSpan: 4,
|
||||||
|
wrapperColSpan: 0,
|
||||||
|
rows: 4,
|
||||||
|
addonAfter: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
zh_CN: '',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
wrapperColOffset: 0,
|
||||||
|
size: 'medium',
|
||||||
|
labelAlign: 'top',
|
||||||
|
__useMediator: 'value',
|
||||||
|
labelTipsTypes: 'none',
|
||||||
|
labelTipsIcon: '',
|
||||||
|
labelTipsText: {
|
||||||
|
type: 'i18n',
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: '',
|
||||||
|
zh_CN: '',
|
||||||
|
},
|
||||||
|
maxLength: 200,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Div',
|
||||||
|
id: 'node_k1ow3cbo',
|
||||||
|
props: {
|
||||||
|
className: 'div_kh05zf9h',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
__style__:
|
||||||
|
':root {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n background: #fff;\n padding: 20px 0;\n}',
|
||||||
|
events: {},
|
||||||
|
fieldId: 'div_k1ow3h1o',
|
||||||
|
useFieldIdAsDomId: false,
|
||||||
|
customClassName: '',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Button',
|
||||||
|
id: 'node_k1ow3cbn',
|
||||||
|
props: {
|
||||||
|
triggerEventsWhenLoading: false,
|
||||||
|
onClick: {
|
||||||
|
rawType: 'events',
|
||||||
|
type: 'JSExpression',
|
||||||
|
value:
|
||||||
|
'this.utils.legaoBuiltin.execEventFlow.bind(this, [this.submit])',
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
name: 'submit',
|
||||||
|
id: 'submit',
|
||||||
|
params: {},
|
||||||
|
type: 'actionRef',
|
||||||
|
uuid: '1570966253282_0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
size: 'medium',
|
||||||
|
baseIcon: '',
|
||||||
|
otherIcon: '',
|
||||||
|
className: 'button_kh05zf9f',
|
||||||
|
type: 'primary',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
loading: false,
|
||||||
|
content: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'Button',
|
||||||
|
zh_CN: '提交',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__style__: ':root {\n margin-right: 16px;\n width: 80px\n}',
|
||||||
|
fieldId: 'button_k1ow3h1n',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'Button',
|
||||||
|
id: 'node_k1ow3cbp',
|
||||||
|
props: {
|
||||||
|
triggerEventsWhenLoading: false,
|
||||||
|
size: 'medium',
|
||||||
|
baseIcon: '',
|
||||||
|
otherIcon: '',
|
||||||
|
className: 'button_kh05zf9g',
|
||||||
|
type: 'normal',
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
loading: false,
|
||||||
|
content: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'Button',
|
||||||
|
zh_CN: '取消',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
__style__: ':root {\n width: 80px;\n}',
|
||||||
|
fieldId: 'button_k1ow3h1p',
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'RootFooter',
|
||||||
|
id: 'node_k1ow3cbc',
|
||||||
|
props: {},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
5
packages/editor-preset-vision/tests/fixtures/window.ts
vendored
Normal file
5
packages/editor-preset-vision/tests/fixtures/window.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
React.PropTypes = PropTypes;
|
||||||
|
window.React = React;
|
||||||
1
packages/editor-preset-vision/tests/utils/index.ts
Normal file
1
packages/editor-preset-vision/tests/utils/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { getIdsFromSchema, getNodeFromSchemaById } from '@ali/lowcode-test-mate/es/utils';
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
// import { Project } from '../../src/project/project';
|
||||||
|
// import { Node } from '../../src/document/node/node';
|
||||||
|
// import { Designer } from '../../src/designer/designer';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import VisualEngine, {
|
||||||
|
designer,
|
||||||
|
editor,
|
||||||
|
skeleton,
|
||||||
|
/**
|
||||||
|
* VE.Popup
|
||||||
|
*/
|
||||||
|
Popup,
|
||||||
|
/**
|
||||||
|
* VE Utils
|
||||||
|
*/
|
||||||
|
utils,
|
||||||
|
I18nUtil,
|
||||||
|
Hotkey,
|
||||||
|
Env,
|
||||||
|
monitor,
|
||||||
|
/* pub/sub 集线器 */
|
||||||
|
Bus,
|
||||||
|
/* 事件 */
|
||||||
|
EVENTS,
|
||||||
|
/* 修饰方法 */
|
||||||
|
HOOKS,
|
||||||
|
Exchange,
|
||||||
|
context,
|
||||||
|
/**
|
||||||
|
* VE.init
|
||||||
|
*
|
||||||
|
* Initialized the whole VisualEngine UI
|
||||||
|
*/
|
||||||
|
init,
|
||||||
|
ui,
|
||||||
|
Panes,
|
||||||
|
modules,
|
||||||
|
Trunk,
|
||||||
|
Prototype,
|
||||||
|
Bundle,
|
||||||
|
Pages,
|
||||||
|
DragEngine,
|
||||||
|
Viewport,
|
||||||
|
Version,
|
||||||
|
Project,
|
||||||
|
logger,
|
||||||
|
Symbols,
|
||||||
|
} from '../../src';
|
||||||
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
|
|
||||||
|
describe('API 多种导出场景测试', () => {
|
||||||
|
it('window.VisualEngine 和 npm 导出 API 测试', () => {
|
||||||
|
expect(VisualEngine).toBe(window.VisualEngine);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('npm 导出 API 对比测试', () => {
|
||||||
|
expect(VisualEngine.designer).toBe(designer);
|
||||||
|
expect(VisualEngine.editor).toBe(editor);
|
||||||
|
expect(VisualEngine.skeleton).toBe(skeleton);
|
||||||
|
expect(VisualEngine.Popup).toBe(Popup);
|
||||||
|
expect(VisualEngine.utils).toBe(utils);
|
||||||
|
expect(VisualEngine.I18nUtil).toBe(I18nUtil);
|
||||||
|
expect(VisualEngine.Hotkey).toBe(Hotkey);
|
||||||
|
expect(VisualEngine.Env).toBe(Env);
|
||||||
|
expect(VisualEngine.monitor).toBe(monitor);
|
||||||
|
expect(VisualEngine.Bus).toBe(Bus);
|
||||||
|
expect(VisualEngine.EVENTS).toBe(EVENTS);
|
||||||
|
expect(VisualEngine.HOOKS).toBe(HOOKS);
|
||||||
|
expect(VisualEngine.Exchange).toBe(Exchange);
|
||||||
|
expect(VisualEngine.context).toBe(context);
|
||||||
|
expect(VisualEngine.init).toBe(init);
|
||||||
|
expect(VisualEngine.ui).toBe(ui);
|
||||||
|
expect(VisualEngine.Panes).toBe(Panes);
|
||||||
|
expect(VisualEngine.modules).toBe(modules);
|
||||||
|
expect(VisualEngine.Trunk).toBe(Trunk);
|
||||||
|
expect(VisualEngine.Prototype).toBe(Prototype);
|
||||||
|
expect(VisualEngine.Bundle).toBe(Bundle);
|
||||||
|
expect(VisualEngine.DragEngine).toBe(DragEngine);
|
||||||
|
expect(VisualEngine.Pages).toBe(Pages);
|
||||||
|
expect(VisualEngine.Viewport).toBe(Viewport);
|
||||||
|
expect(VisualEngine.Version).toBe(Version);
|
||||||
|
expect(VisualEngine.Project).toBe(Project);
|
||||||
|
expect(VisualEngine.logger).toBe(logger);
|
||||||
|
expect(VisualEngine.Symbols).toBe(Symbols);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import VisualEngine from '../../src';
|
||||||
|
|
||||||
|
describe('VisualEngine.Exchange 相关 API 测试', () => {
|
||||||
|
it('select / getSelected', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(formSchema);
|
||||||
|
VisualEngine.Exchange.select(doc?.getNode('form'));
|
||||||
|
expect(VisualEngine.Exchange.getSelected()?.componentName).toBe('Form');
|
||||||
|
expect(VisualEngine.Exchange.getSelected()?.id).toBe('form');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('onIntoView', () => {
|
||||||
|
expect(typeof VisualEngine.Exchange.onIntoView).toBe('function');
|
||||||
|
});
|
||||||
|
});
|
||||||
170
packages/editor-preset-vision/tests/vision-api/pages.test.ts
Normal file
170
packages/editor-preset-vision/tests/vision-api/pages.test.ts
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import VisualEngine, { Prototype } from '../../src';
|
||||||
|
import { Editor } from '@ali/lowcode-editor-core';
|
||||||
|
import { getIdsFromSchema, getNodeFromSchemaById } from '../utils';
|
||||||
|
import divPrototypeConfig from '../fixtures/prototype/div-vision';
|
||||||
|
|
||||||
|
const pageSchema = { componentsTree: [formSchema] };
|
||||||
|
|
||||||
|
describe('VisualEngine.Pages 相关 API 测试', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
VisualEngine.Pages.unload();
|
||||||
|
});
|
||||||
|
describe('addPage 系列', () => {
|
||||||
|
it('基本的节点模型初始化,初始化传入 schema', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema)!;
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
expect(doc.nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
});
|
||||||
|
it('基本的节点模型初始化,初始化传入 schema,带有 slot', () => {
|
||||||
|
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title', {
|
||||||
|
type: 'JSBlock',
|
||||||
|
value: {
|
||||||
|
componentName: 'Slot',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Text',
|
||||||
|
id: 'node_k1ow3cbf',
|
||||||
|
props: {
|
||||||
|
showTitle: false,
|
||||||
|
behavior: 'NORMAL',
|
||||||
|
content: {
|
||||||
|
type: 'variable',
|
||||||
|
value: {
|
||||||
|
use: 'zh_CN',
|
||||||
|
en_US: 'Title',
|
||||||
|
zh_CN: '个人信息',
|
||||||
|
type: 'i18n',
|
||||||
|
},
|
||||||
|
variable: 'state.title',
|
||||||
|
},
|
||||||
|
__style__: {},
|
||||||
|
fieldId: 'text_k1ow3h1j',
|
||||||
|
maxLine: 0,
|
||||||
|
},
|
||||||
|
condition: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
slotTitle: '标题区域',
|
||||||
|
slotName: 'title',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const doc = VisualEngine.Pages.addPage({ componentsTree: [formSchemaWithSlot] })!;
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
// slot 会多出(1 + N)个节点
|
||||||
|
expect(doc.nodesMap.size).toBe(expectedNodeCnt + 2);
|
||||||
|
});
|
||||||
|
it.only('基本的节点模型初始化,初始化传入 schema,构造 prototype', () => {
|
||||||
|
const proto = new Prototype(divPrototypeConfig);
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema)!;
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
expect(doc.nodesMap.size).toBe(expectedNodeCnt);
|
||||||
|
});
|
||||||
|
it('导出 schema', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema)!;
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const exportedData = doc.toData();
|
||||||
|
expect(exportedData).toHaveProperty('componentsMap');
|
||||||
|
expect(exportedData).toHaveProperty('componentsTree');
|
||||||
|
expect(exportedData.componentsTree).toHaveLength(1);
|
||||||
|
const exportedSchema = exportedData.componentsTree[0];
|
||||||
|
expect(getIdsFromSchema(exportedSchema).length).toBe(expectedNodeCnt);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('removePage 系列', () => {
|
||||||
|
it('removePage', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema)!;
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
expect(VisualEngine.Pages.documents).toHaveLength(1);
|
||||||
|
VisualEngine.Pages.removePage(doc);
|
||||||
|
expect(VisualEngine.Pages.documents).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getPage 系列', () => {
|
||||||
|
it('getPage', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema);
|
||||||
|
const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
|
||||||
|
const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
|
||||||
|
expect(VisualEngine.Pages.getPage(0)).toBe(doc);
|
||||||
|
expect(VisualEngine.Pages.getPage((_doc) => _doc.rootNode.id === 'page')).toBe(doc2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('setPages 系列', () => {
|
||||||
|
it('setPages componentsTree 只有一个元素', () => {
|
||||||
|
VisualEngine.Pages.setPages([pageSchema]);
|
||||||
|
const { currentDocument } = VisualEngine.Pages;
|
||||||
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
const exportedData = currentDocument.toData();
|
||||||
|
expect(exportedData).toHaveProperty('componentsMap');
|
||||||
|
expect(exportedData).toHaveProperty('componentsTree');
|
||||||
|
expect(exportedData.componentsTree).toHaveLength(1);
|
||||||
|
const exportedSchema = exportedData.componentsTree[0];
|
||||||
|
expect(getIdsFromSchema(exportedSchema).length).toBe(expectedNodeCnt);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('setCurrentPage / getCurrentPage / currentPage / currentDocument 系列', () => {
|
||||||
|
it('getCurrentPage', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema)!;
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
expect(doc).toBe(VisualEngine.Pages.getCurrentPage());
|
||||||
|
expect(doc).toBe(VisualEngine.Pages.currentDocument);
|
||||||
|
expect(doc).toBe(VisualEngine.Pages.currentPage);
|
||||||
|
});
|
||||||
|
it('setCurrentPage', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema);
|
||||||
|
expect(doc).toBe(VisualEngine.Pages.currentDocument);
|
||||||
|
const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
|
||||||
|
const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
|
||||||
|
expect(doc2).toBe(VisualEngine.Pages.currentDocument);
|
||||||
|
VisualEngine.Pages.setCurrentPage(doc);
|
||||||
|
expect(doc).toBe(VisualEngine.Pages.currentDocument);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('onCurrentPageChange 系列', () => {
|
||||||
|
it('多次切换', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema);
|
||||||
|
const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
|
||||||
|
const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
|
||||||
|
const docChangeHandler = jest.fn();
|
||||||
|
VisualEngine.Pages.onCurrentDocumentChange(docChangeHandler);
|
||||||
|
VisualEngine.Pages.setCurrentPage(doc);
|
||||||
|
expect(docChangeHandler).toHaveBeenCalledTimes(1);
|
||||||
|
expect(docChangeHandler).toHaveBeenLastCalledWith(doc);
|
||||||
|
|
||||||
|
VisualEngine.Pages.setCurrentPage(doc2);
|
||||||
|
expect(docChangeHandler).toHaveBeenCalledTimes(2);
|
||||||
|
expect(docChangeHandler).toHaveBeenLastCalledWith(doc2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('toData 系列', () => {
|
||||||
|
it('基本的节点模型初始化,模型导出,初始化传入 schema', () => {
|
||||||
|
const doc = VisualEngine.Pages.addPage(pageSchema);
|
||||||
|
const anotherFormSchema = set(cloneDeep(formSchema), 'id', 'page');
|
||||||
|
const doc2 = VisualEngine.Pages.addPage({ componentsTree: [anotherFormSchema] });
|
||||||
|
const dataList = VisualEngine.Pages.toData();
|
||||||
|
expect(dataList.length).toBe(2);
|
||||||
|
expect(dataList[0]).toHaveProperty('componentsMap');
|
||||||
|
expect(dataList[0]).toHaveProperty('componentsTree');
|
||||||
|
expect(dataList[0].componentsTree).toHaveLength(1);
|
||||||
|
expect(dataList[0].componentsTree[0].id).toBe('node_k1ow3cb9');
|
||||||
|
expect(dataList[1]).toHaveProperty('componentsMap');
|
||||||
|
expect(dataList[1]).toHaveProperty('componentsTree');
|
||||||
|
expect(dataList[1].componentsTree).toHaveLength(1);
|
||||||
|
expect(dataList[1].componentsTree[0].id).toBe('page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import set from 'lodash/set';
|
||||||
|
import cloneDeep from 'lodash/clonedeep';
|
||||||
|
import '../fixtures/window';
|
||||||
|
import formSchema from '../fixtures/schema/form';
|
||||||
|
import { Project } from '../../src';
|
||||||
|
|
||||||
|
describe.skip('VisualEngine.Project 相关 API 测试', () => {
|
||||||
|
it('getSchema / setSchema 系列', () => {
|
||||||
|
Project.setSchema({
|
||||||
|
componentsMap: {},
|
||||||
|
componentsTree: [formSchema],
|
||||||
|
});
|
||||||
|
expect(Project.getSchema()).toEqual({
|
||||||
|
componentsMap: {},
|
||||||
|
componentsTree: [formSchema],
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setConfig', () => {
|
||||||
|
Project.setConfig({ haha: 1 });
|
||||||
|
expect(Project.get('config')).toEqual({
|
||||||
|
haha: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-setters
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-setters",
|
"name": "@ali/lowcode-editor-setters",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "Builtin setters for Ali lowCode engine",
|
"description": "Builtin setters for Ali lowCode engine",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
@ -21,7 +21,7 @@
|
|||||||
"@ali/iceluna-comp-react-node": "^1.0.5",
|
"@ali/iceluna-comp-react-node": "^1.0.5",
|
||||||
"@ali/iceluna-sdk": "^1.0.5-beta.24",
|
"@ali/iceluna-sdk": "^1.0.5-beta.24",
|
||||||
"@ali/lc-style-setter": "^0.0.1",
|
"@ali/lc-style-setter": "^0.0.1",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.19.16",
|
"@alifd/next": "^1.19.16",
|
||||||
"acorn": "^6.4.1",
|
"acorn": "^6.4.1",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
|||||||
@ -12,5 +12,6 @@ module.exports = {
|
|||||||
'no-prototype-builtins': 1,
|
'no-prototype-builtins': 1,
|
||||||
'no-confusing-arrow': 1,
|
'no-confusing-arrow': 1,
|
||||||
'no-case-declarations': 1,
|
'no-case-declarations': 1,
|
||||||
|
'lines-between-class-members': 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-editor-skeleton
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-editor-skeleton",
|
"name": "@ali/lowcode-editor-skeleton",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "alibaba lowcode editor skeleton",
|
"description": "alibaba lowcode editor skeleton",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"module": "es/index.js",
|
"module": "es/index.js",
|
||||||
@ -19,10 +19,10 @@
|
|||||||
"editor"
|
"editor"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-designer": "^0.13.1-10",
|
"@ali/lowcode-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@ali/ve-icons": "latest",
|
"@ali/ve-icons": "latest",
|
||||||
"@ali/ve-less-variables": "^2.0.0",
|
"@ali/ve-less-variables": "^2.0.0",
|
||||||
"@alifd/next": "^1.20.12",
|
"@alifd/next": "^1.20.12",
|
||||||
|
|||||||
@ -26,10 +26,10 @@ export class SettingsPrimaryPane extends Component<{ editor: Editor; config: any
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setShouldIgnoreRoot() {
|
async setShouldIgnoreRoot() {
|
||||||
let designMode = await this.props.editor.get('designMode');
|
const designMode = await this.props.editor.get('designMode');
|
||||||
this.setState({
|
this.setState({
|
||||||
shouldIgnoreRoot: designMode === 'live',
|
shouldIgnoreRoot: designMode === 'live',
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@ -329,7 +329,7 @@ export default function (metadata: TransformedComponentMetadata): TransformedCom
|
|||||||
if (advanceGroup.length > 0) {
|
if (advanceGroup.length > 0) {
|
||||||
combined.push({
|
combined.push({
|
||||||
name: '#advanced',
|
name: '#advanced',
|
||||||
title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advance' },
|
title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advanced' },
|
||||||
items: advanceGroup,
|
items: advanceGroup,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-material-parser
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-material-parser",
|
"name": "@ali/lowcode-material-parser",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "material parser for Ali lowCode engine",
|
"description": "material parser for Ali lowCode engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-components-pane
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-components-pane",
|
"name": "@ali/lowcode-plugin-components-pane",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "alibaba lowcode editor component-list plugin",
|
"description": "alibaba lowcode editor component-list plugin",
|
||||||
"files": [
|
"files": [
|
||||||
"es/",
|
"es/",
|
||||||
@ -20,9 +20,9 @@
|
|||||||
],
|
],
|
||||||
"author": "xiayang.xy",
|
"author": "xiayang.xy",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-designer": "^0.13.1-10",
|
"@ali/lowcode-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.19.19",
|
"@alifd/next": "^1.19.19",
|
||||||
"react": "^16.8.1"
|
"react": "^16.8.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-designer
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-designer",
|
"name": "@ali/lowcode-plugin-designer",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "alibaba lowcode editor designer plugin",
|
"description": "alibaba lowcode editor designer plugin",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
@ -20,8 +20,8 @@
|
|||||||
],
|
],
|
||||||
"author": "xiayang.xy",
|
"author": "xiayang.xy",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-designer": "^0.13.1-10",
|
"@ali/lowcode-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.1",
|
||||||
"react-dom": "^16.8.1"
|
"react-dom": "^16.8.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-event-bind-dialog
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-event-bind-dialog",
|
"name": "@ali/lowcode-plugin-event-bind-dialog",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "alibaba lowcode editor event bind dialog plugin",
|
"description": "alibaba lowcode editor event bind dialog plugin",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
@ -19,8 +19,8 @@
|
|||||||
],
|
],
|
||||||
"author": "zude.hzd",
|
"author": "zude.hzd",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.19.16",
|
"@alifd/next": "^1.19.16",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.1",
|
||||||
"react-dom": "^16.8.1"
|
"react-dom": "^16.8.1"
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-outline-pane
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-outline-pane",
|
"name": "@ali/lowcode-plugin-outline-pane",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "Outline pane for Ali lowCode engine",
|
"description": "Outline pane for Ali lowCode engine",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
@ -14,10 +14,10 @@
|
|||||||
"test:snapshot": "ava --update-snapshots"
|
"test:snapshot": "ava --update-snapshots"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-designer": "^0.13.1-10",
|
"@ali/lowcode-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.19.16",
|
"@alifd/next": "^1.19.16",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"react": "^16",
|
"react": "^16",
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-sample-logo
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-sample-logo",
|
"name": "@ali/lowcode-plugin-sample-logo",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "alibaba lowcode editor logo plugin",
|
"description": "alibaba lowcode editor logo plugin",
|
||||||
"files": [
|
"files": [
|
||||||
"es/",
|
"es/",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
],
|
],
|
||||||
"author": "xiayang.xy",
|
"author": "xiayang.xy",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"react": "^16.8.1"
|
"react": "^16.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.13.1-11"></a>
|
||||||
|
## [0.13.1-11](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-10...v0.13.1-11) (2020-11-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @ali/lowcode-plugin-sample-preview
|
||||||
|
|
||||||
<a name="0.13.1-10"></a>
|
<a name="0.13.1-10"></a>
|
||||||
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
## [0.13.1-10](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/v0.13.1-9...v0.13.1-10) (2020-10-26)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-plugin-sample-preview",
|
"name": "@ali/lowcode-plugin-sample-preview",
|
||||||
"version": "0.13.1-10",
|
"version": "0.13.1-11",
|
||||||
"description": "alibaba lowcode editor sample preview plugin",
|
"description": "alibaba lowcode editor sample preview plugin",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
@ -19,11 +19,11 @@
|
|||||||
"editor"
|
"editor"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ali/lowcode-designer": "^0.13.1-10",
|
"@ali/lowcode-designer": "^0.13.1-11",
|
||||||
"@ali/lowcode-editor-core": "^0.13.1-10",
|
"@ali/lowcode-editor-core": "^0.13.1-11",
|
||||||
"@ali/lowcode-react-renderer": "^0.13.1-10",
|
"@ali/lowcode-react-renderer": "^0.13.1-11",
|
||||||
"@ali/lowcode-types": "^0.13.1-10",
|
"@ali/lowcode-types": "^0.13.1-11",
|
||||||
"@ali/lowcode-utils": "^0.13.1-10",
|
"@ali/lowcode-utils": "^0.13.1-11",
|
||||||
"@alifd/next": "^1.x",
|
"@alifd/next": "^1.x",
|
||||||
"react": "^16.8.1"
|
"react": "^16.8.1"
|
||||||
},
|
},
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user