@nocobase/plugin-ui-schema-storage 0.7.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/esm/actions/ui-schema-action.d.ts +16 -0
- package/esm/actions/ui-schema-action.js +100 -0
- package/esm/actions/ui-schema-action.js.map +1 -0
- package/esm/collections/uiSchemaServerHooks.d.ts +3 -0
- package/esm/collections/uiSchemaServerHooks.js +27 -0
- package/esm/collections/uiSchemaServerHooks.js.map +1 -0
- package/esm/collections/uiSchemaTemplates.d.ts +2 -0
- package/esm/collections/uiSchemaTemplates.js +39 -0
- package/esm/collections/uiSchemaTemplates.js.map +1 -0
- package/esm/collections/uiSchemaTreePath.d.ts +3 -0
- package/esm/collections/uiSchemaTreePath.js +42 -0
- package/esm/collections/uiSchemaTreePath.js.map +1 -0
- package/esm/collections/uiSchemas.d.ts +3 -0
- package/esm/collections/uiSchemas.js +32 -0
- package/esm/collections/uiSchemas.js.map +1 -0
- package/esm/dao/ui_schema_dao.d.ts +4 -0
- package/esm/dao/ui_schema_dao.js +6 -0
- package/esm/dao/ui_schema_dao.js.map +1 -0
- package/esm/dao/ui_schema_node_dao.d.ts +22 -0
- package/esm/dao/ui_schema_node_dao.js +6 -0
- package/esm/dao/ui_schema_node_dao.js.map +1 -0
- package/esm/helper.d.ts +0 -0
- package/esm/helper.js +1 -0
- package/esm/helper.js.map +1 -0
- package/esm/index.d.ts +3 -0
- package/esm/index.js +4 -0
- package/esm/index.js.map +1 -0
- package/esm/model.d.ts +6 -0
- package/esm/model.js +9 -0
- package/esm/model.js.map +1 -0
- package/esm/repository.d.ts +72 -0
- package/esm/repository.js +858 -0
- package/esm/repository.js.map +1 -0
- package/esm/server-hooks/hooks/bind-menu-to-role.d.ts +5 -0
- package/esm/server-hooks/hooks/bind-menu-to-role.js +26 -0
- package/esm/server-hooks/hooks/bind-menu-to-role.js.map +1 -0
- package/esm/server-hooks/hooks/factory.d.ts +6 -0
- package/esm/server-hooks/hooks/factory.js +8 -0
- package/esm/server-hooks/hooks/factory.js.map +1 -0
- package/esm/server-hooks/hooks/index.d.ts +6 -0
- package/esm/server-hooks/hooks/index.js +12 -0
- package/esm/server-hooks/hooks/index.js.map +1 -0
- package/esm/server-hooks/hooks/remove-parents-if-no-children.d.ts +6 -0
- package/esm/server-hooks/hooks/remove-parents-if-no-children.js +21 -0
- package/esm/server-hooks/hooks/remove-parents-if-no-children.js.map +1 -0
- package/esm/server-hooks/hooks/remove-schema.d.ts +6 -0
- package/esm/server-hooks/hooks/remove-schema.js +29 -0
- package/esm/server-hooks/hooks/remove-schema.js.map +1 -0
- package/esm/server-hooks/index.d.ts +23 -0
- package/esm/server-hooks/index.js +133 -0
- package/esm/server-hooks/index.js.map +1 -0
- package/esm/server-hooks/model.d.ts +3 -0
- package/esm/server-hooks/model.js +4 -0
- package/esm/server-hooks/model.js.map +1 -0
- package/esm/server.d.ts +10 -0
- package/esm/server.js +78 -0
- package/esm/server.js.map +1 -0
- package/lib/actions/ui-schema-action.d.ts +16 -0
- package/lib/actions/ui-schema-action.js +106 -0
- package/lib/actions/ui-schema-action.js.map +1 -0
- package/lib/collections/uiSchemaServerHooks.d.ts +3 -0
- package/lib/collections/uiSchemaServerHooks.js +29 -0
- package/lib/collections/uiSchemaServerHooks.js.map +1 -0
- package/lib/collections/uiSchemaTemplates.d.ts +2 -0
- package/lib/collections/uiSchemaTemplates.js +41 -0
- package/lib/collections/uiSchemaTemplates.js.map +1 -0
- package/lib/collections/uiSchemaTreePath.d.ts +3 -0
- package/lib/collections/uiSchemaTreePath.js +44 -0
- package/lib/collections/uiSchemaTreePath.js.map +1 -0
- package/lib/collections/uiSchemas.d.ts +3 -0
- package/lib/collections/uiSchemas.js +34 -0
- package/lib/collections/uiSchemas.js.map +1 -0
- package/lib/dao/ui_schema_dao.d.ts +4 -0
- package/lib/dao/ui_schema_dao.js +10 -0
- package/lib/dao/ui_schema_dao.js.map +1 -0
- package/lib/dao/ui_schema_node_dao.d.ts +22 -0
- package/lib/dao/ui_schema_node_dao.js +10 -0
- package/lib/dao/ui_schema_node_dao.js.map +1 -0
- package/lib/helper.d.ts +0 -0
- package/lib/helper.js +1 -0
- package/lib/helper.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +21 -0
- package/lib/index.js.map +1 -0
- package/lib/model.d.ts +6 -0
- package/lib/model.js +12 -0
- package/lib/model.js.map +1 -0
- package/lib/repository.d.ts +72 -0
- package/lib/repository.js +865 -0
- package/lib/repository.js.map +1 -0
- package/lib/server-hooks/hooks/bind-menu-to-role.d.ts +5 -0
- package/lib/server-hooks/hooks/bind-menu-to-role.js +30 -0
- package/lib/server-hooks/hooks/bind-menu-to-role.js.map +1 -0
- package/lib/server-hooks/hooks/factory.d.ts +6 -0
- package/lib/server-hooks/hooks/factory.js +12 -0
- package/lib/server-hooks/hooks/factory.js.map +1 -0
- package/lib/server-hooks/hooks/index.d.ts +6 -0
- package/lib/server-hooks/hooks/index.js +15 -0
- package/lib/server-hooks/hooks/index.js.map +1 -0
- package/lib/server-hooks/hooks/remove-parents-if-no-children.d.ts +6 -0
- package/lib/server-hooks/hooks/remove-parents-if-no-children.js +25 -0
- package/lib/server-hooks/hooks/remove-parents-if-no-children.js.map +1 -0
- package/lib/server-hooks/hooks/remove-schema.d.ts +6 -0
- package/lib/server-hooks/hooks/remove-schema.js +33 -0
- package/lib/server-hooks/hooks/remove-schema.js.map +1 -0
- package/lib/server-hooks/index.d.ts +23 -0
- package/lib/server-hooks/index.js +137 -0
- package/lib/server-hooks/index.js.map +1 -0
- package/lib/server-hooks/model.d.ts +3 -0
- package/lib/server-hooks/model.js +8 -0
- package/lib/server-hooks/model.js.map +1 -0
- package/lib/server.d.ts +10 -0
- package/lib/server.js +85 -0
- package/lib/server.js.map +1 -0
- package/package.json +22 -0
- package/tsconfig.build.json +9 -0
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
import { Repository } from '@nocobase/database';
|
|
17
|
+
import { uid } from '@nocobase/utils';
|
|
18
|
+
import lodash from 'lodash';
|
|
19
|
+
const nodeKeys = ['properties', 'definitions', 'patternProperties', 'additionalProperties', 'items'];
|
|
20
|
+
function transaction(transactionAbleArgPosition) {
|
|
21
|
+
return (target, propertyKey, descriptor) => {
|
|
22
|
+
const originalMethod = descriptor.value;
|
|
23
|
+
descriptor.value = function (...args) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
if (!lodash.isNumber(transactionAbleArgPosition)) {
|
|
26
|
+
transactionAbleArgPosition = originalMethod.length - 1;
|
|
27
|
+
}
|
|
28
|
+
let transaction = lodash.get(args, [transactionAbleArgPosition, 'transaction']);
|
|
29
|
+
let handleTransaction = false;
|
|
30
|
+
if (!transaction) {
|
|
31
|
+
transaction = yield this.database.sequelize.transaction();
|
|
32
|
+
handleTransaction = true;
|
|
33
|
+
lodash.set(args, transactionAbleArgPosition, Object.assign(Object.assign({}, lodash.get(args, transactionAbleArgPosition, {})), { transaction }));
|
|
34
|
+
}
|
|
35
|
+
if (handleTransaction) {
|
|
36
|
+
try {
|
|
37
|
+
const results = yield originalMethod.apply(this, args);
|
|
38
|
+
yield transaction.commit();
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
yield transaction.rollback();
|
|
43
|
+
throw e;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
return yield originalMethod.apply(this, args);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
return descriptor;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export class UiSchemaRepository extends Repository {
|
|
55
|
+
tableNameAdapter(tableName) {
|
|
56
|
+
if (this.database.sequelize.getDialect() === 'postgres') {
|
|
57
|
+
return `"${tableName}"`;
|
|
58
|
+
}
|
|
59
|
+
return tableName;
|
|
60
|
+
}
|
|
61
|
+
get uiSchemasTableName() {
|
|
62
|
+
return this.tableNameAdapter(this.model.tableName);
|
|
63
|
+
}
|
|
64
|
+
get uiSchemaTreePathTableName() {
|
|
65
|
+
const model = this.database.getCollection('uiSchemaTreePath').model;
|
|
66
|
+
return this.tableNameAdapter(model.tableName);
|
|
67
|
+
}
|
|
68
|
+
sqlAdapter(sql) {
|
|
69
|
+
if (this.database.sequelize.getDialect() === 'mysql') {
|
|
70
|
+
return lodash.replace(sql, /"/g, '`');
|
|
71
|
+
}
|
|
72
|
+
return sql;
|
|
73
|
+
}
|
|
74
|
+
static schemaToSingleNodes(schema, carry = [], childOptions = null) {
|
|
75
|
+
const node = lodash.cloneDeep(lodash.isString(schema)
|
|
76
|
+
? {
|
|
77
|
+
'x-uid': schema,
|
|
78
|
+
}
|
|
79
|
+
: schema);
|
|
80
|
+
if (!lodash.get(node, 'name')) {
|
|
81
|
+
node.name = uid();
|
|
82
|
+
}
|
|
83
|
+
if (!lodash.get(node, 'x-uid')) {
|
|
84
|
+
node['x-uid'] = uid();
|
|
85
|
+
}
|
|
86
|
+
if (childOptions) {
|
|
87
|
+
node.childOptions = childOptions;
|
|
88
|
+
}
|
|
89
|
+
carry.push(node);
|
|
90
|
+
for (const nodeKey of nodeKeys) {
|
|
91
|
+
const nodeProperty = lodash.get(node, nodeKey);
|
|
92
|
+
const childNodeChildOptions = {
|
|
93
|
+
parentUid: node['x-uid'],
|
|
94
|
+
parentPath: [node['x-uid'], ...lodash.get(childOptions, 'parentPath', [])],
|
|
95
|
+
type: nodeKey,
|
|
96
|
+
};
|
|
97
|
+
// array items
|
|
98
|
+
if (nodeKey === 'items' && nodeProperty) {
|
|
99
|
+
const handleItems = lodash.isArray(nodeProperty) ? nodeProperty : [nodeProperty];
|
|
100
|
+
for (const [i, item] of handleItems.entries()) {
|
|
101
|
+
carry = this.schemaToSingleNodes(item, carry, Object.assign(Object.assign({}, childNodeChildOptions), { sort: i + 1 }));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else if (lodash.isPlainObject(nodeProperty)) {
|
|
105
|
+
const subNodeNames = lodash.keys(lodash.get(node, nodeKey));
|
|
106
|
+
delete node[nodeKey];
|
|
107
|
+
for (const [i, subNodeName] of subNodeNames.entries()) {
|
|
108
|
+
const subSchema = Object.assign({ name: subNodeName }, lodash.get(nodeProperty, subNodeName));
|
|
109
|
+
carry = this.schemaToSingleNodes(subSchema, carry, Object.assign(Object.assign({}, childNodeChildOptions), { sort: i + 1 }));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return carry;
|
|
114
|
+
}
|
|
115
|
+
getProperties(uid, options = {}) {
|
|
116
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
const { transaction } = options;
|
|
118
|
+
const db = this.database;
|
|
119
|
+
const rawSql = `
|
|
120
|
+
SELECT "SchemaTable"."x-uid" as "x-uid", "SchemaTable"."name" as "name", "SchemaTable"."schema" as "schema",
|
|
121
|
+
TreePath.depth as depth,
|
|
122
|
+
NodeInfo.type as type, NodeInfo.async as async, ParentPath.ancestor as parent, ParentPath.sort as sort
|
|
123
|
+
FROM ${this.uiSchemaTreePathTableName} as TreePath
|
|
124
|
+
LEFT JOIN ${this.uiSchemasTableName} as "SchemaTable" ON "SchemaTable"."x-uid" = TreePath.descendant
|
|
125
|
+
LEFT JOIN ${this.uiSchemaTreePathTableName} as NodeInfo ON NodeInfo.descendant = "SchemaTable"."x-uid" and NodeInfo.descendant = NodeInfo.ancestor and NodeInfo.depth = 0
|
|
126
|
+
LEFT JOIN ${this.uiSchemaTreePathTableName} as ParentPath ON (ParentPath.descendant = "SchemaTable"."x-uid" AND ParentPath.depth = 1)
|
|
127
|
+
WHERE TreePath.ancestor = :ancestor AND (NodeInfo.async = false or TreePath.depth = 1)`;
|
|
128
|
+
const nodes = yield db.sequelize.query(this.sqlAdapter(rawSql), {
|
|
129
|
+
replacements: {
|
|
130
|
+
ancestor: uid,
|
|
131
|
+
},
|
|
132
|
+
transaction,
|
|
133
|
+
});
|
|
134
|
+
if (nodes[0].length == 0) {
|
|
135
|
+
return {};
|
|
136
|
+
}
|
|
137
|
+
const schema = this.nodesToSchema(nodes[0], uid);
|
|
138
|
+
return lodash.pick(schema, ['type', 'properties']);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
getJsonSchema(uid, options) {
|
|
142
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
const db = this.database;
|
|
144
|
+
const treeTable = this.uiSchemaTreePathTableName;
|
|
145
|
+
const rawSql = `
|
|
146
|
+
SELECT "SchemaTable"."x-uid" as "x-uid", "SchemaTable"."name" as name, "SchemaTable"."schema" as "schema" ,
|
|
147
|
+
TreePath.depth as depth,
|
|
148
|
+
NodeInfo.type as type, NodeInfo.async as async, ParentPath.ancestor as parent, ParentPath.sort as sort
|
|
149
|
+
FROM ${treeTable} as TreePath
|
|
150
|
+
LEFT JOIN ${this.uiSchemasTableName} as "SchemaTable" ON "SchemaTable"."x-uid" = TreePath.descendant
|
|
151
|
+
LEFT JOIN ${treeTable} as NodeInfo ON NodeInfo.descendant = "SchemaTable"."x-uid" and NodeInfo.descendant = NodeInfo.ancestor and NodeInfo.depth = 0
|
|
152
|
+
LEFT JOIN ${treeTable} as ParentPath ON (ParentPath.descendant = "SchemaTable"."x-uid" AND ParentPath.depth = 1)
|
|
153
|
+
WHERE TreePath.ancestor = :ancestor ${(options === null || options === void 0 ? void 0 : options.includeAsyncNode) ? '' : 'AND (NodeInfo.async != true )'}
|
|
154
|
+
`;
|
|
155
|
+
const nodes = yield db.sequelize.query(this.sqlAdapter(rawSql), {
|
|
156
|
+
replacements: {
|
|
157
|
+
ancestor: uid,
|
|
158
|
+
},
|
|
159
|
+
transaction: options === null || options === void 0 ? void 0 : options.transaction,
|
|
160
|
+
});
|
|
161
|
+
if (nodes[0].length == 0) {
|
|
162
|
+
return {};
|
|
163
|
+
}
|
|
164
|
+
const schema = this.nodesToSchema(nodes[0], uid);
|
|
165
|
+
return schema;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
ignoreSchemaProperties(schemaProperties) {
|
|
169
|
+
return lodash.omit(schemaProperties, nodeKeys);
|
|
170
|
+
}
|
|
171
|
+
nodesToSchema(nodes, rootUid) {
|
|
172
|
+
const nodeAttributeSanitize = (node) => {
|
|
173
|
+
const schema = Object.assign(Object.assign(Object.assign({}, this.ignoreSchemaProperties(lodash.isPlainObject(node.schema) ? node.schema : JSON.parse(node.schema))), lodash.pick(node, [...nodeKeys, 'name'])), { ['x-uid']: node['x-uid'], ['x-async']: !!node.async });
|
|
174
|
+
if (lodash.isNumber(node.sort)) {
|
|
175
|
+
schema['x-index'] = node.sort;
|
|
176
|
+
}
|
|
177
|
+
return schema;
|
|
178
|
+
};
|
|
179
|
+
const buildTree = (rootNode) => {
|
|
180
|
+
const children = nodes.filter((node) => node.parent == rootNode['x-uid']);
|
|
181
|
+
if (children.length > 0) {
|
|
182
|
+
const childrenGroupByType = lodash.groupBy(children, 'type');
|
|
183
|
+
for (const childType of Object.keys(childrenGroupByType)) {
|
|
184
|
+
const properties = childrenGroupByType[childType]
|
|
185
|
+
.map((child) => buildTree(child))
|
|
186
|
+
.sort((a, b) => a['x-index'] - b['x-index']);
|
|
187
|
+
rootNode[childType] =
|
|
188
|
+
childType == 'items'
|
|
189
|
+
? properties.length == 1
|
|
190
|
+
? properties[0]
|
|
191
|
+
: properties
|
|
192
|
+
: properties.reduce((carry, item) => {
|
|
193
|
+
carry[item.name] = item;
|
|
194
|
+
delete item['name'];
|
|
195
|
+
return carry;
|
|
196
|
+
}, {});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return nodeAttributeSanitize(rootNode);
|
|
200
|
+
};
|
|
201
|
+
return buildTree(nodes.find((node) => node['x-uid'] == rootUid));
|
|
202
|
+
}
|
|
203
|
+
clearAncestor(uid, options) {
|
|
204
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
205
|
+
const db = this.database;
|
|
206
|
+
const treeTable = this.uiSchemaTreePathTableName;
|
|
207
|
+
yield db.sequelize.query(`DELETE
|
|
208
|
+
FROM ${treeTable}
|
|
209
|
+
WHERE descendant IN
|
|
210
|
+
(SELECT descendant FROM (SELECT descendant FROM ${treeTable} WHERE ancestor = :uid) as descendantTable)
|
|
211
|
+
AND ancestor IN (SELECT ancestor
|
|
212
|
+
FROM (SELECT ancestor FROM ${treeTable} WHERE descendant = :uid AND ancestor != descendant) as ancestorTable)
|
|
213
|
+
`, {
|
|
214
|
+
type: 'DELETE',
|
|
215
|
+
replacements: {
|
|
216
|
+
uid,
|
|
217
|
+
},
|
|
218
|
+
transaction: options.transaction,
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
patch(newSchema, options) {
|
|
223
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
224
|
+
const { transaction } = options;
|
|
225
|
+
const rootUid = newSchema['x-uid'];
|
|
226
|
+
const oldTree = yield this.getJsonSchema(rootUid);
|
|
227
|
+
const traverSchemaTree = (schema, path = []) => __awaiter(this, void 0, void 0, function* () {
|
|
228
|
+
const node = schema;
|
|
229
|
+
const oldNode = path.length == 0 ? oldTree : lodash.get(oldTree, path);
|
|
230
|
+
const oldNodeUid = oldNode['x-uid'];
|
|
231
|
+
yield this.updateNode(oldNodeUid, node, transaction);
|
|
232
|
+
const properties = node.properties;
|
|
233
|
+
if (lodash.isPlainObject(properties)) {
|
|
234
|
+
for (const name of Object.keys(properties)) {
|
|
235
|
+
yield traverSchemaTree(properties[name], [...path, 'properties', name]);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
yield traverSchemaTree(newSchema);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
updateNode(uid, schema, transaction) {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
const nodeModel = yield this.findOne({
|
|
245
|
+
filter: {
|
|
246
|
+
'x-uid': uid,
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
yield nodeModel.update({
|
|
250
|
+
schema: Object.assign(Object.assign({}, nodeModel.get('schema')), lodash.omit(schema, ['x-async', 'name', 'x-uid', 'properties'])),
|
|
251
|
+
}, {
|
|
252
|
+
hooks: false,
|
|
253
|
+
transaction,
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
childrenCount(uid, transaction) {
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
const db = this.database;
|
|
260
|
+
const countResult = yield db.sequelize.query(`SELECT COUNT(*) as count FROM ${this.uiSchemaTreePathTableName} where ancestor = :ancestor and depth = 1`, {
|
|
261
|
+
replacements: {
|
|
262
|
+
ancestor: uid,
|
|
263
|
+
},
|
|
264
|
+
type: 'SELECT',
|
|
265
|
+
transaction,
|
|
266
|
+
});
|
|
267
|
+
return parseInt(countResult[0]['count']);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
isLeafNode(uid, transaction) {
|
|
271
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
272
|
+
const childrenCount = yield this.childrenCount(uid, transaction);
|
|
273
|
+
return childrenCount === 0;
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
findParentUid(uid, transaction) {
|
|
277
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
278
|
+
const parent = yield this.database.getRepository('uiSchemaTreePath').findOne({
|
|
279
|
+
filter: {
|
|
280
|
+
descendant: uid,
|
|
281
|
+
depth: 1,
|
|
282
|
+
},
|
|
283
|
+
transaction,
|
|
284
|
+
});
|
|
285
|
+
return parent ? parent.get('ancestor') : null;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
findNodeSchemaWithParent(uid, transaction) {
|
|
289
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
290
|
+
const schema = yield this.database.getRepository('uiSchemas').findOne({
|
|
291
|
+
filter: {
|
|
292
|
+
'x-uid': uid,
|
|
293
|
+
},
|
|
294
|
+
transaction,
|
|
295
|
+
});
|
|
296
|
+
return {
|
|
297
|
+
parentUid: yield this.findParentUid(uid, transaction),
|
|
298
|
+
schema,
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
isSingleChild(uid, transaction) {
|
|
303
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
304
|
+
const db = this.database;
|
|
305
|
+
const parent = yield this.findParentUid(uid, transaction);
|
|
306
|
+
if (!parent) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const parentChildrenCount = yield this.childrenCount(parent, transaction);
|
|
310
|
+
if (parentChildrenCount == 1) {
|
|
311
|
+
const schema = yield db.getRepository('uiSchemas').findOne({
|
|
312
|
+
filter: {
|
|
313
|
+
'x-uid': parent,
|
|
314
|
+
},
|
|
315
|
+
transaction,
|
|
316
|
+
});
|
|
317
|
+
return schema;
|
|
318
|
+
}
|
|
319
|
+
return null;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
removeEmptyParents(options) {
|
|
323
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
324
|
+
const { transaction, uid, breakRemoveOn } = options;
|
|
325
|
+
const removeParent = (nodeUid) => __awaiter(this, void 0, void 0, function* () {
|
|
326
|
+
const parent = yield this.isSingleChild(nodeUid, transaction);
|
|
327
|
+
if (parent && !this.breakOnMatched(parent, breakRemoveOn)) {
|
|
328
|
+
yield removeParent(parent.get('x-uid'));
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
yield this.remove(nodeUid, { transaction });
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
yield removeParent(uid);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
breakOnMatched(schemaInstance, breakRemoveOn) {
|
|
338
|
+
if (!breakRemoveOn) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
for (const key of Object.keys(breakRemoveOn)) {
|
|
342
|
+
const instanceValue = schemaInstance.get(key);
|
|
343
|
+
const breakRemoveOnValue = breakRemoveOn[key];
|
|
344
|
+
if (instanceValue !== breakRemoveOnValue) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
recursivelyRemoveIfNoChildren(options) {
|
|
351
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
352
|
+
const { uid, transaction, breakRemoveOn } = options;
|
|
353
|
+
const removeLeafNode = (nodeUid) => __awaiter(this, void 0, void 0, function* () {
|
|
354
|
+
const isLeafNode = yield this.isLeafNode(nodeUid, transaction);
|
|
355
|
+
if (isLeafNode) {
|
|
356
|
+
const { parentUid, schema } = yield this.findNodeSchemaWithParent(nodeUid, transaction);
|
|
357
|
+
if (this.breakOnMatched(schema, breakRemoveOn)) {
|
|
358
|
+
// break at here
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
// remove current node
|
|
363
|
+
yield this.remove(nodeUid, {
|
|
364
|
+
transaction,
|
|
365
|
+
});
|
|
366
|
+
// continue remove
|
|
367
|
+
yield removeLeafNode(parentUid);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
yield removeLeafNode(uid);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
remove(uid, options) {
|
|
375
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
376
|
+
let { transaction } = options;
|
|
377
|
+
if (options === null || options === void 0 ? void 0 : options.removeParentsIfNoChildren) {
|
|
378
|
+
yield this.removeEmptyParents({ transaction, uid, breakRemoveOn: options.breakRemoveOn });
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
yield this.database.sequelize.query(this.sqlAdapter(`DELETE FROM ${this.uiSchemasTableName} WHERE "x-uid" IN (
|
|
382
|
+
SELECT descendant FROM ${this.uiSchemaTreePathTableName} WHERE ancestor = :uid
|
|
383
|
+
)`), {
|
|
384
|
+
replacements: {
|
|
385
|
+
uid,
|
|
386
|
+
},
|
|
387
|
+
transaction,
|
|
388
|
+
});
|
|
389
|
+
yield this.database.sequelize.query(` DELETE FROM ${this.uiSchemaTreePathTableName}
|
|
390
|
+
WHERE descendant IN (
|
|
391
|
+
select descendant FROM
|
|
392
|
+
(SELECT descendant
|
|
393
|
+
FROM ${this.uiSchemaTreePathTableName}
|
|
394
|
+
WHERE ancestor = :uid)as descendantTable) `, {
|
|
395
|
+
replacements: {
|
|
396
|
+
uid,
|
|
397
|
+
},
|
|
398
|
+
transaction,
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
insertBeside(targetUid, schema, side, options) {
|
|
403
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
404
|
+
const { transaction } = options;
|
|
405
|
+
const targetParent = yield this.findParentUid(targetUid, transaction);
|
|
406
|
+
const db = this.database;
|
|
407
|
+
const treeTable = this.uiSchemaTreePathTableName;
|
|
408
|
+
const typeQuery = yield db.sequelize.query(`SELECT type from ${treeTable} WHERE ancestor = :uid AND depth = 0;`, {
|
|
409
|
+
type: 'SELECT',
|
|
410
|
+
replacements: {
|
|
411
|
+
uid: targetUid,
|
|
412
|
+
},
|
|
413
|
+
transaction,
|
|
414
|
+
});
|
|
415
|
+
const nodes = UiSchemaRepository.schemaToSingleNodes(schema);
|
|
416
|
+
const rootNode = nodes[0];
|
|
417
|
+
rootNode.childOptions = {
|
|
418
|
+
parentUid: targetParent,
|
|
419
|
+
type: typeQuery[0]['type'],
|
|
420
|
+
position: {
|
|
421
|
+
type: side,
|
|
422
|
+
target: targetUid,
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
const insertedNodes = yield this.insertNodes(nodes, options);
|
|
426
|
+
return yield this.getJsonSchema(insertedNodes[0].get('x-uid'), {
|
|
427
|
+
transaction,
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
insertInner(targetUid, schema, position, options) {
|
|
432
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
433
|
+
const { transaction } = options;
|
|
434
|
+
const nodes = UiSchemaRepository.schemaToSingleNodes(schema);
|
|
435
|
+
const rootNode = nodes[0];
|
|
436
|
+
rootNode.childOptions = {
|
|
437
|
+
parentUid: targetUid,
|
|
438
|
+
type: lodash.get(schema, 'x-node-type', 'properties'),
|
|
439
|
+
position,
|
|
440
|
+
};
|
|
441
|
+
const insertedNodes = yield this.insertNodes(nodes, options);
|
|
442
|
+
return yield this.getJsonSchema(insertedNodes[0].get('x-uid'), {
|
|
443
|
+
transaction,
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
schemaExists(schema, options) {
|
|
448
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
449
|
+
if (lodash.isObject(schema) && !schema['x-uid']) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
const { transaction } = options;
|
|
453
|
+
const result = yield this.database.sequelize.query(this.sqlAdapter(`select "x-uid" from ${this.uiSchemasTableName} where "x-uid" = :uid`), {
|
|
454
|
+
type: 'SELECT',
|
|
455
|
+
replacements: {
|
|
456
|
+
uid: lodash.isString(schema) ? schema : schema['x-uid'],
|
|
457
|
+
},
|
|
458
|
+
transaction,
|
|
459
|
+
});
|
|
460
|
+
return result.length > 0;
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
insertAdjacent(position, target, schema, options) {
|
|
464
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
465
|
+
const { transaction } = options;
|
|
466
|
+
if (options.wrap) {
|
|
467
|
+
// insert wrap schema using insertNewSchema
|
|
468
|
+
const wrapSchemaNodes = yield this.insertNewSchema(options.wrap, {
|
|
469
|
+
transaction,
|
|
470
|
+
returnNode: true,
|
|
471
|
+
});
|
|
472
|
+
const lastWrapNode = wrapSchemaNodes[wrapSchemaNodes.length - 1];
|
|
473
|
+
// insert schema into wrap schema
|
|
474
|
+
yield this.insertAdjacent('afterBegin', lastWrapNode['x-uid'], schema, lodash.omit(options, 'wrap'));
|
|
475
|
+
schema = wrapSchemaNodes[0]['x-uid'];
|
|
476
|
+
options.removeParentsIfNoChildren = false;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
const schemaExists = yield this.schemaExists(schema, { transaction });
|
|
480
|
+
if (schemaExists) {
|
|
481
|
+
schema = lodash.isString(schema) ? schema : schema['x-uid'];
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
const insertedSchema = yield this.insertNewSchema(schema, {
|
|
485
|
+
transaction,
|
|
486
|
+
returnNode: true,
|
|
487
|
+
});
|
|
488
|
+
schema = insertedSchema[0]['x-uid'];
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return yield this[`insert${lodash.upperFirst(position)}`](target, schema, options);
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
insertAfterBegin(targetUid, schema, options) {
|
|
495
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
496
|
+
return yield this.insertInner(targetUid, schema, 'first', options);
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
insertBeforeEnd(targetUid, schema, options) {
|
|
500
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
501
|
+
return yield this.insertInner(targetUid, schema, 'last', options);
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
insertBeforeBegin(targetUid, schema, options) {
|
|
505
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
506
|
+
return yield this.insertBeside(targetUid, schema, 'before', options);
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
insertAfterEnd(targetUid, schema, options) {
|
|
510
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
511
|
+
return yield this.insertBeside(targetUid, schema, 'after', options);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
insertNodes(nodes, options) {
|
|
515
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
516
|
+
const { transaction } = options;
|
|
517
|
+
const insertedNodes = [];
|
|
518
|
+
for (const node of nodes) {
|
|
519
|
+
insertedNodes.push(yield this.insertSingleNode(node, Object.assign(Object.assign({}, options), { transaction })));
|
|
520
|
+
}
|
|
521
|
+
return insertedNodes;
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
insert(schema, options) {
|
|
525
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
526
|
+
const nodes = UiSchemaRepository.schemaToSingleNodes(schema);
|
|
527
|
+
const insertedNodes = yield this.insertNodes(nodes, options);
|
|
528
|
+
return this.getJsonSchema(insertedNodes[0].get('x-uid'), {
|
|
529
|
+
transaction: options === null || options === void 0 ? void 0 : options.transaction,
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
insertNewSchema(schema, options) {
|
|
534
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
535
|
+
const { transaction } = options;
|
|
536
|
+
const nodes = UiSchemaRepository.schemaToSingleNodes(schema);
|
|
537
|
+
// insert schema fist
|
|
538
|
+
yield this.database.sequelize.query(this.sqlAdapter(`INSERT INTO ${this.uiSchemasTableName} ("x-uid", "name", "schema") VALUES ${nodes
|
|
539
|
+
.map((n) => '(?)')
|
|
540
|
+
.join(',')};`), {
|
|
541
|
+
replacements: lodash.cloneDeep(nodes).map((node) => {
|
|
542
|
+
const { uid, name } = this.prepareSingleNodeForInsert(node);
|
|
543
|
+
return [uid, name, JSON.stringify(node)];
|
|
544
|
+
}),
|
|
545
|
+
type: 'insert',
|
|
546
|
+
transaction,
|
|
547
|
+
});
|
|
548
|
+
const treePathData = lodash.cloneDeep(nodes).reduce((carry, item) => {
|
|
549
|
+
const { uid, childOptions, async } = this.prepareSingleNodeForInsert(item);
|
|
550
|
+
return [
|
|
551
|
+
...carry,
|
|
552
|
+
// self reference
|
|
553
|
+
[uid, uid, 0, (childOptions === null || childOptions === void 0 ? void 0 : childOptions.type) || null, async, null],
|
|
554
|
+
// parent references
|
|
555
|
+
...lodash.get(childOptions, 'parentPath', []).map((parentUid, index) => {
|
|
556
|
+
return [parentUid, uid, index + 1, null, null, childOptions.sort];
|
|
557
|
+
}),
|
|
558
|
+
];
|
|
559
|
+
}, []);
|
|
560
|
+
// insert tree path
|
|
561
|
+
yield this.database.sequelize.query(this.sqlAdapter(`INSERT INTO ${this.uiSchemaTreePathTableName} (ancestor, descendant, depth, type, async, sort) VALUES ${treePathData.map((item) => '(?)').join(',')}`), {
|
|
562
|
+
replacements: treePathData,
|
|
563
|
+
type: 'insert',
|
|
564
|
+
transaction,
|
|
565
|
+
});
|
|
566
|
+
const rootNode = nodes[0];
|
|
567
|
+
if (rootNode['x-server-hooks']) {
|
|
568
|
+
const rootModel = yield this.findOne({ filter: { 'x-uid': rootNode['x-uid'] }, transaction });
|
|
569
|
+
yield this.database.emitAsync(`${this.collection.name}.afterCreateWithAssociations`, rootModel, options);
|
|
570
|
+
}
|
|
571
|
+
if (options === null || options === void 0 ? void 0 : options.returnNode) {
|
|
572
|
+
return nodes;
|
|
573
|
+
}
|
|
574
|
+
return this.getJsonSchema(nodes[0]['x-uid'], {
|
|
575
|
+
transaction,
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
insertSchemaRecord(name, uid, schema, transaction) {
|
|
580
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
581
|
+
const serverHooks = schema['x-server-hooks'] || [];
|
|
582
|
+
const node = yield this.create({
|
|
583
|
+
values: {
|
|
584
|
+
name,
|
|
585
|
+
['x-uid']: uid,
|
|
586
|
+
schema,
|
|
587
|
+
serverHooks,
|
|
588
|
+
},
|
|
589
|
+
transaction,
|
|
590
|
+
context: {
|
|
591
|
+
disableInsertHook: true,
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
return node;
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
prepareSingleNodeForInsert(schema) {
|
|
598
|
+
const uid = schema['x-uid'];
|
|
599
|
+
const name = schema['name'];
|
|
600
|
+
const async = lodash.get(schema, 'x-async', false);
|
|
601
|
+
const childOptions = schema['childOptions'];
|
|
602
|
+
delete schema['x-uid'];
|
|
603
|
+
delete schema['x-async'];
|
|
604
|
+
delete schema['name'];
|
|
605
|
+
delete schema['childOptions'];
|
|
606
|
+
return { uid, name, async, childOptions };
|
|
607
|
+
}
|
|
608
|
+
insertSingleNode(schema, options) {
|
|
609
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
610
|
+
const { transaction } = options;
|
|
611
|
+
const db = this.database;
|
|
612
|
+
const { uid, name, async, childOptions } = this.prepareSingleNodeForInsert(schema);
|
|
613
|
+
let savedNode;
|
|
614
|
+
// check node exists or not
|
|
615
|
+
const existsNode = yield this.findOne({
|
|
616
|
+
filter: {
|
|
617
|
+
'x-uid': uid,
|
|
618
|
+
},
|
|
619
|
+
transaction,
|
|
620
|
+
});
|
|
621
|
+
const treeTable = this.uiSchemaTreePathTableName;
|
|
622
|
+
if (existsNode) {
|
|
623
|
+
savedNode = existsNode;
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
savedNode = yield this.insertSchemaRecord(name, uid, schema, transaction);
|
|
627
|
+
}
|
|
628
|
+
if (childOptions) {
|
|
629
|
+
const oldParentUid = yield this.findParentUid(uid, transaction);
|
|
630
|
+
const parentUid = childOptions.parentUid;
|
|
631
|
+
const childrenCount = yield this.childrenCount(uid, transaction);
|
|
632
|
+
const isTree = childrenCount > 0;
|
|
633
|
+
// if node is a tree root move tree to new path
|
|
634
|
+
if (isTree) {
|
|
635
|
+
yield this.clearAncestor(uid, { transaction });
|
|
636
|
+
// insert new tree path
|
|
637
|
+
yield db.sequelize.query(`INSERT INTO ${treeTable} (ancestor, descendant, depth)
|
|
638
|
+
SELECT supertree.ancestor, subtree.descendant, supertree.depth + subtree.depth + 1
|
|
639
|
+
FROM ${treeTable} AS supertree
|
|
640
|
+
CROSS JOIN ${treeTable} AS subtree
|
|
641
|
+
WHERE supertree.descendant = :parentUid
|
|
642
|
+
AND subtree.ancestor = :uid;`, {
|
|
643
|
+
type: 'INSERT',
|
|
644
|
+
replacements: {
|
|
645
|
+
uid,
|
|
646
|
+
parentUid,
|
|
647
|
+
},
|
|
648
|
+
transaction,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
// update type
|
|
652
|
+
yield db.sequelize.query(`UPDATE ${treeTable} SET type = :type WHERE depth = 0 AND ancestor = :uid AND descendant = :uid`, {
|
|
653
|
+
type: 'update',
|
|
654
|
+
transaction,
|
|
655
|
+
replacements: {
|
|
656
|
+
type: childOptions.type,
|
|
657
|
+
uid,
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
if (!isTree) {
|
|
661
|
+
if (existsNode) {
|
|
662
|
+
// remove old path
|
|
663
|
+
yield db.sequelize.query(`DELETE FROM ${treeTable} WHERE descendant = :uid AND ancestor != descendant`, {
|
|
664
|
+
type: 'DELETE',
|
|
665
|
+
replacements: {
|
|
666
|
+
uid,
|
|
667
|
+
},
|
|
668
|
+
transaction,
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
// insert tree path
|
|
672
|
+
yield db.sequelize.query(`INSERT INTO ${treeTable} (ancestor, descendant, depth)
|
|
673
|
+
SELECT t.ancestor, :modelKey, depth + 1 FROM ${treeTable} AS t WHERE t.descendant = :modelParentKey `, {
|
|
674
|
+
type: 'INSERT',
|
|
675
|
+
transaction,
|
|
676
|
+
replacements: {
|
|
677
|
+
modelKey: savedNode.get('x-uid'),
|
|
678
|
+
modelParentKey: parentUid,
|
|
679
|
+
},
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
if (!existsNode) {
|
|
683
|
+
// insert type && async
|
|
684
|
+
yield db.sequelize.query(`INSERT INTO ${treeTable}(ancestor, descendant, depth, type, async) VALUES (:modelKey, :modelKey, 0, :type, :async )`, {
|
|
685
|
+
type: 'INSERT',
|
|
686
|
+
replacements: {
|
|
687
|
+
modelKey: savedNode.get('x-uid'),
|
|
688
|
+
type: childOptions.type,
|
|
689
|
+
async,
|
|
690
|
+
},
|
|
691
|
+
transaction,
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
const nodePosition = childOptions.position || 'last';
|
|
695
|
+
let sort;
|
|
696
|
+
// insert at first
|
|
697
|
+
if (nodePosition === 'first') {
|
|
698
|
+
sort = 1;
|
|
699
|
+
let updateSql = `UPDATE ${treeTable} as TreeTable
|
|
700
|
+
SET sort = TreeTable.sort + 1
|
|
701
|
+
FROM ${treeTable} as NodeInfo
|
|
702
|
+
WHERE NodeInfo.descendant = TreeTable.descendant and NodeInfo.depth = 0
|
|
703
|
+
AND TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and NodeInfo.type = :type`;
|
|
704
|
+
// Compatible with mysql
|
|
705
|
+
if (this.database.sequelize.getDialect() === 'mysql') {
|
|
706
|
+
updateSql = `UPDATE ${treeTable} as TreeTable
|
|
707
|
+
JOIN ${treeTable} as NodeInfo ON (NodeInfo.descendant = TreeTable.descendant and NodeInfo.depth = 0)
|
|
708
|
+
SET TreeTable.sort = TreeTable.sort + 1
|
|
709
|
+
WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and NodeInfo.type = :type`;
|
|
710
|
+
}
|
|
711
|
+
// move all child last index
|
|
712
|
+
yield db.sequelize.query(updateSql, {
|
|
713
|
+
replacements: {
|
|
714
|
+
ancestor: childOptions.parentUid,
|
|
715
|
+
type: childOptions.type,
|
|
716
|
+
},
|
|
717
|
+
transaction,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
if (nodePosition === 'last') {
|
|
721
|
+
const maxSort = yield db.sequelize.query(`SELECT ${this.database.sequelize.getDialect() === 'postgres' ? 'coalesce' : 'ifnull'}(MAX(TreeTable.sort), 0) as maxsort FROM ${treeTable} as TreeTable
|
|
722
|
+
LEFT JOIN ${treeTable} as NodeInfo
|
|
723
|
+
ON NodeInfo.descendant = TreeTable.descendant and NodeInfo.depth = 0
|
|
724
|
+
WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and NodeInfo.type = :type`, {
|
|
725
|
+
type: 'SELECT',
|
|
726
|
+
replacements: {
|
|
727
|
+
ancestor: childOptions.parentUid,
|
|
728
|
+
type: childOptions.type,
|
|
729
|
+
},
|
|
730
|
+
transaction,
|
|
731
|
+
});
|
|
732
|
+
sort = parseInt(maxSort[0]['maxsort']) + 1;
|
|
733
|
+
}
|
|
734
|
+
if (lodash.isPlainObject(nodePosition)) {
|
|
735
|
+
const targetPosition = nodePosition;
|
|
736
|
+
const target = targetPosition.target;
|
|
737
|
+
const targetSort = yield db.sequelize.query(`SELECT TreeTable.sort as sort FROM ${treeTable} as TreeTable
|
|
738
|
+
LEFT JOIN ${treeTable} as NodeInfo
|
|
739
|
+
ON NodeInfo.descendant = TreeTable.descendant and NodeInfo.depth = 0 WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor AND TreeTable.descendant = :descendant and NodeInfo.type = :type`, {
|
|
740
|
+
type: 'SELECT',
|
|
741
|
+
replacements: {
|
|
742
|
+
ancestor: childOptions.parentUid,
|
|
743
|
+
descendant: target,
|
|
744
|
+
type: childOptions.type,
|
|
745
|
+
},
|
|
746
|
+
transaction,
|
|
747
|
+
});
|
|
748
|
+
sort = targetSort[0].sort;
|
|
749
|
+
if (targetPosition.type == 'after') {
|
|
750
|
+
sort += 1;
|
|
751
|
+
}
|
|
752
|
+
let updateSql = `UPDATE ${treeTable} as TreeTable
|
|
753
|
+
SET sort = TreeTable.sort + 1
|
|
754
|
+
FROM ${treeTable} as NodeInfo
|
|
755
|
+
WHERE NodeInfo.descendant = TreeTable.descendant
|
|
756
|
+
and NodeInfo.depth = 0
|
|
757
|
+
AND TreeTable.depth = 1
|
|
758
|
+
AND TreeTable.ancestor = :ancestor
|
|
759
|
+
and TreeTable.sort >= :sort
|
|
760
|
+
and NodeInfo.type = :type`;
|
|
761
|
+
if (this.database.sequelize.getDialect() === 'mysql') {
|
|
762
|
+
updateSql = `UPDATE ${treeTable} as TreeTable
|
|
763
|
+
JOIN ${treeTable} as NodeInfo ON (NodeInfo.descendant = TreeTable.descendant and NodeInfo.depth = 0)
|
|
764
|
+
SET TreeTable.sort = TreeTable.sort + 1
|
|
765
|
+
WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort >= :sort and NodeInfo.type = :type`;
|
|
766
|
+
}
|
|
767
|
+
yield db.sequelize.query(updateSql, {
|
|
768
|
+
replacements: {
|
|
769
|
+
ancestor: childOptions.parentUid,
|
|
770
|
+
sort,
|
|
771
|
+
type: childOptions.type,
|
|
772
|
+
},
|
|
773
|
+
transaction,
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
// update order
|
|
777
|
+
const updateSql = `UPDATE ${treeTable} SET sort = :sort WHERE depth = 1 AND ancestor = :ancestor AND descendant = :descendant`;
|
|
778
|
+
yield db.sequelize.query(updateSql, {
|
|
779
|
+
type: 'UPDATE',
|
|
780
|
+
replacements: {
|
|
781
|
+
ancestor: childOptions.parentUid,
|
|
782
|
+
sort,
|
|
783
|
+
descendant: uid,
|
|
784
|
+
},
|
|
785
|
+
transaction,
|
|
786
|
+
});
|
|
787
|
+
// move node to new parent
|
|
788
|
+
if (oldParentUid !== null && oldParentUid !== parentUid) {
|
|
789
|
+
yield this.database.emitAsync('uiSchemaMove', savedNode, {
|
|
790
|
+
transaction,
|
|
791
|
+
oldParentUid,
|
|
792
|
+
parentUid,
|
|
793
|
+
});
|
|
794
|
+
if (options.removeParentsIfNoChildren) {
|
|
795
|
+
yield this.recursivelyRemoveIfNoChildren({
|
|
796
|
+
transaction,
|
|
797
|
+
uid: oldParentUid,
|
|
798
|
+
breakRemoveOn: options.breakRemoveOn,
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
// insert root node path
|
|
805
|
+
yield db.sequelize.query(`INSERT INTO ${treeTable}(ancestor, descendant, depth, async) VALUES (:modelKey, :modelKey, 0, :async )`, {
|
|
806
|
+
type: 'INSERT',
|
|
807
|
+
replacements: {
|
|
808
|
+
modelKey: savedNode.get('x-uid'),
|
|
809
|
+
async,
|
|
810
|
+
},
|
|
811
|
+
transaction,
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
return savedNode;
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
__decorate([
|
|
819
|
+
transaction()
|
|
820
|
+
], UiSchemaRepository.prototype, "clearAncestor", null);
|
|
821
|
+
__decorate([
|
|
822
|
+
transaction()
|
|
823
|
+
], UiSchemaRepository.prototype, "patch", null);
|
|
824
|
+
__decorate([
|
|
825
|
+
transaction()
|
|
826
|
+
], UiSchemaRepository.prototype, "remove", null);
|
|
827
|
+
__decorate([
|
|
828
|
+
transaction()
|
|
829
|
+
], UiSchemaRepository.prototype, "insertBeside", null);
|
|
830
|
+
__decorate([
|
|
831
|
+
transaction()
|
|
832
|
+
], UiSchemaRepository.prototype, "insertInner", null);
|
|
833
|
+
__decorate([
|
|
834
|
+
transaction()
|
|
835
|
+
], UiSchemaRepository.prototype, "insertAdjacent", null);
|
|
836
|
+
__decorate([
|
|
837
|
+
transaction()
|
|
838
|
+
], UiSchemaRepository.prototype, "insertAfterBegin", null);
|
|
839
|
+
__decorate([
|
|
840
|
+
transaction()
|
|
841
|
+
], UiSchemaRepository.prototype, "insertBeforeEnd", null);
|
|
842
|
+
__decorate([
|
|
843
|
+
transaction()
|
|
844
|
+
], UiSchemaRepository.prototype, "insertBeforeBegin", null);
|
|
845
|
+
__decorate([
|
|
846
|
+
transaction()
|
|
847
|
+
], UiSchemaRepository.prototype, "insertAfterEnd", null);
|
|
848
|
+
__decorate([
|
|
849
|
+
transaction()
|
|
850
|
+
], UiSchemaRepository.prototype, "insertNodes", null);
|
|
851
|
+
__decorate([
|
|
852
|
+
transaction()
|
|
853
|
+
], UiSchemaRepository.prototype, "insert", null);
|
|
854
|
+
__decorate([
|
|
855
|
+
transaction()
|
|
856
|
+
], UiSchemaRepository.prototype, "insertNewSchema", null);
|
|
857
|
+
export default UiSchemaRepository;
|
|
858
|
+
//# sourceMappingURL=repository.js.map
|