refactor(menu): Made sure the menu can be used for more than group
This commit is contained in:
parent
a79898b2e9
commit
1d73ee8a78
16 changed files with 650 additions and 406 deletions
105
source/Menu/MenuTraversal.ts
Normal file
105
source/Menu/MenuTraversal.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import {AnyMenuItem, MenuItemType} from "./MenuRenderer.types";
|
||||
import {TraversalMap, StringifiedTraversalPath, TraversalPath, TraversalKey} from "./MenuTraversal.types";
|
||||
import {InvalidTraversalRouteError} from "./InvalidTraversalRouteError";
|
||||
|
||||
export class MenuTraversal {
|
||||
private readonly traversalMap: TraversalMap
|
||||
private currentPath: TraversalPath = [];
|
||||
|
||||
public get path() {
|
||||
return this.currentPath;
|
||||
}
|
||||
|
||||
public get stringifiedPath(): StringifiedTraversalPath {
|
||||
return this.stringifyTraversalPath(this.currentPath);
|
||||
}
|
||||
|
||||
public get currentMenuItem(): AnyMenuItem {
|
||||
const path = this.stringifiedPath;
|
||||
if (!this.traversalMap.has(path)) {
|
||||
throw new InvalidTraversalRouteError(this.currentPath);
|
||||
}
|
||||
|
||||
return <AnyMenuItem>this.traversalMap.get(path);
|
||||
}
|
||||
|
||||
public get isRoot(): boolean {
|
||||
return this.currentPath.length === 0;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly menu: AnyMenuItem[],
|
||||
private readonly rootLabel: string = "",
|
||||
private readonly rootDescription: string = ''
|
||||
) {
|
||||
this.traversalMap = this.generateTraversalMap();
|
||||
|
||||
}
|
||||
|
||||
public travelForward(next: TraversalKey) {
|
||||
const nextPath = [
|
||||
...this.currentPath,
|
||||
next
|
||||
];
|
||||
|
||||
if (!this.traversalMap.has(this.stringifyTraversalPath(nextPath))) {
|
||||
throw new InvalidTraversalRouteError(nextPath);
|
||||
}
|
||||
|
||||
this.currentPath = nextPath;
|
||||
}
|
||||
|
||||
public travelBack() {
|
||||
this.currentPath.pop();
|
||||
}
|
||||
|
||||
public getMenuItem(path: StringifiedTraversalPath): AnyMenuItem
|
||||
{
|
||||
if (!this.traversalMap.has(path)) {
|
||||
throw new InvalidTraversalRouteError([path]);
|
||||
}
|
||||
|
||||
return <AnyMenuItem>this.traversalMap.get(path);
|
||||
}
|
||||
|
||||
public static unstringifyTraversalPath(path: StringifiedTraversalPath): TraversalPath {
|
||||
return path.split('/');
|
||||
}
|
||||
|
||||
private generateTraversalMap(): TraversalMap {
|
||||
const map = new Map<StringifiedTraversalPath, AnyMenuItem>();
|
||||
|
||||
map.set('', {
|
||||
traversalKey: '',
|
||||
label: this.rootLabel,
|
||||
description: this.rootDescription,
|
||||
type: MenuItemType.Collection,
|
||||
children: this.menu
|
||||
});
|
||||
|
||||
const that = this;
|
||||
|
||||
function traversePath(path: TraversalPath, menuItem: AnyMenuItem) {
|
||||
path = [...path, menuItem.traversalKey];
|
||||
map.set(that.stringifyTraversalPath(path), menuItem);
|
||||
|
||||
if (menuItem.type !== MenuItemType.Collection) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuItem.children.forEach((nextMenuItem) => {
|
||||
traversePath(path, nextMenuItem);
|
||||
})
|
||||
}
|
||||
|
||||
this.menu.forEach((menuItem) => {
|
||||
traversePath([], menuItem);
|
||||
})
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private stringifyTraversalPath(path: TraversalPath): StringifiedTraversalPath {
|
||||
return path.join('/');
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue