fix: the parent cannot be moved to the child schema

This commit is contained in:
chenos 2022-02-14 16:39:22 +08:00
parent 1a7f638f85
commit 441a7aecf2
2 changed files with 85 additions and 2 deletions

View File

@ -451,3 +451,41 @@ describe('wrap', () => {
expect(schema.properties.row2.properties.col21.properties.block2).toBeDefined();
});
});
describe('parentsIn', () => {
let schema: Schema;
beforeEach(() => {
schema = new Schema({
type: 'void',
name: 'page',
properties: {
menu: {
type: 'void',
'x-uid': 'menu',
properties: {
item1: {
type: 'void',
'x-uid': 'item1',
},
item2: {
type: 'void',
'x-uid': 'item2',
},
},
},
},
});
});
test('parentsIn', () => {
const dn = createDesignable({
current: schema.properties.menu.properties.item1,
});
const callback = jest.fn();
dn.on('error', callback);
dn.insertAfterBegin(schema.properties.menu);
expect(schema.properties.menu).toBeDefined();
expect(callback.mock.calls[0][1].code).toBe('parent_is_not_allowed');
});
});

View File

@ -68,20 +68,37 @@ export class Designable {
generateUid(schema);
}
on(name: 'afterInsertAdjacent' | 'afterRemove', listener: any) {
on(name: 'afterInsertAdjacent' | 'afterRemove' | 'error', listener: any) {
if (!this.events[name]) {
this.events[name] = [];
}
this.events[name].push(listener);
}
emit(name: 'afterInsertAdjacent' | 'afterRemove', ...args) {
emit(name: 'afterInsertAdjacent' | 'afterRemove' | 'error', ...args) {
if (!this.events[name]) {
return;
}
this.events[name].forEach((fn) => fn.bind(this)(this.current, ...args));
}
parentsIn(schema: Schema) {
if (!schema) {
return false;
}
if (!Schema.isSchemaInstance(schema)) {
return false;
}
let s = this.current;
while (s?.parent) {
if (s.parent === schema) {
return true;
}
s = s.parent;
}
return false;
}
insertAdjacent(position: Position, schema: ISchema, options: InsertAdjacentOptions = {}) {
switch (position) {
case 'beforeBegin':
@ -193,6 +210,13 @@ export class Designable {
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
if (this.parentsIn(schema)) {
this.emit('error', {
code: 'parent_is_not_allowed',
schema,
});
return;
}
schema.parent.removeProperty(schema.name);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
@ -237,6 +261,13 @@ export class Designable {
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
if (this.parentsIn(schema)) {
this.emit('error', {
code: 'parent_is_not_allowed',
schema,
});
return;
}
schema.parent.removeProperty(schema.name);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
@ -272,6 +303,13 @@ export class Designable {
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
if (this.parentsIn(schema)) {
this.emit('error', {
code: 'parent_is_not_allowed',
schema,
});
return;
}
schema.parent.removeProperty(schema.name);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);
@ -294,6 +332,13 @@ export class Designable {
const opts = {};
const { wrap = defaultWrap, removeParentsIfNoChildren } = options;
if (Schema.isSchemaInstance(schema)) {
if (this.parentsIn(schema)) {
this.emit('error', {
code: 'parent_is_not_allowed',
schema,
});
return;
}
schema.parent.removeProperty(schema.name);
if (removeParentsIfNoChildren) {
opts['removed'] = this.removeIfNoChildren(schema.parent);