@c8y/ngx-components 1023.71.1 → 1023.75.1
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.
- package/asset-properties/index.d.ts +19 -1
- package/asset-properties/index.d.ts.map +1 -1
- package/cockpit-config/index.d.ts +4 -3
- package/cockpit-config/index.d.ts.map +1 -1
- package/context-dashboard/index.d.ts +202 -4
- package/context-dashboard/index.d.ts.map +1 -1
- package/datapoints-export-selector/index.d.ts +8 -1
- package/datapoints-export-selector/index.d.ts.map +1 -1
- package/device-profile/index.d.ts +8 -1
- package/device-profile/index.d.ts.map +1 -1
- package/events/cockpit/index.d.ts +6 -0
- package/events/cockpit/index.d.ts.map +1 -0
- package/events/devicemanagement/index.d.ts +6 -0
- package/events/devicemanagement/index.d.ts.map +1 -0
- package/events/events-timeline/index.d.ts +10 -10
- package/events/events-timeline/index.d.ts.map +1 -1
- package/events/index.d.ts +363 -5
- package/events/index.d.ts.map +1 -1
- package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs +1 -1
- package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-alarms.mjs +1 -1
- package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-asset-properties.mjs +2 -2
- package/fesm2022/c8y-ngx-components-asset-properties.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-auth-configuration.mjs +1 -1
- package/fesm2022/c8y-ngx-components-auth-configuration.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-shared-lazy-add-branding-modal.mjs +1 -1
- package/fesm2022/c8y-ngx-components-branding-shared-lazy-add-branding-modal.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs +2 -2
- package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-cockpit-config.mjs +8 -11
- package/fesm2022/c8y-ngx-components-cockpit-config.mjs.map +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-alarm-count-config.component-CPLDClTp.mjs → c8y-ngx-components-computed-asset-properties-alarm-count-config.component-DX9Rgjgl.mjs} +2 -2
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-alarm-count-config.component-CPLDClTp.mjs.map → c8y-ngx-components-computed-asset-properties-alarm-count-config.component-DX9Rgjgl.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-9be_iMQg.mjs → c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-CRpLJ5H7.mjs} +8 -8
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-9be_iMQg.mjs.map → c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-CRpLJ5H7.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-B2em01_W.mjs → c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-2rDsrxcs.mjs} +2 -2
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-B2em01_W.mjs.map → c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-2rDsrxcs.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-event-count-config.component-CQuGa1RI.mjs → c8y-ngx-components-computed-asset-properties-event-count-config.component-BJNoqWZf.mjs} +2 -2
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-event-count-config.component-CQuGa1RI.mjs.map → c8y-ngx-components-computed-asset-properties-event-count-config.component-BJNoqWZf.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-CkmurxJv.mjs → c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-DYac6foX.mjs} +3 -3
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-CkmurxJv.mjs.map → c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-DYac6foX.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-last-measurement-config.component-CTK9zNUh.mjs → c8y-ngx-components-computed-asset-properties-last-measurement-config.component-3yTe6lIr.mjs} +3 -3
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-last-measurement-config.component-CTK9zNUh.mjs.map → c8y-ngx-components-computed-asset-properties-last-measurement-config.component-3yTe6lIr.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties.mjs +1 -1
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-DsCDppJx.mjs → c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-C7yXSDYC.mjs} +3 -3
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-DsCDppJx.mjs.map → c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-C7yXSDYC.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-general-settings.component-RdLW5nde.mjs → c8y-ngx-components-context-dashboard-dashboard-general-settings.component-w8N16Z3t.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-general-settings.component-RdLW5nde.mjs.map → c8y-ngx-components-context-dashboard-dashboard-general-settings.component-w8N16Z3t.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +561 -21
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +2 -2
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-library-details.mjs +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-library-details.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +41 -8
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-device-profile.mjs +38 -12
- package/fesm2022/c8y-ngx-components-device-profile.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ecosystem-license-confirm.mjs +1 -1
- package/fesm2022/c8y-ngx-components-ecosystem-license-confirm.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs +1 -1
- package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-ecosystem.mjs +1 -1
- package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-events-cockpit.mjs +54 -0
- package/fesm2022/c8y-ngx-components-events-cockpit.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-events-devicemanagement.mjs +79 -0
- package/fesm2022/c8y-ngx-components-events-devicemanagement.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-events-events-timeline.mjs +30 -23
- package/fesm2022/c8y-ngx-components-events-events-timeline.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-events.mjs +1080 -4
- package/fesm2022/c8y-ngx-components-events.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-file-preview.mjs +48 -41
- package/fesm2022/c8y-ngx-components-file-preview.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-files-repository.mjs +1 -1
- package/fesm2022/c8y-ngx-components-files-repository.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-global-context.mjs +68 -34
- package/fesm2022/c8y-ngx-components-global-context.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-interval-picker.mjs +3 -3
- package/fesm2022/c8y-ngx-components-interval-picker.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-location.mjs +1 -1
- package/fesm2022/c8y-ngx-components-location.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-operation-picker.mjs +1 -1
- package/fesm2022/c8y-ngx-components-operation-picker.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs +1 -1
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-device-profile.mjs +1 -1
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-device-profile.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-software.mjs +1 -1
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-software.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-protocol-lpwan.mjs +5 -5
- package/fesm2022/c8y-ngx-components-protocol-lpwan.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-protocol-opcua.mjs +2 -2
- package/fesm2022/c8y-ngx-components-protocol-opcua.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-shared.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-shared.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-vnc-remote-access-vnc-endpoint-modal.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-vnc-remote-access-vnc-endpoint-modal.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-vnc-vnc-viewer.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-vnc-vnc-viewer.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-repository-firmware.mjs +1 -1
- package/fesm2022/c8y-ngx-components-repository-firmware.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-static-assets-modal.mjs +1 -1
- package/fesm2022/c8y-ngx-components-static-assets-modal.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-time-context.mjs +1 -1
- package/fesm2022/c8y-ngx-components-time-context.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs +1 -1
- package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-event-list.mjs +39 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-event-list.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget.mjs +76 -4
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-events.mjs +236 -0
- package/fesm2022/c8y-ngx-components-widgets-implementations-events.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-widgets-implementations-html-widget.mjs +271 -31
- package/fesm2022/c8y-ngx-components-widgets-implementations-html-widget.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-image.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-image.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-kpi.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-kpi.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-linear-gauge.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-linear-gauge.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +248 -26
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/file-preview/index.d.ts +7 -6
- package/file-preview/index.d.ts.map +1 -1
- package/global-context/index.d.ts +3 -0
- package/global-context/index.d.ts.map +1 -1
- package/index.d.ts +106 -11
- package/index.d.ts.map +1 -1
- package/locales/de.po +117 -3
- package/locales/es.po +117 -3
- package/locales/fr.po +117 -3
- package/locales/ja_JP.po +117 -3
- package/locales/ko.po +117 -3
- package/locales/locales.pot +117 -3
- package/locales/nl.po +117 -3
- package/locales/pl.po +117 -3
- package/locales/pt_BR.po +117 -3
- package/locales/zh_CN.po +117 -3
- package/locales/zh_TW.po +117 -3
- package/package.json +1 -1
- package/widgets/definitions/event-list/index.d.ts +44 -1
- package/widgets/definitions/event-list/index.d.ts.map +1 -1
- package/widgets/implementations/alarms/index.d.ts +2 -0
- package/widgets/implementations/alarms/index.d.ts.map +1 -1
- package/widgets/implementations/events/index.d.ts +89 -0
- package/widgets/implementations/events/index.d.ts.map +1 -0
- package/widgets/implementations/html-widget/index.d.ts +69 -9
- package/widgets/implementations/html-widget/index.d.ts.map +1 -1
|
@@ -1,35 +1,37 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Component, inject, InjectionToken, EventEmitter, Output, Input, signal, DestroyRef, TemplateRef, ViewChild, Optional, Inject, HostListener, input, HostBinding, NgModule } from '@angular/core';
|
|
2
|
+
import { Injectable, Component, inject, InjectionToken, EventEmitter, Output, Input, signal, DestroyRef, TemplateRef, ViewChild, Optional, Inject, HostListener, input, HostBinding, NgModule, Injector, runInInjectionContext, ChangeDetectionStrategy } from '@angular/core';
|
|
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, C8yTranslateDirective, DynamicComponentModule, DynamicComponentComponent, sortByPriority, isPromise, CoreModule, WIDGET_CONFIGURATION_GRID_SIZE, HighlightComponent, EmptyStateComponent, FormGroupComponent, RequiredInputPlaceholderDirective, ProductExperienceDirective, ResizableGridComponent, DashboardChildChange, CopyDashboardDisabledReason, TitleComponent, ActionBarItemComponent, HelpComponent, WidgetsDashboardComponent, DatePipe, hookRoute, hookTab, PreviewService, hookNavigator } 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, PreviewService, hookNavigator, ManagedObjectRealtimeService, BottomDrawerService, ClipboardService, InputGroupEditableComponent, MessageDirective } from '@c8y/ngx-components';
|
|
5
5
|
import * as i1 from '@angular/router';
|
|
6
6
|
import { RouterOutlet, ActivatedRoute, RouterModule } from '@angular/router';
|
|
7
|
-
import { of, Subject, from, combineLatest, map as map$1, merge, BehaviorSubject, tap as tap$1, withLatestFrom, mergeMap as mergeMap$1, shareReplay as shareReplay$1, scan, debounceTime, isObservable, iif, timer, filter as filter$1, switchMap as switchMap$1, take } from 'rxjs';
|
|
7
|
+
import { of, Subject, from, combineLatest, map as map$1, merge, BehaviorSubject, tap as tap$1, withLatestFrom, mergeMap as mergeMap$1, shareReplay as shareReplay$1, scan, debounceTime, isObservable, iif, timer, filter as filter$1, switchMap as switchMap$1, take, forkJoin, firstValueFrom } from 'rxjs';
|
|
8
8
|
import { gettext } from '@c8y/ngx-components/gettext';
|
|
9
9
|
import { __decorate, __metadata } from 'tslib';
|
|
10
10
|
import * as i3 from '@angular/common';
|
|
11
11
|
import { NgTemplateOutlet, CommonModule, NgClass, AsyncPipe, NgIf, NgForOf, NgFor } from '@angular/common';
|
|
12
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
12
|
+
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
13
13
|
import * as i6 from '@c8y/ngx-components/context-dashboard-state';
|
|
14
14
|
import * as i2$1 from '@ngx-translate/core';
|
|
15
|
-
import { assign, pick, isEmpty, cloneDeep, some, keys, keyBy, has, set, reduce, forEach, get, isEqual, clone, merge as merge$1, omit, sortBy, isNull, escapeRegExp, findIndex, kebabCase, every } from 'lodash-es';
|
|
15
|
+
import { assign, pick, isEmpty, cloneDeep, some, keys, keyBy, has, set, reduce, forEach, get, isEqual, clone, merge as merge$1, omit, sortBy, isNull, escapeRegExp, findIndex, kebabCase, every, words, camelCase } from 'lodash-es';
|
|
16
16
|
import * as i2$2 from 'ngx-bootstrap/popover';
|
|
17
17
|
import { PopoverModule, PopoverDirective } from 'ngx-bootstrap/popover';
|
|
18
18
|
import * as i1$1 from '@c8y/client';
|
|
19
19
|
import { QueriesUtil, InventoryService } from '@c8y/client';
|
|
20
|
-
import { tap, map, catchError, throwIfEmpty, filter, mergeMap, toArray, first, distinctUntilChanged, shareReplay, switchMap } from 'rxjs/operators';
|
|
21
|
-
import * as
|
|
20
|
+
import { tap, map, catchError, throwIfEmpty, filter, mergeMap, toArray, first, distinctUntilChanged, shareReplay, switchMap, startWith, take as take$1 } from 'rxjs/operators';
|
|
21
|
+
import * as i1$2 from '@angular/forms';
|
|
22
22
|
import { Validators, NgForm, ControlContainer, FormsModule } from '@angular/forms';
|
|
23
23
|
import * as i2$3 from 'ngx-bootstrap/collapse';
|
|
24
24
|
import { CollapseDirective, CollapseModule } from 'ngx-bootstrap/collapse';
|
|
25
|
-
import * as i1$
|
|
25
|
+
import * as i1$3 from '@c8y/ngx-components/assets-navigator';
|
|
26
26
|
import { AssetSelectorModule } from '@c8y/ngx-components/assets-navigator';
|
|
27
|
+
import * as i2$4 from 'ngx-bootstrap/tooltip';
|
|
27
28
|
import { TooltipDirective, TooltipModule } from 'ngx-bootstrap/tooltip';
|
|
28
29
|
import { IconSelectorModule } from '@c8y/ngx-components/icon-selector';
|
|
29
|
-
import * as i1$
|
|
30
|
+
import * as i1$4 from 'ngx-bootstrap/dropdown';
|
|
30
31
|
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
|
31
32
|
import { defaultWidgetIds } from '@c8y/ngx-components/widgets/definitions';
|
|
32
33
|
import { GlobalContextWidgetWrapperComponent, ConfigModeControlsComponent } from '@c8y/ngx-components/global-context';
|
|
34
|
+
import { AssetPropertiesService, ComputedPropertiesService, AssetPropertySelectorDrawerComponent, AssetPropertyValuePipe } from '@c8y/ngx-components/asset-properties';
|
|
33
35
|
|
|
34
36
|
const newDashboardTab = {
|
|
35
37
|
featureId: 'newDashboard',
|
|
@@ -1170,12 +1172,12 @@ class DashboardDetailService {
|
|
|
1170
1172
|
children: dashboard?.children || {}
|
|
1171
1173
|
});
|
|
1172
1174
|
}
|
|
1173
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DashboardDetailService, deps: [{ token:
|
|
1175
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DashboardDetailService, deps: [{ token: i1$2.FormBuilder }, { token: i2$1.TranslateService }, { token: i2.TabsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1174
1176
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DashboardDetailService }); }
|
|
1175
1177
|
}
|
|
1176
1178
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DashboardDetailService, decorators: [{
|
|
1177
1179
|
type: Injectable
|
|
1178
|
-
}], ctorParameters: () => [{ type:
|
|
1180
|
+
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: i2$1.TranslateService }, { type: i2.TabsService }] });
|
|
1179
1181
|
|
|
1180
1182
|
class DashboardDetailComponent {
|
|
1181
1183
|
constructor(contextDashboardService, translateService, contextRoute, activatedRoute, tabsService, router, inventory, route, dashboardDetailService, appState, groupService, modal, gainsightService) {
|
|
@@ -2004,7 +2006,7 @@ class WidgetAssetSelectorComponent {
|
|
|
2004
2006
|
this.widgetConfigService.updateConfig({ device });
|
|
2005
2007
|
}
|
|
2006
2008
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: WidgetAssetSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2007
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", 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 @if (widgetConfigService.isDeviceTypeDashboard$ | async) {\n <div class=\"alert alert-info m-4\">\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 @if (!isRequired) {\n <div class=\"p-t-8\">\n <p translate>Asset selection is optional for this widget.</p>\n @if (!selectedDevice) {\n <button\n class=\"btn btn-primary btn-sm m-t-8 text-truncate\"\n (click)=\"selectCurrentContext()\"\n ngNonBindable\n translate\n [translateParams]=\"{\n deviceName:\n (widgetConfigService.currentConfig$ | async)?.settings?.context?.name ||\n (deviceWithIdTpl\n | translate\n : {\n id: (widgetConfigService.currentConfig$ | async)?.settings?.context?.id\n })\n }\"\n >\n Use context asset \"{{ deviceName }}\"\n </button>\n }\n @if (selectedDevice) {\n <button\n class=\"btn btn-default btn-sm m-t-8 text-truncate\"\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 }\n </div>\n }\n </div>\n }\n @if (!(widgetConfigService.isDeviceTypeDashboard$ | async) && assetSelectorConfig) {\n <c8y-asset-selector-miller\n class=\"d-block bg-inherit p-relative\"\n name=\"configAsset\"\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\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 @if (\n selectedDevice &&\n (!(widgetConfigService.isDeviceTypeDashboard$ | async) ||\n (!isRequired && (widgetConfigService.isDeviceTypeDashboard$ | async)))\n ) {\n <button\n class=\"btn-clean text-12 m-r-4\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n @if (selectedDevice) {\n <span\n class=\"text-truncate\"\n title=\"{{\n selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id })\n }}\"\n >\n {{ selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id }) }}\n </span>\n }\n @if (!selectedDevice) {\n <span translate>No asset selected</span>\n }\n </span>\n </c8y-widget-config-feedback>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i1$
|
|
2009
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", 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 @if (widgetConfigService.isDeviceTypeDashboard$ | async) {\n <div class=\"alert alert-info m-4\">\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 @if (!isRequired) {\n <div class=\"p-t-8\">\n <p translate>Asset selection is optional for this widget.</p>\n @if (!selectedDevice) {\n <button\n class=\"btn btn-primary btn-sm m-t-8 text-truncate\"\n (click)=\"selectCurrentContext()\"\n ngNonBindable\n translate\n [translateParams]=\"{\n deviceName:\n (widgetConfigService.currentConfig$ | async)?.settings?.context?.name ||\n (deviceWithIdTpl\n | translate\n : {\n id: (widgetConfigService.currentConfig$ | async)?.settings?.context?.id\n })\n }\"\n >\n Use context asset \"{{ deviceName }}\"\n </button>\n }\n @if (selectedDevice) {\n <button\n class=\"btn btn-default btn-sm m-t-8 text-truncate\"\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 }\n </div>\n }\n </div>\n }\n @if (!(widgetConfigService.isDeviceTypeDashboard$ | async) && assetSelectorConfig) {\n <c8y-asset-selector-miller\n class=\"d-block bg-inherit p-relative\"\n name=\"configAsset\"\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\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 @if (\n selectedDevice &&\n (!(widgetConfigService.isDeviceTypeDashboard$ | async) ||\n (!isRequired && (widgetConfigService.isDeviceTypeDashboard$ | async)))\n ) {\n <button\n class=\"btn-clean text-12 m-r-4\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n (click)=\"selectedDevice = null; updateConfig(null)\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n @if (selectedDevice) {\n <span\n class=\"text-truncate\"\n title=\"{{\n selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id })\n }}\"\n >\n {{ selectedDevice.name || (deviceWithIdTpl | translate: { id: selectedDevice.id }) }}\n </span>\n }\n @if (!selectedDevice) {\n <span translate>No asset selected</span>\n }\n </span>\n </c8y-widget-config-feedback>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i1$3.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { kind: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); }
|
|
2008
2010
|
}
|
|
2009
2011
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: WidgetAssetSelectorComponent, decorators: [{
|
|
2010
2012
|
type: Component,
|
|
@@ -2091,6 +2093,41 @@ class WidgetConfigService {
|
|
|
2091
2093
|
* Indicates if the selected widget is placed on a device type dashboard.
|
|
2092
2094
|
*/
|
|
2093
2095
|
this.isDeviceTypeDashboard$ = this._isDeviceTypeDashboard$.asObservable();
|
|
2096
|
+
/**
|
|
2097
|
+
* A bus for broadcasting {@link WidgetConfigNotification} events between independent
|
|
2098
|
+
* widget config sections during an active configuration session.
|
|
2099
|
+
*
|
|
2100
|
+
* **Who emits:** Any config section component (or its service) that needs to
|
|
2101
|
+
* inform other sections about a state change — for example,
|
|
2102
|
+
* `AssetPropertyMappingsComponent` emits an
|
|
2103
|
+
* `AssetPropertyMappingKeyRenamedNotification` whenever a mapping key is renamed
|
|
2104
|
+
* so that referencing sections can update their stored keys.
|
|
2105
|
+
*
|
|
2106
|
+
* **Who subscribes:** Config section components that hold references to data owned
|
|
2107
|
+
* by other sections. Subscribers should filter by `type` and silently ignore
|
|
2108
|
+
* unknown variants to stay forward-compatible:
|
|
2109
|
+
*
|
|
2110
|
+
* ```ts
|
|
2111
|
+
* this.widgetConfigService.notify$
|
|
2112
|
+
* .pipe(takeUntil(this.destroy$))
|
|
2113
|
+
* .subscribe(notification => {
|
|
2114
|
+
* if (notification.type === 'asset-property-mapping-key-renamed') {
|
|
2115
|
+
* // handle rename
|
|
2116
|
+
* }
|
|
2117
|
+
* // ignore other types
|
|
2118
|
+
* });
|
|
2119
|
+
* ```
|
|
2120
|
+
*
|
|
2121
|
+
* **Subscription management:** Each subscriber is responsible for unsubscribing
|
|
2122
|
+
* (e.g. via `takeUntil(destroy$)` or `DestroyRef`). The subject itself is never
|
|
2123
|
+
* completed by the service — it lives for the lifetime of the service instance.
|
|
2124
|
+
*
|
|
2125
|
+
* **Unknown notification types:** Because `WidgetConfigNotification` is a
|
|
2126
|
+
* discriminated union that may grow over time, always guard with an `if`/`switch`
|
|
2127
|
+
* on `type` rather than exhaustive checks, so that future additions do not break
|
|
2128
|
+
* existing subscribers.
|
|
2129
|
+
*/
|
|
2130
|
+
this.notify$ = new Subject();
|
|
2094
2131
|
/**
|
|
2095
2132
|
* The current configuration of the selected widget as observable.
|
|
2096
2133
|
* Only to read the value. Use `updateConfig` to update the configuration.
|
|
@@ -2379,7 +2416,7 @@ class AppearanceSettingsComponent {
|
|
|
2379
2416
|
return value;
|
|
2380
2417
|
}
|
|
2381
2418
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AppearanceSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2382
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: AppearanceSettingsComponent, isStandalone: true, selector: "c8y-appearance-settings", inputs: { themeClass: "themeClass", headerClass: "headerClass", defaultThemeClass: "defaultThemeClass", defaultHeaderClass: "defaultHeaderClass", dashboardSettings: "dashboardSettings", possibleStylingTheme: "possibleStylingTheme", possibleStylingHeader: "possibleStylingHeader", columns: "columns" }, outputs: { themeClassChange: "themeClassChange", headerClassChange: "headerClassChange", onChange: "onChange" }, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-lg-{{ 12 / columns }} col-xs-12\">\n <fieldset class=\"c8y-fieldset c8y-fieldset--lg\">\n <legend *ngIf=\"dashboardSettings\">{{ 'Default theme' | translate }}</legend>\n <legend *ngIf=\"!dashboardSettings\">{{ 'Theme' | translate }}</legend>\n <ul class=\"list-group\">\n <li\n class=\"list-group-item d-flex a-i-center p-l-0 p-r-0 fit-w\"\n *ngFor=\"let themeClassItem of possibleStylingTheme; let i = index\"\n >\n <div\n class=\"list-item-checkbox\"\n style=\"max-width: calc(100% - 24px)\"\n >\n <label class=\"c8y-radio\">\n <input\n name=\"content\"\n type=\"radio\"\n [id]=\"'groupradiocontentclass' + i\"\n [value]=\"themeClassItem.class\"\n [ngModel]=\"themeClass\"\n (click)=\"themeClassClick(themeClassItem.class)\"\n />\n <span></span>\n <span\n class=\"text-truncate\"\n title=\"{{ themeClassItem.label | translate }}{{\n themeClassItem.class === defaultThemeClass\n ? ' | ' + (dashboardDefaultLabel | translate)\n : ''\n }}\"\n >\n <span>{{ themeClassItem.label | translate }}</span>\n <br />\n <small\n class=\"text-muted\"\n *ngIf=\"themeClassItem.class === defaultThemeClass\"\n >\n {{ dashboardDefaultLabel | translate }}\n </small>\n </span>\n </label>\n </div>\n\n <button\n class=\"btn-help btn-help--sm m-l-auto\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ themeClassItem.description | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </li>\n </ul>\n </fieldset>\n </div>\n <div class=\"col-lg-{{ 12 / columns }} col-xs-12\">\n <fieldset class=\"c8y-fieldset c8y-fieldset--lg\">\n <legend *ngIf=\"dashboardSettings\">\n {{ 'Default widget header style' | translate }}\n </legend>\n <legend *ngIf=\"!dashboardSettings\">\n {{ 'Widget header style' | translate }}\n </legend>\n <ul class=\"list-group\">\n <li\n class=\"list-group-item d-flex a-i-center p-l-0 p-r-0\"\n *ngFor=\"let headerClassItem of possibleStylingHeader; let i = index\"\n >\n <div\n class=\"list-item-checkbox\"\n style=\"max-width: calc(100% - 24px)\"\n >\n <label class=\"c8y-radio\">\n <input\n name=\"header\"\n type=\"radio\"\n [id]=\"'groupradioheaderclass' + i\"\n [value]=\"headerClassItem.class\"\n [ngModel]=\"headerClass\"\n (click)=\"headerClassClick(headerClassItem.class)\"\n />\n <span></span>\n <span\n class=\"text-truncate\"\n title=\"{{ headerClassItem.label | translate }}{{\n headerClassItem.class === defaultHeaderClass\n ? ' | ' + (dashboardDefaultLabel | translate)\n : ''\n }}\"\n >\n <span>{{ headerClassItem.label | translate }}</span>\n <br />\n <small\n class=\"text-muted\"\n *ngIf=\"headerClassItem.class === defaultHeaderClass\"\n >\n {{ dashboardDefaultLabel | translate }}\n </small>\n </span>\n </label>\n </div>\n <button\n class=\"btn-help btn-help--sm m-l-auto\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ headerClassItem.description | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </li>\n </ul>\n </fieldset>\n </div>\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type:
|
|
2419
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: AppearanceSettingsComponent, isStandalone: true, selector: "c8y-appearance-settings", inputs: { themeClass: "themeClass", headerClass: "headerClass", defaultThemeClass: "defaultThemeClass", defaultHeaderClass: "defaultHeaderClass", dashboardSettings: "dashboardSettings", possibleStylingTheme: "possibleStylingTheme", possibleStylingHeader: "possibleStylingHeader", columns: "columns" }, outputs: { themeClassChange: "themeClassChange", headerClassChange: "headerClassChange", onChange: "onChange" }, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-lg-{{ 12 / columns }} col-xs-12\">\n <fieldset class=\"c8y-fieldset c8y-fieldset--lg\">\n <legend *ngIf=\"dashboardSettings\">{{ 'Default theme' | translate }}</legend>\n <legend *ngIf=\"!dashboardSettings\">{{ 'Theme' | translate }}</legend>\n <ul class=\"list-group\">\n <li\n class=\"list-group-item d-flex a-i-center p-l-0 p-r-0 fit-w\"\n *ngFor=\"let themeClassItem of possibleStylingTheme; let i = index\"\n >\n <div\n class=\"list-item-checkbox\"\n style=\"max-width: calc(100% - 24px)\"\n >\n <label class=\"c8y-radio\">\n <input\n name=\"content\"\n type=\"radio\"\n [id]=\"'groupradiocontentclass' + i\"\n [value]=\"themeClassItem.class\"\n [ngModel]=\"themeClass\"\n (click)=\"themeClassClick(themeClassItem.class)\"\n />\n <span></span>\n <span\n class=\"text-truncate\"\n title=\"{{ themeClassItem.label | translate }}{{\n themeClassItem.class === defaultThemeClass\n ? ' | ' + (dashboardDefaultLabel | translate)\n : ''\n }}\"\n >\n <span>{{ themeClassItem.label | translate }}</span>\n <br />\n <small\n class=\"text-muted\"\n *ngIf=\"themeClassItem.class === defaultThemeClass\"\n >\n {{ dashboardDefaultLabel | translate }}\n </small>\n </span>\n </label>\n </div>\n\n <button\n class=\"btn-help btn-help--sm m-l-auto\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ themeClassItem.description | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </li>\n </ul>\n </fieldset>\n </div>\n <div class=\"col-lg-{{ 12 / columns }} col-xs-12\">\n <fieldset class=\"c8y-fieldset c8y-fieldset--lg\">\n <legend *ngIf=\"dashboardSettings\">\n {{ 'Default widget header style' | translate }}\n </legend>\n <legend *ngIf=\"!dashboardSettings\">\n {{ 'Widget header style' | translate }}\n </legend>\n <ul class=\"list-group\">\n <li\n class=\"list-group-item d-flex a-i-center p-l-0 p-r-0\"\n *ngFor=\"let headerClassItem of possibleStylingHeader; let i = index\"\n >\n <div\n class=\"list-item-checkbox\"\n style=\"max-width: calc(100% - 24px)\"\n >\n <label class=\"c8y-radio\">\n <input\n name=\"header\"\n type=\"radio\"\n [id]=\"'groupradioheaderclass' + i\"\n [value]=\"headerClassItem.class\"\n [ngModel]=\"headerClass\"\n (click)=\"headerClassClick(headerClassItem.class)\"\n />\n <span></span>\n <span\n class=\"text-truncate\"\n title=\"{{ headerClassItem.label | translate }}{{\n headerClassItem.class === defaultHeaderClass\n ? ' | ' + (dashboardDefaultLabel | translate)\n : ''\n }}\"\n >\n <span>{{ headerClassItem.label | translate }}</span>\n <br />\n <small\n class=\"text-muted\"\n *ngIf=\"headerClassItem.class === defaultHeaderClass\"\n >\n {{ dashboardDefaultLabel | translate }}\n </small>\n </span>\n </label>\n </div>\n <button\n class=\"btn-help btn-help--sm m-l-auto\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ headerClassItem.description | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n ></button>\n </li>\n </ul>\n </fieldset>\n </div>\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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: i1$2.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i2$2.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
2383
2420
|
}
|
|
2384
2421
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AppearanceSettingsComponent, decorators: [{
|
|
2385
2422
|
type: Component,
|
|
@@ -2749,7 +2786,7 @@ class WidgetConfigComponent {
|
|
|
2749
2786
|
return widgetConfig;
|
|
2750
2787
|
}
|
|
2751
2788
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: WidgetConfigComponent, deps: [{ token: WidgetService }, { token: i2.BottomDrawerRef }, { token: ContextDashboardService }, { token: WidgetConfigService }, { token: i2.BottomDrawerService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2752
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: WidgetConfigComponent, isStandalone: true, selector: "c8y-widget-config", host: { listeners: { "document:keydown.escape": "onEscapePress($event)" }, classAttribute: "d-contents" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "configForm", first: true, predicate: ["configForm"], descendants: true }], ngImport: i0, template: "<!-- select widget -->\n@if (!(widgetConfigService.selected$ | async)) {\n <div class=\"card-header j-c-center separator\">\n <div\n class=\"h4 text-center\"\n id=\"drawerTitle\"\n >\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 #searchInput\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 @for (cmp of searchResult || components; track cmp) {\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 (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n @if (!cmp.previewImage) {\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n } @else {\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n }\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 }\n @if (searchResult && searchResult.length === 0) {\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 >\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 }\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}\n\n<!-- widget configuration -->\n@if (!!(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 @if (selected) {\n <div class=\"p-t-8\">\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n }\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [collapsible]=\"false\"\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=\"widgetTitle\"\n type=\"text\"\n required\n [(ngModel)]=\"widgetTitle\"\n (ngModelChange)=\"onWidgetTitleChange($event)\"\n />\n </c8y-form-group>\n </div>\n\n @if (!(widgetConfigService.hasConfig$ | async)) {\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 ></c8y-ui-empty-state>\n }\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n @if (widgetConfigService.hasConfig$ | async) {\n @if (widgetConfigService.providers$ | async; as providers) {\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n }\n }\n </form>\n </div>\n </div>\n\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\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}\n", dependencies: [{ 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: 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: "component", type: ResizableGridComponent, selector: "c8y-resizable-grid", inputs: ["leftColumnWidth", "trackId", "collapseThreshold", "collapsible"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
|
|
2789
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: WidgetConfigComponent, isStandalone: true, selector: "c8y-widget-config", host: { listeners: { "document:keydown.escape": "onEscapePress($event)" }, classAttribute: "d-contents" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "configForm", first: true, predicate: ["configForm"], descendants: true }], ngImport: i0, template: "<!-- select widget -->\n@if (!(widgetConfigService.selected$ | async)) {\n <div class=\"card-header j-c-center separator\">\n <div\n class=\"h4 text-center\"\n id=\"drawerTitle\"\n >\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 #searchInput\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 @for (cmp of searchResult || components; track cmp) {\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 (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n @if (!cmp.previewImage) {\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n } @else {\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n }\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 }\n @if (searchResult && searchResult.length === 0) {\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 >\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 }\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}\n\n<!-- widget configuration -->\n@if (!!(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 @if (selected) {\n <div class=\"p-t-8\">\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n }\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [collapsible]=\"false\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.DEFAULT\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=\"widgetTitle\"\n type=\"text\"\n required\n [(ngModel)]=\"widgetTitle\"\n (ngModelChange)=\"onWidgetTitleChange($event)\"\n />\n </c8y-form-group>\n </div>\n\n @if (!(widgetConfigService.hasConfig$ | async)) {\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 ></c8y-ui-empty-state>\n }\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n @if (widgetConfigService.hasConfig$ | async) {\n @if (widgetConfigService.providers$ | async; as providers) {\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n }\n }\n </form>\n </div>\n </div>\n\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\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}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.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: 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: "component", type: ResizableGridComponent, selector: "c8y-resizable-grid", inputs: ["leftColumnWidth", "trackId", "collapseThreshold", "collapsible"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
|
|
2753
2790
|
}
|
|
2754
2791
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: WidgetConfigComponent, decorators: [{
|
|
2755
2792
|
type: Component,
|
|
@@ -2768,7 +2805,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2768
2805
|
C8yTranslatePipe,
|
|
2769
2806
|
AsyncPipe,
|
|
2770
2807
|
ResizableGridComponent
|
|
2771
|
-
], standalone: true, template: "<!-- select widget -->\n@if (!(widgetConfigService.selected$ | async)) {\n <div class=\"card-header j-c-center separator\">\n <div\n class=\"h4 text-center\"\n id=\"drawerTitle\"\n >\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 #searchInput\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 @for (cmp of searchResult || components; track cmp) {\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 (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n @if (!cmp.previewImage) {\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n } @else {\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n }\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 }\n @if (searchResult && searchResult.length === 0) {\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 >\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 }\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}\n\n<!-- widget configuration -->\n@if (!!(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 @if (selected) {\n <div class=\"p-t-8\">\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n }\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [collapsible]=\"false\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.
|
|
2808
|
+
], standalone: true, template: "<!-- select widget -->\n@if (!(widgetConfigService.selected$ | async)) {\n <div class=\"card-header j-c-center separator\">\n <div\n class=\"h4 text-center\"\n id=\"drawerTitle\"\n >\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 #searchInput\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 @for (cmp of searchResult || components; track cmp) {\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 (click)=\"select(cmp)\"\n >\n <div\n class=\"border-bottom\"\n role=\"presentation\"\n >\n @if (!cmp.previewImage) {\n <div class=\"h1\"><i c8yIcon=\"file-image-o\"></i></div>\n <small translate>Preview not available</small>\n } @else {\n <img\n class=\"widget-thumbnail\"\n alt=\"{{ cmp.label | translate }}\"\n [src]=\"cmp.previewImage\"\n />\n }\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 }\n @if (searchResult && searchResult.length === 0) {\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 >\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 }\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}\n\n<!-- widget configuration -->\n@if (!!(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 @if (selected) {\n <div class=\"p-t-8\">\n <p>\n {{ selected.description | translate }}\n </p>\n </div>\n }\n </div>\n\n <c8y-resizable-grid\n class=\"min-height-0 flex-grow\"\n [collapsible]=\"false\"\n [trackId]=\"'c8y-widget-resizable-grid-size-' + (widgetConfigService.instanceId$ | async)\"\n [leftColumnWidth]=\"\n (widgetConfigService.currentConfig$ | async)?.settings?.configurationViewGridSize ||\n WIDGET_CONFIGURATION_GRID_SIZE.DEFAULT\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=\"widgetTitle\"\n type=\"text\"\n required\n [(ngModel)]=\"widgetTitle\"\n (ngModelChange)=\"onWidgetTitleChange($event)\"\n />\n </c8y-form-group>\n </div>\n\n @if (!(widgetConfigService.hasConfig$ | async)) {\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 ></c8y-ui-empty-state>\n }\n <div>\n <form\n name=\"form\"\n #configForm=\"ngForm\"\n >\n @if (widgetConfigService.hasConfig$ | async) {\n @if (widgetConfigService.providers$ | async; as providers) {\n <ng-container\n *c8yComponentOutlet=\"widgetConfigRoot; providers: providers\"\n ></ng-container>\n }\n }\n </form>\n </div>\n </div>\n\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\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}\n" }]
|
|
2772
2809
|
}], ctorParameters: () => [{ type: WidgetService }, { type: i2.BottomDrawerRef }, { type: ContextDashboardService }, { type: WidgetConfigService }, { type: i2.BottomDrawerService }, { type: i0.ChangeDetectorRef }], propDecorators: { searchInput: [{
|
|
2773
2810
|
type: ViewChild,
|
|
2774
2811
|
args: ['searchInput', { static: false }]
|
|
@@ -3751,7 +3788,7 @@ class ContextDashboardModule {
|
|
|
3751
3788
|
TooltipModule,
|
|
3752
3789
|
PopoverModule,
|
|
3753
3790
|
AssetSelectorModule,
|
|
3754
|
-
IconSelectorModule, i1$
|
|
3791
|
+
IconSelectorModule, i1$4.BsDropdownModule, i2$3.CollapseModule, RouterModule,
|
|
3755
3792
|
AppearanceSettingsComponent,
|
|
3756
3793
|
TypeDashboardInfoComponent,
|
|
3757
3794
|
WidgetPreviewComponent,
|
|
@@ -3777,13 +3814,13 @@ class ContextDashboardModule {
|
|
|
3777
3814
|
hookRoute([
|
|
3778
3815
|
{
|
|
3779
3816
|
path: DashboardDetailsTabId.GENERAL,
|
|
3780
|
-
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-general-settings.component-
|
|
3817
|
+
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-general-settings.component-w8N16Z3t.mjs').then(m => m.DashboardGeneralSettingsComponent),
|
|
3781
3818
|
outlet: DASHBOARD_DETAILS_OUTLET,
|
|
3782
3819
|
context: ViewContext.Dashboard
|
|
3783
3820
|
},
|
|
3784
3821
|
{
|
|
3785
3822
|
path: DashboardDetailsTabId.APPEARANCE,
|
|
3786
|
-
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-
|
|
3823
|
+
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-C7yXSDYC.mjs').then(m => m.DashboardAppearanceSettingsComponent),
|
|
3787
3824
|
outlet: DASHBOARD_DETAILS_OUTLET,
|
|
3788
3825
|
context: ViewContext.Dashboard
|
|
3789
3826
|
},
|
|
@@ -3850,13 +3887,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
3850
3887
|
hookRoute([
|
|
3851
3888
|
{
|
|
3852
3889
|
path: DashboardDetailsTabId.GENERAL,
|
|
3853
|
-
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-general-settings.component-
|
|
3890
|
+
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-general-settings.component-w8N16Z3t.mjs').then(m => m.DashboardGeneralSettingsComponent),
|
|
3854
3891
|
outlet: DASHBOARD_DETAILS_OUTLET,
|
|
3855
3892
|
context: ViewContext.Dashboard
|
|
3856
3893
|
},
|
|
3857
3894
|
{
|
|
3858
3895
|
path: DashboardDetailsTabId.APPEARANCE,
|
|
3859
|
-
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-
|
|
3896
|
+
loadComponent: () => import('./c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-C7yXSDYC.mjs').then(m => m.DashboardAppearanceSettingsComponent),
|
|
3860
3897
|
outlet: DASHBOARD_DETAILS_OUTLET,
|
|
3861
3898
|
context: ViewContext.Dashboard
|
|
3862
3899
|
},
|
|
@@ -4419,9 +4456,512 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
4419
4456
|
type: Input
|
|
4420
4457
|
}] } });
|
|
4421
4458
|
|
|
4459
|
+
class AssetPropertyMappingsService {
|
|
4460
|
+
constructor() {
|
|
4461
|
+
this.injector = inject(Injector);
|
|
4462
|
+
this.inventory = inject(InventoryService);
|
|
4463
|
+
this.moRealtime = inject(ManagedObjectRealtimeService);
|
|
4464
|
+
this.assetProperties = inject(AssetPropertiesService);
|
|
4465
|
+
this.computedProperties = inject(ComputedPropertiesService);
|
|
4466
|
+
}
|
|
4467
|
+
/**
|
|
4468
|
+
* Creates an Observable stream of asset property values that emits updates with realtime changes.
|
|
4469
|
+
* Uses realtimeControl$ to enable/disable underlying realtime notifications.
|
|
4470
|
+
*
|
|
4471
|
+
* @param mappings - The asset property mappings configuration.
|
|
4472
|
+
* @param realtimeControl$ - Observable that controls realtime notifications (true = enabled, false = disabled, default = enabled).
|
|
4473
|
+
* @returns Observable emitting updated asset property values as they change.
|
|
4474
|
+
*/
|
|
4475
|
+
getValues$(mappings, realtimeControl$ = of(true)) {
|
|
4476
|
+
if (!mappings) {
|
|
4477
|
+
return of({});
|
|
4478
|
+
}
|
|
4479
|
+
const { regular, computed } = this.groupByType(mappings);
|
|
4480
|
+
const _regularByAssetId = this.groupByAssetId(regular);
|
|
4481
|
+
return merge(...computed.map(mapping => this.getComputedPropertyValues$(mapping, realtimeControl$)), ...Object.entries(_regularByAssetId).map(([assetId, mappings]) => this.getRegularPropertyValues$(assetId, mappings, realtimeControl$))).pipe(scan((acc, update) => ({ ...acc, ...update }), {}), startWith({}));
|
|
4482
|
+
}
|
|
4483
|
+
groupByType(mappings) {
|
|
4484
|
+
const regular = [];
|
|
4485
|
+
const computed = [];
|
|
4486
|
+
for (const [name, mapping] of Object.entries(mappings)) {
|
|
4487
|
+
if (!mapping) {
|
|
4488
|
+
continue;
|
|
4489
|
+
}
|
|
4490
|
+
if (mapping.assetProperty) {
|
|
4491
|
+
if (mapping.assetProperty.computed) {
|
|
4492
|
+
computed.push({ name, ...mapping });
|
|
4493
|
+
}
|
|
4494
|
+
else {
|
|
4495
|
+
regular.push({ name, ...mapping });
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
return { regular, computed };
|
|
4500
|
+
}
|
|
4501
|
+
groupByAssetId(mappings) {
|
|
4502
|
+
return mappings.reduce((acc, mapping) => {
|
|
4503
|
+
const assetId = mapping.assetProperty.asset.id;
|
|
4504
|
+
if (!acc[assetId]) {
|
|
4505
|
+
acc[assetId] = [];
|
|
4506
|
+
}
|
|
4507
|
+
acc[assetId].push(mapping);
|
|
4508
|
+
return acc;
|
|
4509
|
+
}, {});
|
|
4510
|
+
}
|
|
4511
|
+
getComputedPropertyValues$(mapping, realtimeControl$) {
|
|
4512
|
+
if (!mapping.assetProperty) {
|
|
4513
|
+
return of(null);
|
|
4514
|
+
}
|
|
4515
|
+
const metadata = {
|
|
4516
|
+
mode: 'realtime',
|
|
4517
|
+
realtimeControl$
|
|
4518
|
+
};
|
|
4519
|
+
const computedValue$ = from(this.inventory.detail(mapping.assetProperty.asset.id, { withLatestValues: true })).pipe(switchMap(({ data: asset }) => from(this.computedProperties.getByName(mapping.assetProperty.name)).pipe(switchMap(definition => {
|
|
4520
|
+
let value = null;
|
|
4521
|
+
runInInjectionContext(definition.injector || this.injector, () => {
|
|
4522
|
+
value = definition.value({
|
|
4523
|
+
config: mapping.assetProperty.config,
|
|
4524
|
+
context: asset,
|
|
4525
|
+
metadata
|
|
4526
|
+
});
|
|
4527
|
+
});
|
|
4528
|
+
if (isObservable(value)) {
|
|
4529
|
+
return value;
|
|
4530
|
+
}
|
|
4531
|
+
else if (value instanceof Promise) {
|
|
4532
|
+
return from(value);
|
|
4533
|
+
}
|
|
4534
|
+
else {
|
|
4535
|
+
return of(value);
|
|
4536
|
+
}
|
|
4537
|
+
}))));
|
|
4538
|
+
return realtimeControl$.pipe(distinctUntilChanged(), switchMap(enabled => (enabled ? computedValue$ : computedValue$.pipe(take$1(1)))), map(value => ({ [mapping.name]: value })), catchError(err => {
|
|
4539
|
+
// eslint-disable-next-line no-console
|
|
4540
|
+
console.warn(`Error in computed property stream for asset ${mapping.assetProperty.asset.id}, property ${mapping.assetProperty.name}:`, err);
|
|
4541
|
+
return of({ [mapping.name]: null });
|
|
4542
|
+
}), shareReplay({ bufferSize: 1, refCount: true }));
|
|
4543
|
+
}
|
|
4544
|
+
getRegularPropertyValues$(assetId, mappings, realtimeControl$) {
|
|
4545
|
+
return realtimeControl$.pipe(distinctUntilChanged(), switchMap(enabled => {
|
|
4546
|
+
if (!enabled) {
|
|
4547
|
+
return from(this.inventory.detail(assetId, { withLatestValues: true })).pipe(map(res => res?.data));
|
|
4548
|
+
}
|
|
4549
|
+
else {
|
|
4550
|
+
return from(this.inventory.detail(assetId, { withLatestValues: true })).pipe(switchMap(initial => this.moRealtime.onAll$(assetId).pipe(map(update => update?.data), startWith(initial?.data))));
|
|
4551
|
+
}
|
|
4552
|
+
}), map(asset => mappings.reduce((acc, mapping) => ({
|
|
4553
|
+
...acc,
|
|
4554
|
+
[mapping.name]: this.getRegularPropertyValue(asset, mapping.assetProperty)
|
|
4555
|
+
}), {})), catchError(err => {
|
|
4556
|
+
// eslint-disable-next-line no-console
|
|
4557
|
+
console.warn(`Error in controlled asset stream for asset ${assetId}:`, err);
|
|
4558
|
+
return of(mappings.reduce((acc, m) => ({ ...acc, [m.name]: null }), {}));
|
|
4559
|
+
}), shareReplay({ bufferSize: 1, refCount: true }));
|
|
4560
|
+
}
|
|
4561
|
+
getRegularPropertyValue(asset, property) {
|
|
4562
|
+
if (!asset || !property) {
|
|
4563
|
+
return null;
|
|
4564
|
+
}
|
|
4565
|
+
let value;
|
|
4566
|
+
if (this.assetProperties.isComplexProperty(property)) {
|
|
4567
|
+
value = asset[property.name];
|
|
4568
|
+
}
|
|
4569
|
+
else if ('keyPath' in property) {
|
|
4570
|
+
value = get(asset, property.keyPath);
|
|
4571
|
+
}
|
|
4572
|
+
else {
|
|
4573
|
+
value = asset[property.name];
|
|
4574
|
+
}
|
|
4575
|
+
return value ?? null;
|
|
4576
|
+
}
|
|
4577
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AssetPropertyMappingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4578
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AssetPropertyMappingsService, providedIn: 'root' }); }
|
|
4579
|
+
}
|
|
4580
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AssetPropertyMappingsService, decorators: [{
|
|
4581
|
+
type: Injectable,
|
|
4582
|
+
args: [{ providedIn: 'root' }]
|
|
4583
|
+
}] });
|
|
4584
|
+
|
|
4585
|
+
const IDENTIFIER_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
4586
|
+
function stripC8yPrefix(s) {
|
|
4587
|
+
return s.startsWith('c8y_') ? s.slice(4) : s;
|
|
4588
|
+
}
|
|
4589
|
+
/**
|
|
4590
|
+
* Returns a semantically meaningful base key for the given asset property.
|
|
4591
|
+
*
|
|
4592
|
+
* - Computed properties with a configured data point (e.g. Last measurement):
|
|
4593
|
+
* strips `c8y_` from fragment and series, deduplicates if they resolve to the
|
|
4594
|
+
* same word (e.g. `c8y_Humidity` / `Humidity` → `humidity`), then camelCases.
|
|
4595
|
+
* - Nested properties with a keyPath longer than one segment:
|
|
4596
|
+
* uses `camelCase` of the joined, `c8y_`-stripped path segments, e.g. `addressCity`.
|
|
4597
|
+
* - All other properties: strips leading `c8y_` and camelCases the name.
|
|
4598
|
+
*/
|
|
4599
|
+
function getPropertyBaseKey(property) {
|
|
4600
|
+
if (property.computed) {
|
|
4601
|
+
const dp = property.config?.dp?.[0];
|
|
4602
|
+
if (dp?.fragment) {
|
|
4603
|
+
const strippedFragment = stripC8yPrefix(dp.fragment);
|
|
4604
|
+
const strippedSeries = stripC8yPrefix(dp.series);
|
|
4605
|
+
const seriesLower = strippedSeries.toLowerCase();
|
|
4606
|
+
const isDuplicate = words(strippedFragment).some(w => w.toLowerCase() === seriesLower);
|
|
4607
|
+
const raw = isDuplicate ? strippedFragment : `${strippedFragment}_${strippedSeries}`;
|
|
4608
|
+
return camelCase(raw);
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
if ('keyPath' in property && Array.isArray(property.keyPath) && property.keyPath.length > 1) {
|
|
4612
|
+
return camelCase(property.keyPath.map(stripC8yPrefix).join('_'));
|
|
4613
|
+
}
|
|
4614
|
+
return camelCase(stripC8yPrefix(property.name));
|
|
4615
|
+
}
|
|
4616
|
+
function escapeForRegExp(key) {
|
|
4617
|
+
return key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
4618
|
+
}
|
|
4619
|
+
/** Wraps key in quotes for bracket notation, choosing the quote style that requires fewest escapes. */
|
|
4620
|
+
function quoteAndEscape(key) {
|
|
4621
|
+
const escaped = key.replace(/\\/g, '\\\\');
|
|
4622
|
+
if (!key.includes("'")) {
|
|
4623
|
+
return `'${escaped}'`;
|
|
4624
|
+
}
|
|
4625
|
+
if (!key.includes('"')) {
|
|
4626
|
+
return `"${escaped}"`;
|
|
4627
|
+
}
|
|
4628
|
+
return `'${escaped.replace(/'/g, "\\'")}'`;
|
|
4629
|
+
}
|
|
4630
|
+
/** How the key would appear inside a JS single-quoted string literal. */
|
|
4631
|
+
function encodeForSingleQuote(key) {
|
|
4632
|
+
return key.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
4633
|
+
}
|
|
4634
|
+
/** How the key would appear inside a JS double-quoted string literal. */
|
|
4635
|
+
function encodeForDoubleQuote(key) {
|
|
4636
|
+
return key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
4637
|
+
}
|
|
4638
|
+
/**
|
|
4639
|
+
* Replaces all references to `oldKey` via `expressionPrefixes` in the given code string with
|
|
4640
|
+
* `newKey`, handling both bracket notation (`prefix?.['key']`, `prefix?.["key"]`) and dot notation
|
|
4641
|
+
* (`prefix?.key`, `prefix.key`).
|
|
4642
|
+
*
|
|
4643
|
+
* Bracket notation matching correctly handles JS string escape sequences (e.g. `['it\'s']`).
|
|
4644
|
+
*
|
|
4645
|
+
* @param code - Source code to transform.
|
|
4646
|
+
* @param oldKey - The property key to rename.
|
|
4647
|
+
* @param newKey - The new property key.
|
|
4648
|
+
* @param expressionPrefixes - One or more expression prefixes to match against (e.g. `['this.c8yProperties', 'c8yProperties']`).
|
|
4649
|
+
*/
|
|
4650
|
+
function renamePropertyKeyInCode(code, oldKey, newKey, expressionPrefixes = ['this.c8yProperties']) {
|
|
4651
|
+
const encodedSingle = encodeForSingleQuote(oldKey);
|
|
4652
|
+
const encodedDouble = encodeForDoubleQuote(oldKey);
|
|
4653
|
+
const escapedDot = escapeForRegExp(oldKey);
|
|
4654
|
+
for (const prefix of expressionPrefixes) {
|
|
4655
|
+
const escapedPrefix = escapeForRegExp(prefix);
|
|
4656
|
+
// Replace bracket notation: prefix?.['oldKey'] and prefix?.["oldKey"] (combined, handles escaped quotes)
|
|
4657
|
+
code = code.replace(new RegExp(`(?<![.\\w$])(${escapedPrefix})(\\?\\.)?\\[(?:'${escapeForRegExp(encodedSingle)}'|"${escapeForRegExp(encodedDouble)}")\\]`, 'g'), (_match, obj, chain) => `${obj}${chain ?? ''}[${quoteAndEscape(newKey)}]`);
|
|
4658
|
+
// Replace dot notation: prefix?.oldKey and prefix.oldKey
|
|
4659
|
+
// Only applicable when the old key is a valid JS identifier.
|
|
4660
|
+
if (IDENTIFIER_REGEX.test(oldKey)) {
|
|
4661
|
+
code = code.replace(new RegExp(`(?<![.\\w$])(${escapedPrefix})(\\??)\\.(${escapedDot})(?=[^\\w$]|$)`, 'g'), (_match, obj, chain, _key) => {
|
|
4662
|
+
if (IDENTIFIER_REGEX.test(newKey)) {
|
|
4663
|
+
return `${obj}${chain}.${newKey}`;
|
|
4664
|
+
}
|
|
4665
|
+
// newKey is not a valid identifier — convert to bracket notation
|
|
4666
|
+
return `${obj}${chain ? '?.' : ''}[${quoteAndEscape(newKey)}]`;
|
|
4667
|
+
});
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
return code;
|
|
4671
|
+
}
|
|
4672
|
+
|
|
4673
|
+
class AssetPropertyMappingsComponent {
|
|
4674
|
+
constructor() {
|
|
4675
|
+
this.widgetConfigService = inject(WidgetConfigService);
|
|
4676
|
+
this.bottomDrawerService = inject(BottomDrawerService);
|
|
4677
|
+
this.inventory = inject(InventoryService);
|
|
4678
|
+
this.clipboardService = inject(ClipboardService);
|
|
4679
|
+
this.alert = inject(AlertService);
|
|
4680
|
+
this.widgetConfigPath = input(['mappings'], ...(ngDevMode ? [{ debugName: "widgetConfigPath" }] : []));
|
|
4681
|
+
this.initialMappings = input({}, ...(ngDevMode ? [{ debugName: "initialMappings" }] : []));
|
|
4682
|
+
this.allowAddingNewMappings = input(true, ...(ngDevMode ? [{ debugName: "allowAddingNewMappings" }] : []));
|
|
4683
|
+
this.allowRenamingMappings = input(true, ...(ngDevMode ? [{ debugName: "allowRenamingMappings" }] : []));
|
|
4684
|
+
this.allowRelabellingMappings = input(true, ...(ngDevMode ? [{ debugName: "allowRelabellingMappings" }] : []));
|
|
4685
|
+
this.allowEditingMappings = input(true, ...(ngDevMode ? [{ debugName: "allowEditingMappings" }] : []));
|
|
4686
|
+
this.allowRemovingMappings = input(true, ...(ngDevMode ? [{ debugName: "allowRemovingMappings" }] : []));
|
|
4687
|
+
this.showLabels = input(true, ...(ngDevMode ? [{ debugName: "showLabels" }] : []));
|
|
4688
|
+
this.showNames = input(true, ...(ngDevMode ? [{ debugName: "showNames" }] : []));
|
|
4689
|
+
this.showAssets = input(true, ...(ngDevMode ? [{ debugName: "showAssets" }] : []));
|
|
4690
|
+
this.showProperties = input(true, ...(ngDevMode ? [{ debugName: "showProperties" }] : []));
|
|
4691
|
+
this.showValues = input(true, ...(ngDevMode ? [{ debugName: "showValues" }] : []));
|
|
4692
|
+
this.actionsColumnSpan = input(3, ...(ngDevMode ? [{ debugName: "actionsColumnSpan" }] : []));
|
|
4693
|
+
/**
|
|
4694
|
+
* Callback to transform a mapping into the text that gets copied to the clipboard.
|
|
4695
|
+
* Exposed as an input so widget config factories can override the default (e.g. to
|
|
4696
|
+
* produce a template expression like `${this.c8yProperties?.temperature}`).
|
|
4697
|
+
*/
|
|
4698
|
+
this.onBeforeCopyMappingToClipboard = input((mapping) => String(mapping.name), ...(ngDevMode ? [{ debugName: "onBeforeCopyMappingToClipboard" }] : []));
|
|
4699
|
+
this.emptyStateTitle = gettext('No asset property mappings');
|
|
4700
|
+
this.emptyStateSubtitle = gettext('Add first asset property mapping.');
|
|
4701
|
+
this.mappings$ = this.widgetConfigService.currentConfig$.pipe(map$1(config => get(config, this.widgetConfigPath())));
|
|
4702
|
+
this.keys$ = this.mappings$.pipe(map$1(mappings => Object.keys(mappings || {}).sort((a, b) => a.localeCompare(b))));
|
|
4703
|
+
this.mappingsSignal = toSignal(this.mappings$, { initialValue: null });
|
|
4704
|
+
this.keysSignal = toSignal(this.keys$, { initialValue: null });
|
|
4705
|
+
this.isDrawerOpen = signal(false, ...(ngDevMode ? [{ debugName: "isDrawerOpen" }] : []));
|
|
4706
|
+
this.labelValidatorCache = new Map();
|
|
4707
|
+
this.nameValidatorCache = new Map();
|
|
4708
|
+
this.assetsCache = new Map();
|
|
4709
|
+
this.resolvedAssets$ = this.mappings$.pipe(switchMap$1(mappings => {
|
|
4710
|
+
const ids = [
|
|
4711
|
+
...new Set(Object.values(mappings || {})
|
|
4712
|
+
.map(m => m?.assetProperty?.asset?.id)
|
|
4713
|
+
.filter((id) => Boolean(id)))
|
|
4714
|
+
];
|
|
4715
|
+
if (!ids.length)
|
|
4716
|
+
return of(new Map(this.assetsCache));
|
|
4717
|
+
return forkJoin(ids.map(id => from(this.getAsset(id)))).pipe(map$1(() => new Map(this.assetsCache)));
|
|
4718
|
+
}));
|
|
4719
|
+
}
|
|
4720
|
+
/** Distributes (12 - actionsColumnSpan) columns evenly among visible row-1 columns (label, name). */
|
|
4721
|
+
get row1ColumnSpans() {
|
|
4722
|
+
return this.distributeColumns([
|
|
4723
|
+
{ key: 'label', visible: this.showLabels() },
|
|
4724
|
+
{ key: 'name', visible: this.showNames() }
|
|
4725
|
+
], 12 - this.actionsColumnSpan());
|
|
4726
|
+
}
|
|
4727
|
+
/** Distributes all 12 columns evenly among visible row-2 columns (asset, property, value). */
|
|
4728
|
+
get row2ColumnSpans() {
|
|
4729
|
+
return this.distributeColumns([
|
|
4730
|
+
{ key: 'asset', visible: this.showAssets() },
|
|
4731
|
+
{ key: 'property', visible: this.showProperties() },
|
|
4732
|
+
{ key: 'value', visible: this.showValues() }
|
|
4733
|
+
], 12);
|
|
4734
|
+
}
|
|
4735
|
+
async ngOnInit() {
|
|
4736
|
+
const config = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4737
|
+
if (!get(config, this.widgetConfigPath())) {
|
|
4738
|
+
const newConfig = { ...config };
|
|
4739
|
+
const mappings = structuredClone(this.initialMappings());
|
|
4740
|
+
for (const [key, mapping] of Object.entries(mappings)) {
|
|
4741
|
+
if (mapping.assetProperty && !mapping.assetProperty.asset) {
|
|
4742
|
+
if (!config.device) {
|
|
4743
|
+
delete mappings[key];
|
|
4744
|
+
continue;
|
|
4745
|
+
}
|
|
4746
|
+
mapping.assetProperty.asset = { id: config.device.id, name: config.device.name };
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
set(newConfig, this.widgetConfigPath(), mappings);
|
|
4750
|
+
this.widgetConfigService.updateConfig(newConfig);
|
|
4751
|
+
}
|
|
4752
|
+
}
|
|
4753
|
+
async getAsset(id) {
|
|
4754
|
+
if (!this.assetsCache.has(id)) {
|
|
4755
|
+
const asset = (await this.inventory.detail(id, { withLatestValues: true })).data;
|
|
4756
|
+
this.assetsCache.set(id, asset);
|
|
4757
|
+
}
|
|
4758
|
+
return this.assetsCache.get(id);
|
|
4759
|
+
}
|
|
4760
|
+
async addMappings() {
|
|
4761
|
+
if (this.isDrawerOpen())
|
|
4762
|
+
return;
|
|
4763
|
+
this.isDrawerOpen.set(true);
|
|
4764
|
+
let latestConfig = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4765
|
+
const drawer = this.bottomDrawerService.openDrawer(AssetPropertySelectorDrawerComponent, {
|
|
4766
|
+
disableClickOutside: true,
|
|
4767
|
+
initialState: {
|
|
4768
|
+
allowChangingContext: true,
|
|
4769
|
+
contextAsset: latestConfig.device ? await this.getAsset(latestConfig.device.id) : null,
|
|
4770
|
+
hideSelection: false,
|
|
4771
|
+
config: {
|
|
4772
|
+
selectMode: 'plus',
|
|
4773
|
+
expansionMode: 'collapsedByDefault',
|
|
4774
|
+
showValue: true,
|
|
4775
|
+
showKey: true,
|
|
4776
|
+
allowAddingCustomProperties: true,
|
|
4777
|
+
addAssetToProperty: true
|
|
4778
|
+
}
|
|
4779
|
+
}
|
|
4780
|
+
});
|
|
4781
|
+
try {
|
|
4782
|
+
latestConfig = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4783
|
+
const selectedProperties = await drawer.instance.result;
|
|
4784
|
+
const newConfig = { ...latestConfig };
|
|
4785
|
+
const mappings = (get(newConfig, this.widgetConfigPath()) || {});
|
|
4786
|
+
for (const property of selectedProperties) {
|
|
4787
|
+
const baseKey = getPropertyBaseKey(property);
|
|
4788
|
+
let key = baseKey;
|
|
4789
|
+
let counter = 0;
|
|
4790
|
+
while (key in mappings) {
|
|
4791
|
+
key = `${baseKey}${++counter}`;
|
|
4792
|
+
}
|
|
4793
|
+
mappings[key] = {
|
|
4794
|
+
label: property.label,
|
|
4795
|
+
assetProperty: property
|
|
4796
|
+
};
|
|
4797
|
+
}
|
|
4798
|
+
set(newConfig, this.widgetConfigPath(), mappings);
|
|
4799
|
+
this.widgetConfigService.updateConfig(newConfig);
|
|
4800
|
+
}
|
|
4801
|
+
catch (ex) {
|
|
4802
|
+
// cancelled
|
|
4803
|
+
}
|
|
4804
|
+
finally {
|
|
4805
|
+
this.isDrawerOpen.set(false);
|
|
4806
|
+
}
|
|
4807
|
+
}
|
|
4808
|
+
async editMapping(placeholderName, mapping) {
|
|
4809
|
+
if (this.isDrawerOpen())
|
|
4810
|
+
return;
|
|
4811
|
+
this.isDrawerOpen.set(true);
|
|
4812
|
+
let latestConfig = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4813
|
+
const drawer = this.bottomDrawerService.openDrawer(AssetPropertySelectorDrawerComponent, {
|
|
4814
|
+
disableClickOutside: true,
|
|
4815
|
+
initialState: {
|
|
4816
|
+
allowChangingContext: true,
|
|
4817
|
+
contextAsset: latestConfig.device ? await this.getAsset(latestConfig.device.id) : null,
|
|
4818
|
+
hideSelection: false,
|
|
4819
|
+
config: {
|
|
4820
|
+
selectMode: 'single',
|
|
4821
|
+
expansionMode: 'collapsedByDefault',
|
|
4822
|
+
showValue: true,
|
|
4823
|
+
showKey: true,
|
|
4824
|
+
allowAddingCustomProperties: true,
|
|
4825
|
+
addAssetToProperty: true
|
|
4826
|
+
}
|
|
4827
|
+
}
|
|
4828
|
+
});
|
|
4829
|
+
try {
|
|
4830
|
+
latestConfig = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4831
|
+
const [selectedProperty] = await drawer.instance.result;
|
|
4832
|
+
const newConfig = { ...latestConfig };
|
|
4833
|
+
const mappings = (get(newConfig, this.widgetConfigPath()) || {});
|
|
4834
|
+
mappings[placeholderName] = {
|
|
4835
|
+
label: mapping.label,
|
|
4836
|
+
assetProperty: selectedProperty
|
|
4837
|
+
};
|
|
4838
|
+
set(newConfig, this.widgetConfigPath(), mappings);
|
|
4839
|
+
this.widgetConfigService.updateConfig(newConfig);
|
|
4840
|
+
}
|
|
4841
|
+
catch (ex) {
|
|
4842
|
+
// cancelled
|
|
4843
|
+
}
|
|
4844
|
+
finally {
|
|
4845
|
+
this.isDrawerOpen.set(false);
|
|
4846
|
+
}
|
|
4847
|
+
}
|
|
4848
|
+
async clearMapping(placeholderName) {
|
|
4849
|
+
const config = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4850
|
+
set(config, [...this.widgetConfigPath(), placeholderName, 'assetProperty'], null);
|
|
4851
|
+
this.widgetConfigService.updateConfig(config);
|
|
4852
|
+
}
|
|
4853
|
+
async copyMappingToClipboard(name, mapping) {
|
|
4854
|
+
const mappingToTextFn = this.onBeforeCopyMappingToClipboard();
|
|
4855
|
+
const text = mappingToTextFn({ name, ...mapping });
|
|
4856
|
+
await this.clipboardService.writeText(text);
|
|
4857
|
+
}
|
|
4858
|
+
async removeMapping(name) {
|
|
4859
|
+
const config = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4860
|
+
const mappings = (get(config, this.widgetConfigPath()) || {});
|
|
4861
|
+
delete mappings[name];
|
|
4862
|
+
set(config, this.widgetConfigPath(), mappings);
|
|
4863
|
+
this.widgetConfigService.updateConfig(config);
|
|
4864
|
+
}
|
|
4865
|
+
async removeAllMappings() {
|
|
4866
|
+
const config = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4867
|
+
set(config, this.widgetConfigPath(), {});
|
|
4868
|
+
this.widgetConfigService.updateConfig(config);
|
|
4869
|
+
}
|
|
4870
|
+
getLabelValidators(key) {
|
|
4871
|
+
if (!this.labelValidatorCache.has(key)) {
|
|
4872
|
+
this.labelValidatorCache.set(key, [
|
|
4873
|
+
Validators.required,
|
|
4874
|
+
ctrl => this.isLabelAlreadyUsed(ctrl.value, key, this.mappingsSignal())
|
|
4875
|
+
? { 'label-already-used': true }
|
|
4876
|
+
: null
|
|
4877
|
+
]);
|
|
4878
|
+
}
|
|
4879
|
+
return this.labelValidatorCache.get(key);
|
|
4880
|
+
}
|
|
4881
|
+
getNameValidators(key) {
|
|
4882
|
+
if (!this.nameValidatorCache.has(key)) {
|
|
4883
|
+
this.nameValidatorCache.set(key, [
|
|
4884
|
+
Validators.required,
|
|
4885
|
+
ctrl => this.isNameAlreadyUsed(ctrl.value, key, this.keysSignal())
|
|
4886
|
+
? { 'key-already-used': true }
|
|
4887
|
+
: null
|
|
4888
|
+
]);
|
|
4889
|
+
}
|
|
4890
|
+
return this.nameValidatorCache.get(key);
|
|
4891
|
+
}
|
|
4892
|
+
isLabelAlreadyUsed(value, key, mappings) {
|
|
4893
|
+
const trimmed = value.trim();
|
|
4894
|
+
return (!!trimmed &&
|
|
4895
|
+
Object.entries(mappings || {})
|
|
4896
|
+
.filter(([k]) => k !== key)
|
|
4897
|
+
.some(([k, m]) => (m?.label || k) === trimmed));
|
|
4898
|
+
}
|
|
4899
|
+
isNameAlreadyUsed(value, key, keys) {
|
|
4900
|
+
const trimmed = value.trim();
|
|
4901
|
+
return trimmed !== key && (keys || []).includes(trimmed);
|
|
4902
|
+
}
|
|
4903
|
+
async saveLabel(key, newLabel) {
|
|
4904
|
+
const config = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4905
|
+
const mappings = (get(config, this.widgetConfigPath()) || {});
|
|
4906
|
+
if (!mappings[key]) {
|
|
4907
|
+
return;
|
|
4908
|
+
}
|
|
4909
|
+
mappings[key] = { ...mappings[key], label: newLabel.trim() };
|
|
4910
|
+
set(config, this.widgetConfigPath(), mappings);
|
|
4911
|
+
this.widgetConfigService.updateConfig(config);
|
|
4912
|
+
}
|
|
4913
|
+
async saveName(key, newName) {
|
|
4914
|
+
const trimmedName = newName.trim();
|
|
4915
|
+
if (trimmedName === key) {
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
const config = await firstValueFrom(this.widgetConfigService.currentConfig$);
|
|
4919
|
+
const mappings = (get(config, this.widgetConfigPath()) || {});
|
|
4920
|
+
mappings[trimmedName] = mappings[key];
|
|
4921
|
+
delete mappings[key];
|
|
4922
|
+
set(config, this.widgetConfigPath(), mappings);
|
|
4923
|
+
this.widgetConfigService.updateConfig(config);
|
|
4924
|
+
this.widgetConfigService.notify$.next({
|
|
4925
|
+
type: 'asset-property-mapping-key-renamed',
|
|
4926
|
+
oldKey: key,
|
|
4927
|
+
newKey: trimmedName
|
|
4928
|
+
});
|
|
4929
|
+
}
|
|
4930
|
+
distributeColumns(columns, available) {
|
|
4931
|
+
const visible = columns.filter(c => c.visible);
|
|
4932
|
+
const n = visible.length;
|
|
4933
|
+
const base = n > 0 ? Math.floor(available / n) : 0;
|
|
4934
|
+
const remainder = n > 0 ? available % n : 0;
|
|
4935
|
+
const result = Object.fromEntries(columns.map(c => [c.key, 0]));
|
|
4936
|
+
visible.forEach((col, i) => {
|
|
4937
|
+
result[col.key] = base + (i < remainder ? 1 : 0);
|
|
4938
|
+
});
|
|
4939
|
+
return result;
|
|
4940
|
+
}
|
|
4941
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AssetPropertyMappingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4942
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: AssetPropertyMappingsComponent, isStandalone: true, selector: "c8y-asset-property-mappings", inputs: { widgetConfigPath: { classPropertyName: "widgetConfigPath", publicName: "widgetConfigPath", isSignal: true, isRequired: false, transformFunction: null }, initialMappings: { classPropertyName: "initialMappings", publicName: "initialMappings", isSignal: true, isRequired: false, transformFunction: null }, allowAddingNewMappings: { classPropertyName: "allowAddingNewMappings", publicName: "allowAddingNewMappings", isSignal: true, isRequired: false, transformFunction: null }, allowRenamingMappings: { classPropertyName: "allowRenamingMappings", publicName: "allowRenamingMappings", isSignal: true, isRequired: false, transformFunction: null }, allowRelabellingMappings: { classPropertyName: "allowRelabellingMappings", publicName: "allowRelabellingMappings", isSignal: true, isRequired: false, transformFunction: null }, allowEditingMappings: { classPropertyName: "allowEditingMappings", publicName: "allowEditingMappings", isSignal: true, isRequired: false, transformFunction: null }, allowRemovingMappings: { classPropertyName: "allowRemovingMappings", publicName: "allowRemovingMappings", isSignal: true, isRequired: false, transformFunction: null }, showLabels: { classPropertyName: "showLabels", publicName: "showLabels", isSignal: true, isRequired: false, transformFunction: null }, showNames: { classPropertyName: "showNames", publicName: "showNames", isSignal: true, isRequired: false, transformFunction: null }, showAssets: { classPropertyName: "showAssets", publicName: "showAssets", isSignal: true, isRequired: false, transformFunction: null }, showProperties: { classPropertyName: "showProperties", publicName: "showProperties", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null }, actionsColumnSpan: { classPropertyName: "actionsColumnSpan", publicName: "actionsColumnSpan", isSignal: true, isRequired: false, transformFunction: null }, onBeforeCopyMappingToClipboard: { classPropertyName: "onBeforeCopyMappingToClipboard", publicName: "onBeforeCopyMappingToClipboard", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"responsive-grid-table-wrapper--300 responsive-grid-table-wrapper--striped inner-scroll separator-top\"\n style=\"max-height: 300px\"\n>\n @let keys = keys$ | async;\n @let resolvedAssets = resolvedAssets$ | async;\n @let allMappings = mappings$ | async;\n @if (!keys?.length) {\n <div class=\"p-24\">\n <c8y-ui-empty-state\n icon=\"code\"\n [title]=\"emptyStateTitle | translate\"\n [subtitle]=\"emptyStateSubtitle | translate\"\n ></c8y-ui-empty-state>\n </div>\n } @else {\n @for (key of keys; track key) {\n @let mapping = allMappings?.[key];\n @let property = mapping?.assetProperty;\n @let asset = resolvedAssets?.get(property?.asset?.id);\n <div\n class=\"responsive-grid-table responsive-grid-table__body responsive-grid-table--condensed responsive-grid-table--separator p-l-16\"\n >\n @if (showLabels()) {\n <div\n [class]=\"'col-' + row1ColumnSpans.label\"\n [attr.aria-label]=\"'Label' | translate\"\n >\n <div class=\"fit-w\">\n <p class=\"text-label-small\">{{ 'Label' | translate }}</p>\n @if (allowRelabellingMappings()) {\n <c8y-input-group-editable\n name=\"label-{{ key }}\"\n size=\"sm\"\n [ariaLabel]=\"'Label' | translate\"\n [ngModel]=\"mapping?.label || key\"\n [validators]=\"getLabelValidators(key)\"\n (ngModelChange)=\"saveLabel(key, $event)\"\n >\n <c8y-message\n name=\"label-already-used\"\n [text]=\"'Label already used. Use a different one.' | translate\"\n ></c8y-message>\n </c8y-input-group-editable>\n } @else {\n <span class=\"tag tag--default text-bold\">{{ mapping?.label || key }}</span>\n }\n </div>\n </div>\n }\n @if (showNames()) {\n <div\n [class]=\"'col-' + row1ColumnSpans.name\"\n [attr.aria-label]=\"'Name' | translate\"\n >\n <div class=\"fit-w\">\n <p class=\"text-label-small\">{{ 'Name' | translate }}</p>\n @if (allowRenamingMappings()) {\n <c8y-input-group-editable\n class=\"text-bold\"\n name=\"name-{{ key }}\"\n size=\"sm\"\n [ariaLabel]=\"'Name' | translate\"\n [ngModel]=\"key\"\n [validators]=\"getNameValidators(key)\"\n (ngModelChange)=\"saveName(key, $event)\"\n >\n <c8y-message\n name=\"key-already-used\"\n [text]=\"'Name already used. Use a different one.' | translate\"\n ></c8y-message>\n </c8y-input-group-editable>\n } @else {\n {{ key }}\n }\n </div>\n </div>\n }\n <div [class]=\"'showOnHover col-' + actionsColumnSpan()\">\n <div class=\"col-actions fit-w min-width-0\">\n <button\n class=\"btn-dot btn-sm m-0\"\n [attr.aria-label]=\"'Copy mapping to clipboard' | translate\"\n tooltip=\"{{ 'Copy mapping to clipboard' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"copyMappingToClipboard(key, mapping!)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"clipboard\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (allowEditingMappings() && !mapping?.assetProperty) {\n <button\n class=\"btn-dot btn-sm m-0\"\n [attr.aria-label]=\"'Assign property' | translate\"\n tooltip=\"{{ 'Assign property' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n [disabled]=\"isDrawerOpen()\"\n (click)=\"editMapping(key, mapping!)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"pencil\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n @if (allowEditingMappings() && mapping?.assetProperty) {\n <button\n class=\"btn-dot btn-sm m-0\"\n [attr.aria-label]=\"'Clear mapping' | translate\"\n tooltip=\"{{ 'Clear mapping' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"clearMapping(key)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"remove-property\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n @if (allowRemovingMappings()) {\n <button\n class=\"btn-dot btn-sm btn-dot--danger m-0\"\n [attr.aria-label]=\"'Remove mapping' | translate\"\n tooltip=\"{{ 'Remove mapping' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"removeMapping(key)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n </div>\n </div>\n @if (showAssets()) {\n <div\n [class]=\"'p-b-16 col-' + row2ColumnSpans.asset\"\n [attr.aria-label]=\"'Asset' | translate\"\n >\n <div class=\"min-width-0\">\n <p class=\"text-label-small\">{{ 'Asset' | translate }}</p>\n {{ mapping?.assetProperty?.asset?.name || mapping?.assetProperty?.asset?.id || '\u2014' }}\n </div>\n </div>\n }\n @if (showProperties()) {\n <div\n [class]=\"'p-b-16 col-' + row2ColumnSpans.property\"\n [attr.aria-label]=\"'Property' | translate\"\n >\n <div class=\"min-width-0\">\n <p class=\"text-label-small\">{{ 'Property' | translate }}</p>\n {{ property?.label || property?.name || '\u2014' }}\n </div>\n </div>\n }\n @if (showValues()) {\n <div\n [class]=\"'p-b-16 col-' + row2ColumnSpans.value\"\n [attr.aria-label]=\"'Value' | translate\"\n >\n <div class=\"min-width-0\">\n <p class=\"text-label-small\">{{ 'Value' | translate }}</p>\n @if (property && asset) {\n @let value = (property | c8yAssetPropertyValue: asset | async) ?? '\u2014';\n <samp\n class=\"text-truncate min-width-0\"\n title=\"{{ value }}\"\n >\n {{ value }}\n </samp>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n</div>\n@if (allowAddingNewMappings() || (allowRemovingMappings() && (keys$ | async)?.length)) {\n <div class=\"p-16 separator-top d-flex j-c-between a-i-center\">\n @if (allowAddingNewMappings()) {\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n [disabled]=\"isDrawerOpen()\"\n (click)=\"addMappings()\"\n >\n <i\n c8yIcon=\"plus-circle\"\n aria-hidden=\"true\"\n ></i>\n {{ 'Add mappings' | translate }}\n </button>\n }\n @if (allowRemovingMappings() && (keys$ | async)?.length) {\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n [disabled]=\"isDrawerOpen()\"\n (click)=\"removeAllMappings()\"\n >\n <i\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n {{ 'Remove all mappings' | translate }}\n </button>\n }\n </div>\n}\n\n<c8y-widget-config-feedback>\n <span\n class=\"tag tag--info chip text-12 m-4\"\n ngNonBindable\n translate\n [translateParams]=\"{\n count: (keys$ | async)?.length ?? 0\n }\"\n >\n {{ count }} selected\n </span>\n</c8y-widget-config-feedback>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: InputGroupEditableComponent, selector: "c8y-input-group-editable", inputs: ["ariaLabel", "name", "size", "placeholder", "validators", "asyncValidators"], outputs: ["save", "cancel"] }, { kind: "directive", type: MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$4.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AssetPropertyValuePipe, name: "c8yAssetPropertyValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4943
|
+
}
|
|
4944
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AssetPropertyMappingsComponent, decorators: [{
|
|
4945
|
+
type: Component,
|
|
4946
|
+
args: [{ selector: 'c8y-asset-property-mappings', imports: [
|
|
4947
|
+
AsyncPipe,
|
|
4948
|
+
FormsModule,
|
|
4949
|
+
IconDirective,
|
|
4950
|
+
C8yTranslatePipe,
|
|
4951
|
+
C8yTranslateDirective,
|
|
4952
|
+
InputGroupEditableComponent,
|
|
4953
|
+
MessageDirective,
|
|
4954
|
+
EmptyStateComponent,
|
|
4955
|
+
AssetPropertyValuePipe,
|
|
4956
|
+
BsDropdownModule,
|
|
4957
|
+
TooltipModule,
|
|
4958
|
+
WidgetConfigFeedbackComponent
|
|
4959
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"responsive-grid-table-wrapper--300 responsive-grid-table-wrapper--striped inner-scroll separator-top\"\n style=\"max-height: 300px\"\n>\n @let keys = keys$ | async;\n @let resolvedAssets = resolvedAssets$ | async;\n @let allMappings = mappings$ | async;\n @if (!keys?.length) {\n <div class=\"p-24\">\n <c8y-ui-empty-state\n icon=\"code\"\n [title]=\"emptyStateTitle | translate\"\n [subtitle]=\"emptyStateSubtitle | translate\"\n ></c8y-ui-empty-state>\n </div>\n } @else {\n @for (key of keys; track key) {\n @let mapping = allMappings?.[key];\n @let property = mapping?.assetProperty;\n @let asset = resolvedAssets?.get(property?.asset?.id);\n <div\n class=\"responsive-grid-table responsive-grid-table__body responsive-grid-table--condensed responsive-grid-table--separator p-l-16\"\n >\n @if (showLabels()) {\n <div\n [class]=\"'col-' + row1ColumnSpans.label\"\n [attr.aria-label]=\"'Label' | translate\"\n >\n <div class=\"fit-w\">\n <p class=\"text-label-small\">{{ 'Label' | translate }}</p>\n @if (allowRelabellingMappings()) {\n <c8y-input-group-editable\n name=\"label-{{ key }}\"\n size=\"sm\"\n [ariaLabel]=\"'Label' | translate\"\n [ngModel]=\"mapping?.label || key\"\n [validators]=\"getLabelValidators(key)\"\n (ngModelChange)=\"saveLabel(key, $event)\"\n >\n <c8y-message\n name=\"label-already-used\"\n [text]=\"'Label already used. Use a different one.' | translate\"\n ></c8y-message>\n </c8y-input-group-editable>\n } @else {\n <span class=\"tag tag--default text-bold\">{{ mapping?.label || key }}</span>\n }\n </div>\n </div>\n }\n @if (showNames()) {\n <div\n [class]=\"'col-' + row1ColumnSpans.name\"\n [attr.aria-label]=\"'Name' | translate\"\n >\n <div class=\"fit-w\">\n <p class=\"text-label-small\">{{ 'Name' | translate }}</p>\n @if (allowRenamingMappings()) {\n <c8y-input-group-editable\n class=\"text-bold\"\n name=\"name-{{ key }}\"\n size=\"sm\"\n [ariaLabel]=\"'Name' | translate\"\n [ngModel]=\"key\"\n [validators]=\"getNameValidators(key)\"\n (ngModelChange)=\"saveName(key, $event)\"\n >\n <c8y-message\n name=\"key-already-used\"\n [text]=\"'Name already used. Use a different one.' | translate\"\n ></c8y-message>\n </c8y-input-group-editable>\n } @else {\n {{ key }}\n }\n </div>\n </div>\n }\n <div [class]=\"'showOnHover col-' + actionsColumnSpan()\">\n <div class=\"col-actions fit-w min-width-0\">\n <button\n class=\"btn-dot btn-sm m-0\"\n [attr.aria-label]=\"'Copy mapping to clipboard' | translate\"\n tooltip=\"{{ 'Copy mapping to clipboard' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"copyMappingToClipboard(key, mapping!)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"clipboard\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (allowEditingMappings() && !mapping?.assetProperty) {\n <button\n class=\"btn-dot btn-sm m-0\"\n [attr.aria-label]=\"'Assign property' | translate\"\n tooltip=\"{{ 'Assign property' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n [disabled]=\"isDrawerOpen()\"\n (click)=\"editMapping(key, mapping!)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"pencil\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n @if (allowEditingMappings() && mapping?.assetProperty) {\n <button\n class=\"btn-dot btn-sm m-0\"\n [attr.aria-label]=\"'Clear mapping' | translate\"\n tooltip=\"{{ 'Clear mapping' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"clearMapping(key)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"remove-property\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n @if (allowRemovingMappings()) {\n <button\n class=\"btn-dot btn-sm btn-dot--danger m-0\"\n [attr.aria-label]=\"'Remove mapping' | translate\"\n tooltip=\"{{ 'Remove mapping' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"removeMapping(key)\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n </div>\n </div>\n @if (showAssets()) {\n <div\n [class]=\"'p-b-16 col-' + row2ColumnSpans.asset\"\n [attr.aria-label]=\"'Asset' | translate\"\n >\n <div class=\"min-width-0\">\n <p class=\"text-label-small\">{{ 'Asset' | translate }}</p>\n {{ mapping?.assetProperty?.asset?.name || mapping?.assetProperty?.asset?.id || '\u2014' }}\n </div>\n </div>\n }\n @if (showProperties()) {\n <div\n [class]=\"'p-b-16 col-' + row2ColumnSpans.property\"\n [attr.aria-label]=\"'Property' | translate\"\n >\n <div class=\"min-width-0\">\n <p class=\"text-label-small\">{{ 'Property' | translate }}</p>\n {{ property?.label || property?.name || '\u2014' }}\n </div>\n </div>\n }\n @if (showValues()) {\n <div\n [class]=\"'p-b-16 col-' + row2ColumnSpans.value\"\n [attr.aria-label]=\"'Value' | translate\"\n >\n <div class=\"min-width-0\">\n <p class=\"text-label-small\">{{ 'Value' | translate }}</p>\n @if (property && asset) {\n @let value = (property | c8yAssetPropertyValue: asset | async) ?? '\u2014';\n <samp\n class=\"text-truncate min-width-0\"\n title=\"{{ value }}\"\n >\n {{ value }}\n </samp>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n</div>\n@if (allowAddingNewMappings() || (allowRemovingMappings() && (keys$ | async)?.length)) {\n <div class=\"p-16 separator-top d-flex j-c-between a-i-center\">\n @if (allowAddingNewMappings()) {\n <button\n class=\"btn btn-default btn-sm\"\n type=\"button\"\n [disabled]=\"isDrawerOpen()\"\n (click)=\"addMappings()\"\n >\n <i\n c8yIcon=\"plus-circle\"\n aria-hidden=\"true\"\n ></i>\n {{ 'Add mappings' | translate }}\n </button>\n }\n @if (allowRemovingMappings() && (keys$ | async)?.length) {\n <button\n class=\"btn btn-danger btn-sm\"\n type=\"button\"\n [disabled]=\"isDrawerOpen()\"\n (click)=\"removeAllMappings()\"\n >\n <i\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n {{ 'Remove all mappings' | translate }}\n </button>\n }\n </div>\n}\n\n<c8y-widget-config-feedback>\n <span\n class=\"tag tag--info chip text-12 m-4\"\n ngNonBindable\n translate\n [translateParams]=\"{\n count: (keys$ | async)?.length ?? 0\n }\"\n >\n {{ count }} selected\n </span>\n</c8y-widget-config-feedback>\n" }]
|
|
4960
|
+
}], propDecorators: { widgetConfigPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetConfigPath", required: false }] }], initialMappings: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialMappings", required: false }] }], allowAddingNewMappings: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowAddingNewMappings", required: false }] }], allowRenamingMappings: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowRenamingMappings", required: false }] }], allowRelabellingMappings: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowRelabellingMappings", required: false }] }], allowEditingMappings: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowEditingMappings", required: false }] }], allowRemovingMappings: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowRemovingMappings", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }], showNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNames", required: false }] }], showAssets: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAssets", required: false }] }], showProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "showProperties", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], actionsColumnSpan: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsColumnSpan", required: false }] }], onBeforeCopyMappingToClipboard: [{ type: i0.Input, args: [{ isSignal: true, alias: "onBeforeCopyMappingToClipboard", required: false }] }] } });
|
|
4961
|
+
|
|
4422
4962
|
/**
|
|
4423
4963
|
* Generated bundle index. Do not edit.
|
|
4424
4964
|
*/
|
|
4425
4965
|
|
|
4426
|
-
export { ALL_GLOBAL_ROLES_SELECTED, AddDashboardComponent, AddDashboardFactory, AppearanceSettingsComponent, CONTEXT_DASHBOARD_CONFIG, ContextDashboardComponent, ContextDashboardModule, ContextDashboardService, ContextDashboardType, DASHBOARD_CHILDREN_STATE_NAME, DASHBOARD_DETAILS_OUTLET, DASHBOARD_DETAILS_TABS_OUTLET_NAME, DASHBOARD_SETTINGS_CHANGES, DASHBOARD_THEME_CLASSES, DashboardActionBarFactory, DashboardDetailComponent, DashboardDetailService, DashboardDetailsTabId, DeviceInfoDashboardComponent, DeviceInfoDashboardModule, DeviceManagementHomeDashboardComponent, DeviceManagementHomeDashboardModule, GlobalContextSectionComponent, HOOK_WIDGET_CONFIG, NewDashboardGuard, PRODUCT_EXPERIENCE, PasteDashboardActionComponent, REPORT_DEFAULT_NAVIGATION_NODE_PRIORITY, STYLING_CLASS_PREFIXES, TypeDashboardInfoComponent, WIDGET_CONTENT_CLASSES, WIDGET_HEADER_CLASSES, WidgetAssetSelectorComponent, WidgetConfigAppearanceComponent, WidgetConfigComponent, WidgetConfigFeedbackComponent, WidgetConfigGeneralComponent, WidgetConfigSectionComponent, WidgetConfigSectionService, WidgetConfigService, WidgetPreviewComponent, WidgetPreviewWrapperComponent, WidgetService, hookWidgetConfig, newDashboardTab };
|
|
4966
|
+
export { ALL_GLOBAL_ROLES_SELECTED, AddDashboardComponent, AddDashboardFactory, AppearanceSettingsComponent, AssetPropertyMappingsComponent, AssetPropertyMappingsService, CONTEXT_DASHBOARD_CONFIG, ContextDashboardComponent, ContextDashboardModule, ContextDashboardService, ContextDashboardType, DASHBOARD_CHILDREN_STATE_NAME, DASHBOARD_DETAILS_OUTLET, DASHBOARD_DETAILS_TABS_OUTLET_NAME, DASHBOARD_SETTINGS_CHANGES, DASHBOARD_THEME_CLASSES, DashboardActionBarFactory, DashboardDetailComponent, DashboardDetailService, DashboardDetailsTabId, DeviceInfoDashboardComponent, DeviceInfoDashboardModule, DeviceManagementHomeDashboardComponent, DeviceManagementHomeDashboardModule, GlobalContextSectionComponent, HOOK_WIDGET_CONFIG, NewDashboardGuard, PRODUCT_EXPERIENCE, PasteDashboardActionComponent, REPORT_DEFAULT_NAVIGATION_NODE_PRIORITY, STYLING_CLASS_PREFIXES, TypeDashboardInfoComponent, WIDGET_CONTENT_CLASSES, WIDGET_HEADER_CLASSES, WidgetAssetSelectorComponent, WidgetConfigAppearanceComponent, WidgetConfigComponent, WidgetConfigFeedbackComponent, WidgetConfigGeneralComponent, WidgetConfigSectionComponent, WidgetConfigSectionService, WidgetConfigService, WidgetPreviewComponent, WidgetPreviewWrapperComponent, WidgetService, getPropertyBaseKey, hookWidgetConfig, newDashboardTab, quoteAndEscape, renamePropertyKeyInCode };
|
|
4427
4967
|
//# sourceMappingURL=c8y-ngx-components-context-dashboard.mjs.map
|