@nocobase/plugin-graph-collection-manager 0.10.1-alpha.1 → 0.11.1-alpha.1
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/client.d.ts +2 -3
- package/client.js +1 -30
- package/lib/client/GraphCollectionProvider.js +1 -14
- package/lib/client/GraphCollectionShortcut.js +2 -9
- package/lib/client/GraphDrawPage.js +53 -47
- package/lib/client/action-hooks.d.ts +14 -1
- package/lib/client/action-hooks.js +12 -11
- package/lib/client/components/EditCollectionAction.d.ts +2 -1
- package/lib/client/components/EditCollectionAction.js +3 -19
- package/lib/client/components/Entity.js +28 -47
- package/lib/client/components/FieldSummary.d.ts +1 -1
- package/lib/client/components/FieldSummary.js +9 -16
- package/lib/client/index.d.ts +5 -1
- package/lib/client/index.js +21 -6
- package/lib/client/style.d.ts +12 -9
- package/lib/client/style.js +211 -196
- package/lib/client/utils.d.ts +3 -3
- package/lib/client/utils.js +15 -11
- package/package.json +27 -6
- package/server.d.ts +2 -3
- package/server.js +1 -30
- package/src/client/GraphCollectionProvider.tsx +33 -0
- package/src/client/GraphCollectionShortcut.tsx +141 -0
- package/src/client/GraphDrawPage.tsx +1382 -0
- package/src/client/action-hooks.tsx +237 -0
- package/src/client/components/AddCollectionAction.tsx +28 -0
- package/src/client/components/AddFieldAction.tsx +37 -0
- package/src/client/components/CollectionNodeProvder.tsx +28 -0
- package/src/client/components/EditCollectionAction.tsx +21 -0
- package/src/client/components/EditFieldAction.tsx +30 -0
- package/src/client/components/Entity.tsx +495 -0
- package/src/client/components/FieldSummary.tsx +42 -0
- package/src/client/components/OverrideFieldAction.tsx +30 -0
- package/src/client/components/ViewFieldAction.tsx +12 -0
- package/src/client/components/ViewNode.tsx +22 -0
- package/src/client/index.tsx +10 -0
- package/src/client/locale/en-US.ts +15 -0
- package/src/client/locale/es-ES.ts +15 -0
- package/src/client/locale/index.ts +3 -0
- package/src/client/locale/ja-JP.ts +13 -0
- package/src/client/locale/pt-BR.ts +15 -0
- package/src/client/locale/zh-CN.ts +16 -0
- package/src/client/style.tsx +227 -0
- package/src/client/utils.tsx +548 -0
- package/src/index.ts +1 -0
- package/src/server/actions/.gitkeep +0 -0
- package/src/server/collections/.gitkeep +0 -0
- package/src/server/collections/graphPositions.ts +22 -0
- package/src/server/index.ts +13 -0
- package/src/server/models/.gitkeep +0 -0
- package/src/server/repositories/.gitkeep +0 -0
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
import { lodash } from '@nocobase/utils/client';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
|
|
4
|
+
const { groupBy, reduce, uniq, uniqBy } = lodash;
|
|
5
|
+
|
|
6
|
+
const shape = {
|
|
7
|
+
ER: 'er-rect',
|
|
8
|
+
EDGE: 'edge',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const useGCMTranslation = () => {
|
|
12
|
+
return useTranslation('graph-collection-manager');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const getInheritCollections = (collections, name) => {
|
|
16
|
+
const parents = [];
|
|
17
|
+
const getParents = (name) => {
|
|
18
|
+
const collection = collections?.find((collection) => collection.name === name);
|
|
19
|
+
if (collection) {
|
|
20
|
+
const { inherits } = collection;
|
|
21
|
+
if (inherits) {
|
|
22
|
+
for (let index = 0; index < inherits.length; index++) {
|
|
23
|
+
const collectionKey = inherits[index];
|
|
24
|
+
parents.push(collectionKey);
|
|
25
|
+
getParents(collectionKey);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return uniq(parents);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return getParents(name);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getChildrenCollections = (collections, name) => {
|
|
36
|
+
const childrens = [];
|
|
37
|
+
const getChildrens = (name) => {
|
|
38
|
+
const inheritCollections = collections.filter((v) => {
|
|
39
|
+
return v.inherits?.includes(name);
|
|
40
|
+
});
|
|
41
|
+
inheritCollections.forEach((v) => {
|
|
42
|
+
const collectionKey = v.name;
|
|
43
|
+
childrens.push(v);
|
|
44
|
+
return getChildrens(collectionKey);
|
|
45
|
+
});
|
|
46
|
+
return childrens;
|
|
47
|
+
};
|
|
48
|
+
return getChildrens(name);
|
|
49
|
+
};
|
|
50
|
+
export const formatData = (data) => {
|
|
51
|
+
const edgeData = [];
|
|
52
|
+
const targetTablekeys = [];
|
|
53
|
+
const tableData = data.map((item, index) => {
|
|
54
|
+
const ports = [];
|
|
55
|
+
const totalFields = [...item.fields];
|
|
56
|
+
const inheritCollections = getInheritCollections(data, item.name);
|
|
57
|
+
const inheritedFields = reduce(
|
|
58
|
+
inheritCollections,
|
|
59
|
+
(result, value) => {
|
|
60
|
+
const arr = result;
|
|
61
|
+
const parentFields = data
|
|
62
|
+
.find((k) => k.name === value)
|
|
63
|
+
?.fields.map((v) => {
|
|
64
|
+
return { ...v, sourceCollectionName: item.name };
|
|
65
|
+
});
|
|
66
|
+
return arr.concat(parentFields);
|
|
67
|
+
},
|
|
68
|
+
[],
|
|
69
|
+
);
|
|
70
|
+
uniqBy(totalFields.concat(inheritedFields), 'name').forEach((field) => {
|
|
71
|
+
field.uiSchema &&
|
|
72
|
+
ports.push({
|
|
73
|
+
id: field.key,
|
|
74
|
+
group: 'list',
|
|
75
|
+
...field,
|
|
76
|
+
});
|
|
77
|
+
['obo', 'oho', 'o2o', 'o2m', 'm2o', 'm2m', 'linkTo'].includes(field.interface) && edgeData.push(field);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
targetTablekeys.push(item.name);
|
|
81
|
+
const portsData = formatPortData(ports);
|
|
82
|
+
return {
|
|
83
|
+
id: item.name,
|
|
84
|
+
shape: shape.ER,
|
|
85
|
+
name: item.name,
|
|
86
|
+
title: item.title,
|
|
87
|
+
width: 250,
|
|
88
|
+
// height: 40 * portsData.initPorts?.length||40,
|
|
89
|
+
ports: [...(portsData.initPorts || []), ...(portsData.morePorts || [])],
|
|
90
|
+
item: item,
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
const edges = formatEdgeData(edgeData, targetTablekeys, tableData);
|
|
94
|
+
const inheritEdges = formatInheritEdgeData(data);
|
|
95
|
+
return { nodesData: tableData, edgesData: edges, inheritEdges };
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const formatPortData = (ports) => {
|
|
99
|
+
const portsData = groupBy(ports, (v) => {
|
|
100
|
+
if (
|
|
101
|
+
v.isForeignKey ||
|
|
102
|
+
v.primaryKey ||
|
|
103
|
+
['obo', 'oho', 'o2o', 'o2m', 'm2o', 'm2m', 'linkTo', 'id'].includes(v.interface)
|
|
104
|
+
) {
|
|
105
|
+
return 'initPorts';
|
|
106
|
+
} else {
|
|
107
|
+
return 'morePorts';
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return portsData;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const formatInheritEdgeData = (collections) => {
|
|
114
|
+
const commonAttrs = {
|
|
115
|
+
attrs: {
|
|
116
|
+
line: {
|
|
117
|
+
strokeWidth: 1,
|
|
118
|
+
textAnchor: 'middle',
|
|
119
|
+
textVerticalAnchor: 'middle',
|
|
120
|
+
stroke: '#ddd',
|
|
121
|
+
sourceMarker: null,
|
|
122
|
+
// targetMarker: null,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
router: {
|
|
126
|
+
name: 'smooth',
|
|
127
|
+
args: {
|
|
128
|
+
direction: 'H',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
labels: [
|
|
132
|
+
{
|
|
133
|
+
markup: [
|
|
134
|
+
{
|
|
135
|
+
tagName: 'ellipse',
|
|
136
|
+
selector: 'labelBody',
|
|
137
|
+
style: {
|
|
138
|
+
cursor: 'pointer',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
tagName: 'text',
|
|
143
|
+
selector: 'labelText',
|
|
144
|
+
style: {
|
|
145
|
+
cursor: 'pointer',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
attrs: {
|
|
150
|
+
labelText: {
|
|
151
|
+
text: 'inherits',
|
|
152
|
+
fill: 'rgba(0, 0, 0, 0.3)',
|
|
153
|
+
textAnchor: 'middle',
|
|
154
|
+
textVerticalAnchor: 'middle',
|
|
155
|
+
},
|
|
156
|
+
labelBody: {
|
|
157
|
+
ref: 'labelText',
|
|
158
|
+
refWidth: '100%',
|
|
159
|
+
refHeight: '100%',
|
|
160
|
+
fill: 'var(--nb-box-bg)',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
position: {
|
|
164
|
+
distance: 0.5,
|
|
165
|
+
args: {
|
|
166
|
+
keepGradient: true,
|
|
167
|
+
ensureLegibility: true,
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
};
|
|
173
|
+
const inheritEdges = [];
|
|
174
|
+
collections.forEach((v) => {
|
|
175
|
+
const parentCollectonKeys = v.inherits || [];
|
|
176
|
+
if (parentCollectonKeys.length) {
|
|
177
|
+
parentCollectonKeys.forEach((k) => {
|
|
178
|
+
inheritEdges.push({
|
|
179
|
+
id: v.name + k,
|
|
180
|
+
source: {
|
|
181
|
+
cell: v.name,
|
|
182
|
+
connectionPoint: 'rect',
|
|
183
|
+
},
|
|
184
|
+
target: {
|
|
185
|
+
cell: k,
|
|
186
|
+
connectionPoint: 'rect',
|
|
187
|
+
},
|
|
188
|
+
connector: 'rounded',
|
|
189
|
+
connectionType: 'inherited',
|
|
190
|
+
...commonAttrs,
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return inheritEdges;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const formatEdgeData = (data, targetTables, tableData) => {
|
|
199
|
+
const edges = [];
|
|
200
|
+
for (let i = 0; i < data.length; i++) {
|
|
201
|
+
if (targetTables.includes(data[i].target)) {
|
|
202
|
+
const targetTable = tableData.find((v) => v.name === data[i].target);
|
|
203
|
+
const sourceTable = tableData.find((v) => v.name === (data[i].sourceCollectionName || data[i].collectionName));
|
|
204
|
+
const commonAttrs = {
|
|
205
|
+
attrs: {
|
|
206
|
+
line: {
|
|
207
|
+
strokeWidth: 1,
|
|
208
|
+
textAnchor: 'middle',
|
|
209
|
+
textVerticalAnchor: 'middle',
|
|
210
|
+
stroke: '#ddd',
|
|
211
|
+
sourceMarker: null,
|
|
212
|
+
targetMarker: null,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
router:
|
|
216
|
+
sourceTable.id === targetTable.id
|
|
217
|
+
? {
|
|
218
|
+
name: 'oneSide',
|
|
219
|
+
args: {
|
|
220
|
+
side: 'left',
|
|
221
|
+
},
|
|
222
|
+
}
|
|
223
|
+
: {
|
|
224
|
+
name: 'er',
|
|
225
|
+
args: {
|
|
226
|
+
direction: 'H',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
labels: [
|
|
230
|
+
{
|
|
231
|
+
markup: [
|
|
232
|
+
{
|
|
233
|
+
tagName: 'ellipse',
|
|
234
|
+
selector: 'labelBody',
|
|
235
|
+
style: {
|
|
236
|
+
cursor: 'pointer',
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
tagName: 'text',
|
|
241
|
+
selector: 'labelText',
|
|
242
|
+
style: {
|
|
243
|
+
cursor: 'pointer',
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
attrs: {
|
|
248
|
+
labelText: {
|
|
249
|
+
text: getRelationship(data[i].interface)[0],
|
|
250
|
+
fill: 'rgba(0, 0, 0, 0.3)',
|
|
251
|
+
textAnchor: 'middle',
|
|
252
|
+
textVerticalAnchor: 'middle',
|
|
253
|
+
},
|
|
254
|
+
labelBody: {
|
|
255
|
+
ref: 'labelText',
|
|
256
|
+
refWidth: '100%',
|
|
257
|
+
refHeight: '100%',
|
|
258
|
+
stroke: '#ddd',
|
|
259
|
+
fill: 'var(--nb-box-bg)',
|
|
260
|
+
strokeWidth: 1,
|
|
261
|
+
rx: 10,
|
|
262
|
+
ry: 10,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
position: {
|
|
266
|
+
distance: 0.3,
|
|
267
|
+
args: {
|
|
268
|
+
keepGradient: true,
|
|
269
|
+
ensureLegibility: true,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
markup: [
|
|
275
|
+
{
|
|
276
|
+
tagName: 'ellipse',
|
|
277
|
+
selector: 'labelBody',
|
|
278
|
+
style: {
|
|
279
|
+
cursor: 'pointer',
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
tagName: 'text',
|
|
284
|
+
selector: 'labelText',
|
|
285
|
+
style: {
|
|
286
|
+
cursor: 'pointer',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
attrs: {
|
|
291
|
+
labelText: {
|
|
292
|
+
text: getRelationship(data[i].interface)[1],
|
|
293
|
+
fill: 'rgba(0, 0, 0, 0.3)',
|
|
294
|
+
textAnchor: 'middle',
|
|
295
|
+
textVerticalAnchor: 'middle',
|
|
296
|
+
},
|
|
297
|
+
labelBody: {
|
|
298
|
+
ref: 'labelText',
|
|
299
|
+
refWidth: '100%',
|
|
300
|
+
refHeight: '100%',
|
|
301
|
+
stroke: '#ddd',
|
|
302
|
+
fill: 'var(--nb-box-bg)',
|
|
303
|
+
rx: 10,
|
|
304
|
+
ry: 10,
|
|
305
|
+
strokeWidth: 1,
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
position: {
|
|
309
|
+
distance: 0.7,
|
|
310
|
+
args: {
|
|
311
|
+
keepGradient: true,
|
|
312
|
+
ensureLegibility: true,
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
};
|
|
318
|
+
const isuniq = (id) => {
|
|
319
|
+
const targetEdge = edges.find((v) => v.id === id);
|
|
320
|
+
if (targetEdge) {
|
|
321
|
+
targetEdge.associated.push(data[i].name);
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
return true;
|
|
325
|
+
};
|
|
326
|
+
if (['m2m', 'linkTo'].includes(data[i].interface)) {
|
|
327
|
+
const throughTable = tableData.find((v) => v.name === data[i].through);
|
|
328
|
+
if (throughTable) {
|
|
329
|
+
const sCellId1 = sourceTable.id;
|
|
330
|
+
const tCellId1 = throughTable.id;
|
|
331
|
+
const sPortId1 = sourceTable.ports.find((v) => v.name === data[i].sourceKey)?.id;
|
|
332
|
+
const tPortId1 = throughTable.ports.find((v) => v.name === data[i].foreignKey)?.id;
|
|
333
|
+
const sCellId2 = targetTable.id;
|
|
334
|
+
const tCellId2 = throughTable.id;
|
|
335
|
+
const sPortId2 = targetTable.ports.find((v) => v.name === data[i].targetKey)?.id;
|
|
336
|
+
const tPortId2 = throughTable.ports.find((v) => v.name === data[i].otherKey)?.id;
|
|
337
|
+
const id1 = sCellId1 + sPortId1 + tCellId1 + tPortId1;
|
|
338
|
+
const id2 = sCellId2 + sPortId2 + tCellId2 + tPortId2;
|
|
339
|
+
edges.push({
|
|
340
|
+
id: id1,
|
|
341
|
+
source: {
|
|
342
|
+
cell: sCellId1,
|
|
343
|
+
port: sPortId1,
|
|
344
|
+
anchor: {
|
|
345
|
+
name: 'right',
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
target: {
|
|
349
|
+
cell: tCellId1,
|
|
350
|
+
port: tPortId1,
|
|
351
|
+
anchor: {
|
|
352
|
+
name: 'left',
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
associated: [data[i].name],
|
|
356
|
+
m2m: [id1, id2],
|
|
357
|
+
...commonAttrs,
|
|
358
|
+
});
|
|
359
|
+
edges.push({
|
|
360
|
+
id: id2,
|
|
361
|
+
source: {
|
|
362
|
+
cell: sCellId2,
|
|
363
|
+
port: sPortId2,
|
|
364
|
+
anchor: {
|
|
365
|
+
name: 'right',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
target: {
|
|
369
|
+
cell: tCellId2,
|
|
370
|
+
port: tPortId2,
|
|
371
|
+
anchor: {
|
|
372
|
+
name: 'left',
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
associated: [data[i].name],
|
|
376
|
+
m2m: [id1, id2],
|
|
377
|
+
...commonAttrs,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
} else {
|
|
381
|
+
const isLegalEdge = tableData
|
|
382
|
+
.find((v) => v.name == (data[i].sourceCollectionName || data[i].collectionName))
|
|
383
|
+
.ports.find((v) => v.name === data[i].foreignKey);
|
|
384
|
+
const sCellId1 = sourceTable.id;
|
|
385
|
+
const tCellId1 = targetTable.id;
|
|
386
|
+
const sPortId1 = isLegalEdge?.id;
|
|
387
|
+
const tPortId1 = targetTable.ports.find((v) => v.name === data[i].targetKey)?.id;
|
|
388
|
+
const sCellId2 = sourceTable.id;
|
|
389
|
+
const tCellId2 = targetTable.id;
|
|
390
|
+
const sPortId2 = sourceTable.ports.find((v) => v.name === data[i].sourceKey)?.id;
|
|
391
|
+
const tPortId2 = targetTable.ports.find((v) => v.name === data[i].foreignKey)?.id;
|
|
392
|
+
const id1 = sCellId1 + sPortId1 + tCellId1 + tPortId1;
|
|
393
|
+
const id2 = sCellId2 + sPortId2 + tCellId2 + tPortId2;
|
|
394
|
+
isuniq(tCellId1 + tPortId1 + sCellId1 + sPortId1) &&
|
|
395
|
+
isLegalEdge &&
|
|
396
|
+
tPortId1 &&
|
|
397
|
+
edges.push({
|
|
398
|
+
id: id1,
|
|
399
|
+
source: {
|
|
400
|
+
cell: sCellId1,
|
|
401
|
+
port: sPortId1,
|
|
402
|
+
anchor: {
|
|
403
|
+
name: 'right',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
target: {
|
|
407
|
+
cell: tCellId1,
|
|
408
|
+
port: tPortId1,
|
|
409
|
+
anchor: {
|
|
410
|
+
name: 'left',
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
associated: [data[i].name],
|
|
414
|
+
...commonAttrs,
|
|
415
|
+
});
|
|
416
|
+
isuniq(tCellId2 + tPortId2 + sCellId2 + sPortId2) &&
|
|
417
|
+
sPortId2 &&
|
|
418
|
+
tPortId2 &&
|
|
419
|
+
edges.push({
|
|
420
|
+
id: id2,
|
|
421
|
+
source: {
|
|
422
|
+
cell: sCellId2,
|
|
423
|
+
port: sPortId2,
|
|
424
|
+
anchor: {
|
|
425
|
+
name: 'right',
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
target: {
|
|
429
|
+
cell: tCellId2,
|
|
430
|
+
port: tPortId2,
|
|
431
|
+
anchor: {
|
|
432
|
+
name: 'left',
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
associated: [data[i].name],
|
|
436
|
+
...commonAttrs,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return uniqBy(edges, 'id');
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
const getRelationship = (relatioship) => {
|
|
445
|
+
switch (relatioship) {
|
|
446
|
+
case 'm2m':
|
|
447
|
+
case 'linkTo':
|
|
448
|
+
return ['1', 'N'];
|
|
449
|
+
case 'o2m':
|
|
450
|
+
return ['1', 'N'];
|
|
451
|
+
case 'm2o':
|
|
452
|
+
return ['N', '1'];
|
|
453
|
+
case 'obo':
|
|
454
|
+
case 'oho':
|
|
455
|
+
return ['1', '1'];
|
|
456
|
+
default:
|
|
457
|
+
return [];
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
export const getDiffNode = (newNodes, oldNodes) => {
|
|
462
|
+
const arr = [];
|
|
463
|
+
const length1 = newNodes.length;
|
|
464
|
+
const length2 = oldNodes.length;
|
|
465
|
+
for (let i = 0; i < length1; i++) {
|
|
466
|
+
if (!oldNodes.find((v) => v.id === newNodes[i].id)) {
|
|
467
|
+
arr.push({
|
|
468
|
+
status: 'add',
|
|
469
|
+
node: newNodes[i],
|
|
470
|
+
});
|
|
471
|
+
} else {
|
|
472
|
+
const oldNode = oldNodes.find((v) => v.id === newNodes[i].id);
|
|
473
|
+
const oldPorts = oldNode?.ports.items;
|
|
474
|
+
const newPorts = newNodes[i].ports;
|
|
475
|
+
if (oldNode) {
|
|
476
|
+
for (let h = 0; h < newPorts.length; h++) {
|
|
477
|
+
if (!oldPorts.find((v) => v.id === newPorts[h].id)) {
|
|
478
|
+
arr.push({
|
|
479
|
+
status: 'insertPort',
|
|
480
|
+
node: newNodes[i],
|
|
481
|
+
port: { index: h, port: newPorts[h] },
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
for (let k = 0; k < oldPorts.length; k++) {
|
|
486
|
+
if (!newPorts.find((v) => v.id === oldPorts[k].id)) {
|
|
487
|
+
arr.push({
|
|
488
|
+
status: 'deletePort',
|
|
489
|
+
node: newNodes[i],
|
|
490
|
+
port: oldPorts[k],
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (oldNode.title !== newNodes[i].title) {
|
|
496
|
+
arr.push({
|
|
497
|
+
status: 'updateNode',
|
|
498
|
+
node: newNodes[i],
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
for (let i = 0; i < length2; i++) {
|
|
505
|
+
if (!newNodes.find((v) => v.id === oldNodes[i].id)) {
|
|
506
|
+
arr.push({
|
|
507
|
+
status: 'delete',
|
|
508
|
+
node: oldNodes[i],
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return arr;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
export const getDiffEdge = (newEdges, oldEdges) => {
|
|
516
|
+
const length1 = newEdges.length;
|
|
517
|
+
const length2 = oldEdges?.length;
|
|
518
|
+
const edges = [];
|
|
519
|
+
for (let i = 0; i < length1; i++) {
|
|
520
|
+
if (!oldEdges.find((v) => v.id === newEdges[i].id)) {
|
|
521
|
+
edges.push({
|
|
522
|
+
status: 'add',
|
|
523
|
+
edge: newEdges[i],
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
for (let i = 0; i < length2; i++) {
|
|
528
|
+
if (!newEdges.find((v) => v.id === oldEdges[i].id)) {
|
|
529
|
+
edges.push({
|
|
530
|
+
status: 'delete',
|
|
531
|
+
edge: oldEdges[i],
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return edges;
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
let graphContainer;
|
|
539
|
+
/**
|
|
540
|
+
* 所有的 getPopupContainer 都需要保证返回的是唯一的 div。React 18 concurrent 下会反复调用该方法
|
|
541
|
+
* 参考:https://ant.design/docs/react/migration-v5-cn#%E5%8D%87%E7%BA%A7%E5%87%86%E5%A4%87
|
|
542
|
+
*/
|
|
543
|
+
export const getPopupContainer = () => {
|
|
544
|
+
if (graphContainer) {
|
|
545
|
+
return graphContainer;
|
|
546
|
+
}
|
|
547
|
+
return (graphContainer = document.getElementById('graph_container'));
|
|
548
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './server';
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineCollection } from '@nocobase/database';
|
|
2
|
+
|
|
3
|
+
export default defineCollection({
|
|
4
|
+
namespace: 'graph-collection-manager.graphCollectionPositions',
|
|
5
|
+
duplicator: 'required',
|
|
6
|
+
name: 'graphPositions',
|
|
7
|
+
fields: [
|
|
8
|
+
{
|
|
9
|
+
type: 'string',
|
|
10
|
+
name: 'collectionName',
|
|
11
|
+
unique: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
type: 'double',
|
|
15
|
+
name: 'x',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: 'double',
|
|
19
|
+
name: 'y',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Plugin } from '@nocobase/server';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
export class GraphCollectionManagerPlugin extends Plugin {
|
|
5
|
+
async load() {
|
|
6
|
+
await this.db.import({
|
|
7
|
+
directory: path.resolve(__dirname, 'collections'),
|
|
8
|
+
});
|
|
9
|
+
this.app.acl.allow('graphPositions', '*');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default GraphCollectionManagerPlugin;
|
|
File without changes
|
|
File without changes
|