@c8y/ngx-components 1022.44.3 → 1022.45.2

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 (76) hide show
  1. package/asset-properties/asset-properties.model.d.ts +1 -1
  2. package/asset-properties/asset-properties.model.d.ts.map +1 -1
  3. package/asset-properties/asset-property-list/asset-property-value.pipe.d.ts.map +1 -1
  4. package/computed-asset-properties/last-measurement/last-measurement-value.d.ts +2 -1
  5. package/computed-asset-properties/last-measurement/last-measurement-value.d.ts.map +1 -1
  6. package/computed-asset-properties/strategies/last-measurement-strategy.d.ts +4 -3
  7. package/computed-asset-properties/strategies/last-measurement-strategy.d.ts.map +1 -1
  8. package/context-dashboard/context-dashboard.service.d.ts +20 -2
  9. package/context-dashboard/context-dashboard.service.d.ts.map +1 -1
  10. package/context-dashboard/widget-config/widget-asset-selector.component.d.ts +8 -2
  11. package/context-dashboard/widget-config/widget-asset-selector.component.d.ts.map +1 -1
  12. package/context-dashboard/widget-config.component.d.ts.map +1 -1
  13. package/context-dashboard/widget-config.service.d.ts +7 -1
  14. package/context-dashboard/widget-config.service.d.ts.map +1 -1
  15. package/core/bottom-drawer/bottom-drawer.component.d.ts +16 -2
  16. package/core/bottom-drawer/bottom-drawer.component.d.ts.map +1 -1
  17. package/core/bottom-drawer/bottom-drawer.service.d.ts +13 -5
  18. package/core/bottom-drawer/bottom-drawer.service.d.ts.map +1 -1
  19. package/core/dashboard/widgets-dashboard.component.d.ts +8 -0
  20. package/core/dashboard/widgets-dashboard.component.d.ts.map +1 -1
  21. package/core/router/router.service.d.ts +1 -0
  22. package/core/router/router.service.d.ts.map +1 -1
  23. package/dashboard-manager/dashboard-manager.service.d.ts +5 -4
  24. package/dashboard-manager/dashboard-manager.service.d.ts.map +1 -1
  25. package/dashboard-manager/devicemanagement/dashboard-manager-navigation.factory.d.ts +10 -0
  26. package/dashboard-manager/devicemanagement/dashboard-manager-navigation.factory.d.ts.map +1 -0
  27. package/dashboard-manager/devicemanagement/dashboard-manager-tabs.factory.d.ts +11 -0
  28. package/dashboard-manager/devicemanagement/dashboard-manager-tabs.factory.d.ts.map +1 -0
  29. package/dashboard-manager/devicemanagement/index.d.ts +4 -0
  30. package/dashboard-manager/devicemanagement/index.d.ts.map +1 -1
  31. package/dashboard-manager/index.d.ts +2 -1
  32. package/dashboard-manager/index.d.ts.map +1 -1
  33. package/dashboard-manager/type-dashboards-list/index.d.ts +2 -0
  34. package/dashboard-manager/type-dashboards-list/index.d.ts.map +1 -0
  35. package/editor/editor.component.d.ts +1 -0
  36. package/editor/editor.component.d.ts.map +1 -1
  37. package/fesm2022/c8y-ngx-components-asset-properties.mjs +1 -1
  38. package/fesm2022/c8y-ngx-components-asset-properties.mjs.map +1 -1
  39. package/fesm2022/c8y-ngx-components-computed-asset-properties.mjs +1 -1
  40. package/fesm2022/c8y-ngx-components-computed-asset-properties.mjs.map +1 -1
  41. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +56 -26
  42. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  43. package/fesm2022/c8y-ngx-components-dashboard-manager-devicemanagement.mjs +81 -6
  44. package/fesm2022/c8y-ngx-components-dashboard-manager-devicemanagement.mjs.map +1 -1
  45. package/fesm2022/c8y-ngx-components-dashboard-manager.mjs +185 -166
  46. package/fesm2022/c8y-ngx-components-dashboard-manager.mjs.map +1 -1
  47. package/fesm2022/c8y-ngx-components-editor.mjs +24 -1
  48. package/fesm2022/c8y-ngx-components-editor.mjs.map +1 -1
  49. package/fesm2022/c8y-ngx-components-map.mjs +1 -1
  50. package/fesm2022/c8y-ngx-components-map.mjs.map +1 -1
  51. package/fesm2022/c8y-ngx-components-sub-assets.mjs +11 -8
  52. package/fesm2022/c8y-ngx-components-sub-assets.mjs.map +1 -1
  53. package/fesm2022/c8y-ngx-components-widgets-implementations-cockpit-welcome.mjs +2 -2
  54. package/fesm2022/c8y-ngx-components-widgets-implementations-cockpit-welcome.mjs.map +1 -1
  55. package/fesm2022/c8y-ngx-components-widgets-implementations-html-widget.mjs.map +1 -1
  56. package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs +12 -7
  57. package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs.map +1 -1
  58. package/fesm2022/c8y-ngx-components.mjs +111 -31
  59. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  60. package/locales/de.po +19 -0
  61. package/locales/es.po +19 -0
  62. package/locales/fr.po +19 -0
  63. package/locales/ja_JP.po +17 -0
  64. package/locales/ko.po +18 -0
  65. package/locales/locales.pot +18 -0
  66. package/locales/nl.po +19 -0
  67. package/locales/pl.po +19 -0
  68. package/locales/pt_BR.po +19 -0
  69. package/locales/zh_CN.po +18 -0
  70. package/locales/zh_TW.po +18 -0
  71. package/package.json +1 -1
  72. package/sub-assets/add-group/add-group.component.d.ts.map +1 -1
  73. package/sub-assets/sub-assets.component.d.ts.map +1 -1
  74. package/widgets/implementations/html-widget/widget-code-editor-section/widget-code-editor.component.d.ts.map +1 -1
  75. package/widgets/implementations/map/map-widget.component.d.ts +1 -0
  76. package/widgets/implementations/map/map-widget.component.d.ts.map +1 -1
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, Component, inject, InjectionToken, EventEmitter, Output, Input, TemplateRef, ViewChild, Optional, Inject, HostListener, HostBinding, NgModule } from '@angular/core';
3
3
  import * as i2 from '@c8y/ngx-components';
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, DynamicComponentModule, DynamicComponentComponent, sortByPriority, isPromise, CoreModule, WIDGET_CONFIGURATION_GRID_SIZE, C8yTranslateDirective, HighlightComponent, EmptyStateComponent, FormGroupComponent, RequiredInputPlaceholderDirective, ProductExperienceDirective, ResizableGridComponent, DashboardChildChange, CopyDashboardDisabledReason, TitleComponent, ActionBarItemComponent, HelpComponent, WidgetsDashboardComponent, DatePipe, hookRoute, hookTab, hookNavigator } from '@c8y/ngx-components';
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, hookNavigator } from '@c8y/ngx-components';
5
5
  import * as i1 from '@angular/router';
6
6
  import { RouterOutlet, ActivatedRoute, RouterModule } from '@angular/router';
7
7
  import { of, Subject, from, combineLatest, map as map$1, timer, BehaviorSubject, tap as tap$1, withLatestFrom, mergeMap as mergeMap$1, shareReplay as shareReplay$1, merge, scan, debounceTime, isObservable, iif } from 'rxjs';
@@ -295,7 +295,7 @@ class ContextDashboardService {
295
295
  this._formDisabled = value;
296
296
  this.formDisabledSubject.next(value);
297
297
  }
298
- constructor(inventory, tabs, modal, translateService, router, navigator, permissions, alert, dynamicComponent, groupService, optionsService) {
298
+ constructor(inventory, tabs, modal, translateService, router, navigator, permissions, alert, dynamicComponent, groupService, optionsService, appStateService) {
299
299
  this.inventory = inventory;
300
300
  this.tabs = tabs;
301
301
  this.modal = modal;
@@ -307,6 +307,7 @@ class ContextDashboardService {
307
307
  this.dynamicComponent = dynamicComponent;
308
308
  this.groupService = groupService;
309
309
  this.optionsService = optionsService;
310
+ this.appStateService = appStateService;
310
311
  this.REPORT_PARTIAL_NAME = 'report_';
311
312
  this.VERSION_HISTORY_SIZE_LIMIT = 10;
312
313
  this.INVENTORY_ROLES = [
@@ -316,11 +317,13 @@ class ContextDashboardService {
316
317
  this.cache = new Map();
317
318
  this.DEFAULT_PAGESIZE = 1000;
318
319
  this.FRAGMENT_NAME = 'c8y_Dashboard';
320
+ this.APPLIED_TO_FRAGMENT = 'c8y_AppliedToApplications';
319
321
  this.DASHBOARD_ROUTE_PATH = 'dashboard';
320
322
  this.INDEX_SPLIT = '!';
321
323
  this.CACHE_TIMEOUT = 500;
322
324
  this._formDisabled = true;
323
325
  this.formDisabledSubject = new Subject();
326
+ this.appName = '';
324
327
  this.HIDE_TYPE_DASHBOARD_FOR_ASSETS = 'hideTypeDashboardForAssets';
325
328
  this.formDisabled$ = this.formDisabledSubject.asObservable();
326
329
  this.queriesUtil = new QueriesUtil();
@@ -334,6 +337,9 @@ class ContextDashboardService {
334
337
  assign(dashboard, { c8y_Global: {} });
335
338
  }
336
339
  dashboard.name = dashboard.c8y_Dashboard.name;
340
+ if (this.appStateService?.currentApplication?.value) {
341
+ dashboard[this.APPLIED_TO_FRAGMENT] = [this.appStateService?.currentApplication?.value.key];
342
+ }
337
343
  const { data } = dashboardType === ContextDashboardType.Group ||
338
344
  dashboardType === ContextDashboardType.Device ||
339
345
  (context?.contextData?.id && dashboardType === ContextDashboardType.Named)
@@ -351,7 +357,7 @@ class ContextDashboardService {
351
357
  const dashboardCfg = dashboard.c8y_Dashboard;
352
358
  dashboard.name = dashboard.c8y_Dashboard.name;
353
359
  assign(dashboard, this.adjustDashboardFor24Columns({ c8y_Dashboard: dashboardCfg }), this.updateDashboardHistory(dashboard, dashboardCfg));
354
- const keepFragments = this.clean(pick(dashboard, [this.FRAGMENT_NAME, 'id', 'name']));
360
+ const keepFragments = this.clean(pick(dashboard, [this.FRAGMENT_NAME, 'id', 'name', this.APPLIED_TO_FRAGMENT]));
355
361
  keepFragments.c8y_DashboardHistory = dashboard.c8y_DashboardHistory;
356
362
  await this.serializeWidgetConfigs(keepFragments);
357
363
  const [, dashboardTypeFragments] = this.getDashboardFragments(dashboard, context, '', true);
@@ -694,7 +700,11 @@ class ContextDashboardService {
694
700
  const finalFilterCriteria = typeFilterCriteria
695
701
  ? [...filterCriteria, typeFilterCriteria]
696
702
  : filterCriteria;
697
- const query = this.queriesUtil.buildQuery({ __filter: { __or: finalFilterCriteria } });
703
+ const query = this.queriesUtil.buildQuery({
704
+ __filter: {
705
+ __and: [{ __or: finalFilterCriteria }, this.appliedToFilter()]
706
+ }
707
+ });
698
708
  const now = Date.now();
699
709
  const cacheHasValidResponse = this.contextDashboardsCache &&
700
710
  this.contextDashboardsCache.query === query &&
@@ -712,6 +722,18 @@ class ContextDashboardService {
712
722
  };
713
723
  return this.contextDashboardsCache.result;
714
724
  }
725
+ appliedToFilter() {
726
+ const key = this.appStateService?.currentApplication?.value?.key || '';
727
+ if (!key) {
728
+ return {};
729
+ }
730
+ return {
731
+ __or: [
732
+ { __not: { __has: this.APPLIED_TO_FRAGMENT } }, // legacy / unlabeled ⇒ show in all
733
+ { [this.APPLIED_TO_FRAGMENT]: { __in: [key] } }
734
+ ]
735
+ };
736
+ }
715
737
  /**
716
738
  * Creates a tuple describing the dashboard type and its fragments. For assets like devices and groups, it's possible
717
739
  * to have two fragments: one indicating this particular device/asset with its ID, and the second indicating
@@ -991,13 +1013,13 @@ class ContextDashboardService {
991
1013
  [`c8y_Dashboard!name!${dashboardCfg.name}`]: {}
992
1014
  };
993
1015
  }
994
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ContextDashboardService, deps: [{ token: i1$1.InventoryService }, { token: i2.TabsService }, { token: i2.ModalService }, { token: i2$1.TranslateService }, { token: i1.Router }, { token: i2.NavigatorService }, { token: i2.Permissions }, { token: i2.AlertService }, { token: i2.DynamicComponentService }, { token: i2.GroupService }, { token: i2.OptionsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1016
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ContextDashboardService, deps: [{ token: i1$1.InventoryService }, { token: i2.TabsService }, { token: i2.ModalService }, { token: i2$1.TranslateService }, { token: i1.Router }, { token: i2.NavigatorService }, { token: i2.Permissions }, { token: i2.AlertService }, { token: i2.DynamicComponentService }, { token: i2.GroupService }, { token: i2.OptionsService }, { token: i2.AppStateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
995
1017
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ContextDashboardService, providedIn: 'root' }); }
996
1018
  }
997
1019
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ContextDashboardService, decorators: [{
998
1020
  type: Injectable,
999
1021
  args: [{ providedIn: 'root' }]
1000
- }], ctorParameters: () => [{ type: i1$1.InventoryService }, { type: i2.TabsService }, { type: i2.ModalService }, { type: i2$1.TranslateService }, { type: i1.Router }, { type: i2.NavigatorService }, { type: i2.Permissions }, { type: i2.AlertService }, { type: i2.DynamicComponentService }, { type: i2.GroupService }, { type: i2.OptionsService }] });
1022
+ }], ctorParameters: () => [{ type: i1$1.InventoryService }, { type: i2.TabsService }, { type: i2.ModalService }, { type: i2$1.TranslateService }, { type: i1.Router }, { type: i2.NavigatorService }, { type: i2.Permissions }, { type: i2.AlertService }, { type: i2.DynamicComponentService }, { type: i2.GroupService }, { type: i2.OptionsService }, { type: i2.AppStateService }] });
1001
1023
 
1002
1024
  const DEFAULT_DUPLICATE_WITHOUT_TYPE = () => {
1003
1025
  throw new Error('duplicateWithoutTypeFn Not implemented');
@@ -1856,6 +1878,11 @@ class WidgetAssetSelectorComponent {
1856
1878
  * If set to true, a device must be selected. Default is true.
1857
1879
  */
1858
1880
  this.isRequired = true;
1881
+ /**
1882
+ * Template for displaying device names with their IDs.
1883
+ * @ignore
1884
+ */
1885
+ this.deviceWithIdTpl = gettext('Device {{ id }}');
1859
1886
  }
1860
1887
  /**
1861
1888
  * @ignore
@@ -1878,7 +1905,7 @@ class WidgetAssetSelectorComponent {
1878
1905
  else if (this.isRequired && !this.hasContext(this.widgetConfigService.currentConfig)) {
1879
1906
  this.sectionComponent.section.expanded = true;
1880
1907
  }
1881
- else if (this.hasContext(this.widgetConfigService.currentConfig)) {
1908
+ else if (this.hasContext(this.widgetConfigService.currentConfig) && this.isRequired) {
1882
1909
  this.selectedDevice = this.widgetConfigService.currentConfig.settings?.context;
1883
1910
  }
1884
1911
  this.assetSelectorConfig = {
@@ -1914,11 +1941,15 @@ class WidgetAssetSelectorComponent {
1914
1941
  this.updateConfig($event.change.item);
1915
1942
  }
1916
1943
  }
1944
+ selectCurrentContext() {
1945
+ this.selectedDevice = this.widgetConfigService.currentConfig.settings?.context;
1946
+ this.updateConfig(this.selectedDevice);
1947
+ }
1917
1948
  updateConfig(device) {
1918
1949
  this.widgetConfigService.updateConfig({ device });
1919
1950
  }
1920
1951
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WidgetAssetSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1921
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: WidgetAssetSelectorComponent, isStandalone: true, selector: "c8y-widget-asset-selector", inputs: { isRequired: "isRequired", showUnassigned: "showUnassigned", groupsSelectable: "groupsSelectable", assetSelectorConfig: "assetSelectorConfig", selectedDevice: "selectedDevice" }, host: { classAttribute: "bg-level-1" }, ngImport: i0, template: "<div class=\"card borderless\">\n <div\n class=\"card-block p-0 bg-inherit\"\n style=\"height: 315px\"\n >\n <!-- \n ngIf is needed to avoid a race condition as \n asset-selector seems not to support dynamic config changes\n -->\n <c8y-asset-selector-miller\n class=\"d-block bg-inherit p-relative\"\n *ngIf=\"assetSelectorConfig\"\n (onSelected)=\"selectionChanged($event)\"\n [config]=\"assetSelectorConfig\"\n [asset]=\"(widgetConfigService.currentConfig$ | async).settings?.context\"\n [(ngModel)]=\"selectedDevice\"\n [required]=\"isRequired\"\n name=\"configAsset\"\n ></c8y-asset-selector-miller>\n </div>\n\n <c8y-widget-config-feedback>\n <span\n class=\"tag chip text-12 m-4\"\n [ngClass]=\"{\n 'tag--info': selectedDevice || !isRequired,\n 'tag--danger': !selectedDevice && isRequired\n }\"\n >\n <button\n class=\"btn-clean text-12 m-r-4\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n *ngIf=\"selectedDevice\"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n <span\n class=\"text-truncate\"\n title=\"{{ selectedDevice.name || 'Device ' + selectedDevice.id }}\"\n *ngIf=\"selectedDevice\"\n >\n {{ selectedDevice.name || 'Device ' + selectedDevice.id }}\n </span>\n <span\n *ngIf=\"!selectedDevice\"\n translate\n >\n No asset selected\n </span>\n </span>\n </c8y-widget-config-feedback>\n</div>\n", dependencies: [{ kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i1$2.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); }
1952
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: WidgetAssetSelectorComponent, isStandalone: true, selector: "c8y-widget-asset-selector", inputs: { isRequired: "isRequired", showUnassigned: "showUnassigned", groupsSelectable: "groupsSelectable", assetSelectorConfig: "assetSelectorConfig", selectedDevice: "selectedDevice" }, host: { classAttribute: "bg-level-1" }, ngImport: i0, template: "<div class=\"card borderless\">\n <div\n class=\"card-block p-0 bg-inherit\"\n style=\"height: 315px\"\n >\n <div\n class=\"alert alert-info m-4\"\n *ngIf=\"widgetConfigService.isDeviceTypeDashboard$ | async\"\n >\n <i class=\"fa fa-info-circle m-r-4\"></i>\n <span translate>\n This widget is used within a dashboard template, so the asset selector is unavailable. The\n widget automatically inherits the asset from the context in which the dashboard is\n displayed.\n </span>\n\n <div\n class=\"p-t-8\"\n *ngIf=\"!isRequired\"\n >\n <p translate>Asset selection is optional for this widget.</p>\n <button\n class=\"btn btn-primary btn-sm m-t-8\"\n *ngIf=\"!selectedDevice\"\n (click)=\"selectCurrentContext()\"\n ngNonBindable\n translate\n [translateParams]=\"{\n deviceName:\n (widgetConfigService.currentConfig$ | async)?.settings?.context?.name ||\n (deviceWithIdTpl\n | translate\n : { id: (widgetConfigService.currentConfig$ | async)?.settings?.context?.id })\n }\"\n >\n Use context asset \"{{ deviceName }}\"\n </button>\n <button\n class=\"btn btn-default btn-sm m-t-8\"\n *ngIf=\"selectedDevice\"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n ngNonBindable\n translate\n [translateParams]=\"{\n deviceName:\n selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id })\n }\"\n >\n Use without asset \"{{ deviceName }}\"\n </button>\n </div>\n </div>\n <c8y-asset-selector-miller\n class=\"d-block bg-inherit p-relative\"\n name=\"configAsset\"\n *ngIf=\"!(widgetConfigService.isDeviceTypeDashboard$ | async) && assetSelectorConfig\"\n (onSelected)=\"selectionChanged($event)\"\n [config]=\"assetSelectorConfig\"\n [asset]=\"(widgetConfigService.currentConfig$ | async).settings?.context\"\n [(ngModel)]=\"selectedDevice\"\n [required]=\"isRequired\"\n ></c8y-asset-selector-miller>\n\n <c8y-widget-config-feedback>\n <span\n class=\"tag chip text-12 m-4\"\n [ngClass]=\"{\n 'tag--info': selectedDevice || !isRequired,\n 'tag--danger': !selectedDevice && isRequired\n }\"\n >\n <button\n class=\"btn-clean text-12 m-r-4\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n *ngIf=\"\n selectedDevice &&\n (!(widgetConfigService.isDeviceTypeDashboard$ | async) ||\n (!isRequired && (widgetConfigService.isDeviceTypeDashboard$ | async)))\n \"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n <span\n class=\"text-truncate\"\n title=\"{{\n selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id })\n }}\"\n *ngIf=\"selectedDevice\"\n >\n {{ selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id }) }}\n </span>\n <span\n *ngIf=\"!selectedDevice\"\n translate\n >\n No asset selected\n </span>\n </span>\n </c8y-widget-config-feedback>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i1$2.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); }
1922
1953
  }
1923
1954
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WidgetAssetSelectorComponent, decorators: [{
1924
1955
  type: Component,
@@ -1930,8 +1961,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1930
1961
  NgClass,
1931
1962
  C8yTranslatePipe,
1932
1963
  IconDirective,
1933
- FormsModule
1934
- ], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], template: "<div class=\"card borderless\">\n <div\n class=\"card-block p-0 bg-inherit\"\n style=\"height: 315px\"\n >\n <!-- \n ngIf is needed to avoid a race condition as \n asset-selector seems not to support dynamic config changes\n -->\n <c8y-asset-selector-miller\n class=\"d-block bg-inherit p-relative\"\n *ngIf=\"assetSelectorConfig\"\n (onSelected)=\"selectionChanged($event)\"\n [config]=\"assetSelectorConfig\"\n [asset]=\"(widgetConfigService.currentConfig$ | async).settings?.context\"\n [(ngModel)]=\"selectedDevice\"\n [required]=\"isRequired\"\n name=\"configAsset\"\n ></c8y-asset-selector-miller>\n </div>\n\n <c8y-widget-config-feedback>\n <span\n class=\"tag chip text-12 m-4\"\n [ngClass]=\"{\n 'tag--info': selectedDevice || !isRequired,\n 'tag--danger': !selectedDevice && isRequired\n }\"\n >\n <button\n class=\"btn-clean text-12 m-r-4\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n *ngIf=\"selectedDevice\"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n <span\n class=\"text-truncate\"\n title=\"{{ selectedDevice.name || 'Device ' + selectedDevice.id }}\"\n *ngIf=\"selectedDevice\"\n >\n {{ selectedDevice.name || 'Device ' + selectedDevice.id }}\n </span>\n <span\n *ngIf=\"!selectedDevice\"\n translate\n >\n No asset selected\n </span>\n </span>\n </c8y-widget-config-feedback>\n</div>\n" }]
1964
+ FormsModule,
1965
+ C8yTranslateDirective
1966
+ ], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], template: "<div class=\"card borderless\">\n <div\n class=\"card-block p-0 bg-inherit\"\n style=\"height: 315px\"\n >\n <div\n class=\"alert alert-info m-4\"\n *ngIf=\"widgetConfigService.isDeviceTypeDashboard$ | async\"\n >\n <i class=\"fa fa-info-circle m-r-4\"></i>\n <span translate>\n This widget is used within a dashboard template, so the asset selector is unavailable. The\n widget automatically inherits the asset from the context in which the dashboard is\n displayed.\n </span>\n\n <div\n class=\"p-t-8\"\n *ngIf=\"!isRequired\"\n >\n <p translate>Asset selection is optional for this widget.</p>\n <button\n class=\"btn btn-primary btn-sm m-t-8\"\n *ngIf=\"!selectedDevice\"\n (click)=\"selectCurrentContext()\"\n ngNonBindable\n translate\n [translateParams]=\"{\n deviceName:\n (widgetConfigService.currentConfig$ | async)?.settings?.context?.name ||\n (deviceWithIdTpl\n | translate\n : { id: (widgetConfigService.currentConfig$ | async)?.settings?.context?.id })\n }\"\n >\n Use context asset \"{{ deviceName }}\"\n </button>\n <button\n class=\"btn btn-default btn-sm m-t-8\"\n *ngIf=\"selectedDevice\"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n ngNonBindable\n translate\n [translateParams]=\"{\n deviceName:\n selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id })\n }\"\n >\n Use without asset \"{{ deviceName }}\"\n </button>\n </div>\n </div>\n <c8y-asset-selector-miller\n class=\"d-block bg-inherit p-relative\"\n name=\"configAsset\"\n *ngIf=\"!(widgetConfigService.isDeviceTypeDashboard$ | async) && assetSelectorConfig\"\n (onSelected)=\"selectionChanged($event)\"\n [config]=\"assetSelectorConfig\"\n [asset]=\"(widgetConfigService.currentConfig$ | async).settings?.context\"\n [(ngModel)]=\"selectedDevice\"\n [required]=\"isRequired\"\n ></c8y-asset-selector-miller>\n\n <c8y-widget-config-feedback>\n <span\n class=\"tag chip text-12 m-4\"\n [ngClass]=\"{\n 'tag--info': selectedDevice || !isRequired,\n 'tag--danger': !selectedDevice && isRequired\n }\"\n >\n <button\n class=\"btn-clean text-12 m-r-4\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n *ngIf=\"\n selectedDevice &&\n (!(widgetConfigService.isDeviceTypeDashboard$ | async) ||\n (!isRequired && (widgetConfigService.isDeviceTypeDashboard$ | async)))\n \"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n <span\n class=\"text-truncate\"\n title=\"{{\n selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id })\n }}\"\n *ngIf=\"selectedDevice\"\n >\n {{ selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id }) }}\n </span>\n <span\n *ngIf=\"!selectedDevice\"\n translate\n >\n No asset selected\n </span>\n </span>\n </c8y-widget-config-feedback>\n </div>\n</div>\n" }]
1935
1967
  }], propDecorators: { isRequired: [{
1936
1968
  type: Input
1937
1969
  }], showUnassigned: [{
@@ -1982,10 +2014,15 @@ class WidgetConfigService {
1982
2014
  this.widgetConfigSectionService = widgetConfigSectionService;
1983
2015
  this._currentConfig$ = new BehaviorSubject(null);
1984
2016
  this._instanceId$ = new BehaviorSubject(null);
2017
+ this._isDeviceTypeDashboard$ = new BehaviorSubject(false);
1985
2018
  /**
1986
2019
  * The unique identifier of the current widget instance.
1987
2020
  */
1988
2021
  this.instanceId$ = this._instanceId$.asObservable();
2022
+ /**
2023
+ * Indicates if the selected widget is placed on a device type dashboard.
2024
+ */
2025
+ this.isDeviceTypeDashboard$ = this._isDeviceTypeDashboard$.asObservable();
1989
2026
  /**
1990
2027
  * The preview of the currently selected widget. If `null` no preview is shown
1991
2028
  * (except if the selected widget has no configuration).
@@ -2151,10 +2188,12 @@ class WidgetConfigService {
2151
2188
  * Select a widget
2152
2189
  * @param selected The widget to select.
2153
2190
  * @param identifier An optional unique identifier for the widget instance. Only used if the widget is not new.
2191
+ * @param isDeviceTypeDashboard Indicates if the selected widget is placed on a device-type dashboard. This is used to determine if the default asset selector should be shown.
2154
2192
  */
2155
- selectWidget(selected, identifier = null) {
2193
+ selectWidget(selected, identifier = null, isDeviceTypeDashboard = false) {
2156
2194
  this.selected$.next(selected);
2157
2195
  this._instanceId$.next(identifier);
2196
+ this._isDeviceTypeDashboard$.next(isDeviceTypeDashboard);
2158
2197
  }
2159
2198
  /**
2160
2199
  * Deselect the currently selected.
@@ -2521,7 +2560,7 @@ class WidgetConfigComponent {
2521
2560
  this.selected.data.title = this.selected.data.title || cmp.label;
2522
2561
  this.componentLabel = cmp.label;
2523
2562
  this.widgetConfigService.initConfig(this.widgetConfig);
2524
- this.widgetConfigService.selectWidget(this.selected, this.identifier);
2563
+ this.widgetConfigService.selectWidget(this.selected, this.identifier, this.isDeviceTypeDashboard);
2525
2564
  }
2526
2565
  search() {
2527
2566
  if (this.searchTerm.length > 0) {
@@ -2614,18 +2653,9 @@ class WidgetConfigComponent {
2614
2653
  const noDeviceTarget = widgetConfig.settings.ng1
2615
2654
  ? widgetConfig.settings.ng1.options.noDeviceTarget
2616
2655
  : widgetConfig.settings.noDeviceTarget;
2617
- if (isDeviceType) {
2618
- widgetConfig.settings.hideTarget = isDeviceType;
2619
- if (!noDeviceTarget) {
2620
- widgetConfig.device = {
2621
- id: this.context.id,
2622
- name: this.context.name
2623
- };
2624
- }
2625
- }
2626
- else if (this.context?.id && !noDeviceTarget) {
2627
- // if the widget is a new widget, we assign the current context
2628
- // as well to have the device available on init of the component
2656
+ const needsTargetAndIsDeviceType = isDeviceType && !noDeviceTarget && widgetConfig.device;
2657
+ const isNewWidgetWithContext = !this.isEdit && this.context?.id && !noDeviceTarget;
2658
+ if (needsTargetAndIsDeviceType || isNewWidgetWithContext) {
2629
2659
  widgetConfig.device = {
2630
2660
  id: this.context.id,
2631
2661
  name: this.context.name
@@ -2634,7 +2664,7 @@ class WidgetConfigComponent {
2634
2664
  return widgetConfig;
2635
2665
  }
2636
2666
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WidgetConfigComponent, deps: [{ token: WidgetService }, { token: i2.BottomDrawerRef }, { token: ContextDashboardService }, { token: WidgetConfigService }], target: i0.ɵɵFactoryTarget.Component }); }
2637
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: WidgetConfigComponent, isStandalone: true, selector: "c8y-widget-config", host: { classAttribute: "d-contents" }, viewQueries: [{ propertyName: "configForm", first: true, predicate: ["configForm"], descendants: true }], ngImport: i0, template: "<!-- select widget -->\n<ng-container *ngIf=\"!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header j-c-center separator\">\n <div class=\"h4 text-center\">\n {{ 'Select widget' | translate }}\n </div>\n </div>\n <div class=\"card-inner-scroll fit-h bg-level-2\">\n <div\n class=\"bg-level-0 p-l-24 p-r-24 p-t-8 p-b-8 sticky-header-top-0 elevation-md\"\n style=\"z-index: 2\"\n >\n <div class=\"row\">\n <div class=\"col-sm-6 col-sm-offset-3\">\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n [attr.aria-label]=\"'Search' | translate\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"text\"\n data-cy=\"widget-config--Search\"\n [(ngModel)]=\"searchTerm\"\n [ngModelOptions]=\"{ standalone: true }\"\n (keydown)=\"searchChange$.next($event)\"\n />\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n <i [c8yIcon]=\"searchTerm.length === 0 ? 'search' : 'close'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-block\">\n <div class=\"card-group p-l-24 p-r-24 d-grid grid__col--auto-300 gap-24 card-select m-b-0\">\n <button\n class=\"btn-clean d-col card m-b-0\"\n [title]=\"cmp.description || cmp.label | translate\"\n type=\"button\"\n data-cy=\"widget-config--widget-list\"\n *ngFor=\"let cmp of searchResult || components\"\n (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n <ng-container *ngIf=\"!cmp.previewImage; else previewImage\">\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n </ng-container>\n <ng-template #previewImage>\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n </ng-template>\n </div>\n <div class=\"card-block\">\n <p class=\"card-title text-truncate text-medium\">\n <c8y-highlight\n text=\"{{ cmp.label | translate }}\"\n [pattern]=\"searchTerm\"\n ></c8y-highlight>\n </p>\n <p\n class=\"small text-default\"\n style=\"white-space: wrap\"\n >\n {{ cmp.description | translate }}\n </p>\n </div>\n </button>\n <c8y-ui-empty-state\n class=\"p-24 grid__col--fullspan\"\n [icon]=\"'search'\"\n [title]=\"'No widgets found.' | translate\"\n [subtitle]=\"' Rephrase your search term.' | translate\"\n *ngIf=\"searchResult && searchResult.length === 0\"\n >\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Reset search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n {{ 'Reset search' | translate }}\n </button>\n </c8y-ui-empty-state>\n </div>\n </div>\n </div>\n <div class=\"card-footer text-center separator flex-no-shrink\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n </div>\n</ng-container>\n\n<!-- widget configuration -->\n<ng-container *ngIf=\"!!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header d-block separator-bottom flex-no-shrink\">\n <div\n class=\"h3 p-t-16\"\n title=\"{{ selected?.label | translate }}\"\n >\n <span>{{ selected?.label | translate }}</span>\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n [title]=\"'Change widget' | translate\"\n (click)=\"backToWidgetSelection(); (false)\"\n >\n <i c8yIcon=\"replace\"></i>\n {{ 'Change widget' | translate }}\n </button>\n </div>\n <div\n class=\"p-t-8\"\n *ngIf=\"selected\"\n >\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.HALF\n \"\n >\n <div\n class=\"bg-level-1 inner-scroll\"\n left-pane\n >\n <div class=\"p-16 flex-no-shrink separator-bottom bg-level-1\">\n <c8y-form-group>\n <label\n for=\"widgetTitle\"\n translate\n >\n Widget title\n </label>\n <input\n class=\"form-control\"\n id=\"widgetTitle\"\n placeholder=\"{{ 'e.g.' | translate }} {{ componentLabel | translate }}\"\n name=\"title\"\n type=\"text\"\n required\n [(ngModel)]=\"selected?.data.title\"\n />\n </c8y-form-group>\n </div>\n\n <c8y-ui-empty-state\n class=\"p-24\"\n [icon]=\"'settings'\"\n [title]=\"'No configuration needed.' | translate\"\n [subtitle]=\"'This widget does not need any specific configuration.' | translate\"\n [horizontal]=\"true\"\n *ngIf=\"!(widgetConfigService.hasConfig$ | async)\"\n ></c8y-ui-empty-state>\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n <ng-container *ngIf=\"widgetConfigService.hasConfig$ | async\">\n <ng-container *ngIf=\"widgetConfigService.providers$ | async as providers\">\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </form>\n </div>\n </div>\n <div\n class=\"inner-scroll p-32 p-t-0\"\n right-pane\n >\n <c8y-widget-preview [previewClasses]=\"getStyle(true)\"></c8y-widget-preview>\n\n <c8y-appearance-settings\n [(themeClass)]=\"styling.contentClass\"\n [(headerClass)]=\"styling.headerClass\"\n [possibleStylingTheme]=\"possibleStyling.WIDGET_CONTENT_CLASSES\"\n [possibleStylingHeader]=\"possibleStyling.WIDGET_HEADER_CLASSES\"\n [defaultThemeClass]=\"defaultStyling.contentClass\"\n [defaultHeaderClass]=\"defaultStyling.headerClass\"\n [columns]=\"2\"\n ></c8y-appearance-settings>\n </div>\n </c8y-resizable-grid>\n <div class=\"card-footer separator text-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n data-cy=\"widget-config--save-widget\"\n (click)=\"save()\"\n [disabled]=\"(contextDashboardService.formDisabled$ | async) || isSaveDisabled()\"\n c8yProductExperience\n [actionName]=\"current ? 'editWidget' : 'createWidget'\"\n [actionData]=\"{ widgetName: selected && selected.id }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: C8yComponentOutlet, selector: "[c8yComponentOutlet]", inputs: ["c8yComponentOutlet", "c8yComponentOutletInjector", "c8yComponentOutletEnvironmentInjector", "c8yComponentOutletProviders", "c8yComponentOutletInitialState"] }, { kind: "component", type: WidgetPreviewComponent, selector: "c8y-widget-preview", inputs: ["previewClasses"] }, { kind: "component", type: AppearanceSettingsComponent, selector: "c8y-appearance-settings", inputs: ["themeClass", "headerClass", "defaultThemeClass", "defaultHeaderClass", "dashboardSettings", "possibleStylingTheme", "possibleStylingHeader", "columns"], outputs: ["themeClassChange", "headerClassChange", "onChange"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: ResizableGridComponent, selector: "c8y-resizable-grid", inputs: ["leftColumnWidth", "trackId", "collapseThreshold"] }] }); }
2667
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: WidgetConfigComponent, isStandalone: true, selector: "c8y-widget-config", host: { classAttribute: "d-contents" }, viewQueries: [{ propertyName: "configForm", first: true, predicate: ["configForm"], descendants: true }], ngImport: i0, template: "<!-- select widget -->\n<ng-container *ngIf=\"!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header j-c-center separator\">\n <div class=\"h4 text-center\" id=\"drawerTitle\">\n {{ 'Select widget' | translate }}\n </div>\n </div>\n <div class=\"card-inner-scroll fit-h bg-level-2\">\n <div\n class=\"bg-level-0 p-l-24 p-r-24 p-t-8 p-b-8 sticky-header-top-0 elevation-md\"\n style=\"z-index: 2\"\n >\n <div class=\"row\">\n <div class=\"col-sm-6 col-sm-offset-3\">\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n [attr.aria-label]=\"'Search' | translate\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"text\"\n data-cy=\"widget-config--Search\"\n [(ngModel)]=\"searchTerm\"\n [ngModelOptions]=\"{ standalone: true }\"\n (keydown)=\"searchChange$.next($event)\"\n />\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n <i [c8yIcon]=\"searchTerm.length === 0 ? 'search' : 'close'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-block\">\n <div class=\"card-group p-l-24 p-r-24 d-grid grid__col--auto-300 gap-24 card-select m-b-0\">\n <button\n class=\"btn-clean d-col card m-b-0\"\n [title]=\"cmp.description || cmp.label | translate\"\n type=\"button\"\n data-cy=\"widget-config--widget-list\"\n *ngFor=\"let cmp of searchResult || components\"\n (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n <ng-container *ngIf=\"!cmp.previewImage; else previewImage\">\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n </ng-container>\n <ng-template #previewImage>\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n </ng-template>\n </div>\n <div class=\"card-block\">\n <p class=\"card-title text-truncate text-medium\">\n <c8y-highlight\n text=\"{{ cmp.label | translate }}\"\n [pattern]=\"searchTerm\"\n ></c8y-highlight>\n </p>\n <p\n class=\"small text-default\"\n style=\"white-space: wrap\"\n >\n {{ cmp.description | translate }}\n </p>\n </div>\n </button>\n <c8y-ui-empty-state\n class=\"p-24 grid__col--fullspan\"\n [icon]=\"'search'\"\n [title]=\"'No widgets found.' | translate\"\n [subtitle]=\"' Rephrase your search term.' | translate\"\n *ngIf=\"searchResult && searchResult.length === 0\"\n >\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Reset search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n {{ 'Reset search' | translate }}\n </button>\n </c8y-ui-empty-state>\n </div>\n </div>\n </div>\n <div class=\"card-footer text-center separator flex-no-shrink\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n </div>\n</ng-container>\n\n<!-- widget configuration -->\n<ng-container *ngIf=\"!!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header d-block separator-bottom flex-no-shrink\">\n <div\n class=\"h3 p-t-16\"\n title=\"{{ selected?.label | translate }}\"\n >\n <span>{{ selected?.label | translate }}</span>\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n [title]=\"'Change widget' | translate\"\n (click)=\"backToWidgetSelection(); (false)\"\n >\n <i c8yIcon=\"replace\"></i>\n {{ 'Change widget' | translate }}\n </button>\n </div>\n <div\n class=\"p-t-8\"\n *ngIf=\"selected\"\n >\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.HALF\n \"\n >\n <div\n class=\"bg-level-1 inner-scroll\"\n left-pane\n >\n <div class=\"p-16 flex-no-shrink separator-bottom bg-level-1\">\n <c8y-form-group>\n <label\n for=\"widgetTitle\"\n translate\n >\n Widget title\n </label>\n <input\n class=\"form-control\"\n id=\"widgetTitle\"\n placeholder=\"{{ 'e.g.' | translate }} {{ componentLabel | translate }}\"\n name=\"title\"\n type=\"text\"\n required\n [(ngModel)]=\"selected?.data.title\"\n />\n </c8y-form-group>\n </div>\n\n <c8y-ui-empty-state\n class=\"p-24\"\n [icon]=\"'settings'\"\n [title]=\"'No configuration needed.' | translate\"\n [subtitle]=\"'This widget does not need any specific configuration.' | translate\"\n [horizontal]=\"true\"\n *ngIf=\"!(widgetConfigService.hasConfig$ | async)\"\n ></c8y-ui-empty-state>\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n <ng-container *ngIf=\"widgetConfigService.hasConfig$ | async\">\n <ng-container *ngIf=\"widgetConfigService.providers$ | async as providers\">\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </form>\n </div>\n </div>\n <div\n class=\"inner-scroll p-32 p-t-0\"\n right-pane\n >\n <c8y-widget-preview [previewClasses]=\"getStyle(true)\"></c8y-widget-preview>\n\n <c8y-appearance-settings\n [(themeClass)]=\"styling.contentClass\"\n [(headerClass)]=\"styling.headerClass\"\n [possibleStylingTheme]=\"possibleStyling.WIDGET_CONTENT_CLASSES\"\n [possibleStylingHeader]=\"possibleStyling.WIDGET_HEADER_CLASSES\"\n [defaultThemeClass]=\"defaultStyling.contentClass\"\n [defaultHeaderClass]=\"defaultStyling.headerClass\"\n [columns]=\"2\"\n ></c8y-appearance-settings>\n </div>\n </c8y-resizable-grid>\n <div class=\"card-footer separator text-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n data-cy=\"widget-config--save-widget\"\n (click)=\"save()\"\n [disabled]=\"(contextDashboardService.formDisabled$ | async) || isSaveDisabled()\"\n c8yProductExperience\n [actionName]=\"current ? 'editWidget' : 'createWidget'\"\n [actionData]=\"{ widgetName: selected && selected.id }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: C8yComponentOutlet, selector: "[c8yComponentOutlet]", inputs: ["c8yComponentOutlet", "c8yComponentOutletInjector", "c8yComponentOutletEnvironmentInjector", "c8yComponentOutletProviders", "c8yComponentOutletInitialState"] }, { kind: "component", type: WidgetPreviewComponent, selector: "c8y-widget-preview", inputs: ["previewClasses"] }, { kind: "component", type: AppearanceSettingsComponent, selector: "c8y-appearance-settings", inputs: ["themeClass", "headerClass", "defaultThemeClass", "defaultHeaderClass", "dashboardSettings", "possibleStylingTheme", "possibleStylingHeader", "columns"], outputs: ["themeClassChange", "headerClassChange", "onChange"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: ResizableGridComponent, selector: "c8y-resizable-grid", inputs: ["leftColumnWidth", "trackId", "collapseThreshold"] }] }); }
2638
2668
  }
2639
2669
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: WidgetConfigComponent, decorators: [{
2640
2670
  type: Component,
@@ -2655,7 +2685,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
2655
2685
  C8yTranslatePipe,
2656
2686
  AsyncPipe,
2657
2687
  ResizableGridComponent
2658
- ], standalone: true, template: "<!-- select widget -->\n<ng-container *ngIf=\"!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header j-c-center separator\">\n <div class=\"h4 text-center\">\n {{ 'Select widget' | translate }}\n </div>\n </div>\n <div class=\"card-inner-scroll fit-h bg-level-2\">\n <div\n class=\"bg-level-0 p-l-24 p-r-24 p-t-8 p-b-8 sticky-header-top-0 elevation-md\"\n style=\"z-index: 2\"\n >\n <div class=\"row\">\n <div class=\"col-sm-6 col-sm-offset-3\">\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n [attr.aria-label]=\"'Search' | translate\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"text\"\n data-cy=\"widget-config--Search\"\n [(ngModel)]=\"searchTerm\"\n [ngModelOptions]=\"{ standalone: true }\"\n (keydown)=\"searchChange$.next($event)\"\n />\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n <i [c8yIcon]=\"searchTerm.length === 0 ? 'search' : 'close'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-block\">\n <div class=\"card-group p-l-24 p-r-24 d-grid grid__col--auto-300 gap-24 card-select m-b-0\">\n <button\n class=\"btn-clean d-col card m-b-0\"\n [title]=\"cmp.description || cmp.label | translate\"\n type=\"button\"\n data-cy=\"widget-config--widget-list\"\n *ngFor=\"let cmp of searchResult || components\"\n (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n <ng-container *ngIf=\"!cmp.previewImage; else previewImage\">\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n </ng-container>\n <ng-template #previewImage>\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n </ng-template>\n </div>\n <div class=\"card-block\">\n <p class=\"card-title text-truncate text-medium\">\n <c8y-highlight\n text=\"{{ cmp.label | translate }}\"\n [pattern]=\"searchTerm\"\n ></c8y-highlight>\n </p>\n <p\n class=\"small text-default\"\n style=\"white-space: wrap\"\n >\n {{ cmp.description | translate }}\n </p>\n </div>\n </button>\n <c8y-ui-empty-state\n class=\"p-24 grid__col--fullspan\"\n [icon]=\"'search'\"\n [title]=\"'No widgets found.' | translate\"\n [subtitle]=\"' Rephrase your search term.' | translate\"\n *ngIf=\"searchResult && searchResult.length === 0\"\n >\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Reset search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n {{ 'Reset search' | translate }}\n </button>\n </c8y-ui-empty-state>\n </div>\n </div>\n </div>\n <div class=\"card-footer text-center separator flex-no-shrink\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n </div>\n</ng-container>\n\n<!-- widget configuration -->\n<ng-container *ngIf=\"!!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header d-block separator-bottom flex-no-shrink\">\n <div\n class=\"h3 p-t-16\"\n title=\"{{ selected?.label | translate }}\"\n >\n <span>{{ selected?.label | translate }}</span>\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n [title]=\"'Change widget' | translate\"\n (click)=\"backToWidgetSelection(); (false)\"\n >\n <i c8yIcon=\"replace\"></i>\n {{ 'Change widget' | translate }}\n </button>\n </div>\n <div\n class=\"p-t-8\"\n *ngIf=\"selected\"\n >\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.HALF\n \"\n >\n <div\n class=\"bg-level-1 inner-scroll\"\n left-pane\n >\n <div class=\"p-16 flex-no-shrink separator-bottom bg-level-1\">\n <c8y-form-group>\n <label\n for=\"widgetTitle\"\n translate\n >\n Widget title\n </label>\n <input\n class=\"form-control\"\n id=\"widgetTitle\"\n placeholder=\"{{ 'e.g.' | translate }} {{ componentLabel | translate }}\"\n name=\"title\"\n type=\"text\"\n required\n [(ngModel)]=\"selected?.data.title\"\n />\n </c8y-form-group>\n </div>\n\n <c8y-ui-empty-state\n class=\"p-24\"\n [icon]=\"'settings'\"\n [title]=\"'No configuration needed.' | translate\"\n [subtitle]=\"'This widget does not need any specific configuration.' | translate\"\n [horizontal]=\"true\"\n *ngIf=\"!(widgetConfigService.hasConfig$ | async)\"\n ></c8y-ui-empty-state>\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n <ng-container *ngIf=\"widgetConfigService.hasConfig$ | async\">\n <ng-container *ngIf=\"widgetConfigService.providers$ | async as providers\">\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </form>\n </div>\n </div>\n <div\n class=\"inner-scroll p-32 p-t-0\"\n right-pane\n >\n <c8y-widget-preview [previewClasses]=\"getStyle(true)\"></c8y-widget-preview>\n\n <c8y-appearance-settings\n [(themeClass)]=\"styling.contentClass\"\n [(headerClass)]=\"styling.headerClass\"\n [possibleStylingTheme]=\"possibleStyling.WIDGET_CONTENT_CLASSES\"\n [possibleStylingHeader]=\"possibleStyling.WIDGET_HEADER_CLASSES\"\n [defaultThemeClass]=\"defaultStyling.contentClass\"\n [defaultHeaderClass]=\"defaultStyling.headerClass\"\n [columns]=\"2\"\n ></c8y-appearance-settings>\n </div>\n </c8y-resizable-grid>\n <div class=\"card-footer separator text-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n data-cy=\"widget-config--save-widget\"\n (click)=\"save()\"\n [disabled]=\"(contextDashboardService.formDisabled$ | async) || isSaveDisabled()\"\n c8yProductExperience\n [actionName]=\"current ? 'editWidget' : 'createWidget'\"\n [actionData]=\"{ widgetName: selected && selected.id }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</ng-container>\n" }]
2688
+ ], standalone: true, template: "<!-- select widget -->\n<ng-container *ngIf=\"!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header j-c-center separator\">\n <div class=\"h4 text-center\" id=\"drawerTitle\">\n {{ 'Select widget' | translate }}\n </div>\n </div>\n <div class=\"card-inner-scroll fit-h bg-level-2\">\n <div\n class=\"bg-level-0 p-l-24 p-r-24 p-t-8 p-b-8 sticky-header-top-0 elevation-md\"\n style=\"z-index: 2\"\n >\n <div class=\"row\">\n <div class=\"col-sm-6 col-sm-offset-3\">\n <div class=\"input-group input-group-search\">\n <input\n class=\"form-control\"\n [attr.aria-label]=\"'Search' | translate\"\n placeholder=\"{{ 'Search\u2026' | translate }}\"\n type=\"text\"\n data-cy=\"widget-config--Search\"\n [(ngModel)]=\"searchTerm\"\n [ngModelOptions]=\"{ standalone: true }\"\n (keydown)=\"searchChange$.next($event)\"\n />\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n <i [c8yIcon]=\"searchTerm.length === 0 ? 'search' : 'close'\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-block\">\n <div class=\"card-group p-l-24 p-r-24 d-grid grid__col--auto-300 gap-24 card-select m-b-0\">\n <button\n class=\"btn-clean d-col card m-b-0\"\n [title]=\"cmp.description || cmp.label | translate\"\n type=\"button\"\n data-cy=\"widget-config--widget-list\"\n *ngFor=\"let cmp of searchResult || components\"\n (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n <ng-container *ngIf=\"!cmp.previewImage; else previewImage\">\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n </ng-container>\n <ng-template #previewImage>\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n </ng-template>\n </div>\n <div class=\"card-block\">\n <p class=\"card-title text-truncate text-medium\">\n <c8y-highlight\n text=\"{{ cmp.label | translate }}\"\n [pattern]=\"searchTerm\"\n ></c8y-highlight>\n </p>\n <p\n class=\"small text-default\"\n style=\"white-space: wrap\"\n >\n {{ cmp.description | translate }}\n </p>\n </div>\n </button>\n <c8y-ui-empty-state\n class=\"p-24 grid__col--fullspan\"\n [icon]=\"'search'\"\n [title]=\"'No widgets found.' | translate\"\n [subtitle]=\"' Rephrase your search term.' | translate\"\n *ngIf=\"searchResult && searchResult.length === 0\"\n >\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Reset search' | translate }}\"\n type=\"button\"\n (click)=\"resetSearch()\"\n >\n {{ 'Reset search' | translate }}\n </button>\n </c8y-ui-empty-state>\n </div>\n </div>\n </div>\n <div class=\"card-footer text-center separator flex-no-shrink\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n </div>\n</ng-container>\n\n<!-- widget configuration -->\n<ng-container *ngIf=\"!!(widgetConfigService.selected$ | async)\">\n <div class=\"card-header d-block separator-bottom flex-no-shrink\">\n <div\n class=\"h3 p-t-16\"\n title=\"{{ selected?.label | translate }}\"\n >\n <span>{{ selected?.label | translate }}</span>\n <button\n class=\"btn btn-default btn-sm m-l-8\"\n [title]=\"'Change widget' | translate\"\n (click)=\"backToWidgetSelection(); (false)\"\n >\n <i c8yIcon=\"replace\"></i>\n {{ 'Change widget' | translate }}\n </button>\n </div>\n <div\n class=\"p-t-8\"\n *ngIf=\"selected\"\n >\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.HALF\n \"\n >\n <div\n class=\"bg-level-1 inner-scroll\"\n left-pane\n >\n <div class=\"p-16 flex-no-shrink separator-bottom bg-level-1\">\n <c8y-form-group>\n <label\n for=\"widgetTitle\"\n translate\n >\n Widget title\n </label>\n <input\n class=\"form-control\"\n id=\"widgetTitle\"\n placeholder=\"{{ 'e.g.' | translate }} {{ componentLabel | translate }}\"\n name=\"title\"\n type=\"text\"\n required\n [(ngModel)]=\"selected?.data.title\"\n />\n </c8y-form-group>\n </div>\n\n <c8y-ui-empty-state\n class=\"p-24\"\n [icon]=\"'settings'\"\n [title]=\"'No configuration needed.' | translate\"\n [subtitle]=\"'This widget does not need any specific configuration.' | translate\"\n [horizontal]=\"true\"\n *ngIf=\"!(widgetConfigService.hasConfig$ | async)\"\n ></c8y-ui-empty-state>\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n <ng-container *ngIf=\"widgetConfigService.hasConfig$ | async\">\n <ng-container *ngIf=\"widgetConfigService.providers$ | async as providers\">\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </form>\n </div>\n </div>\n <div\n class=\"inner-scroll p-32 p-t-0\"\n right-pane\n >\n <c8y-widget-preview [previewClasses]=\"getStyle(true)\"></c8y-widget-preview>\n\n <c8y-appearance-settings\n [(themeClass)]=\"styling.contentClass\"\n [(headerClass)]=\"styling.headerClass\"\n [possibleStylingTheme]=\"possibleStyling.WIDGET_CONTENT_CLASSES\"\n [possibleStylingHeader]=\"possibleStyling.WIDGET_HEADER_CLASSES\"\n [defaultThemeClass]=\"defaultStyling.contentClass\"\n [defaultHeaderClass]=\"defaultStyling.headerClass\"\n [columns]=\"2\"\n ></c8y-appearance-settings>\n </div>\n </c8y-resizable-grid>\n <div class=\"card-footer separator text-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n data-cy=\"widget-config--cancel-widget\"\n (click)=\"close()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n data-cy=\"widget-config--save-widget\"\n (click)=\"save()\"\n [disabled]=\"(contextDashboardService.formDisabled$ | async) || isSaveDisabled()\"\n c8yProductExperience\n [actionName]=\"current ? 'editWidget' : 'createWidget'\"\n [actionData]=\"{ widgetName: selected && selected.id }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n</ng-container>\n" }]
2659
2689
  }], ctorParameters: () => [{ type: WidgetService }, { type: i2.BottomDrawerRef }, { type: ContextDashboardService }, { type: WidgetConfigService }], propDecorators: { configForm: [{
2660
2690
  type: ViewChild,
2661
2691
  args: ['configForm', { static: false }]