|
|
|
@ -52,31 +52,16 @@ export abstract class AbstractTreeService<T extends { [key: string | number | sy |
|
|
|
return this._visible$.asObservable(); |
|
|
|
} |
|
|
|
|
|
|
|
protected createTree(items: T[]): TreeNode<T>[] { |
|
|
|
return createTreeFromList<T, TreeNode<T>>( |
|
|
|
items, |
|
|
|
item => item[this.id], |
|
|
|
item => item[this.parentId], |
|
|
|
item => BaseTreeNode.create(item), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
protected createGroupedTree(list: TreeNode<T>[]): RouteGroup<T>[] | undefined { |
|
|
|
const map = createGroupMap<T>(list, this.othersGroup); |
|
|
|
if (!map) { |
|
|
|
return undefined; |
|
|
|
} |
|
|
|
|
|
|
|
return Array.from(map, ([key, items]) => ({ group: key, items })); |
|
|
|
} |
|
|
|
|
|
|
|
private filterWith(setOrMap: Set<string> | Map<string, T>): T[] { |
|
|
|
return this._flat$.value.filter(item => !setOrMap.has(item[this.id])); |
|
|
|
} |
|
|
|
|
|
|
|
private findItemsToRemove(set: Set<string>): Set<string> { |
|
|
|
return this._flat$.value.reduce((acc, item) => { |
|
|
|
if (!acc.has(item[this.parentId])) return acc; |
|
|
|
if (!acc.has(item[this.parentId])) { |
|
|
|
return acc; |
|
|
|
} |
|
|
|
|
|
|
|
const childSet = new Set([item[this.id]]); |
|
|
|
const children = this.findItemsToRemove(childSet); |
|
|
|
return new Set([...acc, ...children]); |
|
|
|
@ -90,6 +75,24 @@ export abstract class AbstractTreeService<T extends { [key: string | number | sy |
|
|
|
return flatItems; |
|
|
|
} |
|
|
|
|
|
|
|
protected createTree(items: T[]): TreeNode<T>[] { |
|
|
|
return createTreeFromList<T, TreeNode<T>>( |
|
|
|
items, |
|
|
|
item => item[this.id], |
|
|
|
item => item[this.parentId], |
|
|
|
item => BaseTreeNode.create(item), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
protected createGroupedTree(list: TreeNode<T>[]): RouteGroup<T>[] | undefined { |
|
|
|
const map = createGroupMap<T>(list, this.othersGroup); |
|
|
|
if (!map) { |
|
|
|
return undefined; |
|
|
|
} |
|
|
|
|
|
|
|
return Array.from(map, ([key, items]) => ({ group: key, items })); |
|
|
|
} |
|
|
|
|
|
|
|
add(items: T[]): T[] { |
|
|
|
if (this.filterRoutesEnabled) { |
|
|
|
const map = new Map<string, T>(); |
|
|
|
@ -137,17 +140,26 @@ export abstract class AbstractTreeService<T extends { [key: string | number | sy |
|
|
|
this.filterRoutesEnabled = true; |
|
|
|
} |
|
|
|
|
|
|
|
find(predicate: (item: TreeNode<T>) => boolean, tree = this.tree): TreeNode<T> | null { |
|
|
|
return tree.reduce<TreeNode<T> | null>( |
|
|
|
(acc, node) => (acc ? acc : predicate(node) ? node : this.find(predicate, node.children)), |
|
|
|
null, |
|
|
|
); |
|
|
|
find(predicate: (item: TreeNode<T>) => boolean, tree = this.tree): TreeNode<T> | null { |
|
|
|
return tree.reduce<TreeNode<T> | null>((acc, node) => { |
|
|
|
if (acc) { |
|
|
|
return acc; |
|
|
|
} |
|
|
|
|
|
|
|
if (predicate(node)) { |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
return this.find(predicate, node.children); |
|
|
|
}, null); |
|
|
|
} |
|
|
|
|
|
|
|
patch(identifier: string, props: Partial<T>): T[] | false { |
|
|
|
const flatItems = this._flat$.value; |
|
|
|
const index = flatItems.findIndex(item => item[this.id] === identifier); |
|
|
|
if (index < 0) return false; |
|
|
|
if (index < 0) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
flatItems[index] = { ...flatItems[index], ...props }; |
|
|
|
|
|
|
|
@ -171,15 +183,17 @@ export abstract class AbstractTreeService<T extends { [key: string | number | sy |
|
|
|
search(params: Partial<T>, tree = this.tree): TreeNode<T> | null { |
|
|
|
const searchKeys = Object.keys(params) as Array<keyof Partial<T>>; |
|
|
|
|
|
|
|
return tree.reduce<TreeNode<T> | null>( |
|
|
|
(acc, node) => |
|
|
|
acc |
|
|
|
? acc |
|
|
|
: searchKeys.every(key => node[key] === params[key]) |
|
|
|
? node |
|
|
|
: this.search(params, node.children), |
|
|
|
null, |
|
|
|
); |
|
|
|
return tree.reduce<TreeNode<T> | null>((acc, node) => { |
|
|
|
if (acc) { |
|
|
|
return acc; |
|
|
|
} |
|
|
|
|
|
|
|
if (searchKeys.every(key => node.item[key] === params[key])) { |
|
|
|
return node; |
|
|
|
} |
|
|
|
|
|
|
|
return this.search(params, node.children); |
|
|
|
}, null); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|