UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

193 lines (186 loc) 9.45 kB
import { AssetHierarchyService, C8yTranslatePipe, ViewContext, BreadcrumbService, RouterService, GroupService, ContextRouteService, hookBreadcrumb } from '@c8y/ngx-components'; import * as i0 from '@angular/core'; import { InjectionToken, inject, Component, Injector, Injectable } from '@angular/core'; import { firstValueFrom } from 'rxjs'; import { NgStyle } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { gettext } from '@c8y/ngx-components/gettext'; import { cloneDeep } from 'lodash-es'; import { AssetNodeService } from '@c8y/ngx-components/module-federation-exports/assets-navigator'; const GROUP_BREADCRUMB_CONTEXT_DATA = new InjectionToken('GROUP_BREADCRUMB_CONTEXT_DATA'); const GROUP_BREADCRUMB_FACTORY = new InjectionToken('GROUP_BREADCRUMB_FACTORY'); class GroupBreadcrumbEllipsisComponent { constructor() { this.isLoading = false; this.assetHierarchyService = inject(AssetHierarchyService); this.contextData = inject(GROUP_BREADCRUMB_CONTEXT_DATA); this.factory = inject(GROUP_BREADCRUMB_FACTORY); } async onClick() { this.isLoading = true; const ancestorPaths = await this.assetHierarchyService.getAncestorPaths(this.contextData.id); this.factory.setAncestorPaths(ancestorPaths); this.isLoading = false; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GroupBreadcrumbEllipsisComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: GroupBreadcrumbEllipsisComponent, isStandalone: true, selector: "c8y-group-breadcrumb-ellipsis", ngImport: i0, template: "<button\n class=\"btn-clean btn btn-xs p-t-0 p-b-0\"\n [ngStyle]=\"{ cursor: isLoading ? 'wait' : 'pointer' }\"\n title=\"{{ 'Show all paths' | translate }}\"\n type=\"button\"\n (click)=\"!isLoading && onClick()\"\n>\n ...\n</button>\n", dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GroupBreadcrumbEllipsisComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-group-breadcrumb-ellipsis', standalone: true, imports: [NgStyle, C8yTranslatePipe], template: "<button\n class=\"btn-clean btn btn-xs p-t-0 p-b-0\"\n [ngStyle]=\"{ cursor: isLoading ? 'wait' : 'pointer' }\"\n title=\"{{ 'Show all paths' | translate }}\"\n type=\"button\"\n (click)=\"!isLoading && onClick()\"\n>\n ...\n</button>\n" }] }] }); class GroupBreadcrumbFactory { constructor() { this.SUPPORTED_CONTEXTS = [ViewContext.Device, ViewContext.Group]; this.GROUP_ICON = 'c8y-group'; this.DEVICE_ICON = 'data-transfer'; this.deviceDefaultLabel = gettext('Device {{id}}'); this.currentBreadcrumbData = null; this.breadcrumbService = inject(BreadcrumbService); this.routerService = inject(RouterService); this.groupService = inject(GroupService); this.translateService = inject(TranslateService); this.injector = inject(Injector); this.contextRouteService = inject(ContextRouteService); this.assetNodeService = inject(AssetNodeService); } async get(activatedRoute) { const routeData = this.contextRouteService.getContextData(activatedRoute); const context = routeData?.context; const contextData = routeData?.contextData; // Only show breadcrumbs for Device/Group contexts with contextData if (!this.SUPPORTED_CONTEXTS.includes(context) || !contextData) { return null; } // Check if same context as before const isSameContext = this.currentBreadcrumbData?.contextData?.id === contextData.id; // If same context and has ancestor paths loaded, return full breadcrumb if (isSameContext && this.currentBreadcrumbData?.ancestorPaths) { return this.buildFullBreadcrumb(this.currentBreadcrumbData.ancestorPaths); } // If same context but no ancestor paths, return existing ellipsis breadcrumb if (isSameContext && this.currentBreadcrumbData?.breadcrumbs) { return this.currentBreadcrumbData.breadcrumbs; } // New context - determine if root or nested const rootNodesResult = await firstValueFrom(this.assetNodeService.rootGroups$); const rootNodes = rootNodesResult.data || []; const isRootNode = rootNodes.some(node => node.id === contextData.id); const icon = await this.getIcon(contextData); // Root node: simple breadcrumb if (isRootNode) { const breadcrumbs = [ { items: [ { label: gettext('Groups'), path: 'group', icon: this.GROUP_ICON }, { label: contextData.name, icon, path: '' } ] } ]; this.currentBreadcrumbData = { contextData: cloneDeep(contextData), breadcrumbs }; return breadcrumbs; } // Nested node: breadcrumb with ellipsis component const ellipsisInjector = Injector.create({ parent: this.injector, providers: [ { provide: GROUP_BREADCRUMB_CONTEXT_DATA, useValue: contextData }, { provide: GROUP_BREADCRUMB_FACTORY, useValue: this } ] }); const breadcrumbs = [ { injector: ellipsisInjector, items: [ { label: gettext('Groups'), path: 'group', icon: this.GROUP_ICON }, { component: GroupBreadcrumbEllipsisComponent }, { label: contextData.name || this.translateService.instant(this.deviceDefaultLabel, { id: contextData.id }), icon, path: '' } ] } ]; this.currentBreadcrumbData = { contextData: cloneDeep(contextData), breadcrumbs }; return breadcrumbs; } setAncestorPaths(ancestorPaths) { if (!this.currentBreadcrumbData) { return; } this.currentBreadcrumbData.ancestorPaths = ancestorPaths; this.breadcrumbService.refresh(); // will trigger factory `get` once again } async buildFullBreadcrumb(ancestorPaths) { const converted = await this.convertToBreadcrumbItems(ancestorPaths); const sorted = this.sortBreadcrumbItems(converted); const breadcrumbs = sorted.map(bc => ({ items: [ { label: gettext('Groups'), path: 'group', icon: this.GROUP_ICON }, ...bc.map((item, index) => ({ ...item, path: index === bc.length - 1 ? undefined : item.path })) ], forceDropdownOpen: sorted.length > 1 })); this.currentBreadcrumbData.breadcrumbs = breadcrumbs; return breadcrumbs; } async convertToBreadcrumbItems(ancestorPaths) { return Promise.all(ancestorPaths.map(async (path) => Promise.all(path.map(async (managedObject) => ({ label: managedObject.name || this.translateService.instant(this.deviceDefaultLabel, { id: managedObject.id }), path: '/' + this.routerService.getHref(managedObject, ''), icon: await this.getIcon(managedObject) }))))); } sortBreadcrumbItems(breadcrumbItems) { const breadcrumbs = breadcrumbItems.map(items => ({ items })); const sorted = this.breadcrumbService.sortByPreferredPath(breadcrumbs); return sorted.map(breadcrumb => breadcrumb.items); } async getIcon(managedObject) { if (this.groupService.isDevice(managedObject)) { return this.DEVICE_ICON; } return this.groupService.getIcon(managedObject); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GroupBreadcrumbFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GroupBreadcrumbFactory }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GroupBreadcrumbFactory, decorators: [{ type: Injectable }] }); const groupBreadcrumbsProviders = [hookBreadcrumb(GroupBreadcrumbFactory)]; /** * Generated bundle index. Do not edit. */ export { groupBreadcrumbsProviders }; //# sourceMappingURL=c8y-ngx-components-group-breadcrumbs.mjs.map