feat(client): add designable test cases

This commit is contained in:
chenos 2022-02-14 15:50:19 +08:00
parent be489996c3
commit 1a7f638f85
11 changed files with 839 additions and 140 deletions

View File

@ -19,6 +19,7 @@ export interface IResource {
create?: (params?: ActionParams) => Promise<any>;
update?: (params?: ActionParams) => Promise<any>;
destroy?: (params?: ActionParams) => Promise<any>;
[key: string]: (params?: ActionParams) => Promise<any>;
}
export class APIClient {

View File

@ -103,6 +103,96 @@ const FormBlockInitializerItem = itemWrap((props) => {
);
});
const TestInitializerItem = itemWrap((props) => {
const { insert } = props;
return (
<SchemaInitializer.Item
icon={<FormOutlined />}
onClick={() => {
insert({
type: 'void',
name: uid(),
'x-decorator': 'CardItem',
'x-component': 'Grid',
'x-uid': uid(),
properties: {
row1: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col11: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block1: {
type: 'void',
title: '1',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
block2: {
type: 'void',
title: '2',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
col12: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block3: {
type: 'void',
title: '3',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
},
},
row2: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col21: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block4: {
type: 'void',
title: '4',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
col22: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
block5: {
type: 'void',
title: '5',
'x-decorator': 'BlockItem',
'x-component': 'Block',
},
},
},
},
},
},
});
}}
>
Test
</SchemaInitializer.Item>
);
});
export const AddGridBlockItem = observer((props: any) => {
return (
<SchemaInitializer.Button
@ -123,6 +213,11 @@ export const AddGridBlockItem = observer((props: any) => {
title: 'Form',
component: FormBlockInitializerItem,
},
{
type: 'item',
title: 'Test',
component: TestInitializerItem,
},
],
},
]}

View File

@ -74,8 +74,10 @@ const useCurrentFieldSchema = (path: string) => {
remove() {
schema &&
remove(schema, {
breakComponent: 'Grid',
removeEmptyParents: true,
removeParentsIfNoChildren: true,
breakSchema: (s) => {
return s['x-component'] === 'Grid';
},
});
},
};

View File

@ -0,0 +1,13 @@
import { observer, useFieldSchema } from '@formily/react';
import React from 'react';
import { DragHandler } from '../../';
export const Block = observer((props) => {
const fieldSchema = useFieldSchema();
return (
<div style={{ marginBottom: 20, padding: '0 20px', height: 50, lineHeight: '50px', background: '#f1f1f1' }}>
Block {fieldSchema.title}
<DragHandler />
</div>
);
});

View File

@ -1,5 +1,4 @@
import { observer, useFieldSchema } from '@formily/react';
import { uid } from '@formily/shared';
import { BlockItem, DragHandler, Grid, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
import React from 'react';
@ -13,87 +12,151 @@ const Block = observer((props) => {
);
});
export default function App() {
return (
<SchemaComponentProvider components={{ Grid, Block, BlockItem }}>
<SchemaComponent
schema={{
const schema = {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
name: 'grid1',
'x-decorator': 'CardItem',
'x-component': 'Grid',
'x-uid': uid(),
properties: {
row1: {
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col11: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
block1: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '1',
'x-decorator': 'BlockItem',
'x-component': 'Block',
'x-uid': 'a9m97uffyku',
'x-async': false,
'x-index': 1,
},
block2: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '2',
title: '2.1',
'x-decorator': 'BlockItem',
'x-component': 'Block',
'x-uid': 'lensw462z8w',
'x-async': false,
'x-index': 2,
},
block234: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '2.2',
'x-decorator': 'BlockItem',
'x-component': 'Block',
'x-uid': 'lensw462z81',
'x-async': false,
'x-index': 3,
},
},
'x-uid': '4shevom50rl',
'x-async': false,
'x-index': 1,
},
col12: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
block3: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '3',
'x-decorator': 'BlockItem',
'x-component': 'Block',
'x-uid': 'kp4kjknbs2l',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'u7n3beze0gr',
'x-async': false,
'x-index': 2,
},
},
'x-uid': 'qfl04eq71tt',
'x-async': false,
'x-index': 1,
},
row2: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
'x-uid': uid(),
properties: {
col21: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
block4: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '4',
'x-decorator': 'BlockItem',
'x-component': 'Block',
'x-uid': 'v5bd5kcyhat',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'bwg0mv89atk',
'x-async': false,
'x-index': 1,
},
col22: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
block5: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '5',
'x-decorator': 'BlockItem',
'x-component': 'Block',
'x-uid': 'noh1flz5oqg',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'oz0rypr2rlj',
'x-async': false,
'x-index': 2,
},
},
'x-uid': '5igqpmvilz1',
'x-async': false,
'x-index': 2,
},
},
}}
/>
};
export default function App() {
return (
<SchemaComponentProvider components={{ Grid, Block, BlockItem }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
}

View File

@ -1,20 +1,44 @@
import { ISchema } from '@formily/react';
import { ISchema, observer, useFieldSchema } from '@formily/react';
import { uid } from '@formily/shared';
import { CardItem, Form, Grid, Markdown, SchemaComponent, SchemaComponentProvider, VoidTable } from '@nocobase/client';
import {
BlockItem,
CardItem,
DragHandler,
Form,
Grid,
Markdown,
SchemaComponent,
SchemaComponentProvider,
VoidTable
} from '@nocobase/client';
import React from 'react';
const Block = observer((props) => {
const fieldSchema = useFieldSchema();
return (
<div style={{ marginBottom: 20, padding: '0 20px', height: 50, lineHeight: '50px', background: '#f1f1f1' }}>
Block {fieldSchema.title}
<DragHandler />
</div>
);
});
const schema: ISchema = {
type: 'object',
properties: {
grid: {
type: 'void',
name: 'grid1',
'x-component': 'Grid',
'x-item-initializer': 'Grid.AddBlockItem',
'x-uid': uid(),
properties: {},
},
},
};
export default function App() {
return (
<SchemaComponentProvider components={{ Grid, CardItem, Markdown, Form, VoidTable }}>
<SchemaComponentProvider components={{ BlockItem, Block, Grid, CardItem, Markdown, Form, VoidTable }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);

View File

@ -1 +1,3 @@
export * from './Block';
export * from './Grid';

View File

@ -7,7 +7,6 @@ const useDragEnd = () => {
const { refresh } = useDesignable();
return ({ active, over }: DragEndEvent) => {
console.log({ active, over });
const activeSchema = active?.data?.current?.schema;
const overSchema = over?.data?.current?.schema;
const insertAdjacent = over?.data?.current?.insertAdjacent;
@ -35,7 +34,7 @@ const useDragEnd = () => {
if (insertAdjacent) {
dn.insertAdjacent(insertAdjacent, activeSchema, {
wrap: wrapSchema,
removeEmptyParents: true,
removeParentsIfNoChildren: true,
});
return;
}

View File

@ -34,16 +34,11 @@ export const Sortable = (props: any) => {
export const SortableItem: React.FC<any> = observer((props) => {
const field = useField();
const fieldSchema = useFieldSchema();
const onInsertAdjacent = ({ dn, orginDraggedParentSchema }) => {
dn.removeIfChildrenEmpty(orginDraggedParentSchema, {
removeEmptyParents: true,
});
};
return (
<Sortable
{...props}
id={field.address.toString()}
data={{ insertAdjacent: 'afterEnd', onInsertAdjacent, schema: fieldSchema }}
data={{ insertAdjacent: 'afterEnd', schema: fieldSchema }}
>
{props.children}
</Sortable>

View File

@ -0,0 +1,453 @@
import { Schema } from '@formily/react';
import { createDesignable, Designable } from '../useDesignable';
describe('createDesignable', () => {
let dn: Designable;
let schema: Schema;
beforeEach(() => {
schema = new Schema({
type: 'void',
name: 'global',
'x-uid': 'global',
properties: {
current: {
type: 'void',
'x-uid': 'current',
properties: {
child: {
type: 'void',
'x-uid': 'child',
},
},
},
},
});
dn = createDesignable({
current: schema.properties.current,
});
});
describe('insert a new node', () => {
test('insertBeforeBegin', () => {
dn.insertBeforeBegin({
name: 'abc',
});
expect(schema.toJSON()).toMatchObject({
type: 'void',
name: 'global',
'x-uid': 'global',
properties: {
abc: {
name: 'abc',
type: 'void',
},
current: {
type: 'void',
name: 'current',
'x-uid': 'current',
properties: {
child: {
type: 'void',
'x-uid': 'child',
},
},
},
},
});
expect(schema.properties.abc['x-uid']).toBeDefined();
expect(Object.keys(schema.properties)).toEqual(['abc', 'current']);
});
test('insertAfterBegin', () => {
dn.insertAfterBegin({
name: 'abc',
});
expect(Object.keys(schema.properties.current.properties)).toEqual(['abc', 'child']);
expect(schema.toJSON()).toMatchObject({
type: 'void',
name: 'global',
'x-uid': 'global',
properties: {
current: {
type: 'void',
name: 'current',
'x-uid': 'current',
properties: {
abc: {
name: 'abc',
type: 'void',
},
child: {
type: 'void',
'x-uid': 'child',
},
},
},
},
});
expect(schema.properties.current.properties.abc['x-uid']).toBeDefined();
});
test('insertBeforeEnd', () => {
dn.insertBeforeEnd({
name: 'abc',
});
expect(schema.toJSON()).toMatchObject({
type: 'void',
name: 'global',
'x-uid': 'global',
properties: {
current: {
type: 'void',
name: 'current',
'x-uid': 'current',
properties: {
child: {
type: 'void',
'x-uid': 'child',
},
abc: {
name: 'abc',
type: 'void',
},
},
},
},
});
expect(schema.properties.current.properties.abc['x-uid']).toBeDefined();
});
test('insertAfterEnd', () => {
dn.insertAfterEnd({
name: 'abc',
});
expect(schema.toJSON()).toMatchObject({
type: 'void',
name: 'global',
'x-uid': 'global',
properties: {
current: {
type: 'void',
name: 'current',
'x-uid': 'current',
properties: {
child: {
type: 'void',
'x-uid': 'child',
},
},
},
abc: {
name: 'abc',
type: 'void',
},
},
});
expect(schema.properties.abc['x-uid']).toBeDefined();
expect(Object.keys(schema.properties)).toEqual(['current', 'abc']);
});
});
describe('move an existing node', () => {
test('insertBeforeBegin', () => {
dn.insertBeforeBegin(schema.properties.current.properties.child);
expect(Object.keys(schema.properties)).toEqual(['child', 'current']);
expect(schema.properties.current?.properties?.child).toBeUndefined();
});
test('insertBeforeBegin', () => {
dn.insertBeforeBegin({
type: 'void',
name: 'a1',
});
dn.insertBeforeBegin({
type: 'void',
name: 'a2',
});
dn.insertBeforeBegin({
type: 'void',
name: 'a3',
});
expect(Object.keys(schema.properties)).toEqual(['a1', 'a2', 'a3', 'current']);
dn.insertBeforeBegin(schema.properties.a2);
expect(Object.keys(schema.properties)).toEqual(['a1', 'a3', 'a2', 'current']);
});
test('insertAfterBegin', () => {
dn.insertBeforeBegin({
name: 'a1',
});
dn.insertAfterBegin(schema.properties.a1);
expect(Object.keys(schema.properties.current.properties)).toEqual(['a1', 'child']);
expect(schema.properties.a1).toBeUndefined();
});
test('insertBeforeEnd', () => {
dn.insertBeforeBegin({
name: 'a1',
});
dn.insertBeforeEnd(schema.properties.a1);
expect(Object.keys(schema.properties.current.properties)).toEqual(['child', 'a1']);
expect(schema.properties.a1).toBeUndefined();
});
test('insertAfterEnd', () => {
dn.insertAfterEnd(schema.properties.current.properties.child);
expect(Object.keys(schema.properties)).toEqual(['current', 'child']);
expect(schema.properties.current?.properties?.child).toBeUndefined();
});
test('insertAfterEnd', () => {
dn.insertAfterEnd({
type: 'void',
name: 'a1',
});
dn.insertAfterEnd({
type: 'void',
name: 'a2',
});
dn.insertAfterEnd({
type: 'void',
name: 'a3',
});
expect(Object.keys(schema.properties)).toEqual(['current', 'a3', 'a2', 'a1']);
dn.insertAfterEnd(schema.properties.a2);
expect(Object.keys(schema.properties)).toEqual(['current', 'a2', 'a3', 'a1']);
});
});
describe('removeIfNoChildren', () => {
test('has child nodes', () => {
dn.removeIfNoChildren(schema.properties.current);
expect(schema.properties.current).toBeDefined();
});
test('no child nodes', () => {
dn.removeIfNoChildren(schema.properties.current.properties.child);
expect(schema.properties.current?.properties?.child).toBeUndefined();
});
});
describe('remove', () => {
test('without schema', () => {
dn.remove();
expect(schema?.properties?.current).toBeUndefined();
});
test('without options', () => {
dn.remove(schema.properties.current.properties.child);
expect(schema.properties.current).toBeDefined();
expect(schema.properties.current?.properties?.child).toBeUndefined();
});
test('removeParentsIfNoChildren + breakSchema json', () => {
dn.remove(schema.properties.current.properties.child, {
removeParentsIfNoChildren: true,
breakSchema: {
'x-uid': 'global',
},
});
expect(schema?.properties?.current).toBeUndefined();
});
test('removeParentsIfNoChildren + breakSchema function', () => {
dn.remove(schema.properties.current.properties.child, {
removeParentsIfNoChildren: true,
breakSchema: (s) => s['x-uid'] === 'global',
});
expect(schema?.properties?.current).toBeUndefined();
});
});
});
describe('x-index', () => {
let dn: Designable;
let schema: Schema;
beforeEach(() => {
schema = new Schema({
type: 'void',
name: 'col1',
'x-uid': 'col1',
properties: {
block1: {
type: 'void',
'x-index': 1,
},
block2: {
type: 'void',
'x-index': 2,
},
block3: {
type: 'void',
'x-index': 3,
},
block4: {
type: 'void',
'x-index': 4,
},
block5: {
type: 'void',
'x-index': 5,
},
},
});
});
test('insertBeforeBeginOrAfterEnd', () => {
dn = createDesignable({
current: schema.properties.block2,
});
dn.insertBeforeBeginOrAfterEnd(schema.properties.block5);
expect(Object.keys(schema.properties)).toEqual(['block1', 'block5', 'block2', 'block3', 'block4']);
});
test('insertBeforeBegin', () => {
dn = createDesignable({
current: schema.properties.block2,
});
dn.insertBeforeBegin({
name: 'block0',
});
expect(Object.keys(schema.properties)).toEqual(['block1', 'block0', 'block2', 'block3', 'block4', 'block5']);
});
test('insertAfterEnd', () => {
dn = createDesignable({
current: schema.properties.block2,
});
dn.insertAfterEnd({
name: 'block0',
});
expect(Object.keys(schema.properties)).toEqual(['block1', 'block2', 'block0', 'block3', 'block4', 'block5']);
});
test('insertAfterBegin', () => {
dn = createDesignable({
current: schema,
});
dn.insertAfterBegin({
name: 'block0',
});
expect(Object.keys(schema.properties)).toEqual(['block0', 'block1', 'block2', 'block3', 'block4', 'block5']);
});
test('insertBeforeEnd', () => {
dn = createDesignable({
current: schema,
});
dn.insertBeforeEnd({
name: 'block0',
});
expect(Object.keys(schema.properties)).toEqual(['block1', 'block2', 'block3', 'block4', 'block5', 'block0']);
});
});
describe('wrap', () => {
let dn: Designable;
let schema: Schema;
const colWrap = (s) => {
return {
name: 'col12',
type: 'void',
'x-uid': 'col12',
properties: {
[s.name]: s,
},
};
};
const rowWrap = (s) => {
return {
name: 'row2',
type: 'void',
'x-uid': 'row2',
properties: {
col21: {
type: 'void',
'x-uid': 'col21',
properties: {
[s.name]: s,
},
},
},
};
};
beforeEach(() => {
schema = new Schema({
type: 'void',
name: 'grid1',
'x-uid': 'grid1',
properties: {
row1: {
type: 'void',
'x-uid': 'row1',
properties: {
col11: {
type: 'void',
'x-uid': 'col11',
properties: {
block1: {
type: 'void',
},
},
},
},
},
},
});
});
test('insertBeforeBegin', () => {
dn = createDesignable({
current: schema.properties.row1.properties.col11,
});
const s = {
type: 'void',
name: 'block2',
};
dn.insertBeforeBegin(s, {
wrap: colWrap,
});
expect(Object.keys(schema.properties.row1.properties)).toEqual(['col12', 'col11']);
expect(schema.properties.row1.properties.col12.properties.block2).toBeDefined();
});
test('insertAfterEnd', () => {
dn = createDesignable({
current: schema.properties.row1.properties.col11,
});
const s = {
type: 'void',
name: 'block2',
};
dn.insertAfterEnd(s, {
wrap: colWrap,
});
expect(Object.keys(schema.properties.row1.properties)).toEqual(['col11', 'col12']);
expect(schema.properties.row1.properties.col12.properties.block2).toBeDefined();
});
test('removeParentsIfNoChildren', () => {
const coldn = createDesignable({
current: schema.properties.row1.properties.col11,
});
const s = {
type: 'void',
name: 'block2',
};
coldn.insertAfterEnd(s, { wrap: colWrap });
const griddn = createDesignable({
current: schema,
});
griddn.insertBeforeEnd(schema.properties.row1.properties.col12.properties.block2, {
wrap: rowWrap,
removeParentsIfNoChildren: true,
});
expect(Object.keys(schema.properties.row1.properties)).toEqual(['col11']);
expect(Object.keys(schema.properties.row2.properties)).toEqual(['col21']);
expect(schema.properties.row2.properties.col21.properties.block2).toBeDefined();
});
});

View File

@ -3,6 +3,7 @@ import { uid } from '@formily/shared';
import get from 'lodash/get';
import set from 'lodash/set';
import React, { useContext } from 'react';
import { useAPIClient } from '../../api-client';
import { SchemaComponentContext } from '../context';
interface CreateDesignableProps {
@ -20,12 +21,14 @@ type Position = 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd';
interface InsertAdjacentOptions {
wrap?: (s: ISchema) => ISchema;
removeEmptyParents?: boolean;
removeParentsIfNoChildren?: boolean;
}
type BreakFn = (s: ISchema) => boolean;
interface RemoveOptions {
removeEmptyParents?: boolean;
breakComponent?: string;
removeParentsIfNoChildren?: boolean;
breakSchema?: ISchema | BreakFn;
}
const generateUid = (s: ISchema) => {
@ -76,7 +79,7 @@ export class Designable {
if (!this.events[name]) {
return;
}
this.events[name].forEach((fn) => fn.bind(this)(...args));
this.events[name].forEach((fn) => fn.bind(this)(this.current, ...args));
}
insertAdjacent(position: Position, schema: ISchema, options: InsertAdjacentOptions = {}) {
@ -92,17 +95,16 @@ export class Designable {
}
}
removeIfChildrenEmpty(schema?: Schema) {
removeIfNoChildren(schema?: Schema) {
if (!schema) {
return;
}
let s = schema;
const count = Object.keys(s.properties || {}).length;
console.log('removeIfChildrenEmpty', count, s.properties);
if (count > 0) {
return;
}
let removed;
let removed: Schema;
while (s.parent) {
removed = s.parent.removeProperty(s.name);
const count = Object.keys(s.parent.properties || {}).length;
@ -111,18 +113,42 @@ export class Designable {
}
s = s.parent;
}
return removed;
}
remove(schema?: Schema, options: RemoveOptions = {}) {
const { removeEmptyParents, breakComponent } = options;
const { removeParentsIfNoChildren, breakSchema } = options;
let s = schema || this.current;
let removed;
const matchSchema = (source: ISchema, target: ISchema) => {
if (!source || !target) {
return;
}
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
const value = target[key];
if (value !== source?.[key]) {
return false;
}
}
}
return true;
};
while (s.parent) {
removed = s.parent.removeProperty(s.name);
if (!removeEmptyParents) {
if (!removeParentsIfNoChildren) {
break;
}
if (s?.parent?.['x-component'] === breakComponent) {
if (typeof breakSchema === 'function') {
if (breakSchema(s?.parent)) {
break;
}
} else {
if (matchSchema(s?.parent, breakSchema)) {
break;
}
}
if (s?.parent?.['x-component'] === breakSchema) {
break;
}
const count = Object.keys(s.parent.properties || {}).length;
@ -131,7 +157,7 @@ export class Designable {
}
s = s.parent;
}
this.emit('afterRemove', removed);
this.emit('afterRemove', removed, options);
}
insertBeforeBeginOrAfterEnd(schema: ISchema, options: InsertAdjacentOptions = {}) {
@ -164,33 +190,38 @@ export class Designable {
if (!Schema.isSchemaInstance(this.current)) {
return;
}
const { wrap = defaultWrap, removeEmptyParents } = options;
const properties = {};
let start = false;
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
schema.parent.removeProperty(schema.name);
if (removeEmptyParents) {
this.removeIfChildrenEmpty(schema.parent);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
}
}
const properties = {};
let start = false;
let order = 0;
let newOrder = 0;
this.current.parent.mapProperties((property, key) => {
if (key === this.current.name) {
newOrder = order;
start = true;
++order;
}
property['x-index'] = order;
++order;
if (start) {
properties[key] = property;
this.current.parent.removeProperty(key);
}
});
this.prepareProperty(schema);
const wrapped = wrap(schema);
const s = this.current.parent.addProperty(wrapped.name, wrapped);
const s = this.current.parent.addProperty(wrapped.name || uid(), wrapped);
s['x-index'] = newOrder;
s.parent = this.current.parent;
this.current.parent.setProperties(properties);
this.emit('afterInsertAdjacent', 'beforeBegin', s);
this.emit('afterInsertAdjacent', 'beforeBegin', s, opts);
}
/**
@ -203,24 +234,29 @@ export class Designable {
if (!Schema.isSchemaInstance(this.current)) {
return;
}
const { wrap = defaultWrap, removeEmptyParents } = options;
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
schema.parent.removeProperty(schema.name);
if (removeEmptyParents) {
this.removeIfChildrenEmpty(schema.parent);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
}
}
const properties = {};
this.current.mapProperties((schema, key) => {
properties[key] = schema;
let order = 1;
this.current.mapProperties((s, key) => {
s['x-index'] = order;
++order;
properties[key] = s;
});
this.current.properties = {};
this.prepareProperty(schema);
const wrapped = wrap(schema);
const s = this.current.addProperty(wrapped.name, wrapped);
const s = this.current.addProperty(wrapped.name || uid(), wrapped);
s['x-index'] = 0;
s.parent = this.current;
this.current.setProperties(properties);
this.emit('afterInsertAdjacent', 'afterBegin', s);
this.emit('afterInsertAdjacent', 'afterBegin', s, opts);
}
/**
@ -233,18 +269,19 @@ export class Designable {
if (!Schema.isSchemaInstance(this.current)) {
return;
}
const { wrap = defaultWrap, removeEmptyParents } = options;
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
schema.parent.removeProperty(schema.name);
if (removeEmptyParents) {
this.removeIfChildrenEmpty(schema.parent);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
}
}
this.prepareProperty(schema);
const wrapped = wrap(schema);
const s = this.current.addProperty(wrapped.name || uid(), wrapped);
s.parent = this.current;
this.emit('afterInsertAdjacent', 'beforeEnd', s);
this.emit('afterInsertAdjacent', 'beforeEnd', s, opts);
}
/**
@ -254,22 +291,29 @@ export class Designable {
if (!Schema.isSchemaInstance(this.current)) {
return;
}
const properties = {};
let start = false;
const { wrap = defaultWrap, removeEmptyParents } = options;
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
schema.parent.removeProperty(schema.name);
console.log('insertAfterEnd', removeEmptyParents);
if (removeEmptyParents) {
this.removeIfChildrenEmpty(schema.parent);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
}
schema.parent = null;
}
let order = 0;
let newOrder = 0;
let start = false;
const properties = {};
this.current.parent.mapProperties((property, key) => {
property['x-index'] = order;
if (key === this.current.name) {
++order;
newOrder = order;
start = true;
}
++order;
if (start && key !== this.current.name) {
properties[key] = property;
this.current.parent.removeProperty(key);
@ -277,13 +321,12 @@ export class Designable {
});
this.prepareProperty(schema);
const wrapped = wrap(schema);
const s = this.current.parent.addProperty(wrapped.name || uid(), wrapped);
s.parent = this.current.parent;
s['x-index'] = newOrder;
this.current.parent.setProperties(properties);
this.emit('afterInsertAdjacent', 'afterEnd', s);
this.emit('afterInsertAdjacent', 'afterEnd', s, opts);
}
}
@ -297,7 +340,16 @@ export function useDesignable() {
const field = useField();
const fieldSchema = useFieldSchema();
const dn = createDesignable({ current: fieldSchema });
dn.on('afterInsertAdjacent', refresh);
const api = useAPIClient();
dn.on('afterInsertAdjacent', async (current, position, schema) => {
refresh();
// await api.request({
// url: `/ui_schemas:insertAdjacent/${current['x-uid']}?position=${position}`,
// method: 'post',
// data: schema.toJSON(),
// });
// console.log(current, position, schema);
});
dn.on('afterRemove', refresh);
return {
designable,