import {Model} from './Model'; import Dexie from 'dexie'; export interface IMenuItem { id?: number; serverId: string; name: string; childIds?: string[]; noDelete?: boolean; noChildren?: boolean; virtual?: boolean; type?: string; shared?: boolean; needsServerUpdate?: boolean; offlineUpdatedAt?: string; faIconClass?: string; } export class MenuItem extends Model implements IMenuItem { id?: number; serverId: string; name: string; childIds?: string[]; noDelete?: boolean; noChildren?: boolean; virtual?: boolean; type?: string; shared?: boolean; needsServerUpdate?: boolean; offlineUpdatedAt?: string; faIconClass?: string; public static getTableName() { return 'menuItems'; } public static getSchema() { // tslint:disable-next-line:max-line-length return '++id, serverId, name, childIds, noDelete, noChildren, virtual, type, shared, needsServerUpdate, offlineUpdatedAt, faIconClass'; } public static deflateTree(nodes: any[]): MenuItem[] { let items = []; for ( const node of nodes ) { const childIds = node.children ? node.children.map(x => x.id) : []; const item = new MenuItem( node.name, node.id, childIds, node.noDelete, node.noChildren, node.virtual, node.type, node.shared, node.faIconClass ); items.push(item); if ( node.children ) { items = items.concat(...this.deflateTree(node.children)); } } return items; } public static inflateTree(items: MenuItem[]) { const serverIdXItems: { [key: string]: MenuItem[] } = {}; for ( const item of items ) { if ( !serverIdXItems[item.serverId] ) { serverIdXItems[item.serverId] = []; } serverIdXItems[item.serverId].push(item); } const inflateNode = (item, alreadyChildren = [], seen = []) => { const node: any = item.getSaveRecord(); seen.push(item); node.id = node.serverId; node.children = []; if ( item.childIds ) { for ( const childId of item.childIds ) { if ( serverIdXItems[childId] ) { const children = serverIdXItems[childId].filter(x => { if ( x.type !== 'page' && item.serverId !== x.serverId ) { return false; } return x !== item && !alreadyChildren.includes(x) && !seen.includes(x); }); node.children = node.children.concat(...children.map(x => inflateNode(x, children, seen))); } } } const pageChildren = []; const otherChildren = []; for ( const child of node.children ) { if ( child.type === 'page' ) { pageChildren.push(child); } else { otherChildren.push(child); } } node.children = [...otherChildren, ...pageChildren]; return node; }; const topLevelItems = items.filter(x => String(x.serverId) === '0'); return topLevelItems.map(x => inflateNode(x)); } constructor( name: string, serverId: string, childIds?: string[], noDelete?: boolean, noChildren?: boolean, virtual?: boolean, type?: string, shared?: boolean, needsServerUpdate?: boolean, offlineUpdatedAt?: string, faIconClass?: string, id?: number ) { super(); this.name = name; this.serverId = serverId; if ( childIds ) { this.childIds = childIds; } if ( typeof noDelete !== 'undefined' ) { this.noDelete = noDelete; } if ( typeof noChildren !== 'undefined' ) { this.noChildren = noChildren; } if ( typeof virtual !== 'undefined' ) { this.virtual = virtual; } if ( type ) { this.type = type; } if ( typeof shared !== 'undefined' ) { this.shared = shared; } if ( typeof needsServerUpdate !== 'undefined' ) { this.needsServerUpdate = needsServerUpdate; } if ( typeof offlineUpdatedAt !== 'undefined' ) { this.offlineUpdatedAt = offlineUpdatedAt; } this.faIconClass = faIconClass; if ( id ) { this.id = id; } } public getDatabase(): Dexie.Table { return this.staticClass().dbService.table('menuItems') as Dexie.Table; } public getSaveRecord(): any { return { ...(this.id ? { id: this.id } : {}), serverId: this.serverId, name: this.name, ...(typeof this.childIds !== 'undefined' ? { childIds: this.childIds } : {}), ...(typeof this.noDelete !== 'undefined' ? { noDelete: this.noDelete } : {}), ...(typeof this.noChildren !== 'undefined' ? { noChildren: this.noChildren } : {}), ...(typeof this.virtual !== 'undefined' ? { virtual: this.virtual } : {}), ...(typeof this.type !== 'undefined' ? { type: this.type } : {}), ...(typeof this.shared !== 'undefined' ? { shared: this.shared } : {}), ...(typeof this.needsServerUpdate !== 'undefined' ? { needsServerUpdate: this.needsServerUpdate } : {}), ...(typeof this.offlineUpdatedAt !== 'undefined' ? { offlineUpdatedAt: this.offlineUpdatedAt } : {}), ...(typeof this.faIconClass !== 'undefined' ? { faIconClass: this.faIconClass } : {}), }; } }