@c8y/ngx-components 1023.17.6 → 1023.17.8
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/fesm2022/c8y-ngx-components-actility-device-registration.mjs +16 -16
- package/fesm2022/c8y-ngx-components-advanced-software-management.mjs +7 -7
- package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs +9 -9
- package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +12 -12
- package/fesm2022/c8y-ngx-components-ai.mjs +3 -3
- package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs +34 -34
- package/fesm2022/c8y-ngx-components-alarms-cockpit.mjs +4 -4
- package/fesm2022/c8y-ngx-components-alarms.mjs +76 -76
- package/fesm2022/c8y-ngx-components-api.mjs +7 -7
- package/fesm2022/c8y-ngx-components-app-logs.mjs +10 -10
- package/fesm2022/c8y-ngx-components-asset-properties.mjs +39 -39
- package/fesm2022/{c8y-ngx-components-asset-property-grid.component-CHjd7Q21.mjs → c8y-ngx-components-asset-property-grid.component-QedBlFUH.mjs} +13 -13
- package/fesm2022/{c8y-ngx-components-asset-property-grid.component-CHjd7Q21.mjs.map → c8y-ngx-components-asset-property-grid.component-QedBlFUH.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-assets-navigator.mjs +32 -32
- package/fesm2022/c8y-ngx-components-auth-configuration.mjs +114 -114
- package/fesm2022/c8y-ngx-components-binary-file-download.mjs +7 -7
- package/fesm2022/c8y-ngx-components-bookmarks.mjs +13 -13
- package/fesm2022/c8y-ngx-components-branding-base-branding.mjs +4 -4
- package/fesm2022/c8y-ngx-components-branding-dark-theme.mjs +7 -7
- package/fesm2022/c8y-ngx-components-branding-extra-css-branding-editor.mjs +7 -7
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor-lazy.mjs +3 -3
- package/fesm2022/c8y-ngx-components-branding-plain-branding-editor.mjs +7 -7
- package/fesm2022/c8y-ngx-components-branding-shared-data.mjs +15 -15
- package/fesm2022/c8y-ngx-components-branding-shared-lazy-add-branding-modal.mjs +6 -6
- package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs +36 -36
- package/fesm2022/c8y-ngx-components-branding-shared.mjs +13 -13
- package/fesm2022/c8y-ngx-components-child-devices.mjs +13 -13
- package/fesm2022/c8y-ngx-components-cockpit-config.mjs +40 -40
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-alarm-count-config.component-Bl18pHcM.mjs → c8y-ngx-components-computed-asset-properties-alarm-count-config.component-SA0syLy7.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-alarm-count-config.component-Bl18pHcM.mjs.map → c8y-ngx-components-computed-asset-properties-alarm-count-config.component-SA0syLy7.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-C5QMFdX1.mjs → c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-BOmgJI14.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-C5QMFdX1.mjs.map → c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-BOmgJI14.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-event-count-config.component-C-Lc5Ble.mjs → c8y-ngx-components-computed-asset-properties-event-count-config.component-CaTb9cph.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-event-count-config.component-C-Lc5Ble.mjs.map → c8y-ngx-components-computed-asset-properties-event-count-config.component-CaTb9cph.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-last-measurement-config.component-BXfM7hTQ.mjs → c8y-ngx-components-computed-asset-properties-last-measurement-config.component-DkrSvf9F.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-computed-asset-properties-last-measurement-config.component-BXfM7hTQ.mjs.map → c8y-ngx-components-computed-asset-properties-last-measurement-config.component-DkrSvf9F.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-computed-asset-properties.mjs +6 -6
- package/fesm2022/c8y-ngx-components-connectivity.mjs +53 -53
- package/fesm2022/c8y-ngx-components-context-dashboard-asset-add.mjs +10 -10
- package/fesm2022/c8y-ngx-components-context-dashboard-asset-view.mjs +7 -7
- package/fesm2022/c8y-ngx-components-context-dashboard-cockpit-home-dashboard.mjs +11 -11
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-BuGMpNrA.mjs → c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-DM3hASUP.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-BuGMpNrA.mjs.map → c8y-ngx-components-context-dashboard-dashboard-appearance-settings.component-DM3hASUP.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-general-settings.component-DN-f35bA.mjs → c8y-ngx-components-context-dashboard-dashboard-general-settings.component-CC5346kW.mjs} +10 -10
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-general-settings.component-DN-f35bA.mjs.map → c8y-ngx-components-context-dashboard-dashboard-general-settings.component-CC5346kW.mjs.map} +1 -1
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-version-history.component-BlIVEV__.mjs → c8y-ngx-components-context-dashboard-dashboard-version-history.component-CHuc--XM.mjs} +4 -4
- package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-version-history.component-BlIVEV__.mjs.map → c8y-ngx-components-context-dashboard-dashboard-version-history.component-CHuc--XM.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard-device-add.mjs +10 -10
- package/fesm2022/c8y-ngx-components-context-dashboard-device-view.mjs +7 -7
- package/fesm2022/c8y-ngx-components-context-dashboard-devicemanagement.mjs +3 -3
- package/fesm2022/c8y-ngx-components-context-dashboard-state.mjs +3 -3
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +102 -102
- package/fesm2022/{c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-m7YeEj9R.mjs → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-D0C7SH6L.mjs} +16 -16
- package/fesm2022/{c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-m7YeEj9R.mjs.map → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-D0C7SH6L.mjs.map} +1 -1
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab.mjs +12 -12
- package/fesm2022/c8y-ngx-components-dashboard-manager-devicemanagement.mjs +6 -6
- package/fesm2022/c8y-ngx-components-dashboard-manager.mjs +22 -22
- package/fesm2022/c8y-ngx-components-data-broker.mjs +7 -7
- package/fesm2022/c8y-ngx-components-data-grid-columns-asset-type.mjs +3 -3
- package/fesm2022/c8y-ngx-components-data-grid-columns.mjs +3 -3
- package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +24 -24
- package/fesm2022/c8y-ngx-components-datapoint-explorer.mjs +13 -13
- package/fesm2022/c8y-ngx-components-datapoint-library-details.mjs +3 -3
- package/fesm2022/c8y-ngx-components-datapoint-library-list.mjs +3 -3
- package/fesm2022/c8y-ngx-components-datapoint-library-services.mjs +3 -3
- package/fesm2022/c8y-ngx-components-datapoint-library.mjs +4 -4
- package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +40 -40
- package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +33 -33
- package/fesm2022/c8y-ngx-components-default-subscriptions.mjs +16 -16
- package/fesm2022/c8y-ngx-components-device-grid.mjs +43 -43
- package/fesm2022/c8y-ngx-components-device-list.mjs +22 -22
- package/fesm2022/c8y-ngx-components-device-map.mjs +12 -12
- package/fesm2022/c8y-ngx-components-device-profile.mjs +34 -34
- package/fesm2022/c8y-ngx-components-device-protocol-object-mappings.mjs +3 -3
- package/fesm2022/c8y-ngx-components-device-protocols.mjs +16 -16
- package/fesm2022/c8y-ngx-components-device-provisioned-certificates.mjs +13 -13
- package/fesm2022/c8y-ngx-components-device-shell.mjs +31 -31
- package/fesm2022/c8y-ngx-components-diagnostics.mjs +13 -13
- package/fesm2022/c8y-ngx-components-echart.mjs +30 -30
- package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs +43 -43
- package/fesm2022/c8y-ngx-components-ecosystem-archived-confirm.mjs +7 -7
- package/fesm2022/c8y-ngx-components-ecosystem-license-confirm.mjs +10 -10
- package/fesm2022/c8y-ngx-components-ecosystem-plugin-setup-stepper.mjs +7 -7
- package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs +46 -46
- package/fesm2022/c8y-ngx-components-ecosystem.mjs +82 -82
- package/fesm2022/c8y-ngx-components-editor.mjs +6 -6
- package/fesm2022/c8y-ngx-components-events-events-timeline.mjs +3 -3
- package/fesm2022/c8y-ngx-components-events.mjs +3 -3
- package/fesm2022/c8y-ngx-components-exports-list.mjs +6 -6
- package/fesm2022/c8y-ngx-components-file-preview.mjs +7 -7
- package/fesm2022/c8y-ngx-components-files-repository.mjs +19 -19
- package/fesm2022/c8y-ngx-components-global-context.mjs +130 -130
- package/fesm2022/c8y-ngx-components-group-breadcrumbs.mjs +6 -6
- package/fesm2022/c8y-ngx-components-icon-selector.mjs +19 -19
- package/fesm2022/c8y-ngx-components-interval-picker.mjs +3 -3
- package/fesm2022/c8y-ngx-components-location.mjs +28 -28
- package/fesm2022/c8y-ngx-components-loriot-device-registration.mjs +16 -16
- package/fesm2022/c8y-ngx-components-map.mjs +19 -19
- package/fesm2022/c8y-ngx-components-messaging-management.mjs +55 -55
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-from-single.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-list-item.mjs +19 -19
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-stepper.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations-bulk-operations-list.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations-bulk-operations-service.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-bulk-operations-stepper-container.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-bulk-single-operations-list.mjs +3 -3
- package/fesm2022/c8y-ngx-components-operations-create-bulk-operation-details.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-device-selector.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-grid-columns.mjs +12 -12
- package/fesm2022/c8y-ngx-components-operations-operation-details.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations-operation-summary.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-operations-list-item-details.mjs +10 -10
- package/fesm2022/c8y-ngx-components-operations-operations-list.mjs +12 -12
- package/fesm2022/c8y-ngx-components-operations-operations-timeline.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-shared.mjs +10 -10
- package/fesm2022/c8y-ngx-components-operations-status-filter.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-configuration.mjs +7 -7
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-device-profile.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-firmware.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-software.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations-stepper-frames.mjs +13 -13
- package/fesm2022/c8y-ngx-components-operations.mjs +7 -7
- package/fesm2022/c8y-ngx-components-pending-mo-request.mjs +7 -7
- package/fesm2022/c8y-ngx-components-platform-configuration.mjs +10 -10
- package/fesm2022/c8y-ngx-components-protocol-lpwan.mjs +38 -38
- package/fesm2022/c8y-ngx-components-protocol-opcua.mjs +58 -58
- package/fesm2022/c8y-ngx-components-register-device.mjs +58 -58
- package/fesm2022/c8y-ngx-components-remote-access-configurations.mjs +9 -9
- package/fesm2022/c8y-ngx-components-remote-access-data.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-passthrough.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-shared.mjs +6 -6
- package/fesm2022/c8y-ngx-components-remote-access-ssh-remote-access-ssh-endpoint-modal.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-ssh.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-telnet.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-terminal-viewer.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-vnc-remote-access-vnc-endpoint-modal.mjs +3 -3
- package/fesm2022/c8y-ngx-components-remote-access-vnc-vnc-viewer.mjs +6 -6
- package/fesm2022/c8y-ngx-components-remote-access-vnc.mjs +3 -3
- package/fesm2022/c8y-ngx-components-replace-device-replace-device-wizard.mjs +6 -6
- package/fesm2022/c8y-ngx-components-replace-device.mjs +10 -10
- package/fesm2022/c8y-ngx-components-report-dashboard.mjs +16 -16
- package/fesm2022/c8y-ngx-components-reports.mjs +19 -19
- package/fesm2022/c8y-ngx-components-repository-configuration.mjs +48 -48
- package/fesm2022/c8y-ngx-components-repository-firmware.mjs +33 -33
- package/fesm2022/c8y-ngx-components-repository-shared.mjs +34 -34
- package/fesm2022/c8y-ngx-components-repository-software.mjs +42 -42
- package/fesm2022/c8y-ngx-components-repository.mjs +4 -4
- package/fesm2022/c8y-ngx-components-search.mjs +19 -19
- package/fesm2022/c8y-ngx-components-sensor-phone-sensor-phone-modal.mjs +6 -6
- package/fesm2022/c8y-ngx-components-sensor-phone.mjs +7 -7
- package/fesm2022/c8y-ngx-components-services-service-command-tab.mjs +3 -3
- package/fesm2022/c8y-ngx-components-services-shared.mjs +3 -3
- package/fesm2022/c8y-ngx-components-services.mjs +29 -29
- package/fesm2022/c8y-ngx-components-sigfox-device-registration.mjs +16 -16
- package/fesm2022/c8y-ngx-components-sms-gateway.mjs +7 -7
- package/fesm2022/c8y-ngx-components-static-assets-data.mjs +3 -3
- package/fesm2022/c8y-ngx-components-static-assets-modal.mjs +9 -9
- package/fesm2022/c8y-ngx-components-static-assets.mjs +6 -6
- package/fesm2022/c8y-ngx-components-sub-assets.mjs +60 -60
- package/fesm2022/c8y-ngx-components-tenants.mjs +40 -40
- package/fesm2022/c8y-ngx-components-time-context.mjs +6 -6
- package/fesm2022/c8y-ngx-components-tracking.mjs +12 -12
- package/fesm2022/c8y-ngx-components-translation-editor-data.mjs +3 -3
- package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs +12 -12
- package/fesm2022/c8y-ngx-components-translation-editor.mjs +6 -6
- package/fesm2022/c8y-ngx-components-trusted-certificates.mjs +33 -33
- package/fesm2022/c8y-ngx-components-upgrade-upgraded-services.mjs +4 -4
- package/fesm2022/c8y-ngx-components-upgrade.mjs +41 -41
- package/fesm2022/c8y-ngx-components-user-roles.mjs +10 -10
- package/fesm2022/c8y-ngx-components-widgets-definitions-datapoints-graph.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget.mjs +6 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs +19 -19
- package/fesm2022/c8y-ngx-components-widgets-implementations-asset-notes.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-implementations-cockpit-legacy-welcome.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-implementations-cockpit-welcome.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +6 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +27 -27
- package/fesm2022/c8y-ngx-components-widgets-implementations-device-control-message.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-implementations-device-management-welcome.mjs +7 -7
- package/fesm2022/c8y-ngx-components-widgets-implementations-help-and-service-widget.mjs +3 -3
- package/fesm2022/c8y-ngx-components-widgets-implementations-html-widget.mjs +24 -24
- package/fesm2022/c8y-ngx-components-widgets-implementations-image.mjs +9 -9
- package/fesm2022/c8y-ngx-components-widgets-implementations-info-gauge.mjs +18 -18
- package/fesm2022/c8y-ngx-components-widgets-implementations-kpi.mjs +6 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-linear-gauge.mjs +6 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-map.mjs +9 -9
- package/fesm2022/c8y-ngx-components-widgets-implementations-markdown.mjs +9 -9
- package/fesm2022/c8y-ngx-components-widgets-implementations-quick-links.mjs +18 -18
- package/fesm2022/c8y-ngx-components-widgets-implementations-three-d-rotation.mjs +9 -9
- package/fesm2022/c8y-ngx-components.mjs +1371 -1371
- package/package.json +1 -1
|
@@ -191,10 +191,10 @@ class JsonValidationService {
|
|
|
191
191
|
};
|
|
192
192
|
return [...schemasPart, defaultPart];
|
|
193
193
|
}
|
|
194
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
195
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
194
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: JsonValidationService, deps: [{ token: i1.DynamicComponentService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
195
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: JsonValidationService }); }
|
|
196
196
|
}
|
|
197
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
197
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: JsonValidationService, decorators: [{
|
|
198
198
|
type: Injectable
|
|
199
199
|
}], ctorParameters: () => [{ type: i1.DynamicComponentService }] });
|
|
200
200
|
|
|
@@ -254,10 +254,10 @@ class AssignWidgetAssetModalComponent {
|
|
|
254
254
|
selectionChange($event, widgetAsset) {
|
|
255
255
|
widgetAsset.selectedAsset = $event.change.item;
|
|
256
256
|
}
|
|
257
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
258
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AssignWidgetAssetModalComponent, isStandalone: true, selector: "c8y-assign-widget-asset-modal", inputs: { assetsToAlign: "assetsToAlign", contextAsset: "contextAsset", notSupportedWidgets: "notSupportedWidgets" }, ngImport: i0, template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n <div\n class=\"d-flex fit-w j-c-center p-16 p-t-0\"\n *ngIf=\"notSupportedWidgets.length\"\n >\n <div class=\"alert alert-warning\">\n {{\n 'Widgets not supported for asset mapping: {{ notSupportedWidgets\n\n\n\n }}' | translate: { notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n <div\n class=\"p-16 d-flex j-c-center\"\n *ngIf=\"!assetsToAlign.length\"\n >\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n <div *ngIf=\"assetsToAlign.length\">\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n\n <c8y-li\n class=\"c8y-list__item--overflow-visible\"\n *ngFor=\"let widgetAsset of updatedWidgetAssets; let i = index\"\n >\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id } }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? ('Asset selected' | translate)\n : ('Asset not selected' | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': !widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n *ngIf=\"\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n <div\n class=\"d-flex gap-4 boxed-label\"\n *ngIf=\"widgetAsset.selectedAsset\"\n >\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id } }}\n </small>\n </span>\n </div>\n\n <div\n class=\"text-muted boxed-label\"\n *ngIf=\"\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n >\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset = widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n <c8y-asset-selector-miller\n *ngIf=\"dropdown.isOpen\"\n (onSelected)=\"selectionChange($event, widgetAsset); dropdown.hide()\"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n [title]=\"'Accept all suggested' | translate\"\n type=\"button\"\n (click)=\"acceptAllSuggestedAndApply()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n {{ 'Accept all suggested' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n *ngIf=\"device.c8y_IsDevice\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n *ngIf=\"device.c8y_IsDeviceGroup && !device.c8y_IsAsset\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n *ngIf=\"device.c8y_IsAsset\"\n ></i>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i1.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i1.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i3.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { 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: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.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: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
|
|
257
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AssignWidgetAssetModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
258
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: AssignWidgetAssetModalComponent, isStandalone: true, selector: "c8y-assign-widget-asset-modal", inputs: { assetsToAlign: "assetsToAlign", contextAsset: "contextAsset", notSupportedWidgets: "notSupportedWidgets" }, ngImport: i0, template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n <div\n class=\"d-flex fit-w j-c-center p-16 p-t-0\"\n *ngIf=\"notSupportedWidgets.length\"\n >\n <div class=\"alert alert-warning\">\n {{\n 'Widgets not supported for asset mapping: {{ notSupportedWidgets\n\n\n\n }}' | translate: { notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n <div\n class=\"p-16 d-flex j-c-center\"\n *ngIf=\"!assetsToAlign.length\"\n >\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n <div *ngIf=\"assetsToAlign.length\">\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n\n <c8y-li\n class=\"c8y-list__item--overflow-visible\"\n *ngFor=\"let widgetAsset of updatedWidgetAssets; let i = index\"\n >\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id } }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? ('Asset selected' | translate)\n : ('Asset not selected' | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': !widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n *ngIf=\"\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n <div\n class=\"d-flex gap-4 boxed-label\"\n *ngIf=\"widgetAsset.selectedAsset\"\n >\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id } }}\n </small>\n </span>\n </div>\n\n <div\n class=\"text-muted boxed-label\"\n *ngIf=\"\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n >\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset = widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n <c8y-asset-selector-miller\n *ngIf=\"dropdown.isOpen\"\n (onSelected)=\"selectionChange($event, widgetAsset); dropdown.hide()\"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n [title]=\"'Accept all suggested' | translate\"\n type=\"button\"\n (click)=\"acceptAllSuggestedAndApply()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n {{ 'Accept all suggested' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n *ngIf=\"device.c8y_IsDevice\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n *ngIf=\"device.c8y_IsDeviceGroup && !device.c8y_IsAsset\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n *ngIf=\"device.c8y_IsAsset\"\n ></i>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i1.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i1.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i3.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { 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: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.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: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
|
|
259
259
|
}
|
|
260
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
260
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AssignWidgetAssetModalComponent, decorators: [{
|
|
261
261
|
type: Component,
|
|
262
262
|
args: [{ selector: 'c8y-assign-widget-asset-modal', standalone: true, imports: [CoreModule, AssetSelectorModule, BsDropdownModule, TooltipModule], template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n <div\n class=\"d-flex fit-w j-c-center p-16 p-t-0\"\n *ngIf=\"notSupportedWidgets.length\"\n >\n <div class=\"alert alert-warning\">\n {{\n 'Widgets not supported for asset mapping: {{ notSupportedWidgets\n\n\n\n }}' | translate: { notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n <div\n class=\"p-16 d-flex j-c-center\"\n *ngIf=\"!assetsToAlign.length\"\n >\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n <div *ngIf=\"assetsToAlign.length\">\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n\n <c8y-li\n class=\"c8y-list__item--overflow-visible\"\n *ngFor=\"let widgetAsset of updatedWidgetAssets; let i = index\"\n >\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id } }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? ('Asset selected' | translate)\n : ('Asset not selected' | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': !widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n *ngIf=\"\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n <div\n class=\"d-flex gap-4 boxed-label\"\n *ngIf=\"widgetAsset.selectedAsset\"\n >\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id } }}\n </small>\n </span>\n </div>\n\n <div\n class=\"text-muted boxed-label\"\n *ngIf=\"\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n >\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset = widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n <c8y-asset-selector-miller\n *ngIf=\"dropdown.isOpen\"\n (onSelected)=\"selectionChange($event, widgetAsset); dropdown.hide()\"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n [title]=\"'Accept all suggested' | translate\"\n type=\"button\"\n (click)=\"acceptAllSuggestedAndApply()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n {{ 'Accept all suggested' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n *ngIf=\"device.c8y_IsDevice\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n *ngIf=\"device.c8y_IsDeviceGroup && !device.c8y_IsAsset\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n *ngIf=\"device.c8y_IsAsset\"\n ></i>\n</ng-template>\n" }]
|
|
263
263
|
}], propDecorators: { assetsToAlign: [{
|
|
@@ -430,10 +430,10 @@ class ImportExportWidgetsService {
|
|
|
430
430
|
});
|
|
431
431
|
return result;
|
|
432
432
|
}
|
|
433
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
434
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.
|
|
433
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ImportExportWidgetsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
434
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ImportExportWidgetsService }); }
|
|
435
435
|
}
|
|
436
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
436
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ImportExportWidgetsService, decorators: [{
|
|
437
437
|
type: Injectable
|
|
438
438
|
}] });
|
|
439
439
|
|
|
@@ -552,10 +552,10 @@ class DashboardJsonEditorComponent {
|
|
|
552
552
|
}
|
|
553
553
|
return null;
|
|
554
554
|
}
|
|
555
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
556
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.
|
|
555
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardJsonEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
556
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DashboardJsonEditorComponent, isStandalone: true, selector: "c8y-dashboard-json-editor", providers: [JsonValidationService, ImportExportWidgetsService], viewQueries: [{ propertyName: "editorComponent", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<div class=\"card-block\">\n<div\n class=\"d-flex d-col\"\n [ngStyle]=\"{ height: '410px' }\"\n>\n <ng-container *ngIf=\"!isExporting && !isImporting; else loading\">\n <div class=\"d-flex gap-16 flex-grow min-height-0\">\n <div class=\"d-col col-md-8 col-xs-6\">\n <label class=\"d-flex a-i-center\">{{ 'Dashboard configuration' | translate }} \n <button \n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n class=\"btn-help \" \n placement=\"right\"\n triggers=\"focus\"\n containerClass=\"text-pre-wrap\"\n [popover]=\"infoText | translate\"\n ></button>\n </label>\n <c8y-editor\n class=\"flex-grow min-height-0\"\n [ngModel]=\"valueString\"\n (ngModelChange)=\"dashboardJSONChange($event)\"\n (editorInit)=\"assignSchema()\"\n [theme]=\"editorTheme\"\n monacoEditorMarkerValidator\n [editorOptions]=\"editorOptions\"\n ></c8y-editor>\n </div>\n <div class=\"col-md-4 d-col col-xs-6\">\n <label translate>Validation</label>\n <div\n class=\"c8y-messages has-error m-b-24 inner-scroll flex-grow\"\n *ngIf=\"errors().length > 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n *ngFor=\"let error of errors()\"\n >\n <span\n class=\"error-path\"\n *ngIf=\"error.path\"\n >\n {{ error.path }}:\n </span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n </div>\n <div\n class=\"c8y-messages has-success m-b-24\"\n *ngIf=\"errors().length === 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n >\n <span class=\"error-message\">{{ 'No errors found' | translate }}</span>\n </div>\n </div>\n <div class=\"d-flex gap-16 a-i-center flex-no-shrink min-height-0 m-t-auto\">\n <c8y-drop-area\n class=\"drop-area-sm min-width-0\"\n [icon]=\"'upload'\"\n *ngIf=\"!isExporting\"\n [accept]=\"'.json'\"\n [maxAllowedFiles]=\"1\"\n [message]=\"'Import JSON' | translate\"\n (dropped)=\"import($event)\"\n [loading]=\"isImporting\"\n ></c8y-drop-area>\n <button\n class=\"btn btn-primary\"\n (click)=\"export()\"\n [disabled]=\"isExporting || isImporting\"\n [ngClass]=\"{\n 'btn-pending': isExporting\n }\"\n >\n {{'Export JSON' | translate}}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n\n<ng-template #loading>\n <c8y-loading></c8y-loading>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.DropAreaComponent, selector: "c8y-drop-area", inputs: ["formControl", "title", "message", "icon", "loadingMessage", "forceHideList", "alwaysShow", "clickToOpen", "loading", "progress", "maxAllowedFiles", "files", "maxFileSizeInMegaBytes", "accept"], outputs: ["dropped"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i4$1.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: EditorComponent, selector: "c8y-editor", inputs: ["editorOptions", "theme"], outputs: ["editorInit"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
|
|
557
557
|
}
|
|
558
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
558
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardJsonEditorComponent, decorators: [{
|
|
559
559
|
type: Component,
|
|
560
560
|
args: [{ selector: 'c8y-dashboard-json-editor', standalone: true, imports: [
|
|
561
561
|
CommonModule,
|
|
@@ -571,10 +571,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
571
571
|
}] } });
|
|
572
572
|
|
|
573
573
|
class DashboardDetailsAdvancedTabComponent {
|
|
574
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
575
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.
|
|
574
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardDetailsAdvancedTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
575
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DashboardDetailsAdvancedTabComponent, isStandalone: true, selector: "app-dashboard-details-advanced-tab", ngImport: i0, template: `<c8y-dashboard-json-editor></c8y-dashboard-json-editor>`, isInline: true, dependencies: [{ kind: "component", type: DashboardJsonEditorComponent, selector: "c8y-dashboard-json-editor" }] }); }
|
|
576
576
|
}
|
|
577
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
577
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DashboardDetailsAdvancedTabComponent, decorators: [{
|
|
578
578
|
type: Component,
|
|
579
579
|
args: [{
|
|
580
580
|
selector: 'app-dashboard-details-advanced-tab',
|
|
@@ -585,4 +585,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
585
585
|
}] });
|
|
586
586
|
|
|
587
587
|
export { DashboardDetailsAdvancedTabComponent };
|
|
588
|
-
//# sourceMappingURL=c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-
|
|
588
|
+
//# sourceMappingURL=c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-D0C7SH6L.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-m7YeEj9R.mjs","sources":["../../dashboard-details-advanced-tab/dashboard-json-editor/json-validation.service.ts","../../dashboard-details-advanced-tab/assign-widget-assets/assign-widget-asset-modal.component.ts","../../dashboard-details-advanced-tab/assign-widget-assets/assign-widget-asset-modal.component.html","../../dashboard-details-advanced-tab/dashboard-json-editor/import-export-widgets.service.ts","../../dashboard-details-advanced-tab/dashboard-json-editor/dashboard-json-editor.component.ts","../../dashboard-details-advanced-tab/dashboard-json-editor/dashboard-json-editor.component.html","../../dashboard-details-advanced-tab/dashboard-details-advanced-tab.component.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { ContextDashboard } from '@c8y/ngx-components/context-dashboard';\nimport { DynamicComponentService } from '@c8y/ngx-components';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { JSONSchema7 } from 'json-schema';\n\nexport type JSONValidationError = {\n message: string;\n path: string;\n};\n\n@Injectable()\nexport class JsonValidationService {\n ajv: Ajv;\n private OMIT_ERRORS = ['must NOT be valid', 'must match exactly one schema in oneOf'];\n\n constructor(private dynamicComponentService: DynamicComponentService) {\n this.ajv = new Ajv({ verbose: true, allErrors: true });\n addFormats(this.ajv as any);\n }\n\n async validateDashboard(dashboardJson: string, schemas?: any[]): Promise<JSONValidationError[]> {\n try {\n // Parse JSON string to object\n const dashboard: ContextDashboard = JSON.parse(dashboardJson);\n\n // Get or use provided schemas\n const validationSchemas = schemas || (await this.getJsonSchemas(dashboard));\n\n // Create a new Ajv instance\n const validator = new Ajv({\n verbose: true,\n allErrors: true\n });\n\n addFormats(validator as any);\n\n // Add all component schemas individually\n validationSchemas.forEach(({ uri, schema }) => {\n validator.addSchema(schema, uri);\n });\n\n const errorsMap = new Map<string, JSONValidationError>();\n\n // Validate main dashboard structure first (without children)\n const mainSchema = validationSchemas.find(\n s => s.uri === 'context-dashboard.c8y-schema-loader'\n )?.schema;\n\n if (!mainSchema) {\n throw new Error('Dashboard schema not found');\n }\n\n // Create a copy without children for main validation\n const dashboardWithoutChildren = { ...dashboard };\n delete dashboardWithoutChildren.children;\n\n const mainValidate = validator.compile(mainSchema);\n mainValidate(dashboardWithoutChildren);\n\n // Now validate each widget with its specific schema\n if (dashboard.children) {\n Object.entries(dashboard.children).forEach(([widgetId, widget]) => {\n const componentId = widget.componentId;\n // Find the correct schema for this widget type\n const widgetSchema = validationSchemas.find(s => s.uri === componentId)?.schema;\n\n if (widgetSchema) {\n // Validate this widget's config against its specific schema\n const validateWidgetConfig = validator.compile(widgetSchema);\n const isValid = validateWidgetConfig(widget.config);\n\n if (!isValid && validateWidgetConfig.errors) {\n validateWidgetConfig.errors.forEach(error => {\n const message = error.message || 'Unknown error';\n const basePath = `/children/${widgetId}/config`;\n const relativePath = error.instancePath;\n const fullPath = basePath + relativePath;\n\n if (!this.OMIT_ERRORS.includes(message)) {\n errorsMap.set(`${message}::${fullPath}`, {\n message,\n path: fullPath\n });\n }\n });\n }\n }\n });\n }\n\n // Process any errors from main validation\n if (mainValidate.errors) {\n mainValidate.errors.forEach(error => {\n const message = error.message || 'Unknown error';\n const path = error.instancePath;\n\n // Skip children validation errors as we handled them separately\n if (!path.includes('/children/') && !this.OMIT_ERRORS.includes(message)) {\n errorsMap.set(`${message}::${path}`, { message, path });\n }\n });\n }\n\n return Array.from(errorsMap.values());\n } catch (error) {\n if (error instanceof SyntaxError) {\n return [{ message: 'Invalid JSON syntax', path: '' }];\n }\n throw error;\n }\n }\n\n /**\n * Returns JSON schema for dashboard and all its children.\n * Children are referenced by their componentId. Dashboard schema is enriched with references to children schemas.\n * @param dashboard Context dashboard object.\n */\n async getJsonSchemas(dashboard: ContextDashboard) {\n try {\n const dashboardChildrenIds = [\n ...new Set(Object.entries(dashboard.children || {}).map(([_, value]) => value.componentId))\n ];\n\n const widgetSchemasPromises = dashboardChildrenIds.map(id => this.getSchemaForWidget(id));\n const widgetSchemasResults = await Promise.allSettled(widgetSchemasPromises);\n\n // Filter out failed or null schemas\n const validWidgetSchemas = widgetSchemasResults\n .filter(\n (result): result is PromiseFulfilledResult<{ id: string; schema: any }> =>\n result.status === 'fulfilled' && result.value !== null\n )\n .map(result => result.value);\n\n const { schema: dashboardSchemaOriginal }: { schema: JSONSchema7 } = await import(\n 'c8y-schema-loader?interfaceName=ContextDashboard!@c8y/ngx-components/context-dashboard'\n );\n const dashboardSchema = JSON.parse(JSON.stringify(dashboardSchemaOriginal));\n\n // Modify Widget definition with proper schema structure\n if (validWidgetSchemas.length > 0) {\n // Remove any existing allOf or oneOf conditions that might interfere\n if (dashboardSchema.definitions.Widget.allOf) {\n delete dashboardSchema.definitions.Widget.allOf;\n }\n\n // Set up the oneOf condition\n dashboardSchema.definitions.Widget.oneOf = this.getWidgetSchemasReferences(\n validWidgetSchemas.map(({ id }) => id)\n );\n }\n\n return [\n {\n uri: 'context-dashboard.c8y-schema-loader',\n fileMatch: ['*'],\n schema: dashboardSchema\n },\n ...validWidgetSchemas.map(({ id, schema }) => ({\n uri: id,\n schema: schema\n }))\n ];\n } catch (error) {\n console.error('Error processing dashboard schemas:', error);\n throw error;\n }\n }\n\n private async getSchemaForWidget(id: string) {\n try {\n const def = await this.dynamicComponentService.getById(id);\n if (def?.data?.schema && typeof def.data.schema === 'function') {\n const { schema }: { schema: JSONSchema7 } = await def.data.schema();\n return { id, schema };\n }\n return null;\n } catch (error) {\n console.warn(`Failed to fetch schema for widget ${id}:`, error);\n return null;\n }\n }\n\n private getWidgetSchemasReferences(widgetIds: string[]) {\n // provide references to all children schemas\n const schemasPart = widgetIds.map(id => {\n return {\n properties: {\n componentId: { const: id },\n config: { $ref: `${id}#` } // Ensure proper URI reference format\n },\n required: ['componentId'] // Only require componentId\n };\n });\n\n // provide default schema for object if component has no schema definition\n const defaultPart = {\n not: {\n properties: {\n componentId: {\n enum: widgetIds\n }\n }\n },\n properties: {\n config: {\n type: 'object',\n additionalProperties: true\n }\n }\n };\n\n return [...schemasPart, defaultPart];\n }\n}\n","import { Component, inject, Input, OnInit } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { CoreModule } from '@c8y/ngx-components';\nimport { BsModalRef } from 'ngx-bootstrap/modal';\nimport { IManagedObject } from '@c8y/client';\nimport {\n AssetSelectionChangeEvent,\n AssetSelectorModule\n} from '@c8y/ngx-components/assets-navigator';\nimport { WidgetAssetToAlign } from '../advanced-tab.model';\nimport { BsDropdownModule } from 'ngx-bootstrap/dropdown';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n@Component({\n selector: 'c8y-assign-widget-asset-modal',\n templateUrl: './assign-widget-asset-modal.component.html',\n standalone: true,\n imports: [CoreModule, AssetSelectorModule, BsDropdownModule, TooltipModule]\n})\nexport class AssignWidgetAssetModalComponent implements OnInit {\n @Input() assetsToAlign: WidgetAssetToAlign[];\n @Input() contextAsset: IManagedObject;\n @Input() notSupportedWidgets: string[] = [];\n\n modalTitle = gettext(`\n For each asset in the supported widgets, the suggested source is based on the original one.\n You can either accept the suggestion, select a different asset, or decide to configure it later.\n Please note: If you don't pick any of the options available, the widget will not be imported.\n `);\n assetIdInfo = gettext('id: {{ assetId }}');\n acceptSuggestedLabel = gettext('Accept suggested asset');\n noSuggestedAssetLabel = gettext('No suggestion available');\n updatedWidgetAssets: (WidgetAssetToAlign & { selectedAsset?: IManagedObject | null })[] = [];\n hasSuggestedAssets: boolean;\n result: Promise<WidgetAssetToAlign[]> = new Promise((resolve, reject) => {\n this._close = resolve;\n this._cancel = reject;\n });\n private _close: (value: WidgetAssetToAlign[]) => void;\n private _cancel: (reason?: any) => void;\n private bsModalRef = inject(BsModalRef);\n\n ngOnInit() {\n this.updatedWidgetAssets = this.assetsToAlign.map(asset => ({\n ...asset\n }));\n this.hasSuggestedAssets = this.updatedWidgetAssets.some(\n asset => !!asset.deviceRef.value.suggestedDevice\n );\n }\n\n apply(): void {\n const alignedAssets: WidgetAssetToAlign[] = this.updatedWidgetAssets.map(asset => {\n return {\n widgetId: asset.widgetId,\n title: asset.title,\n deviceRef: {\n path: asset.deviceRef.path,\n value:\n asset.selectedAsset == null\n ? asset.selectedAsset\n : { ...asset.selectedAsset, suggestedDevice: null }\n }\n };\n });\n this._close(alignedAssets);\n this.bsModalRef.hide();\n }\n\n acceptAllSuggested() {\n this.updatedWidgetAssets.forEach(asset => {\n asset.selectedAsset = asset.deviceRef.value.suggestedDevice;\n });\n }\n\n acceptAllSuggestedAndApply() {\n this.acceptAllSuggested();\n this.apply();\n }\n\n cancel() {\n this.bsModalRef.hide();\n this._cancel();\n }\n\n selectionChange(\n $event: AssetSelectionChangeEvent,\n widgetAsset: WidgetAssetToAlign & { selectedAsset?: IManagedObject | null }\n ) {\n widgetAsset.selectedAsset = $event.change.item;\n }\n}\n","<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n <div\n class=\"d-flex fit-w j-c-center p-16 p-t-0\"\n *ngIf=\"notSupportedWidgets.length\"\n >\n <div class=\"alert alert-warning\">\n {{\n 'Widgets not supported for asset mapping: {{ notSupportedWidgets\n\n\n\n }}' | translate: { notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n <div\n class=\"p-16 d-flex j-c-center\"\n *ngIf=\"!assetsToAlign.length\"\n >\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n <div *ngIf=\"assetsToAlign.length\">\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n\n <c8y-li\n class=\"c8y-list__item--overflow-visible\"\n *ngFor=\"let widgetAsset of updatedWidgetAssets; let i = index\"\n >\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id } }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? ('Asset selected' | translate)\n : ('Asset not selected' | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': !widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n *ngIf=\"\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n <div\n class=\"d-flex gap-4 boxed-label\"\n *ngIf=\"widgetAsset.selectedAsset\"\n >\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id } }}\n </small>\n </span>\n </div>\n\n <div\n class=\"text-muted boxed-label\"\n *ngIf=\"\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n >\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset = widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n <c8y-asset-selector-miller\n *ngIf=\"dropdown.isOpen\"\n (onSelected)=\"selectionChange($event, widgetAsset); dropdown.hide()\"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n [title]=\"'Accept all suggested' | translate\"\n type=\"button\"\n (click)=\"acceptAllSuggestedAndApply()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n {{ 'Accept all suggested' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n *ngIf=\"device.c8y_IsDevice\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n *ngIf=\"device.c8y_IsDeviceGroup && !device.c8y_IsAsset\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n *ngIf=\"device.c8y_IsAsset\"\n ></i>\n</ng-template>\n","import { inject, Injectable, Injector, runInInjectionContext } from '@angular/core';\nimport { ContextDashboard, DashboardDetailService } from '@c8y/ngx-components/context-dashboard';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { cloneDeep } from 'lodash-es';\nimport { saveAs } from 'file-saver';\nimport {\n AlertService,\n DroppedFile,\n DynamicComponentService,\n Widget,\n WidgetDataType\n} from '@c8y/ngx-components';\nimport { IManagedObject } from '@c8y/client';\nimport { BsModalService } from 'ngx-bootstrap/modal';\nimport { AssignWidgetAssetModalComponent } from '../assign-widget-assets/assign-widget-asset-modal.component';\nimport { WidgetAssetToAlign } from '../advanced-tab.model';\n\n@Injectable()\nexport class ImportExportWidgetsService {\n private dynamicComponentService = inject(DynamicComponentService);\n private injector = inject(Injector);\n private alertService = inject(AlertService);\n private dashboardDetailService = inject(DashboardDetailService);\n private modal = inject(BsModalService);\n\n /**\n * Export the dashboard to a JSON file. If the widget has an export method, it will be called to export\n * the widget's configuration.\n * @param dashboard Context dashboard to be exported\n */\n async export(dashboard: ContextDashboard) {\n const copiedDashboard: ContextDashboard = cloneDeep(dashboard);\n\n for (const [id, child] of Object.entries(copiedDashboard.children || {})) {\n try {\n const definition = await this.dynamicComponentService.getById(child.componentId);\n\n if (definition && typeof definition.data.export === 'function') {\n const widgetData: WidgetDataType = definition.data;\n const pluginInjector = definition.injector || this.injector;\n await runInInjectionContext(pluginInjector, async () => {\n const exportedConfig = await widgetData.export(\n child.config,\n this.dashboardDetailService.details,\n { pluginInjector, injector: this.injector }\n );\n copiedDashboard.children[id].config = exportedConfig;\n });\n }\n } catch (error) {\n this.alertService.addServerFailure(error);\n }\n }\n const dateStr = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `dashboard_${dateStr}.json`;\n const blob = new Blob([JSON.stringify(copiedDashboard)], { type: 'application/json' });\n saveAs(blob, filename);\n this.alertService.success(gettext('Dashboard exported.'));\n }\n\n /**\n * Import the dashboard from a JSON file. If the widget has an import method, it will be called to import\n * widget's configuration.\n * @param file JSON file with context dashboard configuration\n */\n async import(file: DroppedFile[]) {\n if (!file || file.length === 0) {\n return;\n }\n const dashboard: ContextDashboard = await file[0].readAsJson();\n const notSupportedWidgets: string[] = [];\n\n for (const [id, child] of Object.entries(dashboard.children)) {\n try {\n const definition = await this.dynamicComponentService.getById(child.componentId);\n\n if (definition && typeof definition.data.import === 'function') {\n const widgetData: WidgetDataType = definition.data;\n const pluginInjector = definition.injector || this.injector;\n await runInInjectionContext(pluginInjector, async () => {\n const importedConfig = await widgetData.import(\n child.config,\n this.dashboardDetailService.details,\n { pluginInjector, injector: this.injector }\n );\n dashboard.children[id].config = importedConfig;\n });\n } else {\n notSupportedWidgets.push(child.title);\n }\n } catch (error) {\n console.error(`Error importing widget with id ${id}:`, error);\n }\n }\n if (Object.entries(dashboard.children).length) {\n dashboard.children = await this.assignWidgetAssets(dashboard.children, notSupportedWidgets);\n if (!dashboard.children) {\n return;\n }\n }\n\n return JSON.stringify(dashboard, null, 2);\n }\n\n private async assignWidgetAssets(\n widgets: {\n [id: string]: Widget;\n },\n notSupportedWidgets: string[]\n ): Promise<{ [id: string]: Widget }> {\n const assetsToAlign = this.findWidgetsWithSuggestedDevice(widgets);\n const contextAsset = this.dashboardDetailService.details.context;\n\n try {\n const modalRef = this.modal.show(AssignWidgetAssetModalComponent, {\n class: 'modal-lg',\n ariaDescribedby: 'modal-body',\n ariaLabelledBy: 'modal-title',\n ignoreBackdropClick: true,\n keyboard: false,\n initialState: { assetsToAlign, contextAsset, notSupportedWidgets }\n }).content;\n const result = await modalRef.result;\n\n return this.updateWidgets(widgets, result);\n } catch (_) {\n // cancel clicked\n return null;\n }\n }\n\n private findWidgetsWithSuggestedDevice(widgets: Record<string, Widget>): WidgetAssetToAlign[] {\n const results: WidgetAssetToAlign[] = [];\n\n const searchObject = (obj: any, path: string[] = []): void => {\n if (!obj || typeof obj !== 'object') return;\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (key === 'suggestedDevice') {\n // Find the nearest device/__target reference\n let deviceRef: (IManagedObject & { suggestedDevice: IManagedObject }) | null = null;\n let devicePath: string[] = [];\n\n // Search for __target or device in parent objects\n let currentObj = obj;\n const currentSearchPath = [...path];\n while (currentObj && !deviceRef) {\n if (currentObj.__target) {\n deviceRef = currentObj.__target;\n devicePath = [...currentSearchPath, '__target'];\n break;\n }\n if (currentObj.device) {\n deviceRef = currentObj.device;\n devicePath = [...currentSearchPath, 'device'];\n break;\n }\n // Move up one level\n currentSearchPath.pop();\n currentObj = this.getObjectByPath(widgets, currentSearchPath);\n }\n\n if (deviceRef) {\n const widgetId = path[0]; // First element in path should be widget ID\n results.push({\n widgetId,\n title: widgets[widgetId].title,\n deviceRef: { path: devicePath, value: deviceRef }\n });\n }\n } else if (typeof value === 'object') {\n searchObject(value, currentPath);\n }\n }\n };\n\n searchObject(widgets);\n return results;\n }\n\n private getObjectByPath(obj: any, path: string[]): any {\n return path.reduce((curr, key) => curr && curr[key], obj);\n }\n\n private updateWidgets(\n originalWidgets: Record<string, Widget>,\n processedReferences: Array<{\n widgetId: string;\n deviceRef: { path: string[]; value: IManagedObject };\n }>\n ): Record<string, Widget> {\n const result = JSON.parse(JSON.stringify(originalWidgets));\n\n // remove widgets that were no aligned\n processedReferences.forEach(ref => {\n if (ref.deviceRef.value === undefined) {\n delete result[ref.widgetId];\n return;\n }\n\n // apply selected assets to widgets\n const obj = this.getObjectByPath(result, ref.deviceRef.path.slice(0, -1));\n const lastKey = ref.deviceRef.path[ref.deviceRef.path.length - 1];\n if (obj && lastKey) {\n obj[lastKey] = ref.deviceRef.value;\n delete obj[lastKey]?.suggestedDevice;\n }\n });\n\n return result;\n }\n}\n","import { ContextDashboard, DashboardDetailService } from '@c8y/ngx-components/context-dashboard';\nimport { Component, inject, OnInit, signal, ViewChild } from '@angular/core';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport {\n CommonModule,\n CoreModule,\n DroppedFile,\n FormsModule,\n ThemeOptions\n} from '@c8y/ngx-components';\nimport { EditorComponent } from '@c8y/ngx-components/editor';\nimport { JSONValidationError, JsonValidationService } from './json-validation.service';\nimport { debounceTime, Subject, takeUntil } from 'rxjs';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { ImportExportWidgetsService } from './import-export-widgets.service';\n\n@Component({\n selector: 'c8y-dashboard-json-editor',\n templateUrl: 'dashboard-json-editor.component.html',\n standalone: true,\n imports: [\n CommonModule,\n FormsModule,\n ReactiveFormsModule,\n CoreModule,\n PopoverModule,\n EditorComponent\n ],\n providers: [JsonValidationService, ImportExportWidgetsService]\n})\nexport class DashboardJsonEditorComponent implements OnInit {\n infoText = gettext(\n \"Import / Export allows copying dashboard configurations between assets using JSON files. You can export a dashboard's setup and import it to another asset.\\n\\nNote: Basic knowledge of dashboard JSON structure is required.\"\n );\n @ViewChild(EditorComponent) editorComponent!: EditorComponent;\n dashboard: ContextDashboard;\n\n valueString = '';\n errors = signal<JSONValidationError[]>([]);\n editorDirty: boolean;\n editorTheme: ThemeOptions;\n isExporting = false;\n isImporting = false;\n editorOptions: EditorComponent['editorOptions'] = {\n hover: {\n above: false\n }\n };\n\n private dashboardDetailService = inject(DashboardDetailService);\n private jsonValidationService = inject(JsonValidationService);\n private importExportWidgetsService = inject(ImportExportWidgetsService);\n\n private valueChange = new Subject<void>();\n private destroy$ = new Subject<void>();\n private currentSchemas: any[] | null = null;\n\n ngOnInit() {\n this.dashboard = this.dashboardDetailService.details.dashboard;\n this.editorTheme = this.getEditorTheme();\n\n this.valueString = JSON.stringify(this.dashboard, null, 2);\n this.valueChange.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe(() => {\n this.applyChanges();\n this.validate();\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n dashboardJSONChange(value: string) {\n this.valueString = value;\n this.valueChange.next();\n }\n\n async assignSchema() {\n this.currentSchemas = await this.jsonValidationService.getJsonSchemas(this.dashboard);\n this.editorComponent.monaco.languages.json.jsonDefaults.setDiagnosticsOptions({\n validate: true,\n schemas: this.currentSchemas,\n enableSchemaRequest: false,\n allowComments: false\n });\n this.validate();\n }\n\n async validate() {\n this.editorDirty = this.valueString !== JSON.stringify(this.dashboard, null, 2);\n try {\n const validationResult = await this.jsonValidationService.validateDashboard(\n this.valueString,\n this.currentSchemas\n );\n this.errors.set(validationResult);\n } catch (error) {\n console.error('Validation error:', error);\n this.errors.set([\n {\n message: 'An error occurred during validation',\n path: ''\n }\n ]);\n }\n }\n\n applyChanges() {\n try {\n const newDashboard = JSON.parse(this.valueString);\n this.dashboardDetailService.details.dashboard = newDashboard;\n this.dashboardDetailService.generalSettingsForm.patchValue(newDashboard);\n this.dashboardDetailService.appearanceSettingsForm.patchValue(newDashboard);\n this.dashboardDetailService.widgetsForm.patchValue(newDashboard);\n this.dashboardDetailService.previewChangedFn({\n classes: newDashboard.classes,\n widgetClasses: newDashboard.widgetClasses\n });\n this.dashboardDetailService.dashboardDetailsForm.markAsDirty();\n this.dashboardDetailService.saveButtonDisabled = false;\n } catch (error) {\n // disable save button if JSON is invalid and don't apply value to form\n this.dashboardDetailService.saveButtonDisabled = true;\n }\n }\n\n async export() {\n this.isExporting = true;\n try {\n await this.importExportWidgetsService.export(this.dashboard);\n } finally {\n this.isExporting = false;\n }\n }\n\n async import(file: DroppedFile[]) {\n this.isImporting = true;\n try {\n if (file && file.length !== 0) {\n const importedValue = await this.importExportWidgetsService.import(file);\n if (importedValue) {\n this.valueString = importedValue;\n this.valueChange.next();\n }\n }\n } finally {\n this.isImporting = false;\n }\n }\n\n private getEditorTheme(): ThemeOptions | null {\n const dashboardClasses =\n this.dashboardDetailService.appearanceSettingsForm.get('classes').value;\n\n if (dashboardClasses['dashboard-theme-dark']) {\n return 'dark';\n } else if (dashboardClasses['dashboard-theme-white']) {\n return 'light';\n }\n return null;\n }\n}\n","<div class=\"card-block\">\n<div\n class=\"d-flex d-col\"\n [ngStyle]=\"{ height: '410px' }\"\n>\n <ng-container *ngIf=\"!isExporting && !isImporting; else loading\">\n <div class=\"d-flex gap-16 flex-grow min-height-0\">\n <div class=\"d-col col-md-8 col-xs-6\">\n <label class=\"d-flex a-i-center\">{{ 'Dashboard configuration' | translate }} \n <button \n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n class=\"btn-help \" \n placement=\"right\"\n triggers=\"focus\"\n containerClass=\"text-pre-wrap\"\n [popover]=\"infoText | translate\"\n ></button>\n </label>\n <c8y-editor\n class=\"flex-grow min-height-0\"\n [ngModel]=\"valueString\"\n (ngModelChange)=\"dashboardJSONChange($event)\"\n (editorInit)=\"assignSchema()\"\n [theme]=\"editorTheme\"\n monacoEditorMarkerValidator\n [editorOptions]=\"editorOptions\"\n ></c8y-editor>\n </div>\n <div class=\"col-md-4 d-col col-xs-6\">\n <label translate>Validation</label>\n <div\n class=\"c8y-messages has-error m-b-24 inner-scroll flex-grow\"\n *ngIf=\"errors().length > 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n *ngFor=\"let error of errors()\"\n >\n <span\n class=\"error-path\"\n *ngIf=\"error.path\"\n >\n {{ error.path }}:\n </span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n </div>\n <div\n class=\"c8y-messages has-success m-b-24\"\n *ngIf=\"errors().length === 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n >\n <span class=\"error-message\">{{ 'No errors found' | translate }}</span>\n </div>\n </div>\n <div class=\"d-flex gap-16 a-i-center flex-no-shrink min-height-0 m-t-auto\">\n <c8y-drop-area\n class=\"drop-area-sm min-width-0\"\n [icon]=\"'upload'\"\n *ngIf=\"!isExporting\"\n [accept]=\"'.json'\"\n [maxAllowedFiles]=\"1\"\n [message]=\"'Import JSON' | translate\"\n (dropped)=\"import($event)\"\n [loading]=\"isImporting\"\n ></c8y-drop-area>\n <button\n class=\"btn btn-primary\"\n (click)=\"export()\"\n [disabled]=\"isExporting || isImporting\"\n [ngClass]=\"{\n 'btn-pending': isExporting\n }\"\n >\n {{'Export JSON' | translate}}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n\n<ng-template #loading>\n <c8y-loading></c8y-loading>\n</ng-template>\n","import { Component } from '@angular/core';\nimport { DashboardJsonEditorComponent } from './dashboard-json-editor/dashboard-json-editor.component';\n\n@Component({\n selector: 'app-dashboard-details-advanced-tab',\n template: `<c8y-dashboard-json-editor></c8y-dashboard-json-editor>`,\n standalone: true,\n imports: [DashboardJsonEditorComponent]\n})\nexport class DashboardDetailsAdvancedTabComponent {}\n"],"names":["i3","i4"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-D0C7SH6L.mjs","sources":["../../dashboard-details-advanced-tab/dashboard-json-editor/json-validation.service.ts","../../dashboard-details-advanced-tab/assign-widget-assets/assign-widget-asset-modal.component.ts","../../dashboard-details-advanced-tab/assign-widget-assets/assign-widget-asset-modal.component.html","../../dashboard-details-advanced-tab/dashboard-json-editor/import-export-widgets.service.ts","../../dashboard-details-advanced-tab/dashboard-json-editor/dashboard-json-editor.component.ts","../../dashboard-details-advanced-tab/dashboard-json-editor/dashboard-json-editor.component.html","../../dashboard-details-advanced-tab/dashboard-details-advanced-tab.component.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { ContextDashboard } from '@c8y/ngx-components/context-dashboard';\nimport { DynamicComponentService } from '@c8y/ngx-components';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { JSONSchema7 } from 'json-schema';\n\nexport type JSONValidationError = {\n message: string;\n path: string;\n};\n\n@Injectable()\nexport class JsonValidationService {\n ajv: Ajv;\n private OMIT_ERRORS = ['must NOT be valid', 'must match exactly one schema in oneOf'];\n\n constructor(private dynamicComponentService: DynamicComponentService) {\n this.ajv = new Ajv({ verbose: true, allErrors: true });\n addFormats(this.ajv as any);\n }\n\n async validateDashboard(dashboardJson: string, schemas?: any[]): Promise<JSONValidationError[]> {\n try {\n // Parse JSON string to object\n const dashboard: ContextDashboard = JSON.parse(dashboardJson);\n\n // Get or use provided schemas\n const validationSchemas = schemas || (await this.getJsonSchemas(dashboard));\n\n // Create a new Ajv instance\n const validator = new Ajv({\n verbose: true,\n allErrors: true\n });\n\n addFormats(validator as any);\n\n // Add all component schemas individually\n validationSchemas.forEach(({ uri, schema }) => {\n validator.addSchema(schema, uri);\n });\n\n const errorsMap = new Map<string, JSONValidationError>();\n\n // Validate main dashboard structure first (without children)\n const mainSchema = validationSchemas.find(\n s => s.uri === 'context-dashboard.c8y-schema-loader'\n )?.schema;\n\n if (!mainSchema) {\n throw new Error('Dashboard schema not found');\n }\n\n // Create a copy without children for main validation\n const dashboardWithoutChildren = { ...dashboard };\n delete dashboardWithoutChildren.children;\n\n const mainValidate = validator.compile(mainSchema);\n mainValidate(dashboardWithoutChildren);\n\n // Now validate each widget with its specific schema\n if (dashboard.children) {\n Object.entries(dashboard.children).forEach(([widgetId, widget]) => {\n const componentId = widget.componentId;\n // Find the correct schema for this widget type\n const widgetSchema = validationSchemas.find(s => s.uri === componentId)?.schema;\n\n if (widgetSchema) {\n // Validate this widget's config against its specific schema\n const validateWidgetConfig = validator.compile(widgetSchema);\n const isValid = validateWidgetConfig(widget.config);\n\n if (!isValid && validateWidgetConfig.errors) {\n validateWidgetConfig.errors.forEach(error => {\n const message = error.message || 'Unknown error';\n const basePath = `/children/${widgetId}/config`;\n const relativePath = error.instancePath;\n const fullPath = basePath + relativePath;\n\n if (!this.OMIT_ERRORS.includes(message)) {\n errorsMap.set(`${message}::${fullPath}`, {\n message,\n path: fullPath\n });\n }\n });\n }\n }\n });\n }\n\n // Process any errors from main validation\n if (mainValidate.errors) {\n mainValidate.errors.forEach(error => {\n const message = error.message || 'Unknown error';\n const path = error.instancePath;\n\n // Skip children validation errors as we handled them separately\n if (!path.includes('/children/') && !this.OMIT_ERRORS.includes(message)) {\n errorsMap.set(`${message}::${path}`, { message, path });\n }\n });\n }\n\n return Array.from(errorsMap.values());\n } catch (error) {\n if (error instanceof SyntaxError) {\n return [{ message: 'Invalid JSON syntax', path: '' }];\n }\n throw error;\n }\n }\n\n /**\n * Returns JSON schema for dashboard and all its children.\n * Children are referenced by their componentId. Dashboard schema is enriched with references to children schemas.\n * @param dashboard Context dashboard object.\n */\n async getJsonSchemas(dashboard: ContextDashboard) {\n try {\n const dashboardChildrenIds = [\n ...new Set(Object.entries(dashboard.children || {}).map(([_, value]) => value.componentId))\n ];\n\n const widgetSchemasPromises = dashboardChildrenIds.map(id => this.getSchemaForWidget(id));\n const widgetSchemasResults = await Promise.allSettled(widgetSchemasPromises);\n\n // Filter out failed or null schemas\n const validWidgetSchemas = widgetSchemasResults\n .filter(\n (result): result is PromiseFulfilledResult<{ id: string; schema: any }> =>\n result.status === 'fulfilled' && result.value !== null\n )\n .map(result => result.value);\n\n const { schema: dashboardSchemaOriginal }: { schema: JSONSchema7 } = await import(\n 'c8y-schema-loader?interfaceName=ContextDashboard!@c8y/ngx-components/context-dashboard'\n );\n const dashboardSchema = JSON.parse(JSON.stringify(dashboardSchemaOriginal));\n\n // Modify Widget definition with proper schema structure\n if (validWidgetSchemas.length > 0) {\n // Remove any existing allOf or oneOf conditions that might interfere\n if (dashboardSchema.definitions.Widget.allOf) {\n delete dashboardSchema.definitions.Widget.allOf;\n }\n\n // Set up the oneOf condition\n dashboardSchema.definitions.Widget.oneOf = this.getWidgetSchemasReferences(\n validWidgetSchemas.map(({ id }) => id)\n );\n }\n\n return [\n {\n uri: 'context-dashboard.c8y-schema-loader',\n fileMatch: ['*'],\n schema: dashboardSchema\n },\n ...validWidgetSchemas.map(({ id, schema }) => ({\n uri: id,\n schema: schema\n }))\n ];\n } catch (error) {\n console.error('Error processing dashboard schemas:', error);\n throw error;\n }\n }\n\n private async getSchemaForWidget(id: string) {\n try {\n const def = await this.dynamicComponentService.getById(id);\n if (def?.data?.schema && typeof def.data.schema === 'function') {\n const { schema }: { schema: JSONSchema7 } = await def.data.schema();\n return { id, schema };\n }\n return null;\n } catch (error) {\n console.warn(`Failed to fetch schema for widget ${id}:`, error);\n return null;\n }\n }\n\n private getWidgetSchemasReferences(widgetIds: string[]) {\n // provide references to all children schemas\n const schemasPart = widgetIds.map(id => {\n return {\n properties: {\n componentId: { const: id },\n config: { $ref: `${id}#` } // Ensure proper URI reference format\n },\n required: ['componentId'] // Only require componentId\n };\n });\n\n // provide default schema for object if component has no schema definition\n const defaultPart = {\n not: {\n properties: {\n componentId: {\n enum: widgetIds\n }\n }\n },\n properties: {\n config: {\n type: 'object',\n additionalProperties: true\n }\n }\n };\n\n return [...schemasPart, defaultPart];\n }\n}\n","import { Component, inject, Input, OnInit } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { CoreModule } from '@c8y/ngx-components';\nimport { BsModalRef } from 'ngx-bootstrap/modal';\nimport { IManagedObject } from '@c8y/client';\nimport {\n AssetSelectionChangeEvent,\n AssetSelectorModule\n} from '@c8y/ngx-components/assets-navigator';\nimport { WidgetAssetToAlign } from '../advanced-tab.model';\nimport { BsDropdownModule } from 'ngx-bootstrap/dropdown';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n@Component({\n selector: 'c8y-assign-widget-asset-modal',\n templateUrl: './assign-widget-asset-modal.component.html',\n standalone: true,\n imports: [CoreModule, AssetSelectorModule, BsDropdownModule, TooltipModule]\n})\nexport class AssignWidgetAssetModalComponent implements OnInit {\n @Input() assetsToAlign: WidgetAssetToAlign[];\n @Input() contextAsset: IManagedObject;\n @Input() notSupportedWidgets: string[] = [];\n\n modalTitle = gettext(`\n For each asset in the supported widgets, the suggested source is based on the original one.\n You can either accept the suggestion, select a different asset, or decide to configure it later.\n Please note: If you don't pick any of the options available, the widget will not be imported.\n `);\n assetIdInfo = gettext('id: {{ assetId }}');\n acceptSuggestedLabel = gettext('Accept suggested asset');\n noSuggestedAssetLabel = gettext('No suggestion available');\n updatedWidgetAssets: (WidgetAssetToAlign & { selectedAsset?: IManagedObject | null })[] = [];\n hasSuggestedAssets: boolean;\n result: Promise<WidgetAssetToAlign[]> = new Promise((resolve, reject) => {\n this._close = resolve;\n this._cancel = reject;\n });\n private _close: (value: WidgetAssetToAlign[]) => void;\n private _cancel: (reason?: any) => void;\n private bsModalRef = inject(BsModalRef);\n\n ngOnInit() {\n this.updatedWidgetAssets = this.assetsToAlign.map(asset => ({\n ...asset\n }));\n this.hasSuggestedAssets = this.updatedWidgetAssets.some(\n asset => !!asset.deviceRef.value.suggestedDevice\n );\n }\n\n apply(): void {\n const alignedAssets: WidgetAssetToAlign[] = this.updatedWidgetAssets.map(asset => {\n return {\n widgetId: asset.widgetId,\n title: asset.title,\n deviceRef: {\n path: asset.deviceRef.path,\n value:\n asset.selectedAsset == null\n ? asset.selectedAsset\n : { ...asset.selectedAsset, suggestedDevice: null }\n }\n };\n });\n this._close(alignedAssets);\n this.bsModalRef.hide();\n }\n\n acceptAllSuggested() {\n this.updatedWidgetAssets.forEach(asset => {\n asset.selectedAsset = asset.deviceRef.value.suggestedDevice;\n });\n }\n\n acceptAllSuggestedAndApply() {\n this.acceptAllSuggested();\n this.apply();\n }\n\n cancel() {\n this.bsModalRef.hide();\n this._cancel();\n }\n\n selectionChange(\n $event: AssetSelectionChangeEvent,\n widgetAsset: WidgetAssetToAlign & { selectedAsset?: IManagedObject | null }\n ) {\n widgetAsset.selectedAsset = $event.change.item;\n }\n}\n","<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n <div\n class=\"d-flex fit-w j-c-center p-16 p-t-0\"\n *ngIf=\"notSupportedWidgets.length\"\n >\n <div class=\"alert alert-warning\">\n {{\n 'Widgets not supported for asset mapping: {{ notSupportedWidgets\n\n\n\n }}' | translate: { notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n <div\n class=\"p-16 d-flex j-c-center\"\n *ngIf=\"!assetsToAlign.length\"\n >\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n <div *ngIf=\"assetsToAlign.length\">\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n\n <c8y-li\n class=\"c8y-list__item--overflow-visible\"\n *ngFor=\"let widgetAsset of updatedWidgetAssets; let i = index\"\n >\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id } }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? ('Asset selected' | translate)\n : ('Asset not selected' | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': !widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n *ngIf=\"\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n <div\n class=\"d-flex gap-4 boxed-label\"\n *ngIf=\"widgetAsset.selectedAsset\"\n >\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{ assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id } }}\n </small>\n </span>\n </div>\n\n <div\n class=\"text-muted boxed-label\"\n *ngIf=\"\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n \"\n >\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset = widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n <c8y-asset-selector-miller\n *ngIf=\"dropdown.isOpen\"\n (onSelected)=\"selectionChange($event, widgetAsset); dropdown.hide()\"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n [title]=\"'Accept all suggested' | translate\"\n type=\"button\"\n (click)=\"acceptAllSuggestedAndApply()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n {{ 'Accept all suggested' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n *ngIf=\"device.c8y_IsDevice\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n *ngIf=\"device.c8y_IsDeviceGroup && !device.c8y_IsAsset\"\n ></i>\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n *ngIf=\"device.c8y_IsAsset\"\n ></i>\n</ng-template>\n","import { inject, Injectable, Injector, runInInjectionContext } from '@angular/core';\nimport { ContextDashboard, DashboardDetailService } from '@c8y/ngx-components/context-dashboard';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { cloneDeep } from 'lodash-es';\nimport { saveAs } from 'file-saver';\nimport {\n AlertService,\n DroppedFile,\n DynamicComponentService,\n Widget,\n WidgetDataType\n} from '@c8y/ngx-components';\nimport { IManagedObject } from '@c8y/client';\nimport { BsModalService } from 'ngx-bootstrap/modal';\nimport { AssignWidgetAssetModalComponent } from '../assign-widget-assets/assign-widget-asset-modal.component';\nimport { WidgetAssetToAlign } from '../advanced-tab.model';\n\n@Injectable()\nexport class ImportExportWidgetsService {\n private dynamicComponentService = inject(DynamicComponentService);\n private injector = inject(Injector);\n private alertService = inject(AlertService);\n private dashboardDetailService = inject(DashboardDetailService);\n private modal = inject(BsModalService);\n\n /**\n * Export the dashboard to a JSON file. If the widget has an export method, it will be called to export\n * the widget's configuration.\n * @param dashboard Context dashboard to be exported\n */\n async export(dashboard: ContextDashboard) {\n const copiedDashboard: ContextDashboard = cloneDeep(dashboard);\n\n for (const [id, child] of Object.entries(copiedDashboard.children || {})) {\n try {\n const definition = await this.dynamicComponentService.getById(child.componentId);\n\n if (definition && typeof definition.data.export === 'function') {\n const widgetData: WidgetDataType = definition.data;\n const pluginInjector = definition.injector || this.injector;\n await runInInjectionContext(pluginInjector, async () => {\n const exportedConfig = await widgetData.export(\n child.config,\n this.dashboardDetailService.details,\n { pluginInjector, injector: this.injector }\n );\n copiedDashboard.children[id].config = exportedConfig;\n });\n }\n } catch (error) {\n this.alertService.addServerFailure(error);\n }\n }\n const dateStr = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `dashboard_${dateStr}.json`;\n const blob = new Blob([JSON.stringify(copiedDashboard)], { type: 'application/json' });\n saveAs(blob, filename);\n this.alertService.success(gettext('Dashboard exported.'));\n }\n\n /**\n * Import the dashboard from a JSON file. If the widget has an import method, it will be called to import\n * widget's configuration.\n * @param file JSON file with context dashboard configuration\n */\n async import(file: DroppedFile[]) {\n if (!file || file.length === 0) {\n return;\n }\n const dashboard: ContextDashboard = await file[0].readAsJson();\n const notSupportedWidgets: string[] = [];\n\n for (const [id, child] of Object.entries(dashboard.children)) {\n try {\n const definition = await this.dynamicComponentService.getById(child.componentId);\n\n if (definition && typeof definition.data.import === 'function') {\n const widgetData: WidgetDataType = definition.data;\n const pluginInjector = definition.injector || this.injector;\n await runInInjectionContext(pluginInjector, async () => {\n const importedConfig = await widgetData.import(\n child.config,\n this.dashboardDetailService.details,\n { pluginInjector, injector: this.injector }\n );\n dashboard.children[id].config = importedConfig;\n });\n } else {\n notSupportedWidgets.push(child.title);\n }\n } catch (error) {\n console.error(`Error importing widget with id ${id}:`, error);\n }\n }\n if (Object.entries(dashboard.children).length) {\n dashboard.children = await this.assignWidgetAssets(dashboard.children, notSupportedWidgets);\n if (!dashboard.children) {\n return;\n }\n }\n\n return JSON.stringify(dashboard, null, 2);\n }\n\n private async assignWidgetAssets(\n widgets: {\n [id: string]: Widget;\n },\n notSupportedWidgets: string[]\n ): Promise<{ [id: string]: Widget }> {\n const assetsToAlign = this.findWidgetsWithSuggestedDevice(widgets);\n const contextAsset = this.dashboardDetailService.details.context;\n\n try {\n const modalRef = this.modal.show(AssignWidgetAssetModalComponent, {\n class: 'modal-lg',\n ariaDescribedby: 'modal-body',\n ariaLabelledBy: 'modal-title',\n ignoreBackdropClick: true,\n keyboard: false,\n initialState: { assetsToAlign, contextAsset, notSupportedWidgets }\n }).content;\n const result = await modalRef.result;\n\n return this.updateWidgets(widgets, result);\n } catch (_) {\n // cancel clicked\n return null;\n }\n }\n\n private findWidgetsWithSuggestedDevice(widgets: Record<string, Widget>): WidgetAssetToAlign[] {\n const results: WidgetAssetToAlign[] = [];\n\n const searchObject = (obj: any, path: string[] = []): void => {\n if (!obj || typeof obj !== 'object') return;\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (key === 'suggestedDevice') {\n // Find the nearest device/__target reference\n let deviceRef: (IManagedObject & { suggestedDevice: IManagedObject }) | null = null;\n let devicePath: string[] = [];\n\n // Search for __target or device in parent objects\n let currentObj = obj;\n const currentSearchPath = [...path];\n while (currentObj && !deviceRef) {\n if (currentObj.__target) {\n deviceRef = currentObj.__target;\n devicePath = [...currentSearchPath, '__target'];\n break;\n }\n if (currentObj.device) {\n deviceRef = currentObj.device;\n devicePath = [...currentSearchPath, 'device'];\n break;\n }\n // Move up one level\n currentSearchPath.pop();\n currentObj = this.getObjectByPath(widgets, currentSearchPath);\n }\n\n if (deviceRef) {\n const widgetId = path[0]; // First element in path should be widget ID\n results.push({\n widgetId,\n title: widgets[widgetId].title,\n deviceRef: { path: devicePath, value: deviceRef }\n });\n }\n } else if (typeof value === 'object') {\n searchObject(value, currentPath);\n }\n }\n };\n\n searchObject(widgets);\n return results;\n }\n\n private getObjectByPath(obj: any, path: string[]): any {\n return path.reduce((curr, key) => curr && curr[key], obj);\n }\n\n private updateWidgets(\n originalWidgets: Record<string, Widget>,\n processedReferences: Array<{\n widgetId: string;\n deviceRef: { path: string[]; value: IManagedObject };\n }>\n ): Record<string, Widget> {\n const result = JSON.parse(JSON.stringify(originalWidgets));\n\n // remove widgets that were no aligned\n processedReferences.forEach(ref => {\n if (ref.deviceRef.value === undefined) {\n delete result[ref.widgetId];\n return;\n }\n\n // apply selected assets to widgets\n const obj = this.getObjectByPath(result, ref.deviceRef.path.slice(0, -1));\n const lastKey = ref.deviceRef.path[ref.deviceRef.path.length - 1];\n if (obj && lastKey) {\n obj[lastKey] = ref.deviceRef.value;\n delete obj[lastKey]?.suggestedDevice;\n }\n });\n\n return result;\n }\n}\n","import { ContextDashboard, DashboardDetailService } from '@c8y/ngx-components/context-dashboard';\nimport { Component, inject, OnInit, signal, ViewChild } from '@angular/core';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport {\n CommonModule,\n CoreModule,\n DroppedFile,\n FormsModule,\n ThemeOptions\n} from '@c8y/ngx-components';\nimport { EditorComponent } from '@c8y/ngx-components/editor';\nimport { JSONValidationError, JsonValidationService } from './json-validation.service';\nimport { debounceTime, Subject, takeUntil } from 'rxjs';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { ImportExportWidgetsService } from './import-export-widgets.service';\n\n@Component({\n selector: 'c8y-dashboard-json-editor',\n templateUrl: 'dashboard-json-editor.component.html',\n standalone: true,\n imports: [\n CommonModule,\n FormsModule,\n ReactiveFormsModule,\n CoreModule,\n PopoverModule,\n EditorComponent\n ],\n providers: [JsonValidationService, ImportExportWidgetsService]\n})\nexport class DashboardJsonEditorComponent implements OnInit {\n infoText = gettext(\n \"Import / Export allows copying dashboard configurations between assets using JSON files. You can export a dashboard's setup and import it to another asset.\\n\\nNote: Basic knowledge of dashboard JSON structure is required.\"\n );\n @ViewChild(EditorComponent) editorComponent!: EditorComponent;\n dashboard: ContextDashboard;\n\n valueString = '';\n errors = signal<JSONValidationError[]>([]);\n editorDirty: boolean;\n editorTheme: ThemeOptions;\n isExporting = false;\n isImporting = false;\n editorOptions: EditorComponent['editorOptions'] = {\n hover: {\n above: false\n }\n };\n\n private dashboardDetailService = inject(DashboardDetailService);\n private jsonValidationService = inject(JsonValidationService);\n private importExportWidgetsService = inject(ImportExportWidgetsService);\n\n private valueChange = new Subject<void>();\n private destroy$ = new Subject<void>();\n private currentSchemas: any[] | null = null;\n\n ngOnInit() {\n this.dashboard = this.dashboardDetailService.details.dashboard;\n this.editorTheme = this.getEditorTheme();\n\n this.valueString = JSON.stringify(this.dashboard, null, 2);\n this.valueChange.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe(() => {\n this.applyChanges();\n this.validate();\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n dashboardJSONChange(value: string) {\n this.valueString = value;\n this.valueChange.next();\n }\n\n async assignSchema() {\n this.currentSchemas = await this.jsonValidationService.getJsonSchemas(this.dashboard);\n this.editorComponent.monaco.languages.json.jsonDefaults.setDiagnosticsOptions({\n validate: true,\n schemas: this.currentSchemas,\n enableSchemaRequest: false,\n allowComments: false\n });\n this.validate();\n }\n\n async validate() {\n this.editorDirty = this.valueString !== JSON.stringify(this.dashboard, null, 2);\n try {\n const validationResult = await this.jsonValidationService.validateDashboard(\n this.valueString,\n this.currentSchemas\n );\n this.errors.set(validationResult);\n } catch (error) {\n console.error('Validation error:', error);\n this.errors.set([\n {\n message: 'An error occurred during validation',\n path: ''\n }\n ]);\n }\n }\n\n applyChanges() {\n try {\n const newDashboard = JSON.parse(this.valueString);\n this.dashboardDetailService.details.dashboard = newDashboard;\n this.dashboardDetailService.generalSettingsForm.patchValue(newDashboard);\n this.dashboardDetailService.appearanceSettingsForm.patchValue(newDashboard);\n this.dashboardDetailService.widgetsForm.patchValue(newDashboard);\n this.dashboardDetailService.previewChangedFn({\n classes: newDashboard.classes,\n widgetClasses: newDashboard.widgetClasses\n });\n this.dashboardDetailService.dashboardDetailsForm.markAsDirty();\n this.dashboardDetailService.saveButtonDisabled = false;\n } catch (error) {\n // disable save button if JSON is invalid and don't apply value to form\n this.dashboardDetailService.saveButtonDisabled = true;\n }\n }\n\n async export() {\n this.isExporting = true;\n try {\n await this.importExportWidgetsService.export(this.dashboard);\n } finally {\n this.isExporting = false;\n }\n }\n\n async import(file: DroppedFile[]) {\n this.isImporting = true;\n try {\n if (file && file.length !== 0) {\n const importedValue = await this.importExportWidgetsService.import(file);\n if (importedValue) {\n this.valueString = importedValue;\n this.valueChange.next();\n }\n }\n } finally {\n this.isImporting = false;\n }\n }\n\n private getEditorTheme(): ThemeOptions | null {\n const dashboardClasses =\n this.dashboardDetailService.appearanceSettingsForm.get('classes').value;\n\n if (dashboardClasses['dashboard-theme-dark']) {\n return 'dark';\n } else if (dashboardClasses['dashboard-theme-white']) {\n return 'light';\n }\n return null;\n }\n}\n","<div class=\"card-block\">\n<div\n class=\"d-flex d-col\"\n [ngStyle]=\"{ height: '410px' }\"\n>\n <ng-container *ngIf=\"!isExporting && !isImporting; else loading\">\n <div class=\"d-flex gap-16 flex-grow min-height-0\">\n <div class=\"d-col col-md-8 col-xs-6\">\n <label class=\"d-flex a-i-center\">{{ 'Dashboard configuration' | translate }} \n <button \n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n class=\"btn-help \" \n placement=\"right\"\n triggers=\"focus\"\n containerClass=\"text-pre-wrap\"\n [popover]=\"infoText | translate\"\n ></button>\n </label>\n <c8y-editor\n class=\"flex-grow min-height-0\"\n [ngModel]=\"valueString\"\n (ngModelChange)=\"dashboardJSONChange($event)\"\n (editorInit)=\"assignSchema()\"\n [theme]=\"editorTheme\"\n monacoEditorMarkerValidator\n [editorOptions]=\"editorOptions\"\n ></c8y-editor>\n </div>\n <div class=\"col-md-4 d-col col-xs-6\">\n <label translate>Validation</label>\n <div\n class=\"c8y-messages has-error m-b-24 inner-scroll flex-grow\"\n *ngIf=\"errors().length > 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n *ngFor=\"let error of errors()\"\n >\n <span\n class=\"error-path\"\n *ngIf=\"error.path\"\n >\n {{ error.path }}:\n </span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n </div>\n <div\n class=\"c8y-messages has-success m-b-24\"\n *ngIf=\"errors().length === 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n >\n <span class=\"error-message\">{{ 'No errors found' | translate }}</span>\n </div>\n </div>\n <div class=\"d-flex gap-16 a-i-center flex-no-shrink min-height-0 m-t-auto\">\n <c8y-drop-area\n class=\"drop-area-sm min-width-0\"\n [icon]=\"'upload'\"\n *ngIf=\"!isExporting\"\n [accept]=\"'.json'\"\n [maxAllowedFiles]=\"1\"\n [message]=\"'Import JSON' | translate\"\n (dropped)=\"import($event)\"\n [loading]=\"isImporting\"\n ></c8y-drop-area>\n <button\n class=\"btn btn-primary\"\n (click)=\"export()\"\n [disabled]=\"isExporting || isImporting\"\n [ngClass]=\"{\n 'btn-pending': isExporting\n }\"\n >\n {{'Export JSON' | translate}}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n\n<ng-template #loading>\n <c8y-loading></c8y-loading>\n</ng-template>\n","import { Component } from '@angular/core';\nimport { DashboardJsonEditorComponent } from './dashboard-json-editor/dashboard-json-editor.component';\n\n@Component({\n selector: 'app-dashboard-details-advanced-tab',\n template: `<c8y-dashboard-json-editor></c8y-dashboard-json-editor>`,\n standalone: true,\n imports: [DashboardJsonEditorComponent]\n})\nexport class DashboardDetailsAdvancedTabComponent {}\n"],"names":["i3","i4"],"mappings":"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"}
|