simple-tree-utils
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -24,2 +24,5 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treeUtils = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
exports.TreeUtils = void 0; | ||
const DEFAULT_ID_PROP = 'id'; | ||
const DEFAULT_PARENT_ID_PROP = 'parentId'; | ||
const DEFAULT_CHILDREN_PROP = 'children'; | ||
/** | ||
@@ -29,2 +32,7 @@ * Class to transform and manipulate tree like structures | ||
class TreeUtils { | ||
constructor(config) { | ||
this.idProp = (config === null || config === void 0 ? void 0 : config.idProp) || DEFAULT_ID_PROP; | ||
this.parentIdProp = (config === null || config === void 0 ? void 0 : config.parentIdProp) || DEFAULT_PARENT_ID_PROP; | ||
this.childrenProp = (config === null || config === void 0 ? void 0 : config.childrenProp) || DEFAULT_CHILDREN_PROP; | ||
} | ||
/** | ||
@@ -37,4 +45,4 @@ * Convert list to tree like structure | ||
return TreeUtils.deepCopy(list) | ||
.filter((item) => item.parentId === parentId) | ||
.map((item) => (Object.assign(Object.assign({}, item), { children: this.list2Tree(list, item.id) }))); | ||
.filter((item) => item[this.parentIdProp] === parentId) | ||
.map((item) => (Object.assign(Object.assign({}, item), { [this.childrenProp]: this.list2Tree(list, item[this.idProp]) }))); | ||
} | ||
@@ -48,7 +56,7 @@ /** | ||
return TreeUtils.deepCopy(tree).reduce((acc, curr) => { | ||
const { children } = curr, rest = __rest(curr, ["children"]); | ||
const { children = [this.childrenProp] } = curr, rest = __rest(curr, ["children"]); | ||
return [ | ||
...acc, | ||
Object.assign(Object.assign({}, rest), { parentId }), | ||
...(children.length ? this.tree2List(children, rest.id) : []) | ||
Object.assign(Object.assign({}, rest), { [this.parentIdProp]: parentId }), | ||
...(children.length ? this.tree2List(children, rest[this.idProp]) : []) | ||
]; | ||
@@ -58,3 +66,3 @@ }, []); | ||
findTreeNodeById(tree, id) { | ||
return this.findTreeNode(tree, item => item.id === id); | ||
return this.findTreeNode(tree, item => item[this.idProp] === id); | ||
} | ||
@@ -66,10 +74,14 @@ findTreeNode(tree, fn) { | ||
} | ||
return tree.reduce((acc, curr) => acc || this.findTreeNode(curr.children || [], fn), null); | ||
return tree.reduce((acc, curr) => acc || this.findTreeNode(curr[this.childrenProp] || [], fn), null); | ||
} | ||
findAllTreeNodes(tree, fn) { | ||
const nodes = tree.filter(item => fn(item)); | ||
return tree.reduce((acc, curr) => ([...acc, ...(curr[this.childrenProp].length ? this.findAllTreeNodes(curr[this.childrenProp], fn) : [])]), nodes); | ||
} | ||
deleteNode(tree, id) { | ||
const index = tree.findIndex(item => item.id == id); | ||
const index = tree.findIndex(item => item[this.idProp] == id); | ||
if (index != -1) { | ||
return tree.splice(index, 1)[0]; | ||
} | ||
return tree.reduce((acc, curr) => acc || this.deleteNode(curr.children, id), null); | ||
return tree.reduce((acc, curr) => acc || this.deleteNode(curr[this.childrenProp], id), null); | ||
} | ||
@@ -81,16 +93,16 @@ addNode(tree, parentId, childData) { | ||
} | ||
const index = tree.findIndex(item => item.id == parentId); | ||
const index = tree.findIndex(item => item[this.idProp] == parentId); | ||
if (index != -1) { | ||
tree[index].children.push(Object.assign({ children: [] }, childData)); | ||
tree[index][this.childrenProp].push(Object.assign({ [this.childrenProp]: [] }, childData)); | ||
return; | ||
} | ||
tree.forEach(item => this.addNode(item.children, parentId, childData)); | ||
tree.forEach(item => this.addNode(item[this.childrenProp], parentId, childData)); | ||
} | ||
editNode(tree, id, data) { | ||
const index = tree.findIndex(item => item.id == id); | ||
const index = tree.findIndex(item => item[this.idProp] == id); | ||
if (index != -1) { | ||
tree[index] = Object.assign({ id: tree[index].id, children: [] }, data); | ||
tree[index] = Object.assign({ [this.idProp]: tree[index][this.idProp], [this.childrenProp]: [] }, data); | ||
return; | ||
} | ||
tree.forEach(item => this.editNode(item.children, id, data)); | ||
tree.forEach(item => this.editNode(item[this.childrenProp], id, data)); | ||
} | ||
@@ -100,4 +112,4 @@ findAllChildrenNodes(tree, id) { | ||
return node ? [ | ||
...node.children, | ||
...node.children.reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
...node[this.childrenProp], | ||
...node[this.childrenProp].reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
] : []; | ||
@@ -107,4 +119,4 @@ } | ||
return [ | ||
...node.children, | ||
...node.children.reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
...node[this.childrenProp], | ||
...node[this.childrenProp].reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
]; | ||
@@ -117,3 +129,3 @@ } | ||
parents.push(parent); | ||
parent = this.findNodeParent(tree, parent.id); | ||
parent = this.findNodeParent(tree, parent[this.idProp]); | ||
} | ||
@@ -123,7 +135,7 @@ return parents.reverse(); | ||
findNodeParent(tree, id, parent = null) { | ||
const node = tree.find(item => item.id === id); | ||
const node = tree.find(item => item[this.idProp] === id); | ||
if (node) { | ||
return parent; | ||
} | ||
return tree.reduce((acc, curr) => acc || this.findNodeParent(curr.children || [], id, curr), null); | ||
return tree.reduce((acc, curr) => acc || this.findNodeParent(curr[this.childrenProp] || [], id, curr), null); | ||
} | ||
@@ -130,0 +142,0 @@ static deepCopy(obj) { |
@@ -1,1 +0,1 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treeUtils=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TreeUtils=void 0;var main_1=require("./main");Object.defineProperty(exports,"TreeUtils",{enumerable:true,get:function(){return main_1.TreeUtils}})},{"./main":2}],2:[function(require,module,exports){"use strict";var __rest=this&&this.__rest||function(s,e){var t={};for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p)&&e.indexOf(p)<0)t[p]=s[p];if(s!=null&&typeof Object.getOwnPropertySymbols==="function")for(var i=0,p=Object.getOwnPropertySymbols(s);i<p.length;i++){if(e.indexOf(p[i])<0&&Object.prototype.propertyIsEnumerable.call(s,p[i]))t[p[i]]=s[p[i]]}return t};Object.defineProperty(exports,"__esModule",{value:true});exports.TreeUtils=void 0;class TreeUtils{list2Tree(list,parentId=null){return TreeUtils.deepCopy(list).filter(item=>item.parentId===parentId).map(item=>Object.assign(Object.assign({},item),{children:this.list2Tree(list,item.id)}))}tree2List(tree,parentId=null){return TreeUtils.deepCopy(tree).reduce((acc,curr)=>{const{children}=curr,rest=__rest(curr,["children"]);return[...acc,Object.assign(Object.assign({},rest),{parentId:parentId}),...children.length?this.tree2List(children,rest.id):[]]},[])}findTreeNodeById(tree,id){return this.findTreeNode(tree,item=>item.id===id)}findTreeNode(tree,fn){const node=tree.find(item=>fn(item));if(node){return node}return tree.reduce((acc,curr)=>acc||this.findTreeNode(curr.children||[],fn),null)}deleteNode(tree,id){const index=tree.findIndex(item=>item.id==id);if(index!=-1){return tree.splice(index,1)[0]}return tree.reduce((acc,curr)=>acc||this.deleteNode(curr.children,id),null)}addNode(tree,parentId,childData){if(parentId==null){tree.push(childData);return}const index=tree.findIndex(item=>item.id==parentId);if(index!=-1){tree[index].children.push(Object.assign({children:[]},childData));return}tree.forEach(item=>this.addNode(item.children,parentId,childData))}editNode(tree,id,data){const index=tree.findIndex(item=>item.id==id);if(index!=-1){tree[index]=Object.assign({id:tree[index].id,children:[]},data);return}tree.forEach(item=>this.editNode(item.children,id,data))}findAllChildrenNodes(tree,id){const node=this.findTreeNodeById(tree,id);return node?[...node.children,...node.children.reduce((acc,curr)=>[...acc,...this.getChildrenNodes(curr)],[])]:[]}getChildrenNodes(node){return[...node.children,...node.children.reduce((acc,curr)=>[...acc,...this.getChildrenNodes(curr)],[])]}findAllParentNodes(tree,id){const parents=[];let parent=this.findNodeParent(tree,id);while(parent){parents.push(parent);parent=this.findNodeParent(tree,parent.id)}return parents.reverse()}findNodeParent(tree,id,parent=null){const node=tree.find(item=>item.id===id);if(node){return parent}return tree.reduce((acc,curr)=>acc||this.findNodeParent(curr.children||[],id,curr),null)}static deepCopy(obj){return JSON.parse(JSON.stringify(obj))}}exports.TreeUtils=TreeUtils},{}]},{},[1])(1)}); | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.treeUtils=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TreeUtils=void 0;var main_1=require("./main");Object.defineProperty(exports,"TreeUtils",{enumerable:true,get:function(){return main_1.TreeUtils}})},{"./main":2}],2:[function(require,module,exports){"use strict";var __rest=this&&this.__rest||function(s,e){var t={};for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p)&&e.indexOf(p)<0)t[p]=s[p];if(s!=null&&typeof Object.getOwnPropertySymbols==="function")for(var i=0,p=Object.getOwnPropertySymbols(s);i<p.length;i++){if(e.indexOf(p[i])<0&&Object.prototype.propertyIsEnumerable.call(s,p[i]))t[p[i]]=s[p[i]]}return t};Object.defineProperty(exports,"__esModule",{value:true});exports.TreeUtils=void 0;const DEFAULT_ID_PROP="id";const DEFAULT_PARENT_ID_PROP="parentId";const DEFAULT_CHILDREN_PROP="children";class TreeUtils{constructor(config){this.idProp=(config===null||config===void 0?void 0:config.idProp)||DEFAULT_ID_PROP;this.parentIdProp=(config===null||config===void 0?void 0:config.parentIdProp)||DEFAULT_PARENT_ID_PROP;this.childrenProp=(config===null||config===void 0?void 0:config.childrenProp)||DEFAULT_CHILDREN_PROP}list2Tree(list,parentId=null){return TreeUtils.deepCopy(list).filter(item=>item[this.parentIdProp]===parentId).map(item=>Object.assign(Object.assign({},item),{[this.childrenProp]:this.list2Tree(list,item[this.idProp])}))}tree2List(tree,parentId=null){return TreeUtils.deepCopy(tree).reduce((acc,curr)=>{const{children=[this.childrenProp]}=curr,rest=__rest(curr,["children"]);return[...acc,Object.assign(Object.assign({},rest),{[this.parentIdProp]:parentId}),...children.length?this.tree2List(children,rest[this.idProp]):[]]},[])}findTreeNodeById(tree,id){return this.findTreeNode(tree,item=>item[this.idProp]===id)}findTreeNode(tree,fn){const node=tree.find(item=>fn(item));if(node){return node}return tree.reduce((acc,curr)=>acc||this.findTreeNode(curr[this.childrenProp]||[],fn),null)}findAllTreeNodes(tree,fn){const nodes=tree.filter(item=>fn(item));return tree.reduce((acc,curr)=>[...acc,...curr[this.childrenProp].length?this.findAllTreeNodes(curr[this.childrenProp],fn):[]],nodes)}deleteNode(tree,id){const index=tree.findIndex(item=>item[this.idProp]==id);if(index!=-1){return tree.splice(index,1)[0]}return tree.reduce((acc,curr)=>acc||this.deleteNode(curr[this.childrenProp],id),null)}addNode(tree,parentId,childData){if(parentId==null){tree.push(childData);return}const index=tree.findIndex(item=>item[this.idProp]==parentId);if(index!=-1){tree[index][this.childrenProp].push(Object.assign({[this.childrenProp]:[]},childData));return}tree.forEach(item=>this.addNode(item[this.childrenProp],parentId,childData))}editNode(tree,id,data){const index=tree.findIndex(item=>item[this.idProp]==id);if(index!=-1){tree[index]=Object.assign({[this.idProp]:tree[index][this.idProp],[this.childrenProp]:[]},data);return}tree.forEach(item=>this.editNode(item[this.childrenProp],id,data))}findAllChildrenNodes(tree,id){const node=this.findTreeNodeById(tree,id);return node?[...node[this.childrenProp],...node[this.childrenProp].reduce((acc,curr)=>[...acc,...this.getChildrenNodes(curr)],[])]:[]}getChildrenNodes(node){return[...node[this.childrenProp],...node[this.childrenProp].reduce((acc,curr)=>[...acc,...this.getChildrenNodes(curr)],[])]}findAllParentNodes(tree,id){const parents=[];let parent=this.findNodeParent(tree,id);while(parent){parents.push(parent);parent=this.findNodeParent(tree,parent[this.idProp])}return parents.reverse()}findNodeParent(tree,id,parent=null){const node=tree.find(item=>item[this.idProp]===id);if(node){return parent}return tree.reduce((acc,curr)=>acc||this.findNodeParent(curr[this.childrenProp]||[],id,curr),null)}static deepCopy(obj){return JSON.parse(JSON.stringify(obj))}}exports.TreeUtils=TreeUtils},{}]},{},[1])(1)}); |
@@ -0,1 +1,6 @@ | ||
interface IConfig { | ||
idProp?: string; | ||
parentIdProp?: string; | ||
childrenProp?: string; | ||
} | ||
/** | ||
@@ -5,2 +10,6 @@ * Class to transform and manipulate tree like structures | ||
export declare class TreeUtils { | ||
private readonly idProp; | ||
private readonly parentIdProp; | ||
private readonly childrenProp; | ||
constructor(config?: IConfig); | ||
/** | ||
@@ -20,2 +29,3 @@ * Convert list to tree like structure | ||
findTreeNode(tree: any[], fn: (item: any) => boolean): any; | ||
findAllTreeNodes(tree: any[], fn: (item: any) => boolean): any; | ||
deleteNode(tree: any[], id: any): any; | ||
@@ -30,1 +40,2 @@ addNode(tree: any[], parentId: any, childData: any): void; | ||
} | ||
export {}; |
@@ -16,2 +16,5 @@ "use strict"; | ||
exports.TreeUtils = void 0; | ||
const DEFAULT_ID_PROP = 'id'; | ||
const DEFAULT_PARENT_ID_PROP = 'parentId'; | ||
const DEFAULT_CHILDREN_PROP = 'children'; | ||
/** | ||
@@ -21,2 +24,7 @@ * Class to transform and manipulate tree like structures | ||
class TreeUtils { | ||
constructor(config) { | ||
this.idProp = (config === null || config === void 0 ? void 0 : config.idProp) || DEFAULT_ID_PROP; | ||
this.parentIdProp = (config === null || config === void 0 ? void 0 : config.parentIdProp) || DEFAULT_PARENT_ID_PROP; | ||
this.childrenProp = (config === null || config === void 0 ? void 0 : config.childrenProp) || DEFAULT_CHILDREN_PROP; | ||
} | ||
/** | ||
@@ -29,4 +37,4 @@ * Convert list to tree like structure | ||
return TreeUtils.deepCopy(list) | ||
.filter((item) => item.parentId === parentId) | ||
.map((item) => (Object.assign(Object.assign({}, item), { children: this.list2Tree(list, item.id) }))); | ||
.filter((item) => item[this.parentIdProp] === parentId) | ||
.map((item) => (Object.assign(Object.assign({}, item), { [this.childrenProp]: this.list2Tree(list, item[this.idProp]) }))); | ||
} | ||
@@ -40,7 +48,7 @@ /** | ||
return TreeUtils.deepCopy(tree).reduce((acc, curr) => { | ||
const { children } = curr, rest = __rest(curr, ["children"]); | ||
const { children = [this.childrenProp] } = curr, rest = __rest(curr, ["children"]); | ||
return [ | ||
...acc, | ||
Object.assign(Object.assign({}, rest), { parentId }), | ||
...(children.length ? this.tree2List(children, rest.id) : []) | ||
Object.assign(Object.assign({}, rest), { [this.parentIdProp]: parentId }), | ||
...(children.length ? this.tree2List(children, rest[this.idProp]) : []) | ||
]; | ||
@@ -50,3 +58,3 @@ }, []); | ||
findTreeNodeById(tree, id) { | ||
return this.findTreeNode(tree, item => item.id === id); | ||
return this.findTreeNode(tree, item => item[this.idProp] === id); | ||
} | ||
@@ -58,10 +66,14 @@ findTreeNode(tree, fn) { | ||
} | ||
return tree.reduce((acc, curr) => acc || this.findTreeNode(curr.children || [], fn), null); | ||
return tree.reduce((acc, curr) => acc || this.findTreeNode(curr[this.childrenProp] || [], fn), null); | ||
} | ||
findAllTreeNodes(tree, fn) { | ||
const nodes = tree.filter(item => fn(item)); | ||
return tree.reduce((acc, curr) => ([...acc, ...(curr[this.childrenProp].length ? this.findAllTreeNodes(curr[this.childrenProp], fn) : [])]), nodes); | ||
} | ||
deleteNode(tree, id) { | ||
const index = tree.findIndex(item => item.id == id); | ||
const index = tree.findIndex(item => item[this.idProp] == id); | ||
if (index != -1) { | ||
return tree.splice(index, 1)[0]; | ||
} | ||
return tree.reduce((acc, curr) => acc || this.deleteNode(curr.children, id), null); | ||
return tree.reduce((acc, curr) => acc || this.deleteNode(curr[this.childrenProp], id), null); | ||
} | ||
@@ -73,16 +85,16 @@ addNode(tree, parentId, childData) { | ||
} | ||
const index = tree.findIndex(item => item.id == parentId); | ||
const index = tree.findIndex(item => item[this.idProp] == parentId); | ||
if (index != -1) { | ||
tree[index].children.push(Object.assign({ children: [] }, childData)); | ||
tree[index][this.childrenProp].push(Object.assign({ [this.childrenProp]: [] }, childData)); | ||
return; | ||
} | ||
tree.forEach(item => this.addNode(item.children, parentId, childData)); | ||
tree.forEach(item => this.addNode(item[this.childrenProp], parentId, childData)); | ||
} | ||
editNode(tree, id, data) { | ||
const index = tree.findIndex(item => item.id == id); | ||
const index = tree.findIndex(item => item[this.idProp] == id); | ||
if (index != -1) { | ||
tree[index] = Object.assign({ id: tree[index].id, children: [] }, data); | ||
tree[index] = Object.assign({ [this.idProp]: tree[index][this.idProp], [this.childrenProp]: [] }, data); | ||
return; | ||
} | ||
tree.forEach(item => this.editNode(item.children, id, data)); | ||
tree.forEach(item => this.editNode(item[this.childrenProp], id, data)); | ||
} | ||
@@ -92,4 +104,4 @@ findAllChildrenNodes(tree, id) { | ||
return node ? [ | ||
...node.children, | ||
...node.children.reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
...node[this.childrenProp], | ||
...node[this.childrenProp].reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
] : []; | ||
@@ -99,4 +111,4 @@ } | ||
return [ | ||
...node.children, | ||
...node.children.reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
...node[this.childrenProp], | ||
...node[this.childrenProp].reduce((acc, curr) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
]; | ||
@@ -109,3 +121,3 @@ } | ||
parents.push(parent); | ||
parent = this.findNodeParent(tree, parent.id); | ||
parent = this.findNodeParent(tree, parent[this.idProp]); | ||
} | ||
@@ -115,7 +127,7 @@ return parents.reverse(); | ||
findNodeParent(tree, id, parent = null) { | ||
const node = tree.find(item => item.id === id); | ||
const node = tree.find(item => item[this.idProp] === id); | ||
if (node) { | ||
return parent; | ||
} | ||
return tree.reduce((acc, curr) => acc || this.findNodeParent(curr.children || [], id, curr), null); | ||
return tree.reduce((acc, curr) => acc || this.findNodeParent(curr[this.childrenProp] || [], id, curr), null); | ||
} | ||
@@ -122,0 +134,0 @@ static deepCopy(obj) { |
{ | ||
"name": "simple-tree-utils", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Tree utils library.", | ||
@@ -5,0 +5,0 @@ "keywords": [], |
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
interface IConfig { | ||
idProp?: string, | ||
parentIdProp?: string, | ||
childrenProp?: string, | ||
} | ||
const DEFAULT_ID_PROP = 'id'; | ||
const DEFAULT_PARENT_ID_PROP = 'parentId'; | ||
const DEFAULT_CHILDREN_PROP = 'children'; | ||
/** | ||
@@ -8,2 +18,12 @@ * Class to transform and manipulate tree like structures | ||
private readonly idProp: string; | ||
private readonly parentIdProp: string; | ||
private readonly childrenProp: string; | ||
constructor(config?: IConfig) { | ||
this.idProp = config?.idProp || DEFAULT_ID_PROP; | ||
this.parentIdProp = config?.parentIdProp || DEFAULT_PARENT_ID_PROP; | ||
this.childrenProp = config?.childrenProp || DEFAULT_CHILDREN_PROP; | ||
} | ||
/** | ||
@@ -16,6 +36,6 @@ * Convert list to tree like structure | ||
return TreeUtils.deepCopy(list) | ||
.filter((item: any) => item.parentId === parentId) | ||
.filter((item: any) => item[this.parentIdProp] === parentId) | ||
.map((item: any) => ({ | ||
...item, | ||
children: this.list2Tree(list, item.id) | ||
[this.childrenProp]: this.list2Tree(list, item[this.idProp]) | ||
})); | ||
@@ -31,7 +51,7 @@ } | ||
return TreeUtils.deepCopy(tree).reduce((acc: any, curr: any) => { | ||
const {children, ...rest} = curr; | ||
const {children = [this.childrenProp], ...rest} = curr; | ||
return [ | ||
...acc, | ||
{...rest, parentId}, | ||
...(children.length ? this.tree2List(children, rest.id) : []) | ||
{...rest, [this.parentIdProp]: parentId}, | ||
...(children.length ? this.tree2List(children, rest[this.idProp]) : []) | ||
]; | ||
@@ -42,3 +62,3 @@ }, []) | ||
findTreeNodeById(tree: any[], id: any): any { | ||
return this.findTreeNode(tree, item => item.id === id); | ||
return this.findTreeNode(tree, item => item[this.idProp] === id); | ||
} | ||
@@ -52,12 +72,19 @@ | ||
return tree.reduce((acc, curr) => | ||
acc || this.findTreeNode(curr.children || [], fn), null | ||
acc || this.findTreeNode(curr[this.childrenProp] || [], fn), null | ||
); | ||
} | ||
findAllTreeNodes(tree: any[], fn: (item: any) => boolean): any { | ||
const nodes = tree.filter(item => fn(item)); | ||
return tree.reduce((acc, curr) => ( | ||
[...acc, ...(curr[this.childrenProp].length ? this.findAllTreeNodes(curr[this.childrenProp], fn) : [])] | ||
), nodes); | ||
} | ||
deleteNode(tree: any[], id: any): any { | ||
const index = tree.findIndex(item => item.id == id); | ||
const index = tree.findIndex(item => item[this.idProp] == id); | ||
if (index != -1) { | ||
return tree.splice(index, 1)[0]; | ||
} | ||
return tree.reduce((acc, curr) => acc || this.deleteNode(curr.children, id), null); | ||
return tree.reduce((acc, curr) => acc || this.deleteNode(curr[this.childrenProp], id), null); | ||
} | ||
@@ -70,17 +97,17 @@ | ||
} | ||
const index = tree.findIndex(item => item.id == parentId); | ||
const index = tree.findIndex(item => item[this.idProp] == parentId); | ||
if (index != -1) { | ||
tree[index].children.push({children: [], ...childData}); | ||
tree[index][this.childrenProp].push({[this.childrenProp]: [], ...childData}); | ||
return; | ||
} | ||
tree.forEach(item => this.addNode(item.children, parentId, childData)); | ||
tree.forEach(item => this.addNode(item[this.childrenProp], parentId, childData)); | ||
} | ||
editNode(tree: any[], id: any, data: any): void { | ||
const index = tree.findIndex(item => item.id == id); | ||
const index = tree.findIndex(item => item[this.idProp] == id); | ||
if (index != -1) { | ||
tree[index] = {id: tree[index].id, children: [], ...data}; | ||
tree[index] = {[this.idProp]: tree[index][this.idProp], [this.childrenProp]: [], ...data}; | ||
return; | ||
} | ||
tree.forEach(item => this.editNode(item.children, id, data)); | ||
tree.forEach(item => this.editNode(item[this.childrenProp], id, data)); | ||
} | ||
@@ -91,4 +118,4 @@ | ||
return node ? [ | ||
...node.children, | ||
...node.children.reduce((acc: any, curr: any) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
...node[this.childrenProp], | ||
...node[this.childrenProp].reduce((acc: any, curr: any) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
] : []; | ||
@@ -99,4 +126,4 @@ } | ||
return [ | ||
...node.children, | ||
...node.children.reduce((acc: any, curr: any) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
...node[this.childrenProp], | ||
...node[this.childrenProp].reduce((acc: any, curr: any) => ([...acc, ...this.getChildrenNodes(curr)]), []) | ||
]; | ||
@@ -110,3 +137,3 @@ } | ||
parents.push(parent); | ||
parent = this.findNodeParent(tree, parent.id); | ||
parent = this.findNodeParent(tree, parent[this.idProp]); | ||
} | ||
@@ -117,3 +144,3 @@ return parents.reverse(); | ||
findNodeParent(tree: any[], id: any, parent: any = null): any { | ||
const node = tree.find(item => item.id === id); | ||
const node = tree.find(item => item[this.idProp] === id); | ||
if (node) { | ||
@@ -123,3 +150,3 @@ return parent; | ||
return tree.reduce((acc, curr) => | ||
acc || this.findNodeParent(curr.children || [], id, curr), null | ||
acc || this.findNodeParent(curr[this.childrenProp] || [], id, curr), null | ||
); | ||
@@ -126,0 +153,0 @@ } |
@@ -115,2 +115,30 @@ import {TreeUtils} from "../src"; | ||
}); | ||
}); | ||
it('should find parent of node', () => { | ||
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS)); | ||
expect(treeUtils.findNodeParent(mock, 6).id).toBe(3); | ||
expect(treeUtils.findNodeParent(mock, 1)).toBeNull(); | ||
}); | ||
it('should find ALL parents of node', () => { | ||
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS)); | ||
expect(treeUtils.findAllParentNodes(mock, 6).map((item: any) => item.id)).toEqual([1, 3]); | ||
expect(treeUtils.findAllParentNodes(mock, 4).map((item: any) => item.id)).toEqual([1]); | ||
expect(treeUtils.findAllParentNodes(mock, 5).map((item: any) => item.id)).toEqual([2]); | ||
expect(treeUtils.findAllParentNodes(mock, 1).map((item: any) => item.id)).toEqual([]); | ||
}); | ||
it('should find ALL children of node', () => { | ||
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS)); | ||
expect(treeUtils.findAllChildrenNodes(mock, 1).map((item: any) => item.id)).toEqual([3, 4, 6]); | ||
expect(treeUtils.findAllChildrenNodes(mock, 2).map((item: any) => item.id)).toEqual([5]); | ||
expect(treeUtils.findAllChildrenNodes(mock, 5).map((item: any) => item.id)).toEqual([]); | ||
}); | ||
it('should find ALL nodes that match callback', () => { | ||
const mock = JSON.parse(JSON.stringify(TREE_MOCK_ITEMS)); | ||
expect(treeUtils.findAllTreeNodes(mock, item => item.id % 2 === 0).map((item: any) => item.id)).toEqual([2, 4, 6]); | ||
expect(treeUtils.findAllTreeNodes(mock, item => item.id % 3 === 0).map((item: any) => item.id)).toEqual([3, 6]); | ||
expect(treeUtils.findAllTreeNodes(mock, item => item.name.includes('Node')).map((item: any) => item.id)).toEqual([1, 2, 3, 4, 6, 5]); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41635
671