All files / src/app/core/models/content-page-tree-view content-page-tree-view.model.ts

95.74% Statements 45/47
90% Branches 27/30
100% Functions 17/17
95.55% Lines 43/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135                      28x         24x     24x                               32x       32x     32x 14x 20x 19x       32x   32x       65x     32x                 42x 42x 20x 22x 18x 7x   8x 11x 10x 10x       42x           37x 92x 37x 37x   207x 55x     37x     28x         14x 1x   13x                 60x   60x 24x 36x       60x 60x       144x     60x    
import { ContentPageTree, ContentPageTreeElement } from 'ish-core/models/content-page-tree/content-page-tree.model';
 
/**
 * View on a {@link ContentPageTreeElement } with additional methods for navigating to sub elements or sub paths
 */
export interface ContentPageTreeView extends ContentPageTreeElement {
  parent: string;
  children: ContentPageTreeView[];
  pathElements: ContentPageTreeElement[];
}
 
export function createCompleteContentPageTreeView(
  tree: ContentPageTree,
  contentPageId: string,
  depth: number
): ContentPageTreeView {
  Iif (!tree || !contentPageId || !tree.nodes[contentPageId]) {
    return;
  }
  return unflattenTree(getCompleteContentPageTreeElements(tree, contentPageId, depth), contentPageId);
}
 
/**
 * @param tree
 * @param elementId element of page tree. It will be decided, if element is part of displayed navigation tree.
 * @param rootId
 * @param currentContentPageId
 * @returns Get all displayed navigation tree elements of current content page.
 */
function getContentPageTreeElements(
  tree: ContentPageTree,
  elementId: string,
  rootId: string,
  currentContentPageId: string
): ContentPageTreeView[] {
  Iif (!tree || !elementId || !tree.nodes[elementId]) {
    return;
  }
 
  let treeElements: ContentPageTreeView[] = [];
 
  // If current content page is part of element subtree or equals the element itself, then all children of elements should be analyzed
  if (tree.edges[elementId] && isContentPagePartOfPageTreeElement(tree, currentContentPageId, elementId)) {
    treeElements = tree.edges[elementId]
      .filter(child => child !== elementId)
      .map(child => getContentPageTreeElements(tree, child, rootId, currentContentPageId))
      .flat();
  }
 
  const parent = tree.nodes[elementId].path[tree.nodes[elementId].path.length - 2];
 
  treeElements.push({
    ...tree.nodes[elementId],
    parent,
    children: [],
    pathElements: tree.nodes[elementId].path.map(p => tree.nodes[p]),
  });
 
  return treeElements;
}
 
// Analyze if subtree of page tree element contains current content page id
function isContentPagePartOfPageTreeElement(
  tree: ContentPageTree,
  currentContentPageId: string,
  elementId: string
): boolean {
  let result = false;
  if (elementId === currentContentPageId) {
    result = true;
  } else if (tree.edges[elementId]) {
    if (tree.edges[elementId].find(e => e === currentContentPageId)) {
      result = true;
    } else {
      result = tree.edges[elementId]
        .filter(e => e !== elementId)
        .map(e => isContentPagePartOfPageTreeElement(tree, currentContentPageId, e))
        .find(res => res);
    }
  }
 
  return result;
}
 
// build page tree data based on given elements
function unflattenTree(elements: ContentPageTreeView[], rootId: string): ContentPageTreeView {
  let root: ContentPageTreeView;
  elements.map(element => {
    if (element.contentPageId === rootId) {
      root = element;
      return;
    } else {
      const parentEl = elements.find(el => el.contentPageId === element.parent);
      parentEl.children = [...(parentEl.children || []), element];
    }
  });
  return root;
}
 
export function createContentPageTreeView(
  tree: ContentPageTree,
  rootId: string,
  contentPageId: string
): ContentPageTreeView {
  if (!tree || !rootId || !tree.nodes[rootId] || !isContentPagePartOfPageTreeElement(tree, contentPageId, rootId)) {
    return;
  }
  return unflattenTree(getContentPageTreeElements(tree, rootId, rootId, contentPageId), rootId);
}
 
function getCompleteContentPageTreeElements(
  tree: ContentPageTree,
  contentPageId: string,
  depth: number,
  currentDepth = 0
): ContentPageTreeView[] {
  let treeElements: ContentPageTreeView[] = [];
 
  if (tree.edges[contentPageId] && (currentDepth < depth || Number.isNaN(depth))) {
    treeElements = tree.edges[contentPageId]
      .map(child => getCompleteContentPageTreeElements(tree, child, depth, currentDepth + 1))
      .flat();
  }
 
  const parent = tree.nodes[contentPageId].path[tree.nodes[contentPageId].path.length - 2];
  treeElements.push({
    ...tree.nodes[contentPageId],
    parent,
    children: [],
    pathElements: tree.nodes[contentPageId].path.map(p => tree.nodes[p]),
  });
 
  return treeElements;
}