@c8y/ngx-components 1018.0.115 → 1018.0.125

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 (46) hide show
  1. package/context-dashboard/context-dashboard.model.d.ts +5 -0
  2. package/core/dashboard/dashboard.model.d.ts +5 -0
  3. package/ecosystem/application-plugins/plugin-list.component.d.ts +1 -1
  4. package/esm2020/context-dashboard/context-dashboard.component.mjs +3 -3
  5. package/esm2020/context-dashboard/context-dashboard.model.mjs +1 -1
  6. package/esm2020/context-dashboard/dashboard-detail.component.mjs +1 -1
  7. package/esm2020/core/common/group.service.mjs +2 -11
  8. package/esm2020/core/common/permissions.service.mjs +2 -4
  9. package/esm2020/core/dashboard/dashboard.model.mjs +1 -1
  10. package/esm2020/core/dashboard/widgets-dashboard.component.mjs +5 -4
  11. package/esm2020/core/realtime/measurement-realtime.service.mjs +4 -2
  12. package/esm2020/device-profile/device-profile.component.mjs +4 -2
  13. package/esm2020/ecosystem/application-plugins/plugin-list.component.mjs +15 -7
  14. package/esm2020/sub-assets/add-group/add-group.component.mjs +3 -4
  15. package/esm2020/sub-assets/sub-assets.component.mjs +2 -5
  16. package/esm2020/widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.mjs +2 -2
  17. package/fesm2015/c8y-ngx-components-context-dashboard.mjs +2 -2
  18. package/fesm2015/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  19. package/fesm2015/c8y-ngx-components-device-profile.mjs +3 -1
  20. package/fesm2015/c8y-ngx-components-device-profile.mjs.map +1 -1
  21. package/fesm2015/c8y-ngx-components-ecosystem-application-plugins.mjs +14 -8
  22. package/fesm2015/c8y-ngx-components-ecosystem-application-plugins.mjs.map +1 -1
  23. package/fesm2015/c8y-ngx-components-ecosystem.mjs +14 -8
  24. package/fesm2015/c8y-ngx-components-ecosystem.mjs.map +1 -1
  25. package/fesm2015/c8y-ngx-components-sub-assets.mjs +3 -7
  26. package/fesm2015/c8y-ngx-components-sub-assets.mjs.map +1 -1
  27. package/fesm2015/c8y-ngx-components-widgets-implementations-kpi.mjs +1 -1
  28. package/fesm2015/c8y-ngx-components-widgets-implementations-kpi.mjs.map +1 -1
  29. package/fesm2015/c8y-ngx-components.mjs +30 -35
  30. package/fesm2015/c8y-ngx-components.mjs.map +1 -1
  31. package/fesm2020/c8y-ngx-components-context-dashboard.mjs +2 -2
  32. package/fesm2020/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  33. package/fesm2020/c8y-ngx-components-device-profile.mjs +3 -1
  34. package/fesm2020/c8y-ngx-components-device-profile.mjs.map +1 -1
  35. package/fesm2020/c8y-ngx-components-ecosystem-application-plugins.mjs +14 -6
  36. package/fesm2020/c8y-ngx-components-ecosystem-application-plugins.mjs.map +1 -1
  37. package/fesm2020/c8y-ngx-components-ecosystem.mjs +14 -6
  38. package/fesm2020/c8y-ngx-components-ecosystem.mjs.map +1 -1
  39. package/fesm2020/c8y-ngx-components-sub-assets.mjs +3 -7
  40. package/fesm2020/c8y-ngx-components-sub-assets.mjs.map +1 -1
  41. package/fesm2020/c8y-ngx-components-widgets-implementations-kpi.mjs +1 -1
  42. package/fesm2020/c8y-ngx-components-widgets-implementations-kpi.mjs.map +1 -1
  43. package/fesm2020/c8y-ngx-components.mjs +30 -35
  44. package/fesm2020/c8y-ngx-components.mjs.map +1 -1
  45. package/package.json +1 -1
  46. package/widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.d.ts +2 -2
@@ -153,7 +153,7 @@ class KpiWidgetViewComponent {
153
153
  this.assignContextFromContextDashboard(datapoint);
154
154
  const latestMeasurement$ = this.getLatestMeasurement$(datapoint);
155
155
  const lastTwoValues$ = this.getLastTwoValuesOfObservable$(latestMeasurement$);
156
- const previousValue$ = lastTwoValues$.pipe(map(res => res[0]), startWith(undefined));
156
+ const previousValue$ = lastTwoValues$.pipe(map(([previousVal]) => previousVal), startWith(undefined));
157
157
  const unit$ = latestMeasurement$.pipe(map(latestMeasurementValue => datapoint.unit || latestMeasurementValue.unit || ''), startWith(''), distinctUntilChanged());
158
158
  return combineLatest([
159
159
  latestMeasurement$,
@@ -1 +1 @@
1
- {"version":3,"file":"c8y-ngx-components-widgets-implementations-kpi.mjs","sources":["../../widgets/implementations/kpi/kpi-widget-config/kpi-widget-config.component.ts","../../widgets/implementations/kpi/kpi-widget-config/kpi-widget-config.component.html","../../widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.ts","../../widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.html","../../widgets/implementations/kpi/kpi-widget.module.ts","../../widgets/implementations/kpi/c8y-ngx-components-widgets-implementations-kpi.ts"],"sourcesContent":["import { Component, Input, OnInit } from '@angular/core';\nimport {\n AbstractControl,\n ControlContainer,\n FormBuilder,\n NgForm,\n ValidationErrors,\n ValidatorFn,\n Validators\n} from '@angular/forms';\nimport { OnBeforeSave } from '@c8y/ngx-components';\nimport { WidgetConfigComponent } from '@c8y/ngx-components/context-dashboard';\nimport {\n DatapointAttributesFormConfig,\n DatapointSelectorModalOptions,\n KPIDetails\n} from '@c8y/ngx-components/datapoint-selector';\nimport { IconSelectorService } from '@c8y/ngx-components/icon-selector';\nimport { Observable } from 'rxjs';\nimport { KpiWidgetConfig } from '../kpi-widget.model';\n\nexport function exactlyASingleDatapointActive(): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n const datapoints: KPIDetails[] = control.value;\n\n if (!datapoints || !datapoints.length) {\n return null;\n }\n\n const activeDatapoints = datapoints.filter(datapoint => datapoint.__active);\n\n if (activeDatapoints.length === 1) {\n return null;\n }\n\n return { exactlyOneDatapointNeedsToBeActive: true };\n };\n}\n\n@Component({\n selector: 'c8y-kpi-widget-config',\n templateUrl: './kpi-widget-config.component.html',\n viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]\n})\nexport class KpiWidgetConfigComponent implements OnInit, OnBeforeSave {\n @Input() config: KpiWidgetConfig;\n datapointSelectionConfig: Partial<DatapointSelectorModalOptions> = {};\n defaultFormOptions: Partial<DatapointAttributesFormConfig> = {\n showRedRange: true,\n showYellowRange: true\n };\n formGroup: ReturnType<KpiWidgetConfigComponent['createForm']>;\n availableIcons: string[] = [];\n limits = {\n fontSizeMax: 72,\n fontSizeMin: 18,\n numberOfDecimalPlacesMax: 10,\n numberOfDecimalPlacesMin: 0\n };\n\n constructor(\n private formBuilder: FormBuilder,\n private form: NgForm,\n private iconSelector: IconSelectorService,\n private widgetConfig: WidgetConfigComponent\n ) {}\n\n onBeforeSave(config?: KpiWidgetConfig): boolean | Promise<boolean> | Observable<boolean> {\n if (this.formGroup.valid) {\n Object.assign(config, this.formGroup.value);\n return true;\n }\n return false;\n }\n\n async ngOnInit() {\n if (this.widgetConfig.context?.id) {\n this.datapointSelectionConfig.contextAsset = this.widgetConfig?.context;\n }\n this.initForm();\n if (this.config?.datapoints) {\n this.formGroup.patchValue({ datapoints: this.config.datapoints });\n }\n }\n\n async openIconSelector() {\n try {\n const icon = await this.iconSelector.selectIcon({\n currentSelection: this.formGroup.value.icon\n });\n this.formGroup.patchValue({ icon });\n } catch {\n // nothing to do\n }\n }\n\n private initForm(): void {\n this.formGroup = this.createForm();\n this.form.form.addControl('config', this.formGroup);\n this.formGroup.patchValue(this.config);\n }\n\n private createForm() {\n return this.formBuilder.group({\n numberOfDecimalPlaces: [\n 1,\n [\n Validators.required,\n Validators.min(this.limits.numberOfDecimalPlacesMin),\n Validators.max(this.limits.numberOfDecimalPlacesMax)\n ]\n ],\n showTimestamp: [true, []],\n showTrend: [true, []],\n showIcon: [true, []],\n icon: ['water', [Validators.required, Validators.minLength(1)]],\n fontSize: [\n 36,\n [\n Validators.required,\n Validators.min(this.limits.fontSizeMin),\n Validators.max(this.limits.fontSizeMax)\n ]\n ],\n datapoints: this.formBuilder.control(new Array<KPIDetails>(), [\n Validators.required,\n Validators.minLength(1),\n exactlyASingleDatapointActive()\n ])\n });\n }\n}\n","<div class=\"p-l-24 p-r-24\">\n <form [formGroup]=\"formGroup\" class=\"row no-card-context\">\n <div class=\"col-sm-6 bg-level-0\">\n <c8y-datapoint-selection-list\n [defaultFormOptions]=\"defaultFormOptions\"\n [config]=\"datapointSelectionConfig\"\n [minActiveCount]=\"1\"\n [maxActiveCount]=\"1\"\n formControlName=\"datapoints\"\n name=\"datapoints\"\n class=\"bg-inherit\"\n ></c8y-datapoint-selection-list>\n </div>\n <div class=\"col-sm-6\">\n <div class=\"card-header separator\">\n <div class=\"card-title h4\">{{ 'Layout' | translate }}</div>\n </div>\n <c8y-form-group class=\"p-t-8\">\n <label translate>Icon</label>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-8 icon-32 text-muted\">\n <i [c8yIcon]=\"formGroup.value.icon\"></i>\n </div>\n <button\n class=\"btn btn-default btn-xs\"\n type=\"button\"\n title=\"{{ 'Change' | translate }}\"\n (click)=\"openIconSelector()\"\n >\n {{ 'Change' | translate }}\n </button>\n </div>\n </c8y-form-group>\n <c8y-form-group>\n <label [title]=\"'Number of decimal places' | translate\" translate>\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n formControlName=\"numberOfDecimalPlaces\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </c8y-form-group>\n <div>\n <label>{{ 'Display' | translate }}</label>\n <div class=\"d-flex gap-16 flex-wrap\">\n <c8y-form-group>\n <label [title]=\"'Show timestamp' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTimestamp\" name=\"showTimestamp\" />\n <span></span>\n <span translate>Show timestamp</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showIcon\" name=\"showIcon\" />\n <span></span>\n <span translate>Show icon</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show trend icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTrend\" name=\"showTrend\" />\n <span></span>\n <span translate>Show trend icon</span>\n <button\n class=\"btn-help btn-help--sm\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Indicates the trend between the last two measurement values.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label [title]=\"'Font size of measurement value (px)' | translate\" translate>\n Font size of measurement value (px)\n </label>\n <input\n class=\"form-control\"\n formControlName=\"fontSize\"\n name=\"fontSize\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n />\n <c8y-messages\n [show]=\"formGroup.controls?.fontSize?.touched && formGroup?.controls?.fontSize?.errors\"\n ></c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n </form>\n</div>\n","import { Component, Input, OnInit, Optional } from '@angular/core';\nimport { MeasurementRealtimeService } from '@c8y/ngx-components';\nimport { KPIDetails } from '@c8y/ngx-components/datapoint-selector';\nimport { combineLatest, NEVER, Observable } from 'rxjs';\nimport { distinctUntilChanged, filter, map, pairwise, startWith, tap } from 'rxjs/operators';\nimport { ContextDashboardComponent } from '@c8y/ngx-components/context-dashboard';\nimport { KpiWidgetConfig } from '../kpi-widget.model';\n\ninterface MeasurementValue {\n unit?: string;\n value: number;\n date: string;\n}\n\nenum ColorClass {\n danger = 'text-danger',\n warning = 'text-warning',\n unknown = ''\n}\n\n@Component({\n selector: 'c8y-kpi-widget-view',\n templateUrl: './kpi-widget-view.component.html',\n providers: [MeasurementRealtimeService]\n})\nexport class KpiWidgetViewComponent implements OnInit {\n @Input() config: KpiWidgetConfig = { datapoints: [] };\n state$: Observable<{\n latestMeasurement: MeasurementValue;\n previousValue: MeasurementValue;\n trend: string;\n unit: string;\n colorClass: ColorClass;\n }> = NEVER;\n\n // used to differentiate between loading state and empty state\n noDataInitiallyInDB = false;\n\n constructor(\n private measurementRealtime: MeasurementRealtimeService,\n @Optional() private dashboard: ContextDashboardComponent\n ) {}\n\n async ngOnInit() {\n const datapoints = this.config.datapoints || [];\n const datapoint: KPIDetails = datapoints.find(tmp => tmp.__active);\n if (!datapoint) {\n return;\n }\n\n this.state$ = this.setupObservable(datapoint);\n }\n\n setupObservable(datapoint: KPIDetails): Observable<{\n latestMeasurement: MeasurementValue;\n previousValue: any;\n trend: string;\n unit: string;\n colorClass: ColorClass;\n }> {\n this.assignContextFromContextDashboard(datapoint);\n const latestMeasurement$ = this.getLatestMeasurement$(datapoint);\n const lastTwoValues$ = this.getLastTwoValuesOfObservable$(latestMeasurement$);\n\n const previousValue$ = lastTwoValues$.pipe(\n map(res => res[0]),\n startWith(undefined as any)\n );\n\n const unit$ = latestMeasurement$.pipe(\n map(latestMeasurementValue => datapoint.unit || latestMeasurementValue.unit || ''),\n startWith(''),\n distinctUntilChanged()\n );\n\n return combineLatest([\n latestMeasurement$,\n previousValue$,\n this.getTrendOfLatestMeasurements$(lastTwoValues$),\n unit$,\n this.getColorClass$(latestMeasurement$, datapoint)\n ]).pipe(\n map(([latestMeasurement, previousValue, trend, unit, colorClass]) => {\n return {\n latestMeasurement,\n previousValue,\n trend,\n unit,\n colorClass\n };\n })\n );\n }\n\n private getLatestMeasurement$(datapoint: KPIDetails): Observable<MeasurementValue> {\n return this.measurementRealtime\n .latestValueOfSpecificMeasurement$(\n datapoint.fragment,\n datapoint.series,\n datapoint.__target,\n // we only need the last two values in case we want to show a trend\n this.config.showTrend ? 2 : 1,\n // null will be emitted in case no measurement was found initially\n true\n )\n .pipe(\n tap(measurement => {\n if (!measurement) {\n this.noDataInitiallyInDB = true;\n }\n }),\n filter(measurement => !!measurement),\n map(measurement => {\n return {\n unit: measurement[datapoint.fragment][datapoint.series].unit,\n value: measurement[datapoint.fragment][datapoint.series].value,\n date: measurement.time as string\n };\n })\n );\n }\n\n private getColorClass$(\n measurementAndDatapointCombination$: Observable<MeasurementValue>,\n datapoint: KPIDetails\n ): Observable<ColorClass> {\n return measurementAndDatapointCombination$.pipe(\n map(latestMeasurementValue => {\n if (this.inRangeOf(datapoint, latestMeasurementValue.value, 'redRangeMin', 'redRangeMax')) {\n return ColorClass.danger;\n }\n\n if (\n this.inRangeOf(\n datapoint,\n latestMeasurementValue.value,\n 'yellowRangeMin',\n 'yellowRangeMax'\n )\n ) {\n return ColorClass.warning;\n }\n\n return ColorClass.unknown;\n }),\n startWith(ColorClass.unknown),\n distinctUntilChanged()\n );\n }\n\n private getLastTwoValuesOfObservable$<T>(input$: Observable<T>): Observable<T[]> {\n return input$.pipe(pairwise());\n }\n\n private getTrendOfLatestMeasurements$(latestMeasurement$: Observable<MeasurementValue[]>) {\n return latestMeasurement$.pipe(\n map(res => {\n if (res.length === 2) {\n const oldValue = res[0].value;\n const newValue = res[1].value;\n if (oldValue < newValue) {\n return '45deg';\n }\n if (oldValue > newValue) {\n return '135deg';\n }\n }\n return '90deg';\n }),\n startWith('90deg'),\n distinctUntilChanged()\n );\n }\n\n private inRangeOf(\n datapoint: KPIDetails,\n measurementValue: number,\n minAttribute: string,\n maxAttribute: string\n ): boolean {\n if (\n typeof datapoint[minAttribute] === 'number' &&\n typeof datapoint[maxAttribute] === 'number'\n ) {\n if (\n measurementValue >= datapoint[minAttribute] &&\n measurementValue < datapoint[maxAttribute]\n ) {\n return true;\n }\n }\n return false;\n }\n\n private assignContextFromContextDashboard(datapoint: KPIDetails) {\n if (!this.dashboard?.isDeviceTypeDashboard) {\n return;\n }\n const context = this.dashboard?.context;\n if (context?.id) {\n const { name, id } = context;\n datapoint.__target = { name, id };\n }\n }\n}\n","<div\n class=\"kpi-widget__container d-flex d-col fit-h fit-w a-i-center j-c-center\"\n *ngIf=\"state$ | async as lastState; else noMeasurementFound\"\n>\n <div class=\"d-flex a-i-center j-c-center fit-w\">\n <div\n class=\"m-r-16 flex-no-shrink text-muted\"\n [ngClass]=\"lastState.colorClass\"\n *ngIf=\"config.icon && config.showIcon\"\n >\n <i class=\"icon-32\" [c8yIcon]=\"config.icon\"></i>\n </div>\n <div class=\"text-truncate\">\n <span\n class=\"text-truncate text-medium\"\n [ngClass]=\"lastState.colorClass\"\n [ngStyle]=\"{ 'font-size': (config.fontSize || '36') + 'px' }\"\n title=\"{{\n lastState.colorClass === 'text-danger'\n ? ('Within red range:' | translate)\n : lastState.colorClass === 'text-warning'\n ? ('Within yellow range:' | translate)\n : ''\n }} {{\n lastState.latestMeasurement.value\n | number\n : '1.' +\n (config.numberOfDecimalPlaces || '0') +\n '-' +\n (config.numberOfDecimalPlaces || '0')\n }} {{ lastState.unit || '' }}\"\n >\n {{\n lastState.latestMeasurement.value\n | number\n : '1.' +\n (config.numberOfDecimalPlaces || '0') +\n '-' +\n (config.numberOfDecimalPlaces || '0')\n }}\n <small class=\"text-regular\">{{ lastState.unit || '' }}</small>\n </span>\n </div>\n <div\n class=\"dot dot-info dot-30 m-l-16 flex-no-shrink\"\n *ngIf=\"config?.showTrend && lastState.previousValue as previousValue\"\n >\n <i\n class=\"icon-20\"\n [title]=\"\n ('Previous value' | translate) +\n ': ' +\n (previousValue.value\n | number\n : '1.' +\n (config.numberOfDecimalPlaces || '0') +\n '-' +\n (config.numberOfDecimalPlaces || '0')) +\n ' (' +\n (previousValue.date | date: 'medium') +\n ')'\n \"\n c8yIcon=\"arrow-dotted-up\"\n [ngStyle]=\"{ transform: 'rotate(' + lastState.trend + ')' }\"\n ></i>\n </div>\n </div>\n <div class=\"d-flex j-c-center\">\n <p *ngIf=\"config?.showTimestamp\" class=\"icon-flex text-center text-muted small\">\n <i c8yIcon=\"calendar\"></i>\n {{ lastState.latestMeasurement.date | date: 'medium' }}\n </p>\n </div>\n</div>\n\n<ng-template #noMeasurementFound>\n <div class=\"d-flex fit-h fit-w j-c-center a-i-center\">\n <c8y-ui-empty-state\n *ngIf=\"noDataInitiallyInDB\"\n class=\"fit-w\"\n [icon]=\"'line-chart'\"\n [title]=\"'No measurement to display.' | translate\"\n [subtitle]=\"'Waiting for measurements to be created.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <c8y-loading *ngIf=\"!noDataInitiallyInDB\"></c8y-loading>\n </div>\n</ng-template>\n","import { NgModule } from '@angular/core';\nimport { CoreModule } from '@c8y/ngx-components';\nimport { DatapointSelectorModule } from '@c8y/ngx-components/datapoint-selector';\nimport { IconSelectorModule } from '@c8y/ngx-components/icon-selector';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { KpiWidgetConfigComponent } from './kpi-widget-config/kpi-widget-config.component';\nimport { KpiWidgetViewComponent } from './kpi-widget-view/kpi-widget-view.component';\n\n@NgModule({\n imports: [CoreModule, DatapointSelectorModule, IconSelectorModule, PopoverModule],\n declarations: [KpiWidgetViewComponent, KpiWidgetConfigComponent]\n})\nexport class KpiWidgetModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2","i3"],"mappings":"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"}
1
+ {"version":3,"file":"c8y-ngx-components-widgets-implementations-kpi.mjs","sources":["../../widgets/implementations/kpi/kpi-widget-config/kpi-widget-config.component.ts","../../widgets/implementations/kpi/kpi-widget-config/kpi-widget-config.component.html","../../widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.ts","../../widgets/implementations/kpi/kpi-widget-view/kpi-widget-view.component.html","../../widgets/implementations/kpi/kpi-widget.module.ts","../../widgets/implementations/kpi/c8y-ngx-components-widgets-implementations-kpi.ts"],"sourcesContent":["import { Component, Input, OnInit } from '@angular/core';\nimport {\n AbstractControl,\n ControlContainer,\n FormBuilder,\n NgForm,\n ValidationErrors,\n ValidatorFn,\n Validators\n} from '@angular/forms';\nimport { OnBeforeSave } from '@c8y/ngx-components';\nimport { WidgetConfigComponent } from '@c8y/ngx-components/context-dashboard';\nimport {\n DatapointAttributesFormConfig,\n DatapointSelectorModalOptions,\n KPIDetails\n} from '@c8y/ngx-components/datapoint-selector';\nimport { IconSelectorService } from '@c8y/ngx-components/icon-selector';\nimport { Observable } from 'rxjs';\nimport { KpiWidgetConfig } from '../kpi-widget.model';\n\nexport function exactlyASingleDatapointActive(): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n const datapoints: KPIDetails[] = control.value;\n\n if (!datapoints || !datapoints.length) {\n return null;\n }\n\n const activeDatapoints = datapoints.filter(datapoint => datapoint.__active);\n\n if (activeDatapoints.length === 1) {\n return null;\n }\n\n return { exactlyOneDatapointNeedsToBeActive: true };\n };\n}\n\n@Component({\n selector: 'c8y-kpi-widget-config',\n templateUrl: './kpi-widget-config.component.html',\n viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]\n})\nexport class KpiWidgetConfigComponent implements OnInit, OnBeforeSave {\n @Input() config: KpiWidgetConfig;\n datapointSelectionConfig: Partial<DatapointSelectorModalOptions> = {};\n defaultFormOptions: Partial<DatapointAttributesFormConfig> = {\n showRedRange: true,\n showYellowRange: true\n };\n formGroup: ReturnType<KpiWidgetConfigComponent['createForm']>;\n availableIcons: string[] = [];\n limits = {\n fontSizeMax: 72,\n fontSizeMin: 18,\n numberOfDecimalPlacesMax: 10,\n numberOfDecimalPlacesMin: 0\n };\n\n constructor(\n private formBuilder: FormBuilder,\n private form: NgForm,\n private iconSelector: IconSelectorService,\n private widgetConfig: WidgetConfigComponent\n ) {}\n\n onBeforeSave(config?: KpiWidgetConfig): boolean | Promise<boolean> | Observable<boolean> {\n if (this.formGroup.valid) {\n Object.assign(config, this.formGroup.value);\n return true;\n }\n return false;\n }\n\n async ngOnInit() {\n if (this.widgetConfig.context?.id) {\n this.datapointSelectionConfig.contextAsset = this.widgetConfig?.context;\n }\n this.initForm();\n if (this.config?.datapoints) {\n this.formGroup.patchValue({ datapoints: this.config.datapoints });\n }\n }\n\n async openIconSelector() {\n try {\n const icon = await this.iconSelector.selectIcon({\n currentSelection: this.formGroup.value.icon\n });\n this.formGroup.patchValue({ icon });\n } catch {\n // nothing to do\n }\n }\n\n private initForm(): void {\n this.formGroup = this.createForm();\n this.form.form.addControl('config', this.formGroup);\n this.formGroup.patchValue(this.config);\n }\n\n private createForm() {\n return this.formBuilder.group({\n numberOfDecimalPlaces: [\n 1,\n [\n Validators.required,\n Validators.min(this.limits.numberOfDecimalPlacesMin),\n Validators.max(this.limits.numberOfDecimalPlacesMax)\n ]\n ],\n showTimestamp: [true, []],\n showTrend: [true, []],\n showIcon: [true, []],\n icon: ['water', [Validators.required, Validators.minLength(1)]],\n fontSize: [\n 36,\n [\n Validators.required,\n Validators.min(this.limits.fontSizeMin),\n Validators.max(this.limits.fontSizeMax)\n ]\n ],\n datapoints: this.formBuilder.control(new Array<KPIDetails>(), [\n Validators.required,\n Validators.minLength(1),\n exactlyASingleDatapointActive()\n ])\n });\n }\n}\n","<div class=\"p-l-24 p-r-24\">\n <form [formGroup]=\"formGroup\" class=\"row no-card-context\">\n <div class=\"col-sm-6 bg-level-0\">\n <c8y-datapoint-selection-list\n [defaultFormOptions]=\"defaultFormOptions\"\n [config]=\"datapointSelectionConfig\"\n [minActiveCount]=\"1\"\n [maxActiveCount]=\"1\"\n formControlName=\"datapoints\"\n name=\"datapoints\"\n class=\"bg-inherit\"\n ></c8y-datapoint-selection-list>\n </div>\n <div class=\"col-sm-6\">\n <div class=\"card-header separator\">\n <div class=\"card-title h4\">{{ 'Layout' | translate }}</div>\n </div>\n <c8y-form-group class=\"p-t-8\">\n <label translate>Icon</label>\n <div class=\"d-flex a-i-center\">\n <div class=\"p-r-8 icon-32 text-muted\">\n <i [c8yIcon]=\"formGroup.value.icon\"></i>\n </div>\n <button\n class=\"btn btn-default btn-xs\"\n type=\"button\"\n title=\"{{ 'Change' | translate }}\"\n (click)=\"openIconSelector()\"\n >\n {{ 'Change' | translate }}\n </button>\n </div>\n </c8y-form-group>\n <c8y-form-group>\n <label [title]=\"'Number of decimal places' | translate\" translate>\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n formControlName=\"numberOfDecimalPlaces\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </c8y-form-group>\n <div>\n <label>{{ 'Display' | translate }}</label>\n <div class=\"d-flex gap-16 flex-wrap\">\n <c8y-form-group>\n <label [title]=\"'Show timestamp' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTimestamp\" name=\"showTimestamp\" />\n <span></span>\n <span translate>Show timestamp</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showIcon\" name=\"showIcon\" />\n <span></span>\n <span translate>Show icon</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show trend icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTrend\" name=\"showTrend\" />\n <span></span>\n <span translate>Show trend icon</span>\n <button\n class=\"btn-help btn-help--sm\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Indicates the trend between the last two measurement values.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label [title]=\"'Font size of measurement value (px)' | translate\" translate>\n Font size of measurement value (px)\n </label>\n <input\n class=\"form-control\"\n formControlName=\"fontSize\"\n name=\"fontSize\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n />\n <c8y-messages\n [show]=\"formGroup.controls?.fontSize?.touched && formGroup?.controls?.fontSize?.errors\"\n ></c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n </form>\n</div>\n","import { Component, Input, OnInit, Optional } from '@angular/core';\nimport { MeasurementRealtimeService } from '@c8y/ngx-components';\nimport { KPIDetails } from '@c8y/ngx-components/datapoint-selector';\nimport { combineLatest, NEVER, Observable } from 'rxjs';\nimport { distinctUntilChanged, filter, map, pairwise, startWith, tap } from 'rxjs/operators';\nimport { ContextDashboardComponent } from '@c8y/ngx-components/context-dashboard';\nimport { KpiWidgetConfig } from '../kpi-widget.model';\n\ninterface MeasurementValue {\n unit?: string;\n value: number;\n date: string;\n}\n\nenum ColorClass {\n danger = 'text-danger',\n warning = 'text-warning',\n unknown = ''\n}\n\n@Component({\n selector: 'c8y-kpi-widget-view',\n templateUrl: './kpi-widget-view.component.html',\n providers: [MeasurementRealtimeService]\n})\nexport class KpiWidgetViewComponent implements OnInit {\n @Input() config: KpiWidgetConfig = { datapoints: [] };\n state$: Observable<{\n latestMeasurement: MeasurementValue;\n previousValue: MeasurementValue | undefined;\n trend: string;\n unit: string;\n colorClass: ColorClass;\n }> = NEVER;\n\n // used to differentiate between loading state and empty state\n noDataInitiallyInDB = false;\n\n constructor(\n private measurementRealtime: MeasurementRealtimeService,\n @Optional() private dashboard: ContextDashboardComponent\n ) {}\n\n async ngOnInit() {\n const datapoints = this.config.datapoints || [];\n const datapoint: KPIDetails = datapoints.find(tmp => tmp.__active);\n if (!datapoint) {\n return;\n }\n\n this.state$ = this.setupObservable(datapoint);\n }\n\n setupObservable(datapoint: KPIDetails): Observable<{\n latestMeasurement: MeasurementValue;\n previousValue: MeasurementValue | undefined;\n trend: string;\n unit: string;\n colorClass: ColorClass;\n }> {\n this.assignContextFromContextDashboard(datapoint);\n const latestMeasurement$ = this.getLatestMeasurement$(datapoint);\n const lastTwoValues$ = this.getLastTwoValuesOfObservable$(latestMeasurement$);\n\n const previousValue$ = lastTwoValues$.pipe(\n map(([previousVal]) => previousVal),\n startWith(undefined as MeasurementValue | undefined)\n );\n\n const unit$ = latestMeasurement$.pipe(\n map(latestMeasurementValue => datapoint.unit || latestMeasurementValue.unit || ''),\n startWith(''),\n distinctUntilChanged()\n );\n\n return combineLatest([\n latestMeasurement$,\n previousValue$,\n this.getTrendOfLatestMeasurements$(lastTwoValues$),\n unit$,\n this.getColorClass$(latestMeasurement$, datapoint)\n ]).pipe(\n map(([latestMeasurement, previousValue, trend, unit, colorClass]) => {\n return {\n latestMeasurement,\n previousValue,\n trend,\n unit,\n colorClass\n };\n })\n );\n }\n\n private getLatestMeasurement$(datapoint: KPIDetails): Observable<MeasurementValue> {\n return this.measurementRealtime\n .latestValueOfSpecificMeasurement$(\n datapoint.fragment,\n datapoint.series,\n datapoint.__target,\n // we only need the last two values in case we want to show a trend\n this.config.showTrend ? 2 : 1,\n // null will be emitted in case no measurement was found initially\n true\n )\n .pipe(\n tap(measurement => {\n if (!measurement) {\n this.noDataInitiallyInDB = true;\n }\n }),\n filter(measurement => !!measurement),\n map(measurement => {\n return {\n unit: measurement[datapoint.fragment][datapoint.series].unit,\n value: measurement[datapoint.fragment][datapoint.series].value,\n date: measurement.time as string\n };\n })\n );\n }\n\n private getColorClass$(\n measurementAndDatapointCombination$: Observable<MeasurementValue>,\n datapoint: KPIDetails\n ): Observable<ColorClass> {\n return measurementAndDatapointCombination$.pipe(\n map(latestMeasurementValue => {\n if (this.inRangeOf(datapoint, latestMeasurementValue.value, 'redRangeMin', 'redRangeMax')) {\n return ColorClass.danger;\n }\n\n if (\n this.inRangeOf(\n datapoint,\n latestMeasurementValue.value,\n 'yellowRangeMin',\n 'yellowRangeMax'\n )\n ) {\n return ColorClass.warning;\n }\n\n return ColorClass.unknown;\n }),\n startWith(ColorClass.unknown),\n distinctUntilChanged()\n );\n }\n\n private getLastTwoValuesOfObservable$<T>(input$: Observable<T>): Observable<T[]> {\n return input$.pipe(pairwise());\n }\n\n private getTrendOfLatestMeasurements$(latestMeasurement$: Observable<MeasurementValue[]>) {\n return latestMeasurement$.pipe(\n map(res => {\n if (res.length === 2) {\n const oldValue = res[0].value;\n const newValue = res[1].value;\n if (oldValue < newValue) {\n return '45deg';\n }\n if (oldValue > newValue) {\n return '135deg';\n }\n }\n return '90deg';\n }),\n startWith('90deg'),\n distinctUntilChanged()\n );\n }\n\n private inRangeOf(\n datapoint: KPIDetails,\n measurementValue: number,\n minAttribute: string,\n maxAttribute: string\n ): boolean {\n if (\n typeof datapoint[minAttribute] === 'number' &&\n typeof datapoint[maxAttribute] === 'number'\n ) {\n if (\n measurementValue >= datapoint[minAttribute] &&\n measurementValue < datapoint[maxAttribute]\n ) {\n return true;\n }\n }\n return false;\n }\n\n private assignContextFromContextDashboard(datapoint: KPIDetails) {\n if (!this.dashboard?.isDeviceTypeDashboard) {\n return;\n }\n const context = this.dashboard?.context;\n if (context?.id) {\n const { name, id } = context;\n datapoint.__target = { name, id };\n }\n }\n}\n","<div\n class=\"kpi-widget__container d-flex d-col fit-h fit-w a-i-center j-c-center\"\n *ngIf=\"state$ | async as lastState; else noMeasurementFound\"\n>\n <div class=\"d-flex a-i-center j-c-center fit-w\">\n <div\n class=\"m-r-16 flex-no-shrink text-muted\"\n [ngClass]=\"lastState.colorClass\"\n *ngIf=\"config.icon && config.showIcon\"\n >\n <i class=\"icon-32\" [c8yIcon]=\"config.icon\"></i>\n </div>\n <div class=\"text-truncate\">\n <span\n class=\"text-truncate text-medium\"\n [ngClass]=\"lastState.colorClass\"\n [ngStyle]=\"{ 'font-size': (config.fontSize || '36') + 'px' }\"\n title=\"{{\n lastState.colorClass === 'text-danger'\n ? ('Within red range:' | translate)\n : lastState.colorClass === 'text-warning'\n ? ('Within yellow range:' | translate)\n : ''\n }} {{\n lastState.latestMeasurement.value\n | number\n : '1.' +\n (config.numberOfDecimalPlaces || '0') +\n '-' +\n (config.numberOfDecimalPlaces || '0')\n }} {{ lastState.unit || '' }}\"\n >\n {{\n lastState.latestMeasurement.value\n | number\n : '1.' +\n (config.numberOfDecimalPlaces || '0') +\n '-' +\n (config.numberOfDecimalPlaces || '0')\n }}\n <small class=\"text-regular\">{{ lastState.unit || '' }}</small>\n </span>\n </div>\n <div\n class=\"dot dot-info dot-30 m-l-16 flex-no-shrink\"\n *ngIf=\"config?.showTrend && lastState.previousValue as previousValue\"\n >\n <i\n class=\"icon-20\"\n [title]=\"\n ('Previous value' | translate) +\n ': ' +\n (previousValue.value\n | number\n : '1.' +\n (config.numberOfDecimalPlaces || '0') +\n '-' +\n (config.numberOfDecimalPlaces || '0')) +\n ' (' +\n (previousValue.date | date: 'medium') +\n ')'\n \"\n c8yIcon=\"arrow-dotted-up\"\n [ngStyle]=\"{ transform: 'rotate(' + lastState.trend + ')' }\"\n ></i>\n </div>\n </div>\n <div class=\"d-flex j-c-center\">\n <p *ngIf=\"config?.showTimestamp\" class=\"icon-flex text-center text-muted small\">\n <i c8yIcon=\"calendar\"></i>\n {{ lastState.latestMeasurement.date | date: 'medium' }}\n </p>\n </div>\n</div>\n\n<ng-template #noMeasurementFound>\n <div class=\"d-flex fit-h fit-w j-c-center a-i-center\">\n <c8y-ui-empty-state\n *ngIf=\"noDataInitiallyInDB\"\n class=\"fit-w\"\n [icon]=\"'line-chart'\"\n [title]=\"'No measurement to display.' | translate\"\n [subtitle]=\"'Waiting for measurements to be created.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n <c8y-loading *ngIf=\"!noDataInitiallyInDB\"></c8y-loading>\n </div>\n</ng-template>\n","import { NgModule } from '@angular/core';\nimport { CoreModule } from '@c8y/ngx-components';\nimport { DatapointSelectorModule } from '@c8y/ngx-components/datapoint-selector';\nimport { IconSelectorModule } from '@c8y/ngx-components/icon-selector';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { KpiWidgetConfigComponent } from './kpi-widget-config/kpi-widget-config.component';\nimport { KpiWidgetViewComponent } from './kpi-widget-view/kpi-widget-view.component';\n\n@NgModule({\n imports: [CoreModule, DatapointSelectorModule, IconSelectorModule, PopoverModule],\n declarations: [KpiWidgetViewComponent, KpiWidgetConfigComponent]\n})\nexport class KpiWidgetModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2","i3"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Pipe, Injectable, InjectFlags, InjectionToken, Optional, Inject, isDevMode, EventEmitter, Directive, NgModule, LOCALE_ID, HostListener, Input, Component, Output, HostBinding, forwardRef, TemplateRef, SecurityContext, APP_INITIALIZER, Self, SkipSelf, NgModuleRef, createNgModuleRef, ViewChild, ContentChild, Attribute, ViewContainerRef, ContentChildren, ElementRef, Host, ViewChildren, Injector, importProvidersFrom, ChangeDetectionStrategy, SimpleChange, Type } from '@angular/core';
3
- import { isNaN as isNaN$1, isFinite, castArray, flatten, uniq, sortBy, groupBy, camelCase, isUndefined, throttle as throttle$1, keys, get, each, mapValues, mapKeys, isString, forEach, assign, memoize as memoize$1, find, negate, upperFirst, property as property$1, some, entries, omitBy, min, every, first as first$1, map as map$1, orderBy, flatMap, isEmpty, reduce, union, filter as filter$1, isEqual, snakeCase, matches, cloneDeep, uniqBy, clone, toNumber, isEqualWith, escape as escape$1, escapeRegExp, assignWith, set, findIndex, omit, pick, flow, isNil, chunk, transform, identity, without, indexOf, parseInt as parseInt$1, kebabCase, forOwn } from 'lodash-es';
3
+ import { isNaN as isNaN$1, isFinite, castArray, flatten, uniq, sortBy, groupBy, camelCase, isUndefined, throttle as throttle$1, keys, get, each, mapValues, mapKeys, isString, forEach, assign, find, negate, upperFirst, memoize as memoize$1, property, some, entries, omitBy, min, every, first as first$1, map as map$1, orderBy, flatMap, isEmpty, reduce, union, filter as filter$1, isEqual, snakeCase, matches, cloneDeep, uniqBy, clone, toNumber, isEqualWith, escape as escape$1, escapeRegExp, assignWith, set, findIndex, omit, pick, flow, isNil, chunk, transform, identity, without, indexOf, parseInt as parseInt$1, kebabCase, forOwn } from 'lodash-es';
4
4
  import { merge, of, defer, combineLatest, race, isObservable, from, Subject, BehaviorSubject, fromEvent, pipe, NEVER, concat, throwError, Observable, EMPTY, timer, fromEventPattern, empty, forkJoin, ReplaySubject } from 'rxjs';
5
5
  import { map, distinctUntilChanged, filter, startWith, switchMap, scan, take, shareReplay, debounceTime, tap, catchError, takeUntil, mergeMap, first, share, retryWhen, delay, concatMap, debounce, sample, withLatestFrom, every as every$1, toArray, merge as merge$1, expand, finalize } from 'rxjs/operators';
6
6
  import { __awaiter, __decorate, __metadata } from 'tslib';
@@ -26,7 +26,6 @@ import * as i6 from 'ngx-bootstrap/datepicker';
26
26
  import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
27
27
  import { defineLocale, enGbLocale, zhCnLocale, ruLocale, ptBrLocale, plLocale, nlLocale, koLocale, jaLocale, frLocale, esLocale, deLocale } from 'ngx-bootstrap/chronos';
28
28
  import { coerceNumberProperty } from '@angular/cdk/coercion';
29
- import { property, sortBy as sortBy$1, isEmpty as isEmpty$1, flatten as flatten$1, get as get$1, set as set$1, pick as pick$1 } from 'lodash';
30
29
  import * as i1$4 from '@angular/platform-browser';
31
30
  import { saveAs } from 'file-saver';
32
31
  import * as i1$5 from 'ngx-bootstrap/dropdown';
@@ -35,6 +34,7 @@ import * as i6$1 from '@angular/cdk/a11y';
35
34
  import { A11yModule } from '@angular/cdk/a11y';
36
35
  import * as i1$a from 'ngx-bootstrap/collapse';
37
36
  import { CollapseModule } from 'ngx-bootstrap/collapse';
37
+ import { sortBy as sortBy$1, isEmpty as isEmpty$1, flatten as flatten$1, get as get$1, set as set$1, pick as pick$1 } from 'lodash';
38
38
  import * as i1$8 from 'ngx-bootstrap/modal';
39
39
  import { ModalModule as ModalModule$1, BsModalRef } from 'ngx-bootstrap/modal';
40
40
  import * as i5 from '@angular/forms';
@@ -4643,23 +4643,6 @@ var GroupFragment;
4643
4643
  GroupFragment["dynamicGroupQueryString"] = "c8y_DeviceQueryString";
4644
4644
  })(GroupFragment || (GroupFragment = {}));
4645
4645
 
4646
- /**
4647
- * Decorator to memoize function results.
4648
- * @param resolver Cache key resolver function, used by memoize from lodash.
4649
- */
4650
- function memoize(resolver) {
4651
- return (target, fnName, descriptor) => {
4652
- const fn = descriptor.value;
4653
- descriptor.value = function (...args) {
4654
- const memoizedFnName = `_${fnName}Memoized`;
4655
- if (!this[memoizedFnName]) {
4656
- this[memoizedFnName] = memoize$1(fn, resolver);
4657
- }
4658
- return this[memoizedFnName](...args);
4659
- };
4660
- };
4661
- }
4662
-
4663
4646
  /**
4664
4647
  * AssetTypesService is being used to manage a cache of all existing asset types.
4665
4648
  * This service is injected in the AssetOverviewNavigationFactory class, which will trigger
@@ -4983,18 +4966,12 @@ class GroupService {
4983
4966
  }
4984
4967
  GroupService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GroupService, deps: [{ token: AssetTypesService }], target: i0.ɵɵFactoryTarget.Injectable });
4985
4968
  GroupService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GroupService, providedIn: 'root' });
4986
- __decorate([
4987
- memoize(property('id')),
4988
- __metadata("design:type", Function),
4989
- __metadata("design:paramtypes", [Object, Object]),
4990
- __metadata("design:returntype", Promise)
4991
- ], GroupService.prototype, "getIcon", null);
4992
4969
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: GroupService, decorators: [{
4993
4970
  type: Injectable,
4994
4971
  args: [{
4995
4972
  providedIn: 'root'
4996
4973
  }]
4997
- }], ctorParameters: function () { return [{ type: AssetTypesService }]; }, propDecorators: { getIcon: [] } });
4974
+ }], ctorParameters: function () { return [{ type: AssetTypesService }]; } });
4998
4975
 
4999
4976
  class GetGroupIconPipe {
5000
4977
  constructor(groupService) {
@@ -5102,6 +5079,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
5102
5079
  args: [{ name: 'humanize' }]
5103
5080
  }] });
5104
5081
 
5082
+ /**
5083
+ * Decorator to memoize function results.
5084
+ * @param resolver Cache key resolver function, used by memoize from lodash.
5085
+ */
5086
+ function memoize(resolver) {
5087
+ return (target, fnName, descriptor) => {
5088
+ const fn = descriptor.value;
5089
+ descriptor.value = function (...args) {
5090
+ const memoizedFnName = `_${fnName}Memoized`;
5091
+ if (!this[memoizedFnName]) {
5092
+ this[memoizedFnName] = memoize$1(fn, resolver);
5093
+ }
5094
+ return this[memoizedFnName](...args);
5095
+ };
5096
+ };
5097
+ }
5098
+
5105
5099
  class Permissions {
5106
5100
  constructor(appState, inventory, user) {
5107
5101
  this.appState = appState;
@@ -5164,11 +5158,9 @@ class Permissions {
5164
5158
  });
5165
5159
  }
5166
5160
  checkWithRequest(mo) {
5167
- const moName = mo.name;
5168
5161
  const moId = mo.id;
5169
5162
  const partialUpdateObject = {
5170
- id: moId,
5171
- name: moName
5163
+ id: moId
5172
5164
  };
5173
5165
  return this.inventory
5174
5166
  .update(partialUpdateObject)
@@ -5197,13 +5189,13 @@ class Permissions {
5197
5189
  Permissions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: Permissions, deps: [{ token: AppStateService }, { token: i1$1.InventoryService }, { token: i1$1.UserService }], target: i0.ɵɵFactoryTarget.Injectable });
5198
5190
  Permissions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: Permissions, providedIn: 'root' });
5199
5191
  __decorate([
5200
- memoize(property$1('id')),
5192
+ memoize(property('id')),
5201
5193
  __metadata("design:type", Function),
5202
5194
  __metadata("design:paramtypes", [Object]),
5203
5195
  __metadata("design:returntype", Promise)
5204
5196
  ], Permissions.prototype, "checkIfOwner", null);
5205
5197
  __decorate([
5206
- memoize(property$1('id')),
5198
+ memoize(property('id')),
5207
5199
  __metadata("design:type", Function),
5208
5200
  __metadata("design:paramtypes", [Object]),
5209
5201
  __metadata("design:returntype", void 0)
@@ -24616,7 +24608,8 @@ class WidgetsDashboardComponent {
24616
24608
  allowFullscreen: false,
24617
24609
  canCopy: true,
24618
24610
  canDelete: true,
24619
- isLoading: false
24611
+ isLoading: false,
24612
+ columns: 12
24620
24613
  };
24621
24614
  this.onAddWidget = new EventEmitter();
24622
24615
  this.onEditWidget = new EventEmitter();
@@ -24710,7 +24703,7 @@ class WidgetsDashboardComponent {
24710
24703
  }
24711
24704
  }
24712
24705
  WidgetsDashboardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: WidgetsDashboardComponent, deps: [{ token: DynamicComponentService }], target: i0.ɵɵFactoryTarget.Component });
24713
- WidgetsDashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: WidgetsDashboardComponent, selector: "c8y-widgets-dashboard", inputs: { widgets: "widgets", context: "context", contextDashboard: "contextDashboard", _settings: ["settings", "_settings"], breadcrumb: "breadcrumb" }, outputs: { onAddWidget: "onAddWidget", onEditWidget: "onEditWidget", onDeleteWidget: "onDeleteWidget", onChangeDashboard: "onChangeDashboard", onEditDashboard: "onEditDashboard", onCopyDashboard: "onCopyDashboard", onDeleteDashboard: "onDeleteDashboard", onFreeze: "onFreeze", onChangeStart: "onChangeStart", onChangeEnd: "onChangeEnd" }, host: { styleAttribute: "\n display: block;\n ", classAttribute: "dashboard c8y-grid-dashboard" }, providers: [WidgetsDashboardEventService], ngImport: i0, template: "<c8y-title *ngIf=\"!!settings.title\">\n {{ settings.title | translate }}\n</c8y-title>\n\n<c8y-breadcrumb *ngIf=\"!!breadcrumb\">\n <c8y-breadcrumb-item\n [icon]=\"breadcrumb.icon\"\n [label]=\"breadcrumb.label\"\n [path]=\"breadcrumb.path\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onAddWidget.observers.length\">\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"widget-dashboard--Add-widget\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add widget' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onEditDashboard.observers.length\">\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onEditDashboard.emit()\"\n data-cy=\"widgets-dashboard--edit-widget\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"settings.allowFullscreen\">\n <button\n title=\"{{ 'Full screen' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n (click)=\"toggleFullscreen()\"\n >\n <i [c8yIcon]=\"fullScreen() ? 'compress' : 'expand'\"></i>\n {{ 'Full screen' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"navbar-form\"\n *ngIf=\"onFreeze.observers.length\"\n>\n <button\n title=\"{{ 'Lock/unlock this dashboard' | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n [ngClass]=\"{ active: settings.isFrozen }\"\n (click)=\"onFreeze.emit(settings)\"\n [disabled]=\"settings.isDisabled\"\n uib-btn-checkbox\n data-cy=\"widgets-dashboard--button-lock-toggle\"\n >\n <i [c8yIcon]=\"settings.isFrozen ? 'lock' : 'unlock'\"></i>\n </button>\n</c8y-action-bar-item>\n<c8y-action-bar-item [placement]=\"'more'\" [priority]=\"-2000\" *ngIf=\"settings.canCopy\">\n <button title=\"{{ 'Copy dashboard' | translate }}\" type=\"button\" (click)=\"onCopyDashboard.emit()\" class=\"btn btn-link\">\n <i c8yIcon=\"clone\"></i>\n <span class=\"m-l-4\" translate>Copy dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n *ngIf=\"settings.canDelete && onDeleteDashboard.observers.length\"\n>\n <button\n title=\"{{ 'Delete dashboard' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteDashboard.emit()\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Delete dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<ng-template #loadingIndicator>\n <c8y-loading class=\"col-xs-12 text-center\" *ngIf=\"isLoadingWidgets$ | async\"></c8y-loading>\n</ng-template>\n\n<ng-container *ngIf=\"!(isLoadingWidgets$ | async); else loadingIndicator\">\n <ng-container *ngIf=\"resolvedWidgets$ | async as widgetsToDisplay\">\n <!-- empty state -->\n <c8y-ui-empty-state\n *ngIf=\"widgetsToDisplay?.length === 0\"\n [icon]=\"'c8y-device'\"\n [title]=\"'No widgets to display.' | translate\"\n >\n <div *ngIf=\"!settings.isFrozen && onAddWidget.observers.length\">\n <p translate>Add widgets to this dashboard.</p>\n <div>\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n class=\"btn btn-primary m-t-16\"\n translate\n >\n Add widget\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate ngNonBindable>\n Find out more in the\n <a c8y-guide-href=\"users-guide/cockpit/#dashboards\">User guide`KEEP_ORIGINAL`</a>\n .\n </small>\n </p>\n </div>\n </c8y-ui-empty-state>\n\n <c8y-dashboard\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n #dashboard\n >\n <c8y-dashboard-child\n *ngFor=\"let widget of widgetsToDisplay\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || settings.defaultWidth\"\n [height]=\"widget._height || settings.defaultHeight\"\n [margin]=\"settings.widgetMargin\"\n [isFrozen]=\"settings.isFrozen || settings.isDisabled\"\n [class]=\"widget.classes\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n (changeStart)=\"onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n #child\n >\n <c8y-dashboard-child-title>\n <span \n data-cy=\"c8y-dashboard-list--device-widget\"\n *ngIf=\"settings.translateWidgetTitle\">\n {{ widget.title | translate }}\n </span>\n <span *ngIf=\"!settings.translateWidgetTitle\">\n {{ widget.title }}\n </span>\n </c8y-dashboard-child-title>\n <c8y-dashboard-child-action *ngIf=\"onEditWidget.observers.length\">\n <button\n title=\"{{ 'Edit widget' | translate }}\"\n type=\"button\"\n (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"pencil\"></i>\n <span class=\"m-l-4\" translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dashboard-child-action *ngIf=\"onDeleteWidget.observers.length\">\n <button\n title=\"{{ 'Remove widget' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n\n <c8y-widget-time-context\n *ngIf=\"\n widget.config?.displaySettings?.globalTimeContext &&\n widget.config.widgetInstanceGlobalTimeContext\n \"\n (dateContextChange)=\"updateWidgetConfig({ date: $event }, widget)\"\n [canDecouple]=\"widget.config.canDecoupleGlobalTimeContext\"\n ></c8y-widget-time-context>\n\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n *ngIf=\"child.intersected\"\n (updateWidgetClasses)=\"updateWidgetClasses(widget, $event)\"\n ></c8y-dynamic-component>\n </c8y-dashboard-child>\n </c8y-dashboard>\n </ng-container>\n</ng-container>\n\n", dependencies: [{ kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading" }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId"] }, { kind: "component", type: DynamicComponentComponent, selector: "c8y-dynamic-component", inputs: ["componentId", "config", "mode", "notFoundError", "executeResolvers"], outputs: ["updateWidgetClasses"] }, { kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: DashboardChildComponent, selector: "c8y-dashboard-child", inputs: ["x", "y", "width", "height", "data", "margin", "isFrozen", "useIntersection", "class"], outputs: ["changeStart", "changeEnd"] }, { kind: "component", type: DashboardComponent, selector: "c8y-dashboard", inputs: ["columns", "gap", "rows"], outputs: ["dashboardChange"] }, { kind: "component", type: DashboardChildTitleComponent, selector: "c8y-dashboard-child-title" }, { kind: "component", type: DashboardChildActionComponent, selector: "c8y-dashboard-child-action" }, { kind: "component", type: WidgetTimeContextComponent, selector: "c8y-widget-time-context", inputs: ["canDecouple"], outputs: ["dateContextChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] });
24706
+ WidgetsDashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: WidgetsDashboardComponent, selector: "c8y-widgets-dashboard", inputs: { widgets: "widgets", context: "context", contextDashboard: "contextDashboard", _settings: ["settings", "_settings"], breadcrumb: "breadcrumb" }, outputs: { onAddWidget: "onAddWidget", onEditWidget: "onEditWidget", onDeleteWidget: "onDeleteWidget", onChangeDashboard: "onChangeDashboard", onEditDashboard: "onEditDashboard", onCopyDashboard: "onCopyDashboard", onDeleteDashboard: "onDeleteDashboard", onFreeze: "onFreeze", onChangeStart: "onChangeStart", onChangeEnd: "onChangeEnd" }, host: { styleAttribute: "\n display: block;\n ", classAttribute: "dashboard c8y-grid-dashboard" }, providers: [WidgetsDashboardEventService], ngImport: i0, template: "<c8y-title *ngIf=\"!!settings.title\">\n {{ settings.title | translate }}\n</c8y-title>\n\n<c8y-breadcrumb *ngIf=\"!!breadcrumb\">\n <c8y-breadcrumb-item\n [icon]=\"breadcrumb.icon\"\n [label]=\"breadcrumb.label\"\n [path]=\"breadcrumb.path\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onAddWidget.observers.length\">\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"widget-dashboard--Add-widget\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add widget' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onEditDashboard.observers.length\">\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onEditDashboard.emit()\"\n data-cy=\"widgets-dashboard--edit-widget\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"settings.allowFullscreen\">\n <button\n title=\"{{ 'Full screen' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n (click)=\"toggleFullscreen()\"\n >\n <i [c8yIcon]=\"fullScreen() ? 'compress' : 'expand'\"></i>\n {{ 'Full screen' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"navbar-form\"\n *ngIf=\"onFreeze.observers.length\"\n>\n <button\n title=\"{{ 'Lock/unlock this dashboard' | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n [ngClass]=\"{ active: settings.isFrozen }\"\n (click)=\"onFreeze.emit(settings)\"\n [disabled]=\"settings.isDisabled\"\n uib-btn-checkbox\n data-cy=\"widgets-dashboard--button-lock-toggle\"\n >\n <i [c8yIcon]=\"settings.isFrozen ? 'lock' : 'unlock'\"></i>\n </button>\n</c8y-action-bar-item>\n<c8y-action-bar-item [placement]=\"'more'\" [priority]=\"-2000\" *ngIf=\"settings.canCopy\">\n <button title=\"{{ 'Copy dashboard' | translate }}\" type=\"button\" (click)=\"onCopyDashboard.emit()\" class=\"btn btn-link\">\n <i c8yIcon=\"clone\"></i>\n <span class=\"m-l-4\" translate>Copy dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n *ngIf=\"settings.canDelete && onDeleteDashboard.observers.length\"\n>\n <button\n title=\"{{ 'Delete dashboard' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteDashboard.emit()\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Delete dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<ng-template #loadingIndicator>\n <c8y-loading class=\"col-xs-12 text-center\" *ngIf=\"isLoadingWidgets$ | async\"></c8y-loading>\n</ng-template>\n\n<ng-container *ngIf=\"!(isLoadingWidgets$ | async); else loadingIndicator\">\n <ng-container *ngIf=\"resolvedWidgets$ | async as widgetsToDisplay\">\n <!-- empty state -->\n <c8y-ui-empty-state\n *ngIf=\"widgetsToDisplay?.length === 0\"\n [icon]=\"'c8y-device'\"\n [title]=\"'No widgets to display.' | translate\"\n >\n <div *ngIf=\"!settings.isFrozen && onAddWidget.observers.length\">\n <p translate>Add widgets to this dashboard.</p>\n <div>\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n class=\"btn btn-primary m-t-16\"\n translate\n >\n Add widget\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate ngNonBindable>\n Find out more in the\n <a c8y-guide-href=\"users-guide/cockpit/#dashboards\">User guide`KEEP_ORIGINAL`</a>\n .\n </small>\n </p>\n </div>\n </c8y-ui-empty-state>\n\n <c8y-dashboard\n [columns]=\"settings.columns\"\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n #dashboard\n >\n <c8y-dashboard-child\n *ngFor=\"let widget of widgetsToDisplay\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || settings.defaultWidth\"\n [height]=\"widget._height || settings.defaultHeight\"\n [margin]=\"settings.widgetMargin\"\n [isFrozen]=\"settings.isFrozen || settings.isDisabled\"\n [class]=\"widget.classes\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n (changeStart)=\"onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n #child\n >\n <c8y-dashboard-child-title>\n <span \n data-cy=\"c8y-dashboard-list--device-widget\"\n *ngIf=\"settings.translateWidgetTitle\">\n {{ widget.title | translate }}\n </span>\n <span *ngIf=\"!settings.translateWidgetTitle\">\n {{ widget.title }}\n </span>\n </c8y-dashboard-child-title>\n <c8y-dashboard-child-action *ngIf=\"onEditWidget.observers.length\">\n <button\n title=\"{{ 'Edit widget' | translate }}\"\n type=\"button\"\n (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"pencil\"></i>\n <span class=\"m-l-4\" translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dashboard-child-action *ngIf=\"onDeleteWidget.observers.length\">\n <button\n title=\"{{ 'Remove widget' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n\n <c8y-widget-time-context\n *ngIf=\"\n widget.config?.displaySettings?.globalTimeContext &&\n widget.config.widgetInstanceGlobalTimeContext\n \"\n (dateContextChange)=\"updateWidgetConfig({ date: $event }, widget)\"\n [canDecouple]=\"widget.config.canDecoupleGlobalTimeContext\"\n ></c8y-widget-time-context>\n\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n *ngIf=\"child.intersected\"\n (updateWidgetClasses)=\"updateWidgetClasses(widget, $event)\"\n ></c8y-dynamic-component>\n </c8y-dashboard-child>\n </c8y-dashboard>\n </ng-container>\n</ng-container>\n\n", dependencies: [{ kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading" }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId"] }, { kind: "component", type: DynamicComponentComponent, selector: "c8y-dynamic-component", inputs: ["componentId", "config", "mode", "notFoundError", "executeResolvers"], outputs: ["updateWidgetClasses"] }, { kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: DashboardChildComponent, selector: "c8y-dashboard-child", inputs: ["x", "y", "width", "height", "data", "margin", "isFrozen", "useIntersection", "class"], outputs: ["changeStart", "changeEnd"] }, { kind: "component", type: DashboardComponent, selector: "c8y-dashboard", inputs: ["columns", "gap", "rows"], outputs: ["dashboardChange"] }, { kind: "component", type: DashboardChildTitleComponent, selector: "c8y-dashboard-child-title" }, { kind: "component", type: DashboardChildActionComponent, selector: "c8y-dashboard-child-action" }, { kind: "component", type: WidgetTimeContextComponent, selector: "c8y-widget-time-context", inputs: ["canDecouple"], outputs: ["dateContextChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] });
24714
24707
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: WidgetsDashboardComponent, decorators: [{
24715
24708
  type: Component,
24716
24709
  args: [{ selector: 'c8y-widgets-dashboard', host: {
@@ -24718,7 +24711,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
24718
24711
  display: block;
24719
24712
  `,
24720
24713
  class: 'dashboard c8y-grid-dashboard'
24721
- }, providers: [WidgetsDashboardEventService], template: "<c8y-title *ngIf=\"!!settings.title\">\n {{ settings.title | translate }}\n</c8y-title>\n\n<c8y-breadcrumb *ngIf=\"!!breadcrumb\">\n <c8y-breadcrumb-item\n [icon]=\"breadcrumb.icon\"\n [label]=\"breadcrumb.label\"\n [path]=\"breadcrumb.path\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onAddWidget.observers.length\">\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"widget-dashboard--Add-widget\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add widget' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onEditDashboard.observers.length\">\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onEditDashboard.emit()\"\n data-cy=\"widgets-dashboard--edit-widget\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"settings.allowFullscreen\">\n <button\n title=\"{{ 'Full screen' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n (click)=\"toggleFullscreen()\"\n >\n <i [c8yIcon]=\"fullScreen() ? 'compress' : 'expand'\"></i>\n {{ 'Full screen' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"navbar-form\"\n *ngIf=\"onFreeze.observers.length\"\n>\n <button\n title=\"{{ 'Lock/unlock this dashboard' | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n [ngClass]=\"{ active: settings.isFrozen }\"\n (click)=\"onFreeze.emit(settings)\"\n [disabled]=\"settings.isDisabled\"\n uib-btn-checkbox\n data-cy=\"widgets-dashboard--button-lock-toggle\"\n >\n <i [c8yIcon]=\"settings.isFrozen ? 'lock' : 'unlock'\"></i>\n </button>\n</c8y-action-bar-item>\n<c8y-action-bar-item [placement]=\"'more'\" [priority]=\"-2000\" *ngIf=\"settings.canCopy\">\n <button title=\"{{ 'Copy dashboard' | translate }}\" type=\"button\" (click)=\"onCopyDashboard.emit()\" class=\"btn btn-link\">\n <i c8yIcon=\"clone\"></i>\n <span class=\"m-l-4\" translate>Copy dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n *ngIf=\"settings.canDelete && onDeleteDashboard.observers.length\"\n>\n <button\n title=\"{{ 'Delete dashboard' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteDashboard.emit()\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Delete dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<ng-template #loadingIndicator>\n <c8y-loading class=\"col-xs-12 text-center\" *ngIf=\"isLoadingWidgets$ | async\"></c8y-loading>\n</ng-template>\n\n<ng-container *ngIf=\"!(isLoadingWidgets$ | async); else loadingIndicator\">\n <ng-container *ngIf=\"resolvedWidgets$ | async as widgetsToDisplay\">\n <!-- empty state -->\n <c8y-ui-empty-state\n *ngIf=\"widgetsToDisplay?.length === 0\"\n [icon]=\"'c8y-device'\"\n [title]=\"'No widgets to display.' | translate\"\n >\n <div *ngIf=\"!settings.isFrozen && onAddWidget.observers.length\">\n <p translate>Add widgets to this dashboard.</p>\n <div>\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n class=\"btn btn-primary m-t-16\"\n translate\n >\n Add widget\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate ngNonBindable>\n Find out more in the\n <a c8y-guide-href=\"users-guide/cockpit/#dashboards\">User guide`KEEP_ORIGINAL`</a>\n .\n </small>\n </p>\n </div>\n </c8y-ui-empty-state>\n\n <c8y-dashboard\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n #dashboard\n >\n <c8y-dashboard-child\n *ngFor=\"let widget of widgetsToDisplay\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || settings.defaultWidth\"\n [height]=\"widget._height || settings.defaultHeight\"\n [margin]=\"settings.widgetMargin\"\n [isFrozen]=\"settings.isFrozen || settings.isDisabled\"\n [class]=\"widget.classes\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n (changeStart)=\"onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n #child\n >\n <c8y-dashboard-child-title>\n <span \n data-cy=\"c8y-dashboard-list--device-widget\"\n *ngIf=\"settings.translateWidgetTitle\">\n {{ widget.title | translate }}\n </span>\n <span *ngIf=\"!settings.translateWidgetTitle\">\n {{ widget.title }}\n </span>\n </c8y-dashboard-child-title>\n <c8y-dashboard-child-action *ngIf=\"onEditWidget.observers.length\">\n <button\n title=\"{{ 'Edit widget' | translate }}\"\n type=\"button\"\n (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"pencil\"></i>\n <span class=\"m-l-4\" translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dashboard-child-action *ngIf=\"onDeleteWidget.observers.length\">\n <button\n title=\"{{ 'Remove widget' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n\n <c8y-widget-time-context\n *ngIf=\"\n widget.config?.displaySettings?.globalTimeContext &&\n widget.config.widgetInstanceGlobalTimeContext\n \"\n (dateContextChange)=\"updateWidgetConfig({ date: $event }, widget)\"\n [canDecouple]=\"widget.config.canDecoupleGlobalTimeContext\"\n ></c8y-widget-time-context>\n\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n *ngIf=\"child.intersected\"\n (updateWidgetClasses)=\"updateWidgetClasses(widget, $event)\"\n ></c8y-dynamic-component>\n </c8y-dashboard-child>\n </c8y-dashboard>\n </ng-container>\n</ng-container>\n\n" }]
24714
+ }, providers: [WidgetsDashboardEventService], template: "<c8y-title *ngIf=\"!!settings.title\">\n {{ settings.title | translate }}\n</c8y-title>\n\n<c8y-breadcrumb *ngIf=\"!!breadcrumb\">\n <c8y-breadcrumb-item\n [icon]=\"breadcrumb.icon\"\n [label]=\"breadcrumb.label\"\n [path]=\"breadcrumb.path\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onAddWidget.observers.length\">\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"widget-dashboard--Add-widget\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add widget' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onEditDashboard.observers.length\">\n <button\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onEditDashboard.emit()\"\n data-cy=\"widgets-dashboard--edit-widget\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"settings.allowFullscreen\">\n <button\n title=\"{{ 'Full screen' | translate }}\"\n type=\"button\"\n class=\"btn btn-link\"\n (click)=\"toggleFullscreen()\"\n >\n <i [c8yIcon]=\"fullScreen() ? 'compress' : 'expand'\"></i>\n {{ 'Full screen' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"navbar-form\"\n *ngIf=\"onFreeze.observers.length\"\n>\n <button\n title=\"{{ 'Lock/unlock this dashboard' | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n [ngClass]=\"{ active: settings.isFrozen }\"\n (click)=\"onFreeze.emit(settings)\"\n [disabled]=\"settings.isDisabled\"\n uib-btn-checkbox\n data-cy=\"widgets-dashboard--button-lock-toggle\"\n >\n <i [c8yIcon]=\"settings.isFrozen ? 'lock' : 'unlock'\"></i>\n </button>\n</c8y-action-bar-item>\n<c8y-action-bar-item [placement]=\"'more'\" [priority]=\"-2000\" *ngIf=\"settings.canCopy\">\n <button title=\"{{ 'Copy dashboard' | translate }}\" type=\"button\" (click)=\"onCopyDashboard.emit()\" class=\"btn btn-link\">\n <i c8yIcon=\"clone\"></i>\n <span class=\"m-l-4\" translate>Copy dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n *ngIf=\"settings.canDelete && onDeleteDashboard.observers.length\"\n>\n <button\n title=\"{{ 'Delete dashboard' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteDashboard.emit()\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Delete dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<ng-template #loadingIndicator>\n <c8y-loading class=\"col-xs-12 text-center\" *ngIf=\"isLoadingWidgets$ | async\"></c8y-loading>\n</ng-template>\n\n<ng-container *ngIf=\"!(isLoadingWidgets$ | async); else loadingIndicator\">\n <ng-container *ngIf=\"resolvedWidgets$ | async as widgetsToDisplay\">\n <!-- empty state -->\n <c8y-ui-empty-state\n *ngIf=\"widgetsToDisplay?.length === 0\"\n [icon]=\"'c8y-device'\"\n [title]=\"'No widgets to display.' | translate\"\n >\n <div *ngIf=\"!settings.isFrozen && onAddWidget.observers.length\">\n <p translate>Add widgets to this dashboard.</p>\n <div>\n <button\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n class=\"btn btn-primary m-t-16\"\n translate\n >\n Add widget\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate ngNonBindable>\n Find out more in the\n <a c8y-guide-href=\"users-guide/cockpit/#dashboards\">User guide`KEEP_ORIGINAL`</a>\n .\n </small>\n </p>\n </div>\n </c8y-ui-empty-state>\n\n <c8y-dashboard\n [columns]=\"settings.columns\"\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n #dashboard\n >\n <c8y-dashboard-child\n *ngFor=\"let widget of widgetsToDisplay\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || settings.defaultWidth\"\n [height]=\"widget._height || settings.defaultHeight\"\n [margin]=\"settings.widgetMargin\"\n [isFrozen]=\"settings.isFrozen || settings.isDisabled\"\n [class]=\"widget.classes\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n (changeStart)=\"onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n #child\n >\n <c8y-dashboard-child-title>\n <span \n data-cy=\"c8y-dashboard-list--device-widget\"\n *ngIf=\"settings.translateWidgetTitle\">\n {{ widget.title | translate }}\n </span>\n <span *ngIf=\"!settings.translateWidgetTitle\">\n {{ widget.title }}\n </span>\n </c8y-dashboard-child-title>\n <c8y-dashboard-child-action *ngIf=\"onEditWidget.observers.length\">\n <button\n title=\"{{ 'Edit widget' | translate }}\"\n type=\"button\"\n (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"pencil\"></i>\n <span class=\"m-l-4\" translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dashboard-child-action *ngIf=\"onDeleteWidget.observers.length\">\n <button\n title=\"{{ 'Remove widget' | translate }}\"\n type=\"button\"\n (click)=\"onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"delete\"></i>\n <span class=\"m-l-4\" translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n\n <c8y-widget-time-context\n *ngIf=\"\n widget.config?.displaySettings?.globalTimeContext &&\n widget.config.widgetInstanceGlobalTimeContext\n \"\n (dateContextChange)=\"updateWidgetConfig({ date: $event }, widget)\"\n [canDecouple]=\"widget.config.canDecoupleGlobalTimeContext\"\n ></c8y-widget-time-context>\n\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n *ngIf=\"child.intersected\"\n (updateWidgetClasses)=\"updateWidgetClasses(widget, $event)\"\n ></c8y-dynamic-component>\n </c8y-dashboard-child>\n </c8y-dashboard>\n </ng-container>\n</ng-container>\n\n" }]
24722
24715
  }], ctorParameters: function () { return [{ type: DynamicComponentService }]; }, propDecorators: { widgets: [{
24723
24716
  type: Input
24724
24717
  }], context: [{
@@ -28785,7 +28778,9 @@ class MeasurementRealtimeService extends RealtimeService {
28785
28778
  map(result => !emitNullIfInitialValuesWereNotFound || result.data.length ? result.data : [null]),
28786
28779
  // reverse required, so that measurements are received ordered by time (ascending).
28787
28780
  // from ensures values are sent as single measurements and not a measurement array.
28788
- switchMap(result => from(result.reverse())));
28781
+ // TODO: replace `[...result].reverse()` with `result.toReversed()` once es2023 is available.
28782
+ // Had to clone the result array as otherwise reverse may alternate the array multiple times if the observable is subscribed multiple times.
28783
+ switchMap(result => from([...result].reverse())));
28789
28784
  }
28790
28785
  channel() {
28791
28786
  return '/measurements/*';