OpenSlides/client/src/app/core/ui-services/tree.service.ts

422 lines
15 KiB
TypeScript
Raw Normal View History

2018-11-22 15:14:01 +01:00
import { Injectable } from '@angular/core';
import { Displayable } from 'app/site/base/displayable';
2018-11-22 15:14:01 +01:00
import { Identifiable } from 'app/shared/models/base/identifiable';
/**
* A basic representation of a tree node. This node does not stores any data.
2018-11-22 15:14:01 +01:00
*/
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
export interface TreeIdNode {
2018-11-22 15:14:01 +01:00
id: number;
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
children?: TreeIdNode[];
}
/**
* Extends the TreeIdNode with a name to display.
*/
export interface TreeNodeWithoutItem extends TreeIdNode {
name: string;
children?: TreeNodeWithoutItem[];
}
/**
* A representation of nodes with the item atached.
*/
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
export interface OSTreeNode<T> extends TreeNodeWithoutItem {
2018-11-22 15:14:01 +01:00
item: T;
children?: OSTreeNode<T>[];
}
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
/**
* Interface which defines the nodes for the sorting trees.
*
* Contains information like
* item: The base item the node is created from.
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
* level: The level of the node. The higher, the deeper the level.
* position: The position in the array of the node.
* isExpanded: Boolean if the node is expanded.
* expandable: Boolean if the node is expandable.
* id: The id of the node.
* filtered: Optional boolean to check, if the node is filtered.
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
*/
export interface FlatNode<T> {
item: T;
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
level: number;
position?: number;
isExpanded?: boolean;
isSeen: boolean;
expandable: boolean;
id: number;
filtered?: boolean;
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
}
2018-11-22 15:14:01 +01:00
/**
* This services handles all operations belonging to trees. It can build trees of plain lists (giving the weight
* and parentId property) and traverse the trees in pre-order.
*/
@Injectable({
providedIn: 'root'
})
2019-02-08 17:24:32 +01:00
export class TreeService {
2018-11-22 15:14:01 +01:00
/**
* Returns the weight casted to a number from a given model.
*
* @param item The model to get the weight from.
* @param key
* @returns the weight of the model
*/
private getAttributeAsNumber<T extends Identifiable & Displayable>(item: T, key: keyof T): number {
return (<any>item[key]) as number;
}
/**
* Build our representation of a tree node given the model and optional children
* to append to this node.
*
* @param item The model to create a node of.
* @param children Optional children to append to this node.
* @returns The created node.
*/
private buildTreeNode<T extends Identifiable & Displayable>(item: T, children?: OSTreeNode<T>[]): OSTreeNode<T> {
return {
name: item.getTitle(),
id: item.id,
item: item,
children: children
};
}
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
/**
* Function to build flat nodes from `OSTreeNode`s.
* Iterates recursively through the list of nodes.
*
* @param items
* @param weightKey
* @param parentKey
*
* @returns An array containing flat nodes.
*/
public makeFlatTree<T extends Identifiable & Displayable>(
items: T[],
weightKey: keyof T,
parentKey: keyof T
): FlatNode<T>[] {
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
const tree = this.makeTree(items, weightKey, parentKey);
const flatNodes: FlatNode<T>[] = [];
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
for (const node of tree) {
flatNodes.push(...this.makePartialFlatTree(node, 0));
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
}
for (let i = 0; i < flatNodes.length; ++i) {
flatNodes[i].position = i;
}
return flatNodes;
}
/**
* Function to convert a flat tree to a nested tree built from `OSTreeNodeWithOutItem`.
*
* @param nodes The array of flat nodes, which should be converted.
*
* @returns The tree with nested information.
*/
public makeTreeFromFlatTree<T extends Identifiable & Displayable>(nodes: FlatNode<T>[]): TreeIdNode[] {
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
const basicTree: TreeIdNode[] = [];
for (let i = 0; i < nodes.length; ) {
// build the next node inclusive its children
const nextNode = this.buildBranchFromFlatTree(nodes[i], nodes, 0);
// append this node to the tree
basicTree.push(nextNode.node);
// step to the next related item in the array
i += nextNode.length;
}
return basicTree;
}
2018-11-22 15:14:01 +01:00
/**
* Builds a tree from the given items on the relations between items with weight and parentId
*
* @param items All items to traverse
* @param weightKey The key giving access to the weight property
* @param parentIdKey The key giving access to the parentId property
* @returns An iterator for all items in the right order.
*/
public makeTree<T extends Identifiable & Displayable>(
items: T[],
weightKey: keyof T,
parentIdKey: keyof T
): OSTreeNode<T>[] {
// Sort items after their weight
items.sort((a, b) => this.getAttributeAsNumber(a, weightKey) - this.getAttributeAsNumber(b, weightKey));
// Build a dict with all children (dict-value) to a specific
// item id (dict-key).
const children: { [parendId: number]: T[] } = {};
items.forEach(model => {
if (model[parentIdKey]) {
const parentId = this.getAttributeAsNumber(model, parentIdKey);
if (children[parentId]) {
children[parentId].push(model);
} else {
children[parentId] = [model];
}
}
});
// Recursive function that generates a nested list with all
// items with there children
const getChildren: (_models?: T[]) => OSTreeNode<T>[] = _models => {
if (!_models) {
return;
}
const nodes: OSTreeNode<T>[] = [];
_models.forEach(_model => {
nodes.push(this.buildTreeNode(_model, getChildren(children[_model.id])));
});
return nodes;
};
// Generates the list of root items (with no parents)
const parentItems = items.filter(model => !this.getAttributeAsNumber(model, parentIdKey));
return getChildren(parentItems);
}
/**
* Removes `item` from the tree.
*
* @param tree The tree with items
* @returns The tree without items
*/
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
public stripTree<T>(tree: OSTreeNode<T>[]): TreeNodeWithoutItem[] {
return tree.map(node => {
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
const nodeWithoutItem: TreeNodeWithoutItem = {
name: node.name,
id: node.id
};
if (node.children) {
nodeWithoutItem.children = this.stripTree(node.children);
}
return nodeWithoutItem;
});
}
2019-02-04 15:41:01 +01:00
/**
* Reduce a list of items to nodes independent from each other in a given
* branch of a tree
*
* @param branch the tree to traverse
* @param items the items to check
* @returns the selection of items that belong to different branches
*/
private getTopItemsFromBranch<T extends Identifiable & Displayable>(branch: OSTreeNode<T>, items: T[]): T[] {
const item = items.find(i => branch.item.id === i.id);
if (item) {
return [item];
} else if (!branch.children) {
return [];
} else {
return [].concat(...branch.children.map(child => this.getTopItemsFromBranch(child, items)));
}
}
/**
* Searches a tree for a list of given items and fetches all branches that include
* these items and their dependants
2019-02-04 15:41:01 +01:00
*
* @param tree an array of OsTreeNode branches
* @param items the items that need to be included
*
* @returns an array of OsTreeNodes with the top-most item being included
* in the input list
2019-02-04 15:41:01 +01:00
*/
public getBranchesFromTree<T extends Identifiable & Displayable>(
tree: OSTreeNode<T>[],
items: T[]
): OSTreeNode<T>[] {
let results: OSTreeNode<T>[] = [];
2019-02-04 15:41:01 +01:00
tree.forEach(branch => {
if (items.some(item => item.id === branch.item.id)) {
results.push(branch);
} else if (branch.children && branch.children.length) {
results = results.concat(this.getBranchesFromTree(branch.children, items));
2019-02-04 15:41:01 +01:00
}
});
return results;
}
/**
* Inserts OSTreeNode branches into another tree at the position specified
*
* @param tree A (partial) tree the branches need to be inserted into. It
* is assumed that this tree does not contain the branches to be inserted.
* See also {@link getTreeWithoutSelection}
* @param branches OsTreeNodes to be inserted. See also {@link getBranchesFromTree}
* @param parentId the id of a parent node under which the branches should be inserted
* @param olderSibling (optional) the id of the item on the same level
* the tree is to be inserted behind
* @returns the re-arranged tree containing the branches
*/
public insertBranchesIntoTree<T extends Identifiable & Displayable>(
tree: OSTreeNode<T>[],
branches: OSTreeNode<T>[],
parentId: number,
olderSibling?: number
): OSTreeNode<T>[] {
if (!parentId && olderSibling) {
const older = tree.findIndex(branch => branch.id === olderSibling);
if (older >= 0) {
return [...tree.slice(0, older + 1), ...branches, ...tree.slice(older + 1)];
} else {
for (const branch of tree) {
if (branch.children && branch.children.length) {
branch.children = this.insertBranchesIntoTree(branch.children, branches, null, olderSibling);
}
}
return tree;
}
} else if (parentId) {
for (const branch of tree) {
if (branch.id !== parentId) {
if (branch.children && branch.children.length) {
branch.children = this.insertBranchesIntoTree(
branch.children,
branches,
parentId,
olderSibling
);
}
} else {
if (!branch.children) {
branch.children = branches;
} else {
if (olderSibling) {
const older = branch.children.findIndex(child => child.id === olderSibling);
if (older >= 0) {
branch.children = [
...branch.children.slice(0, older + 1),
...branches,
...branch.children.slice(older + 1)
];
}
} else {
branch.children = [...branch.children, ...branches];
}
}
}
}
return tree;
} else {
throw new Error('This should not happen. Invalid sorting items given');
}
}
/**
* Return the part of a tree not including or being hierarchically dependant
* on the items in the input arrray
2019-02-04 15:41:01 +01:00
*
* @param tree
* @param items
* @returns all the branch without the given items or their dependants
2019-02-04 15:41:01 +01:00
*/
public getTreeWithoutSelection<T extends Identifiable & Displayable>(
tree: OSTreeNode<T>[],
items: T[]
): OSTreeNode<T>[] {
const result: OSTreeNode<T>[] = [];
2019-02-04 15:41:01 +01:00
tree.forEach(branch => {
if (!items.find(i => i.id === branch.item.id)) {
if (branch.children) {
branch.children = this.getTreeWithoutSelection(branch.children, items);
2019-02-04 15:41:01 +01:00
}
result.push(branch);
2019-02-04 15:41:01 +01:00
}
});
return result;
}
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
/**
* Helper to turn a tree into an array of items
*
* @param tree
* @returns the items contained in the tree.
*/
public getFlatItemsFromTree<T extends Identifiable & Displayable>(tree: OSTreeNode<T>[]): T[] {
let result = [];
for (const branch of tree) {
result.push(branch.item);
if (branch.children && branch.children.length) {
result = result.concat(this.getFlatItemsFromTree(branch.children));
}
}
return result;
}
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
/**
* Helper function to go recursively through the children of given node.
*
* @param item The current item from which the flat node will be created.
* @param level The level the flat node will be.
* @param additionalTag Optional: A key of the items. If this parameter is set, the nodes will have a tag for filtering them.
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
*
* @returns An array containing the parent node with all its children.
*/
private makePartialFlatTree<T extends Identifiable & Displayable>(
item: OSTreeNode<T>,
level: number
): FlatNode<T>[] {
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
const children = item.children;
const node: FlatNode<T> = {
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
id: item.id,
item: item.item,
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
expandable: !!children,
isExpanded: !!children,
level: level,
isSeen: true
};
const flatNodes: FlatNode<T>[] = [node];
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
if (children) {
for (const child of children) {
flatNodes.push(...this.makePartialFlatTree(child, level + 1));
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
}
}
return flatNodes;
}
/**
* Function, that returns a node containing information like id, name and children.
* Children only, if available.
*
* @param node The node which is converted.
* @param nodes The array with all nodes to convert.
* @param length The number of converted nodes related to the parent node.
*
* @returns `OSTreeNodeWithOutItem`
*/
private buildBranchFromFlatTree<T extends Identifiable & Displayable>(
node: FlatNode<T>,
nodes: FlatNode<T>[],
Replaces the old `angular2tree` with a custom drag&drop tree Calculates the direction of the moving. Finishes the moving of nodes in same level Adds some style Sets the padding dynamically Adds placeholder depends on the horizontal movement Set the placeholder at the correct place, so the user can see, where he will drop the moved node Finishes moving of nodes - Old parents change their option to expand. - New parents change their option to expand. - If the user moves a node between nodes with a higher level, the node will be moved to the next index with same or lower level. Fixes the visibility of moved node - If the new parent is not visible, the moved node will not be seen. If the user moves an expanded node, the new parent should expanded, too, if it's not already. Sending successfully data to the server - Sorting the items Handles moving nodes between parent and children - If the user moves a node between a parent and its children, the children will be relinked to the moved node as their new parent. Replaces the old `sorting-tree` to a new one - The new `sorted-tree` replaces the old `sorting-tree`. - The old package `angular-tree-component` was removed. - The user will only see the buttons to save or cancel his changes, if he made changes. - The buttons, that do not work currently, were removed. Adds a guard to check if the user made changes. - If the user made changes but he has not saved them, then there is a dialog that will prompt to ask for confirmation. Before cancelling the changes the user has to confirm this.
2019-02-22 12:04:36 +01:00
length: number
): { node: TreeIdNode; length: number } {
const children = [];
// Begins at the position of the node in the array.
// Ends if the next node has the same or higher level than the given node.
for (let i = node.position + 1; !!nodes[i] && nodes[i].level >= node.level + 1; ++i) {
const nextNode = nodes[i];
// The next node is a child if the level is one higher than the given node.
if (nextNode.level === node.level + 1) {
// Makes the child nodes recursively.
const child = this.buildBranchFromFlatTree(nextNode, nodes, 0);
length += child.length;
children.push(child.node);
}
}
// Makes the node with child nodes.
const osNode: TreeIdNode = {
id: node.id,
children: children.length > 0 ? children : undefined
};
// Returns the built node and increase the length by one.
return { node: osNode, length: ++length };
}
2018-11-22 15:14:01 +01:00
}