@c8y/ngx-components 1024.14.1 → 1024.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,6 +39,15 @@ class GroupBreadcrumbFactory {
39
39
  this.DEVICE_ICON = 'data-transfer';
40
40
  this.deviceDefaultLabel = gettext('Device {{id}}');
41
41
  this.currentBreadcrumbData = null;
42
+ /**
43
+ * One navigation fires the breadcrumb extension point several times in quick
44
+ * succession (NavigationEnd of the route itself, the redirect to the first
45
+ * context tab, and `selectPreferredByPath()` from the navigator click). All of
46
+ * them call `get()` before the first resolution has populated
47
+ * `currentBreadcrumbData`, so without coalescing the whole body — root-group
48
+ * lookup, icon resolution, ancestor traversal — runs once per trigger.
49
+ */
50
+ this.inFlightGet = null;
42
51
  this.breadcrumbService = inject(BreadcrumbService);
43
52
  this.routerService = inject(RouterService);
44
53
  this.groupService = inject(GroupService);
@@ -46,6 +55,7 @@ class GroupBreadcrumbFactory {
46
55
  this.injector = inject(Injector);
47
56
  this.contextRouteService = inject(ContextRouteService);
48
57
  this.assetNodeService = inject(AssetNodeService);
58
+ this.assetHierarchyService = inject(AssetHierarchyService);
49
59
  }
50
60
  async get(activatedRoute) {
51
61
  const routeData = this.contextRouteService.getContextData(activatedRoute);
@@ -65,13 +75,32 @@ class GroupBreadcrumbFactory {
65
75
  if (isSameContext && this.currentBreadcrumbData?.breadcrumbs) {
66
76
  return this.currentBreadcrumbData.breadcrumbs;
67
77
  }
78
+ if (this.inFlightGet?.contextId === contextData.id) {
79
+ return this.inFlightGet.promise;
80
+ }
81
+ const promise = this.resolveBreadcrumbs(contextData).finally(() => {
82
+ if (this.inFlightGet?.contextId === contextData.id) {
83
+ this.inFlightGet = null;
84
+ }
85
+ });
86
+ this.inFlightGet = { contextId: contextData.id, promise };
87
+ return promise;
88
+ }
89
+ setAncestorPaths(ancestorPaths) {
90
+ if (!this.currentBreadcrumbData) {
91
+ return;
92
+ }
93
+ this.currentBreadcrumbData.ancestorPaths = ancestorPaths;
94
+ this.breadcrumbService.refresh(); // will trigger factory `get` once again
95
+ }
96
+ async resolveBreadcrumbs(contextData) {
68
97
  // New context - determine if root or nested
69
98
  const rootNodesResult = await firstValueFrom(this.assetNodeService.rootGroups$);
70
99
  const rootNodes = rootNodesResult.data || [];
71
100
  const isRootNode = rootNodes.some(node => node.id === contextData.id);
72
- const icon = await this.getIcon(contextData);
73
101
  // Root node: simple breadcrumb
74
102
  if (isRootNode) {
103
+ const icon = await this.getIcon(contextData);
75
104
  const breadcrumbs = [
76
105
  {
77
106
  items: [
@@ -94,7 +123,24 @@ class GroupBreadcrumbFactory {
94
123
  };
95
124
  return breadcrumbs;
96
125
  }
97
- // Nested node: breadcrumb with ellipsis component
126
+ // Nested node: resolve the icon and the ancestor paths in parallel so the
127
+ // single-path lookup adds no extra latency to the breadcrumb render.
128
+ const [icon, autoResolvedPaths] = await Promise.all([
129
+ this.getIcon(contextData),
130
+ this.assetHierarchyService.getAncestorPathsForSingleParent(contextData.id)
131
+ ]);
132
+ // A genuine single path renders the full breadcrumb directly. Multiple paths
133
+ // (a chain that forks higher up) return null and keep the lazy ellipsis so
134
+ // the user reveals them via the dropdown.
135
+ if (autoResolvedPaths?.length === 1) {
136
+ this.currentBreadcrumbData = {
137
+ contextData: cloneDeep(contextData),
138
+ breadcrumbs: [],
139
+ ancestorPaths: autoResolvedPaths
140
+ };
141
+ return this.buildFullBreadcrumb(autoResolvedPaths);
142
+ }
143
+ // Multi-parent node: breadcrumb with ellipsis component
98
144
  const ellipsisInjector = Injector.create({
99
145
  parent: this.injector,
100
146
  providers: [
@@ -129,13 +175,6 @@ class GroupBreadcrumbFactory {
129
175
  };
130
176
  return breadcrumbs;
131
177
  }
132
- setAncestorPaths(ancestorPaths) {
133
- if (!this.currentBreadcrumbData) {
134
- return;
135
- }
136
- this.currentBreadcrumbData.ancestorPaths = ancestorPaths;
137
- this.breadcrumbService.refresh(); // will trigger factory `get` once again
138
- }
139
178
  async buildFullBreadcrumb(ancestorPaths) {
140
179
  const converted = await this.convertToBreadcrumbItems(ancestorPaths);
141
180
  const sorted = this.sortBreadcrumbItems(converted);
@@ -1 +1 @@
1
- {"version":3,"file":"c8y-ngx-components-group-breadcrumbs.mjs","sources":["../../group-breadcrumbs/group-breadcrumb.tokens.ts","../../group-breadcrumbs/group-breadcrumb-ellipsis.component.ts","../../group-breadcrumbs/group-breadcrumb-ellipsis.component.html","../../group-breadcrumbs/group-breadcrumb.factory.ts","../../group-breadcrumbs/index.ts","../../group-breadcrumbs/c8y-ngx-components-group-breadcrumbs.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { IManagedObject } from '@c8y/client';\nimport { GroupBreadcrumbFactory } from './group-breadcrumb.factory';\n\nexport const GROUP_BREADCRUMB_CONTEXT_DATA = new InjectionToken<IManagedObject>(\n 'GROUP_BREADCRUMB_CONTEXT_DATA'\n);\n\nexport const GROUP_BREADCRUMB_FACTORY = new InjectionToken<GroupBreadcrumbFactory>(\n 'GROUP_BREADCRUMB_FACTORY'\n);\n","import { Component, inject } from '@angular/core';\nimport { NgStyle } from '@angular/common';\nimport { GROUP_BREADCRUMB_CONTEXT_DATA, GROUP_BREADCRUMB_FACTORY } from './group-breadcrumb.tokens';\nimport { AssetHierarchyService, C8yTranslatePipe } from '@c8y/ngx-components';\n\n@Component({\n selector: 'c8y-group-breadcrumb-ellipsis',\n templateUrl: './group-breadcrumb-ellipsis.component.html',\n standalone: true,\n imports: [NgStyle, C8yTranslatePipe]\n})\nexport class GroupBreadcrumbEllipsisComponent {\n isLoading = false;\n\n private assetHierarchyService = inject(AssetHierarchyService);\n private contextData = inject(GROUP_BREADCRUMB_CONTEXT_DATA);\n private factory = inject(GROUP_BREADCRUMB_FACTORY);\n\n async onClick() {\n this.isLoading = true;\n const ancestorPaths = await this.assetHierarchyService.getAncestorPaths(this.contextData.id);\n this.factory.setAncestorPaths(ancestorPaths);\n this.isLoading = false;\n }\n}\n","<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","import { Injectable, Injector, inject } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport { IManagedObject } from '@c8y/client';\nimport { firstValueFrom } from 'rxjs';\nimport { GroupBreadcrumbEllipsisComponent } from './group-breadcrumb-ellipsis.component';\nimport { GROUP_BREADCRUMB_CONTEXT_DATA, GROUP_BREADCRUMB_FACTORY } from './group-breadcrumb.tokens';\nimport { TranslateService } from '@ngx-translate/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { cloneDeep } from 'lodash-es';\nimport {\n Breadcrumb,\n BreadcrumbItemWithLabel,\n BreadcrumbService,\n ContextRouteService,\n ExtensionFactory,\n GroupService,\n RouterService,\n ViewContext\n} from '@c8y/ngx-components';\nimport { AssetNodeService } from '@c8y/ngx-components/module-federation-exports/assets-navigator';\n\n@Injectable()\nexport class GroupBreadcrumbFactory implements ExtensionFactory<Breadcrumb> {\n private readonly SUPPORTED_CONTEXTS = [ViewContext.Device, ViewContext.Group];\n private readonly GROUP_ICON = 'c8y-group';\n private readonly DEVICE_ICON = 'data-transfer';\n private deviceDefaultLabel = gettext('Device {{id}}');\n\n private currentBreadcrumbData: {\n contextData: IManagedObject;\n breadcrumbs: Breadcrumb[];\n ancestorPaths?: IManagedObject[][];\n } | null = null;\n\n private breadcrumbService = inject(BreadcrumbService);\n private routerService = inject(RouterService);\n private groupService = inject(GroupService);\n private translateService = inject(TranslateService);\n private injector = inject(Injector);\n private contextRouteService = inject(ContextRouteService);\n private assetNodeService = inject(AssetNodeService);\n\n async get(activatedRoute?: ActivatedRoute): Promise<Breadcrumb[] | null> {\n const routeData = this.contextRouteService.getContextData(activatedRoute);\n const context = routeData?.context;\n const contextData = routeData?.contextData as IManagedObject;\n\n // Only show breadcrumbs for Device/Group contexts with contextData\n if (!this.SUPPORTED_CONTEXTS.includes(context) || !contextData) {\n return null;\n }\n\n // Check if same context as before\n const isSameContext = this.currentBreadcrumbData?.contextData?.id === contextData.id;\n\n // If same context and has ancestor paths loaded, return full breadcrumb\n if (isSameContext && this.currentBreadcrumbData?.ancestorPaths) {\n return this.buildFullBreadcrumb(this.currentBreadcrumbData.ancestorPaths);\n }\n\n // If same context but no ancestor paths, return existing ellipsis breadcrumb\n if (isSameContext && this.currentBreadcrumbData?.breadcrumbs) {\n return this.currentBreadcrumbData.breadcrumbs;\n }\n\n // New context - determine if root or nested\n const rootNodesResult = await firstValueFrom(this.assetNodeService.rootGroups$);\n const rootNodes = rootNodesResult.data || [];\n\n const isRootNode = rootNodes.some(node => node.id === contextData.id);\n const icon = await this.getIcon(contextData);\n\n // Root node: simple breadcrumb\n if (isRootNode) {\n const breadcrumbs: Breadcrumb[] = [\n {\n items: [\n {\n label: gettext('Groups'),\n path: 'group',\n icon: this.GROUP_ICON\n },\n {\n label: contextData.name,\n icon,\n path: ''\n }\n ]\n }\n ];\n\n this.currentBreadcrumbData = {\n contextData: cloneDeep(contextData),\n breadcrumbs\n };\n\n return breadcrumbs;\n }\n\n // Nested node: breadcrumb with ellipsis component\n const ellipsisInjector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: GROUP_BREADCRUMB_CONTEXT_DATA, useValue: contextData },\n { provide: GROUP_BREADCRUMB_FACTORY, useValue: this }\n ]\n });\n\n const breadcrumbs: Breadcrumb[] = [\n {\n injector: ellipsisInjector,\n items: [\n {\n label: gettext('Groups'),\n path: 'group',\n icon: this.GROUP_ICON\n },\n {\n component: GroupBreadcrumbEllipsisComponent\n },\n {\n label:\n contextData.name ||\n this.translateService.instant(this.deviceDefaultLabel, { id: contextData.id }),\n icon,\n path: ''\n }\n ]\n }\n ];\n\n this.currentBreadcrumbData = {\n contextData: cloneDeep(contextData),\n breadcrumbs\n };\n\n return breadcrumbs;\n }\n\n setAncestorPaths(ancestorPaths: IManagedObject[][]) {\n if (!this.currentBreadcrumbData) {\n return;\n }\n\n this.currentBreadcrumbData.ancestorPaths = ancestorPaths;\n this.breadcrumbService.refresh(); // will trigger factory `get` once again\n }\n\n private async buildFullBreadcrumb(ancestorPaths: IManagedObject[][]): Promise<Breadcrumb[]> {\n const converted = await this.convertToBreadcrumbItems(ancestorPaths);\n const sorted = this.sortBreadcrumbItems(converted);\n\n const breadcrumbs: Breadcrumb[] = sorted.map(\n bc =>\n ({\n items: [\n {\n label: gettext('Groups'),\n path: 'group',\n icon: this.GROUP_ICON\n },\n ...bc.map((item, index) => ({\n ...item,\n path: index === bc.length - 1 ? undefined : item.path\n }))\n ],\n forceDropdownOpen: sorted.length > 1\n }) as Breadcrumb\n );\n\n this.currentBreadcrumbData.breadcrumbs = breadcrumbs;\n\n return breadcrumbs;\n }\n\n private async convertToBreadcrumbItems(\n ancestorPaths: IManagedObject[][]\n ): Promise<BreadcrumbItemWithLabel[][]> {\n return Promise.all(\n ancestorPaths.map(async path =>\n Promise.all(\n path.map(async managedObject => ({\n label:\n managedObject.name ||\n this.translateService.instant(this.deviceDefaultLabel, { id: managedObject.id }),\n path: '/' + this.routerService.getHref(managedObject, ''),\n icon: await this.getIcon(managedObject)\n }))\n )\n )\n );\n }\n\n private sortBreadcrumbItems(\n breadcrumbItems: BreadcrumbItemWithLabel[][]\n ): BreadcrumbItemWithLabel[][] {\n const breadcrumbs: Breadcrumb[] = breadcrumbItems.map(items => ({ items }));\n const sorted = this.breadcrumbService.sortByPreferredPath(breadcrumbs);\n return sorted.map(breadcrumb => breadcrumb.items as BreadcrumbItemWithLabel[]);\n }\n\n private async getIcon(managedObject: IManagedObject): Promise<string> {\n if (this.groupService.isDevice(managedObject)) {\n return this.DEVICE_ICON;\n }\n return this.groupService.getIcon(managedObject);\n }\n}\n","import { hookBreadcrumb } from '@c8y/ngx-components';\nimport { GroupBreadcrumbFactory } from './group-breadcrumb.factory';\n\nexport const groupBreadcrumbsProviders = [hookBreadcrumb(GroupBreadcrumbFactory)];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"c8y-ngx-components-group-breadcrumbs.mjs","sources":["../../group-breadcrumbs/group-breadcrumb.tokens.ts","../../group-breadcrumbs/group-breadcrumb-ellipsis.component.ts","../../group-breadcrumbs/group-breadcrumb-ellipsis.component.html","../../group-breadcrumbs/group-breadcrumb.factory.ts","../../group-breadcrumbs/index.ts","../../group-breadcrumbs/c8y-ngx-components-group-breadcrumbs.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { IManagedObject } from '@c8y/client';\nimport { GroupBreadcrumbFactory } from './group-breadcrumb.factory';\n\nexport const GROUP_BREADCRUMB_CONTEXT_DATA = new InjectionToken<IManagedObject>(\n 'GROUP_BREADCRUMB_CONTEXT_DATA'\n);\n\nexport const GROUP_BREADCRUMB_FACTORY = new InjectionToken<GroupBreadcrumbFactory>(\n 'GROUP_BREADCRUMB_FACTORY'\n);\n","import { Component, inject } from '@angular/core';\nimport { NgStyle } from '@angular/common';\nimport { GROUP_BREADCRUMB_CONTEXT_DATA, GROUP_BREADCRUMB_FACTORY } from './group-breadcrumb.tokens';\nimport { AssetHierarchyService, C8yTranslatePipe } from '@c8y/ngx-components';\n\n@Component({\n selector: 'c8y-group-breadcrumb-ellipsis',\n templateUrl: './group-breadcrumb-ellipsis.component.html',\n standalone: true,\n imports: [NgStyle, C8yTranslatePipe]\n})\nexport class GroupBreadcrumbEllipsisComponent {\n isLoading = false;\n\n private assetHierarchyService = inject(AssetHierarchyService);\n private contextData = inject(GROUP_BREADCRUMB_CONTEXT_DATA);\n private factory = inject(GROUP_BREADCRUMB_FACTORY);\n\n async onClick() {\n this.isLoading = true;\n const ancestorPaths = await this.assetHierarchyService.getAncestorPaths(this.contextData.id);\n this.factory.setAncestorPaths(ancestorPaths);\n this.isLoading = false;\n }\n}\n","<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","import { Injectable, Injector, inject } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport { IManagedObject } from '@c8y/client';\nimport { firstValueFrom } from 'rxjs';\nimport { GroupBreadcrumbEllipsisComponent } from './group-breadcrumb-ellipsis.component';\nimport { GROUP_BREADCRUMB_CONTEXT_DATA, GROUP_BREADCRUMB_FACTORY } from './group-breadcrumb.tokens';\nimport { TranslateService } from '@ngx-translate/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { cloneDeep } from 'lodash-es';\nimport {\n AssetHierarchyService,\n Breadcrumb,\n BreadcrumbItemWithLabel,\n BreadcrumbService,\n ContextRouteService,\n ExtensionFactory,\n GroupService,\n RouterService,\n ViewContext\n} from '@c8y/ngx-components';\nimport { AssetNodeService } from '@c8y/ngx-components/module-federation-exports/assets-navigator';\n\n@Injectable()\nexport class GroupBreadcrumbFactory implements ExtensionFactory<Breadcrumb> {\n private readonly SUPPORTED_CONTEXTS = [ViewContext.Device, ViewContext.Group];\n private readonly GROUP_ICON = 'c8y-group';\n private readonly DEVICE_ICON = 'data-transfer';\n private deviceDefaultLabel = gettext('Device {{id}}');\n\n private currentBreadcrumbData: {\n contextData: IManagedObject;\n breadcrumbs: Breadcrumb[];\n ancestorPaths?: IManagedObject[][];\n } | null = null;\n\n /**\n * One navigation fires the breadcrumb extension point several times in quick\n * succession (NavigationEnd of the route itself, the redirect to the first\n * context tab, and `selectPreferredByPath()` from the navigator click). All of\n * them call `get()` before the first resolution has populated\n * `currentBreadcrumbData`, so without coalescing the whole body — root-group\n * lookup, icon resolution, ancestor traversal — runs once per trigger.\n */\n private inFlightGet: { contextId: string; promise: Promise<Breadcrumb[] | null> } | null = null;\n\n private breadcrumbService = inject(BreadcrumbService);\n private routerService = inject(RouterService);\n private groupService = inject(GroupService);\n private translateService = inject(TranslateService);\n private injector = inject(Injector);\n private contextRouteService = inject(ContextRouteService);\n private assetNodeService = inject(AssetNodeService);\n private assetHierarchyService = inject(AssetHierarchyService);\n\n async get(activatedRoute?: ActivatedRoute): Promise<Breadcrumb[] | null> {\n const routeData = this.contextRouteService.getContextData(activatedRoute);\n const context = routeData?.context;\n const contextData = routeData?.contextData as IManagedObject;\n\n // Only show breadcrumbs for Device/Group contexts with contextData\n if (!this.SUPPORTED_CONTEXTS.includes(context) || !contextData) {\n return null;\n }\n\n // Check if same context as before\n const isSameContext = this.currentBreadcrumbData?.contextData?.id === contextData.id;\n\n // If same context and has ancestor paths loaded, return full breadcrumb\n if (isSameContext && this.currentBreadcrumbData?.ancestorPaths) {\n return this.buildFullBreadcrumb(this.currentBreadcrumbData.ancestorPaths);\n }\n\n // If same context but no ancestor paths, return existing ellipsis breadcrumb\n if (isSameContext && this.currentBreadcrumbData?.breadcrumbs) {\n return this.currentBreadcrumbData.breadcrumbs;\n }\n\n if (this.inFlightGet?.contextId === contextData.id) {\n return this.inFlightGet.promise;\n }\n\n const promise = this.resolveBreadcrumbs(contextData).finally(() => {\n if (this.inFlightGet?.contextId === contextData.id) {\n this.inFlightGet = null;\n }\n });\n this.inFlightGet = { contextId: contextData.id, promise };\n return promise;\n }\n\n setAncestorPaths(ancestorPaths: IManagedObject[][]) {\n if (!this.currentBreadcrumbData) {\n return;\n }\n\n this.currentBreadcrumbData.ancestorPaths = ancestorPaths;\n this.breadcrumbService.refresh(); // will trigger factory `get` once again\n }\n\n private async resolveBreadcrumbs(contextData: IManagedObject): Promise<Breadcrumb[] | null> {\n // New context - determine if root or nested\n const rootNodesResult = await firstValueFrom(this.assetNodeService.rootGroups$);\n const rootNodes = rootNodesResult.data || [];\n\n const isRootNode = rootNodes.some(node => node.id === contextData.id);\n\n // Root node: simple breadcrumb\n if (isRootNode) {\n const icon = await this.getIcon(contextData);\n const breadcrumbs: Breadcrumb[] = [\n {\n items: [\n {\n label: gettext('Groups'),\n path: 'group',\n icon: this.GROUP_ICON\n },\n {\n label: contextData.name,\n icon,\n path: ''\n }\n ]\n }\n ];\n\n this.currentBreadcrumbData = {\n contextData: cloneDeep(contextData),\n breadcrumbs\n };\n\n return breadcrumbs;\n }\n\n // Nested node: resolve the icon and the ancestor paths in parallel so the\n // single-path lookup adds no extra latency to the breadcrumb render.\n const [icon, autoResolvedPaths] = await Promise.all([\n this.getIcon(contextData),\n this.assetHierarchyService.getAncestorPathsForSingleParent(contextData.id)\n ]);\n\n // A genuine single path renders the full breadcrumb directly. Multiple paths\n // (a chain that forks higher up) return null and keep the lazy ellipsis so\n // the user reveals them via the dropdown.\n if (autoResolvedPaths?.length === 1) {\n this.currentBreadcrumbData = {\n contextData: cloneDeep(contextData),\n breadcrumbs: [],\n ancestorPaths: autoResolvedPaths\n };\n return this.buildFullBreadcrumb(autoResolvedPaths);\n }\n\n // Multi-parent node: breadcrumb with ellipsis component\n const ellipsisInjector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: GROUP_BREADCRUMB_CONTEXT_DATA, useValue: contextData },\n { provide: GROUP_BREADCRUMB_FACTORY, useValue: this }\n ]\n });\n\n const breadcrumbs: Breadcrumb[] = [\n {\n injector: ellipsisInjector,\n items: [\n {\n label: gettext('Groups'),\n path: 'group',\n icon: this.GROUP_ICON\n },\n {\n component: GroupBreadcrumbEllipsisComponent\n },\n {\n label:\n contextData.name ||\n this.translateService.instant(this.deviceDefaultLabel, { id: contextData.id }),\n icon,\n path: ''\n }\n ]\n }\n ];\n\n this.currentBreadcrumbData = {\n contextData: cloneDeep(contextData),\n breadcrumbs\n };\n\n return breadcrumbs;\n }\n\n private async buildFullBreadcrumb(ancestorPaths: IManagedObject[][]): Promise<Breadcrumb[]> {\n const converted = await this.convertToBreadcrumbItems(ancestorPaths);\n const sorted = this.sortBreadcrumbItems(converted);\n\n const breadcrumbs: Breadcrumb[] = sorted.map(\n bc =>\n ({\n items: [\n {\n label: gettext('Groups'),\n path: 'group',\n icon: this.GROUP_ICON\n },\n ...bc.map((item, index) => ({\n ...item,\n path: index === bc.length - 1 ? undefined : item.path\n }))\n ],\n forceDropdownOpen: sorted.length > 1\n }) as Breadcrumb\n );\n\n this.currentBreadcrumbData.breadcrumbs = breadcrumbs;\n\n return breadcrumbs;\n }\n\n private async convertToBreadcrumbItems(\n ancestorPaths: IManagedObject[][]\n ): Promise<BreadcrumbItemWithLabel[][]> {\n return Promise.all(\n ancestorPaths.map(async path =>\n Promise.all(\n path.map(async managedObject => ({\n label:\n managedObject.name ||\n this.translateService.instant(this.deviceDefaultLabel, { id: managedObject.id }),\n path: '/' + this.routerService.getHref(managedObject, ''),\n icon: await this.getIcon(managedObject)\n }))\n )\n )\n );\n }\n\n private sortBreadcrumbItems(\n breadcrumbItems: BreadcrumbItemWithLabel[][]\n ): BreadcrumbItemWithLabel[][] {\n const breadcrumbs: Breadcrumb[] = breadcrumbItems.map(items => ({ items }));\n const sorted = this.breadcrumbService.sortByPreferredPath(breadcrumbs);\n return sorted.map(breadcrumb => breadcrumb.items as BreadcrumbItemWithLabel[]);\n }\n\n private async getIcon(managedObject: IManagedObject): Promise<string> {\n if (this.groupService.isDevice(managedObject)) {\n return this.DEVICE_ICON;\n }\n return this.groupService.getIcon(managedObject);\n }\n}\n","import { hookBreadcrumb } from '@c8y/ngx-components';\nimport { GroupBreadcrumbFactory } from './group-breadcrumb.factory';\n\nexport const groupBreadcrumbsProviders = [hookBreadcrumb(GroupBreadcrumbFactory)];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}