@c8y/ngx-components 1023.53.0 → 1023.55.5
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/alarms/index.d.ts +2 -1
- package/alarms/index.d.ts.map +1 -1
- package/application-access/list/index.d.ts +36 -0
- package/application-access/list/index.d.ts.map +1 -0
- package/application-access/user/application-access-user-details-wrapper/index.d.ts +33 -0
- package/application-access/user/application-access-user-details-wrapper/index.d.ts.map +1 -0
- package/application-access/user/index.d.ts +6 -0
- package/application-access/user/index.d.ts.map +1 -0
- package/asset-properties/index.d.ts +1 -1
- package/context-dashboard/index.d.ts +1 -1
- package/datapoints-export-selector/index.d.ts +2 -2
- package/device-enrolment/index.d.ts +6 -0
- package/device-enrolment/index.d.ts.map +1 -0
- package/device-enrolment/modal/index.d.ts +88 -0
- package/device-enrolment/modal/index.d.ts.map +1 -0
- package/device-grid/index.d.ts +1 -1
- package/device-list/index.d.ts +1 -1
- package/device-shell/index.d.ts +1 -1
- package/echart/index.d.ts +1 -1
- package/echart/models/index.d.ts +2 -2
- package/fesm2022/c8y-ngx-components-alarms-cockpit.mjs +1 -1
- package/fesm2022/c8y-ngx-components-alarms-devicemanagement.mjs +1 -1
- package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-application-access-list.mjs +180 -0
- package/fesm2022/c8y-ngx-components-application-access-list.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-application-access-user-application-access-user-details-wrapper.mjs +113 -0
- package/fesm2022/c8y-ngx-components-application-access-user-application-access-user-details-wrapper.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-application-access-user.mjs +20 -0
- package/fesm2022/c8y-ngx-components-application-access-user.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-branding-shared.mjs +1 -1
- package/fesm2022/c8y-ngx-components-child-devices.mjs +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard-asset-add.mjs +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard-device-add.mjs +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard-devicemanagement.mjs +1 -1
- package/fesm2022/{c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-D0C7SH6L.mjs → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DvKsV_Fs.mjs} +14 -12
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DvKsV_Fs.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab.mjs +2 -2
- package/fesm2022/c8y-ngx-components-datapoint-explorer-devicemanagement.mjs +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-explorer.mjs +1 -1
- package/fesm2022/c8y-ngx-components-datapoint-library.mjs +1 -1
- package/fesm2022/c8y-ngx-components-device-enrolment-modal.mjs +570 -0
- package/fesm2022/c8y-ngx-components-device-enrolment-modal.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-device-enrolment.mjs +147 -0
- package/fesm2022/c8y-ngx-components-device-enrolment.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-ecosystem.mjs +2 -2
- package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-exports.mjs +1 -1
- package/fesm2022/c8y-ngx-components-feature-toggles.mjs +1 -1
- package/fesm2022/c8y-ngx-components-register-device.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-ssh.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-telnet.mjs +1 -1
- package/fesm2022/c8y-ngx-components-remote-access-vnc.mjs +1 -1
- package/fesm2022/c8y-ngx-components-report-dashboard.mjs +1 -1
- package/fesm2022/c8y-ngx-components-repository-firmware.mjs +1 -1
- package/fesm2022/c8y-ngx-components-repository-shared.mjs +3 -5
- package/fesm2022/c8y-ngx-components-repository-shared.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-sub-assets.mjs +132 -55
- package/fesm2022/c8y-ngx-components-sub-assets.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-tenants.mjs +71 -32
- package/fesm2022/c8y-ngx-components-tenants.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-upgrade.mjs +7 -1
- package/fesm2022/c8y-ngx-components-upgrade.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-cockpit-welcome.mjs +4 -4
- package/fesm2022/c8y-ngx-components-widgets-implementations-cockpit-welcome.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +454 -225
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/index.d.ts +109 -39
- package/index.d.ts.map +1 -1
- package/locales/de.po +184 -13
- package/locales/es.po +183 -13
- package/locales/fr.po +183 -13
- package/locales/ja_JP.po +162 -13
- package/locales/ko.po +184 -13
- package/locales/locales.pot +157 -8
- package/locales/nl.po +183 -13
- package/locales/pl.po +183 -13
- package/locales/pt_BR.po +183 -13
- package/locales/zh_CN.po +184 -13
- package/locales/zh_TW.po +183 -13
- package/map/index.d.ts +1 -0
- package/map/index.d.ts.map +1 -1
- package/operations/bulk-operations-service/index.d.ts +1 -1
- package/package.json +1 -1
- package/protocol-opcua/mappings/index.d.ts +1 -1
- package/register-device/index.d.ts +1 -1
- package/remote-access/data/index.d.ts +1 -0
- package/remote-access/data/index.d.ts.map +1 -1
- package/repository/shared/index.d.ts.map +1 -1
- package/sub-assets/index.d.ts +9 -3
- package/sub-assets/index.d.ts.map +1 -1
- package/tenants/index.d.ts +1 -0
- package/tenants/index.d.ts.map +1 -1
- package/upgrade/index.d.ts.map +1 -1
- package/widgets/implementations/asset-table/index.d.ts +1 -1
- package/widgets/implementations/datapoints-table/index.d.ts +2 -2
- package/widgets/implementations/kpi/index.d.ts +1 -1
- package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-D0C7SH6L.mjs.map +0 -1
|
@@ -11,7 +11,7 @@ import * as i4 from '@c8y/ngx-components/assets-navigator';
|
|
|
11
11
|
import { AssetTypeGridColumn, AssetTypeCellRendererComponent } from '@c8y/ngx-components/data-grid-columns/asset-type';
|
|
12
12
|
import * as i1 from '@ngx-translate/core';
|
|
13
13
|
import { firstValueFrom, catchError, of, Subject, delay, takeUntil as takeUntil$1, tap } from 'rxjs';
|
|
14
|
-
import { NgIf, NgClass, NgTemplateOutlet, NgStyle,
|
|
14
|
+
import { NgIf, NgClass, NgTemplateOutlet, NgStyle, AsyncPipe } from '@angular/common';
|
|
15
15
|
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
16
16
|
import { CdkStep } from '@angular/cdk/stepper';
|
|
17
17
|
import * as i4$1 from '@c8y/ngx-components/device-list';
|
|
@@ -76,15 +76,27 @@ class SubAssetsService extends DataGridService {
|
|
|
76
76
|
this.IS_DYNAMIC_GROUP_FRAGMENT = 'c8y_IsDynamicGroup';
|
|
77
77
|
}
|
|
78
78
|
async getCustomProperties(group) {
|
|
79
|
-
const assetType
|
|
80
|
-
|
|
81
|
-
if (assetType) {
|
|
79
|
+
const assetType = await firstValueFrom(this.assetTypes.getAssetTypeByName$(group.type));
|
|
80
|
+
if (assetType?.c8y_IsAssetType) {
|
|
82
81
|
const { data } = await this.inventoryService.childAdditionsList(assetType, {
|
|
83
82
|
pageSize: 2000,
|
|
84
83
|
query: "$filter=(has('c8y_IsAssetProperty'))"
|
|
85
84
|
});
|
|
86
85
|
return data;
|
|
87
86
|
}
|
|
87
|
+
else if (assetType?.c8y_JsonSchema?.definitions) {
|
|
88
|
+
const data = [];
|
|
89
|
+
Object.entries(assetType.c8y_JsonSchema.definitions).forEach(([key, value]) => {
|
|
90
|
+
const required = assetType.c8y_JsonSchema.required?.includes(key) || false;
|
|
91
|
+
if (typeof value === 'object' && value !== null) {
|
|
92
|
+
data.push({ ...value, key, isRequired: required });
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
data.push({ key, isRequired: required });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
88
100
|
return [];
|
|
89
101
|
}
|
|
90
102
|
getDefaultColumns(_filterable = true, _sortable = true) {
|
|
@@ -475,7 +487,7 @@ class DeleteAssetsModalComponent {
|
|
|
475
487
|
this.deleteGroupSubAssetsMsg = this.translateService.instant(gettext('Also delete all devices inside "{{name}}" and its subassets.'), { name: this.asset.name });
|
|
476
488
|
}
|
|
477
489
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeleteAssetsModalComponent, deps: [{ token: i1.TranslateService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
478
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DeleteAssetsModalComponent, isStandalone: true, selector: "c8y-delete-assets-modal", inputs: { showWithCascadeCheckbox: "showWithCascadeCheckbox", showWithDeviceUserCheckbox: "showWithDeviceUserCheckbox", asset: "asset" }, viewQueries: [{ propertyName: "modalRef", first: true, predicate: ["modalRef"], descendants: true }], ngImport: i0, template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n <form #assetsForm=\"ngForm\">\n <p class=\"text-wrap m-b-16\">\n {{ message | translate }}\n </p>\n <c8y-form-group *ngIf=\"showWithCascadeCheckbox\" class=\"m-b-0\">\n <label title=\"{{ 'Delete devices' | translate }}\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n name=\"cascade\"\n [(ngModel)]=\"config.cascade\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.CASCADE_DELETE\n }\"\n [disabled]=\"config?.withDeviceUser\"\n />\n <span></span>\n <span class=\"text-break-word\">\n {{ deleteGroupSubAssetsMsg | translate }}\n </span>\n </label>\n </c8y-form-group>\n <c8y-form-group *ngIf=\"showWithDeviceUserCheckbox\" class=\"m-b-0\">\n <label title=\"{{ 'Delete associated device owner' | translate }}\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n name=\"withDeviceUser\"\n [(ngModel)]=\"config.withDeviceUser\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.DELETE_DEVICE_OWNER\n }\"\n [disabled]=\"config?.cascade\"\n />\n <span></span>\n <span>\n {{ 'Also delete associated device owner.' | translate }}\n </span>\n </label>\n </c8y-form-group>\n </form>\n</c8y-confirm-modal>\n", dependencies: [{ kind: "component", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: ["title", "body", "confirmOptions", "status", "labels"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
490
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DeleteAssetsModalComponent, isStandalone: true, selector: "c8y-delete-assets-modal", inputs: { showWithCascadeCheckbox: "showWithCascadeCheckbox", showWithDeviceUserCheckbox: "showWithDeviceUserCheckbox", asset: "asset" }, viewQueries: [{ propertyName: "modalRef", first: true, predicate: ["modalRef"], descendants: true }], ngImport: i0, template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n <form #assetsForm=\"ngForm\">\n <p class=\"text-wrap m-b-16\">\n {{ message | translate }}\n </p>\n <c8y-form-group *ngIf=\"showWithCascadeCheckbox\" class=\"m-b-0\">\n <label title=\"{{ 'Delete devices' | translate }}\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n name=\"cascade\"\n [(ngModel)]=\"config.cascade\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.CASCADE_DELETE\n }\"\n [disabled]=\"config?.withDeviceUser\"\n />\n <span></span>\n <span class=\"text-break-word\">\n {{ deleteGroupSubAssetsMsg | translate }}\n </span>\n </label>\n </c8y-form-group>\n <c8y-form-group *ngIf=\"showWithDeviceUserCheckbox\" class=\"m-b-0\">\n <label title=\"{{ 'Delete associated device owner' | translate }}\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n name=\"withDeviceUser\"\n [(ngModel)]=\"config.withDeviceUser\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.DELETE_ASSET.COMPONENTS.DELETE_ASSETS_MODAL,\n action: PRODUCT_EXPERIENCE.DELETE_ASSET.ACTIONS.DELETE_DEVICE_OWNER\n }\"\n [disabled]=\"config?.cascade\"\n />\n <span></span>\n <span>\n {{ 'Also delete associated device owner.' | translate }}\n </span>\n </label>\n </c8y-form-group>\n </form>\n</c8y-confirm-modal>\n", dependencies: [{ kind: "component", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: ["title", "body", "confirmOptions", "status", "requireCodeVerification", "labels"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
479
491
|
}
|
|
480
492
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DeleteAssetsModalComponent, decorators: [{
|
|
481
493
|
type: Component,
|
|
@@ -617,7 +629,7 @@ class UnassignModalComponent {
|
|
|
617
629
|
this.closeSubject.complete();
|
|
618
630
|
}
|
|
619
631
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UnassignModalComponent, deps: [{ token: i1.TranslateService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
620
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: UnassignModalComponent, isStandalone: true, selector: "c8y-unassign-modal", inputs: { asset: "asset" }, viewQueries: [{ propertyName: "modalRef", first: true, predicate: ["modalRef"], descendants: true }], ngImport: i0, template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n <span>{{ message | translate }}</span>\n</c8y-confirm-modal>\n", dependencies: [{ kind: "component", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: ["title", "body", "confirmOptions", "status", "labels"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
632
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: UnassignModalComponent, isStandalone: true, selector: "c8y-unassign-modal", inputs: { asset: "asset" }, viewQueries: [{ propertyName: "modalRef", first: true, predicate: ["modalRef"], descendants: true }], ngImport: i0, template: "<c8y-confirm-modal [title]=\"title\" [status]=\"status\" [labels]=\"labels\" #modalRef>\n <span>{{ message | translate }}</span>\n</c8y-confirm-modal>\n", dependencies: [{ kind: "component", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: ["title", "body", "confirmOptions", "status", "requireCodeVerification", "labels"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
621
633
|
}
|
|
622
634
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UnassignModalComponent, decorators: [{
|
|
623
635
|
type: Component,
|
|
@@ -1410,7 +1422,7 @@ class AssetPropertiesItemComponent {
|
|
|
1410
1422
|
formComplexPropsValue() {
|
|
1411
1423
|
const complexProps = {};
|
|
1412
1424
|
this.complex.forEach(complexObj => {
|
|
1413
|
-
if (complexObj.file) {
|
|
1425
|
+
if (complexObj.file || complexObj.type === 'date') {
|
|
1414
1426
|
complexProps[complexObj.key] = complexObj.value;
|
|
1415
1427
|
}
|
|
1416
1428
|
else {
|
|
@@ -1445,21 +1457,11 @@ class AssetPropertiesItemComponent {
|
|
|
1445
1457
|
return this.filesService.toBase64(imageFile);
|
|
1446
1458
|
}
|
|
1447
1459
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AssetPropertiesItemComponent, deps: [{ token: i3.AlertService }, { token: i3.C8yJSONSchema }, { token: i3.FilesService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1448
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1460
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AssetPropertiesItemComponent, isStandalone: true, selector: "c8y-asset-properties-item", inputs: { key: "key", value: "value", label: "label", type: "type", file: "file", complex: "complex", isEdit: "isEdit", jsonSchema: "jsonSchema" }, usesOnChanges: true, ngImport: i0, template: "@if (!isEdit) {\n @switch (type) {\n @case ('date') {\n {{ (value | c8yDate: 'fullDate') || ('Undefined' | translate) }}\n }\n @case ('file') {\n @if (file) {\n @if (previewImage) {\n <img\n class=\"img-responsive\"\n [src]=\"previewImage\"\n />\n }\n @if (!previewImage) {\n <button\n class=\"btn btn-clean text-truncate p-0\"\n title=\"{{ 'Download' | translate }} {{ file.name }}\"\n type=\"button\"\n (click)=\"filesService.download(file)\"\n >\n {{ file.name }}\n </button>\n }\n } @else {\n {{ 'No file attached.' | translate }}\n }\n }\n @case ('object') {\n <ul class=\"list-unstyled c8y-custom-properties\">\n @for (prop of complex; track prop.key; let i = $index) {\n <li\n class=\"p-t-4 p-b-4 d-flex text-nowrap\"\n [ngClass]=\"{ 'separator-top-bottom': i === 0, 'separator-bottom': i > 0 }\"\n >\n <label\n class=\"small m-b-0 m-r-8 text-truncate\"\n title=\"{{ prop.label | translate }}\"\n [ngClass]=\"{ 'a-s-start': prop.file }\"\n >\n {{ prop.label | translate }}\n </label>\n <span\n class=\"m-l-auto\"\n [ngStyle]=\"{\n 'max-width': prop.file ? '50%' : '100%',\n 'min-width': '0'\n }\"\n >\n <c8y-asset-properties-item\n [file]=\"prop.file\"\n [key]=\"prop.key\"\n [type]=\"prop.type\"\n [value]=\"prop.value\"\n ></c8y-asset-properties-item>\n </span>\n </li>\n }\n </ul>\n }\n @case (type === 'number' || type === 'boolean' ? type : '') {\n <p\n class=\"text-truncate\"\n title=\"{{ value != null ? value : ('Undefined' | translate) }}\"\n >\n {{ value != null ? value : ('Undefined' | translate) }}\n </p>\n }\n @default {\n <p\n class=\"text-truncate\"\n title=\"{{ (value | translate) || ('Undefined' | translate) }}\"\n >\n {{ (value | translate) || ('Undefined' | translate) }}\n </p>\n }\n }\n}\n@if (isEdit) {\n <formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n ></formly-form>\n}\n", dependencies: [{ kind: "component", type: AssetPropertiesItemComponent, selector: "c8y-asset-properties-item", inputs: ["key", "value", "label", "type", "file", "complex", "isEdit", "jsonSchema"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$2.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] }); }
|
|
1449
1461
|
}
|
|
1450
1462
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AssetPropertiesItemComponent, decorators: [{
|
|
1451
1463
|
type: Component,
|
|
1452
|
-
args: [{ selector: 'c8y-asset-properties-item', imports: [
|
|
1453
|
-
NgIf,
|
|
1454
|
-
NgSwitch,
|
|
1455
|
-
NgSwitchCase,
|
|
1456
|
-
NgFor,
|
|
1457
|
-
NgClass,
|
|
1458
|
-
NgSwitchDefault,
|
|
1459
|
-
FormlyModule,
|
|
1460
|
-
C8yTranslatePipe,
|
|
1461
|
-
DatePipe
|
|
1462
|
-
], template: "<ng-container [ngSwitch]=\"type\" *ngIf=\"!isEdit\">\n <ng-container *ngSwitchCase=\"'date'\">\n {{ (value | c8yDate: 'fullDate') || ('Undefined' | translate) }}\n </ng-container>\n <ng-container *ngSwitchCase=\"'file'\">\n <ng-container *ngIf=\"file\">\n <img *ngIf=\"previewImage\" [src]=\"previewImage\" class=\"img-responsive\" />\n <button\n *ngIf=\"!previewImage\"\n (click)=\"filesService.download(file)\"\n type=\"button\"\n title=\"{{ 'Download' | translate }} {{ file.name }}\"\n class=\"btn btn-clean text-truncate p-0\"\n >\n {{ file.name }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"!file\">\n {{ 'No file attached.' | translate }}\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'object'\">\n <ul class=\"list-unstyled c8y-custom-properties\">\n <li\n *ngFor=\"let prop of complex; let i = index\"\n [ngClass]=\"{ 'separator-top-bottom': i === 0, 'separator-bottom': i > 0 }\"\n class=\"p-t-4 p-b-4 d-flex text-nowrap\"\n >\n <label\n class=\"small m-b-0 m-r-8 text-truncate\"\n title=\"{{ prop.label | translate }}\"\n [ngClass]=\"{ 'a-s-start': prop.file }\"\n >\n {{ prop.label | translate }}\n </label>\n <span class=\"m-l-auto\" style=\"max-width: {{ prop.file ? '50%' : '100%' }}; min-width:0;\">\n <c8y-asset-properties-item\n [file]=\"prop.file\"\n [key]=\"prop.key\"\n [type]=\"prop.type\"\n [value]=\"prop.value\"\n ></c8y-asset-properties-item>\n </span>\n </li>\n </ul>\n </ng-container>\n <!--\n <ng-container *ngSwitchCase=\"'boolean'\">\n <input type=\"checkbox\" [checked]=\"value\" [disabled]=\"true\" />\n </ng-container>\n -->\n <ng-container *ngSwitchCase=\"type === 'number' || type === 'boolean' ? type : ''\">\n <p class=\"text-truncate\" title=\"{{ value != null ? value : ('Undefined' | translate) }}\">\n {{ value != null ? value : ('Undefined' | translate) }}\n </p>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <p class=\"text-truncate\" title=\"{{ (value | translate) || ('Undefined' | translate) }}\">\n {{ (value | translate) || ('Undefined' | translate) }}\n </p>\n </ng-container>\n</ng-container>\n<formly-form *ngIf=\"isEdit\" [form]=\"form\" [fields]=\"fields\" [model]=\"model\"></formly-form>\n" }]
|
|
1464
|
+
args: [{ selector: 'c8y-asset-properties-item', imports: [NgClass, FormlyModule, C8yTranslatePipe, DatePipe], template: "@if (!isEdit) {\n @switch (type) {\n @case ('date') {\n {{ (value | c8yDate: 'fullDate') || ('Undefined' | translate) }}\n }\n @case ('file') {\n @if (file) {\n @if (previewImage) {\n <img\n class=\"img-responsive\"\n [src]=\"previewImage\"\n />\n }\n @if (!previewImage) {\n <button\n class=\"btn btn-clean text-truncate p-0\"\n title=\"{{ 'Download' | translate }} {{ file.name }}\"\n type=\"button\"\n (click)=\"filesService.download(file)\"\n >\n {{ file.name }}\n </button>\n }\n } @else {\n {{ 'No file attached.' | translate }}\n }\n }\n @case ('object') {\n <ul class=\"list-unstyled c8y-custom-properties\">\n @for (prop of complex; track prop.key; let i = $index) {\n <li\n class=\"p-t-4 p-b-4 d-flex text-nowrap\"\n [ngClass]=\"{ 'separator-top-bottom': i === 0, 'separator-bottom': i > 0 }\"\n >\n <label\n class=\"small m-b-0 m-r-8 text-truncate\"\n title=\"{{ prop.label | translate }}\"\n [ngClass]=\"{ 'a-s-start': prop.file }\"\n >\n {{ prop.label | translate }}\n </label>\n <span\n class=\"m-l-auto\"\n [ngStyle]=\"{\n 'max-width': prop.file ? '50%' : '100%',\n 'min-width': '0'\n }\"\n >\n <c8y-asset-properties-item\n [file]=\"prop.file\"\n [key]=\"prop.key\"\n [type]=\"prop.type\"\n [value]=\"prop.value\"\n ></c8y-asset-properties-item>\n </span>\n </li>\n }\n </ul>\n }\n @case (type === 'number' || type === 'boolean' ? type : '') {\n <p\n class=\"text-truncate\"\n title=\"{{ value != null ? value : ('Undefined' | translate) }}\"\n >\n {{ value != null ? value : ('Undefined' | translate) }}\n </p>\n }\n @default {\n <p\n class=\"text-truncate\"\n title=\"{{ (value | translate) || ('Undefined' | translate) }}\"\n >\n {{ (value | translate) || ('Undefined' | translate) }}\n </p>\n }\n }\n}\n@if (isEdit) {\n <formly-form\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n ></formly-form>\n}\n" }]
|
|
1463
1465
|
}], ctorParameters: () => [{ type: i3.AlertService }, { type: i3.C8yJSONSchema }, { type: i3.FilesService }], propDecorators: { key: [{
|
|
1464
1466
|
type: Input
|
|
1465
1467
|
}], value: [{
|
|
@@ -1716,10 +1718,14 @@ class AssetPropertiesComponent {
|
|
|
1716
1718
|
}
|
|
1717
1719
|
async loadAsset() {
|
|
1718
1720
|
this.isLoading = true;
|
|
1719
|
-
|
|
1720
|
-
this.assetType = await firstValueFrom(assetType$);
|
|
1721
|
+
this.assetType = await firstValueFrom(this.assetTypes.getAssetTypeByName$(this.asset.type));
|
|
1721
1722
|
try {
|
|
1722
|
-
|
|
1723
|
+
const sourceArray = this.assetType?.c8y_IsAssetType?.properties ||
|
|
1724
|
+
this.assetType?.c8y_AllowedPropertyDefinitions;
|
|
1725
|
+
const keyField = this.assetType?.c8y_IsAssetType?.properties ? 'id' : 'identifier';
|
|
1726
|
+
if (sourceArray) {
|
|
1727
|
+
this.properties = this.keepOrder(sourceArray, this.properties, keyField);
|
|
1728
|
+
}
|
|
1723
1729
|
}
|
|
1724
1730
|
catch (ex) {
|
|
1725
1731
|
console.warn(ex);
|
|
@@ -1729,16 +1735,41 @@ class AssetPropertiesComponent {
|
|
|
1729
1735
|
}
|
|
1730
1736
|
async resolveCustomProperties(managedObjects) {
|
|
1731
1737
|
const properties = [];
|
|
1732
|
-
for (const
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
this.
|
|
1738
|
+
for (const property of managedObjects) {
|
|
1739
|
+
let item;
|
|
1740
|
+
if (property.c8y_JsonSchema) {
|
|
1741
|
+
[item] = await this.parseItem(property, property.c8y_JsonSchema.properties, this.asset);
|
|
1742
|
+
}
|
|
1743
|
+
else if (property.key) {
|
|
1744
|
+
this.transformType(property);
|
|
1745
|
+
const jsonSchema = {};
|
|
1746
|
+
jsonSchema[property.key] = property;
|
|
1747
|
+
[item] = await this.parseItem(null, jsonSchema, this.asset);
|
|
1748
|
+
}
|
|
1749
|
+
if (item) {
|
|
1750
|
+
this.setItemRequired(item, property);
|
|
1736
1751
|
this.updatePositionKeyLabel(item);
|
|
1737
1752
|
properties.push(item);
|
|
1738
1753
|
}
|
|
1739
1754
|
}
|
|
1740
1755
|
return properties;
|
|
1741
1756
|
}
|
|
1757
|
+
transformType(property) {
|
|
1758
|
+
if (property.format === 'date-time') {
|
|
1759
|
+
property.type = 'date';
|
|
1760
|
+
}
|
|
1761
|
+
else if (this.isFileTypeProperty(property)) {
|
|
1762
|
+
property.type = 'file';
|
|
1763
|
+
property.contentMediaType = property.properties?.binaryId?.contentMediaType;
|
|
1764
|
+
property.maxSize = property.properties?.binarySize?.maximum;
|
|
1765
|
+
}
|
|
1766
|
+
else if (property.enum) {
|
|
1767
|
+
property.type = 'enum';
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
isFileTypeProperty(property) {
|
|
1771
|
+
return property.required?.[0] === 'binaryId';
|
|
1772
|
+
}
|
|
1742
1773
|
deleteTitleFromMOJsonSchema(mo) {
|
|
1743
1774
|
const schemaProperties = mo?.c8y_JsonSchema?.properties;
|
|
1744
1775
|
const property = Object.keys(schemaProperties || {})[0];
|
|
@@ -1746,13 +1777,35 @@ class AssetPropertiesComponent {
|
|
|
1746
1777
|
}
|
|
1747
1778
|
/**
|
|
1748
1779
|
* This method is used to order the complex properties in the order specified by the user in asset properties screen.
|
|
1749
|
-
* @param mo - Managed object of the complex property associated with the asset.
|
|
1780
|
+
* @param mo - Managed object of the complex property associated with the asset (old structure) or properties object (new structure).
|
|
1750
1781
|
*/
|
|
1751
1782
|
orderComplexProperties(mo) {
|
|
1752
|
-
const
|
|
1753
|
-
const keyValuesArray = toPairs(
|
|
1783
|
+
const target = mo.c8y_JsonSchema ? mo.c8y_JsonSchema.properties[mo.name]?.['properties'] : mo;
|
|
1784
|
+
const keyValuesArray = toPairs(target);
|
|
1754
1785
|
const orderedProperties = sortBy(keyValuesArray, ([, value]) => value.order);
|
|
1755
|
-
|
|
1786
|
+
const result = fromPairs(orderedProperties);
|
|
1787
|
+
if (mo.c8y_JsonSchema) {
|
|
1788
|
+
mo.c8y_JsonSchema.properties[mo.name]['properties'] = result;
|
|
1789
|
+
return mo;
|
|
1790
|
+
}
|
|
1791
|
+
return result;
|
|
1792
|
+
}
|
|
1793
|
+
async addOrderDetails(properties, key) {
|
|
1794
|
+
const propDetails = await this.getPropertyDetails(key);
|
|
1795
|
+
propDetails.c8y_Order?.forEach(item => {
|
|
1796
|
+
if (properties[item.identifier]) {
|
|
1797
|
+
properties[item.identifier]['order'] = item.order;
|
|
1798
|
+
}
|
|
1799
|
+
});
|
|
1800
|
+
}
|
|
1801
|
+
async getPropertyDetails(identifier) {
|
|
1802
|
+
const query = {
|
|
1803
|
+
__filter: {
|
|
1804
|
+
__and: [{ type: 'c8y_PropertyDefinition' }, { c8y_Contexts: 'asset' }, { name: identifier }]
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
const { data } = await this.inventory.listQuery(query);
|
|
1808
|
+
return data[0];
|
|
1756
1809
|
}
|
|
1757
1810
|
async parseItem(mo, properties, asset) {
|
|
1758
1811
|
if (!asset) {
|
|
@@ -1776,9 +1829,17 @@ class AssetPropertiesComponent {
|
|
|
1776
1829
|
value = !isNaN(valueDate.getTime()) ? valueDate : '';
|
|
1777
1830
|
}
|
|
1778
1831
|
if (type === 'object') {
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1832
|
+
if (mo?.c8y_JsonSchema) {
|
|
1833
|
+
this.deleteTitleFromMOJsonSchema(mo);
|
|
1834
|
+
this.orderComplexProperties(mo);
|
|
1835
|
+
}
|
|
1836
|
+
else {
|
|
1837
|
+
for (const [, value] of Object.entries(properties[key].properties)) {
|
|
1838
|
+
this.transformType(value);
|
|
1839
|
+
}
|
|
1840
|
+
await this.addOrderDetails(properties[key].properties, key);
|
|
1841
|
+
properties[key].properties = this.orderComplexProperties(properties[key].properties);
|
|
1842
|
+
}
|
|
1782
1843
|
if (!value) {
|
|
1783
1844
|
value = {};
|
|
1784
1845
|
for (const prop in properties[key].properties) {
|
|
@@ -1786,18 +1847,19 @@ class AssetPropertiesComponent {
|
|
|
1786
1847
|
}
|
|
1787
1848
|
}
|
|
1788
1849
|
}
|
|
1850
|
+
const schema = mo?.c8y_JsonSchema || { properties: properties };
|
|
1789
1851
|
items.push({
|
|
1790
1852
|
key,
|
|
1791
1853
|
value,
|
|
1792
|
-
label: title || mo
|
|
1854
|
+
label: title || mo?.label,
|
|
1793
1855
|
type,
|
|
1794
|
-
description: mo.description,
|
|
1856
|
+
description: mo?.description || properties[key].description,
|
|
1795
1857
|
file,
|
|
1796
1858
|
complex: type === 'object'
|
|
1797
1859
|
? await this.parseItem(mo, properties[key].properties, value)
|
|
1798
1860
|
: undefined,
|
|
1799
1861
|
isEdit: false,
|
|
1800
|
-
jsonSchema:
|
|
1862
|
+
jsonSchema: schema
|
|
1801
1863
|
});
|
|
1802
1864
|
}
|
|
1803
1865
|
return items;
|
|
@@ -1818,11 +1880,16 @@ class AssetPropertiesComponent {
|
|
|
1818
1880
|
try {
|
|
1819
1881
|
if (prop.type === 'object') {
|
|
1820
1882
|
this.updateUndefinedToPropTypeValue(prop, propertyValue[prop.key]);
|
|
1883
|
+
for (const currentProp of prop.complex) {
|
|
1884
|
+
if (currentProp.type === 'file') {
|
|
1885
|
+
await this.uploadFileProperty(propertyValue, prop, currentProp);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1821
1888
|
}
|
|
1822
1889
|
else {
|
|
1823
1890
|
this.updateUndefinedToPropTypeValue(prop, propertyValue);
|
|
1891
|
+
propertyValue = await this.uploadFiles(propertyValue, prop.value);
|
|
1824
1892
|
}
|
|
1825
|
-
propertyValue = await this.uploadFiles(propertyValue, prop.value);
|
|
1826
1893
|
// Avoid making a PUT request containing just the id, as response body might be incomplete
|
|
1827
1894
|
const hasValues = Object.values(propertyValue).some(value => value !== undefined);
|
|
1828
1895
|
if (!hasValues) {
|
|
@@ -1842,6 +1909,12 @@ class AssetPropertiesComponent {
|
|
|
1842
1909
|
this.toggleEdit(prop);
|
|
1843
1910
|
}
|
|
1844
1911
|
}
|
|
1912
|
+
async uploadFileProperty(propertyValue, prop, currentProp) {
|
|
1913
|
+
const fileInfo = {};
|
|
1914
|
+
fileInfo[currentProp.key] = propertyValue[prop.key][currentProp.key];
|
|
1915
|
+
const value = await this.uploadFiles(fileInfo, currentProp.value);
|
|
1916
|
+
propertyValue[prop.key][currentProp.key] = value[currentProp.key];
|
|
1917
|
+
}
|
|
1845
1918
|
updateUndefinedToPropTypeValue(prop, propertyValue) {
|
|
1846
1919
|
for (const [key, value] of Object.entries(propertyValue)) {
|
|
1847
1920
|
const property = prop.complex ? find(prop.complex, { key: key }) : prop;
|
|
@@ -1859,15 +1932,15 @@ class AssetPropertiesComponent {
|
|
|
1859
1932
|
return '';
|
|
1860
1933
|
}
|
|
1861
1934
|
}
|
|
1862
|
-
keepOrder(correctOrderedIds, properties) {
|
|
1863
|
-
|
|
1864
|
-
const
|
|
1935
|
+
keepOrder(correctOrderedIds, properties, keyField) {
|
|
1936
|
+
return correctOrderedIds.map(item => {
|
|
1937
|
+
const itemKey = item[keyField];
|
|
1938
|
+
const foundProperty = properties.find(property => property.key === itemKey || property.id === itemKey);
|
|
1865
1939
|
if (!foundProperty) {
|
|
1866
1940
|
throw new Error('Custom property mismatch');
|
|
1867
1941
|
}
|
|
1868
1942
|
return foundProperty;
|
|
1869
1943
|
});
|
|
1870
|
-
return orderedProperties;
|
|
1871
1944
|
}
|
|
1872
1945
|
async uploadFiles(model, moId) {
|
|
1873
1946
|
const keys = Object.keys(model);
|
|
@@ -1899,36 +1972,37 @@ class AssetPropertiesComponent {
|
|
|
1899
1972
|
}
|
|
1900
1973
|
}
|
|
1901
1974
|
setItemRequired(item, mo) {
|
|
1902
|
-
const isAssetPropertyRequired =
|
|
1975
|
+
const isAssetPropertyRequired = this.assetType?.c8y_IsAssetType
|
|
1976
|
+
? !!this.assetType.c8y_IsAssetType.properties.find(p => p.id === mo.id)?.isRequired
|
|
1977
|
+
: mo.isRequired;
|
|
1903
1978
|
if (!isAssetPropertyRequired) {
|
|
1904
1979
|
return;
|
|
1905
1980
|
}
|
|
1906
1981
|
const isComplexProperty = !!item?.complex?.length;
|
|
1982
|
+
const propertyKey = mo.c8y_JsonSchema?.key || mo.key;
|
|
1907
1983
|
if (isComplexProperty) {
|
|
1908
|
-
const complexProperty = item.jsonSchema?.properties?.[
|
|
1984
|
+
const complexProperty = item.jsonSchema?.properties?.[propertyKey];
|
|
1909
1985
|
complexProperty.required = item.complex.map(({ key }) => key);
|
|
1910
1986
|
}
|
|
1911
1987
|
else {
|
|
1912
|
-
item.jsonSchema.required = [
|
|
1988
|
+
item.jsonSchema.required = [propertyKey];
|
|
1913
1989
|
}
|
|
1914
1990
|
}
|
|
1915
1991
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AssetPropertiesComponent, deps: [{ token: i3.AssetTypesRealtimeService }, { token: i2.InventoryService }, { token: i2.InventoryBinaryService }, { token: i3.AlertService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1916
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1992
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AssetPropertiesComponent, isStandalone: true, selector: "c8y-asset-properties", inputs: { asset: "asset", properties: "properties" }, outputs: { assetChange: "assetChange" }, usesOnChanges: true, ngImport: i0, template: "<ng-container>\n <div class=\"card-header bg-inherit separator sticky-top\">\n <h1\n class=\"card-title p-t-4 p-b-4\"\n ngNonBindable\n translate\n [translateParams]=\"{\n label: assetType?.c8y_JsonSchema?.title || assetType?.label || '' | translate\n }\"\n >\n {{ label }} properties\n </h1>\n </div>\n <div class=\"card-block\">\n @if (isLoading) {\n <div class=\"text-center\">\n <c8y-loading></c8y-loading>\n </div>\n }\n\n @if (!isLoading) {\n @for (prop of customProperties; track prop.key) {\n <div\n class=\"card m-b-8\"\n title=\"{{ prop.description | translate }}\"\n [ngClass]=\"{ 'card-highlight': prop.isEdit }\"\n >\n <div\n class=\"card-block\"\n [ngClass]=\"{ 'p-b-0': prop.isEdit }\"\n >\n @if (!prop.isEdit) {\n <div class=\"d-flex p-b-8 a-i-center\">\n <p\n class=\"text-medium text-truncate\"\n title=\"{{ prop?.label | translate }}\"\n >\n {{ prop?.label | translate }}\n </p>\n <button\n class=\"btn btn-dot m-l-auto text-12\"\n [attr.aria-label]=\"'Edit' | translate\"\n tooltip=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"toggleEdit(prop)\"\n >\n <i c8yIcon=\"pencil\"></i>\n </button>\n </div>\n }\n <c8y-asset-properties-item\n #assetProps\n [file]=\"prop.file\"\n [key]=\"prop.key\"\n [type]=\"prop.type\"\n [value]=\"prop.value\"\n [complex]=\"prop.complex\"\n [isEdit]=\"prop.isEdit\"\n [jsonSchema]=\"prop.jsonSchema\"\n ></c8y-asset-properties-item>\n @if (prop.key === POSITION_PROPERTY_KEY) {\n <div>\n <c8y-asset-location\n [locationMO]=\"asset\"\n [isEdit]=\"prop.isEdit\"\n [form]=\"assetProps.form\"\n ></c8y-asset-location>\n </div>\n }\n </div>\n @if (prop.isEdit) {\n <div class=\"card-footer p-t-0\">\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"toggleEdit(prop)\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Save' | translate }}\"\n type=\"button\"\n [disabled]=\"!assetProps?.form?.valid || !assetProps?.form?.dirty\"\n (click)=\"save(assetProps.form.value, prop)\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n }\n </div>\n }\n }\n </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: 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: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: AssetPropertiesItemComponent, selector: "c8y-asset-properties-item", inputs: ["key", "value", "label", "type", "file", "complex", "isEdit", "jsonSchema"] }, { kind: "component", type: AssetLocationComponent, selector: "c8y-asset-location", inputs: ["isEdit", "locationMO", "form"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
|
|
1917
1993
|
}
|
|
1918
1994
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AssetPropertiesComponent, decorators: [{
|
|
1919
1995
|
type: Component,
|
|
1920
1996
|
args: [{ selector: 'c8y-asset-properties', imports: [
|
|
1921
1997
|
C8yTranslateDirective,
|
|
1922
|
-
NgIf,
|
|
1923
1998
|
LoadingComponent,
|
|
1924
|
-
NgFor,
|
|
1925
1999
|
NgClass,
|
|
1926
2000
|
TooltipDirective,
|
|
1927
2001
|
IconDirective,
|
|
1928
2002
|
AssetPropertiesItemComponent,
|
|
1929
2003
|
AssetLocationComponent,
|
|
1930
2004
|
C8yTranslatePipe
|
|
1931
|
-
], template: "<ng-container>\n <div class=\"card-header bg-inherit separator sticky-top\">\n <h1\n class=\"card-title p-t-4 p-b-4\"\n ngNonBindable\n translate\n [translateParams]=\"{
|
|
2005
|
+
], template: "<ng-container>\n <div class=\"card-header bg-inherit separator sticky-top\">\n <h1\n class=\"card-title p-t-4 p-b-4\"\n ngNonBindable\n translate\n [translateParams]=\"{\n label: assetType?.c8y_JsonSchema?.title || assetType?.label || '' | translate\n }\"\n >\n {{ label }} properties\n </h1>\n </div>\n <div class=\"card-block\">\n @if (isLoading) {\n <div class=\"text-center\">\n <c8y-loading></c8y-loading>\n </div>\n }\n\n @if (!isLoading) {\n @for (prop of customProperties; track prop.key) {\n <div\n class=\"card m-b-8\"\n title=\"{{ prop.description | translate }}\"\n [ngClass]=\"{ 'card-highlight': prop.isEdit }\"\n >\n <div\n class=\"card-block\"\n [ngClass]=\"{ 'p-b-0': prop.isEdit }\"\n >\n @if (!prop.isEdit) {\n <div class=\"d-flex p-b-8 a-i-center\">\n <p\n class=\"text-medium text-truncate\"\n title=\"{{ prop?.label | translate }}\"\n >\n {{ prop?.label | translate }}\n </p>\n <button\n class=\"btn btn-dot m-l-auto text-12\"\n [attr.aria-label]=\"'Edit' | translate\"\n tooltip=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"toggleEdit(prop)\"\n >\n <i c8yIcon=\"pencil\"></i>\n </button>\n </div>\n }\n <c8y-asset-properties-item\n #assetProps\n [file]=\"prop.file\"\n [key]=\"prop.key\"\n [type]=\"prop.type\"\n [value]=\"prop.value\"\n [complex]=\"prop.complex\"\n [isEdit]=\"prop.isEdit\"\n [jsonSchema]=\"prop.jsonSchema\"\n ></c8y-asset-properties-item>\n @if (prop.key === POSITION_PROPERTY_KEY) {\n <div>\n <c8y-asset-location\n [locationMO]=\"asset\"\n [isEdit]=\"prop.isEdit\"\n [form]=\"assetProps.form\"\n ></c8y-asset-location>\n </div>\n }\n </div>\n @if (prop.isEdit) {\n <div class=\"card-footer p-t-0\">\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"toggleEdit(prop)\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary btn-sm\"\n title=\"{{ 'Save' | translate }}\"\n type=\"button\"\n [disabled]=\"!assetProps?.form?.valid || !assetProps?.form?.dirty\"\n (click)=\"save(assetProps.form.value, prop)\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n }\n </div>\n }\n }\n </div>\n</ng-container>\n" }]
|
|
1932
2006
|
}], ctorParameters: () => [{ type: i3.AssetTypesRealtimeService }, { type: i2.InventoryService }, { type: i2.InventoryBinaryService }, { type: i3.AlertService }], propDecorators: { asset: [{
|
|
1933
2007
|
type: Input
|
|
1934
2008
|
}], assetChange: [{
|
|
@@ -1966,6 +2040,7 @@ class GroupInfoComponent {
|
|
|
1966
2040
|
c8y_Notes: ''
|
|
1967
2041
|
};
|
|
1968
2042
|
this.filterMsg = gettext('Smart groups are groups dynamically constructed based on filtering criteria.');
|
|
2043
|
+
this.descriptionLabel = gettext('e.g. My description');
|
|
1969
2044
|
this.GROUP_UPDATED_MSG = gettext('Group updated.');
|
|
1970
2045
|
this.destroyed$ = new Subject();
|
|
1971
2046
|
this.deviceListExtensionService.items$.pipe(takeUntil(this.destroyed$)).subscribe(columns => {
|
|
@@ -1986,9 +2061,13 @@ class GroupInfoComponent {
|
|
|
1986
2061
|
externalFilterQuery: col.filter.externalFilterQuery,
|
|
1987
2062
|
...this.withPropsFromGridColumn(col)
|
|
1988
2063
|
}));
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2064
|
+
if (this.assetNodeService.isAsset(this.group)) {
|
|
2065
|
+
const assetType = await firstValueFrom(this.assetType.getAssetTypeByName$(this.group.type));
|
|
2066
|
+
this.label = assetType?.label || assetType?.c8y_JsonSchema?.title || gettext('Group');
|
|
2067
|
+
}
|
|
2068
|
+
else {
|
|
2069
|
+
this.label = gettext('Group');
|
|
2070
|
+
}
|
|
1992
2071
|
}
|
|
1993
2072
|
}
|
|
1994
2073
|
isSmartGroup() {
|
|
@@ -2059,13 +2138,12 @@ class GroupInfoComponent {
|
|
|
2059
2138
|
}
|
|
2060
2139
|
}
|
|
2061
2140
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GroupInfoComponent, deps: [{ token: i2.InventoryService }, { token: SubAssetsService }, { token: i2.SmartGroupsService }, { token: i3.AlertService }, { token: i3.ModalService }, { token: i4.AssetNodeService }, { token: i3.AssetTypesRealtimeService }, { token: i4$1.DeviceListExtensionService }, { token: SUB_ASSETS_CONFIG }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2062
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: GroupInfoComponent, isStandalone: true, selector: "c8y-group-info", inputs: { group: "group" }, outputs: { groupChange: "groupChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"bg-level-1 separator-bottom\">\n <div class=\"card-block p-t-24 p-b-24 large-padding\">\n <div class=\"content-flex-70\">\n <div class=\"text-center col-1\">\n <i\n class=\"c8y-icon-duocolor icon-48\"\n [c8yIcon]=\"groupIcon\"\n ></i>\n <p>\n <small\n class=\"label label-info\"\n *ngIf=\"group.c8y_IsDynamicGroup\"\n >\n {{ 'Smart group' | translate }}\n </small>\n <small\n class=\"label label-info text-truncate d-inline-block\"\n title=\"{{ label | translate }}\"\n *ngIf=\"!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent\"\n >\n {{ label | translate }}\n </small>\n <small\n class=\"label label-info\"\n *ngIf=\"group.com_cumulocity_model_Agent\"\n >\n {{ 'Remote group' | translate }}\n </small>\n </p>\n </div>\n\n <div class=\"flex-grow col-10\">\n <div class=\"content-flex-80\">\n <div class=\"col-9\">\n <form #groupNameForm=\"ngForm\">\n <c8y-form-group class=\"form-group-lg m-b-0\">\n <label\n class=\"sr-only\"\n for=\"groupName\"\n translate\n >\n Name\n </label>\n <p\n class=\"form-control-static\"\n *ngIf=\"!canEdit\"\n >\n {{ groupInfoModel.name }}\n </p>\n <div\n class=\"input-group input-group-lg input-group-editable\"\n *ngIf=\"canEdit\"\n >\n <input\n class=\"form-control\"\n title=\"{{ groupInfoModel.name }}\"\n id=\"groupName\"\n placeholder=\"{{ 'e.g. My group' | translate }}\"\n name=\"name\"\n type=\"text\"\n required\n [(ngModel)]=\"groupInfoModel.name\"\n size=\"{{ groupInfoModel.name.length + 2 }}\"\n maxlength=\"254\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupNameForm.form.invalid\"\n (click)=\"\n update({ name: groupInfoModel.name }); groupNameForm.form.markAsPristine()\n \"\n [actionName]=\"'groupInfo:EditedNameSaved'\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </form>\n <form #groupDescriptionForm=\"ngForm\">\n <label\n class=\"sr-only\"\n for=\"description\"\n translate\n >\n Description\n </label>\n <p\n class=\"form-control-static\"\n *ngIf=\"!canEdit\"\n >\n {{ groupInfoModel.c8y_Notes }}\n </p>\n <div\n class=\"input-group input-group-editable\"\n *ngIf=\"canEdit\"\n >\n <textarea\n class=\"form-control no-resize\"\n title=\"{{\n groupInfoModel.c8y_Notes\n ? groupInfoModel.c8y_Notes\n : ('e.g. My description' | translate)\n }}\"\n id=\"description\"\n placeholder=\"{{ 'e.g. My description' | translate }}\"\n name=\"description\"\n c8y-textarea-autoresize\n [(ngModel)]=\"groupInfoModel.c8y_Notes\"\n cols=\"{{ groupInfoModel.c8y_Notes ? groupInfoModel.c8y_Notes.length : 25 }}\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n ></textarea>\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupDescriptionForm.form.invalid\"\n (click)=\"\n update({ c8y_Notes: groupInfoModel.c8y_Notes });\n groupDescriptionForm.form.markAsPristine()\n \"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </form>\n\n <div\n class=\"dropdown m-t-8\"\n placement=\"bottom left\"\n container=\"body\"\n type=\"button\"\n dropdown\n *ngIf=\"isSmartGroup()\"\n #ddFilters=\"bs-dropdown\"\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Smart group filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n [disabled]=\"columnsWithFilter?.length === 0\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Smart group filters' | translate }}</span>\n <span\n class=\"p-relative p-l-4 p-r-16\"\n *ngIf=\"columnsWithFilter?.length > 0\"\n >\n <span class=\"badge badge-system p-absolute\" data-cy=\"group-info--filter-number\">\n {{ columnsWithFilter?.length }}\n </span>\n </span>\n </button>\n <button\n class=\"btn-help btn-help--sm m-r-4\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ filterMsg | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n data-cy=\"group-info--help-button\"\n container=\"body\"\n type=\"button\"\n ></button>\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n <li\n *ngFor=\"let column of columnsWithFilter; let last = last\"\n [ngClass]=\"{ 'separator-bottom': !last }\"\n >\n <ng-container>\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n <div\n class=\"list-group-item borderless d-flex d-col\"\n *ngFor=\"\n let groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n let first = first\n \"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n <p\n class=\"small p-b-4\"\n *ngIf=\"groupedFilterChips.label\"\n >\n {{ groupedFilterChips.label | translate }}\n </p>\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n <span\n class=\"tag tag--info chip\"\n data-cy=\"group-info--grouped-filter-chip\"\n *ngFor=\"let chip of groupedFilterChips.chips\"\n >\n {{ chip.displayValue | translate }}\n </span>\n </div>\n </div>\n </ng-container>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class=\"flex-grow\">\n <ul class=\"list-unstyled small\">\n <li class=\"p-t-4 p-b-4 d-flex separator-top-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.creationTime | c8yDate }}</span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.lastUpdated | c8yDate }}</span>\n </li>\n <li\n class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\"\n *ngIf=\"group.com_cumulocity_model_Agent\"\n >\n <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n <span\n class=\"m-l-auto\"\n *ngIf=\"group.c8y_BrokerSource\"\n >\n {{ group.c8y_BrokerSource.status }}\n </span>\n <span\n class=\"m-l-auto\"\n *ngIf=\"!group.c8y_BrokerSource\"\n >\n {{ 'Offline' | translate }}\n </span>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: TextareaAutoresizeDirective, selector: "[c8y-textarea-autoresize]" }, { kind: "directive", type: BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: FilterMapperPipe, name: "mapToFilterChips" }, { kind: "pipe", type: GroupedFilterChips, name: "groupedFilterChips" }] }); }
|
|
2141
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: GroupInfoComponent, isStandalone: true, selector: "c8y-group-info", inputs: { group: "group" }, outputs: { groupChange: "groupChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"bg-level-1 separator-bottom\">\n <div class=\"card-block p-t-24 p-b-24 large-padding\">\n <div class=\"content-flex-70\">\n <div class=\"text-center col-1\">\n <i\n class=\"c8y-icon-duocolor icon-48\"\n [c8yIcon]=\"groupIcon\"\n ></i>\n <p>\n @if (group.c8y_IsDynamicGroup) {\n <small class=\"label label-info\">\n {{ 'Smart group' | translate }}\n </small>\n }\n @if (!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent) {\n <small\n class=\"label label-info text-truncate d-inline-block\"\n title=\"{{ label | translate }}\"\n >\n {{ label | translate }}\n </small>\n }\n @if (group.com_cumulocity_model_Agent) {\n <small class=\"label label-info\">\n {{ 'Remote group' | translate }}\n </small>\n }\n </p>\n </div>\n\n <div class=\"flex-grow col-10\">\n <div class=\"content-flex-80\">\n <div class=\"col-9\">\n <form #groupNameForm=\"ngForm\">\n <c8y-form-group class=\"form-group-lg m-b-0\">\n <label\n class=\"sr-only\"\n for=\"groupName\"\n translate\n >\n Name\n </label>\n @if (!canEdit) {\n <p class=\"form-control-static\">\n {{ groupInfoModel.name }}\n </p>\n }\n @if (canEdit) {\n <div class=\"input-group input-group-lg input-group-editable\">\n <input\n class=\"form-control\"\n title=\"{{ groupInfoModel.name }}\"\n id=\"groupName\"\n placeholder=\"{{ 'e.g. My group' | translate }}\"\n name=\"name\"\n type=\"text\"\n required\n [(ngModel)]=\"groupInfoModel.name\"\n size=\"{{ groupInfoModel.name.length + 2 }}\"\n maxlength=\"254\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupNameForm.form.invalid\"\n (click)=\"\n update({ name: groupInfoModel.name }); groupNameForm.form.markAsPristine()\n \"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n }\n </c8y-form-group>\n </form>\n <form #groupDescriptionForm=\"ngForm\">\n <label\n class=\"sr-only\"\n for=\"description\"\n translate\n >\n Description\n </label>\n @if (canEdit) {\n <div class=\"input-group input-group-editable\">\n <textarea\n class=\"form-control no-resize\"\n title=\"{{\n groupInfoModel.c8y_Notes\n ? groupInfoModel.c8y_Notes\n : (descriptionLabel | translate)\n }}\"\n id=\"description\"\n placeholder=\"{{ descriptionLabel | translate }}\"\n name=\"description\"\n c8y-textarea-autoresize\n [(ngModel)]=\"groupInfoModel.c8y_Notes\"\n cols=\"{{ groupInfoModel.c8y_Notes ? groupInfoModel.c8y_Notes.length : 25 }}\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n ></textarea>\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupDescriptionForm.form.invalid\"\n (click)=\"\n update({ c8y_Notes: groupInfoModel.c8y_Notes });\n groupDescriptionForm.form.markAsPristine()\n \"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n } @else {\n <p class=\"form-control-static\">\n {{ groupInfoModel.c8y_Notes }}\n </p>\n }\n </form>\n\n @if (isSmartGroup()) {\n <div\n class=\"dropdown m-t-8\"\n placement=\"bottom left\"\n container=\"body\"\n type=\"button\"\n dropdown\n #ddFilters=\"bs-dropdown\"\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Smart group filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n [disabled]=\"columnsWithFilter?.length === 0\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Smart group filters' | translate }}</span>\n @if (columnsWithFilter?.length > 0) {\n <span class=\"p-relative p-l-4 p-r-16\">\n <span\n class=\"badge badge-system p-absolute\"\n data-cy=\"group-info--filter-number\"\n >\n {{ columnsWithFilter?.length }}\n </span>\n </span>\n }\n </button>\n <button\n class=\"btn-help btn-help--sm m-r-4\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ filterMsg | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n data-cy=\"group-info--help-button\"\n ></button>\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n @for (column of columnsWithFilter; track column; let last = $last) {\n <li [ngClass]=\"{ 'separator-bottom': !last }\">\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n @for (\n groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n track groupedFilterChips;\n let first = $first\n ) {\n <div\n class=\"list-group-item borderless d-flex d-col\"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n @if (groupedFilterChips.label) {\n <p class=\"small p-b-4\">\n {{ groupedFilterChips.label | translate }}\n </p>\n }\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n @for (chip of groupedFilterChips.chips; track chip) {\n <span\n class=\"tag tag--info chip\"\n data-cy=\"group-info--grouped-filter-chip\"\n >\n {{ chip.displayValue | translate }}\n </span>\n }\n </div>\n </div>\n }\n </li>\n }\n </ul>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"flex-grow\">\n <ul class=\"list-unstyled small\">\n <li class=\"p-t-4 p-b-4 d-flex separator-top-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.creationTime | c8yDate }}</span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.lastUpdated | c8yDate }}</span>\n </li>\n @if (group.com_cumulocity_model_Agent) {\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n @if (group.c8y_BrokerSource) {\n <span class=\"m-l-auto\">\n {{ group.c8y_BrokerSource.status | translate }}\n </span>\n }\n @if (!group.c8y_BrokerSource) {\n <span class=\"m-l-auto\">\n {{ 'Offline' | translate }}\n </span>\n }\n </li>\n }\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "directive", type: TextareaAutoresizeDirective, selector: "[c8y-textarea-autoresize]" }, { kind: "directive", type: BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: FilterMapperPipe, name: "mapToFilterChips" }, { kind: "pipe", type: GroupedFilterChips, name: "groupedFilterChips" }] }); }
|
|
2063
2142
|
}
|
|
2064
2143
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GroupInfoComponent, decorators: [{
|
|
2065
2144
|
type: Component,
|
|
2066
2145
|
args: [{ selector: 'c8y-group-info', imports: [
|
|
2067
2146
|
IconDirective,
|
|
2068
|
-
NgIf,
|
|
2069
2147
|
FormsModule,
|
|
2070
2148
|
FormGroupComponent,
|
|
2071
2149
|
C8yTranslateDirective,
|
|
@@ -2076,14 +2154,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2076
2154
|
BsDropdownToggleDirective,
|
|
2077
2155
|
PopoverDirective,
|
|
2078
2156
|
BsDropdownMenuDirective,
|
|
2079
|
-
NgFor,
|
|
2080
2157
|
NgClass,
|
|
2081
2158
|
C8yTranslatePipe,
|
|
2082
2159
|
AsyncPipe,
|
|
2083
2160
|
DatePipe,
|
|
2084
2161
|
FilterMapperPipe,
|
|
2085
2162
|
GroupedFilterChips
|
|
2086
|
-
], template: "<div class=\"bg-level-1 separator-bottom\">\n <div class=\"card-block p-t-24 p-b-24 large-padding\">\n <div class=\"content-flex-70\">\n <div class=\"text-center col-1\">\n <i\n class=\"c8y-icon-duocolor icon-48\"\n [c8yIcon]=\"groupIcon\"\n ></i>\n <p>\n <small\n class=\"label label-info\"\n *ngIf=\"group.c8y_IsDynamicGroup\"\n >\n {{ 'Smart group' | translate }}\n </small>\n <small\n class=\"label label-info text-truncate d-inline-block\"\n title=\"{{ label | translate }}\"\n *ngIf=\"!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent\"\n >\n {{ label | translate }}\n </small>\n <small\n class=\"label label-info\"\n *ngIf=\"group.com_cumulocity_model_Agent\"\n >\n {{ 'Remote group' | translate }}\n </small>\n </p>\n </div>\n\n <div class=\"flex-grow col-10\">\n <div class=\"content-flex-80\">\n <div class=\"col-9\">\n <form #groupNameForm=\"ngForm\">\n <c8y-form-group class=\"form-group-lg m-b-0\">\n <label\n class=\"sr-only\"\n for=\"groupName\"\n translate\n >\n Name\n </label>\n <p\n class=\"form-control-static\"\n *ngIf=\"!canEdit\"\n >\n {{ groupInfoModel.name }}\n </p>\n <div\n class=\"input-group input-group-lg input-group-editable\"\n *ngIf=\"canEdit\"\n >\n <input\n class=\"form-control\"\n title=\"{{ groupInfoModel.name }}\"\n id=\"groupName\"\n placeholder=\"{{ 'e.g. My group' | translate }}\"\n name=\"name\"\n type=\"text\"\n required\n [(ngModel)]=\"groupInfoModel.name\"\n size=\"{{ groupInfoModel.name.length + 2 }}\"\n maxlength=\"254\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupNameForm.form.invalid\"\n (click)=\"\n update({ name: groupInfoModel.name }); groupNameForm.form.markAsPristine()\n \"\n [actionName]=\"'groupInfo:EditedNameSaved'\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </form>\n <form #groupDescriptionForm=\"ngForm\">\n <label\n class=\"sr-only\"\n for=\"description\"\n translate\n >\n Description\n </label>\n <p\n class=\"form-control-static\"\n *ngIf=\"!canEdit\"\n >\n {{ groupInfoModel.c8y_Notes }}\n </p>\n <div\n class=\"input-group input-group-editable\"\n *ngIf=\"canEdit\"\n >\n <textarea\n class=\"form-control no-resize\"\n title=\"{{\n groupInfoModel.c8y_Notes\n ? groupInfoModel.c8y_Notes\n : ('e.g. My description' | translate)\n }}\"\n id=\"description\"\n placeholder=\"{{ 'e.g. My description' | translate }}\"\n name=\"description\"\n c8y-textarea-autoresize\n [(ngModel)]=\"groupInfoModel.c8y_Notes\"\n cols=\"{{ groupInfoModel.c8y_Notes ? groupInfoModel.c8y_Notes.length : 25 }}\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n ></textarea>\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupDescriptionForm.form.invalid\"\n (click)=\"\n update({ c8y_Notes: groupInfoModel.c8y_Notes });\n groupDescriptionForm.form.markAsPristine()\n \"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n </form>\n\n <div\n class=\"dropdown m-t-8\"\n placement=\"bottom left\"\n container=\"body\"\n type=\"button\"\n dropdown\n *ngIf=\"isSmartGroup()\"\n #ddFilters=\"bs-dropdown\"\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Smart group filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n [disabled]=\"columnsWithFilter?.length === 0\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Smart group filters' | translate }}</span>\n <span\n class=\"p-relative p-l-4 p-r-16\"\n *ngIf=\"columnsWithFilter?.length > 0\"\n >\n <span class=\"badge badge-system p-absolute\" data-cy=\"group-info--filter-number\">\n {{ columnsWithFilter?.length }}\n </span>\n </span>\n </button>\n <button\n class=\"btn-help btn-help--sm m-r-4\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ filterMsg | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n data-cy=\"group-info--help-button\"\n container=\"body\"\n type=\"button\"\n ></button>\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n <li\n *ngFor=\"let column of columnsWithFilter; let last = last\"\n [ngClass]=\"{ 'separator-bottom': !last }\"\n >\n <ng-container>\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n <div\n class=\"list-group-item borderless d-flex d-col\"\n *ngFor=\"\n let groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n let first = first\n \"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n <p\n class=\"small p-b-4\"\n *ngIf=\"groupedFilterChips.label\"\n >\n {{ groupedFilterChips.label | translate }}\n </p>\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n <span\n class=\"tag tag--info chip\"\n data-cy=\"group-info--grouped-filter-chip\"\n *ngFor=\"let chip of groupedFilterChips.chips\"\n >\n {{ chip.displayValue | translate }}\n </span>\n </div>\n </div>\n </ng-container>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class=\"flex-grow\">\n <ul class=\"list-unstyled small\">\n <li class=\"p-t-4 p-b-4 d-flex separator-top-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.creationTime | c8yDate }}</span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.lastUpdated | c8yDate }}</span>\n </li>\n <li\n class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\"\n *ngIf=\"group.com_cumulocity_model_Agent\"\n >\n <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n <span\n class=\"m-l-auto\"\n *ngIf=\"group.c8y_BrokerSource\"\n >\n {{ group.c8y_BrokerSource.status }}\n </span>\n <span\n class=\"m-l-auto\"\n *ngIf=\"!group.c8y_BrokerSource\"\n >\n {{ 'Offline' | translate }}\n </span>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
|
|
2163
|
+
], template: "<div class=\"bg-level-1 separator-bottom\">\n <div class=\"card-block p-t-24 p-b-24 large-padding\">\n <div class=\"content-flex-70\">\n <div class=\"text-center col-1\">\n <i\n class=\"c8y-icon-duocolor icon-48\"\n [c8yIcon]=\"groupIcon\"\n ></i>\n <p>\n @if (group.c8y_IsDynamicGroup) {\n <small class=\"label label-info\">\n {{ 'Smart group' | translate }}\n </small>\n }\n @if (!group.c8y_IsDynamicGroup && !group.com_cumulocity_model_Agent) {\n <small\n class=\"label label-info text-truncate d-inline-block\"\n title=\"{{ label | translate }}\"\n >\n {{ label | translate }}\n </small>\n }\n @if (group.com_cumulocity_model_Agent) {\n <small class=\"label label-info\">\n {{ 'Remote group' | translate }}\n </small>\n }\n </p>\n </div>\n\n <div class=\"flex-grow col-10\">\n <div class=\"content-flex-80\">\n <div class=\"col-9\">\n <form #groupNameForm=\"ngForm\">\n <c8y-form-group class=\"form-group-lg m-b-0\">\n <label\n class=\"sr-only\"\n for=\"groupName\"\n translate\n >\n Name\n </label>\n @if (!canEdit) {\n <p class=\"form-control-static\">\n {{ groupInfoModel.name }}\n </p>\n }\n @if (canEdit) {\n <div class=\"input-group input-group-lg input-group-editable\">\n <input\n class=\"form-control\"\n title=\"{{ groupInfoModel.name }}\"\n id=\"groupName\"\n placeholder=\"{{ 'e.g. My group' | translate }}\"\n name=\"name\"\n type=\"text\"\n required\n [(ngModel)]=\"groupInfoModel.name\"\n size=\"{{ groupInfoModel.name.length + 2 }}\"\n maxlength=\"254\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n />\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupNameForm.form.invalid\"\n (click)=\"\n update({ name: groupInfoModel.name }); groupNameForm.form.markAsPristine()\n \"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.NAME\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n }\n </c8y-form-group>\n </form>\n <form #groupDescriptionForm=\"ngForm\">\n <label\n class=\"sr-only\"\n for=\"description\"\n translate\n >\n Description\n </label>\n @if (canEdit) {\n <div class=\"input-group input-group-editable\">\n <textarea\n class=\"form-control no-resize\"\n title=\"{{\n groupInfoModel.c8y_Notes\n ? groupInfoModel.c8y_Notes\n : (descriptionLabel | translate)\n }}\"\n id=\"description\"\n placeholder=\"{{ descriptionLabel | translate }}\"\n name=\"description\"\n c8y-textarea-autoresize\n [(ngModel)]=\"groupInfoModel.c8y_Notes\"\n cols=\"{{ groupInfoModel.c8y_Notes ? groupInfoModel.c8y_Notes.length : 25 }}\"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n action: PRODUCT_EXPERIENCE.GROUP_INFO.ACTIONS.EDIT,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n ></textarea>\n <span></span>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"groupDescriptionForm.form.invalid\"\n (click)=\"\n update({ c8y_Notes: groupInfoModel.c8y_Notes });\n groupDescriptionForm.form.markAsPristine()\n \"\n c8yProductExperience\n [actionName]=\"PRODUCT_EXPERIENCE.EVENT\"\n [actionData]=\"{\n component: PRODUCT_EXPERIENCE.GROUP_INFO.COMPONENTS.GROUP_INFO,\n result: PRODUCT_EXPERIENCE.GROUP_INFO.RESULTS.EDIT_SAVED,\n property: PRODUCT_EXPERIENCE.GROUP_INFO.PROPERTIES.DESCRIPTION\n }\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n } @else {\n <p class=\"form-control-static\">\n {{ groupInfoModel.c8y_Notes }}\n </p>\n }\n </form>\n\n @if (isSmartGroup()) {\n <div\n class=\"dropdown m-t-8\"\n placement=\"bottom left\"\n container=\"body\"\n type=\"button\"\n dropdown\n #ddFilters=\"bs-dropdown\"\n [insideClick]=\"true\"\n >\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Smart group filters' | translate }}\"\n aria-haspopup=\"true\"\n dropdownToggle\n data-cy=\"c8y-data-grid--filters\"\n [disabled]=\"columnsWithFilter?.length === 0\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"filter\"\n ></i>\n <span>{{ 'Smart group filters' | translate }}</span>\n @if (columnsWithFilter?.length > 0) {\n <span class=\"p-relative p-l-4 p-r-16\">\n <span\n class=\"badge badge-system p-absolute\"\n data-cy=\"group-info--filter-number\"\n >\n {{ columnsWithFilter?.length }}\n </span>\n </span>\n }\n </button>\n <button\n class=\"btn-help btn-help--sm m-r-4\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{ filterMsg | translate }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n data-cy=\"group-info--help-button\"\n ></button>\n <div\n class=\"dropdown-menu\"\n *dropdownMenu\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"data-grid__dropdown bg-level-0\">\n <ul class=\"list-unstyled m-0\">\n @for (column of columnsWithFilter; track column; let last = $last) {\n <li [ngClass]=\"{ 'separator-bottom': !last }\">\n <div\n class=\"dropdown-header sticky-top text-truncate no-border-top p-b-0\"\n title=\"{{ (column.header | translate) || column.name }}\"\n >\n <label>\n {{ (column.header | translate) || column.name }}\n </label>\n </div>\n @for (\n groupedFilterChips of column\n | mapToFilterChips\n | async\n | groupedFilterChips;\n track groupedFilterChips;\n let first = $first\n ) {\n <div\n class=\"list-group-item borderless d-flex d-col\"\n [ngClass]=\"{ 'p-t-0': first }\"\n >\n @if (groupedFilterChips.label) {\n <p class=\"small p-b-4\">\n {{ groupedFilterChips.label | translate }}\n </p>\n }\n <div class=\"d-flex a-i-center gap-4 flex-wrap\">\n @for (chip of groupedFilterChips.chips; track chip) {\n <span\n class=\"tag tag--info chip\"\n data-cy=\"group-info--grouped-filter-chip\"\n >\n {{ chip.displayValue | translate }}\n </span>\n }\n </div>\n </div>\n }\n </li>\n }\n </ul>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"flex-grow\">\n <ul class=\"list-unstyled small\">\n <li class=\"p-t-4 p-b-4 d-flex separator-top-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Created' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.creationTime | c8yDate }}</span>\n </li>\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Last updated' | translate }}</label>\n <span class=\"m-l-auto\">{{ group.lastUpdated | c8yDate }}</span>\n </li>\n @if (group.com_cumulocity_model_Agent) {\n <li class=\"p-t-4 p-b-4 d-flex separator-bottom text-nowrap\">\n <label class=\"small m-b-0 m-r-8\">{{ 'Status' | translate }}</label>\n @if (group.c8y_BrokerSource) {\n <span class=\"m-l-auto\">\n {{ group.c8y_BrokerSource.status | translate }}\n </span>\n }\n @if (!group.c8y_BrokerSource) {\n <span class=\"m-l-auto\">\n {{ 'Offline' | translate }}\n </span>\n }\n </li>\n }\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
|
|
2087
2164
|
}], ctorParameters: () => [{ type: i2.InventoryService }, { type: SubAssetsService }, { type: i2.SmartGroupsService }, { type: i3.AlertService }, { type: i3.ModalService }, { type: i4.AssetNodeService }, { type: i3.AssetTypesRealtimeService }, { type: i4$1.DeviceListExtensionService }, { type: undefined, decorators: [{
|
|
2088
2165
|
type: Inject,
|
|
2089
2166
|
args: [SUB_ASSETS_CONFIG]
|