feat: insertNewSchema (#245)
* fix: transaction error * stage * feat: insertNewSchema * feat: insertNewSchema Return Value * test * fix: insertAdjacent with root node * feat: insertAdjacent with wrap * fix: test * feat: wrap with new schema * feat: action with wrap params * feat: improve client * feat: improve client * fix: test Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
4422324980
commit
ed8c60eb85
@ -41,7 +41,7 @@ const RequestSchemaComponent: React.FC<RemoteSchemaComponentProps> = (props) =>
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<FormProvider form={form}>
|
<FormProvider form={form}>
|
||||||
<SchemaComponent memoized scope={scope} schema={schemaTransform(data?.data || {})} />;
|
<SchemaComponent memoized scope={scope} schema={schemaTransform(data?.data || {})} />
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
import { Schema } from '@formily/react';
|
||||||
|
import { splitWrapSchema } from '../useDesignable';
|
||||||
|
|
||||||
|
describe('splitWrapSchema', () => {
|
||||||
|
test('case 1', () => {
|
||||||
|
const wrap = new Schema({
|
||||||
|
'x-uid': 'aaa',
|
||||||
|
properties: {
|
||||||
|
aa: {
|
||||||
|
'x-uid': 'aa',
|
||||||
|
properties: {
|
||||||
|
a: {
|
||||||
|
'x-uid': '123',
|
||||||
|
properties: {
|
||||||
|
bbb: {
|
||||||
|
'x-uid': 'bbb',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const [schema1, schema2] = splitWrapSchema(wrap, { ['x-uid']: 'aaa' });
|
||||||
|
expect(schema1).toBeNull();
|
||||||
|
expect(schema2).toMatchObject({
|
||||||
|
'x-uid': 'aaa',
|
||||||
|
properties: {
|
||||||
|
aa: {
|
||||||
|
'x-uid': 'aa',
|
||||||
|
properties: {
|
||||||
|
a: {
|
||||||
|
'x-uid': '123',
|
||||||
|
properties: {
|
||||||
|
bbb: {
|
||||||
|
'x-uid': 'bbb',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('case 2', () => {
|
||||||
|
const wrap = new Schema({
|
||||||
|
'x-uid': 'aaa',
|
||||||
|
properties: {
|
||||||
|
aa: {
|
||||||
|
'x-uid': 'aa',
|
||||||
|
properties: {
|
||||||
|
a: {
|
||||||
|
'x-uid': '123',
|
||||||
|
properties: {
|
||||||
|
bbb: {
|
||||||
|
'x-uid': 'bbb',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const [schema1, schema2] = splitWrapSchema(wrap, { ['x-uid']: '123' });
|
||||||
|
expect(schema1).toMatchObject({
|
||||||
|
'x-uid': 'aaa',
|
||||||
|
properties: {
|
||||||
|
aa: {
|
||||||
|
'x-uid': 'aa',
|
||||||
|
properties: {},
|
||||||
|
name: 'aa',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(schema2).toMatchObject({
|
||||||
|
'x-uid': '123',
|
||||||
|
properties: {
|
||||||
|
bbb: {
|
||||||
|
'x-uid': 'bbb',
|
||||||
|
name: 'bbb',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'a',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -67,6 +67,29 @@ const matchSchema = (source: ISchema, target: ISchema) => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const splitWrapSchema = (wrapped: Schema, schema: ISchema) => {
|
||||||
|
if (wrapped['x-uid'] && wrapped['x-uid'] === schema['x-uid']) {
|
||||||
|
return [null, wrapped.toJSON()];
|
||||||
|
}
|
||||||
|
const wrappedJson: ISchema = wrapped.toJSON();
|
||||||
|
let schema1 = { ...wrappedJson, properties: {} };
|
||||||
|
let schema2 = null;
|
||||||
|
const findSchema = (properties, parent) => {
|
||||||
|
Object.keys(properties || {}).forEach((key) => {
|
||||||
|
const current = properties[key];
|
||||||
|
if (current['x-uid'] === schema['x-uid']) {
|
||||||
|
schema2 = properties[key];
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
parent.properties[key] = { ...current, properties: {} };
|
||||||
|
findSchema(current?.properties, parent.properties[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
findSchema(wrappedJson.properties, schema1);
|
||||||
|
return [schema1, schema2];
|
||||||
|
};
|
||||||
|
|
||||||
export class Designable {
|
export class Designable {
|
||||||
current: Schema;
|
current: Schema;
|
||||||
options: CreateDesignableProps;
|
options: CreateDesignableProps;
|
||||||
@ -82,12 +105,15 @@ export class Designable {
|
|||||||
if (!api) {
|
if (!api) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.on('insertAdjacent', async ({ onSuccess, current, position, schema, removed }) => {
|
this.on('insertAdjacent', async ({ onSuccess, current, position, schema, wrap, removed }) => {
|
||||||
refresh();
|
refresh();
|
||||||
await api.request({
|
await api.request({
|
||||||
url: `/uiSchemas:insertAdjacent/${current['x-uid']}?position=${position}`,
|
url: `/uiSchemas:insertAdjacent/${current['x-uid']}?position=${position}`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: schema.toJSON(),
|
data: {
|
||||||
|
schema,
|
||||||
|
wrap,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
if (removed?.['x-uid']) {
|
if (removed?.['x-uid']) {
|
||||||
await api.request({
|
await api.request({
|
||||||
@ -313,9 +339,11 @@ export class Designable {
|
|||||||
s['x-index'] = newOrder;
|
s['x-index'] = newOrder;
|
||||||
s.parent = this.current.parent;
|
s.parent = this.current.parent;
|
||||||
this.current.parent.setProperties(properties);
|
this.current.parent.setProperties(properties);
|
||||||
|
const [schema1, schema2] = splitWrapSchema(s, schema);
|
||||||
this.emit('insertAdjacent', {
|
this.emit('insertAdjacent', {
|
||||||
position: 'beforeBegin',
|
position: 'beforeBegin',
|
||||||
schema: s,
|
schema: schema2,
|
||||||
|
wrap: schema1,
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -359,9 +387,11 @@ export class Designable {
|
|||||||
s['x-index'] = 0;
|
s['x-index'] = 0;
|
||||||
s.parent = this.current;
|
s.parent = this.current;
|
||||||
this.current.setProperties(properties);
|
this.current.setProperties(properties);
|
||||||
|
const [schema1, schema2] = splitWrapSchema(s, schema);
|
||||||
this.emit('insertAdjacent', {
|
this.emit('insertAdjacent', {
|
||||||
position: 'afterBegin',
|
position: 'afterBegin',
|
||||||
schema: s,
|
schema: schema2,
|
||||||
|
wrap: schema1,
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -395,9 +425,11 @@ export class Designable {
|
|||||||
const wrapped = wrap(schema);
|
const wrapped = wrap(schema);
|
||||||
const s = this.current.addProperty(wrapped.name || uid(), wrapped);
|
const s = this.current.addProperty(wrapped.name || uid(), wrapped);
|
||||||
s.parent = this.current;
|
s.parent = this.current;
|
||||||
|
const [schema1, schema2] = splitWrapSchema(s, schema);
|
||||||
this.emit('insertAdjacent', {
|
this.emit('insertAdjacent', {
|
||||||
position: 'beforeEnd',
|
position: 'beforeEnd',
|
||||||
schema: s,
|
schema: schema2,
|
||||||
|
wrap: schema1,
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -451,9 +483,11 @@ export class Designable {
|
|||||||
s.parent = this.current.parent;
|
s.parent = this.current.parent;
|
||||||
s['x-index'] = newOrder;
|
s['x-index'] = newOrder;
|
||||||
this.current.parent.setProperties(properties);
|
this.current.parent.setProperties(properties);
|
||||||
|
const [schema1, schema2] = splitWrapSchema(s, schema);
|
||||||
this.emit('insertAdjacent', {
|
this.emit('insertAdjacent', {
|
||||||
position: 'afterEnd',
|
position: 'afterEnd',
|
||||||
schema: s,
|
schema: schema2,
|
||||||
|
wrap: schema1,
|
||||||
...opts,
|
...opts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -229,4 +229,33 @@ describe('action test', () => {
|
|||||||
const { data } = response.body;
|
const { data } = response.body;
|
||||||
expect(data.properties.e['x-uid']).toEqual('n5');
|
expect(data.properties.e['x-uid']).toEqual('n5');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('insert adjacent with bit schema', async () => {
|
||||||
|
const schema = require('./fixtures/data').default;
|
||||||
|
|
||||||
|
await app
|
||||||
|
.agent()
|
||||||
|
.resource('uiSchemas')
|
||||||
|
.insert({
|
||||||
|
values: {
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
A: {
|
||||||
|
'x-uid': 'A',
|
||||||
|
},
|
||||||
|
B: {
|
||||||
|
'x-uid': 'B',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = await app.agent().resource('uiSchemas').insertAdjacent({
|
||||||
|
resourceIndex: 'A',
|
||||||
|
position: 'afterEnd',
|
||||||
|
values: schema,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.statusCode).toEqual(200);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
6350
packages/plugin-ui-schema-storage/src/__tests__/fixtures/data.ts
Normal file
6350
packages/plugin-ui-schema-storage/src/__tests__/fixtures/data.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
|||||||
|
export default {
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
'x-uid': 'p1',
|
||||||
|
'x-component-props': {
|
||||||
|
title: "alias's",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
'x-uid': 'p2',
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
properties: {
|
||||||
|
p211: {
|
||||||
|
'x-uid': 'p211',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'i1',
|
||||||
|
'x-uid': 'i1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'i2',
|
||||||
|
'x-uid': 'i2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -338,20 +338,24 @@ describe('server hooks', () => {
|
|||||||
|
|
||||||
await uiSchemaRepository.insert(schema);
|
await uiSchemaRepository.insert(schema);
|
||||||
|
|
||||||
await uiSchemaRepository.insertAfterEnd('E', {
|
await uiSchemaRepository.insertAdjacent(
|
||||||
|
'afterEnd',
|
||||||
|
'E',
|
||||||
|
{
|
||||||
|
'x-uid': 'D',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
wrap: {
|
||||||
'x-uid': 'F',
|
'x-uid': 'F',
|
||||||
name: 'F',
|
name: 'F',
|
||||||
properties: {
|
properties: {
|
||||||
G: {
|
G: {
|
||||||
'x-uid': 'G',
|
'x-uid': 'G',
|
||||||
properties: {
|
|
||||||
D: {
|
|
||||||
'x-uid': 'D',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
const A = await uiSchemaRepository.getJsonSchema('A');
|
const A = await uiSchemaRepository.getJsonSchema('A');
|
||||||
expect(A).toEqual({
|
expect(A).toEqual({
|
||||||
|
@ -316,25 +316,24 @@ describe('server hooks', () => {
|
|||||||
|
|
||||||
await uiSchemaRepository.insert(schema);
|
await uiSchemaRepository.insert(schema);
|
||||||
|
|
||||||
await uiSchemaRepository.insertAfterEnd(
|
await uiSchemaRepository.insertAdjacent(
|
||||||
|
'afterEnd',
|
||||||
'E',
|
'E',
|
||||||
{
|
{
|
||||||
|
'x-uid': 'D',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
wrap: {
|
||||||
'x-uid': 'F',
|
'x-uid': 'F',
|
||||||
name: 'F',
|
name: 'F',
|
||||||
properties: {
|
properties: {
|
||||||
G: {
|
G: {
|
||||||
'x-uid': 'G',
|
'x-uid': 'G',
|
||||||
properties: {
|
|
||||||
D: {
|
|
||||||
'x-uid': 'D',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
removeParentsIfNoChildren: true,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(jestFn).toHaveBeenCalled();
|
expect(jestFn).toHaveBeenCalled();
|
||||||
|
@ -418,7 +418,7 @@ describe('ui_schema repository', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await repository.insert(schema);
|
await repository.insert(schema);
|
||||||
await repository.insertBeforeBegin('i1', {
|
await repository.insertAdjacent('beforeBegin', 'i1', {
|
||||||
'x-uid': 'i2',
|
'x-uid': 'i2',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -476,7 +476,7 @@ describe('ui_schema repository', () => {
|
|||||||
name: 'newNode',
|
name: 'newNode',
|
||||||
};
|
};
|
||||||
|
|
||||||
await repository.insertAfterBegin(rootUid, newNode);
|
await repository.insertAdjacent('afterBegin', rootUid, newNode);
|
||||||
const schema = await repository.getJsonSchema(rootUid);
|
const schema = await repository.getJsonSchema(rootUid);
|
||||||
expect(schema['properties']['newNode']['x-index']).toEqual(1);
|
expect(schema['properties']['newNode']['x-index']).toEqual(1);
|
||||||
expect(schema['properties'].a1['x-index']).toEqual(2);
|
expect(schema['properties'].a1['x-index']).toEqual(2);
|
||||||
@ -488,7 +488,7 @@ describe('ui_schema repository', () => {
|
|||||||
name: 'newNode',
|
name: 'newNode',
|
||||||
};
|
};
|
||||||
|
|
||||||
await repository.insertBeforeEnd(rootUid, newNode);
|
await repository.insertAdjacent('beforeEnd', rootUid, newNode);
|
||||||
const schema = await repository.getJsonSchema(rootUid);
|
const schema = await repository.getJsonSchema(rootUid);
|
||||||
expect(schema['properties']['newNode']['x-index']).toEqual(3);
|
expect(schema['properties']['newNode']['x-index']).toEqual(3);
|
||||||
expect(schema['properties'].a1['x-index']).toEqual(1);
|
expect(schema['properties'].a1['x-index']).toEqual(1);
|
||||||
@ -506,7 +506,7 @@ describe('ui_schema repository', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await repository.insertBeforeBegin(b1Node.get('x-uid') as string, newNode);
|
await repository.insertAdjacent('beforeBegin', b1Node.get('x-uid') as string, newNode);
|
||||||
|
|
||||||
const schema = await repository.getJsonSchema(rootUid);
|
const schema = await repository.getJsonSchema(rootUid);
|
||||||
expect(schema['properties']['newNode']['x-index']).toEqual(2);
|
expect(schema['properties']['newNode']['x-index']).toEqual(2);
|
||||||
@ -525,7 +525,7 @@ describe('ui_schema repository', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await repository.insertAfterEnd(a1Node.get('x-uid') as string, newNode);
|
await repository.insertAdjacent('afterEnd', a1Node.get('x-uid') as string, newNode);
|
||||||
|
|
||||||
const schema = await repository.getJsonSchema(rootUid);
|
const schema = await repository.getJsonSchema(rootUid);
|
||||||
expect(schema['properties']['newNode']['x-index']).toEqual(2);
|
expect(schema['properties']['newNode']['x-index']).toEqual(2);
|
||||||
@ -544,7 +544,7 @@ describe('ui_schema repository', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await repository.insertAfterEnd(b1Node.get('x-uid') as string, newNode);
|
await repository.insertAdjacent('afterEnd', b1Node.get('x-uid') as string, newNode);
|
||||||
|
|
||||||
const schema = await repository.getJsonSchema(rootUid);
|
const schema = await repository.getJsonSchema(rootUid);
|
||||||
expect(schema['properties']['newNode']['x-index']).toEqual(3);
|
expect(schema['properties']['newNode']['x-index']).toEqual(3);
|
||||||
@ -578,21 +578,28 @@ describe('ui_schema repository', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await repository.insertAfterBegin('n1', {
|
await repository.insertAdjacent(
|
||||||
|
'afterBegin',
|
||||||
|
'n1',
|
||||||
|
{
|
||||||
|
'x-uid': 'n4',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
wrap: {
|
||||||
name: 'f',
|
name: 'f',
|
||||||
'x-uid': 'n6',
|
'x-uid': 'n6',
|
||||||
properties: {
|
properties: {
|
||||||
g: {
|
g: {
|
||||||
'x-uid': 'n7',
|
'x-uid': 'n7',
|
||||||
properties: {
|
|
||||||
d: { 'x-uid': 'n4' },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const schema = await repository.getJsonSchema('n1');
|
const schema = await repository.getJsonSchema('n1');
|
||||||
expect(schema.properties.f.properties.g.properties.d.properties.e['x-uid']).toEqual('n5');
|
expect(schema.properties.f.properties.g.properties.d.properties.e['x-uid']).toEqual('n5');
|
||||||
|
expect(schema.properties.f.properties.g.properties.d['x-uid']).toEqual('n4');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should insertAfterBegin by node', async () => {
|
it('should insertAfterBegin by node', async () => {
|
||||||
@ -612,7 +619,7 @@ describe('ui_schema repository', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await repository.insertAfterBegin('n2', 'n4');
|
await repository.insertAdjacent('afterBegin', 'n2', 'n4');
|
||||||
const schema = await repository.getJsonSchema('n1');
|
const schema = await repository.getJsonSchema('n1');
|
||||||
expect(schema['properties'].b.properties.d['x-uid']).toEqual('n4');
|
expect(schema['properties'].b.properties.d['x-uid']).toEqual('n4');
|
||||||
});
|
});
|
||||||
@ -878,25 +885,24 @@ describe('ui_schema repository', () => {
|
|||||||
|
|
||||||
await repository.insert(schema);
|
await repository.insert(schema);
|
||||||
|
|
||||||
await repository.insertAfterBegin(
|
await repository.insertAdjacent(
|
||||||
|
'afterBegin',
|
||||||
'E',
|
'E',
|
||||||
{
|
{
|
||||||
|
'x-uid': 'D',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
wrap: {
|
||||||
'x-uid': 'F',
|
'x-uid': 'F',
|
||||||
name: 'F',
|
name: 'F',
|
||||||
properties: {
|
properties: {
|
||||||
G: {
|
G: {
|
||||||
'x-uid': 'G',
|
'x-uid': 'G',
|
||||||
properties: {
|
|
||||||
D: {
|
|
||||||
'x-uid': 'D',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
removeParentsIfNoChildren: true,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const A = await repository.getJsonSchema('A');
|
const A = await repository.getJsonSchema('A');
|
||||||
@ -962,25 +968,24 @@ describe('ui_schema repository', () => {
|
|||||||
|
|
||||||
await repository.insert(schema);
|
await repository.insert(schema);
|
||||||
|
|
||||||
await repository.insertAfterEnd(
|
await repository.insertAdjacent(
|
||||||
|
'afterEnd',
|
||||||
'E',
|
'E',
|
||||||
{
|
{
|
||||||
|
'x-uid': 'D',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
wrap: {
|
||||||
'x-uid': 'F',
|
'x-uid': 'F',
|
||||||
name: 'F',
|
name: 'F',
|
||||||
properties: {
|
properties: {
|
||||||
G: {
|
G: {
|
||||||
'x-uid': 'G',
|
'x-uid': 'G',
|
||||||
properties: {
|
|
||||||
D: {
|
|
||||||
'x-uid': 'D',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
removeParentsIfNoChildren: true,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const A = await repository.getJsonSchema('A');
|
const A = await repository.getJsonSchema('A');
|
||||||
@ -1108,4 +1113,490 @@ describe('ui_schema repository', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should insert big schema', async () => {
|
||||||
|
const schema = require('./fixtures/data').default;
|
||||||
|
|
||||||
|
console.time('test');
|
||||||
|
await repository.insertNewSchema(schema);
|
||||||
|
console.timeEnd('test');
|
||||||
|
|
||||||
|
const rootUid = schema['x-uid'];
|
||||||
|
const savedSchema = await repository.getJsonSchema(rootUid);
|
||||||
|
expect(savedSchema).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert new with insertAfterEnd', async () => {
|
||||||
|
const root = {
|
||||||
|
'x-uid': 'root',
|
||||||
|
name: 'root',
|
||||||
|
properties: {
|
||||||
|
c1: {
|
||||||
|
'x-uid': 'c1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const newNode = {
|
||||||
|
'x-uid': 'new',
|
||||||
|
name: 'new',
|
||||||
|
properties: {
|
||||||
|
nc1: {
|
||||||
|
'x-uid': 'nc1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await repository.insertNewSchema(root);
|
||||||
|
await repository.insertNewSchema(newNode);
|
||||||
|
|
||||||
|
await repository.insertAdjacent('afterEnd', 'c1', {
|
||||||
|
'x-uid': 'new',
|
||||||
|
});
|
||||||
|
|
||||||
|
const json = await repository.getJsonSchema('root');
|
||||||
|
expect(json).toEqual({
|
||||||
|
properties: {
|
||||||
|
c1: {
|
||||||
|
'x-uid': 'c1',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
new: {
|
||||||
|
properties: {
|
||||||
|
nc1: {
|
||||||
|
'x-uid': 'nc1',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'new',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'root',
|
||||||
|
'x-uid': 'root',
|
||||||
|
'x-async': false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert big schema using insertAfterEnd', async () => {
|
||||||
|
const tree = {
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
A: {
|
||||||
|
'x-uid': 'A',
|
||||||
|
},
|
||||||
|
B: {
|
||||||
|
'x-uid': 'B',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await repository.insert(tree);
|
||||||
|
const schema = require('./fixtures/data').default;
|
||||||
|
|
||||||
|
await repository.insertAdjacent('afterEnd', 'A', schema);
|
||||||
|
const rootUid = schema['x-uid'];
|
||||||
|
const savedSchema = await repository.getJsonSchema(rootUid);
|
||||||
|
expect(savedSchema).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('schemaToSingleNodes', () => {
|
||||||
|
it('should with parent Paths', async () => {
|
||||||
|
const schema = {
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
'x-uid': 'p1',
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
'x-uid': 'p2',
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
properties: {
|
||||||
|
p211: {
|
||||||
|
'x-uid': 'p211',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'i1',
|
||||||
|
'x-uid': 'i1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'i2',
|
||||||
|
'x-uid': 'i2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const nodes = UiSchemaRepository.schemaToSingleNodes(schema);
|
||||||
|
const p211Node = nodes.find((node) => node['x-uid'] === 'p211');
|
||||||
|
expect(p211Node['childOptions'].parentPath).toEqual(['p21', 'p2', 'root']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('insertAdjacent', () => {
|
||||||
|
it('should works with wrap and new schema', async () => {
|
||||||
|
const schema = {
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
'x-uid': 'p1',
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
'x-uid': 'p2',
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await repository.insert(schema);
|
||||||
|
|
||||||
|
await repository.insertAdjacent(
|
||||||
|
'afterEnd',
|
||||||
|
'p2',
|
||||||
|
{
|
||||||
|
name: 'p311',
|
||||||
|
'x-uid': 'p311',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
wrap: {
|
||||||
|
'x-uid': 'p3',
|
||||||
|
name: 'p3',
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
'x-uid': 'p31',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const root = await repository.getJsonSchema('root');
|
||||||
|
expect(root).toEqual({
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p1',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p2',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
p3: {
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
properties: {
|
||||||
|
p311: {
|
||||||
|
'x-uid': 'p311',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p31',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p3',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
'x-async': false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should works with wrap', async () => {
|
||||||
|
const schema = {
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
'x-uid': 'p1',
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
'x-uid': 'p2',
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await repository.insert(schema);
|
||||||
|
|
||||||
|
await repository.insertAdjacent(
|
||||||
|
'afterEnd',
|
||||||
|
'p1',
|
||||||
|
{
|
||||||
|
'x-uid': 'p21',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
removeParentsIfNoChildren: true,
|
||||||
|
breakRemoveOn: {
|
||||||
|
'x-uid': 'root',
|
||||||
|
},
|
||||||
|
wrap: {
|
||||||
|
'x-uid': 'p3',
|
||||||
|
name: 'p3',
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
'x-uid': 'p31',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const root = await repository.getJsonSchema('root');
|
||||||
|
expect(root).toEqual({
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p1',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
p3: {
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p31',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p3',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
'x-async': false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert newSchema using insertNewSchema', async () => {
|
||||||
|
const schema = {
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
'x-uid': 'p1',
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
'x-uid': 'p2',
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await repository.insert(schema);
|
||||||
|
|
||||||
|
await repository.insertAdjacent('afterEnd', 'p2', {
|
||||||
|
'x-uid': 'p3',
|
||||||
|
name: 'p3',
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
'x-uid': 'p31',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const root = await repository.getJsonSchema('root');
|
||||||
|
expect(root).toEqual({
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p1',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p2',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
p3: {
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
'x-uid': 'p31',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p3',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
'x-async': false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should insert oldSchema using first x-uid', async () => {
|
||||||
|
const schema = {
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
'x-uid': 'p1',
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
'x-uid': 'p2',
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await repository.insert(schema);
|
||||||
|
|
||||||
|
const insertSchema = {
|
||||||
|
'x-uid': 'p3',
|
||||||
|
name: 'p3',
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
'x-uid': 'p31',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await repository.insert(insertSchema);
|
||||||
|
await repository.insertAdjacent('afterEnd', 'p2', insertSchema);
|
||||||
|
|
||||||
|
const root = await repository.getJsonSchema('root');
|
||||||
|
expect(root).toEqual({
|
||||||
|
properties: {
|
||||||
|
p1: {
|
||||||
|
properties: {
|
||||||
|
p11: {
|
||||||
|
'x-uid': 'p11',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p1',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
properties: {
|
||||||
|
p21: {
|
||||||
|
'x-uid': 'p21',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p2',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
p3: {
|
||||||
|
properties: {
|
||||||
|
p31: {
|
||||||
|
'x-uid': 'p31',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'p3',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'root-name',
|
||||||
|
'x-uid': 'root',
|
||||||
|
'x-async': false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Context } from '@nocobase/actions';
|
import { Context } from '@nocobase/actions';
|
||||||
import UiSchemaRepository from '../repository';
|
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
|
import UiSchemaRepository from '../repository';
|
||||||
|
|
||||||
const getRepositoryFromCtx = (ctx: Context) => {
|
const getRepositoryFromCtx = (ctx: Context) => {
|
||||||
return ctx.db.getCollection('uiSchemas').repository as UiSchemaRepository;
|
return ctx.db.getCollection('uiSchemas').repository as UiSchemaRepository;
|
||||||
@ -21,10 +21,19 @@ const callRepositoryMethod = (method, paramsKey: 'resourceIndex' | 'values') =>
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function parseInsertAdjacentValues(values) {
|
||||||
|
if (lodash.has(values, 'schema')) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { schema: values, wrap: null };
|
||||||
|
}
|
||||||
|
|
||||||
export const uiSchemaActions = {
|
export const uiSchemaActions = {
|
||||||
getJsonSchema: callRepositoryMethod('getJsonSchema', 'resourceIndex'),
|
getJsonSchema: callRepositoryMethod('getJsonSchema', 'resourceIndex'),
|
||||||
getProperties: callRepositoryMethod('getProperties', 'resourceIndex'),
|
getProperties: callRepositoryMethod('getProperties', 'resourceIndex'),
|
||||||
insert: callRepositoryMethod('insert', 'values'),
|
insert: callRepositoryMethod('insert', 'values'),
|
||||||
|
insertNewSchema: callRepositoryMethod('insertNewSchema', 'values'),
|
||||||
remove: callRepositoryMethod('remove', 'resourceIndex'),
|
remove: callRepositoryMethod('remove', 'resourceIndex'),
|
||||||
patch: callRepositoryMethod('patch', 'values'),
|
patch: callRepositoryMethod('patch', 'values'),
|
||||||
clearAncestor: callRepositoryMethod('clearAncestor', 'resourceIndex'),
|
clearAncestor: callRepositoryMethod('clearAncestor', 'resourceIndex'),
|
||||||
@ -33,9 +42,12 @@ export const uiSchemaActions = {
|
|||||||
const { resourceIndex, position, values, removeParentsIfNoChildren, breakRemoveOn } = ctx.action.params;
|
const { resourceIndex, position, values, removeParentsIfNoChildren, breakRemoveOn } = ctx.action.params;
|
||||||
const repository = getRepositoryFromCtx(ctx);
|
const repository = getRepositoryFromCtx(ctx);
|
||||||
|
|
||||||
ctx.body = await repository.insertAdjacent(position, resourceIndex, values, {
|
const { schema, wrap } = parseInsertAdjacentValues(values);
|
||||||
|
|
||||||
|
ctx.body = await repository.insertAdjacent(position, resourceIndex, schema, {
|
||||||
removeParentsIfNoChildren,
|
removeParentsIfNoChildren,
|
||||||
breakRemoveOn,
|
breakRemoveOn,
|
||||||
|
wrap,
|
||||||
});
|
});
|
||||||
|
|
||||||
await next();
|
await next();
|
||||||
@ -51,9 +63,12 @@ function insertPositionActionBuilder(position: 'beforeBegin' | 'afterBegin' | 'b
|
|||||||
return async function (ctx: Context, next) {
|
return async function (ctx: Context, next) {
|
||||||
const { resourceIndex, values, removeParentsIfNoChildren, breakRemoveOn } = ctx.action.params;
|
const { resourceIndex, values, removeParentsIfNoChildren, breakRemoveOn } = ctx.action.params;
|
||||||
const repository = getRepositoryFromCtx(ctx);
|
const repository = getRepositoryFromCtx(ctx);
|
||||||
ctx.body = await repository.insertAdjacent(position, resourceIndex, values, {
|
const { schema, wrap } = parseInsertAdjacentValues(values);
|
||||||
|
|
||||||
|
ctx.body = await repository.insertAdjacent(position, resourceIndex, schema, {
|
||||||
removeParentsIfNoChildren,
|
removeParentsIfNoChildren,
|
||||||
breakRemoveOn,
|
breakRemoveOn,
|
||||||
|
wrap,
|
||||||
});
|
});
|
||||||
await next();
|
await next();
|
||||||
};
|
};
|
||||||
|
@ -4,8 +4,10 @@ export interface TargetPosition {
|
|||||||
}
|
}
|
||||||
export interface ChildOptions {
|
export interface ChildOptions {
|
||||||
parentUid: string;
|
parentUid: string;
|
||||||
|
parentPath?: string[];
|
||||||
type: string;
|
type: string;
|
||||||
position?: 'first' | 'last' | TargetPosition;
|
position?: 'first' | 'last' | TargetPosition;
|
||||||
|
sort?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SchemaNode {
|
export interface SchemaNode {
|
||||||
|
@ -18,7 +18,9 @@ export interface removeParentOptions extends TransactionAble {
|
|||||||
breakRemoveOn?: BreakRemoveOnType;
|
breakRemoveOn?: BreakRemoveOnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InsertAdjacentOptions extends removeParentOptions {}
|
interface InsertAdjacentOptions extends removeParentOptions {
|
||||||
|
wrap?: any;
|
||||||
|
}
|
||||||
|
|
||||||
const nodeKeys = ['properties', 'definitions', 'patternProperties', 'additionalProperties', 'items'];
|
const nodeKeys = ['properties', 'definitions', 'patternProperties', 'additionalProperties', 'items'];
|
||||||
|
|
||||||
@ -111,31 +113,30 @@ export class UiSchemaRepository extends Repository {
|
|||||||
|
|
||||||
for (const nodeKey of nodeKeys) {
|
for (const nodeKey of nodeKeys) {
|
||||||
const nodeProperty = lodash.get(node, nodeKey);
|
const nodeProperty = lodash.get(node, nodeKey);
|
||||||
|
const childNodeChildOptions = {
|
||||||
|
parentUid: node['x-uid'],
|
||||||
|
parentPath: [node['x-uid'], ...lodash.get(childOptions, 'parentPath', [])],
|
||||||
|
type: nodeKey,
|
||||||
|
};
|
||||||
|
|
||||||
// array items
|
// array items
|
||||||
if (nodeKey === 'items' && nodeProperty) {
|
if (nodeKey === 'items' && nodeProperty) {
|
||||||
const handleItems = lodash.isArray(nodeProperty) ? nodeProperty : [nodeProperty];
|
const handleItems = lodash.isArray(nodeProperty) ? nodeProperty : [nodeProperty];
|
||||||
for (const item of handleItems) {
|
for (const [i, item] of handleItems.entries()) {
|
||||||
carry = this.schemaToSingleNodes(item, carry, {
|
carry = this.schemaToSingleNodes(item, carry, { ...childNodeChildOptions, sort: i + 1 });
|
||||||
parentUid: node['x-uid'],
|
|
||||||
type: nodeKey,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if (lodash.isPlainObject(nodeProperty)) {
|
} else if (lodash.isPlainObject(nodeProperty)) {
|
||||||
const subNodeNames = lodash.keys(lodash.get(node, nodeKey));
|
const subNodeNames = lodash.keys(lodash.get(node, nodeKey));
|
||||||
|
|
||||||
delete node[nodeKey];
|
delete node[nodeKey];
|
||||||
|
|
||||||
for (const subNodeName of subNodeNames) {
|
for (const [i, subNodeName] of subNodeNames.entries()) {
|
||||||
const subSchema = {
|
const subSchema = {
|
||||||
name: subNodeName,
|
name: subNodeName,
|
||||||
...lodash.get(nodeProperty, subNodeName),
|
...lodash.get(nodeProperty, subNodeName),
|
||||||
};
|
};
|
||||||
|
|
||||||
carry = this.schemaToSingleNodes(subSchema, carry, {
|
carry = this.schemaToSingleNodes(subSchema, carry, { ...childNodeChildOptions, sort: i + 1 });
|
||||||
parentUid: node['x-uid'],
|
|
||||||
type: nodeKey,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,11 +539,32 @@ export class UiSchemaRepository extends Repository {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const insertedNodes = await this.insertNodes(nodes, options);
|
const insertedNodes = await this.insertNodes(nodes, options);
|
||||||
|
|
||||||
return await this.getJsonSchema(insertedNodes[0].get('x-uid'), {
|
return await this.getJsonSchema(insertedNodes[0].get('x-uid'), {
|
||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async schemaExists(schema: any, options?: TransactionAble): Promise<boolean> {
|
||||||
|
if (lodash.isObject(schema) && !schema['x-uid']) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { transaction } = options;
|
||||||
|
const result = await this.database.sequelize.query(
|
||||||
|
this.sqlAdapter(`select "x-uid" from ${this.uiSchemasTableName} where "x-uid" = :uid`),
|
||||||
|
{
|
||||||
|
type: 'SELECT',
|
||||||
|
replacements: {
|
||||||
|
uid: lodash.isString(schema) ? schema : schema['x-uid'],
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
@transaction()
|
@transaction()
|
||||||
async insertAdjacent(
|
async insertAdjacent(
|
||||||
position: 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd',
|
position: 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd',
|
||||||
@ -550,26 +572,57 @@ export class UiSchemaRepository extends Repository {
|
|||||||
schema: any,
|
schema: any,
|
||||||
options?: InsertAdjacentOptions,
|
options?: InsertAdjacentOptions,
|
||||||
) {
|
) {
|
||||||
|
const { transaction } = options;
|
||||||
|
|
||||||
|
if (options.wrap) {
|
||||||
|
// insert wrap schema using insertNewSchema
|
||||||
|
const wrapSchemaNodes = await this.insertNewSchema(options.wrap, {
|
||||||
|
transaction,
|
||||||
|
returnNode: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const lastWrapNode = wrapSchemaNodes[wrapSchemaNodes.length - 1];
|
||||||
|
|
||||||
|
// insert schema into wrap schema
|
||||||
|
await this.insertAdjacent('afterBegin', lastWrapNode['x-uid'], schema, lodash.omit(options, 'wrap'));
|
||||||
|
|
||||||
|
schema = wrapSchemaNodes[0]['x-uid'];
|
||||||
|
|
||||||
|
options.removeParentsIfNoChildren = false;
|
||||||
|
} else {
|
||||||
|
const schemaExists = await this.schemaExists(schema, { transaction });
|
||||||
|
if (schemaExists) {
|
||||||
|
schema = lodash.isString(schema) ? schema : schema['x-uid'];
|
||||||
|
} else {
|
||||||
|
const insertedSchema = await this.insertNewSchema(schema, {
|
||||||
|
transaction,
|
||||||
|
returnNode: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
schema = insertedSchema[0]['x-uid'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await this[`insert${lodash.upperFirst(position)}`](target, schema, options);
|
return await this[`insert${lodash.upperFirst(position)}`](target, schema, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@transaction()
|
@transaction()
|
||||||
async insertAfterBegin(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
protected async insertAfterBegin(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
||||||
return await this.insertInner(targetUid, schema, 'first', options);
|
return await this.insertInner(targetUid, schema, 'first', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@transaction()
|
@transaction()
|
||||||
async insertBeforeEnd(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
protected async insertBeforeEnd(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
||||||
return await this.insertInner(targetUid, schema, 'last', options);
|
return await this.insertInner(targetUid, schema, 'last', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@transaction()
|
@transaction()
|
||||||
async insertBeforeBegin(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
protected async insertBeforeBegin(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
||||||
return await this.insertBeside(targetUid, schema, 'before', options);
|
return await this.insertBeside(targetUid, schema, 'before', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@transaction()
|
@transaction()
|
||||||
async insertAfterEnd(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
protected async insertAfterEnd(targetUid: string, schema: any, options?: InsertAdjacentOptions) {
|
||||||
return await this.insertBeside(targetUid, schema, 'after', options);
|
return await this.insertBeside(targetUid, schema, 'after', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,6 +653,70 @@ export class UiSchemaRepository extends Repository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@transaction()
|
||||||
|
async insertNewSchema(
|
||||||
|
schema: any,
|
||||||
|
options?: TransactionAble & {
|
||||||
|
returnNode?: boolean;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const { transaction } = options;
|
||||||
|
|
||||||
|
const nodes = UiSchemaRepository.schemaToSingleNodes(schema);
|
||||||
|
// insert schema fist
|
||||||
|
await this.database.sequelize.query(
|
||||||
|
this.sqlAdapter(
|
||||||
|
`INSERT INTO ${this.uiSchemasTableName} ("x-uid", "name", "schema") VALUES ${nodes
|
||||||
|
.map((n) => '(?)')
|
||||||
|
.join(',')};`,
|
||||||
|
),
|
||||||
|
{
|
||||||
|
replacements: lodash.cloneDeep(nodes).map((node) => {
|
||||||
|
const { uid, name } = this.prepareSingleNodeForInsert(node);
|
||||||
|
return [uid, name, JSON.stringify(node)];
|
||||||
|
}),
|
||||||
|
type: 'insert',
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const treePathData: Array<any> = lodash.cloneDeep(nodes).reduce((carry, item) => {
|
||||||
|
const { uid, childOptions, async } = this.prepareSingleNodeForInsert(item);
|
||||||
|
|
||||||
|
return [
|
||||||
|
...carry,
|
||||||
|
// self reference
|
||||||
|
[uid, uid, 0, childOptions?.type || null, async, null],
|
||||||
|
// parent references
|
||||||
|
...lodash.get(childOptions, 'parentPath', []).map((parentUid, index) => {
|
||||||
|
return [parentUid, uid, index + 1, null, null, childOptions.sort];
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// insert tree path
|
||||||
|
await this.database.sequelize.query(
|
||||||
|
this.sqlAdapter(
|
||||||
|
`INSERT INTO ${
|
||||||
|
this.uiSchemaTreePathTableName
|
||||||
|
} (ancestor, descendant, depth, type, async, sort) VALUES ${treePathData.map((item) => '(?)').join(',')}`,
|
||||||
|
),
|
||||||
|
{
|
||||||
|
replacements: treePathData,
|
||||||
|
type: 'insert',
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (options?.returnNode) {
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getJsonSchema(nodes[0]['x-uid'], {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async insertSchemaRecord(name, uid, schema, transaction) {
|
private async insertSchemaRecord(name, uid, schema, transaction) {
|
||||||
const serverHooks = schema['x-server-hooks'] || [];
|
const serverHooks = schema['x-server-hooks'] || [];
|
||||||
|
|
||||||
@ -619,11 +736,7 @@ export class UiSchemaRepository extends Repository {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
async insertSingleNode(schema: SchemaNode, options: TransactionAble & removeParentOptions) {
|
private prepareSingleNodeForInsert(schema: SchemaNode) {
|
||||||
const { transaction } = options;
|
|
||||||
|
|
||||||
const db = this.database;
|
|
||||||
|
|
||||||
const uid = schema['x-uid'];
|
const uid = schema['x-uid'];
|
||||||
const name = schema['name'];
|
const name = schema['name'];
|
||||||
const async = lodash.get(schema, 'x-async', false);
|
const async = lodash.get(schema, 'x-async', false);
|
||||||
@ -634,6 +747,15 @@ export class UiSchemaRepository extends Repository {
|
|||||||
delete schema['name'];
|
delete schema['name'];
|
||||||
delete schema['childOptions'];
|
delete schema['childOptions'];
|
||||||
|
|
||||||
|
return { uid, name, async, childOptions };
|
||||||
|
}
|
||||||
|
|
||||||
|
async insertSingleNode(schema: SchemaNode, options: TransactionAble & removeParentOptions) {
|
||||||
|
const { transaction } = options;
|
||||||
|
|
||||||
|
const db = this.database;
|
||||||
|
|
||||||
|
const { uid, name, async, childOptions } = this.prepareSingleNodeForInsert(schema);
|
||||||
let savedNode;
|
let savedNode;
|
||||||
|
|
||||||
// check node exists or not
|
// check node exists or not
|
||||||
@ -656,18 +778,9 @@ export class UiSchemaRepository extends Repository {
|
|||||||
const oldParentUid = await this.findParentUid(uid, transaction);
|
const oldParentUid = await this.findParentUid(uid, transaction);
|
||||||
const parentUid = childOptions.parentUid;
|
const parentUid = childOptions.parentUid;
|
||||||
|
|
||||||
const isTreeQuery = await db.sequelize.query(
|
const childrenCount = await this.childrenCount(uid, transaction);
|
||||||
`SELECT COUNT(*) as childrenCount from ${treeTable} WHERE ancestor = :ancestor AND descendant != ancestor`,
|
|
||||||
{
|
|
||||||
type: 'SELECT',
|
|
||||||
replacements: {
|
|
||||||
ancestor: uid,
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const isTree = isTreeQuery[0]['childrenCount'];
|
const isTree = childrenCount > 0;
|
||||||
|
|
||||||
// if node is a tree root move tree to new path
|
// if node is a tree root move tree to new path
|
||||||
if (isTree) {
|
if (isTree) {
|
||||||
@ -692,6 +805,19 @@ export class UiSchemaRepository extends Repository {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update type
|
||||||
|
await db.sequelize.query(
|
||||||
|
`UPDATE ${treeTable} SET type = :type WHERE depth = 0 AND ancestor = :uid AND descendant = :uid`,
|
||||||
|
{
|
||||||
|
type: 'update',
|
||||||
|
transaction,
|
||||||
|
replacements: {
|
||||||
|
type: childOptions.type,
|
||||||
|
uid,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
if (!isTree) {
|
if (!isTree) {
|
||||||
if (existsNode) {
|
if (existsNode) {
|
||||||
// remove old path
|
// remove old path
|
||||||
|
Loading…
Reference in New Issue
Block a user