@c8y/ngx-components 1023.71.1 → 1023.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-plain-branding-editor.mjs +1 -1
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor.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-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-Cek3_qZQ.mjs → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DVEnCRzW.mjs} +2 -2
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DVEnCRzW.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab.mjs +2 -2
- 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 +108 -52
- 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-alarms-alarm-list.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-alarm-list.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-all-critical-alarms.mjs +4 -5
- package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-all-critical-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-recent-alarms.mjs +4 -5
- package/fesm2022/c8y-ngx-components-widgets-definitions-alarms-recent-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-asset-notes.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-asset-notes.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-asset-table.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-asset-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-graph.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-graph.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-table.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-device-control-message.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-device-control-message.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 +77 -5
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-image.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-image.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-info-gauge.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-info-gauge.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-kpi.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-kpi.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-linear-gauge.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-linear-gauge.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-map.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-map.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-markdown.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-markdown.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-radial-gauge.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-radial-gauge.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-silo.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-silo.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-three-d-rotation.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-definitions-three-d-rotation.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs +67 -60
- 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 +2 -2
- 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 +380 -170
- 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 +90 -1
- package/global-context/index.d.ts.map +1 -1
- package/index.d.ts +116 -15
- package/index.d.ts.map +1 -1
- package/locales/de.po +120 -3
- package/locales/es.po +120 -3
- package/locales/fr.po +120 -3
- package/locales/ja_JP.po +120 -3
- package/locales/ko.po +120 -3
- package/locales/locales.pot +120 -3
- package/locales/nl.po +120 -3
- package/locales/pl.po +120 -3
- package/locales/pt_BR.po +120 -3
- package/locales/zh_CN.po +120 -3
- package/locales/zh_TW.po +120 -3
- package/package.json +1 -1
- package/widgets/definitions/alarms/all-critical-alarms/index.d.ts +1 -2
- package/widgets/definitions/alarms/all-critical-alarms/index.d.ts.map +1 -1
- package/widgets/definitions/alarms/recent-alarms/index.d.ts +1 -2
- package/widgets/definitions/alarms/recent-alarms/index.d.ts.map +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 +8 -1
- 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
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-Cek3_qZQ.mjs.map +0 -1
|
@@ -1,41 +1,61 @@
|
|
|
1
1
|
import { NgIf, NgClass, AsyncPipe } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, Injectable, Input, Component, input, computed, ChangeDetectionStrategy, viewChild, SecurityContext, ViewChild } from '@angular/core';
|
|
3
|
+
import { inject, Injectable, Input, Component, input, computed, ChangeDetectionStrategy, viewChild, SecurityContext, ViewChild, DestroyRef, signal } from '@angular/core';
|
|
4
4
|
import * as i2 from '@angular/forms';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
6
6
|
import { Router, RouterModule } from '@angular/router';
|
|
7
7
|
import { gettext } from '@c8y/ngx-components/gettext';
|
|
8
8
|
import * as i2$1 from '@c8y/ngx-components';
|
|
9
|
-
import { AppStateService, Permissions, IconDirective, C8yTranslatePipe, TabsModule, LoadingComponent, OptionsService, ClipboardService } from '@c8y/ngx-components';
|
|
10
|
-
import { WidgetConfigService, WidgetConfigFeedbackComponent } from '@c8y/ngx-components/context-dashboard';
|
|
9
|
+
import { AppStateService, Permissions, IconDirective, C8yTranslatePipe, ManagedObjectRealtimeService, TabsModule, LoadingComponent, AlertService, OptionsService, ClipboardService, DashboardChildComponent } from '@c8y/ngx-components';
|
|
10
|
+
import { WidgetConfigService, quoteAndEscape, WidgetConfigFeedbackComponent, AssetPropertyMappingsService, renamePropertyKeyInCode } from '@c8y/ngx-components/context-dashboard';
|
|
11
11
|
import * as i1 from 'ngx-bootstrap/popover';
|
|
12
12
|
import { PopoverModule } from 'ngx-bootstrap/popover';
|
|
13
13
|
import * as i3 from 'ngx-bootstrap/tooltip';
|
|
14
14
|
import { TooltipModule, TooltipDirective } from 'ngx-bootstrap/tooltip';
|
|
15
15
|
import { isEmpty } from 'lodash';
|
|
16
|
-
import { Subject, first, map, filter, withLatestFrom, switchMap, shareReplay, takeUntil, startWith, combineLatest, distinctUntilChanged, debounceTime, of, merge, from, isEmpty as isEmpty$1, catchError,
|
|
16
|
+
import { Subject, first, map, filter, withLatestFrom, switchMap, shareReplay, takeUntil, startWith, combineLatest, distinctUntilChanged, debounceTime, of, EMPTY, merge, from, isEmpty as isEmpty$1, catchError, fromEvent, BehaviorSubject } from 'rxjs';
|
|
17
17
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
18
18
|
import { InventoryService } from '@c8y/client';
|
|
19
19
|
import { kebabCase } from 'lodash-es';
|
|
20
20
|
import { TranslateService } from '@ngx-translate/core';
|
|
21
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
22
|
+
import { PRESET_NAME, REFRESH_OPTION, LocalControlsComponent, GLOBAL_CONTEXT_DISPLAY_MODE, GlobalContextConnectorComponent } from '@c8y/ngx-components/global-context';
|
|
23
|
+
import * as i4 from 'ngx-bootstrap/dropdown';
|
|
24
|
+
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
|
21
25
|
import { EditorComponent } from '@c8y/ngx-components/editor';
|
|
26
|
+
import { map as map$1, distinctUntilChanged as distinctUntilChanged$1, switchMap as switchMap$1, filter as filter$1 } from 'rxjs/operators';
|
|
22
27
|
import { AssetPropertyListComponent, AssetPropertyActionDirective } from '@c8y/ngx-components/asset-properties';
|
|
23
28
|
|
|
24
29
|
const INITIAL_HTML_FORMATTED = `<div>
|
|
25
30
|
<h2>Hello from <span class="branded">HTML widget</span></h2>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
|
|
32
|
+
<p class="m-t-16">
|
|
33
|
+
\$\{this.c8yTranslate('You can use HTML and JavaScript template literals:')\}
|
|
29
34
|
</p>
|
|
30
35
|
|
|
31
|
-
<
|
|
36
|
+
<p class="m-t-16">
|
|
37
|
+
<b>Context properties:</b> Access the assigned asset's properties via <code>c8yContext</code>: <br>
|
|
38
|
+
<tt>\$\{this.c8yContext ? this.c8yTranslate('Selected asset: {{ assetName }}', { assetName: this.c8yContext.name }) : this.c8yTranslate('No asset selected')\}</tt>
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<p class="m-t-16">
|
|
42
|
+
<b>Asset properties:</b> Use "Asset properties" to select other properties (incl. computed ones) and access their values via <code>c8yProperties</code>: <br>
|
|
43
|
+
<i>Last updated:</i> <tt>\${this.c8yProperties?.lastUpdated || '-'}</tt> <br>
|
|
44
|
+
<i>Last device message:</i> <tt>\${this.c8yProperties?.lastDeviceMessage || '-'}</tt>
|
|
45
|
+
</p>
|
|
32
46
|
|
|
33
|
-
<p>
|
|
34
|
-
Use the CSS editor to customize
|
|
47
|
+
<p class="m-t-16">
|
|
48
|
+
<b>Styles:</b> Use the CSS editor to customize styles. You can use <span class="text-bold">any design-token CSS variable</span> in there.
|
|
35
49
|
</p>
|
|
36
50
|
|
|
37
|
-
<p>
|
|
38
|
-
|
|
51
|
+
<p class="m-t-16">
|
|
52
|
+
<b>Translations:</b> Use the <code>c8yTranslate('text {{ var }}', { var: value })</code> function to translate strings.
|
|
53
|
+
<i>Note: texts must be written in English and their translations must be available in the loaded standard or custom translation resources.</i>
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
<p class="m-t-16">
|
|
57
|
+
<b>Buttons:</b> Use other HTML elements like buttons: <br>
|
|
58
|
+
<a class="btn btn-primary m-t-8" href="#/group">\$\{this.c8yTranslate('Go to groups')\}</a>
|
|
39
59
|
</p>
|
|
40
60
|
</div>`;
|
|
41
61
|
const INITIAL_CSS_FORMATTED = `
|
|
@@ -60,6 +80,10 @@ export default class ${name} extends LitElement {
|
|
|
60
80
|
static properties = {
|
|
61
81
|
// The managed object this widget is assigned to. Can be null.
|
|
62
82
|
c8yContext: { type: Object },
|
|
83
|
+
// The object with realtime values of configured properties. Can be null.
|
|
84
|
+
c8yProperties: { type: Object },
|
|
85
|
+
// The instant translation function.
|
|
86
|
+
c8yTranslate: { type: Function },
|
|
63
87
|
};
|
|
64
88
|
|
|
65
89
|
constructor() {
|
|
@@ -143,6 +167,7 @@ class HtmlWidgetConfigService {
|
|
|
143
167
|
this.widgetConfigService = inject(WidgetConfigService);
|
|
144
168
|
this.appState = inject(AppStateService);
|
|
145
169
|
this.destroy$ = new Subject();
|
|
170
|
+
this.notify$ = this.widgetConfigService.notify$;
|
|
146
171
|
this.init$ = this.widgetConfigService.currentConfig$.pipe(first(), map(current => {
|
|
147
172
|
if (current.html) {
|
|
148
173
|
current.config = this.mapLegacyConfig(current);
|
|
@@ -338,6 +363,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
338
363
|
|
|
339
364
|
class HtmlFrameComponent {
|
|
340
365
|
constructor() {
|
|
366
|
+
this.propertyValues$ = EMPTY;
|
|
341
367
|
/**
|
|
342
368
|
* If set to true, it will be ensured that a unique hash is generated
|
|
343
369
|
* for every webcomponent. This is useful if configured as otherwise it might
|
|
@@ -348,6 +374,7 @@ class HtmlFrameComponent {
|
|
|
348
374
|
this.alerts = [];
|
|
349
375
|
this.sanitizer = inject(DomSanitizer);
|
|
350
376
|
this.translateService = inject(TranslateService);
|
|
377
|
+
this.moRealtime = inject(ManagedObjectRealtimeService);
|
|
351
378
|
this.destroy$ = new Subject();
|
|
352
379
|
this.hostElement = viewChild('hostElement', ...(ngDevMode ? [{ debugName: "hostElement" }] : []));
|
|
353
380
|
this.reload$ = new Subject();
|
|
@@ -447,9 +474,21 @@ class HtmlFrameComponent {
|
|
|
447
474
|
}
|
|
448
475
|
createWebComponent(webComponentName, divHostElement, context) {
|
|
449
476
|
const webComponent = document.createElement(webComponentName);
|
|
450
|
-
webComponent.c8yContext = context;
|
|
451
477
|
const instantTranslate = this.translateService.instant.bind(this.translateService);
|
|
452
478
|
webComponent.c8yTranslate = instantTranslate;
|
|
479
|
+
// TODO: should c8yContext be updated in realtime and also connected under global time controls?
|
|
480
|
+
webComponent.c8yContext = context;
|
|
481
|
+
if (context?.id) {
|
|
482
|
+
this.moRealtime
|
|
483
|
+
.onAll$(context.id)
|
|
484
|
+
.pipe(takeUntil(merge(this.reload$, this.destroy$)))
|
|
485
|
+
.subscribe(res => {
|
|
486
|
+
webComponent.c8yContext = res.data;
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
this.propertyValues$.pipe(takeUntil(merge(this.reload$, this.destroy$))).subscribe(values => {
|
|
490
|
+
webComponent.c8yProperties = values;
|
|
491
|
+
});
|
|
453
492
|
divHostElement.appendChild(webComponent);
|
|
454
493
|
return webComponent;
|
|
455
494
|
}
|
|
@@ -491,7 +530,7 @@ class HtmlFrameComponent {
|
|
|
491
530
|
return webComponentScript;
|
|
492
531
|
}
|
|
493
532
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlFrameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
494
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: HtmlFrameComponent, isStandalone: true, selector: "c8y-html-frame", inputs: { config: "config", device: "device", useSalt: "useSalt" }, host: { classAttribute: "d-contents" }, viewQueries: [{ propertyName: "hostElement", first: true, predicate: ["hostElement"], descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "@for (alert of alerts; track alert) {\n <div\n class=\"alert m-8\"\n role=\"alert\"\n [ngClass]=\"{\n 'alert-danger': alert.type === 'danger',\n 'alert-warning': alert.type === 'warning',\n 'alert-info': alert.type === 'info',\n 'alert-success': alert.type === 'success'\n }\"\n >\n <p><strong translate>There was an issue in the HTML widget:</strong></p>\n <pre>{{ alert.text }}</pre>\n </div>\n}\n<div\n class=\"fit-w fit-h\"\n #hostElement\n></div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
533
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: HtmlFrameComponent, isStandalone: true, selector: "c8y-html-frame", inputs: { config: "config", device: "device", propertyValues$: "propertyValues$", useSalt: "useSalt" }, host: { classAttribute: "d-contents" }, viewQueries: [{ propertyName: "hostElement", first: true, predicate: ["hostElement"], descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "@for (alert of alerts; track alert) {\n <div\n class=\"alert m-8\"\n role=\"alert\"\n [ngClass]=\"{\n 'alert-danger': alert.type === 'danger',\n 'alert-warning': alert.type === 'warning',\n 'alert-info': alert.type === 'info',\n 'alert-success': alert.type === 'success'\n }\"\n >\n <p><strong translate>There was an issue in the HTML widget:</strong></p>\n <pre>{{ alert.text }}</pre>\n </div>\n}\n<div\n class=\"fit-w fit-h\"\n #hostElement\n></div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
495
534
|
}
|
|
496
535
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlFrameComponent, decorators: [{
|
|
497
536
|
type: Component,
|
|
@@ -500,6 +539,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
500
539
|
type: Input
|
|
501
540
|
}], device: [{
|
|
502
541
|
type: Input
|
|
542
|
+
}], propertyValues$: [{
|
|
543
|
+
type: Input
|
|
503
544
|
}], useSalt: [{
|
|
504
545
|
type: Input
|
|
505
546
|
}], hostElement: [{ type: i0.ViewChild, args: ['hostElement', { isSignal: true }] }] } });
|
|
@@ -508,6 +549,9 @@ class WidgetCodeEditorComponent {
|
|
|
508
549
|
constructor() {
|
|
509
550
|
this.mode = 'code';
|
|
510
551
|
this.configService = inject(HtmlWidgetConfigService);
|
|
552
|
+
this.translate = inject(TranslateService);
|
|
553
|
+
this.widgetConfigService = inject(WidgetConfigService);
|
|
554
|
+
this.propertyKeys$ = this.widgetConfigService.currentConfig$.pipe(map(config => Object.keys(config?.properties || {}).sort((a, b) => a.localeCompare(b))));
|
|
511
555
|
this.isAutoSaveEnabled = true;
|
|
512
556
|
this.language = 'html';
|
|
513
557
|
this.isLoading = false;
|
|
@@ -518,8 +562,10 @@ class WidgetCodeEditorComponent {
|
|
|
518
562
|
this.BUTTON_ENABLE_AUTOSAVE_LABEL = gettext('Enable auto save`An action you can do on the html widget editor`');
|
|
519
563
|
this.TAB_OUTLET_NAME = 'html-widget-tab-outlet';
|
|
520
564
|
this.destroy$ = new Subject();
|
|
565
|
+
this.suggestionProviders = [];
|
|
521
566
|
}
|
|
522
567
|
ngOnDestroy() {
|
|
568
|
+
this.suggestionProviders.forEach(a => a.dispose());
|
|
523
569
|
this.destroy$.next();
|
|
524
570
|
this.destroy$.complete();
|
|
525
571
|
}
|
|
@@ -557,6 +603,9 @@ class WidgetCodeEditorComponent {
|
|
|
557
603
|
this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
|
|
558
604
|
this.saveCode();
|
|
559
605
|
});
|
|
606
|
+
this.propertyKeys$.pipe(takeUntil(this.destroy$)).subscribe(keys => {
|
|
607
|
+
this.registerPropertySuggestions(keys);
|
|
608
|
+
});
|
|
560
609
|
}
|
|
561
610
|
formatCode() {
|
|
562
611
|
this.editor.getAction('editor.action.formatDocument').run();
|
|
@@ -580,12 +629,122 @@ class WidgetCodeEditorComponent {
|
|
|
580
629
|
}
|
|
581
630
|
this.configService.changeCss(code);
|
|
582
631
|
}
|
|
632
|
+
insertPropertyAtCursor(key) {
|
|
633
|
+
if (!this.editor) {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
const text = this.getFormattedPropertyExpression(key);
|
|
637
|
+
const monaco = this.editorComponent.monaco;
|
|
638
|
+
const position = this.editor.getPosition();
|
|
639
|
+
const range = new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column);
|
|
640
|
+
this.editor.executeEdits('insert-property', [{ range, text, forceMoveMarkers: true }]);
|
|
641
|
+
this.editor.focus();
|
|
642
|
+
}
|
|
643
|
+
registerPropertySuggestions(keys) {
|
|
644
|
+
this.suggestionProviders.forEach(a => a.dispose());
|
|
645
|
+
this.suggestionProviders = [];
|
|
646
|
+
if (!keys.length)
|
|
647
|
+
return;
|
|
648
|
+
const monaco = this.editorComponent.monaco;
|
|
649
|
+
const providerOptions = {
|
|
650
|
+
triggerCharacters: ['$', '.', '[', "'"],
|
|
651
|
+
provideCompletionItems: (model, position) => {
|
|
652
|
+
const lineText = model.getValueInRange({
|
|
653
|
+
startLineNumber: position.lineNumber,
|
|
654
|
+
startColumn: 1,
|
|
655
|
+
endLineNumber: position.lineNumber,
|
|
656
|
+
endColumn: position.column
|
|
657
|
+
});
|
|
658
|
+
const makeRange = (startColumn) => ({
|
|
659
|
+
startLineNumber: position.lineNumber,
|
|
660
|
+
endLineNumber: position.lineNumber,
|
|
661
|
+
startColumn,
|
|
662
|
+
endColumn: position.column
|
|
663
|
+
});
|
|
664
|
+
// Case 1: after dot access – this.c8yProperties?. or this.c8yProperties.
|
|
665
|
+
const dotMatch = /this\.c8yProperties\??\.(\w*)$/.exec(lineText);
|
|
666
|
+
if (dotMatch) {
|
|
667
|
+
const typed = dotMatch[1];
|
|
668
|
+
const startColumn = position.column - typed.length;
|
|
669
|
+
const suggestions = keys
|
|
670
|
+
.filter(key => !/[^a-zA-Z0-9_]/.test(key) && key.startsWith(typed))
|
|
671
|
+
.map(key => ({
|
|
672
|
+
label: key,
|
|
673
|
+
kind: monaco.languages.CompletionItemKind.Property,
|
|
674
|
+
insertText: key,
|
|
675
|
+
range: makeRange(startColumn),
|
|
676
|
+
sortText: key
|
|
677
|
+
}));
|
|
678
|
+
return { suggestions };
|
|
679
|
+
}
|
|
680
|
+
// Case 2: after bracket access – this.c8yProperties?.[ or this.c8yProperties[
|
|
681
|
+
const bracketMatch = /this\.c8yProperties(?:\?\.)?\[([^\]]*)$/.exec(lineText);
|
|
682
|
+
if (bracketMatch) {
|
|
683
|
+
const typed = bracketMatch[1];
|
|
684
|
+
const charAfterCursor = model.getValueInRange({
|
|
685
|
+
startLineNumber: position.lineNumber,
|
|
686
|
+
startColumn: position.column,
|
|
687
|
+
endLineNumber: position.lineNumber,
|
|
688
|
+
endColumn: position.column + 1
|
|
689
|
+
});
|
|
690
|
+
const closingBracketAlreadyPresent = charAfterCursor === ']';
|
|
691
|
+
const startColumn = position.column - typed.length;
|
|
692
|
+
const endColumn = closingBracketAlreadyPresent ? position.column + 1 : position.column;
|
|
693
|
+
const suggestions = keys.map(key => ({
|
|
694
|
+
label: key,
|
|
695
|
+
kind: monaco.languages.CompletionItemKind.Property,
|
|
696
|
+
insertText: `${quoteAndEscape(key)}]`,
|
|
697
|
+
range: {
|
|
698
|
+
startLineNumber: position.lineNumber,
|
|
699
|
+
endLineNumber: position.lineNumber,
|
|
700
|
+
startColumn,
|
|
701
|
+
endColumn
|
|
702
|
+
},
|
|
703
|
+
sortText: key
|
|
704
|
+
}));
|
|
705
|
+
return { suggestions };
|
|
706
|
+
}
|
|
707
|
+
// Case 3: fresh new expression – cursor is at a word boundary and the user
|
|
708
|
+
// has started typing a key name.
|
|
709
|
+
const freshMatch = /(?:^|[\s=(<>,;{}\[\]"'`])(\w*)$/.exec(lineText);
|
|
710
|
+
if (freshMatch) {
|
|
711
|
+
const typed = freshMatch[1];
|
|
712
|
+
if (!typed)
|
|
713
|
+
return { suggestions: [] };
|
|
714
|
+
const startColumn = position.column - typed.length;
|
|
715
|
+
const suggestions = keys
|
|
716
|
+
.filter(key => key.startsWith(typed))
|
|
717
|
+
.map(key => {
|
|
718
|
+
const insertText = this.getFormattedPropertyExpression(key);
|
|
719
|
+
return {
|
|
720
|
+
label: key,
|
|
721
|
+
kind: monaco.languages.CompletionItemKind.Property,
|
|
722
|
+
insertText,
|
|
723
|
+
range: makeRange(startColumn),
|
|
724
|
+
detail: insertText,
|
|
725
|
+
filterText: key,
|
|
726
|
+
sortText: key
|
|
727
|
+
};
|
|
728
|
+
});
|
|
729
|
+
return { suggestions };
|
|
730
|
+
}
|
|
731
|
+
return { suggestions: [] };
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
this.suggestionProviders.push(monaco.languages.registerCompletionItemProvider('html', providerOptions), monaco.languages.registerCompletionItemProvider('javascript', providerOptions));
|
|
735
|
+
}
|
|
736
|
+
getFormattedPropertyExpression(key) {
|
|
737
|
+
const nonAlphanumericRegex = /[^a-zA-Z0-9]/;
|
|
738
|
+
const formattedKey = nonAlphanumericRegex.test(key) ? `[${quoteAndEscape(key)}]` : `${key}`;
|
|
739
|
+
return '${this.c8yProperties?.' + formattedKey + '}';
|
|
740
|
+
}
|
|
583
741
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: WidgetCodeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
584
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: WidgetCodeEditorComponent, isStandalone: true, selector: "c8y-widget-code-editor", inputs: { mode: "mode", config: "config" }, viewQueries: [{ propertyName: "editorComponent", first: true, predicate: EditorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<c8y-widget-config-feedback>\n <div class=\"d-flex\">\n @if (config?.devMode && !config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n translate\n >\n Advanced developer mode\n </span>\n }\n </div>\n <div class=\"d-flex\">\n @if (config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n [title]=\"\n 'This widget is in legacy mode. Consider to upgrade this to a new HTML widget. Read our documentation on details to transform your widget'\n | translate\n \"\n translate\n >\n Legacy mode\n </span>\n }\n </div>\n</c8y-widget-config-feedback>\n\n<div class=\"d-flex d-col fit-h fit-w\">\n <c8y-html-widget-advanced-settings\n [devMode]=\"config?.devMode\"\n [cssEncapsulation]=\"config?.options?.cssEncapsulation\"\n ></c8y-html-widget-advanced-settings>\n\n <fieldset class=\"c8y-fieldset p-0 overflow-hidden\">\n <legend class=\"m-l-16 p-l-0\">{{ 'Code' | translate }}</legend>\n\n <div class=\"btn-group btn-group-sm m-l-0 p-t-8 p-b-8 p-l-16 p-r-16 fit-w d-flex\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Undo' | translate\"\n [tooltip]=\"'Undo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"undo()\"\n >\n <i [c8yIcon]=\"'undo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Redo' | translate\"\n [tooltip]=\"'Redo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"redo()\"\n >\n <i [c8yIcon]=\"'redo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Format code' | translate\"\n [tooltip]=\"'Format code' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"formatCode()\"\n >\n <i [c8yIcon]=\"'format-align-left'\"></i>\n </button>\n\n <label class=\"c8y-switch m-l-auto\">\n <input\n type=\"checkbox\"\n [checked]=\"isAutoSaveEnabled\"\n (change)=\"isAutoSaveEnabled = !isAutoSaveEnabled\"\n />\n <span></span>\n <span translate>Auto save</span>\n </label>\n </div>\n\n <div\n class=\"btn-toolbar m-0 p-relative\"\n role=\"toolbar\"\n >\n <c8y-tabs-outlet\n class=\"elevation-none\"\n [outletName]=\"TAB_OUTLET_NAME\"\n [orientation]=\"'horizontal'\"\n [openFirstTab]=\"false\"\n ></c8y-tabs-outlet>\n <c8y-tab\n [icon]=\"'code'\"\n [label]=\"(config?.devMode ? TAB_WEBCOMPONENT_LABEL : TAB_HTML_LABEL) | translate\"\n [priority]=\"100\"\n [showAlways]=\"true\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'code'\"\n (onSelect)=\"switchMode('code')\"\n ></c8y-tab>\n @if (!config?.devMode && !config?.legacy) {\n <c8y-tab\n [icon]=\"'c8y-css'\"\n [label]=\"TAB_CSS_LABEL | translate\"\n [priority]=\"0\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'css'\"\n (onSelect)=\"switchMode('css')\"\n ></c8y-tab>\n }\n </div>\n\n @if (!isLoading) {\n @if (!(mode === 'css' && config?.devMode)) {\n <c8y-editor\n class=\"flex-grow d-block\"\n style=\"height: 450px\"\n [ngModel]=\"value\"\n (ngModelChange)=\"changeCode($event)\"\n [editorOptions]=\"{\n language,\n tabSize: 2,\n insertSpaces: true,\n minimap: { enabled: false }\n }\"\n (editorInit)=\"editorLoaded($event)\"\n ></c8y-editor>\n }\n } @else {\n <c8y-loading></c8y-loading>\n }\n </fieldset>\n</div>\n", dependencies: [{ kind: "component", type: EditorComponent, selector: "c8y-editor", inputs: ["editorOptions", "theme"], outputs: ["editorInit"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.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: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$1.TabsOutletComponent, selector: "c8y-tabs-outlet,c8y-ui-tabs", inputs: ["tabs", "orientation", "navigatorOpen", "outletName", "context", "openFirstTab", "hasHeader"] }, { kind: "component", type: i2$1.TabComponent, selector: "c8y-tab", inputs: ["path", "label", "icon", "priority", "orientation", "injector", "tabsOutlet", "isActive", "text", "showAlways"], outputs: ["onSelect"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.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: "ngmodule", type: PopoverModule }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: AdvancedSettingsComponent, selector: "c8y-html-widget-advanced-settings", inputs: ["devMode", "cssEncapsulation"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
742
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: WidgetCodeEditorComponent, isStandalone: true, selector: "c8y-widget-code-editor", inputs: { mode: "mode", config: "config" }, viewQueries: [{ propertyName: "editorComponent", first: true, predicate: EditorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<c8y-widget-config-feedback>\n <div class=\"d-flex\">\n @if (config?.devMode && !config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n translate\n >\n Advanced developer mode\n </span>\n }\n </div>\n <div class=\"d-flex\">\n @if (config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n [title]=\"\n 'This widget is in legacy mode. Consider to upgrade this to a new HTML widget. Read our documentation on details to transform your widget'\n | translate\n \"\n translate\n >\n Legacy mode\n </span>\n }\n </div>\n</c8y-widget-config-feedback>\n\n<div class=\"d-flex d-col fit-h fit-w\">\n <c8y-html-widget-advanced-settings\n [devMode]=\"config?.devMode\"\n [cssEncapsulation]=\"config?.options?.cssEncapsulation\"\n ></c8y-html-widget-advanced-settings>\n\n <fieldset class=\"c8y-fieldset p-0 overflow-hidden\">\n <legend class=\"m-l-16 p-l-0\">{{ 'Code' | translate }}</legend>\n\n <div class=\"btn-group btn-group-sm m-l-0 p-t-8 p-b-8 p-l-16 p-r-16 fit-w d-flex\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Undo' | translate\"\n [tooltip]=\"'Undo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"undo()\"\n >\n <i [c8yIcon]=\"'undo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Redo' | translate\"\n [tooltip]=\"'Redo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"redo()\"\n >\n <i [c8yIcon]=\"'redo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Format code' | translate\"\n [tooltip]=\"'Format code' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"formatCode()\"\n >\n <i [c8yIcon]=\"'format-align-left'\"></i>\n </button>\n\n @let propertyKeys = propertyKeys$ | async;\n @if (mode !== 'css' && propertyKeys?.length) {\n <div\n class=\"btn-group btn-group-sm m-l-4\"\n container=\"body\"\n dropdown\n >\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Insert property' | translate\"\n [tooltip]=\"'Insert property' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i [c8yIcon]=\"'plus-circle'\"></i>\n </button>\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n >\n @for (key of propertyKeys; track key) {\n <li>\n <button\n class=\"dropdown-item\"\n type=\"button\"\n (click)=\"insertPropertyAtCursor(key)\"\n >\n {{ key }}\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n <label class=\"c8y-switch m-l-auto\">\n <input\n type=\"checkbox\"\n [checked]=\"isAutoSaveEnabled\"\n (change)=\"isAutoSaveEnabled = !isAutoSaveEnabled\"\n />\n <span></span>\n <span translate>Auto save</span>\n </label>\n </div>\n\n <div\n class=\"btn-toolbar m-0 p-relative\"\n role=\"toolbar\"\n >\n <c8y-tabs-outlet\n class=\"elevation-none\"\n [outletName]=\"TAB_OUTLET_NAME\"\n [orientation]=\"'horizontal'\"\n [openFirstTab]=\"false\"\n ></c8y-tabs-outlet>\n <c8y-tab\n [icon]=\"'code'\"\n [label]=\"(config?.devMode ? TAB_WEBCOMPONENT_LABEL : TAB_HTML_LABEL) | translate\"\n [priority]=\"100\"\n [showAlways]=\"true\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'code'\"\n (onSelect)=\"switchMode('code')\"\n ></c8y-tab>\n @if (!config?.devMode && !config?.legacy) {\n <c8y-tab\n [icon]=\"'c8y-css'\"\n [label]=\"TAB_CSS_LABEL | translate\"\n [priority]=\"0\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'css'\"\n (onSelect)=\"switchMode('css')\"\n ></c8y-tab>\n }\n </div>\n\n @if (!isLoading) {\n @if (!(mode === 'css' && config?.devMode)) {\n <c8y-editor\n class=\"flex-grow d-block\"\n style=\"height: 450px\"\n [ngModel]=\"value\"\n (ngModelChange)=\"changeCode($event)\"\n [editorOptions]=\"{\n language,\n tabSize: 2,\n insertSpaces: true,\n minimap: { enabled: false }\n }\"\n (editorInit)=\"editorLoaded($event)\"\n ></c8y-editor>\n }\n } @else {\n <c8y-loading></c8y-loading>\n }\n </fieldset>\n</div>\n", dependencies: [{ kind: "component", type: EditorComponent, selector: "c8y-editor", inputs: ["editorOptions", "theme"], outputs: ["editorInit"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.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: "component", type: WidgetConfigFeedbackComponent, selector: "c8y-widget-config-feedback" }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i2$1.TabsOutletComponent, selector: "c8y-tabs-outlet,c8y-ui-tabs", inputs: ["tabs", "orientation", "navigatorOpen", "outletName", "context", "openFirstTab", "hasHeader"] }, { kind: "component", type: i2$1.TabComponent, selector: "c8y-tab", inputs: ["path", "label", "icon", "priority", "orientation", "injector", "tabsOutlet", "isActive", "text", "showAlways"], outputs: ["onSelect"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i3.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: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i4.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i4.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i4.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: AdvancedSettingsComponent, selector: "c8y-html-widget-advanced-settings", inputs: ["devMode", "cssEncapsulation"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
585
743
|
}
|
|
586
744
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: WidgetCodeEditorComponent, decorators: [{
|
|
587
745
|
type: Component,
|
|
588
746
|
args: [{ standalone: true, imports: [
|
|
747
|
+
AsyncPipe,
|
|
589
748
|
EditorComponent,
|
|
590
749
|
FormsModule,
|
|
591
750
|
IconDirective,
|
|
@@ -594,9 +753,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
594
753
|
TabsModule,
|
|
595
754
|
TooltipModule,
|
|
596
755
|
PopoverModule,
|
|
756
|
+
BsDropdownModule,
|
|
597
757
|
LoadingComponent,
|
|
598
758
|
AdvancedSettingsComponent
|
|
599
|
-
], selector: 'c8y-widget-code-editor', template: "<c8y-widget-config-feedback>\n <div class=\"d-flex\">\n @if (config?.devMode && !config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n translate\n >\n Advanced developer mode\n </span>\n }\n </div>\n <div class=\"d-flex\">\n @if (config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n [title]=\"\n 'This widget is in legacy mode. Consider to upgrade this to a new HTML widget. Read our documentation on details to transform your widget'\n | translate\n \"\n translate\n >\n Legacy mode\n </span>\n }\n </div>\n</c8y-widget-config-feedback>\n\n<div class=\"d-flex d-col fit-h fit-w\">\n <c8y-html-widget-advanced-settings\n [devMode]=\"config?.devMode\"\n [cssEncapsulation]=\"config?.options?.cssEncapsulation\"\n ></c8y-html-widget-advanced-settings>\n\n <fieldset class=\"c8y-fieldset p-0 overflow-hidden\">\n <legend class=\"m-l-16 p-l-0\">{{ 'Code' | translate }}</legend>\n\n <div class=\"btn-group btn-group-sm m-l-0 p-t-8 p-b-8 p-l-16 p-r-16 fit-w d-flex\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Undo' | translate\"\n [tooltip]=\"'Undo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"undo()\"\n >\n <i [c8yIcon]=\"'undo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Redo' | translate\"\n [tooltip]=\"'Redo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"redo()\"\n >\n <i [c8yIcon]=\"'redo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Format code' | translate\"\n [tooltip]=\"'Format code' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"formatCode()\"\n >\n <i [c8yIcon]=\"'format-align-left'\"></i>\n </button>\n\n <label class=\"c8y-switch m-l-auto\">\n <input\n type=\"checkbox\"\n [checked]=\"isAutoSaveEnabled\"\n (change)=\"isAutoSaveEnabled = !isAutoSaveEnabled\"\n />\n <span></span>\n <span translate>Auto save</span>\n </label>\n </div>\n\n <div\n class=\"btn-toolbar m-0 p-relative\"\n role=\"toolbar\"\n >\n <c8y-tabs-outlet\n class=\"elevation-none\"\n [outletName]=\"TAB_OUTLET_NAME\"\n [orientation]=\"'horizontal'\"\n [openFirstTab]=\"false\"\n ></c8y-tabs-outlet>\n <c8y-tab\n [icon]=\"'code'\"\n [label]=\"(config?.devMode ? TAB_WEBCOMPONENT_LABEL : TAB_HTML_LABEL) | translate\"\n [priority]=\"100\"\n [showAlways]=\"true\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'code'\"\n (onSelect)=\"switchMode('code')\"\n ></c8y-tab>\n @if (!config?.devMode && !config?.legacy) {\n <c8y-tab\n [icon]=\"'c8y-css'\"\n [label]=\"TAB_CSS_LABEL | translate\"\n [priority]=\"0\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'css'\"\n (onSelect)=\"switchMode('css')\"\n ></c8y-tab>\n }\n </div>\n\n @if (!isLoading) {\n @if (!(mode === 'css' && config?.devMode)) {\n <c8y-editor\n class=\"flex-grow d-block\"\n style=\"height: 450px\"\n [ngModel]=\"value\"\n (ngModelChange)=\"changeCode($event)\"\n [editorOptions]=\"{\n language,\n tabSize: 2,\n insertSpaces: true,\n minimap: { enabled: false }\n }\"\n (editorInit)=\"editorLoaded($event)\"\n ></c8y-editor>\n }\n } @else {\n <c8y-loading></c8y-loading>\n }\n </fieldset>\n</div>\n" }]
|
|
759
|
+
], selector: 'c8y-widget-code-editor', template: "<c8y-widget-config-feedback>\n <div class=\"d-flex\">\n @if (config?.devMode && !config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n translate\n >\n Advanced developer mode\n </span>\n }\n </div>\n <div class=\"d-flex\">\n @if (config?.legacy) {\n <span\n class=\"tag tag--warning text-12\"\n [title]=\"\n 'This widget is in legacy mode. Consider to upgrade this to a new HTML widget. Read our documentation on details to transform your widget'\n | translate\n \"\n translate\n >\n Legacy mode\n </span>\n }\n </div>\n</c8y-widget-config-feedback>\n\n<div class=\"d-flex d-col fit-h fit-w\">\n <c8y-html-widget-advanced-settings\n [devMode]=\"config?.devMode\"\n [cssEncapsulation]=\"config?.options?.cssEncapsulation\"\n ></c8y-html-widget-advanced-settings>\n\n <fieldset class=\"c8y-fieldset p-0 overflow-hidden\">\n <legend class=\"m-l-16 p-l-0\">{{ 'Code' | translate }}</legend>\n\n <div class=\"btn-group btn-group-sm m-l-0 p-t-8 p-b-8 p-l-16 p-r-16 fit-w d-flex\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Undo' | translate\"\n [tooltip]=\"'Undo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"undo()\"\n >\n <i [c8yIcon]=\"'undo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Redo' | translate\"\n [tooltip]=\"'Redo' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"redo()\"\n >\n <i [c8yIcon]=\"'redo'\"></i>\n </button>\n\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Format code' | translate\"\n [tooltip]=\"'Format code' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"formatCode()\"\n >\n <i [c8yIcon]=\"'format-align-left'\"></i>\n </button>\n\n @let propertyKeys = propertyKeys$ | async;\n @if (mode !== 'css' && propertyKeys?.length) {\n <div\n class=\"btn-group btn-group-sm m-l-4\"\n container=\"body\"\n dropdown\n >\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Insert property' | translate\"\n [tooltip]=\"'Insert property' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n dropdownToggle\n >\n <i [c8yIcon]=\"'plus-circle'\"></i>\n </button>\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n >\n @for (key of propertyKeys; track key) {\n <li>\n <button\n class=\"dropdown-item\"\n type=\"button\"\n (click)=\"insertPropertyAtCursor(key)\"\n >\n {{ key }}\n </button>\n </li>\n }\n </ul>\n </div>\n }\n\n <label class=\"c8y-switch m-l-auto\">\n <input\n type=\"checkbox\"\n [checked]=\"isAutoSaveEnabled\"\n (change)=\"isAutoSaveEnabled = !isAutoSaveEnabled\"\n />\n <span></span>\n <span translate>Auto save</span>\n </label>\n </div>\n\n <div\n class=\"btn-toolbar m-0 p-relative\"\n role=\"toolbar\"\n >\n <c8y-tabs-outlet\n class=\"elevation-none\"\n [outletName]=\"TAB_OUTLET_NAME\"\n [orientation]=\"'horizontal'\"\n [openFirstTab]=\"false\"\n ></c8y-tabs-outlet>\n <c8y-tab\n [icon]=\"'code'\"\n [label]=\"(config?.devMode ? TAB_WEBCOMPONENT_LABEL : TAB_HTML_LABEL) | translate\"\n [priority]=\"100\"\n [showAlways]=\"true\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'code'\"\n (onSelect)=\"switchMode('code')\"\n ></c8y-tab>\n @if (!config?.devMode && !config?.legacy) {\n <c8y-tab\n [icon]=\"'c8y-css'\"\n [label]=\"TAB_CSS_LABEL | translate\"\n [priority]=\"0\"\n [tabsOutlet]=\"TAB_OUTLET_NAME\"\n [isActive]=\"mode === 'css'\"\n (onSelect)=\"switchMode('css')\"\n ></c8y-tab>\n }\n </div>\n\n @if (!isLoading) {\n @if (!(mode === 'css' && config?.devMode)) {\n <c8y-editor\n class=\"flex-grow d-block\"\n style=\"height: 450px\"\n [ngModel]=\"value\"\n (ngModelChange)=\"changeCode($event)\"\n [editorOptions]=\"{\n language,\n tabSize: 2,\n insertSpaces: true,\n minimap: { enabled: false }\n }\"\n (editorInit)=\"editorLoaded($event)\"\n ></c8y-editor>\n }\n } @else {\n <c8y-loading></c8y-loading>\n }\n </fieldset>\n</div>\n" }]
|
|
600
760
|
}], propDecorators: { mode: [{
|
|
601
761
|
type: Input
|
|
602
762
|
}], config: [{
|
|
@@ -607,11 +767,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
607
767
|
}] } });
|
|
608
768
|
|
|
609
769
|
class HtmlWidgetConfigComponent {
|
|
610
|
-
constructor() {
|
|
611
|
-
this.options = inject(OptionsService);
|
|
612
|
-
this.htmlWidgetConfigService = inject(HtmlWidgetConfigService);
|
|
613
|
-
this.widgetConfigService = inject(WidgetConfigService);
|
|
614
|
-
}
|
|
615
770
|
set htmlPreviewTemplate(template) {
|
|
616
771
|
if (template) {
|
|
617
772
|
this.widgetConfigService.setPreview(template);
|
|
@@ -620,19 +775,56 @@ class HtmlWidgetConfigComponent {
|
|
|
620
775
|
this.widgetConfigService.setPreview(null);
|
|
621
776
|
}
|
|
622
777
|
}
|
|
778
|
+
constructor() {
|
|
779
|
+
this.alert = inject(AlertService);
|
|
780
|
+
this.options = inject(OptionsService);
|
|
781
|
+
this.htmlWidgetConfigService = inject(HtmlWidgetConfigService);
|
|
782
|
+
this.widgetConfigService = inject(WidgetConfigService);
|
|
783
|
+
this.assetPropertyMappings = inject(AssetPropertyMappingsService);
|
|
784
|
+
this.controls = PRESET_NAME.AUTO_REFRESH_ONLY;
|
|
785
|
+
this.destroyRef = inject(DestroyRef);
|
|
786
|
+
this.realtimeControl$ = this.widgetConfigService.currentConfig$.pipe(map$1(config => config?.refreshOption === REFRESH_OPTION.LIVE && config?.isAutoRefreshEnabled === true), distinctUntilChanged$1());
|
|
787
|
+
this.propertyValues$ = this.widgetConfigService.currentConfig$.pipe(switchMap$1(config => this.assetPropertyMappings.getValues$(config?.properties, this.realtimeControl$)));
|
|
788
|
+
this.globalContextState$ = this.widgetConfigService.currentConfig$.pipe(map$1(config => config));
|
|
789
|
+
this.htmlWidgetConfigService.notify$
|
|
790
|
+
.pipe(takeUntilDestroyed(this.destroyRef), filter$1((n) => n.type === 'asset-property-mapping-key-renamed'))
|
|
791
|
+
.subscribe(notification => this.handleRename(notification));
|
|
792
|
+
}
|
|
623
793
|
ngOnDestroy() {
|
|
624
794
|
// sadly the service is component scoped
|
|
625
795
|
// but still not recycled correctly. That is why we do
|
|
626
796
|
// it here.
|
|
627
797
|
this.htmlWidgetConfigService.destroy();
|
|
628
798
|
}
|
|
799
|
+
handleRename(notification) {
|
|
800
|
+
const { oldKey, newKey } = notification;
|
|
801
|
+
const htmlWidgetConfig = this.widgetConfigService.currentConfig;
|
|
802
|
+
if (!htmlWidgetConfig?.config) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
const newCode = renamePropertyKeyInCode(htmlWidgetConfig.config.code, oldKey, newKey);
|
|
806
|
+
if (newCode === htmlWidgetConfig.config.code) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
const updated = { ...htmlWidgetConfig.config, code: newCode };
|
|
810
|
+
this.htmlWidgetConfigService.save(updated);
|
|
811
|
+
this.htmlWidgetConfigService.configChanged$.next(updated);
|
|
812
|
+
this.alert.success(gettext('Renamed asset property and updated references in HTML code.'));
|
|
813
|
+
}
|
|
629
814
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlWidgetConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
630
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
815
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: HtmlWidgetConfigComponent, isStandalone: true, selector: "c8y-html-widget-config", viewQueries: [{ propertyName: "htmlPreviewTemplate", first: true, predicate: ["htmlPreview"], descendants: true }], ngImport: i0, template: "<c8y-widget-code-editor\n [config]=\"htmlWidgetConfigService.config$ | async\"\n [mode]=\"'code'\"\n></c8y-widget-code-editor>\n\n<ng-template #htmlPreview>\n @if ((widgetConfigService.currentConfig$ | async)?.displayMode !== 'dashboard') {\n <c8y-local-controls\n [controls]=\"controls\"\n [displayMode]=\"(widgetConfigService.currentConfig$ | async)?.displayMode\"\n [config]=\"globalContextState$ | async\"\n [disabled]=\"true\"\n ></c8y-local-controls>\n }\n <c8y-html-frame\n [config]=\"htmlWidgetConfigService.codeEditorChangeConfig$ | async\"\n [device]=\"(widgetConfigService.currentConfig$ | async).device\"\n [propertyValues$]=\"propertyValues$\"\n [useSalt]=\"true\"\n ></c8y-html-frame>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: HtmlFrameComponent, selector: "c8y-html-frame", inputs: ["config", "device", "propertyValues$", "useSalt"] }, { kind: "component", type: WidgetCodeEditorComponent, selector: "c8y-widget-code-editor", inputs: ["mode", "config"] }, { kind: "component", type: LocalControlsComponent, selector: "c8y-local-controls", inputs: ["controls", "displayMode", "config", "isLoading", "disabled", "emitRefresh"], outputs: ["configChange", "refresh"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); }
|
|
631
816
|
}
|
|
632
817
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlWidgetConfigComponent, decorators: [{
|
|
633
818
|
type: Component,
|
|
634
|
-
args: [{ selector: 'c8y-html-widget-config', standalone: true, imports: [
|
|
635
|
-
|
|
819
|
+
args: [{ selector: 'c8y-html-widget-config', standalone: true, imports: [
|
|
820
|
+
RouterModule,
|
|
821
|
+
FormsModule,
|
|
822
|
+
AsyncPipe,
|
|
823
|
+
HtmlFrameComponent,
|
|
824
|
+
WidgetCodeEditorComponent,
|
|
825
|
+
LocalControlsComponent
|
|
826
|
+
], template: "<c8y-widget-code-editor\n [config]=\"htmlWidgetConfigService.config$ | async\"\n [mode]=\"'code'\"\n></c8y-widget-code-editor>\n\n<ng-template #htmlPreview>\n @if ((widgetConfigService.currentConfig$ | async)?.displayMode !== 'dashboard') {\n <c8y-local-controls\n [controls]=\"controls\"\n [displayMode]=\"(widgetConfigService.currentConfig$ | async)?.displayMode\"\n [config]=\"globalContextState$ | async\"\n [disabled]=\"true\"\n ></c8y-local-controls>\n }\n <c8y-html-frame\n [config]=\"htmlWidgetConfigService.codeEditorChangeConfig$ | async\"\n [device]=\"(widgetConfigService.currentConfig$ | async).device\"\n [propertyValues$]=\"propertyValues$\"\n [useSalt]=\"true\"\n ></c8y-html-frame>\n</ng-template>\n" }]
|
|
827
|
+
}], ctorParameters: () => [], propDecorators: { htmlPreviewTemplate: [{
|
|
636
828
|
type: ViewChild,
|
|
637
829
|
args: ['htmlPreview']
|
|
638
830
|
}] } });
|
|
@@ -679,10 +871,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
679
871
|
}] });
|
|
680
872
|
|
|
681
873
|
class HtmlWidgetComponent {
|
|
874
|
+
constructor() {
|
|
875
|
+
this.config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : []));
|
|
876
|
+
this.realtimeControl$ = new BehaviorSubject(false);
|
|
877
|
+
this.propertyValues$ = computed(() => this.assetPropertiesMappings.getValues$(this.config()?.properties, this.realtimeControl$.asObservable()), ...(ngDevMode ? [{ debugName: "propertyValues$" }] : []));
|
|
878
|
+
this.dashboardChild = inject(DashboardChildComponent);
|
|
879
|
+
this.displayMode = signal(GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD, ...(ngDevMode ? [{ debugName: "displayMode" }] : []));
|
|
880
|
+
this.contextConfig = signal({}, ...(ngDevMode ? [{ debugName: "contextConfig" }] : []));
|
|
881
|
+
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
882
|
+
/**
|
|
883
|
+
* Controls link state to global context:
|
|
884
|
+
* - true/undefined: Widget follows global time context
|
|
885
|
+
* - false: Widget uses local state, ignores global changes
|
|
886
|
+
* Set to false when user is interacting (scrolling, zooming) to prevent interruption
|
|
887
|
+
*/
|
|
888
|
+
this.isLinkedToGlobal = signal(undefined, ...(ngDevMode ? [{ debugName: "isLinkedToGlobal" }] : []));
|
|
889
|
+
this.GLOBAL_CONTEXT_DISPLAY_MODE = GLOBAL_CONTEXT_DISPLAY_MODE;
|
|
890
|
+
this.PRESET_NAME = PRESET_NAME;
|
|
891
|
+
this.assetPropertiesMappings = inject(AssetPropertyMappingsService);
|
|
892
|
+
}
|
|
682
893
|
ngOnInit() {
|
|
683
|
-
|
|
684
|
-
|
|
894
|
+
const config = this.config();
|
|
895
|
+
if (config?.html && !config.config) {
|
|
896
|
+
config.config = this.mapLegacyConfig(config);
|
|
685
897
|
}
|
|
898
|
+
const { displayMode = GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD, dateTimeContext, aggregation, isAutoRefreshEnabled, refreshInterval, refreshOption } = config;
|
|
899
|
+
this.displayMode.set(displayMode);
|
|
900
|
+
this.contextConfig.set({
|
|
901
|
+
dateTimeContext,
|
|
902
|
+
aggregation,
|
|
903
|
+
isAutoRefreshEnabled,
|
|
904
|
+
refreshInterval,
|
|
905
|
+
refreshOption
|
|
906
|
+
});
|
|
907
|
+
// Initialize realtime from persisted config — controls may be hidden in
|
|
908
|
+
// config display mode (AUTO_REFRESH_ONLY.config = []), in which case
|
|
909
|
+
// onContextChange never fires and realtimeControl$ would stay false.
|
|
910
|
+
this.realtimeControl$.next(this.shouldEnableRealtime());
|
|
911
|
+
}
|
|
912
|
+
onContextChange(event) {
|
|
913
|
+
const { context } = event;
|
|
914
|
+
this.contextConfig.set(context);
|
|
915
|
+
this.realtimeControl$.next(this.shouldEnableRealtime());
|
|
916
|
+
}
|
|
917
|
+
getDashboardChild() {
|
|
918
|
+
return this.dashboardChild;
|
|
919
|
+
}
|
|
920
|
+
shouldEnableRealtime() {
|
|
921
|
+
const ctx = this.contextConfig();
|
|
922
|
+
return ctx.refreshOption === REFRESH_OPTION.LIVE && ctx.isAutoRefreshEnabled === true;
|
|
686
923
|
}
|
|
687
924
|
mapLegacyConfig(current) {
|
|
688
925
|
const isAlreadyInAdvancedMode = current?.config?.devMode === true;
|
|
@@ -701,14 +938,17 @@ class HtmlWidgetComponent {
|
|
|
701
938
|
};
|
|
702
939
|
}
|
|
703
940
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
704
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
941
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: HtmlWidgetComponent, isStandalone: true, selector: "c8y-html-widget", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n <c8y-global-context-connector\n [controls]=\"PRESET_NAME.AUTO_REFRESH_ONLY\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n [dashboardChild]=\"getDashboardChild()\"\n [linked]=\"isLinkedToGlobal()\"\n [emitRefresh]=\"false\"\n (configChange)=\"onContextChange($event)\"\n >\n </c8y-global-context-connector>\n} @else {\n <c8y-local-controls\n [controls]=\"PRESET_NAME.AUTO_REFRESH_ONLY\"\n [displayMode]=\"displayMode()\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n [emitRefresh]=\"false\"\n (configChange)=\"onContextChange($event)\"\n >\n </c8y-local-controls>\n}\n\n<div class=\"p-16\">\n <c8y-html-frame\n [config]=\"config().config\"\n [device]=\"config().device\"\n [propertyValues$]=\"propertyValues$()\"\n ></c8y-html-frame>\n</div>\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "component", type: HtmlFrameComponent, selector: "c8y-html-frame", inputs: ["config", "device", "propertyValues$", "useSalt"] }, { kind: "component", type: GlobalContextConnectorComponent, selector: "c8y-global-context-connector", inputs: ["controls", "config", "isLoading", "dashboardChild", "linked", "emitRefresh"], outputs: ["configChange", "refresh", "linkedChange"] }, { kind: "component", type: LocalControlsComponent, selector: "c8y-local-controls", inputs: ["controls", "displayMode", "config", "isLoading", "disabled", "emitRefresh"], outputs: ["configChange", "refresh"] }] }); }
|
|
705
942
|
}
|
|
706
943
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HtmlWidgetComponent, decorators: [{
|
|
707
944
|
type: Component,
|
|
708
|
-
args: [{ selector: 'c8y-html-widget', standalone: true, imports: [
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
945
|
+
args: [{ selector: 'c8y-html-widget', standalone: true, imports: [
|
|
946
|
+
RouterModule,
|
|
947
|
+
HtmlFrameComponent,
|
|
948
|
+
GlobalContextConnectorComponent,
|
|
949
|
+
LocalControlsComponent
|
|
950
|
+
], template: "@if (displayMode() === GLOBAL_CONTEXT_DISPLAY_MODE.DASHBOARD) {\n <c8y-global-context-connector\n [controls]=\"PRESET_NAME.AUTO_REFRESH_ONLY\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n [dashboardChild]=\"getDashboardChild()\"\n [linked]=\"isLinkedToGlobal()\"\n [emitRefresh]=\"false\"\n (configChange)=\"onContextChange($event)\"\n >\n </c8y-global-context-connector>\n} @else {\n <c8y-local-controls\n [controls]=\"PRESET_NAME.AUTO_REFRESH_ONLY\"\n [displayMode]=\"displayMode()\"\n [config]=\"contextConfig()\"\n [isLoading]=\"isLoading()\"\n [emitRefresh]=\"false\"\n (configChange)=\"onContextChange($event)\"\n >\n </c8y-local-controls>\n}\n\n<div class=\"p-16\">\n <c8y-html-frame\n [config]=\"config().config\"\n [device]=\"config().device\"\n [propertyValues$]=\"propertyValues$()\"\n ></c8y-html-frame>\n</div>\n" }]
|
|
951
|
+
}], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
|
|
712
952
|
|
|
713
953
|
/**
|
|
714
954
|
* Generated bundle index. Do not edit.
|