@onehat/data 1.17.0 → 1.17.2
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/cypress/plugins/index.js +2 -32
- package/cypress.config.js +42 -0
- package/package.json +22 -22
- package/src/Entity/Entity.js +328 -4
- package/src/Repository/Ajax.js +13 -3
- package/src/Repository/OneBuild.js +80 -0
- package/src/Repository/Repository.js +118 -30
- package/src/Schema/Schema.js +33 -0
- package/cypress/cypress.json +0 -177
- package/cypress.json +0 -1
- package/src/Entity/TreeNode.js +0 -190
- /package/cypress/{integration/Async.spec.js → e2e/Async.cy.js} +0 -0
- /package/cypress/{integration/Config.spec.js → e2e/Config.cy.js} +0 -0
- /package/cypress/{integration/Entity.spec.js → e2e/Entity.cy.js} +0 -0
- /package/cypress/{integration/OneHatData.spec.js → e2e/OneHatData.cy.js} +0 -0
- /package/cypress/{integration/Property/Base64.spec.js → e2e/Property/Base64.cy.js} +0 -0
- /package/cypress/{integration/Property/Boolean.spec.js → e2e/Property/Boolean.cy.js} +0 -0
- /package/cypress/{integration/Property/Currency.spec.js → e2e/Property/Currency.cy.js} +0 -0
- /package/cypress/{integration/Property/Date.spec.js → e2e/Property/Date.cy.js} +0 -0
- /package/cypress/{integration/Property/DateTime.spec.js → e2e/Property/DateTime.cy.js} +0 -0
- /package/cypress/{integration/Property/Float.spec.js → e2e/Property/Float.cy.js} +0 -0
- /package/cypress/{integration/Property/Integer.spec.js → e2e/Property/Integer.cy.js} +0 -0
- /package/cypress/{integration/Property/Json.spec.js → e2e/Property/Json.cy.js} +0 -0
- /package/cypress/{integration/Property/Percent.spec.js → e2e/Property/Percent.cy.js} +0 -0
- /package/cypress/{integration/Property/PercentInt.spec.js → e2e/Property/PercentInt.cy.js} +0 -0
- /package/cypress/{integration/Property/Property.spec.js → e2e/Property/Property.cy.js} +0 -0
- /package/cypress/{integration/Property/String.spec.js → e2e/Property/String.cy.js} +0 -0
- /package/cypress/{integration/Property/Time.spec.js → e2e/Property/Time.cy.js} +0 -0
- /package/cypress/{integration/Property/Uuid.spec.js → e2e/Property/Uuid.cy.js} +0 -0
- /package/cypress/{integration/Repository/Ajax.spec.js → e2e/Repository/Ajax.cy.js} +0 -0
- /package/cypress/{integration/Repository/LocalFromRemote.spec.js → e2e/Repository/LocalFromRemote.cy.js} +0 -0
- /package/cypress/{integration/Repository/Memory.spec.js → e2e/Repository/Memory.cy.js} +0 -0
- /package/cypress/{integration/Repository/OneBuild.spec.js → e2e/Repository/OneBuild.cy.js} +0 -0
- /package/cypress/{integration/Repository/Repository.spec.js → e2e/Repository/Repository.cy.js} +0 -0
- /package/cypress/{integration/Schema.spec.js → e2e/Schema.cy.js} +0 -0
- /package/cypress/support/{index.js → e2e.js} +0 -0
package/cypress/plugins/index.js
CHANGED
|
@@ -1,32 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
mode: 'development',
|
|
4
|
-
devtool: 'cheap-module-source-map', // See https://survivejs.com/webpack/building/source-maps/
|
|
5
|
-
module: {
|
|
6
|
-
rules: [
|
|
7
|
-
{
|
|
8
|
-
test: /\.(js|jsx|mjs)$/,
|
|
9
|
-
exclude: /node_modules\/(?!(@onehat)\/).*/,
|
|
10
|
-
loader: 'babel-loader',
|
|
11
|
-
options: {
|
|
12
|
-
cacheDirectory: false,
|
|
13
|
-
presets: [
|
|
14
|
-
'@babel/preset-env'
|
|
15
|
-
],
|
|
16
|
-
plugins: [
|
|
17
|
-
'@babel/plugin-proposal-class-properties',
|
|
18
|
-
'@babel/plugin-transform-runtime'
|
|
19
|
-
],
|
|
20
|
-
sourceType: 'unambiguous',
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
module.exports = (on, config) => {
|
|
28
|
-
on('file:preprocessor', webpack({
|
|
29
|
-
webpackOptions,
|
|
30
|
-
watchOptions: {},
|
|
31
|
-
}));
|
|
32
|
-
};
|
|
1
|
+
module.exports = (on) => {
|
|
2
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { defineConfig } from "cypress";
|
|
2
|
+
import webpackPreprocessor from "@cypress/webpack-preprocessor";
|
|
3
|
+
import Webpack from "webpack";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
e2e: {
|
|
7
|
+
experimentalRunAllSpecs: true,
|
|
8
|
+
chromeWebSecurity: false,
|
|
9
|
+
setupNodeEvents(on) {
|
|
10
|
+
const options = webpackPreprocessor.defaultOptions;
|
|
11
|
+
if (!options.module) {
|
|
12
|
+
options.module = {
|
|
13
|
+
rules: [],
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (!options.module.rules) {
|
|
17
|
+
options.module.rules = [];
|
|
18
|
+
}
|
|
19
|
+
options.module.rules.push({
|
|
20
|
+
test: /\.(js|jsx|mjs)$/,
|
|
21
|
+
exclude: [/node_modules\/(?!(@onehat)\/).*/],
|
|
22
|
+
use: [{
|
|
23
|
+
loader: 'babel-loader',
|
|
24
|
+
options: {
|
|
25
|
+
cacheDirectory: false,
|
|
26
|
+
presets: [
|
|
27
|
+
'@babel/preset-env'
|
|
28
|
+
],
|
|
29
|
+
plugins: [
|
|
30
|
+
'@babel/plugin-transform-class-properties',
|
|
31
|
+
'@babel/plugin-transform-runtime'
|
|
32
|
+
],
|
|
33
|
+
sourceType: 'unambiguous',
|
|
34
|
+
},
|
|
35
|
+
}],
|
|
36
|
+
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
on('file:preprocessor', webpackPreprocessor(options));
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
});
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onehat/data",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.2",
|
|
4
4
|
"description": "JS data modeling package with adapters for many storage mediums.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "npx cypress open
|
|
8
|
+
"test": "npx cypress open",
|
|
9
|
+
"test2": "DEBUG=cypress:* npx cypress open",
|
|
9
10
|
"docs": "jsdoc -c ./jsdoc.json -t ./node_modules/ink-docstrap/template -R README.md"
|
|
10
11
|
},
|
|
11
12
|
"repository": {
|
|
@@ -35,37 +36,36 @@
|
|
|
35
36
|
},
|
|
36
37
|
"homepage": "https://github.com/OneHatRepo/data#readme",
|
|
37
38
|
"dependencies": {
|
|
38
|
-
"@onehat/events": "^1.6.
|
|
39
|
+
"@onehat/events": "^1.6.6",
|
|
39
40
|
"accounting-js": "^1.1.1",
|
|
40
|
-
"axios": "^1.
|
|
41
|
-
"chrono-node": "^2.
|
|
42
|
-
"fast-xml-parser": "^4.
|
|
41
|
+
"axios": "^1.4.0",
|
|
42
|
+
"chrono-node": "^2.6.3",
|
|
43
|
+
"fast-xml-parser": "^4.2.2",
|
|
43
44
|
"he": "^1.2.0",
|
|
44
|
-
"js-base64": "^3.7.
|
|
45
|
+
"js-base64": "^3.7.5",
|
|
45
46
|
"lodash": "^4.17.21",
|
|
46
47
|
"moment": "^2.29.4",
|
|
47
48
|
"natsort": "^2.0.3",
|
|
48
49
|
"numeral": "^2.0.6",
|
|
49
|
-
"qs": "^6.11.
|
|
50
|
+
"qs": "^6.11.2",
|
|
50
51
|
"relative-time-parser": "^1.0.15",
|
|
51
52
|
"uuid": "^9.0.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"@babel/core": "^7.
|
|
55
|
-
"@babel/node": "^7.
|
|
56
|
-
"@babel/plugin-
|
|
55
|
+
"@babel/core": "^7.22.1",
|
|
56
|
+
"@babel/node": "^7.22.1",
|
|
57
|
+
"@babel/plugin-transform-class-properties": "^7.22.3",
|
|
57
58
|
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
58
|
-
"@babel/preset-env": "^7.
|
|
59
|
-
"@babel/register": "^7.
|
|
60
|
-
"@babel/runtime": "^7.
|
|
61
|
-
"@cypress/webpack-preprocessor": "^5.
|
|
62
|
-
"babel-loader": "^
|
|
63
|
-
"cypress": "
|
|
59
|
+
"@babel/preset-env": "^7.22.4",
|
|
60
|
+
"@babel/register": "^7.21.0",
|
|
61
|
+
"@babel/runtime": "^7.22.3",
|
|
62
|
+
"@cypress/webpack-preprocessor": "^5.17.1",
|
|
63
|
+
"babel-loader": "^9.1.2",
|
|
64
|
+
"cypress": "12.13.0",
|
|
64
65
|
"ink-docstrap": "^1.3.2",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"yup": "^
|
|
69
|
-
|
|
66
|
+
"joi": "^17.9.2",
|
|
67
|
+
"jsdoc": "^4.0.2",
|
|
68
|
+
"webpack": "^5.85.0",
|
|
69
|
+
"yup": "^1.2.0"
|
|
70
70
|
}
|
|
71
71
|
}
|
package/src/Entity/Entity.js
CHANGED
|
@@ -35,7 +35,7 @@ class Entity extends EventEmitter {
|
|
|
35
35
|
* @param {boolean} originalIsMapped - Has data already been mapped according to schema?
|
|
36
36
|
* @param {boolean} isDelayedSave - Should the repository skip autosave when immediately adding the record?
|
|
37
37
|
*/
|
|
38
|
-
constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false) {
|
|
38
|
+
constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false, isRoot = false) {
|
|
39
39
|
super(...arguments);
|
|
40
40
|
|
|
41
41
|
if (!schema) {
|
|
@@ -104,9 +104,43 @@ class Entity extends EventEmitter {
|
|
|
104
104
|
this.properties = [];
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
|
-
* @member {boolean}
|
|
107
|
+
* @member {boolean} isTree - Whether this Entity is a TreeNode
|
|
108
108
|
*/
|
|
109
|
-
this.
|
|
109
|
+
this.isTree = schema.model.isTree || false;
|
|
110
|
+
|
|
111
|
+
if (this.isTree && !schema.model.parentIdProperty) {
|
|
112
|
+
throw new Error('parentIdProperty cannot be empty for a TreeNode');
|
|
113
|
+
}
|
|
114
|
+
if (this.isTree && this.repository?.isClosureTable && !schema.model.depthProperty) {
|
|
115
|
+
throw new Error('depthProperty cannot be empty for a Closure Table TreeNode');
|
|
116
|
+
}
|
|
117
|
+
if (this.isTree && !schema.model.hasChildrenProperty) {
|
|
118
|
+
throw new Error('hasChildrenProperty cannot be empty for a TreeNode');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @member {boolean} isRoot - Whether this TreeNode is the root TreeNode
|
|
123
|
+
* For trees only
|
|
124
|
+
*/
|
|
125
|
+
this.isRoot = false;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @member {TreeNode} parent - The parent TreeNode for this TreeNode
|
|
129
|
+
* For trees only
|
|
130
|
+
*/
|
|
131
|
+
this.parent = null;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @member {array} children - Contains any children of this TreeNode
|
|
135
|
+
* For trees only
|
|
136
|
+
*/
|
|
137
|
+
this.children = this._originalData.children && !_.isEmpty(this._originalData.children) ? this._originalData.children : [];
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @member {boolean} isChildrenLoaded - Whether child TreeNodes have loaded for this TreeNode
|
|
141
|
+
* For trees only
|
|
142
|
+
*/
|
|
143
|
+
this.isChildrenLoaded = this._originalData.isChildrenLoaded || false;
|
|
110
144
|
|
|
111
145
|
/**
|
|
112
146
|
* @member {boolean} isPersisted - Whether this object has been persisted in a storage medium
|
|
@@ -350,7 +384,7 @@ class Entity extends EventEmitter {
|
|
|
350
384
|
* Assumes (and sets) isTempId === false.
|
|
351
385
|
* @param {array} originalData - Raw data to load into entity.
|
|
352
386
|
*/
|
|
353
|
-
loadOriginalData = (originalData) => {
|
|
387
|
+
loadOriginalData = (originalData, assembleTreeNodes = true) => {
|
|
354
388
|
if (this.isDestroyed) {
|
|
355
389
|
throw Error('this.loadOriginalData is no longer valid. Entity has been destroyed.');
|
|
356
390
|
}
|
|
@@ -358,6 +392,10 @@ class Entity extends EventEmitter {
|
|
|
358
392
|
this._originalData = originalData || {};
|
|
359
393
|
this.reset();
|
|
360
394
|
this.getIdProperty().isTempId = false;
|
|
395
|
+
|
|
396
|
+
if (this.isTree && this.repository && assembleTreeNodes) {
|
|
397
|
+
this.repository.assembleTreeNodes(); // rebuilds them all
|
|
398
|
+
}
|
|
361
399
|
}
|
|
362
400
|
|
|
363
401
|
/**
|
|
@@ -1432,6 +1470,292 @@ class Entity extends EventEmitter {
|
|
|
1432
1470
|
}
|
|
1433
1471
|
|
|
1434
1472
|
|
|
1473
|
+
|
|
1474
|
+
// ______
|
|
1475
|
+
// /_ __/_______ ___ _____
|
|
1476
|
+
// / / / ___/ _ \/ _ \/ ___/
|
|
1477
|
+
// / / / / / __/ __(__ )
|
|
1478
|
+
// /_/ /_/ \___/\___/____/
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* Gets the "parentId" Property object for this TreeNode.
|
|
1482
|
+
* This is the Property whose value represents the id for the parent TreeNode.
|
|
1483
|
+
* @return {Property} parentId Property
|
|
1484
|
+
*/
|
|
1485
|
+
getParentIdProperty = () => {
|
|
1486
|
+
this.ensureTree();
|
|
1487
|
+
if (this.isDestroyed) {
|
|
1488
|
+
throw Error('this.getParentIdProperty is no longer valid. TreeNode has been destroyed.');
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
const parentIdProperty = this.getSchema().model.parentIdProperty;
|
|
1492
|
+
return this.getProperty(parentIdProperty);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
/**
|
|
1496
|
+
* Gets the parentId for this TreeNode.
|
|
1497
|
+
* It does this by getting the parentId property's submitValue.
|
|
1498
|
+
* It doesn't look at some value created by client on the TreeNode.
|
|
1499
|
+
* @return {any} parentId - The parentId
|
|
1500
|
+
*/
|
|
1501
|
+
getParentId = () => {
|
|
1502
|
+
this.ensureTree();
|
|
1503
|
+
if (this.isDestroyed) {
|
|
1504
|
+
throw Error('this.getParentId is no longer valid. TreeNode has been destroyed.');
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
return this.geParentIdProperty().getSubmitValue();
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Getter of parentId for this TreeNode.
|
|
1512
|
+
* @return {any} parentId - The parentId
|
|
1513
|
+
*/
|
|
1514
|
+
get parentId() {
|
|
1515
|
+
return this.getParentId();
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* Getter of hasParent
|
|
1520
|
+
* Returns true if this is not a root node
|
|
1521
|
+
* @return {boolean} hasParent
|
|
1522
|
+
*/
|
|
1523
|
+
get hasParent() {
|
|
1524
|
+
this.ensureTree();
|
|
1525
|
+
|
|
1526
|
+
return !this.isRoot;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* Gets the "depth" Property object for this TreeNode.
|
|
1531
|
+
* This is the Property whose value represents the depth of the TreeNode.
|
|
1532
|
+
* @return {Property} parentId Property
|
|
1533
|
+
*/
|
|
1534
|
+
getDepthProperty = () => {
|
|
1535
|
+
this.ensureTree();
|
|
1536
|
+
if (this.isDestroyed) {
|
|
1537
|
+
throw Error('this.getDepthProperty is no longer valid. TreeNode has been destroyed.');
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
const depthProperty = this.getSchema().model.depthProperty;
|
|
1541
|
+
return this.getProperty(depthProperty);
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
/**
|
|
1545
|
+
* Gets the depth for this TreeNode.
|
|
1546
|
+
* It does this by getting the depth property's submitValue.
|
|
1547
|
+
* @return {any} depth - The depth
|
|
1548
|
+
*/
|
|
1549
|
+
getDepth = () => {
|
|
1550
|
+
this.ensureTree();
|
|
1551
|
+
if (this.isDestroyed) {
|
|
1552
|
+
throw Error('this.getDepth is no longer valid. TreeNode has been destroyed.');
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
return this.getDepthProperty().getSubmitValue();
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* Getter of depth for this TreeNode.
|
|
1560
|
+
* @return {any} depth - The depth
|
|
1561
|
+
*/
|
|
1562
|
+
get depth() {
|
|
1563
|
+
return this.getDepth();
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
/**
|
|
1567
|
+
* Gets the "hasChildren" Property object for this TreeNode.
|
|
1568
|
+
* This is the Property whose value represents whether this TreeNode has any children.
|
|
1569
|
+
* @return {Property} parentId Property
|
|
1570
|
+
*/
|
|
1571
|
+
getHasChildrenProperty = () => {
|
|
1572
|
+
this.ensureTree();
|
|
1573
|
+
if (this.isDestroyed) {
|
|
1574
|
+
throw Error('this.getHasChildrenProperty is no longer valid. TreeNode has been destroyed.');
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
const hasChildrenProperty = this.getSchema().model.hasChildrenProperty;
|
|
1578
|
+
return this.getProperty(hasChildrenProperty);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
/**
|
|
1582
|
+
* Gets the hasChildren value for this TreeNode.
|
|
1583
|
+
* It does this by getting the hasChildren property's submitValue.
|
|
1584
|
+
* It doesn't look at some value created by client on the TreeNode.
|
|
1585
|
+
* @return {any} parentId - The parentId
|
|
1586
|
+
*/
|
|
1587
|
+
getHasChildren = () => {
|
|
1588
|
+
this.ensureTree();
|
|
1589
|
+
if (this.isDestroyed) {
|
|
1590
|
+
throw Error('this.getHasChildren is no longer valid. TreeNode has been destroyed.');
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
return this.getHasChildrenProperty().getSubmitValue();
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
/**
|
|
1597
|
+
* Getter of hasChildren for this TreeNode.
|
|
1598
|
+
* @return {any} parentId - The parentId
|
|
1599
|
+
*/
|
|
1600
|
+
get hasChildren() {
|
|
1601
|
+
return this.getHasChildren();
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
/**
|
|
1605
|
+
* Getter of parent TreeNode for this TreeNode.
|
|
1606
|
+
* @return {TreeNode} parent - The parent TreeNode
|
|
1607
|
+
*/
|
|
1608
|
+
getParent = () => {
|
|
1609
|
+
this.ensureTree();
|
|
1610
|
+
if (this.isDestroyed) {
|
|
1611
|
+
throw Error('this.getParent is no longer valid. TreeNode has been destroyed.');
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
if (!this.hasParent) {
|
|
1615
|
+
return null;
|
|
1616
|
+
}
|
|
1617
|
+
return this.parent;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
/**
|
|
1621
|
+
* Getter of child TreeNodes for this TreeNode.
|
|
1622
|
+
* @return {array} children - The children
|
|
1623
|
+
*/
|
|
1624
|
+
getChildren = async () => {
|
|
1625
|
+
this.ensureTree();
|
|
1626
|
+
if (this.isDestroyed) {
|
|
1627
|
+
throw Error('this.getChildren is no longer valid. TreeNode has been destroyed.');
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
if (!this.isChildrenLoaded) {
|
|
1631
|
+
await this.loadChildren();
|
|
1632
|
+
}
|
|
1633
|
+
return this.children;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
/**
|
|
1637
|
+
* Loads the children of this TreeNode from repository.
|
|
1638
|
+
*/
|
|
1639
|
+
loadChildren = async (depth) => {
|
|
1640
|
+
this.ensureTree();
|
|
1641
|
+
if (this.isDestroyed) {
|
|
1642
|
+
throw Error('this.loadChildren is no longer valid. TreeNode has been destroyed.');
|
|
1643
|
+
}
|
|
1644
|
+
if (!this.repository?.loadChildren) {
|
|
1645
|
+
throw Error('repository.loadChildren is not defined.');
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
this.children = await this.repository.loadChildren(this, depth); // populates the children with a reference to this in child.parent
|
|
1649
|
+
this.isChildrenLoaded = true;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
/**
|
|
1653
|
+
* Alias for loadChildren
|
|
1654
|
+
*/
|
|
1655
|
+
reloadChildren = () => { // alias
|
|
1656
|
+
return this.loadChildren();
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
/**
|
|
1660
|
+
* Gets the previous sibling of this TreeNode from repository.
|
|
1661
|
+
* @return {TreeNode} sibling
|
|
1662
|
+
*/
|
|
1663
|
+
getPrevousSibling = async () => {
|
|
1664
|
+
this.ensureTree();
|
|
1665
|
+
if (this.isDestroyed) {
|
|
1666
|
+
throw Error('this.getPrevousSibling is no longer valid. TreeNode has been destroyed.');
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
const
|
|
1670
|
+
parent = this.getParent(),
|
|
1671
|
+
siblings = await parent.getChildren();
|
|
1672
|
+
let previous;
|
|
1673
|
+
_.each(siblings, (treeNode) => {
|
|
1674
|
+
if (treeNode === this) {
|
|
1675
|
+
return false;
|
|
1676
|
+
}
|
|
1677
|
+
previous = treeNode;
|
|
1678
|
+
})
|
|
1679
|
+
return previous;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
/**
|
|
1683
|
+
* Gets the next sibling of this TreeNode from repository.
|
|
1684
|
+
* @return {TreeNode} sibling
|
|
1685
|
+
*/
|
|
1686
|
+
getNextSibling = async () => {
|
|
1687
|
+
this.ensureTree();
|
|
1688
|
+
if (this.isDestroyed) {
|
|
1689
|
+
throw Error('this.getNextSibling is no longer valid. TreeNode has been destroyed.');
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
const
|
|
1693
|
+
parent = this.getParent(),
|
|
1694
|
+
siblings = await parent.getChildren();
|
|
1695
|
+
let returnNext = false,
|
|
1696
|
+
next = null;
|
|
1697
|
+
_.each(siblings, (treeNode) => {
|
|
1698
|
+
if (returnNext) {
|
|
1699
|
+
next = treeNode;
|
|
1700
|
+
return false;
|
|
1701
|
+
}
|
|
1702
|
+
if (treeNode === this) {
|
|
1703
|
+
returnNext = true;
|
|
1704
|
+
}
|
|
1705
|
+
})
|
|
1706
|
+
return next;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/**
|
|
1710
|
+
* Gets the child of this TreeNode at index ix from repository.
|
|
1711
|
+
* @return {TreeNode} child
|
|
1712
|
+
*/
|
|
1713
|
+
getChildAt = (ix) => {
|
|
1714
|
+
this.ensureTree();
|
|
1715
|
+
if (this.isDestroyed) {
|
|
1716
|
+
throw Error('this.getChildAt is no longer valid. TreeNode has been destroyed.');
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
return this.children[ix];
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/**
|
|
1723
|
+
* Gets the first child of this TreeNode from repository.
|
|
1724
|
+
* @return {TreeNode} child
|
|
1725
|
+
*/
|
|
1726
|
+
getFirstChild = () => {
|
|
1727
|
+
this.ensureTree();
|
|
1728
|
+
if (this.isDestroyed) {
|
|
1729
|
+
throw Error('this.getFirstChild is no longer valid. TreeNode has been destroyed.');
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
return this.children[0];
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
/**
|
|
1736
|
+
* Gets the last child of this TreeNode from repository.
|
|
1737
|
+
* @return {TreeNode} child
|
|
1738
|
+
*/
|
|
1739
|
+
getLastChild = () => {
|
|
1740
|
+
this.ensureTree();
|
|
1741
|
+
if (this.isDestroyed) {
|
|
1742
|
+
throw Error('this.getLastChild is no longer valid. TreeNode has been destroyed.');
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
return this.children.slice(-1)[0]
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
/**
|
|
1749
|
+
* Helper to make sure this Repository is a tree
|
|
1750
|
+
* @private
|
|
1751
|
+
*/
|
|
1752
|
+
ensureTree = async () => {
|
|
1753
|
+
if (!this.isTree) {
|
|
1754
|
+
this.throwError('This Repository is not a tree!');
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
|
|
1435
1759
|
/**
|
|
1436
1760
|
* Destroy this object.
|
|
1437
1761
|
* - Removes all circular references to parent objects
|
package/src/Repository/Ajax.js
CHANGED
|
@@ -430,6 +430,10 @@ class AjaxRepository extends Repository {
|
|
|
430
430
|
this._relayEntityEvents(entity);
|
|
431
431
|
return entity;
|
|
432
432
|
});
|
|
433
|
+
|
|
434
|
+
if (this.isTree) {
|
|
435
|
+
this.assembleTreeNodes();
|
|
436
|
+
}
|
|
433
437
|
|
|
434
438
|
// Set the total records that pass filter
|
|
435
439
|
this.total = total;
|
|
@@ -492,7 +496,7 @@ class AjaxRepository extends Repository {
|
|
|
492
496
|
}
|
|
493
497
|
|
|
494
498
|
const updatedData = root[0];
|
|
495
|
-
entity.loadOriginalData(updatedData
|
|
499
|
+
entity.loadOriginalData(updatedData);
|
|
496
500
|
entity.emit('reload', entity);
|
|
497
501
|
|
|
498
502
|
this.markLoaded();
|
|
@@ -638,11 +642,14 @@ class AjaxRepository extends Repository {
|
|
|
638
642
|
// Reload each entity with new data
|
|
639
643
|
// TODO: Check this
|
|
640
644
|
_.each(entities, (entity, ix) => {
|
|
641
|
-
entity.loadOriginalData(root[ix]);
|
|
645
|
+
entity.loadOriginalData(root[ix], false); // false to not assembleTreeNodes
|
|
642
646
|
if (entity.isRemotePhantomMode) {
|
|
643
647
|
entity.isRemotePhantom = true;
|
|
644
648
|
}
|
|
645
649
|
});
|
|
650
|
+
if (this.isTree) {
|
|
651
|
+
this.assembleTreeNodes();
|
|
652
|
+
}
|
|
646
653
|
});
|
|
647
654
|
}
|
|
648
655
|
|
|
@@ -748,11 +755,14 @@ class AjaxRepository extends Repository {
|
|
|
748
755
|
// Reload each entity with new data
|
|
749
756
|
// TODO: Check this
|
|
750
757
|
_.each(entities, (entity, ix) => {
|
|
751
|
-
entity.loadOriginalData(root[ix]);
|
|
758
|
+
entity.loadOriginalData(root[ix], false); // false to not assembleTreeNodes
|
|
752
759
|
if (entity.isRemotePhantomMode && entity.isRemotePhantom) {
|
|
753
760
|
entity.isRemotePhantom = false;
|
|
754
761
|
}
|
|
755
762
|
});
|
|
763
|
+
if (this.isTree) {
|
|
764
|
+
this.assembleTreeNodes();
|
|
765
|
+
}
|
|
756
766
|
});
|
|
757
767
|
}
|
|
758
768
|
|
|
@@ -404,6 +404,86 @@ class OneBuildRepository extends AjaxRepository {
|
|
|
404
404
|
});
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
+
|
|
408
|
+
// ______
|
|
409
|
+
// /_ __/_______ ___ _____
|
|
410
|
+
// / / / ___/ _ \/ _ \/ ___/
|
|
411
|
+
// / / / / / __/ __(__ )
|
|
412
|
+
// /_/ /_/ \___/\___/____/
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Gets the root nodes of this tree.
|
|
416
|
+
*/
|
|
417
|
+
getRootNodes = async (getChildren = false, depth) => {
|
|
418
|
+
this.ensureTree();
|
|
419
|
+
if (this.isDestroyed) {
|
|
420
|
+
this.throwError('this.setRootNode is no longer valid. Repository has been destroyed.');
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Clear all entities, if any exist
|
|
425
|
+
_.each(this.entities, (entity) => {
|
|
426
|
+
entity.destroy();
|
|
427
|
+
});
|
|
428
|
+
this.entities = [];
|
|
429
|
+
|
|
430
|
+
// TODO: Load root nodes (and possibly their children)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Loads the children of the supplied treeNode
|
|
437
|
+
*/
|
|
438
|
+
loadChildren = async (treeNode, depth = 1) => {
|
|
439
|
+
this.ensureTree();
|
|
440
|
+
if (this.isDestroyed) {
|
|
441
|
+
this.throwError('this.setRootNode is no longer valid. Repository has been destroyed.');
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
// If children already exist, remove them from the repository
|
|
447
|
+
// This way, we can reload just a portion of the tree
|
|
448
|
+
if (!_.isEmpty(treeNode.children)) {
|
|
449
|
+
const children = treeNode.children;
|
|
450
|
+
treeNode.children = [];
|
|
451
|
+
|
|
452
|
+
_.each(children, (child) => {
|
|
453
|
+
this.removeNode(child);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
// TODO: load children here
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Alias for loadChildren
|
|
466
|
+
*/
|
|
467
|
+
reloadChildren = (treeNode, depth) => {
|
|
468
|
+
return this.loadChildren(treeNode, depth);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Moves the supplied treeNode to a new position on the tree
|
|
473
|
+
*/
|
|
474
|
+
moveTreeNode = async (treeNode, newParentId) => {
|
|
475
|
+
this.ensureTree();
|
|
476
|
+
if (this.isDestroyed) {
|
|
477
|
+
this.throwError('this.moveTreeNode is no longer valid. Repository has been destroyed.');
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// TODO: move node here
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
}
|
|
486
|
+
|
|
407
487
|
}
|
|
408
488
|
|
|
409
489
|
|