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 146 147 148 149 150 151 | 30x 30x 30x 30x 30x 30x 91x 78x 76x 122x 122x 2x 75x 2x 73x 73x 118x 45x 45x 45x 45x 79x 1x 78x 78x 4x 78x 32x 78x 2x 78x 1x 78x 74x 73x 73x 73x 1x 71x 70x 12x 34x 22x 58x 70x 70x 70x 70x 70x 1x | import { Injectable } from '@angular/core';
import { CategoryTreeHelper } from 'ish-core/models/category-tree/category-tree.helper';
import { CategoryTree } from 'ish-core/models/category-tree/category-tree.model';
import { ImageMapper } from 'ish-core/models/image/image.mapper';
import { SeoAttributesMapper } from 'ish-core/models/seo-attributes/seo-attributes.mapper';
import { CategoryData, CategoryPathElement } from './category.interface';
import { Category, CategoryHelper } from './category.model';
@Injectable({ providedIn: 'root' })
export class CategoryMapper {
constructor(private imageMapper: ImageMapper) {}
/**
* Utility Method:
* Maps the incoming raw category path to a path with unique IDs.
*/
mapCategoryPath(path: CategoryPathElement[]) {
if (path?.length) {
return path
.map(x => x.id)
.reduce((acc, _, idx, arr) => [...acc, arr.slice(0, idx + 1).join(CategoryHelper.uniqueIdSeparator)], []);
}
throw new Error('input is falsy');
}
/**
* Utility Method:
* Creates Category stubs from the category path (excluding the last element)
*/
categoriesFromCategoryPath(path: CategoryPathElement[]): CategoryTree {
if (!path?.length) {
return CategoryTreeHelper.empty();
}
let uniqueId: string;
const newCategoryPath: string[] = [];
return (
path
// remove the last
.filter((_, idx, arr) => idx !== arr.length - 1)
.map(pathElement => {
// accumulate and construct uniqueId and categoryPath
uniqueId = !uniqueId ? pathElement.id : uniqueId + CategoryHelper.uniqueIdSeparator + pathElement.id;
newCategoryPath.push(uniqueId);
// yield category stub
return {
uniqueId,
name: pathElement.name,
completenessLevel: 0,
categoryPath: [...newCategoryPath],
};
})
// construct a tree from it
.reduce((tree, cat: Category) => CategoryTreeHelper.add(tree, cat), CategoryTreeHelper.empty())
);
}
/**
* Compute completeness level of incoming raw data.
*/
computeCompleteness(categoryData: CategoryData): number {
if (!categoryData) {
return -1;
}
// adjust CategoryCompletenessLevel.Max accordingly
let count = 0;
if (categoryData.categoryRef) {
// category path categories do not contain a categoryRef
count++;
}
if (categoryData.categoryPath && categoryData.categoryPath.length === 1) {
// root categories have no images but a single-entry categoryPath
count++;
}
if (categoryData.images) {
// images are supplied for sub categories in the category details call
count++;
}
if (categoryData.seoAttributes) {
// seo attributes are only supplied with the category details call
count++;
}
return count;
}
/**
* Maps a raw {@link CategoryData} element to a {@link Category} element ignoring subcategories.
*/
fromDataSingle(categoryData: CategoryData): Category {
if (categoryData) {
const categoryPath = this.mapCategoryPath(categoryData.categoryPath);
const uniqueId = categoryPath[categoryPath.length - 1];
return {
uniqueId,
categoryRef: categoryData.categoryRef,
categoryPath,
name: categoryData.name,
hasOnlineProducts: categoryData.hasOnlineProducts,
description: categoryData.description,
images: this.imageMapper.fromImages(categoryData.images),
attributes: categoryData.attributes,
completenessLevel: this.computeCompleteness(categoryData),
seoAttributes: SeoAttributesMapper.fromData(categoryData.seoAttributes),
};
} else {
throw new Error(`'categoryData' is required`);
}
}
/**
* Converts the tree of {@link CategoryData} to the model entity {@link CategoryTree}.
* Inserts all sub categories accordingly.
*/
fromData(categoryData: CategoryData): CategoryTree {
if (categoryData) {
// recurse into tree
let subTrees: CategoryTree;
if (categoryData.subCategories?.length) {
subTrees = categoryData.subCategories
.map(c => this.fromData(c) as CategoryTree)
.reduce((a, b) => CategoryTreeHelper.merge(a, b));
} else {
subTrees = CategoryTreeHelper.empty();
}
// create tree from current category
const rootCat = this.fromDataSingle(categoryData);
const tree = CategoryTreeHelper.single(rootCat);
// create tree from categoryPath stubs
const categoryPathTree = this.categoriesFromCategoryPath(categoryData.categoryPath);
// merge sub categories onto current tree
const treeWithSubCategories = CategoryTreeHelper.merge(tree, subTrees);
// merge categoryPath stubs onto current tree
return CategoryTreeHelper.merge(treeWithSubCategories, categoryPathTree);
} else {
throw new Error(`'categoryData' is required`);
}
}
}
|