@gudhub/core 1.1.90 → 1.1.92
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/GUDHUB/AppProcessor/AppProcessor.js +0 -3
- package/GUDHUB/Auth/Auth.js +18 -0
- package/GUDHUB/Auth/Auth.test.js +11 -1
- package/GUDHUB/FileManager/FileManager.js +7 -3
- package/GUDHUB/GHConstructor/createAngularModuleInstance.js +40 -31
- package/GUDHUB/ItemProcessor/ItemProcessor.js +10 -1
- package/GUDHUB/Storage/ModulesList.js +42 -2
- package/GUDHUB/Utils/AppsTemplateService/AppsTemplateService.js +48 -5
- package/GUDHUB/Utils/get_date/get_date.test.js +3 -12
- package/GUDHUB/Utils/nested_list/nested_list.js +53 -50
- package/GUDHUB/Utils/nested_list/nested_list.test.js +140 -2
- package/GUDHUB/gudhub.js +24 -4
- package/package.json +1 -1
- package/umd/library.min.js +105 -68
- package/umd/library.min.js.map +1 -1
package/GUDHUB/Auth/Auth.js
CHANGED
|
@@ -10,6 +10,12 @@ export class Auth {
|
|
|
10
10
|
return user;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
async loginWithToken(token) {
|
|
14
|
+
const user = await this.loginWithTokenApi(token);
|
|
15
|
+
this.storage.updateUser(user);
|
|
16
|
+
return user;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
async logout(token) {
|
|
14
20
|
const response = await this.logoutApi(token);
|
|
15
21
|
return response;
|
|
@@ -58,6 +64,18 @@ export class Auth {
|
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
|
|
67
|
+
async loginWithTokenApi(token) {
|
|
68
|
+
try {
|
|
69
|
+
const user = await this.req.axiosRequest({
|
|
70
|
+
method: 'POST',
|
|
71
|
+
url: `${this.req.root}/auth/login?accesstoken=${token}`
|
|
72
|
+
});
|
|
73
|
+
return user;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.log(error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
61
79
|
async updateTokenApi(auth_key) {
|
|
62
80
|
try {
|
|
63
81
|
const user = await this.req.axiosRequest({
|
package/GUDHUB/Auth/Auth.test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import {GudHub} from './../gudhub.js';
|
|
3
3
|
|
|
4
4
|
describe("AUTHORIZATION", async function() {
|
|
@@ -22,6 +22,16 @@ describe("AUTHORIZATION", async function() {
|
|
|
22
22
|
user.fullname.should.equal('Vasya Pupkin');
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
+
it("Authentication with access token", async function () {
|
|
26
|
+
const gudhub = new GudHub();
|
|
27
|
+
|
|
28
|
+
const token = 'accesstoken';
|
|
29
|
+
|
|
30
|
+
const user = await gudhub.loginWithToken(token);
|
|
31
|
+
|
|
32
|
+
user.hasOwnProperty('fullname').should.equal(true);
|
|
33
|
+
})
|
|
34
|
+
|
|
25
35
|
it("Signing up user", async function () {
|
|
26
36
|
const gudhub = new GudHub();
|
|
27
37
|
let credentials = {
|
|
@@ -39,7 +39,7 @@ export class FileManager {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
async updateFileFromStringApi(data, file_id, file_name, extension, format) {
|
|
42
|
+
async updateFileFromStringApi(data, file_id, file_name, extension, format, alt, title) {
|
|
43
43
|
try {
|
|
44
44
|
const fileObj = {
|
|
45
45
|
file_name,
|
|
@@ -47,6 +47,8 @@ export class FileManager {
|
|
|
47
47
|
file_id,
|
|
48
48
|
format,
|
|
49
49
|
source: data,
|
|
50
|
+
alt,
|
|
51
|
+
title
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
const file = await this.req.post({
|
|
@@ -198,13 +200,15 @@ async getFiles(app_id, filesId = []) {
|
|
|
198
200
|
return file;
|
|
199
201
|
}
|
|
200
202
|
|
|
201
|
-
async updateFileFromString(data, file_id, file_name, extension, format) {
|
|
203
|
+
async updateFileFromString(data, file_id, file_name, extension, format, alt, title) {
|
|
202
204
|
const file = await this.updateFileFromStringApi(
|
|
203
205
|
data,
|
|
204
206
|
file_id,
|
|
205
207
|
file_name,
|
|
206
208
|
extension,
|
|
207
|
-
format
|
|
209
|
+
format,
|
|
210
|
+
alt,
|
|
211
|
+
title
|
|
208
212
|
);
|
|
209
213
|
this.updateFileInStorage(file_id, file.app_id, file);
|
|
210
214
|
return file;
|
|
@@ -119,25 +119,27 @@ export default async function createAngularModuleInstance(gudhub, module_id, mod
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// Modules always exports classes as default, so we create new class instance.
|
|
122
|
-
|
|
123
122
|
importedClass = factoryReturns[module_id];
|
|
124
|
-
|
|
125
123
|
}
|
|
126
|
-
|
|
127
124
|
} else {
|
|
128
|
-
|
|
129
125
|
const proxy = new Proxy(nodeWindow, {
|
|
130
126
|
get: (target, property) => {
|
|
131
|
-
|
|
127
|
+
const value = target[property];
|
|
128
|
+
if (typeof value === 'symbol') {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
return value;
|
|
132
132
|
},
|
|
133
133
|
set: (target, property, value) => {
|
|
134
|
+
if (typeof value === 'symbol') {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
134
137
|
target[property] = value;
|
|
135
138
|
global[property] = value;
|
|
136
139
|
return true;
|
|
137
140
|
}
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
// If node's global object don't have window and it's methods yet - set it.
|
|
141
|
+
});
|
|
142
|
+
|
|
141
143
|
if (!global.hasOwnProperty('window')) {
|
|
142
144
|
global.window = proxy;
|
|
143
145
|
global.document = nodeWindow.document;
|
|
@@ -153,35 +155,42 @@ export default async function createAngularModuleInstance(gudhub, module_id, mod
|
|
|
153
155
|
global.WebSocket = nodeWindow.WebSocket;
|
|
154
156
|
global.crypto = nodeWindow.crypto;
|
|
155
157
|
global.DOMParser = nodeWindow.DOMParser;
|
|
156
|
-
|
|
158
|
+
|
|
157
159
|
global.document.queryCommandSupported = (command) => {
|
|
158
160
|
return false;
|
|
159
|
-
}
|
|
161
|
+
};
|
|
160
162
|
global.angular = angular;
|
|
161
163
|
}
|
|
162
|
-
|
|
163
|
-
// Downloading module's code and
|
|
164
|
-
|
|
165
|
-
let response = await axios.get(module_url);
|
|
166
|
-
let code = response.data;
|
|
167
|
-
let encodedCode = encodeURIComponent(code);
|
|
168
|
-
encodedCode = 'data:text/javascript;charset=utf-8,' + encodedCode;
|
|
169
|
-
|
|
170
|
-
let module;
|
|
171
|
-
|
|
172
|
-
// Then, dynamically import modules from data url.
|
|
173
|
-
|
|
164
|
+
|
|
165
|
+
// Downloading module's code and transforming it to a data URL.
|
|
174
166
|
try {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
167
|
+
let response = await axios.get(module_url);
|
|
168
|
+
let code = response.data;
|
|
169
|
+
|
|
170
|
+
// Ensure code is properly encoded, excluding any symbols
|
|
171
|
+
let encodedCode = encodeURIComponent(code);
|
|
172
|
+
|
|
173
|
+
// Creating a data URL
|
|
174
|
+
encodedCode = 'data:text/javascript;charset=utf-8,' + encodedCode;
|
|
175
|
+
|
|
176
|
+
let module;
|
|
177
|
+
|
|
178
|
+
// Dynamically import the module from the data URL.
|
|
179
|
+
try {
|
|
180
|
+
module = await import(/* webpackIgnore: true */ encodedCode);
|
|
181
|
+
} catch (err) {
|
|
182
|
+
console.log(`Error while importing module: ${module_id}`);
|
|
183
|
+
console.log(err);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (module && module.default) {
|
|
187
|
+
importedClass = new module.default();
|
|
188
|
+
} else {
|
|
189
|
+
console.error(`Module ${module_id} didn't export a default class`);
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error("Error fetching module code:", error);
|
|
179
193
|
}
|
|
180
|
-
|
|
181
|
-
// Modules always exports classes as default, so we create new class instance.
|
|
182
|
-
|
|
183
|
-
importedClass = new module.default();
|
|
184
|
-
|
|
185
194
|
}
|
|
186
195
|
|
|
187
196
|
let result = {
|
|
@@ -134,7 +134,7 @@ export class ItemProcessor {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
async getItems(app_id, trash = false) {
|
|
137
|
-
const app = await this.appProcessor.getApp(app_id
|
|
137
|
+
const app = await this.appProcessor.getApp(app_id);
|
|
138
138
|
if(!app) return null;
|
|
139
139
|
return app.items_list;
|
|
140
140
|
}
|
|
@@ -165,6 +165,15 @@ export class ItemProcessor {
|
|
|
165
165
|
);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
async restoreItems(app_id, itemsIds) {
|
|
169
|
+
const preparedItemsList = itemsIds.map((id) => ({
|
|
170
|
+
item_id: id,
|
|
171
|
+
trash: false
|
|
172
|
+
}));
|
|
173
|
+
const updatedItems = await this.updateItemsApi(app_id, preparedItemsList);
|
|
174
|
+
return await this.updateItemsInStorage(app_id, updatedItems);
|
|
175
|
+
}
|
|
176
|
+
|
|
168
177
|
itemListeners() {
|
|
169
178
|
this.pipeService.onRoot("gh_items_get", {}, async (event, data) => {
|
|
170
179
|
if(data && data.app_id) {
|
|
@@ -931,7 +931,7 @@ export default function generateModulesList(async_modules_path, file_server_url,
|
|
|
931
931
|
data_type: 'study_journal',
|
|
932
932
|
name: 'Study Journal',
|
|
933
933
|
icon: 'timeline',
|
|
934
|
-
js: 'https://gudhub.com/modules/Study-Journal/dist/main.js',
|
|
934
|
+
js: 'https://gudhub.com/modules/Study-Journal/dist/main.js?t=1',
|
|
935
935
|
css: 'https://gudhub.com/modules/Study-Journal/dist/style.css',
|
|
936
936
|
type: 'gh_element',
|
|
937
937
|
technology: 'class'
|
|
@@ -958,11 +958,44 @@ export default function generateModulesList(async_modules_path, file_server_url,
|
|
|
958
958
|
data_type: "text_area",
|
|
959
959
|
name: "Text Area",
|
|
960
960
|
icon: "text_icon",
|
|
961
|
-
js: "https://gudhub.com/modules/text-area-ghe/dist/main.js?t=
|
|
961
|
+
js: "https://gudhub.com/modules/text-area-ghe/dist/main.js?t=3",
|
|
962
962
|
css: "https://gudhub.com/modules/text-area-ghe/dist/style.css",
|
|
963
963
|
type: "gh_element",
|
|
964
964
|
technology: "class",
|
|
965
965
|
},
|
|
966
|
+
{
|
|
967
|
+
data_type: "resource_calendar",
|
|
968
|
+
name: "Resource Сalendar",
|
|
969
|
+
icon: "calendar",
|
|
970
|
+
url: file_server_url + '/' + async_modules_path + "resource_calendar_data.js",
|
|
971
|
+
type: 'gh_element',
|
|
972
|
+
technology: 'angular'
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
data_type: "visualizer_with_control_panel",
|
|
976
|
+
name: "Visualizer With Control Panel",
|
|
977
|
+
icon: 'visualizer',
|
|
978
|
+
url: file_server_url + '/' + async_modules_path + "visualizer_with_control_panel_data.js",
|
|
979
|
+
type: 'gh_element',
|
|
980
|
+
technology: 'angular'
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
data_type: "svg_to_pdf",
|
|
984
|
+
name: "SVG To PDF",
|
|
985
|
+
icon: "box",
|
|
986
|
+
js: "https://gudhub.com/modules/SVG-to-PDF-Gh-Element/dist/main.js",
|
|
987
|
+
css: "https://gudhub.com/modules/SVG-to-PDF-Gh-Element/dist/style.css",
|
|
988
|
+
type: "gh_element",
|
|
989
|
+
technology: "class",
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
data_type: "recycle_bin",
|
|
993
|
+
name: "Recycle Bin",
|
|
994
|
+
icon: 'recycle_bin',
|
|
995
|
+
url: file_server_url + '/' + async_modules_path + "recycle_bin_data.js",
|
|
996
|
+
type: 'gh_element',
|
|
997
|
+
technology: "angular",
|
|
998
|
+
},
|
|
966
999
|
/* AUTOMATION MODULES */
|
|
967
1000
|
/*
|
|
968
1001
|
We have next types for automations:
|
|
@@ -1340,6 +1373,13 @@ export default function generateModulesList(async_modules_path, file_server_url,
|
|
|
1340
1373
|
url: file_server_url + '/' + automation_modules_path + 'turbo_sms.js',
|
|
1341
1374
|
type: 'automation',
|
|
1342
1375
|
icon: 'email'
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
data_type: 'JsCode',
|
|
1379
|
+
name: 'Js Code',
|
|
1380
|
+
url: file_server_url + '/' + automation_modules_path + 'js_code.js',
|
|
1381
|
+
type: 'automation',
|
|
1382
|
+
icon: 'code_editor'
|
|
1343
1383
|
}
|
|
1344
1384
|
]
|
|
1345
1385
|
}
|
|
@@ -195,6 +195,8 @@ export default class AppsTemplateService {
|
|
|
195
195
|
|
|
196
196
|
documentInstallerHelper(appId, items, elementId) {
|
|
197
197
|
const self = this;
|
|
198
|
+
const itemsWithClonedDocument = [];
|
|
199
|
+
|
|
198
200
|
return new Promise(async (resolve) => {
|
|
199
201
|
for(const item of items) {
|
|
200
202
|
const itemId = item.item_id;
|
|
@@ -216,10 +218,11 @@ export default class AppsTemplateService {
|
|
|
216
218
|
|
|
217
219
|
field.field_value = newDocument._id;
|
|
218
220
|
|
|
221
|
+
itemsWithClonedDocument.push(item);
|
|
219
222
|
}
|
|
220
223
|
}
|
|
221
224
|
}
|
|
222
|
-
resolve();
|
|
225
|
+
resolve(itemsWithClonedDocument);
|
|
223
226
|
});
|
|
224
227
|
}
|
|
225
228
|
|
|
@@ -440,7 +443,14 @@ export default class AppsTemplateService {
|
|
|
440
443
|
});
|
|
441
444
|
|
|
442
445
|
self.crawling(app.field_list, function (prop, value, parent) {
|
|
443
|
-
|
|
446
|
+
const fieldProps = ["field_id", "FieldId", "destination_field", "element_id"];
|
|
447
|
+
const appProps = ["app_id", "AppId", "destination_app"];
|
|
448
|
+
const viewProps = ["view_id"];
|
|
449
|
+
const srcProps = ["src"];
|
|
450
|
+
|
|
451
|
+
const hasProp = (prop, propArray) => propArray.some(key => prop.indexOf(key) !== -1);
|
|
452
|
+
|
|
453
|
+
if (hasProp(prop, fieldProps)) {
|
|
444
454
|
let fieldsArr = String(value).split(','), newFieldsArr = [];
|
|
445
455
|
|
|
446
456
|
appsConnectingMap.fields.forEach(field => {
|
|
@@ -456,7 +466,7 @@ export default class AppsTemplateService {
|
|
|
456
466
|
}
|
|
457
467
|
}
|
|
458
468
|
|
|
459
|
-
if (
|
|
469
|
+
if (hasProp(prop, appProps)) {
|
|
460
470
|
appsConnectingMap.apps.forEach(app => {
|
|
461
471
|
if (value == app.old_app_id) {
|
|
462
472
|
parent[prop] = app.new_app_id;
|
|
@@ -464,7 +474,7 @@ export default class AppsTemplateService {
|
|
|
464
474
|
})
|
|
465
475
|
}
|
|
466
476
|
|
|
467
|
-
if (prop
|
|
477
|
+
if (hasProp(prop, viewProps)) {
|
|
468
478
|
appsConnectingMap.views.forEach(view => {
|
|
469
479
|
if (value == view.old_view_id) {
|
|
470
480
|
parent[prop] = view.new_view_id;
|
|
@@ -472,7 +482,7 @@ export default class AppsTemplateService {
|
|
|
472
482
|
})
|
|
473
483
|
}
|
|
474
484
|
|
|
475
|
-
if (prop
|
|
485
|
+
if (hasProp(prop, srcProps) && isFinite(value)) {
|
|
476
486
|
const pron_name = 'container_id';
|
|
477
487
|
const old_app_id = appsConnectingMap.apps.find(appMap => appMap.new_app_id === app.app_id).old_app_id;
|
|
478
488
|
const path = self.findPath(source_apps[old_app_id].views_list, pron_name, value);
|
|
@@ -480,6 +490,39 @@ export default class AppsTemplateService {
|
|
|
480
490
|
parent[prop] = `${self.getValueByPath(app.views_list, path, pron_name)}`;
|
|
481
491
|
}
|
|
482
492
|
|
|
493
|
+
if (prop.indexOf("trigger") !== -1 && value.model && value.model.nodes) {
|
|
494
|
+
const nodes = value.model.nodes;
|
|
495
|
+
const nodeProperties = ["inputs", "outputs"];
|
|
496
|
+
|
|
497
|
+
for (const index in nodes) {
|
|
498
|
+
nodeProperties.forEach((property) => {
|
|
499
|
+
const node = nodes[index];
|
|
500
|
+
const numericProperties = Object.keys(node[property]).filter(prop => prop !== '' && !isNaN(prop)); // field_id as keys
|
|
501
|
+
|
|
502
|
+
numericProperties.forEach((old_field_id) => {
|
|
503
|
+
const correspondFieldOfConnectingMap = appsConnectingMap.fields.filter((field) => field.old_field_id == old_field_id);
|
|
504
|
+
|
|
505
|
+
if (correspondFieldOfConnectingMap.length !== 0 && correspondFieldOfConnectingMap[0].new_field_id) {
|
|
506
|
+
const new_field_id = correspondFieldOfConnectingMap[0].new_field_id.toString();
|
|
507
|
+
|
|
508
|
+
const connectionObjectCopy = node[property][old_field_id];
|
|
509
|
+
connectionObjectCopy.connections.forEach((connection) => {
|
|
510
|
+
if (connection.input == old_field_id) {
|
|
511
|
+
connection.input = new_field_id;
|
|
512
|
+
}
|
|
513
|
+
if (connection.output == old_field_id) {
|
|
514
|
+
connection.output = new_field_id;
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
delete node[property][old_field_id];
|
|
519
|
+
|
|
520
|
+
node[property][new_field_id] = connectionObjectCopy;
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
}
|
|
483
526
|
})
|
|
484
527
|
})
|
|
485
528
|
|
|
@@ -53,7 +53,7 @@ describe("GET DATE", function () {
|
|
|
53
53
|
day.getDay().should.equal(6);
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
it("CHECK
|
|
56
|
+
it("CHECK RECURRING DATE / today", function() {
|
|
57
57
|
let today = new Date();
|
|
58
58
|
let result = gudhub.checkRecurringDate(today, 'day');
|
|
59
59
|
result.should.equal(true);
|
|
@@ -64,7 +64,7 @@ describe("GET DATE", function () {
|
|
|
64
64
|
result.should.equal(false);
|
|
65
65
|
})
|
|
66
66
|
|
|
67
|
-
it("CHECK
|
|
67
|
+
it("CHECK RECURRING DATE / week", function() {
|
|
68
68
|
let today = new Date();
|
|
69
69
|
let result = gudhub.checkRecurringDate(today, 'week');
|
|
70
70
|
result.should.equal(true);
|
|
@@ -75,16 +75,7 @@ describe("GET DATE", function () {
|
|
|
75
75
|
result.should.equal(false);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
it(
|
|
79
|
-
let day = gudhub.getDate('this_wednesday');
|
|
80
|
-
let dayTwoYearsBefore = subYears(day, 2);
|
|
81
|
-
|
|
82
|
-
// console.log(dayTwoYearsBefore);
|
|
83
|
-
let result = gudhub.checkRecurringDate(dayTwoYearsBefore, 'week');
|
|
84
|
-
result.should.equal(true);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("CHECK IF DATE IN THIS MONTH", function() {
|
|
78
|
+
it("CHECK RECURRING DATE / month", function() {
|
|
88
79
|
let today = new Date();
|
|
89
80
|
let result = gudhub.checkRecurringDate(today, 'month');
|
|
90
81
|
result.should.equal(true);
|
|
@@ -1,52 +1,55 @@
|
|
|
1
|
-
export function makeNestedList(
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function findIdsOfChildren(parent) {
|
|
24
|
-
parent[children].forEach((child) => {
|
|
25
|
-
if (child[id] == array[i][parent_id]) {
|
|
26
|
-
if (!child[children]) {
|
|
27
|
-
child[children] = [];
|
|
1
|
+
export function makeNestedList(
|
|
2
|
+
arr,
|
|
3
|
+
id,
|
|
4
|
+
parent_id,
|
|
5
|
+
children_property = "children",
|
|
6
|
+
priority_property = null
|
|
7
|
+
) {
|
|
8
|
+
let map = {};
|
|
9
|
+
let roots = [];
|
|
10
|
+
|
|
11
|
+
arr.forEach((item) => {
|
|
12
|
+
map[item[id]] = { ...item, [children_property]: [] };
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
arr.forEach((item) => {
|
|
16
|
+
const parentId = item[parent_id];
|
|
17
|
+
if (parentId && map[parentId]) {
|
|
18
|
+
map[parentId][children_property].push(map[item[id]]);
|
|
19
|
+
} else {
|
|
20
|
+
roots.push(map[item[id]]);
|
|
28
21
|
}
|
|
29
|
-
child[children].push(array[i]);
|
|
30
|
-
array.splice(i, 1);
|
|
31
|
-
i == 0 ? i = 0 : i--;
|
|
32
|
-
} else if (child[children]) {
|
|
33
|
-
findIdsOfChildren(child);
|
|
34
|
-
}
|
|
35
22
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
23
|
+
|
|
24
|
+
const sortTreeByPriority = (nodes) => {
|
|
25
|
+
nodes.forEach((node) => {
|
|
26
|
+
if (node[children_property].length > 0) {
|
|
27
|
+
sortTreeByPriority(node[children_property]);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (priority_property) {
|
|
32
|
+
nodes.sort((a, b) => {
|
|
33
|
+
const priorityA = a[priority_property] ?? Infinity;
|
|
34
|
+
const priorityB = b[priority_property] ?? Infinity;
|
|
35
|
+
return priorityA - priorityB;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
sortTreeByPriority(roots);
|
|
41
|
+
|
|
42
|
+
const cleanEmptyChildren = (nodes) => {
|
|
43
|
+
nodes.forEach((node) => {
|
|
44
|
+
if (node[children_property].length === 0) {
|
|
45
|
+
delete node[children_property];
|
|
46
|
+
} else {
|
|
47
|
+
cleanEmptyChildren(node[children_property]);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
cleanEmptyChildren(roots);
|
|
53
|
+
|
|
54
|
+
return roots;
|
|
55
|
+
};
|