@c8y/ngx-components 1023.97.3 → 1023.97.7

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.
Files changed (54) hide show
  1. package/alarms/index.d.ts.map +1 -1
  2. package/context-dashboard/index.d.ts +29 -3
  3. package/context-dashboard/index.d.ts.map +1 -1
  4. package/ecosystem/index.d.ts.map +1 -1
  5. package/fesm2022/c8y-ngx-components-alarms.mjs +10 -7
  6. package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
  7. package/fesm2022/c8y-ngx-components-context-dashboard-asset-add.mjs +2 -2
  8. package/fesm2022/c8y-ngx-components-context-dashboard-asset-add.mjs.map +1 -1
  9. package/fesm2022/c8y-ngx-components-context-dashboard-asset-view.mjs +2 -2
  10. package/fesm2022/c8y-ngx-components-context-dashboard-asset-view.mjs.map +1 -1
  11. package/fesm2022/c8y-ngx-components-context-dashboard-cockpit-home-dashboard.mjs +3 -3
  12. package/fesm2022/c8y-ngx-components-context-dashboard-cockpit-home-dashboard.mjs.map +1 -1
  13. package/fesm2022/c8y-ngx-components-context-dashboard-device-add.mjs +2 -2
  14. package/fesm2022/c8y-ngx-components-context-dashboard-device-add.mjs.map +1 -1
  15. package/fesm2022/c8y-ngx-components-context-dashboard-device-view.mjs +2 -2
  16. package/fesm2022/c8y-ngx-components-context-dashboard-device-view.mjs.map +1 -1
  17. package/fesm2022/c8y-ngx-components-context-dashboard-devicemanagement.mjs +2 -2
  18. package/fesm2022/c8y-ngx-components-context-dashboard-devicemanagement.mjs.map +1 -1
  19. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +142 -19
  20. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  21. package/fesm2022/c8y-ngx-components-ecosystem.mjs +6 -7
  22. package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
  23. package/fesm2022/c8y-ngx-components-report-dashboard.mjs +4 -4
  24. package/fesm2022/c8y-ngx-components-report-dashboard.mjs.map +1 -1
  25. package/fesm2022/c8y-ngx-components-upgrade.mjs +40 -8
  26. package/fesm2022/c8y-ngx-components-upgrade.mjs.map +1 -1
  27. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +12 -5
  28. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  29. package/fesm2022/c8y-ngx-components-widgets-implementations-quick-links.mjs +40 -11
  30. package/fesm2022/c8y-ngx-components-widgets-implementations-quick-links.mjs.map +1 -1
  31. package/fesm2022/c8y-ngx-components-widgets-implementations-three-d-rotation.mjs +19 -0
  32. package/fesm2022/c8y-ngx-components-widgets-implementations-three-d-rotation.mjs.map +1 -1
  33. package/fesm2022/c8y-ngx-components.mjs +229 -31
  34. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  35. package/index.d.ts +83 -7
  36. package/index.d.ts.map +1 -1
  37. package/locales/de.po +3 -0
  38. package/locales/es.po +3 -0
  39. package/locales/fr.po +3 -0
  40. package/locales/ja_JP.po +3 -0
  41. package/locales/ko.po +3 -0
  42. package/locales/locales.pot +3 -0
  43. package/locales/nl.po +3 -0
  44. package/locales/pl.po +3 -0
  45. package/locales/pt_BR.po +3 -0
  46. package/locales/zh_CN.po +3 -0
  47. package/locales/zh_TW.po +3 -0
  48. package/package.json +1 -1
  49. package/upgrade/index.d.ts +8 -0
  50. package/upgrade/index.d.ts.map +1 -1
  51. package/widgets/implementations/asset-table/index.d.ts.map +1 -1
  52. package/widgets/implementations/quick-links/index.d.ts +3 -1
  53. package/widgets/implementations/quick-links/index.d.ts.map +1 -1
  54. package/widgets/implementations/three-d-rotation/index.d.ts.map +1 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, inject, InjectionToken, EventEmitter, Output, Input, signal, DestroyRef, TemplateRef, ViewChild, Optional, Inject, HostListener, input, HostBinding, NgModule, Injector, runInInjectionContext, ChangeDetectionStrategy } from '@angular/core';
2
+ import { Injectable, Component, inject, InjectionToken, EventEmitter, Output, Input, signal, DestroyRef, TemplateRef, ViewChild, Injector, afterNextRender, Optional, Inject, HostListener, input, HostBinding, NgModule, runInInjectionContext, ChangeDetectionStrategy } from '@angular/core';
3
3
  import * as i2 from '@c8y/ngx-components';
4
4
  import { IconDirective, C8yTranslatePipe, Permissions, ContextRouteService, Status, NavigatorNode, NEW_DASHBOARD_ROUTER_STATE_PROP, getActivatedRoute, ViewContext, TabsOutletComponent, memoize, hookGeneric, ExtensionPointForPlugins, fromTriggerOnce, getInjectedHooks, stateToFactory, ListGroupModule, C8yComponentOutlet, AlertService, C8yTranslateDirective, DynamicComponentModule, DynamicComponentComponent, sortByPriority, isPromise, CoreModule, WIDGET_CONFIGURATION_GRID_SIZE, HighlightComponent, EmptyStateComponent, FormGroupComponent, RequiredInputPlaceholderDirective, ProductExperienceDirective, ResizableGridComponent, DashboardChildChange, CopyDashboardDisabledReason, TitleComponent, ActionBarItemComponent, HelpComponent, WidgetsDashboardComponent, DatePipe, hookRoute, hookTab, PreviewService, hookNavigator, ManagedObjectRealtimeService, BottomDrawerService, ClipboardService, InputGroupEditableComponent, MessageDirective } from '@c8y/ngx-components';
5
5
  import * as i1 from '@angular/router';
@@ -274,6 +274,24 @@ const PRODUCT_EXPERIENCE = {
274
274
  }
275
275
  }
276
276
  };
277
+ const FOUNDATION_CLASSES = [
278
+ 'c8y-dark-theme',
279
+ 'c8y-light-theme',
280
+ 'panel-content-branded'
281
+ ];
282
+ const THEME_FOUNDATION_MAP = {
283
+ 'dashboard-theme-dark': 'c8y-dark-theme',
284
+ 'dashboard-theme-white': 'c8y-light-theme',
285
+ 'dashboard-theme-branded': 'panel-content-branded'
286
+ };
287
+ const WIDGET_FOUNDATION_MAP = {
288
+ 'panel-content-dark': 'c8y-dark-theme',
289
+ 'panel-content-white': 'c8y-light-theme'
290
+ };
291
+ const DASHBOARD_FOUNDATION_MAP = {
292
+ 'dashboard-theme-dark': 'c8y-dark-theme',
293
+ 'dashboard-theme-white': 'c8y-light-theme'
294
+ };
277
295
  const REPORT_DEFAULT_NAVIGATION_NODE_PRIORITY = 30;
278
296
  const DASHBOARD_DETAILS_OUTLET = 'dashboard-details';
279
297
  const DASHBOARD_DETAILS_TABS_OUTLET_NAME = 'dashboardTabs';
@@ -2469,20 +2487,43 @@ class WidgetPreviewComponent {
2469
2487
  constructor() {
2470
2488
  this.widgetConfigService = inject(WidgetConfigService);
2471
2489
  this.widgetConfig = inject(WidgetConfigComponent);
2472
- this.previewClasses = {
2490
+ this.injector = inject(Injector);
2491
+ // charts don't observe CSS vars — force destroy/recreate when theme changes
2492
+ this.showContent = signal(true, ...(ngDevMode ? [{ debugName: "showContent" }] : []));
2493
+ this.previousClassKey = '';
2494
+ this._previewClasses = {
2473
2495
  'dashboard-theme-light': true,
2474
2496
  'panel-title-regular': true
2475
2497
  };
2476
2498
  }
2499
+ set previewClasses(value) {
2500
+ this._previewClasses = value;
2501
+ const classKey = this.activeClassKey(value);
2502
+ if (this.previousClassKey && classKey !== this.previousClassKey) {
2503
+ this.showContent.set(false);
2504
+ afterNextRender(() => this.showContent.set(true), { injector: this.injector });
2505
+ }
2506
+ this.previousClassKey = classKey;
2507
+ }
2508
+ get previewClasses() {
2509
+ return this._previewClasses;
2510
+ }
2477
2511
  get translateWidgetTitle() {
2478
2512
  return this.widgetConfig?.mo.c8y_Dashboard.translateWidgetTitle ?? false;
2479
2513
  }
2514
+ activeClassKey(classes) {
2515
+ return Object.entries(classes ?? {})
2516
+ .filter(([, v]) => v)
2517
+ .map(([k]) => k)
2518
+ .sort()
2519
+ .join(' ');
2520
+ }
2480
2521
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: WidgetPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2481
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: WidgetPreviewComponent, isStandalone: true, selector: "c8y-widget-preview", inputs: { previewClasses: "previewClasses" }, host: { classAttribute: "flex-grow d-flex d-col" }, ngImport: i0, template: "<fieldset class=\"c8y-fieldset p-l-24 p-r-24 p-t-16 p-b-16 flex-grow d-flex d-col min-height-0\">\n <legend>{{ 'Preview' | translate }}</legend>\n <c8y-dashboard\n class=\"dashboard-preview-slot flex-grow min-height-0\"\n [columns]=\"1\"\n [ngClass]=\"previewClasses\"\n >\n <c8y-dashboard-child\n [isFrozen]=\"true\"\n [width]=\"1\"\n [height]=\"6\"\n >\n @let widgetTitle =\n (widgetConfigService.selected$ | async)?.data?.title\n | translate: { noTranslateRemoveContext: !translateWidgetTitle };\n <c8y-dashboard-child-title [attr.title]=\"widgetTitle\">\n <span>\n {{ widgetTitle }}\n </span>\n </c8y-dashboard-child-title>\n\n @if ((widgetConfigService.previewViewState$ | async) === 'noPreview') {\n <div class=\"fit-h d-flex d-col j-c-center a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'visibility-off'\"\n [title]=\"'No preview available.' | translate\"\n [subtitle]=\"'This widget does not provide any preview.' | translate\"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n </div>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'configPreview') {\n <c8y-dynamic-component\n [componentId]=\"(widgetConfigService.selected$ | async)?.id\"\n [config]=\"(widgetConfigService.currentConfig$ | async)?.config\"\n ></c8y-dynamic-component>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'templatePreview') {\n <ng-template [ngTemplateOutlet]=\"widgetConfigService.preview$ | async\"></ng-template>\n }\n </c8y-dashboard-child>\n </c8y-dashboard>\n</fieldset>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: i2.DynamicComponentComponent, selector: "c8y-dynamic-component", inputs: ["componentId", "config", "mode", "notFoundError", "executeResolvers"], outputs: ["updateWidgetClasses"] }, { kind: "component", type: i2.DashboardComponent, selector: "c8y-dashboard", inputs: ["columns", "gap", "rows"], outputs: ["dashboardChange"] }, { kind: "component", type: i2.DashboardChildComponent, selector: "c8y-dashboard-child", inputs: ["x", "y", "width", "height", "data", "margin", "useIntersection", "isFrozen", "canToggleFullscreen", "editMode", "class"], outputs: ["changeStart", "changeEnd", "toggleFullscreen"] }, { kind: "component", type: i2.DashboardChildTitleComponent, selector: "c8y-dashboard-child-title" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
2522
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: WidgetPreviewComponent, isStandalone: true, selector: "c8y-widget-preview", inputs: { previewClasses: "previewClasses" }, host: { classAttribute: "flex-grow d-flex d-col" }, ngImport: i0, template: "<fieldset class=\"c8y-fieldset p-l-24 p-r-24 p-t-16 p-b-16 flex-grow d-flex d-col min-height-0\">\n <legend>{{ 'Preview' | translate }}</legend>\n <c8y-dashboard\n class=\"dashboard-preview-slot flex-grow min-height-0\"\n [columns]=\"1\"\n [ngClass]=\"previewClasses\"\n >\n @if (showContent()) {\n <c8y-dashboard-child\n [isFrozen]=\"true\"\n [width]=\"1\"\n [height]=\"6\"\n >\n @let widgetTitle =\n (widgetConfigService.selected$ | async)?.data?.title\n | translate: { noTranslateRemoveContext: !translateWidgetTitle };\n <c8y-dashboard-child-title [attr.title]=\"widgetTitle\">\n <span>\n {{ widgetTitle }}\n </span>\n </c8y-dashboard-child-title>\n\n @if ((widgetConfigService.previewViewState$ | async) === 'noPreview') {\n <div class=\"fit-h d-flex d-col j-c-center a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'visibility-off'\"\n [title]=\"'No preview available.' | translate\"\n [subtitle]=\"'This widget does not provide any preview.' | translate\"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n </div>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'configPreview') {\n <c8y-dynamic-component\n [componentId]=\"(widgetConfigService.selected$ | async)?.id\"\n [config]=\"(widgetConfigService.currentConfig$ | async)?.config\"\n ></c8y-dynamic-component>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'templatePreview') {\n <ng-template [ngTemplateOutlet]=\"widgetConfigService.preview$ | async\"></ng-template>\n }\n </c8y-dashboard-child>\n }\n </c8y-dashboard>\n</fieldset>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: i2.DynamicComponentComponent, selector: "c8y-dynamic-component", inputs: ["componentId", "config", "mode", "notFoundError", "executeResolvers"], outputs: ["updateWidgetClasses"] }, { kind: "component", type: i2.DashboardComponent, selector: "c8y-dashboard", inputs: ["columns", "gap", "rows"], outputs: ["dashboardChange"] }, { kind: "component", type: i2.DashboardChildComponent, selector: "c8y-dashboard-child", inputs: ["x", "y", "width", "height", "data", "margin", "useIntersection", "isFrozen", "canToggleFullscreen", "editMode", "class"], outputs: ["changeStart", "changeEnd", "toggleFullscreen"] }, { kind: "component", type: i2.DashboardChildTitleComponent, selector: "c8y-dashboard-child-title" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
2482
2523
  }
2483
2524
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: WidgetPreviewComponent, decorators: [{
2484
2525
  type: Component,
2485
- args: [{ selector: 'c8y-widget-preview', host: { class: 'flex-grow d-flex d-col' }, standalone: true, imports: [NgClass, C8yTranslatePipe, CommonModule, CoreModule], template: "<fieldset class=\"c8y-fieldset p-l-24 p-r-24 p-t-16 p-b-16 flex-grow d-flex d-col min-height-0\">\n <legend>{{ 'Preview' | translate }}</legend>\n <c8y-dashboard\n class=\"dashboard-preview-slot flex-grow min-height-0\"\n [columns]=\"1\"\n [ngClass]=\"previewClasses\"\n >\n <c8y-dashboard-child\n [isFrozen]=\"true\"\n [width]=\"1\"\n [height]=\"6\"\n >\n @let widgetTitle =\n (widgetConfigService.selected$ | async)?.data?.title\n | translate: { noTranslateRemoveContext: !translateWidgetTitle };\n <c8y-dashboard-child-title [attr.title]=\"widgetTitle\">\n <span>\n {{ widgetTitle }}\n </span>\n </c8y-dashboard-child-title>\n\n @if ((widgetConfigService.previewViewState$ | async) === 'noPreview') {\n <div class=\"fit-h d-flex d-col j-c-center a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'visibility-off'\"\n [title]=\"'No preview available.' | translate\"\n [subtitle]=\"'This widget does not provide any preview.' | translate\"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n </div>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'configPreview') {\n <c8y-dynamic-component\n [componentId]=\"(widgetConfigService.selected$ | async)?.id\"\n [config]=\"(widgetConfigService.currentConfig$ | async)?.config\"\n ></c8y-dynamic-component>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'templatePreview') {\n <ng-template [ngTemplateOutlet]=\"widgetConfigService.preview$ | async\"></ng-template>\n }\n </c8y-dashboard-child>\n </c8y-dashboard>\n</fieldset>\n" }]
2526
+ args: [{ selector: 'c8y-widget-preview', host: { class: 'flex-grow d-flex d-col' }, standalone: true, imports: [NgClass, C8yTranslatePipe, CommonModule, CoreModule], template: "<fieldset class=\"c8y-fieldset p-l-24 p-r-24 p-t-16 p-b-16 flex-grow d-flex d-col min-height-0\">\n <legend>{{ 'Preview' | translate }}</legend>\n <c8y-dashboard\n class=\"dashboard-preview-slot flex-grow min-height-0\"\n [columns]=\"1\"\n [ngClass]=\"previewClasses\"\n >\n @if (showContent()) {\n <c8y-dashboard-child\n [isFrozen]=\"true\"\n [width]=\"1\"\n [height]=\"6\"\n >\n @let widgetTitle =\n (widgetConfigService.selected$ | async)?.data?.title\n | translate: { noTranslateRemoveContext: !translateWidgetTitle };\n <c8y-dashboard-child-title [attr.title]=\"widgetTitle\">\n <span>\n {{ widgetTitle }}\n </span>\n </c8y-dashboard-child-title>\n\n @if ((widgetConfigService.previewViewState$ | async) === 'noPreview') {\n <div class=\"fit-h d-flex d-col j-c-center a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'visibility-off'\"\n [title]=\"'No preview available.' | translate\"\n [subtitle]=\"'This widget does not provide any preview.' | translate\"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n </div>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'configPreview') {\n <c8y-dynamic-component\n [componentId]=\"(widgetConfigService.selected$ | async)?.id\"\n [config]=\"(widgetConfigService.currentConfig$ | async)?.config\"\n ></c8y-dynamic-component>\n }\n\n @if ((widgetConfigService.previewViewState$ | async) === 'templatePreview') {\n <ng-template [ngTemplateOutlet]=\"widgetConfigService.preview$ | async\"></ng-template>\n }\n </c8y-dashboard-child>\n }\n </c8y-dashboard>\n</fieldset>\n" }]
2486
2527
  }], propDecorators: { previewClasses: [{
2487
2528
  type: Input
2488
2529
  }] } });
@@ -2736,7 +2777,37 @@ class WidgetConfigComponent {
2736
2777
  cssClasses[this.styling.contentClass] = true;
2737
2778
  }
2738
2779
  if (isPreview) {
2739
- cssClasses[`dashboard-theme-${this.defaultStyling.contentClass.split('-').pop()}`] = true;
2780
+ // When the widget has its own explicit theme (dark/white/branded), the preview
2781
+ // should use the widget's theme — not the dashboard's. In the actual dashboard,
2782
+ // dark/white widgets only get their own theme tokens, not the dashboard's branded
2783
+ // overrides. "Match dashboard" (panel-content-light) and non-theme content classes
2784
+ // (e.g. transparent) inherit the dashboard theme.
2785
+ const widgetSuffix = this.styling.contentClass.split('-').pop();
2786
+ const explicitWidgetThemes = new Set(['dark', 'white', 'branded']);
2787
+ const themeSuffix = explicitWidgetThemes.has(widgetSuffix)
2788
+ ? widgetSuffix
2789
+ : this.defaultStyling.contentClass.split('-').pop();
2790
+ cssClasses[`dashboard-theme-${themeSuffix}`] = true;
2791
+ }
2792
+ // Add foundation theme class so branding overrides cascade into the preview.
2793
+ // Widget-level content class takes priority over dashboard-level theme.
2794
+ let foundationClass = null;
2795
+ for (const [cls, fc] of Object.entries(WIDGET_FOUNDATION_MAP)) {
2796
+ if (cssClasses[cls]) {
2797
+ foundationClass = fc;
2798
+ break;
2799
+ }
2800
+ }
2801
+ if (!foundationClass) {
2802
+ for (const [cls, fc] of Object.entries(DASHBOARD_FOUNDATION_MAP)) {
2803
+ if (cssClasses[cls]) {
2804
+ foundationClass = fc;
2805
+ break;
2806
+ }
2807
+ }
2808
+ }
2809
+ if (foundationClass) {
2810
+ cssClasses[foundationClass] = true;
2740
2811
  }
2741
2812
  return cssClasses;
2742
2813
  }
@@ -2887,6 +2958,7 @@ class ContextDashboardComponent {
2887
2958
  other instances.`);
2888
2959
  this.hasPermissionToEditDashboard = false;
2889
2960
  this.destroy$ = new Subject();
2961
+ this.actionBarFoundationClass = null;
2890
2962
  }
2891
2963
  ngOnInit() {
2892
2964
  if (!this.name) {
@@ -2926,6 +2998,7 @@ class ContextDashboardComponent {
2926
2998
  if (this.dataSub) {
2927
2999
  this.dataSub.unsubscribe();
2928
3000
  }
3001
+ this.removeActionBarFoundationClass();
2929
3002
  this.contextDashboardStateService.setSelectedDashboard(null);
2930
3003
  }
2931
3004
  /**
@@ -2935,8 +3008,11 @@ class ContextDashboardComponent {
2935
3008
  * on 'beforeunload' event handler, error is thrown in console because confirm is blocked by browser anyway and returns false)
2936
3009
  */
2937
3010
  async canDeactivate(omitConfirm = false) {
2938
- const canDeactivate = (await this.dashboardDetails.canDeactivate(omitConfirm)) &&
2939
- (await this.widgetsDashboard.canDeactivate(omitConfirm));
3011
+ // The view children are undefined while the dashboard is still loading (the guard can run on a
3012
+ // quick navigation away before the first render). There is nothing to confirm then — allow the
3013
+ // navigation instead of throwing, which would cancel it with an error and trap the page.
3014
+ const canDeactivate = ((await this.dashboardDetails?.canDeactivate(omitConfirm)) ?? true) &&
3015
+ ((await this.widgetsDashboard?.canDeactivate(omitConfirm)) ?? true);
2940
3016
  // Needed in order to reset edit mode, otherwise when switching between dashboards, the edit mode is still enabled.
2941
3017
  if (canDeactivate) {
2942
3018
  await this.cancelEditMode(true);
@@ -3119,7 +3195,7 @@ class ContextDashboardComponent {
3119
3195
  ]);
3120
3196
  }
3121
3197
  }
3122
- catch (ex) {
3198
+ catch {
3123
3199
  // intended empty
3124
3200
  }
3125
3201
  }
@@ -3150,7 +3226,7 @@ class ContextDashboardComponent {
3150
3226
  if (this.dashboard) {
3151
3227
  this.dashboard.historyDescription = {};
3152
3228
  }
3153
- this.widgetsDashboard.editMode$.next(false);
3229
+ this.widgetsDashboard?.editMode$.next(false);
3154
3230
  if (!onDeactivate) {
3155
3231
  // when setWidgets is called during navigation from device to device, navigation fails
3156
3232
  await this.setWidgets(dashboardChildren.children);
@@ -3203,7 +3279,9 @@ class ContextDashboardComponent {
3203
3279
  */
3204
3280
  addDashboardClassToBody() {
3205
3281
  this.class.split(' ').forEach(cssClass => {
3206
- this.renderer.addClass(document.body, cssClass);
3282
+ if (!FOUNDATION_CLASSES.includes(cssClass)) {
3283
+ this.renderer.addClass(document.body, cssClass);
3284
+ }
3207
3285
  });
3208
3286
  }
3209
3287
  /**
@@ -3212,7 +3290,9 @@ class ContextDashboardComponent {
3212
3290
  */
3213
3291
  removeDashboardClassFromBody() {
3214
3292
  this.class.split(' ').forEach(cssClass => {
3215
- this.renderer.removeClass(document.body, cssClass);
3293
+ if (!FOUNDATION_CLASSES.includes(cssClass)) {
3294
+ this.renderer.removeClass(document.body, cssClass);
3295
+ }
3216
3296
  });
3217
3297
  }
3218
3298
  async onLoad(trackExperience) {
@@ -3231,6 +3311,8 @@ class ContextDashboardComponent {
3231
3311
  dashboard: true,
3232
3312
  ...this.dashboard?.classes
3233
3313
  };
3314
+ this.addFoundationClasses(dashboardClasses);
3315
+ this.updateActionBarTheme(dashboardClasses);
3234
3316
  this.isCopyDisabled = this.dashboard
3235
3317
  ? this.getDashboardCopyPermissionState()
3236
3318
  : { state: false, reason: null };
@@ -3259,6 +3341,8 @@ class ContextDashboardComponent {
3259
3341
  dashboard: true,
3260
3342
  ...layoutChanges.classes
3261
3343
  };
3344
+ this.addFoundationClasses(dashboardClasses);
3345
+ this.updateActionBarTheme(dashboardClasses);
3262
3346
  this.class = Object.keys(dashboardClasses).join(' ');
3263
3347
  }
3264
3348
  else if (this.dashboard) {
@@ -3362,6 +3446,45 @@ class ContextDashboardComponent {
3362
3446
  }
3363
3447
  return { state: true };
3364
3448
  }
3449
+ /**
3450
+ * Adds a CSS foundation theme class (c8y-dark-theme / c8y-light-theme)
3451
+ * to dashboard classes based on the selected dashboard theme.
3452
+ * This enables branding overrides to cascade via the standard theme selectors.
3453
+ */
3454
+ addFoundationClasses(dashboardClasses) {
3455
+ for (const [themeClass, foundationClass] of Object.entries(THEME_FOUNDATION_MAP)) {
3456
+ if (dashboardClasses[themeClass]) {
3457
+ dashboardClasses[foundationClass] = true;
3458
+ }
3459
+ }
3460
+ }
3461
+ /**
3462
+ * Adds/removes the foundation theme class on the action bar element,
3463
+ * which lives outside the dashboard container and cannot inherit tokens from it.
3464
+ */
3465
+ updateActionBarTheme(dashboardClasses) {
3466
+ const actionBar = document.querySelector('.c8y-ui-action-bar');
3467
+ if (!actionBar) {
3468
+ return;
3469
+ }
3470
+ this.removeActionBarFoundationClass();
3471
+ for (const [themeClass, foundationClass] of Object.entries(THEME_FOUNDATION_MAP)) {
3472
+ if (dashboardClasses[themeClass]) {
3473
+ this.renderer.addClass(actionBar, foundationClass);
3474
+ this.actionBarFoundationClass = foundationClass;
3475
+ break;
3476
+ }
3477
+ }
3478
+ }
3479
+ removeActionBarFoundationClass() {
3480
+ if (this.actionBarFoundationClass) {
3481
+ const actionBar = document.querySelector('.c8y-ui-action-bar');
3482
+ if (actionBar) {
3483
+ this.renderer.removeClass(actionBar, this.actionBarFoundationClass);
3484
+ }
3485
+ this.actionBarFoundationClass = null;
3486
+ }
3487
+ }
3365
3488
  setNewState(state, descriptionProp, widgetsChanged) {
3366
3489
  const description = this.getDescriptionForNewState(descriptionProp, widgetsChanged);
3367
3490
  this.editModeService.newState({ ...state, changeHistory: description });
@@ -3479,7 +3602,7 @@ class ContextDashboardComponent {
3479
3602
  : this.gainsightService.hashGroupName(str);
3480
3603
  }
3481
3604
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ContextDashboardComponent, deps: [{ token: i1.ActivatedRoute }, { token: i1.Router }, { token: ContextDashboardService }, { token: i2.AlertService }, { token: i0.Renderer2 }, { token: CONTEXT_DASHBOARD_CONFIG }, { token: WidgetService }, { token: i2.BottomDrawerService }, { token: i2.GainsightService }, { token: i2.ActionBarService }, { token: i2$1.TranslateService }, { token: i2.ModalService }, { token: i0.DestroyRef }, { token: i6.ContextDashboardStateService }, { token: DashboardEditModeService }], target: i0.ɵɵFactoryTarget.Component }); }
3482
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ContextDashboardComponent, isStandalone: true, selector: "c8y-context-dashboard", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: false, isRequired: false, transformFunction: null }, childrenClasses: { classPropertyName: "childrenClasses", publicName: "childrenClasses", isSignal: false, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: false, isRequired: false, transformFunction: null }, setTitle: { classPropertyName: "setTitle", publicName: "setTitle", isSignal: false, isRequired: false, transformFunction: null }, defaultWidgets: { classPropertyName: "defaultWidgets", publicName: "defaultWidgets", isSignal: false, isRequired: false, transformFunction: null }, _canCopy: { classPropertyName: "_canCopy", publicName: "canCopy", isSignal: false, isRequired: false, transformFunction: null }, canDelete: { classPropertyName: "canDelete", publicName: "canDelete", isSignal: false, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: false, isRequired: false, transformFunction: null }, breadcrumbSettings: { classPropertyName: "breadcrumbSettings", publicName: "breadcrumbSettings", isSignal: false, isRequired: false, transformFunction: null }, showContextHelpButton: { classPropertyName: "showContextHelpButton", publicName: "showContextHelpButton", isSignal: false, isRequired: false, transformFunction: null }, translateWidgetTitle: { classPropertyName: "translateWidgetTitle", publicName: "translateWidgetTitle", isSignal: false, isRequired: false, transformFunction: null }, translateDashboardTitle: { classPropertyName: "translateDashboardTitle", publicName: "translateDashboardTitle", isSignal: false, isRequired: false, transformFunction: null }, hideAvailability: { classPropertyName: "hideAvailability", publicName: "hideAvailability", isSignal: false, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:beforeunload": "beforeUnloadHandler($event)" }, properties: { "class": "this.class" }, styleAttribute: "\n display: block;\n ", classAttribute: "dashboard c8y-grid-dashboard" }, viewQueries: [{ propertyName: "dashboardDetails", first: true, predicate: DashboardDetailComponent, descendants: true, static: true }, { propertyName: "widgetsDashboard", first: true, predicate: WidgetsDashboardComponent, descendants: true, static: true }], ngImport: i0, template: "@if (title) {\n <c8y-title>\n {{ title }}\n </c8y-title>\n}\n\n@if (dashboard?.deviceType && dashboard.deviceTypeValue) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"10000\"\n >\n <button\n class=\"btn-clean btn-link\"\n popoverTitle=\"{{ 'Dashboard template' | translate }}\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"dashboardTypePopoverRef\"\n placement=\"bottom\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n >\n <span class=\"tag tag--info text-12\">\n <span class=\"dashboard-template-marker\"></span>\n {{ dashboardTypeLabel | translate: { dashboardType: dashboard.deviceTypeValue } }}\n </span>\n </button>\n <ng-template #dashboardTypePopoverRef>\n <div\n [innerHTML]=\"dashboardTypePopover | translate: { dashboardType: dashboard.deviceTypeValue }\"\n ></div>\n </ng-template>\n </c8y-action-bar-item>\n}\n\n@if (defaultWidgets.length > 0) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"-1\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reset widgets' | translate }}\"\n type=\"button\"\n px-event=\"Reset dashboard\"\n (click)=\"restore()\"\n [disabled]=\"disabled || !mo?.id || (widgetsDashboard?.editMode$ | async)\"\n data-cy=\"context-dashboard--button-reset-dashboard\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"reset\"\n ></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visible-lg-inline\">\n {{ 'Reset widgets' | translate }}\n </span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (showContextHelpButton) {\n <c8y-help src=\"/docs/cockpit/working-with-dashboards/#working-with-dashboards\"></c8y-help>\n}\n\n<c8y-dashboard-detail\n class=\"d-contents\"\n [isReport]=\"isReport\"\n [dashboard]=\"dashboard\"\n [mo]=\"mo\"\n [context]=\"context\"\n [deviceType]=\"context?.type\"\n [hideAvailability]=\"hideAvailability\"\n [isNamedDashboard]=\"isNamedDashboard\"\n (dashboardSaved)=\"reloadDashboard($event)\"\n (previewChanged)=\"dashboardPreview($event)\"\n></c8y-dashboard-detail>\n\n<c8y-widgets-dashboard\n [context]=\"context\"\n [contextDashboard]=\"dashboard\"\n [widgets]=\"widgets\"\n [isCopyDisabled]=\"isCopyDisabled\"\n [isSaveDisabled]=\"contextDashboardStateService.isSaveDisabled | async\"\n [settings]=\"{\n isLoading: isLoading,\n isDisabled: disabled,\n canDelete: canDelete && !!dashboard,\n translateWidgetTitle: dashboard?.translateWidgetTitle ?? translateWidgetTitle,\n translateDashboardTitle: dashboard?.translateDashboardTitle ?? translateDashboardTitle,\n allowFullscreen: moduleConfig.allowFullscreen,\n title: setTitle ? dashboard?.name || title : undefined,\n widgetMargin: dashboard?.widgetMargin,\n canCopy: canCopy && !!dashboard,\n defaultWidth: dashboard?.columns >= 24 ? 8 : 4,\n columns: dashboard?.columns || 12\n }\"\n [breadcrumb]=\"breadcrumbSettings\"\n [editModeButtons]=\"{\n undoButtonDisabled: editModeService.undoButtonDisabled,\n changeToUndoName: editModeService.changeToUndoName,\n redoButtonDisabled: !editModeService.redoStackLastItem,\n changeToRedoName: editModeService.redoStackLastItem?.name\n }\"\n (onChangeDashboard)=\"positionOrWidgetDimensionChange($event)\"\n (onAddWidget)=\"addWidget()\"\n (onEditWidget)=\"editWidget($event)\"\n (onDeleteWidget)=\"deleteWidget($event)\"\n (onSaveDashboard)=\"saveWidgetsToDashboard()\"\n (onCancelDashboard)=\"cancelEditMode()\"\n (revertChange)=\"revertChange($event)\"\n (onChangeStart)=\"addDashboardClassToBody()\"\n (onChangeEnd)=\"removeDashboardClassFromBody()\"\n (onEditDashboard)=\"editDashboard()\"\n (onCopyDashboard)=\"copyDashboard()\"\n (onDeleteDashboard)=\"deleteDashboard()\"\n></c8y-widgets-dashboard>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: DashboardDetailComponent, selector: "c8y-dashboard-detail", inputs: ["isReport", "deviceType", "context", "mo", "dashboard", "isNamedDashboard", "hideAvailability"], outputs: ["dashboardSaved", "previewChanged"] }, { kind: "component", type: WidgetsDashboardComponent, selector: "c8y-widgets-dashboard", inputs: ["widgets", "context", "contextDashboard", "settings", "isCopyDisabled", "breadcrumb", "editModeButtons", "isSaveDisabled"], outputs: ["onAddWidget", "onEditWidget", "onDeleteWidget", "onChangeDashboard", "onResize", "onEditDashboard", "onCopyDashboard", "onDeleteDashboard", "onChangeStart", "onChangeEnd", "onSaveDashboard", "onCancelDashboard", "revertChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
3605
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ContextDashboardComponent, isStandalone: true, selector: "c8y-context-dashboard", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: false, isRequired: false, transformFunction: null }, childrenClasses: { classPropertyName: "childrenClasses", publicName: "childrenClasses", isSignal: false, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: false, isRequired: false, transformFunction: null }, setTitle: { classPropertyName: "setTitle", publicName: "setTitle", isSignal: false, isRequired: false, transformFunction: null }, defaultWidgets: { classPropertyName: "defaultWidgets", publicName: "defaultWidgets", isSignal: false, isRequired: false, transformFunction: null }, _canCopy: { classPropertyName: "_canCopy", publicName: "canCopy", isSignal: false, isRequired: false, transformFunction: null }, canDelete: { classPropertyName: "canDelete", publicName: "canDelete", isSignal: false, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: false, isRequired: false, transformFunction: null }, breadcrumbSettings: { classPropertyName: "breadcrumbSettings", publicName: "breadcrumbSettings", isSignal: false, isRequired: false, transformFunction: null }, showContextHelpButton: { classPropertyName: "showContextHelpButton", publicName: "showContextHelpButton", isSignal: false, isRequired: false, transformFunction: null }, translateWidgetTitle: { classPropertyName: "translateWidgetTitle", publicName: "translateWidgetTitle", isSignal: false, isRequired: false, transformFunction: null }, translateDashboardTitle: { classPropertyName: "translateDashboardTitle", publicName: "translateDashboardTitle", isSignal: false, isRequired: false, transformFunction: null }, hideAvailability: { classPropertyName: "hideAvailability", publicName: "hideAvailability", isSignal: false, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:beforeunload": "beforeUnloadHandler($event)" }, properties: { "class": "this.class" }, styleAttribute: "\n display: block;\n ", classAttribute: "dashboard c8y-grid-dashboard" }, viewQueries: [{ propertyName: "dashboardDetails", first: true, predicate: DashboardDetailComponent, descendants: true, static: true }, { propertyName: "widgetsDashboard", first: true, predicate: WidgetsDashboardComponent, descendants: true, static: true }], ngImport: i0, template: "@if (title) {\n <c8y-title>\n {{ title }}\n </c8y-title>\n}\n\n@if (dashboard?.deviceType && dashboard.deviceTypeValue) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"10000\"\n >\n <button\n class=\"btn-clean btn-link\"\n popoverTitle=\"{{ 'Dashboard template' | translate }}\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"dashboardTypePopoverRef\"\n placement=\"bottom\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n >\n <span class=\"tag tag--info text-12\">\n <span class=\"dashboard-template-marker\"></span>\n {{ dashboardTypeLabel | translate: { dashboardType: dashboard.deviceTypeValue } }}\n </span>\n </button>\n <ng-template #dashboardTypePopoverRef>\n <div\n [innerHTML]=\"dashboardTypePopover | translate: { dashboardType: dashboard.deviceTypeValue }\"\n ></div>\n </ng-template>\n </c8y-action-bar-item>\n}\n\n@if (defaultWidgets.length > 0) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"-1\"\n >\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reset widgets' | translate }}\"\n type=\"button\"\n px-event=\"Reset dashboard\"\n (click)=\"restore()\"\n [disabled]=\"disabled || !mo?.id || (widgetsDashboard?.editMode$ | async)\"\n data-cy=\"context-dashboard--button-reset-dashboard\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"reset\"\n ></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visible-lg-inline\">\n {{ 'Reset widgets' | translate }}\n </span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (showContextHelpButton) {\n <c8y-help src=\"/docs/cockpit/working-with-dashboards/#working-with-dashboards\"></c8y-help>\n}\n\n<c8y-dashboard-detail\n class=\"d-contents\"\n [isReport]=\"isReport\"\n [dashboard]=\"dashboard\"\n [mo]=\"mo\"\n [context]=\"context\"\n [deviceType]=\"context?.type\"\n [hideAvailability]=\"hideAvailability\"\n [isNamedDashboard]=\"isNamedDashboard\"\n (dashboardSaved)=\"reloadDashboard($event)\"\n (previewChanged)=\"dashboardPreview($event)\"\n></c8y-dashboard-detail>\n\n<c8y-widgets-dashboard\n [context]=\"context\"\n [contextDashboard]=\"dashboard\"\n [widgets]=\"widgets\"\n [isCopyDisabled]=\"isCopyDisabled\"\n [isSaveDisabled]=\"contextDashboardStateService.isSaveDisabled | async\"\n [settings]=\"{\n isLoading: isLoading,\n isDisabled: disabled,\n canDelete: canDelete && !!dashboard,\n translateWidgetTitle: dashboard?.translateWidgetTitle ?? translateWidgetTitle,\n translateDashboardTitle: dashboard?.translateDashboardTitle ?? translateDashboardTitle,\n allowFullscreen: moduleConfig.allowFullscreen,\n title: setTitle ? dashboard?.name || title : undefined,\n widgetMargin: dashboard?.widgetMargin,\n canCopy: canCopy && !!dashboard,\n defaultWidth: dashboard?.columns >= 24 ? 8 : 4,\n columns: dashboard?.columns || 12\n }\"\n [breadcrumb]=\"breadcrumbSettings\"\n [editModeButtons]=\"{\n undoButtonDisabled: editModeService.undoButtonDisabled,\n changeToUndoName: editModeService.changeToUndoName,\n redoButtonDisabled: !editModeService.redoStackLastItem,\n changeToRedoName: editModeService.redoStackLastItem?.name\n }\"\n (onChangeDashboard)=\"positionOrWidgetDimensionChange($event)\"\n (onAddWidget)=\"addWidget()\"\n (onEditWidget)=\"editWidget($event)\"\n (onDeleteWidget)=\"deleteWidget($event)\"\n (onSaveDashboard)=\"saveWidgetsToDashboard()\"\n (onCancelDashboard)=\"cancelEditMode()\"\n (revertChange)=\"revertChange($event)\"\n (onChangeStart)=\"addDashboardClassToBody()\"\n (onChangeEnd)=\"removeDashboardClassFromBody()\"\n (onEditDashboard)=\"editDashboard()\"\n (onCopyDashboard)=\"copyDashboard()\"\n (onDeleteDashboard)=\"deleteDashboard()\"\n></c8y-widgets-dashboard>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: DashboardDetailComponent, selector: "c8y-dashboard-detail", inputs: ["isReport", "deviceType", "context", "mo", "dashboard", "isNamedDashboard", "hideAvailability"], outputs: ["dashboardSaved", "previewChanged"] }, { kind: "component", type: WidgetsDashboardComponent, selector: "c8y-widgets-dashboard", inputs: ["widgets", "context", "contextDashboard", "settings", "isCopyDisabled", "breadcrumb", "editModeButtons", "isSaveDisabled", "clearWidgetContentOnLeave"], outputs: ["onAddWidget", "onEditWidget", "onDeleteWidget", "onChangeDashboard", "onResize", "onEditDashboard", "onCopyDashboard", "onDeleteDashboard", "onChangeStart", "onChangeEnd", "onSaveDashboard", "onCancelDashboard", "revertChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
3483
3606
  }
3484
3607
  __decorate([
3485
3608
  memoize(),
@@ -4289,7 +4412,7 @@ class DeviceInfoDashboardComponent {
4289
4412
  this.contextSubscription.unsubscribe();
4290
4413
  }
4291
4414
  canDeactivate() {
4292
- return this.contextDashboard?.canDeactivate();
4415
+ return this.contextDashboard?.canDeactivate() ?? Promise.resolve(true);
4293
4416
  }
4294
4417
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeviceInfoDashboardComponent, deps: [{ token: i1.ActivatedRoute }, { token: WidgetService }, { token: i2$1.TranslateService }, { token: i1$1.InventoryService }], target: i0.ɵɵFactoryTarget.Component }); }
4295
4418
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: DeviceInfoDashboardComponent, isStandalone: true, selector: "c8y-device-info-dashboard-dashboard", viewQueries: [{ propertyName: "contextDashboard", first: true, predicate: ContextDashboardComponent, descendants: true }], ngImport: i0, template: "@if (!isLoading) {\n <div>\n <c8y-title>\n {{ title }}\n </c8y-title>\n <c8y-context-dashboard\n [translateWidgetTitle]=\"true\"\n [name]=\"dashboardName\"\n [context]=\"currentContext\"\n [defaultWidgets]=\"widgetsList\"\n [canDelete]=\"false\"\n [hideAvailability]=\"true\"\n [canCopy]=\"false\"\n [disabled]=\"previewEnabled$ | async\"\n ></c8y-context-dashboard>\n </div>\n}\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: ContextDashboardComponent, selector: "c8y-context-dashboard", inputs: ["name", "childrenClasses", "context", "setTitle", "defaultWidgets", "canCopy", "canDelete", "isLoading", "breadcrumbSettings", "showContextHelpButton", "translateWidgetTitle", "translateDashboardTitle", "hideAvailability", "disabled"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
@@ -4327,7 +4450,7 @@ class DeviceInfoDashboardModule {
4327
4450
  label: gettext('Info'),
4328
4451
  priority: 10000,
4329
4452
  icon: 'asterisk',
4330
- canDeactivate: [(component) => component.canDeactivate()],
4453
+ canDeactivate: [(component) => component?.canDeactivate() ?? true],
4331
4454
  rootContext: ViewContext.Dashboard
4332
4455
  })
4333
4456
  ], imports: [CommonModule, CoreModule, ContextDashboardModule, DeviceInfoDashboardComponent] }); }
@@ -4346,7 +4469,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4346
4469
  label: gettext('Info'),
4347
4470
  priority: 10000,
4348
4471
  icon: 'asterisk',
4349
- canDeactivate: [(component) => component.canDeactivate()],
4472
+ canDeactivate: [(component) => component?.canDeactivate() ?? true],
4350
4473
  rootContext: ViewContext.Dashboard
4351
4474
  })
4352
4475
  ]
@@ -4378,7 +4501,7 @@ class DeviceManagementHomeDashboardComponent {
4378
4501
  });
4379
4502
  }
4380
4503
  canDeactivate() {
4381
- return this.contextDashboard?.canDeactivate();
4504
+ return this.contextDashboard?.canDeactivate() ?? Promise.resolve(true);
4382
4505
  }
4383
4506
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeviceManagementHomeDashboardComponent, deps: [{ token: WidgetService }], target: i0.ɵɵFactoryTarget.Component }); }
4384
4507
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: DeviceManagementHomeDashboardComponent, isStandalone: true, selector: "c8y-device-management-home-dashboard", viewQueries: [{ propertyName: "contextDashboard", first: true, predicate: ContextDashboardComponent, descendants: true, static: true }], ngImport: i0, template: "<c8y-title>\n {{ 'Home' | translate }}\n</c8y-title>\n\n<c8y-context-dashboard\n [name]=\"dashboardName\"\n [defaultWidgets]=\"defaultWidgets\"\n [canDelete]=\"false\"\n [hideAvailability]=\"true\"\n></c8y-context-dashboard>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: ContextDashboardComponent, selector: "c8y-context-dashboard", inputs: ["name", "childrenClasses", "context", "setTitle", "defaultWidgets", "canCopy", "canDelete", "isLoading", "breadcrumbSettings", "showContextHelpButton", "translateWidgetTitle", "translateDashboardTitle", "hideAvailability", "disabled"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
@@ -4401,7 +4524,7 @@ class DeviceManagementHomeDashboardModule {
4401
4524
  hookRoute({
4402
4525
  path: 'home',
4403
4526
  component: DeviceManagementHomeDashboardComponent,
4404
- canDeactivate: [(component) => component.canDeactivate()],
4527
+ canDeactivate: [(component) => component?.canDeactivate() ?? true],
4405
4528
  rootContext: ViewContext.Dashboard
4406
4529
  }),
4407
4530
  hookNavigator({ label: gettext('Home'), icon: 'home', priority: 10000, path: '/home' })
@@ -4424,7 +4547,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4424
4547
  hookRoute({
4425
4548
  path: 'home',
4426
4549
  component: DeviceManagementHomeDashboardComponent,
4427
- canDeactivate: [(component) => component.canDeactivate()],
4550
+ canDeactivate: [(component) => component?.canDeactivate() ?? true],
4428
4551
  rootContext: ViewContext.Dashboard
4429
4552
  }),
4430
4553
  hookNavigator({ label: gettext('Home'), icon: 'home', priority: 10000, path: '/home' })
@@ -4998,5 +5121,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
4998
5121
  * Generated bundle index. Do not edit.
4999
5122
  */
5000
5123
 
5001
- export { ALL_GLOBAL_ROLES_SELECTED, AddDashboardComponent, AddDashboardFactory, AppearanceSettingsComponent, AssetPropertyMappingsComponent, AssetPropertyMappingsService, CONTEXT_DASHBOARD_CONFIG, ContextDashboardComponent, ContextDashboardModule, ContextDashboardService, ContextDashboardType, DASHBOARD_CHILDREN_STATE_NAME, DASHBOARD_DETAILS_OUTLET, DASHBOARD_DETAILS_TABS_OUTLET_NAME, DASHBOARD_SETTINGS_CHANGES, DASHBOARD_THEME_CLASSES, DashboardActionBarFactory, DashboardDetailComponent, DashboardDetailService, DashboardDetailsTabId, DeviceInfoDashboardComponent, DeviceInfoDashboardModule, DeviceManagementHomeDashboardComponent, DeviceManagementHomeDashboardModule, GlobalContextSectionComponent, HOOK_WIDGET_CONFIG, NewDashboardGuard, PRODUCT_EXPERIENCE, PasteDashboardActionComponent, REPORT_DEFAULT_NAVIGATION_NODE_PRIORITY, STYLING_CLASS_PREFIXES, TypeDashboardInfoComponent, WIDGET_CONTENT_CLASSES, WIDGET_HEADER_CLASSES, WidgetAssetSelectorComponent, WidgetConfigAppearanceComponent, WidgetConfigComponent, WidgetConfigFeedbackComponent, WidgetConfigGeneralComponent, WidgetConfigSectionComponent, WidgetConfigSectionService, WidgetConfigService, WidgetPreviewComponent, WidgetPreviewWrapperComponent, WidgetService, escapeForRegExp, getPropertyBaseKey, hookWidgetConfig, newDashboardTab, quoteAndEscape, renamePropertyKeyInCode };
5124
+ export { ALL_GLOBAL_ROLES_SELECTED, AddDashboardComponent, AddDashboardFactory, AppearanceSettingsComponent, AssetPropertyMappingsComponent, AssetPropertyMappingsService, CONTEXT_DASHBOARD_CONFIG, ContextDashboardComponent, ContextDashboardModule, ContextDashboardService, ContextDashboardType, DASHBOARD_CHILDREN_STATE_NAME, DASHBOARD_DETAILS_OUTLET, DASHBOARD_DETAILS_TABS_OUTLET_NAME, DASHBOARD_FOUNDATION_MAP, DASHBOARD_SETTINGS_CHANGES, DASHBOARD_THEME_CLASSES, DashboardActionBarFactory, DashboardDetailComponent, DashboardDetailService, DashboardDetailsTabId, DeviceInfoDashboardComponent, DeviceInfoDashboardModule, DeviceManagementHomeDashboardComponent, DeviceManagementHomeDashboardModule, FOUNDATION_CLASSES, GlobalContextSectionComponent, HOOK_WIDGET_CONFIG, NewDashboardGuard, PRODUCT_EXPERIENCE, PasteDashboardActionComponent, REPORT_DEFAULT_NAVIGATION_NODE_PRIORITY, STYLING_CLASS_PREFIXES, THEME_FOUNDATION_MAP, TypeDashboardInfoComponent, WIDGET_CONTENT_CLASSES, WIDGET_FOUNDATION_MAP, WIDGET_HEADER_CLASSES, WidgetAssetSelectorComponent, WidgetConfigAppearanceComponent, WidgetConfigComponent, WidgetConfigFeedbackComponent, WidgetConfigGeneralComponent, WidgetConfigSectionComponent, WidgetConfigSectionService, WidgetConfigService, WidgetPreviewComponent, WidgetPreviewWrapperComponent, WidgetService, escapeForRegExp, getPropertyBaseKey, hookWidgetConfig, newDashboardTab, quoteAndEscape, renamePropertyKeyInCode };
5002
5125
  //# sourceMappingURL=c8y-ngx-components-context-dashboard.mjs.map