|
@@ -698,6 +698,16 @@
|
|
StatTree.el.jstree(true).delete_node(selected.id);
|
|
StatTree.el.jstree(true).delete_node(selected.id);
|
|
StatTree.setDirty();
|
|
StatTree.setDirty();
|
|
}
|
|
}
|
|
|
|
+ },
|
|
|
|
+ separator_after: true,
|
|
|
|
+ },
|
|
|
|
+ "permutate_child_tree": {
|
|
|
|
+ "label": "<span class='text-sm'>Create Child Permutations</span>",
|
|
|
|
+ "action": function (obj) {
|
|
|
|
+ let selected = StatTree.selectedNode();
|
|
|
|
+ if(selected) {
|
|
|
|
+ StatTree.createChildTreePermutations(selected);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -719,6 +729,113 @@
|
|
}, 'json').then(hideMask);
|
|
}, 'json').then(hideMask);
|
|
},
|
|
},
|
|
|
|
|
|
|
|
+ createChildTreePermutations: function(_node) {
|
|
|
|
+
|
|
|
|
+ // permute: thanks: https://stackoverflow.com/a/37580979/921204
|
|
|
|
+ function _permute(permutation) {
|
|
|
|
+ var length = permutation.length,
|
|
|
|
+ result = [permutation.slice()],
|
|
|
|
+ c = new Array(length).fill(0),
|
|
|
|
+ i = 1, k, p;
|
|
|
|
+
|
|
|
|
+ while (i < length) {
|
|
|
|
+ if (c[i] < i) {
|
|
|
|
+ k = i % 2 && c[i];
|
|
|
|
+ p = permutation[i];
|
|
|
|
+ permutation[i] = permutation[k];
|
|
|
|
+ permutation[k] = p;
|
|
|
|
+ ++c[i];
|
|
|
|
+ i = 1;
|
|
|
|
+ result.push(permutation.slice());
|
|
|
|
+ } else {
|
|
|
|
+ c[i] = 0;
|
|
|
|
+ ++i;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ensure 1 child for selected node
|
|
|
|
+ if(_node.children.length !== 1) {
|
|
|
|
+ toastr.error('Line must have exactly one child!');
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ensure all nodes down the node in the tree have only one child (if any)
|
|
|
|
+ function _hasSingleChild(_id) {
|
|
|
|
+ let node = StatTree.el.jstree(true).get_node(_id);
|
|
|
|
+ if(node.children.length === 0) return true; // no children
|
|
|
|
+ if(node.children.length > 1) return false; // more than 1 child, stop already!
|
|
|
|
+ return _hasSingleChild(node.children[0]);
|
|
|
|
+ }
|
|
|
|
+ if(!_hasSingleChild(_node.id)) {
|
|
|
|
+ toastr.error('Single linear child tree structure needed under selected node!');
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // get an array of line "data" of the child tree
|
|
|
|
+ function _getData(_id, _dataArray, _displayLabelArray) {
|
|
|
|
+ let node = StatTree.el.jstree(true).get_node(_id);
|
|
|
|
+ _dataArray.push(node.data);
|
|
|
|
+ _displayLabelArray.push(node.data.displayLabel);
|
|
|
|
+ if(node.children.length) {
|
|
|
|
+ _getData(node.children[0], _dataArray, _displayLabelArray);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ let dataArray = [], displayLabelArray = [];
|
|
|
|
+ _getData(_node.children[0], dataArray, displayLabelArray);
|
|
|
|
+ let dataMap = {};
|
|
|
|
+ for (let i = 0; i < dataArray.length; i++) {
|
|
|
|
+ dataMap[dataArray[i].displayLabel] = JSON.parse(JSON.stringify(dataArray[i]));
|
|
|
|
+ delete dataMap[dataArray[i].displayLabel].dropPercent;
|
|
|
|
+ delete dataMap[dataArray[i].displayLabel].id;
|
|
|
|
+ delete dataMap[dataArray[i].displayLabel].lastRefreshCount;
|
|
|
|
+ delete dataMap[dataArray[i].displayLabel].treeOrderPositionIndex;
|
|
|
|
+ delete dataMap[dataArray[i].displayLabel].uid;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // get all permutations
|
|
|
|
+ let permutations = _permute(displayLabelArray);
|
|
|
|
+
|
|
|
|
+ // create child tree for each permutation
|
|
|
|
+ function _childTreeFromArray(_array, _index = 0) {
|
|
|
|
+ let children = [];
|
|
|
|
+ if(_index < _array.length - 1) {
|
|
|
|
+ children.push(_childTreeFromArray(_array, _index + 1));
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ text: '<span class="stat-tree-anchor">' + _array[_index] + '</span><span class="ml-2 text-secondary line-count-label">(…)</span>',
|
|
|
|
+ state: {
|
|
|
|
+ opened: true,
|
|
|
|
+ disabled: false,
|
|
|
|
+ selected: false,
|
|
|
|
+ },
|
|
|
|
+ children: children,
|
|
|
|
+ data: {
|
|
|
|
+ type: "stat_tree_line",
|
|
|
|
+ displayLabel: _array[_index],
|
|
|
|
+ columns: dataMap[_array[_index]].columns,
|
|
|
|
+ clause: dataMap[_array[_index]].clause
|
|
|
|
+ },
|
|
|
|
+ a_attr: {
|
|
|
|
+ title: dataMap[_array[_index]].clause.clause_text
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // clear current children
|
|
|
|
+ this.el.jstree(true).delete_node(_node.children[0]);
|
|
|
|
+
|
|
|
|
+ // create new child trees
|
|
|
|
+ for (let i = 0; i < permutations.length; i++) {
|
|
|
|
+ let subTree = _childTreeFromArray(permutations[i]);
|
|
|
|
+ this.el.jstree(true).create_node(_node.id, JSON.parse(JSON.stringify(subTree)));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.setDirty();
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
pasteColumnsDeep: function(_node, _strColumns) {
|
|
pasteColumnsDeep: function(_node, _strColumns) {
|
|
_node.data.columns = JSON.parse(_strColumns);
|
|
_node.data.columns = JSON.parse(_strColumns);
|
|
for (let i = 0; i < _node.children.length; i++) {
|
|
for (let i = 0; i < _node.children.length; i++) {
|