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

100% Statements 44/44
100% Branches 16/16
100% Functions 15/15
100% Lines 41/41

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 136 137 138 139 140 141 142 143 144 145 14614x       14x         14x         8x                   4x                       51x 147x   2x               48x 2x     46x   46x     143x     143x   403x           143x                   47x 46x 46x           1x                 44x         110x 7x     43x       8x 7x   19x 19x   12x   1x 2x 1x     35x     43x 4x       43x   43x     43x     43x     43x   1x        
import { Injectable } from '@angular/core';
 
import { Link } from 'ish-core/models/link/link.model';
 
import { ContentPageTreeHelper } from './content-page-tree.helper';
import { ContentPageTreeData } from './content-page-tree.interface';
import { ContentPageTree, ContentPageTreeElement } from './content-page-tree.model';
 
@Injectable({ providedIn: 'root' })
export class ContentPageTreeMapper {
  /**
   * Check type of elements
   */
  private areElementsContentPageTreeData(elements: ContentPageTreeData[] | Link[]): elements is ContentPageTreeData[] {
    return (elements as ContentPageTreeData[])[0].type === 'PageTreeRO';
  }
 
  /**
   *
   * @param tree parent page tree
   * @param element page tree link
   * @returns converted page tree
   */
  convertLinkToTreeData(tree: ContentPageTreeData, element: Link): ContentPageTreeData {
    return {
      page: element,
      type: 'PageTreeRO',
      path: tree.path ? [...tree.path, element] : [tree.page, element], // add element to path if exists or create a new one
    };
  }
 
  /**
   * Utility Method:
   * Maps the incoming raw page tree path to a path with unique IDs.
   */
  mapContentPageTreeElementPath(path: Link[]) {
    if (path?.length) {
      return path.map(x => x?.itemId);
    }
    throw new Error('input is falsy');
  }
 
  /**
   * Utility Method:
   * Creates page tree stubs from the page tree path
   */
  treeElementsFromTreeElementPath(path: Link[]): ContentPageTree {
    if (!path?.length) {
      return ContentPageTreeHelper.empty();
    }
 
    const newTreeElementPath: string[] = [];
 
    return (
      path
        .map(pathElement => {
          newTreeElementPath.push(pathElement.itemId);
 
          // yield page tree element
          return {
            name: pathElement.title,
            path: [...newTreeElementPath].filter((v, i, a) => a.indexOf(v) === i),
            contentPageId: pathElement.itemId,
          };
        })
        // construct a tree from it
        .reduce(
          (tree, element: ContentPageTreeElement) => ContentPageTreeHelper.add(tree, element),
          ContentPageTreeHelper.empty()
        )
    );
  }
 
  /**
   * Maps a raw {@link ContentPageTreeData } element to a {@link ContentPageTreeElement} element ignoring sub elements.
   */
  fromDataSingle(treeData: ContentPageTreeData): ContentPageTreeElement {
    if (treeData) {
      const treePath = this.mapContentPageTreeElementPath(treeData.path);
      return {
        contentPageId: treeData.page?.itemId,
        path: treePath,
        name: treeData.page?.title,
      };
    } else {
      throw new Error(`'treeData' is required`);
    }
  }
 
  /**
   * Converts the tree of {@link ContentPageTreeData} to the model entity {@link ContentPageTree}.
   * Inserts all sub categories accordingly.
   */
  fromData(treeData: ContentPageTreeData): ContentPageTree {
    if (treeData) {
      // recurse into tree
      let subTrees: ContentPageTree;
 
      // add page tree element to path, if it does not exists in current path
      if (treeData.parent && treeData.path?.filter(e => e === treeData.page).length === 0) {
        treeData.path = [...treeData.path, treeData.page];
      }
 
      if (treeData.elements?.length) {
        /**
         * check type of available elements: {@link ContentPageTreeData} or {@link Link}.
         */
        if (this.areElementsContentPageTreeData(treeData.elements)) {
          subTrees = treeData.elements
            .map(c => {
              c.path = [...c.path, c.page];
              return this.fromData(c) as ContentPageTree;
            })
            .reduce((a, b) => ContentPageTreeHelper.merge(a, b));
        } else {
          subTrees = treeData.elements
            .map(c => this.fromData(this.convertLinkToTreeData(treeData, c)) as ContentPageTree)
            .reduce((a, b) => ContentPageTreeHelper.merge(a, b));
        }
      } else {
        subTrees = ContentPageTreeHelper.empty();
      }
 
      if (!treeData.path) {
        treeData.path = [treeData.page];
      }
 
      // create tree from current tree
      const rootPage = this.fromDataSingle(treeData);
 
      const tree = ContentPageTreeHelper.single(rootPage);
 
      // create tree from current tree path stubs
      const elementPathTree = this.treeElementsFromTreeElementPath(treeData.path);
 
      // merge sub elements onto current tree
      const treeWithSubElements = ContentPageTreeHelper.merge(tree, subTrees);
 
      // merge current tree path stubs onto current tree
      return ContentPageTreeHelper.merge(treeWithSubElements, elementPathTree);
    } else {
      throw new Error(`'treeData' is required`);
    }
  }
}