@c8y/ngx-components 1021.60.0 → 1021.62.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/alarms/alarm-details.component.d.ts +0 -4
- package/alarms/alarm-details.component.d.ts.map +1 -1
- package/core/authentication/new-password.component.d.ts +6 -3
- package/core/authentication/new-password.component.d.ts.map +1 -1
- package/core/common/interval-based-reload.abstract.d.ts +12 -1
- package/core/common/interval-based-reload.abstract.d.ts.map +1 -1
- package/core/common/permissions.service.d.ts +2 -0
- package/core/common/permissions.service.d.ts.map +1 -1
- package/core/common/tenant-ui.service.d.ts +9 -2
- package/core/common/tenant-ui.service.d.ts.map +1 -1
- package/core/forms/phone-validation.directive.d.ts +3 -6
- package/core/forms/phone-validation.directive.d.ts.map +1 -1
- package/core/router/router.module.d.ts.map +1 -1
- package/device-provisioned-certificates/device-provisioned-certificates.service.d.ts.map +1 -1
- package/esm2022/alarms/alarm-details.component.mjs +10 -10
- package/esm2022/core/authentication/new-password.component.mjs +26 -5
- package/esm2022/core/common/interval-based-reload.abstract.mjs +50 -2
- package/esm2022/core/common/permissions.service.mjs +3 -1
- package/esm2022/core/common/tenant-ui.service.mjs +28 -6
- package/esm2022/core/forms/phone-validation.directive.mjs +18 -19
- package/esm2022/core/router/router.module.mjs +1 -5
- package/esm2022/core/user/user-edit.component.mjs +1 -1
- package/esm2022/device-provisioned-certificates/device-provisioned-certificates.service.mjs +8 -3
- package/esm2022/tenants/custom-properties/custom-properties.component.mjs +25 -5
- package/esm2022/tenants/existing-tenant.guard.mjs +18 -0
- package/esm2022/tenants/index.mjs +3 -1
- package/esm2022/tenants/support-user-access/support-user-access.component.mjs +31 -0
- package/esm2022/tenants/tenant-form/tenant-form-inputs-definitions.mjs +116 -0
- package/esm2022/tenants/tenant-form/tenant-form.component.mjs +294 -0
- package/esm2022/tenants/tenant-limits/tenant-limits-definitions.mjs +10 -17
- package/esm2022/tenants/tenant-limits/tenant-limits.component.mjs +42 -29
- package/esm2022/tenants/tenant-list/tenant-list.component.mjs +17 -8
- package/esm2022/tenants/tenants.model.mjs +30 -1
- package/esm2022/tenants/tenants.module.mjs +57 -22
- package/esm2022/translation-editor/data/translation-store.service.mjs +11 -8
- package/esm2022/translation-editor/index.mjs +22 -5
- package/esm2022/translation-editor/lazy/advanced-translation-editor/advanced-translation-editor.component.mjs +136 -0
- package/esm2022/translation-editor/lazy/index.mjs +2 -1
- package/esm2022/translation-editor/translation-editor-tab-factory.service.mjs +40 -0
- package/esm2022/translation-editor/translation-editor.constants.mjs +4 -0
- package/esm2022/upgrade/upgraded-services/index.mjs +2 -1
- package/esm2022/upgrade/upgraded-services/tenant-policies.service.mjs +11 -0
- package/esm2022/upgrade/upgraded-services/upgraded-services.module.mjs +12 -3
- package/esm2022/widgets/implementations/alarms/alarm-widget-alarms-reload.component.mjs +9 -7
- package/esm2022/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-reload/datapoints-reload.component.mjs +9 -7
- package/fesm2022/c8y-ngx-components-alarms.mjs +5 -5
- package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-device-provisioned-certificates.mjs +7 -2
- package/fesm2022/c8y-ngx-components-device-provisioned-certificates.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-tenants.mjs +603 -82
- package/fesm2022/c8y-ngx-components-tenants.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-translation-editor-data.mjs +9 -6
- package/fesm2022/c8y-ngx-components-translation-editor-data.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs +127 -2
- package/fesm2022/c8y-ngx-components-translation-editor-lazy.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-translation-editor.mjs +58 -4
- package/fesm2022/c8y-ngx-components-translation-editor.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-upgrade-upgraded-services.mjs +22 -3
- package/fesm2022/c8y-ngx-components-upgrade-upgraded-services.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs +8 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +8 -6
- package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +499 -413
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/locales/de.po +17 -25
- package/locales/es.po +17 -25
- package/locales/fr.po +17 -25
- package/locales/ja_JP.po +17 -25
- package/locales/ko.po +17 -25
- package/locales/locales.pot +34 -24
- package/locales/nl.po +17 -25
- package/locales/pl.po +17 -25
- package/locales/pt_BR.po +17 -25
- package/locales/zh_CN.po +17 -25
- package/locales/zh_TW.po +17 -25
- package/package.json +1 -1
- package/tenants/custom-properties/custom-properties.component.d.ts +4 -2
- package/tenants/custom-properties/custom-properties.component.d.ts.map +1 -1
- package/tenants/existing-tenant.guard.d.ts +13 -0
- package/tenants/existing-tenant.guard.d.ts.map +1 -0
- package/tenants/index.d.ts +2 -0
- package/tenants/index.d.ts.map +1 -1
- package/tenants/support-user-access/support-user-access.component.d.ts +18 -0
- package/tenants/support-user-access/support-user-access.component.d.ts.map +1 -0
- package/tenants/tenant-form/tenant-form-inputs-definitions.d.ts +113 -0
- package/tenants/tenant-form/tenant-form-inputs-definitions.d.ts.map +1 -0
- package/tenants/tenant-form/tenant-form.component.d.ts +79 -0
- package/tenants/tenant-form/tenant-form.component.d.ts.map +1 -0
- package/tenants/tenant-limits/tenant-limits-definitions.d.ts +11 -15
- package/tenants/tenant-limits/tenant-limits-definitions.d.ts.map +1 -1
- package/tenants/tenant-limits/tenant-limits.component.d.ts +9 -7
- package/tenants/tenant-limits/tenant-limits.component.d.ts.map +1 -1
- package/tenants/tenant-list/tenant-list.component.d.ts +6 -3
- package/tenants/tenant-list/tenant-list.component.d.ts.map +1 -1
- package/tenants/tenants.model.d.ts +31 -0
- package/tenants/tenants.model.d.ts.map +1 -1
- package/tenants/tenants.module.d.ts +4 -2
- package/tenants/tenants.module.d.ts.map +1 -1
- package/translation-editor/data/translation-store.service.d.ts +3 -2
- package/translation-editor/data/translation-store.service.d.ts.map +1 -1
- package/translation-editor/index.d.ts.map +1 -1
- package/translation-editor/lazy/advanced-translation-editor/advanced-translation-editor.component.d.ts +28 -0
- package/translation-editor/lazy/advanced-translation-editor/advanced-translation-editor.component.d.ts.map +1 -0
- package/translation-editor/lazy/index.d.ts +1 -0
- package/translation-editor/lazy/index.d.ts.map +1 -1
- package/translation-editor/translation-editor-tab-factory.service.d.ts +22 -0
- package/translation-editor/translation-editor-tab-factory.service.d.ts.map +1 -0
- package/translation-editor/translation-editor.constants.d.ts +4 -0
- package/translation-editor/translation-editor.constants.d.ts.map +1 -0
- package/upgrade/upgraded-services/index.d.ts +1 -0
- package/upgrade/upgraded-services/index.d.ts.map +1 -1
- package/upgrade/upgraded-services/tenant-policies.service.d.ts +11 -0
- package/upgrade/upgraded-services/tenant-policies.service.d.ts.map +1 -0
- package/upgrade/upgraded-services/upgraded-services.module.d.ts.map +1 -1
- package/widgets/implementations/alarms/alarm-widget-alarms-reload.component.d.ts +7 -2
- package/widgets/implementations/alarms/alarm-widget-alarms-reload.component.d.ts.map +1 -1
- package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-reload/datapoints-reload.component.d.ts +7 -2
- package/widgets/implementations/datapoints-table/datapoints-table-view/datapoints-reload/datapoints-reload.component.d.ts.map +1 -1
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, InjectionToken, Optional, Inject, Component, Input, NgModule } from '@angular/core';
|
|
3
|
-
import * as
|
|
2
|
+
import { Injectable, InjectionToken, Optional, Inject, Component, Input, ViewChild, NgModule } from '@angular/core';
|
|
3
|
+
import * as i5$1 from '@angular/router';
|
|
4
4
|
import { RouterLink, RouterModule } from '@angular/router';
|
|
5
5
|
import * as i4$1 from 'ngx-bootstrap/datepicker';
|
|
6
6
|
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
|
|
7
7
|
import * as i1 from '@c8y/ngx-components';
|
|
8
|
-
import { NavigatorNode, gettext, Permissions, BuiltInActionType, Status, ValidationPattern, C8yTranslatePipe, FormGroupComponent, FormsModule, DateTimePickerModule, CoreModule, hookNavigator, hookRoute, ViewContext } from '@c8y/ngx-components';
|
|
8
|
+
import { NavigatorNode, gettext, Permissions, BuiltInActionType, Status, ValidationPattern, validateInternationalPhoneNumber, CommonModule, C8yTranslatePipe, FormGroupComponent, FormsModule, DateTimePickerModule, CoreModule, hookNavigator, hookRoute, ViewContext } from '@c8y/ngx-components';
|
|
9
9
|
import * as i4 from '@angular/common';
|
|
10
|
-
import { CommonModule } from '@angular/common';
|
|
10
|
+
import { CommonModule as CommonModule$1 } from '@angular/common';
|
|
11
11
|
import * as i3 from '@ngx-translate/core';
|
|
12
12
|
import { saveAs } from 'file-saver';
|
|
13
13
|
import { BehaviorSubject, from } from 'rxjs';
|
|
14
|
-
import { expand, takeWhile, reduce, shareReplay } from 'rxjs/operators';
|
|
14
|
+
import { expand, takeWhile, reduce, shareReplay, take } from 'rxjs/operators';
|
|
15
15
|
import * as i1$1 from '@c8y/client';
|
|
16
16
|
import { TenantStatus } from '@c8y/client';
|
|
17
17
|
import * as i5 from '@angular/forms';
|
|
18
|
-
import { FormGroup, FormControl,
|
|
18
|
+
import { Validators, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
19
|
+
import { find, cloneDeep, assign } from 'lodash-es';
|
|
20
|
+
import * as i1$2 from '@c8y/ngx-components/upgrade/upgraded-services';
|
|
19
21
|
import { gettext as gettext$1 } from '@c8y/ngx-components/gettext';
|
|
20
|
-
import { get } from 'lodash-es';
|
|
21
22
|
|
|
22
23
|
class TenantListGuard {
|
|
23
24
|
constructor(tenantUiService) {
|
|
@@ -44,6 +45,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
44
45
|
}], ctorParameters: () => [{ type: i1.TenantUiService }] });
|
|
45
46
|
|
|
46
47
|
const TENANTS_MODULE_CONFIG = new InjectionToken('TenantsModuleConfig');
|
|
48
|
+
const PRODUCT_EXPERIENCE_TENANT_MANAGEMENT = {
|
|
49
|
+
EVENTS: {
|
|
50
|
+
TENANT_MANAGEMENT: 'tenantManagement'
|
|
51
|
+
},
|
|
52
|
+
COMPONENTS: {
|
|
53
|
+
TENANT_LIST: 'tenant-list',
|
|
54
|
+
TENANT_FORM: 'tenant-form',
|
|
55
|
+
TENANT_CUSTOM_PROPERTIES: 'tenant-custom-properties',
|
|
56
|
+
TENANT_LIMITS: 'tenant-limits'
|
|
57
|
+
},
|
|
58
|
+
ACTIONS: {
|
|
59
|
+
TENANT_CREATION_INITIALIZED: 'tenantCreationInitialized',
|
|
60
|
+
TENANT_CREATION_STARTED_FILLING: 'tenantCreationStartedFilling',
|
|
61
|
+
TENANT_CREATION_SAVED: 'tenantCreationSaved',
|
|
62
|
+
TENANT_PROPERTIES_OPENED: 'tenantPropertiesOpened',
|
|
63
|
+
TENANT_PROPERTIES_STARTED_CHANGING: 'tenantPropertiesStartedChanging',
|
|
64
|
+
TENANT_PROPERTIES_SAVED: 'tenantPropertiesSaved',
|
|
65
|
+
TENANT_CUSTOM_PROPERTIES_OPENED: 'tenantCustomPropertiesOpened',
|
|
66
|
+
TENANT_CUSTOM_PROPERTIES_STARTED_CHANGING: 'tenantCustomPropertiesStartedChanging',
|
|
67
|
+
TENANT_CUSTOM_PROPERTIES_SAVED: 'tenantCustomPropertiesSaved',
|
|
68
|
+
TENANT_LIMITS_OPENED: 'tenantLimitsOpened',
|
|
69
|
+
TENANT_LIMITS_STARTED_CHANGING: 'tenantLimitsStartedChanging',
|
|
70
|
+
TENANT_LIMITS_SAVED: 'tenantLimitsSaved'
|
|
71
|
+
},
|
|
72
|
+
RESULTS: {
|
|
73
|
+
SUCCESS: 'success',
|
|
74
|
+
FAILURE: 'failure'
|
|
75
|
+
}
|
|
76
|
+
};
|
|
47
77
|
|
|
48
78
|
class TenantsNavigationFactory {
|
|
49
79
|
constructor(tenantListGuard, config) {
|
|
@@ -185,8 +215,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
185
215
|
args: [{ selector: 'c8y-status-filtering-form-renderer', template: "<form #filterForm=\"ngForm\">\n <div class=\"m-b-8 p-t-8\">\n <label>{{ 'Filter by status' | translate }}</label>\n <c8y-form-group class=\"m-b-0\">\n <label class=\"c8y-checkbox\">\n <input type=\"checkbox\" name=\"active\" [(ngModel)]=\"model.active\" />\n <span></span>\n <span>{{ 'Active`tenant`' | translate }}</span>\n </label>\n </c8y-form-group>\n <c8y-form-group class=\"m-b-0\">\n <label class=\"c8y-checkbox\">\n <input type=\"checkbox\" name=\"suspended\" [(ngModel)]=\"model.suspended\" />\n <span></span>\n <span>{{ 'Suspended`tenant`' | translate }}</span>\n </label>\n </c8y-form-group>\n </div>\n</form>\n\n<div class=\"data-grid__dropdown__footer d-flex separator-top\">\n <button\n class=\"btn btn-default btn-sm m-r-8 flex-grow\"\n (click)=\"resetFilter()\"\n title=\"{{ 'Reset' | translate }}\"\n >\n {{ 'Reset' | translate }}\n </button>\n <button\n class=\"btn btn-primary btn-sm flex-grow\"\n [disabled]=\"filterForm.invalid\"\n (click)=\"applyFilter()\"\n title=\"{{ 'Apply' | translate }}\"\n >\n {{ 'Apply' | translate }}\n </button>\n</div>\n" }]
|
|
186
216
|
}], ctorParameters: () => [{ type: i1.FilteringFormRendererContext }] });
|
|
187
217
|
|
|
218
|
+
const { EVENTS: EVENTS$3, COMPONENTS: COMPONENTS$3, ACTIONS: ACTIONS$3 } = PRODUCT_EXPERIENCE_TENANT_MANAGEMENT;
|
|
188
219
|
class TenantListComponent {
|
|
189
|
-
constructor(appState, alertService, modalService, translateService, tenantService, tenantUiService, location, passwordService, userService, permissionsService) {
|
|
220
|
+
constructor(appState, alertService, modalService, translateService, tenantService, tenantUiService, location, passwordService, userService, permissionsService, gainsightService) {
|
|
190
221
|
this.appState = appState;
|
|
191
222
|
this.alertService = alertService;
|
|
192
223
|
this.modalService = modalService;
|
|
@@ -197,6 +228,7 @@ class TenantListComponent {
|
|
|
197
228
|
this.passwordService = passwordService;
|
|
198
229
|
this.userService = userService;
|
|
199
230
|
this.permissionsService = permissionsService;
|
|
231
|
+
this.gainsightService = gainsightService;
|
|
200
232
|
this.tenants$ = new BehaviorSubject(undefined);
|
|
201
233
|
this.isPermittedToCreateTenanant = this.permissionsService.hasAnyRole([
|
|
202
234
|
Permissions.ROLE_TENANT_MANAGEMENT_ADMIN,
|
|
@@ -336,7 +368,13 @@ class TenantListComponent {
|
|
|
336
368
|
}
|
|
337
369
|
];
|
|
338
370
|
}
|
|
339
|
-
createTenant() {
|
|
371
|
+
createTenant(options = { sendGainsightEvent: true }) {
|
|
372
|
+
if (options.sendGainsightEvent) {
|
|
373
|
+
this.gainsightService.triggerEvent(EVENTS$3.TENANT_MANAGEMENT, {
|
|
374
|
+
component: COMPONENTS$3.TENANT_LIST,
|
|
375
|
+
action: ACTIONS$3.TENANT_CREATION_INITIALIZED
|
|
376
|
+
});
|
|
377
|
+
}
|
|
340
378
|
this.location.go('/tenants/new');
|
|
341
379
|
}
|
|
342
380
|
goToDetails(tenant) {
|
|
@@ -435,13 +473,425 @@ class TenantListComponent {
|
|
|
435
473
|
const blob = new Blob([data], { type: contentType });
|
|
436
474
|
saveAs(blob, filename);
|
|
437
475
|
}
|
|
438
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantListComponent, deps: [{ token: i1.AppStateService }, { token: i1.AlertService }, { token: i1.ModalService }, { token: i3.TranslateService }, { token: i1$1.TenantService }, { token: i1.TenantUiService }, { token: i4.Location }, { token: i1.PasswordService }, { token: i1$1.UserService }, { token: i1.Permissions }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
439
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TenantListComponent, selector: "c8y-tenant-list", ngImport: i0, template: "<c8y-title>\n {{ 'Subtenants' | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-layers\"\n label=\"{{ 'Tenants' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n *ngIf=\"!!(appState.state$ | async).newsletter\"\n [placement]=\"'right'\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{\n 'Downloads the list of emails of users subscribed for newsletter on the current tenant and its subtenants.'\n | translate\n }}\"\n type=\"button\"\n (click)=\"downloadNewsletterEmails()\"\n >\n <i c8yIcon=\"download\"></i>\n {{ 'Email addresses' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Create tenant' | translate }}\"\n type=\"button\"\n (click)=\"createTenant()\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Create tenant' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#managing-subtenants\"></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"tenants$ | async\"\n [pagination]=\"pagination\"\n [showSearch]=\"showSearch\"\n [actionControls]=\"actionControls\"\n (onReload)=\"loadTenants()\"\n >\n <ng-container *ngIf=\"!(tenants$ | async); else empty\">\n <c8y-loading></c8y-loading>\n </ng-container>\n <ng-template #empty>\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-layers'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"\n stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\n \"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <ng-container *ngIf=\"stats?.size === 0\">\n <div>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Create tenant' | translate }}\"\n (click)=\"createTenant()\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n {{ 'Create tenant' | translate }}\n </button>\n </div>\n <p c8y-guide-docs>\n <small\n translate\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"/docs/enterprise-tenant/managing-tenants\">user documentation</a>\n .\n </small>\n </p>\n </ng-container>\n </c8y-ui-empty-state>\n </ng-template>\n\n <c8y-column name=\"company\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }}\">\n <a [routerLink]=\"['/tenants', context.item.id]\">{{ context.value }}</a>\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"parent\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value || currentTenant.name }}\">\n {{ context.value || currentTenant.name }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"creationTime\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value | c8yDate }}\">\n {{ context.value | c8yDate }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"status\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span\n title=\"{{ 'Active`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.ACTIVE\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"check-circle\"\n ></i>\n </span>\n <span\n title=\"{{ 'Suspended`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.SUSPENDED\"\n >\n <i\n class=\"text-danger\"\n c8yIcon=\"ban\"\n ></i>\n </span>\n </ng-container>\n </c8y-column>\n </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "
|
|
476
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantListComponent, deps: [{ token: i1.AppStateService }, { token: i1.AlertService }, { token: i1.ModalService }, { token: i3.TranslateService }, { token: i1$1.TenantService }, { token: i1.TenantUiService }, { token: i4.Location }, { token: i1.PasswordService }, { token: i1$1.UserService }, { token: i1.Permissions }, { token: i1.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
477
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TenantListComponent, selector: "c8y-tenant-list", ngImport: i0, template: "<c8y-title>\n {{ 'Subtenants' | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-layers\"\n label=\"{{ 'Tenants' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n *ngIf=\"!!(appState.state$ | async).newsletter\"\n [placement]=\"'right'\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{\n 'Downloads the list of emails of users subscribed for newsletter on the current tenant and its subtenants.'\n | translate\n }}\"\n type=\"button\"\n (click)=\"downloadNewsletterEmails()\"\n >\n <i c8yIcon=\"download\"></i>\n {{ 'Email addresses' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Create tenant' | translate }}\"\n type=\"button\"\n (click)=\"createTenant({ sendGainsightEvent: false })\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Create tenant' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#managing-subtenants\"></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"tenants$ | async\"\n [pagination]=\"pagination\"\n [showSearch]=\"showSearch\"\n [actionControls]=\"actionControls\"\n (onReload)=\"loadTenants()\"\n >\n <ng-container *ngIf=\"!(tenants$ | async); else empty\">\n <c8y-loading></c8y-loading>\n </ng-container>\n <ng-template #empty>\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-layers'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"\n stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\n \"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <ng-container *ngIf=\"stats?.size === 0\">\n <div>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Create tenant' | translate }}\"\n (click)=\"createTenant()\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n {{ 'Create tenant' | translate }}\n </button>\n </div>\n <p c8y-guide-docs>\n <small\n translate\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"/docs/enterprise-tenant/managing-tenants\">user documentation</a>\n .\n </small>\n </p>\n </ng-container>\n </c8y-ui-empty-state>\n </ng-template>\n\n <c8y-column name=\"company\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }}\">\n <a [routerLink]=\"['/tenants', context.item.id]\">{{ context.value }}</a>\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"parent\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value || currentTenant.name }}\">\n {{ context.value || currentTenant.name }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"creationTime\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value | c8yDate }}\">\n {{ context.value | c8yDate }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"status\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span\n title=\"{{ 'Active`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.ACTIVE\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"check-circle\"\n ></i>\n </span>\n <span\n title=\"{{ 'Suspended`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.SUSPENDED\"\n >\n <i\n class=\"text-danger\"\n c8yIcon=\"ban\"\n ></i>\n </span>\n </ng-container>\n </c8y-column>\n </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "component", type: i1.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i1.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i1.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: i1.CellRendererDefDirective, selector: "[c8yCellRendererDef]" }, { kind: "directive", type: i1.ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "component", type: i1.DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "component", type: i1.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i1.GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: i1.GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "component", type: i1.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "directive", type: i5$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DatePipe, name: "c8yDate" }] }); }
|
|
440
478
|
}
|
|
441
479
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantListComponent, decorators: [{
|
|
442
480
|
type: Component,
|
|
443
|
-
args: [{ selector: 'c8y-tenant-list', template: "<c8y-title>\n {{ 'Subtenants' | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-layers\"\n label=\"{{ 'Tenants' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n *ngIf=\"!!(appState.state$ | async).newsletter\"\n [placement]=\"'right'\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{\n 'Downloads the list of emails of users subscribed for newsletter on the current tenant and its subtenants.'\n | translate\n }}\"\n type=\"button\"\n (click)=\"downloadNewsletterEmails()\"\n >\n <i c8yIcon=\"download\"></i>\n {{ 'Email addresses' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Create tenant' | translate }}\"\n type=\"button\"\n (click)=\"createTenant()\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Create tenant' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#managing-subtenants\"></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"tenants$ | async\"\n [pagination]=\"pagination\"\n [showSearch]=\"showSearch\"\n [actionControls]=\"actionControls\"\n (onReload)=\"loadTenants()\"\n >\n <ng-container *ngIf=\"!(tenants$ | async); else empty\">\n <c8y-loading></c8y-loading>\n </ng-container>\n <ng-template #empty>\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-layers'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"\n stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\n \"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <ng-container *ngIf=\"stats?.size === 0\">\n <div>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Create tenant' | translate }}\"\n (click)=\"createTenant()\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n {{ 'Create tenant' | translate }}\n </button>\n </div>\n <p c8y-guide-docs>\n <small\n translate\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"/docs/enterprise-tenant/managing-tenants\">user documentation</a>\n .\n </small>\n </p>\n </ng-container>\n </c8y-ui-empty-state>\n </ng-template>\n\n <c8y-column name=\"company\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }}\">\n <a [routerLink]=\"['/tenants', context.item.id]\">{{ context.value }}</a>\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"parent\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value || currentTenant.name }}\">\n {{ context.value || currentTenant.name }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"creationTime\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value | c8yDate }}\">\n {{ context.value | c8yDate }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"status\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span\n title=\"{{ 'Active`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.ACTIVE\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"check-circle\"\n ></i>\n </span>\n <span\n title=\"{{ 'Suspended`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.SUSPENDED\"\n >\n <i\n class=\"text-danger\"\n c8yIcon=\"ban\"\n ></i>\n </span>\n </ng-container>\n </c8y-column>\n </c8y-data-grid>\n</div>\n" }]
|
|
444
|
-
}], ctorParameters: () => [{ type: i1.AppStateService }, { type: i1.AlertService }, { type: i1.ModalService }, { type: i3.TranslateService }, { type: i1$1.TenantService }, { type: i1.TenantUiService }, { type: i4.Location }, { type: i1.PasswordService }, { type: i1$1.UserService }, { type: i1.Permissions }] });
|
|
481
|
+
args: [{ selector: 'c8y-tenant-list', template: "<c8y-title>\n {{ 'Subtenants' | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-layers\"\n label=\"{{ 'Tenants' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n *ngIf=\"!!(appState.state$ | async).newsletter\"\n [placement]=\"'right'\"\n>\n <button\n class=\"btn btn-link\"\n title=\"{{\n 'Downloads the list of emails of users subscribed for newsletter on the current tenant and its subtenants.'\n | translate\n }}\"\n type=\"button\"\n (click)=\"downloadNewsletterEmails()\"\n >\n <i c8yIcon=\"download\"></i>\n {{ 'Email addresses' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Create tenant' | translate }}\"\n type=\"button\"\n (click)=\"createTenant({ sendGainsightEvent: false })\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Create tenant' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#managing-subtenants\"></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [rows]=\"tenants$ | async\"\n [pagination]=\"pagination\"\n [showSearch]=\"showSearch\"\n [actionControls]=\"actionControls\"\n (onReload)=\"loadTenants()\"\n >\n <ng-container *ngIf=\"!(tenants$ | async); else empty\">\n <c8y-loading></c8y-loading>\n </ng-container>\n <ng-template #empty>\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-layers'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"\n stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\n \"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <ng-container *ngIf=\"stats?.size === 0\">\n <div>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Create tenant' | translate }}\"\n (click)=\"createTenant()\"\n [disabled]=\"!isPermittedToCreateTenanant\"\n >\n {{ 'Create tenant' | translate }}\n </button>\n </div>\n <p c8y-guide-docs>\n <small\n translate\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"/docs/enterprise-tenant/managing-tenants\">user documentation</a>\n .\n </small>\n </p>\n </ng-container>\n </c8y-ui-empty-state>\n </ng-template>\n\n <c8y-column name=\"company\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }}\">\n <a [routerLink]=\"['/tenants', context.item.id]\">{{ context.value }}</a>\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"parent\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value || currentTenant.name }}\">\n {{ context.value || currentTenant.name }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"creationTime\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value | c8yDate }}\">\n {{ context.value | c8yDate }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"status\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span\n title=\"{{ 'Active`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.ACTIVE\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"check-circle\"\n ></i>\n </span>\n <span\n title=\"{{ 'Suspended`tenant`' | translate }}\"\n *ngIf=\"context.item.status === TenantStatus.SUSPENDED\"\n >\n <i\n class=\"text-danger\"\n c8yIcon=\"ban\"\n ></i>\n </span>\n </ng-container>\n </c8y-column>\n </c8y-data-grid>\n</div>\n" }]
|
|
482
|
+
}], ctorParameters: () => [{ type: i1.AppStateService }, { type: i1.AlertService }, { type: i1.ModalService }, { type: i3.TranslateService }, { type: i1$1.TenantService }, { type: i1.TenantUiService }, { type: i4.Location }, { type: i1.PasswordService }, { type: i1$1.UserService }, { type: i1.Permissions }, { type: i1.GainsightService }] });
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Define all hardTyped tenant form fields, checkboxes and select elements.
|
|
486
|
+
*
|
|
487
|
+
* while still benefiting from hard typing, thanks to "satisfies" keyword
|
|
488
|
+
*/
|
|
489
|
+
const tenantPropertiesDefinitions = {
|
|
490
|
+
tenantID: {
|
|
491
|
+
id: 'tenantId',
|
|
492
|
+
validators: [],
|
|
493
|
+
defaultValue: null,
|
|
494
|
+
type: 'text',
|
|
495
|
+
label: gettext$1('ID')
|
|
496
|
+
},
|
|
497
|
+
domain: {
|
|
498
|
+
id: 'domain',
|
|
499
|
+
validators: [
|
|
500
|
+
Validators.required,
|
|
501
|
+
Validators.maxLength(32),
|
|
502
|
+
// TODO: To be consistent, pattern should be change for domain. It is tenantId, to avoid breaking tests, and be consistent with previous implementation.
|
|
503
|
+
Validators.pattern(ValidationPattern.rules.tenantId.pattern)
|
|
504
|
+
],
|
|
505
|
+
defaultValue: null,
|
|
506
|
+
type: 'text',
|
|
507
|
+
label: gettext$1('Domain/URL'),
|
|
508
|
+
placeholder: gettext$1('e.g. my-tenant`used in URL`')
|
|
509
|
+
},
|
|
510
|
+
companyName: {
|
|
511
|
+
id: 'companyName',
|
|
512
|
+
validators: [
|
|
513
|
+
Validators.required,
|
|
514
|
+
Validators.maxLength(256),
|
|
515
|
+
Validators.pattern(ValidationPattern.rules.noWhiteSpaceAtBeginning.pattern)
|
|
516
|
+
],
|
|
517
|
+
defaultValue: null,
|
|
518
|
+
type: 'text',
|
|
519
|
+
label: gettext$1('Name'),
|
|
520
|
+
placeholder: gettext$1('e.g. Company A')
|
|
521
|
+
},
|
|
522
|
+
contactName: {
|
|
523
|
+
id: 'contactName',
|
|
524
|
+
validators: [Validators.maxLength(30)],
|
|
525
|
+
defaultValue: null,
|
|
526
|
+
type: 'text',
|
|
527
|
+
label: gettext$1('Contact name'),
|
|
528
|
+
placeholder: gettext$1('e.g. Joe Doe`LOCALIZE`')
|
|
529
|
+
},
|
|
530
|
+
contactPhone: {
|
|
531
|
+
id: 'contactPhone',
|
|
532
|
+
validators: [Validators.required, validateInternationalPhoneNumber(), Validators.maxLength(20)],
|
|
533
|
+
defaultValue: null,
|
|
534
|
+
type: 'text',
|
|
535
|
+
label: gettext$1('Contact phone'),
|
|
536
|
+
placeholder: gettext$1('e.g. +49 9 876 543 210`LOCALIZE`')
|
|
537
|
+
},
|
|
538
|
+
administratorEmail: {
|
|
539
|
+
id: 'administratorEmail',
|
|
540
|
+
validators: [Validators.required, Validators.email, Validators.maxLength(256)],
|
|
541
|
+
defaultValue: null,
|
|
542
|
+
type: 'text',
|
|
543
|
+
label: gettext$1(`Administrator's email`),
|
|
544
|
+
placeholder: gettext$1('e.g. joe.doe@example.com`LOCALIZE`')
|
|
545
|
+
},
|
|
546
|
+
administratorUsername: {
|
|
547
|
+
id: 'administratorUsername',
|
|
548
|
+
validators: [
|
|
549
|
+
Validators.required,
|
|
550
|
+
Validators.pattern(ValidationPattern.rules.user.pattern),
|
|
551
|
+
Validators.maxLength(256)
|
|
552
|
+
],
|
|
553
|
+
defaultValue: null,
|
|
554
|
+
type: 'text',
|
|
555
|
+
label: gettext$1(`Administrator's username`),
|
|
556
|
+
placeholder: gettext$1('e.g. joe`LOCALIZE`')
|
|
557
|
+
},
|
|
558
|
+
externalReference: {
|
|
559
|
+
id: 'externalReference',
|
|
560
|
+
validators: [],
|
|
561
|
+
defaultValue: null,
|
|
562
|
+
type: 'text',
|
|
563
|
+
label: gettext$1('External reference'),
|
|
564
|
+
placeholder: gettext$1('e.g. REF12345`reference number`')
|
|
565
|
+
},
|
|
566
|
+
sendPasswordResetEmail: {
|
|
567
|
+
id: 'sendPasswordResetEmail',
|
|
568
|
+
validators: [],
|
|
569
|
+
defaultValue: true,
|
|
570
|
+
type: 'checkbox',
|
|
571
|
+
label: gettext$1('Send password reset link as email')
|
|
572
|
+
},
|
|
573
|
+
tenantPolicy: {
|
|
574
|
+
id: 'tenantPolicy',
|
|
575
|
+
validators: [],
|
|
576
|
+
defaultValue: null,
|
|
577
|
+
type: 'select',
|
|
578
|
+
label: gettext$1('Tenant policy')
|
|
579
|
+
},
|
|
580
|
+
allowCreateTenants: {
|
|
581
|
+
id: 'allowCreateTenants',
|
|
582
|
+
validators: [],
|
|
583
|
+
defaultValue: null,
|
|
584
|
+
type: 'checkbox',
|
|
585
|
+
label: gettext$1('Allow creation of subtenants')
|
|
586
|
+
},
|
|
587
|
+
gainsightEnabled: {
|
|
588
|
+
id: 'gainsightEnabled',
|
|
589
|
+
validators: [],
|
|
590
|
+
defaultValue: false,
|
|
591
|
+
type: 'checkbox',
|
|
592
|
+
label: gettext$1('Enable Gainsight product experience tracking')
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
const tenantFormInputsDefinitions = tenantPropertiesDefinitions;
|
|
596
|
+
|
|
597
|
+
class SupportUserAccessComponent {
|
|
598
|
+
constructor(tenantUiService, appState, permissions) {
|
|
599
|
+
this.tenantUiService = tenantUiService;
|
|
600
|
+
this.appState = appState;
|
|
601
|
+
this.permissions = permissions;
|
|
602
|
+
}
|
|
603
|
+
async ngOnInit() {
|
|
604
|
+
this.isTopTenant = await this.tenantUiService.isManagementTenant();
|
|
605
|
+
this.setSupportUserLogin();
|
|
606
|
+
}
|
|
607
|
+
async setSupportUserLogin() {
|
|
608
|
+
const currentUser = (await this.appState.currentUser).value;
|
|
609
|
+
if (this.permissions.hasAnyRole([Permissions.ROLE_SUPPORT_ADMIN, Permissions.ROLE_SUPPORT_READ])) {
|
|
610
|
+
this.supportUserLogin = encodeURIComponent(`${currentUser.id}$`);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupportUserAccessComponent, deps: [{ token: i1.TenantUiService }, { token: i1.AppStateService }, { token: i1.Permissions }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
614
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SupportUserAccessComponent, isStandalone: true, selector: "c8y-support-user-access", inputs: { tenant: "tenant" }, ngImport: i0, template: "<div class=\"card-header separator sticky-top large-padding\">\n <div class=\"card-title fit-w\">\n <i\n class=\"c8y-icon c8y-icon-c8y-support\"\n [ngClass]=\"{ 'c8y-icon-duocolor': tenant.supportUser?.enabled }\"\n ></i>\n {{ 'Support user access' | translate }}\n </div>\n <ng-container *ngIf=\"tenant.supportUser?.enabled && supportUserLogin && isTopTenant\">\n <a\n class=\"btn btn-default btn-xs\"\n title=\"{{ 'Log in' | translate }}\"\n href=\"//{{ tenant.domain }}/apps/administration/?user={{ supportUserLogin }}\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <i c8yIcon=\"external-link\"></i>\n {{ 'Log in' | translate }}\n </a>\n </ng-container>\n</div>\n<div class=\"card-block large-padding\">\n <div class=\"form-group\">\n <label>{{ 'Status' | translate }}</label>\n <div>\n <p class=\"form-control-static\">\n <span\n title=\"{{ 'Disabled' | translate }}\"\n *ngIf=\"!tenant.supportUser?.enabled\"\n >\n <i\n class=\"text-danger\"\n c8yIcon=\"ban\"\n ></i>\n {{ 'Disabled' | translate }}\n </span>\n <span\n title=\"{{ 'Enabled' | translate }}\"\n *ngIf=\"tenant.supportUser?.enabled\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"check-circle\"\n ></i>\n {{ 'Enabled' | translate }}\n </span>\n </p>\n </div>\n </div>\n <div class=\"form-group\" data-cy=\"c8y-support-user-access--activeRequestCount\">\n <label>{{ 'Active requests count' | translate }}</label>\n\n <p class=\"form-control-static\">\n <span *ngIf=\"tenant.supportUser?.activeRequestCount\">\n <span class=\"badge badge-danger\">\n {{ tenant.supportUser?.activeRequestCount }}\n </span>\n </span>\n <span *ngIf=\"!tenant.supportUser?.enabled && tenant.supportUser?.activeRequestCount === 0\">\n {{ 'No active requests' | translate }}\n </span>\n <span *ngIf=\"tenant.supportUser?.enabled && tenant.supportUser?.activeRequestCount === 0\">\n {{ 'Not applicable' | translate }}\n </span>\n </p>\n </div>\n <div\n class=\"form-group\"\n *ngIf=\"tenant.supportUser?.enabled\"\n >\n <label>{{ 'Expiry date' | translate }}</label>\n <div>\n <p class=\"form-control-static\">\n <span *ngIf=\"tenant.supportUser?.expiryDate\">\n {{ tenant.supportUser?.expiryDate | c8yDate: 'medium' }}\n </span>\n <span *ngIf=\"!tenant.supportUser?.expiryDate\">{{ 'No limit' | translate }}</span>\n </p>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.DatePipe, name: "c8yDate" }] }); }
|
|
615
|
+
}
|
|
616
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupportUserAccessComponent, decorators: [{
|
|
617
|
+
type: Component,
|
|
618
|
+
args: [{ selector: 'c8y-support-user-access', standalone: true, imports: [CommonModule, C8yTranslatePipe], template: "<div class=\"card-header separator sticky-top large-padding\">\n <div class=\"card-title fit-w\">\n <i\n class=\"c8y-icon c8y-icon-c8y-support\"\n [ngClass]=\"{ 'c8y-icon-duocolor': tenant.supportUser?.enabled }\"\n ></i>\n {{ 'Support user access' | translate }}\n </div>\n <ng-container *ngIf=\"tenant.supportUser?.enabled && supportUserLogin && isTopTenant\">\n <a\n class=\"btn btn-default btn-xs\"\n title=\"{{ 'Log in' | translate }}\"\n href=\"//{{ tenant.domain }}/apps/administration/?user={{ supportUserLogin }}\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <i c8yIcon=\"external-link\"></i>\n {{ 'Log in' | translate }}\n </a>\n </ng-container>\n</div>\n<div class=\"card-block large-padding\">\n <div class=\"form-group\">\n <label>{{ 'Status' | translate }}</label>\n <div>\n <p class=\"form-control-static\">\n <span\n title=\"{{ 'Disabled' | translate }}\"\n *ngIf=\"!tenant.supportUser?.enabled\"\n >\n <i\n class=\"text-danger\"\n c8yIcon=\"ban\"\n ></i>\n {{ 'Disabled' | translate }}\n </span>\n <span\n title=\"{{ 'Enabled' | translate }}\"\n *ngIf=\"tenant.supportUser?.enabled\"\n >\n <i\n class=\"text-success\"\n c8yIcon=\"check-circle\"\n ></i>\n {{ 'Enabled' | translate }}\n </span>\n </p>\n </div>\n </div>\n <div class=\"form-group\" data-cy=\"c8y-support-user-access--activeRequestCount\">\n <label>{{ 'Active requests count' | translate }}</label>\n\n <p class=\"form-control-static\">\n <span *ngIf=\"tenant.supportUser?.activeRequestCount\">\n <span class=\"badge badge-danger\">\n {{ tenant.supportUser?.activeRequestCount }}\n </span>\n </span>\n <span *ngIf=\"!tenant.supportUser?.enabled && tenant.supportUser?.activeRequestCount === 0\">\n {{ 'No active requests' | translate }}\n </span>\n <span *ngIf=\"tenant.supportUser?.enabled && tenant.supportUser?.activeRequestCount === 0\">\n {{ 'Not applicable' | translate }}\n </span>\n </p>\n </div>\n <div\n class=\"form-group\"\n *ngIf=\"tenant.supportUser?.enabled\"\n >\n <label>{{ 'Expiry date' | translate }}</label>\n <div>\n <p class=\"form-control-static\">\n <span *ngIf=\"tenant.supportUser?.expiryDate\">\n {{ tenant.supportUser?.expiryDate | c8yDate: 'medium' }}\n </span>\n <span *ngIf=\"!tenant.supportUser?.expiryDate\">{{ 'No limit' | translate }}</span>\n </p>\n </div>\n </div>\n</div>\n" }]
|
|
619
|
+
}], ctorParameters: () => [{ type: i1.TenantUiService }, { type: i1.AppStateService }, { type: i1.Permissions }], propDecorators: { tenant: [{
|
|
620
|
+
type: Input
|
|
621
|
+
}] } });
|
|
622
|
+
|
|
623
|
+
const { ACTIONS: ACTIONS$2, COMPONENTS: COMPONENTS$2, EVENTS: EVENTS$2, RESULTS: RESULTS$2 } = PRODUCT_EXPERIENCE_TENANT_MANAGEMENT;
|
|
624
|
+
class TenantFormComponent {
|
|
625
|
+
constructor(tenantPoliciesServiceProvider, tenantService, tenantUiService, location, alertService, activatedRoute, translateService, gainsightService) {
|
|
626
|
+
this.tenantPoliciesServiceProvider = tenantPoliciesServiceProvider;
|
|
627
|
+
this.tenantService = tenantService;
|
|
628
|
+
this.tenantUiService = tenantUiService;
|
|
629
|
+
this.location = location;
|
|
630
|
+
this.alertService = alertService;
|
|
631
|
+
this.activatedRoute = activatedRoute;
|
|
632
|
+
this.translateService = translateService;
|
|
633
|
+
this.gainsightService = gainsightService;
|
|
634
|
+
this.MANAGEMENT_TENANT_NAME = this.tenantUiService.MANAGEMENT;
|
|
635
|
+
this.tenant = null;
|
|
636
|
+
this.tenantPolicyNone = { name: this.translateService.instant(gettext('None')) };
|
|
637
|
+
this.saveInProgress = false;
|
|
638
|
+
this.showPasswordComponent = false;
|
|
639
|
+
this.tenantForm = new FormGroup({});
|
|
640
|
+
this.fieldDefinitions = { ...tenantFormInputsDefinitions };
|
|
641
|
+
this.initialized = false;
|
|
642
|
+
}
|
|
643
|
+
async ngOnInit() {
|
|
644
|
+
await this.getHost();
|
|
645
|
+
this.getTenantId();
|
|
646
|
+
await this.getTenant();
|
|
647
|
+
await this.checkIfIsEnterpriseEdition();
|
|
648
|
+
this.initialized = true;
|
|
649
|
+
if (!this.isNew) {
|
|
650
|
+
this.sendGainsightEvent(ACTIONS$2.TENANT_PROPERTIES_OPENED);
|
|
651
|
+
}
|
|
652
|
+
this.tenantForm.valueChanges.pipe(take(1)).subscribe(() => {
|
|
653
|
+
this.sendGainsightEvent(this.isNew
|
|
654
|
+
? ACTIONS$2.TENANT_CREATION_STARTED_FILLING
|
|
655
|
+
: ACTIONS$2.TENANT_PROPERTIES_STARTED_CHANGING);
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
async onTenantPolicyChange() {
|
|
659
|
+
const passwordSettings = await this.tenantUiService.getPasswordStrengthSettings();
|
|
660
|
+
this.tenantPolicy = find(this.tenantPolicies, {
|
|
661
|
+
id: this.tenantForm.controls.tenantPolicy.value.id
|
|
662
|
+
});
|
|
663
|
+
const enforcedOnSystemLevel = passwordSettings.enforceStrength;
|
|
664
|
+
const enforcedOnTenantLevel = passwordSettings.strengthValidity;
|
|
665
|
+
const enforcedOnTenantPolicyLevel = this.tenantPoliciesServiceProvider
|
|
666
|
+
? await this.tenantPoliciesServiceProvider.doesEnforceStrongPassword(this.tenantPolicy)
|
|
667
|
+
: undefined;
|
|
668
|
+
if (this.isNew) {
|
|
669
|
+
this.passwordStrengthEnforced = enforcedOnSystemLevel || enforcedOnTenantPolicyLevel;
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
this.passwordStrengthEnforced = enforcedOnSystemLevel || enforcedOnTenantLevel;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
setForm() {
|
|
676
|
+
this.tenantForm.patchValue({
|
|
677
|
+
tenantId: this.tenant.id,
|
|
678
|
+
domain: this.tenant.domain,
|
|
679
|
+
companyName: this.tenant.company,
|
|
680
|
+
contactName: this.tenant.contactName,
|
|
681
|
+
contactPhone: this.tenant.contactPhone,
|
|
682
|
+
administratorEmail: this.tenant.adminEmail,
|
|
683
|
+
administratorUsername: this.tenant.adminName,
|
|
684
|
+
sendPasswordResetEmail: this.tenant.sendPasswordResetEmail,
|
|
685
|
+
allowCreateTenants: this.tenant.allowCreateTenants,
|
|
686
|
+
externalReference: this.tenant.customProperties.externalReference,
|
|
687
|
+
gainsightEnabled: this.tenant.customProperties.gainsightEnabled
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
getTenantId() {
|
|
691
|
+
this.tenantId = this.activatedRoute.snapshot.parent.data.contextData.id;
|
|
692
|
+
this.isNew = !this.tenantId;
|
|
693
|
+
}
|
|
694
|
+
async onSubmit() {
|
|
695
|
+
let tenantToBeSaved;
|
|
696
|
+
if (!this.isNew) {
|
|
697
|
+
const formRawValue = this.tenantForm.getRawValue();
|
|
698
|
+
const customProperties = {
|
|
699
|
+
...this.tenant.customProperties,
|
|
700
|
+
externalReference: formRawValue.externalReference,
|
|
701
|
+
gainsightEnabled: formRawValue.gainsightEnabled
|
|
702
|
+
};
|
|
703
|
+
tenantToBeSaved = {
|
|
704
|
+
id: this.tenant.id,
|
|
705
|
+
company: formRawValue.companyName,
|
|
706
|
+
contactName: formRawValue.contactName,
|
|
707
|
+
contactPhone: formRawValue.contactPhone,
|
|
708
|
+
domain: formRawValue.domain,
|
|
709
|
+
status: this.tenant.status,
|
|
710
|
+
allowCreateTenants: this.tenantForm.value.allowCreateTenants,
|
|
711
|
+
customProperties: customProperties
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
tenantToBeSaved = {
|
|
716
|
+
adminEmail: this.tenantForm.value.administratorEmail,
|
|
717
|
+
adminName: this.tenantForm.value.administratorUsername,
|
|
718
|
+
company: this.tenantForm.value.companyName,
|
|
719
|
+
contactName: this.tenantForm.value.contactName,
|
|
720
|
+
contactPhone: this.tenantForm.value.contactPhone,
|
|
721
|
+
domain: this.tenantForm.value.domain,
|
|
722
|
+
adminPass: this.tenantForm.value.password,
|
|
723
|
+
sendPasswordResetEmail: this.tenantForm.value.sendPasswordResetEmail,
|
|
724
|
+
tenantPolicyId: this.tenantForm.value.tenantPolicy?.id
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
if (this.isNew && this.host) {
|
|
728
|
+
tenantToBeSaved.domain = tenantToBeSaved.domain + this.host;
|
|
729
|
+
}
|
|
730
|
+
const t = cloneDeep(tenantToBeSaved);
|
|
731
|
+
if (t.storageLimitPerDevice === undefined) {
|
|
732
|
+
t.storageLimitPerDevice = 0;
|
|
733
|
+
}
|
|
734
|
+
this.setSaveInProgress(true);
|
|
735
|
+
try {
|
|
736
|
+
let savedTenant;
|
|
737
|
+
if (this.isNew) {
|
|
738
|
+
savedTenant = (await this.tenantService.create(t)).data;
|
|
739
|
+
if (this.tenantForm.value.allowCreateTenants) {
|
|
740
|
+
assign(savedTenant, { allowCreateTenants: this.tenantForm.value.allowCreateTenants });
|
|
741
|
+
await this.tenantService.update(savedTenant);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
savedTenant = (await this.tenantService.update(t)).data;
|
|
746
|
+
}
|
|
747
|
+
this.sendGainsightEvent(this.isNew ? ACTIONS$2.TENANT_CREATION_SAVED : ACTIONS$2.TENANT_PROPERTIES_SAVED, { result: RESULTS$2.SUCCESS });
|
|
748
|
+
this.onSave(savedTenant, this.tenantForm);
|
|
749
|
+
}
|
|
750
|
+
catch (error) {
|
|
751
|
+
this.alertService.addServerFailure(error);
|
|
752
|
+
this.sendGainsightEvent(this.isNew ? ACTIONS$2.TENANT_CREATION_SAVED : ACTIONS$2.TENANT_PROPERTIES_SAVED, { result: RESULTS$2.FAILURE, error });
|
|
753
|
+
}
|
|
754
|
+
finally {
|
|
755
|
+
this.setSaveInProgress(false);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
onSave(tenant, form) {
|
|
759
|
+
if (this.isNew) {
|
|
760
|
+
setTimeout(() => {
|
|
761
|
+
this.location.go(`/tenants/${tenant.id}`);
|
|
762
|
+
location.reload();
|
|
763
|
+
}, 2000);
|
|
764
|
+
this.alertService.success(gettext('Tenant saved.'));
|
|
765
|
+
}
|
|
766
|
+
assign(this.tenant, tenant);
|
|
767
|
+
this.alertService.success(gettext('Tenant saved.'));
|
|
768
|
+
form.markAsPristine();
|
|
769
|
+
}
|
|
770
|
+
setSaveInProgress(value) {
|
|
771
|
+
this.saveInProgress = value;
|
|
772
|
+
}
|
|
773
|
+
cancel() {
|
|
774
|
+
this.location.go('tenants');
|
|
775
|
+
}
|
|
776
|
+
shouldDisableSave() {
|
|
777
|
+
const disabled = !this.tenantForm.valid || !this.tenantForm.dirty || this.saveInProgress;
|
|
778
|
+
if (this.showPasswordComponent) {
|
|
779
|
+
if (this.passwordForm) {
|
|
780
|
+
return disabled || !this.passwordForm.valid;
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
return true;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
return disabled;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
onNewPasswordChanged(newPassword) {
|
|
791
|
+
this.tenantForm.addControl('password', new FormControl(newPassword.password));
|
|
792
|
+
}
|
|
793
|
+
onCheckboxChange(inputField) {
|
|
794
|
+
if (inputField === 'sendPasswordResetEmail') {
|
|
795
|
+
this.showPasswordComponent = !this.tenantForm.value.sendPasswordResetEmail;
|
|
796
|
+
this.removePasswordControl(this.showPasswordComponent);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
setDisabledState() {
|
|
800
|
+
if (!this.isNew) {
|
|
801
|
+
this.tenantForm.controls.tenantId.disable();
|
|
802
|
+
this.tenantForm.controls.domain.disable();
|
|
803
|
+
this.tenantForm.controls.administratorEmail.disable();
|
|
804
|
+
this.tenantForm.controls.administratorUsername.disable();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
async shouldShowSubtenantCheckbox() {
|
|
808
|
+
const currentTenantIsManagement = await this.tenantUiService.isManagementTenant();
|
|
809
|
+
const editedTenantIsChildOfManagement = this.tenant && this.tenant.parent === this.MANAGEMENT_TENANT_NAME;
|
|
810
|
+
return currentTenantIsManagement && (editedTenantIsChildOfManagement || this.isNew);
|
|
811
|
+
}
|
|
812
|
+
removePasswordControl(passwordComponentShown) {
|
|
813
|
+
if (!passwordComponentShown) {
|
|
814
|
+
this.tenantForm.removeControl('password');
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
async getTenant() {
|
|
818
|
+
if (this.tenantId && this.tenantId !== 'new') {
|
|
819
|
+
const detailedTenant = (await this.tenantService.detail(this.tenantId)).data;
|
|
820
|
+
this.title = detailedTenant.company;
|
|
821
|
+
this.onTenant(detailedTenant);
|
|
822
|
+
await this.generateForm();
|
|
823
|
+
this.setForm();
|
|
824
|
+
this.setDisabledState();
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
this.title = this.translateService.instant(gettext('New tenant'));
|
|
828
|
+
await this.generateForm();
|
|
829
|
+
await this.loadTenantPolicies();
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
async loadTenantPolicies() {
|
|
833
|
+
if (this.tenantPoliciesServiceProvider) {
|
|
834
|
+
this.onTenantPolicies(await this.tenantPoliciesServiceProvider.list());
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
async getHost() {
|
|
838
|
+
const currentTenant = await this.tenantService.current();
|
|
839
|
+
this.host = `.${currentTenant.data.domainName.split('.').slice(1).join('.')}`;
|
|
840
|
+
}
|
|
841
|
+
async checkIfIsEnterpriseEdition() {
|
|
842
|
+
this.isEnterpriseEditionTenant = await this.tenantUiService.isEnterpriseTenant();
|
|
843
|
+
}
|
|
844
|
+
onTenantPolicies(tenantPolicies) {
|
|
845
|
+
this.tenantPolicies = [this.tenantPolicyNone, ...tenantPolicies];
|
|
846
|
+
}
|
|
847
|
+
onTenant(tenant = {}) {
|
|
848
|
+
this.tenant = tenant;
|
|
849
|
+
}
|
|
850
|
+
async generateForm() {
|
|
851
|
+
const shouldShowSubtenantCheckbox = await this.shouldShowSubtenantCheckbox();
|
|
852
|
+
const gainsightAvailable = !!(await this.gainsightService.getGainsightKey());
|
|
853
|
+
if (!shouldShowSubtenantCheckbox) {
|
|
854
|
+
delete this.fieldDefinitions.allowCreateTenants;
|
|
855
|
+
}
|
|
856
|
+
if (!this.isNew) {
|
|
857
|
+
delete this.fieldDefinitions.sendPasswordResetEmail;
|
|
858
|
+
}
|
|
859
|
+
if (this.isNew || (this.host && this.isEnterpriseEditionTenant)) {
|
|
860
|
+
delete this.fieldDefinitions.tenantID;
|
|
861
|
+
}
|
|
862
|
+
if (!this.isNew && !this.host) {
|
|
863
|
+
delete this.fieldDefinitions.domain;
|
|
864
|
+
}
|
|
865
|
+
if (this.isNew || !gainsightAvailable) {
|
|
866
|
+
delete this.fieldDefinitions.gainsightEnabled;
|
|
867
|
+
}
|
|
868
|
+
if (this.isNew) {
|
|
869
|
+
delete this.fieldDefinitions.externalReference;
|
|
870
|
+
}
|
|
871
|
+
for (const field of Object.values(this.fieldDefinitions)) {
|
|
872
|
+
this.tenantForm.addControl(field.id, new FormControl(field.defaultValue, field.validators));
|
|
873
|
+
}
|
|
874
|
+
this.fieldKeys = Object.keys(this.fieldDefinitions);
|
|
875
|
+
}
|
|
876
|
+
sendGainsightEvent(action, props = {}) {
|
|
877
|
+
this.gainsightService.triggerEvent(EVENTS$2.TENANT_MANAGEMENT, {
|
|
878
|
+
component: COMPONENTS$2.TENANT_FORM,
|
|
879
|
+
action,
|
|
880
|
+
...props
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantFormComponent, deps: [{ token: i1$2.Ng1TenantPoliciesService, optional: true }, { token: i1$1.TenantService }, { token: i1.TenantUiService }, { token: i4.Location }, { token: i1.AlertService }, { token: i5$1.ActivatedRoute }, { token: i3.TranslateService }, { token: i1.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
884
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TenantFormComponent, selector: "c8y-tenant-form", viewQueries: [{ propertyName: "passwordForm", first: true, predicate: ["passwordForm"], descendants: true }], ngImport: i0, template: "<c8y-title *ngIf=\"title\">\n {{ title }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<form\n [formGroup]=\"tenantForm\"\n (ngSubmit)=\"onSubmit()\"\n>\n <div class=\"card content-fullpage d-grid grid__col--8-4--md\">\n <div class=\"inner-scroll bg-level-0\">\n <div class=\"card-header separator large-padding sticky-top\">\n <div\n class=\"card-title\"\n translate\n >\n Identification\n </div>\n </div>\n\n <div>\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let key of fieldKeys\">\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'text'\">\n <ng-container\n *ngTemplateOutlet=\"textField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'number'\">\n <ng-container\n *ngTemplateOutlet=\"numberField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'checkbox'\">\n <ng-container\n *ngTemplateOutlet=\"checkboxField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'select'\">\n <ng-container\n *ngTemplateOutlet=\"selectField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n <div\n class=\"inner-scroll bg-level-1\"\n *ngIf=\"!isNew && tenant\"\n >\n <c8y-support-user-access [tenant]=\"tenant\"></c8y-support-user-access>\n </div>\n\n <!-- FOOTER CARD -->\n <div\n class=\"card-footer separator large-padding grid__col--fullspan\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n data-cy=\"c8y-tenant-form--cancelButton\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"shouldDisableSave()\"\n data-cy=\"c8y-tenant-form--saveButton\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n\n <!-- NG TEMPLATES -->\n <ng-template\n #textField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <div class=\"input-group\">\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n />\n <span\n class=\"input-group-addon\"\n *ngIf=\"fieldDefinition.id === 'domain' && host && isNew\"\n >\n {{ host }}\n </span>\n </div>\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #numberField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #checkboxField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n (change)=\"onCheckboxChange(fieldDefinition.id)\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n <form\n #passwordForm=\"ngForm\"\n *ngIf=\"showPasswordComponent && fieldDefinition.id === 'sendPasswordResetEmail'\"\n >\n <c8y-new-password\n [showChangePasswordButton]=\"false\"\n [requireStrongPassword]=\"passwordStrengthEnforced\"\n (password)=\"onNewPasswordChanged($event)\"\n ></c8y-new-password>\n </form>\n </ng-template>\n\n <ng-template\n #selectField\n let-fieldDefinition\n >\n <c8y-form-group *ngIf=\"tenantPolicies && tenantPolicies.length > 0\">\n <label>{{ fieldDefinition.label | translate }}</label>\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n title=\"{{ fieldDefinition.label | translate }}\"\n name=\"tenantPolicy\"\n (change)=\"onTenantPolicyChange()\"\n formControlName=\"tenantPolicy\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n >\n <option\n *ngFor=\"let tenantPolicy of tenantPolicies\"\n [ngValue]=\"tenantPolicy\"\n >\n {{ tenantPolicy.name }}\n </option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n </ng-template>\n</form>\n", dependencies: [{ kind: "component", type: i1.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i1.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: i1.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: i1.NewPasswordComponent, selector: "c8y-new-password", inputs: ["showChangePasswordButton", "requireStrongPassword"], outputs: ["password"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i1.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: SupportUserAccessComponent, selector: "c8y-support-user-access", inputs: ["tenant"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
|
|
885
|
+
}
|
|
886
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantFormComponent, decorators: [{
|
|
887
|
+
type: Component,
|
|
888
|
+
args: [{ selector: 'c8y-tenant-form', template: "<c8y-title *ngIf=\"title\">\n {{ title }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<form\n [formGroup]=\"tenantForm\"\n (ngSubmit)=\"onSubmit()\"\n>\n <div class=\"card content-fullpage d-grid grid__col--8-4--md\">\n <div class=\"inner-scroll bg-level-0\">\n <div class=\"card-header separator large-padding sticky-top\">\n <div\n class=\"card-title\"\n translate\n >\n Identification\n </div>\n </div>\n\n <div>\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let key of fieldKeys\">\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'text'\">\n <ng-container\n *ngTemplateOutlet=\"textField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'number'\">\n <ng-container\n *ngTemplateOutlet=\"numberField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'checkbox'\">\n <ng-container\n *ngTemplateOutlet=\"checkboxField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'select'\">\n <ng-container\n *ngTemplateOutlet=\"selectField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n <div\n class=\"inner-scroll bg-level-1\"\n *ngIf=\"!isNew && tenant\"\n >\n <c8y-support-user-access [tenant]=\"tenant\"></c8y-support-user-access>\n </div>\n\n <!-- FOOTER CARD -->\n <div\n class=\"card-footer separator large-padding grid__col--fullspan\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n data-cy=\"c8y-tenant-form--cancelButton\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Save' | translate }}\"\n type=\"submit\"\n [disabled]=\"shouldDisableSave()\"\n data-cy=\"c8y-tenant-form--saveButton\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </div>\n\n <!-- NG TEMPLATES -->\n <ng-template\n #textField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <div class=\"input-group\">\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n />\n <span\n class=\"input-group-addon\"\n *ngIf=\"fieldDefinition.id === 'domain' && host && isNew\"\n >\n {{ host }}\n </span>\n </div>\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #numberField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #checkboxField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n (change)=\"onCheckboxChange(fieldDefinition.id)\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n <form\n #passwordForm=\"ngForm\"\n *ngIf=\"showPasswordComponent && fieldDefinition.id === 'sendPasswordResetEmail'\"\n >\n <c8y-new-password\n [showChangePasswordButton]=\"false\"\n [requireStrongPassword]=\"passwordStrengthEnforced\"\n (password)=\"onNewPasswordChanged($event)\"\n ></c8y-new-password>\n </form>\n </ng-template>\n\n <ng-template\n #selectField\n let-fieldDefinition\n >\n <c8y-form-group *ngIf=\"tenantPolicies && tenantPolicies.length > 0\">\n <label>{{ fieldDefinition.label | translate }}</label>\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n title=\"{{ fieldDefinition.label | translate }}\"\n name=\"tenantPolicy\"\n (change)=\"onTenantPolicyChange()\"\n formControlName=\"tenantPolicy\"\n [attr.data-cy]=\"'c8y-tenant-form--' + fieldDefinition.id\"\n >\n <option\n *ngFor=\"let tenantPolicy of tenantPolicies\"\n [ngValue]=\"tenantPolicy\"\n >\n {{ tenantPolicy.name }}\n </option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n </ng-template>\n</form>\n" }]
|
|
889
|
+
}], ctorParameters: () => [{ type: i1$2.Ng1TenantPoliciesService, decorators: [{
|
|
890
|
+
type: Optional
|
|
891
|
+
}] }, { type: i1$1.TenantService }, { type: i1.TenantUiService }, { type: i4.Location }, { type: i1.AlertService }, { type: i5$1.ActivatedRoute }, { type: i3.TranslateService }, { type: i1.GainsightService }], propDecorators: { passwordForm: [{
|
|
892
|
+
type: ViewChild,
|
|
893
|
+
args: ['passwordForm']
|
|
894
|
+
}] } });
|
|
445
895
|
|
|
446
896
|
const defaultFilters = {
|
|
447
897
|
query: "(type eq 'c8y_JsonSchema') and (appliesTo.TENANTS eq true)",
|
|
@@ -519,12 +969,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
519
969
|
|
|
520
970
|
class CustomPropertyFieldComponent {
|
|
521
971
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomPropertyFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
522
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CustomPropertyFieldComponent, isStandalone: true, selector: "c8y-custom-property-field", inputs: { fieldDefinition: "fieldDefinition", form: "form" }, ngImport: i0, template: "<ng-container *ngIf=\"form && fieldDefinition\">\n <ng-container [ngSwitch]=\"fieldDefinition.type\">\n <ng-container *ngSwitchCase=\"'boolean'\">\n <c8y-form-group [formGroup]=\"form\">\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'number'\">\n <c8y-form-group [formGroup]=\"form\">\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'integer'\">\n <c8y-form-group [formGroup]=\"form\">\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'string'\">\n <c8y-form-group\n *ngIf=\"!fieldDefinition.format\"\n [formGroup]=\"form\"\n >\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n\n <c8y-form-group\n *ngIf=\"fieldDefinition.format === 'datetime'\"\n [formGroup]=\"form\"\n >\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <c8y-date-time-picker\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n data-cy=\"c8y-custom-property-field--date-time-picker\"\n ></c8y-date-time-picker>\n </c8y-form-group>\n </ng-container>\n </ng-container>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: DateTimePickerModule }, { kind: "component", type: i1.DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: ["minDate", "maxDate", "placeholder", "dateInputFormat", "adaptivePosition", "size", "dateType", "config"], outputs: ["onDateSelected"] }] }); }
|
|
972
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CustomPropertyFieldComponent, isStandalone: true, selector: "c8y-custom-property-field", inputs: { fieldDefinition: "fieldDefinition", form: "form" }, ngImport: i0, template: "<ng-container *ngIf=\"form && fieldDefinition\">\n <ng-container [ngSwitch]=\"fieldDefinition.type\">\n <ng-container *ngSwitchCase=\"'boolean'\">\n <c8y-form-group [formGroup]=\"form\">\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'number'\">\n <c8y-form-group [formGroup]=\"form\">\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'integer'\">\n <c8y-form-group [formGroup]=\"form\">\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'string'\">\n <c8y-form-group\n *ngIf=\"!fieldDefinition.format\"\n [formGroup]=\"form\"\n >\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n\n <c8y-form-group\n *ngIf=\"fieldDefinition.format === 'datetime'\"\n [formGroup]=\"form\"\n >\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate }}\n </label>\n <c8y-date-time-picker\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n data-cy=\"c8y-custom-property-field--date-time-picker\"\n ></c8y-date-time-picker>\n </c8y-form-group>\n </ng-container>\n </ng-container>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: DateTimePickerModule }, { kind: "component", type: i1.DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: ["minDate", "maxDate", "placeholder", "dateInputFormat", "adaptivePosition", "size", "dateType", "config"], outputs: ["onDateSelected"] }] }); }
|
|
523
973
|
}
|
|
524
974
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomPropertyFieldComponent, decorators: [{
|
|
525
975
|
type: Component,
|
|
526
976
|
args: [{ selector: 'c8y-custom-property-field', standalone: true, imports: [
|
|
527
|
-
CommonModule,
|
|
977
|
+
CommonModule$1,
|
|
528
978
|
C8yTranslatePipe,
|
|
529
979
|
FormGroupComponent,
|
|
530
980
|
FormsModule,
|
|
@@ -537,12 +987,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
537
987
|
type: Input
|
|
538
988
|
}] } });
|
|
539
989
|
|
|
990
|
+
const { ACTIONS: ACTIONS$1, EVENTS: EVENTS$1, COMPONENTS: COMPONENTS$1, RESULTS: RESULTS$1 } = PRODUCT_EXPERIENCE_TENANT_MANAGEMENT;
|
|
540
991
|
class CustomPropertiesComponent {
|
|
541
|
-
constructor(tenantService, alertService, activatedRoute, customPropertiesService) {
|
|
992
|
+
constructor(tenantService, alertService, activatedRoute, customPropertiesService, gainsightService) {
|
|
542
993
|
this.tenantService = tenantService;
|
|
543
994
|
this.alertService = alertService;
|
|
544
995
|
this.activatedRoute = activatedRoute;
|
|
545
996
|
this.customPropertiesService = customPropertiesService;
|
|
997
|
+
this.gainsightService = gainsightService;
|
|
546
998
|
this.customPropsForm = new FormGroup({});
|
|
547
999
|
this.tenant = null;
|
|
548
1000
|
this.initialized = false;
|
|
@@ -554,6 +1006,10 @@ class CustomPropertiesComponent {
|
|
|
554
1006
|
this.fieldDefinitions = fields;
|
|
555
1007
|
this.applyValuesFromTenant();
|
|
556
1008
|
this.initialized = true;
|
|
1009
|
+
this.sendGainsightEvent(ACTIONS$1.TENANT_CUSTOM_PROPERTIES_OPENED);
|
|
1010
|
+
this.customPropsForm.valueChanges.pipe(take(1)).subscribe(() => {
|
|
1011
|
+
this.sendGainsightEvent(ACTIONS$1.TENANT_CUSTOM_PROPERTIES_STARTED_CHANGING);
|
|
1012
|
+
});
|
|
557
1013
|
}
|
|
558
1014
|
async onSubmit() {
|
|
559
1015
|
if (this.customPropsForm.invalid || !this.tenant) {
|
|
@@ -569,9 +1025,14 @@ class CustomPropertiesComponent {
|
|
|
569
1025
|
try {
|
|
570
1026
|
await this.tenantService.update(updatedTenant);
|
|
571
1027
|
this.alertService.success(gettext('Custom properties values saved.'));
|
|
1028
|
+
this.sendGainsightEvent(ACTIONS$1.TENANT_CUSTOM_PROPERTIES_SAVED, { result: RESULTS$1.SUCCESS });
|
|
572
1029
|
}
|
|
573
1030
|
catch (error) {
|
|
574
1031
|
this.alertService.addServerFailure(error);
|
|
1032
|
+
this.sendGainsightEvent(ACTIONS$1.TENANT_CUSTOM_PROPERTIES_SAVED, {
|
|
1033
|
+
result: RESULTS$1.FAILURE,
|
|
1034
|
+
error
|
|
1035
|
+
});
|
|
575
1036
|
}
|
|
576
1037
|
}
|
|
577
1038
|
async loadTenantDetails() {
|
|
@@ -597,21 +1058,29 @@ class CustomPropertiesComponent {
|
|
|
597
1058
|
});
|
|
598
1059
|
return dirtyValues;
|
|
599
1060
|
}
|
|
600
|
-
|
|
601
|
-
|
|
1061
|
+
sendGainsightEvent(action, props = {}) {
|
|
1062
|
+
this.gainsightService.triggerEvent(EVENTS$1.TENANT_MANAGEMENT, {
|
|
1063
|
+
component: COMPONENTS$1.TENANT_CUSTOM_PROPERTIES,
|
|
1064
|
+
action,
|
|
1065
|
+
...props
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomPropertiesComponent, deps: [{ token: i1$1.TenantService }, { token: i1.AlertService }, { token: i5$1.ActivatedRoute }, { token: CustomPropertiesService }, { token: i1.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1069
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CustomPropertiesComponent, isStandalone: true, selector: "c8y-custom-properties", ngImport: i0, template: "<c8y-title *ngIf=\"tenant\">\n {{ tenant.company }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<ng-container>\n <form\n [formGroup]=\"customPropsForm\"\n (ngSubmit)=\"onSubmit()\"\n >\n <div class=\"card card--fullpage m-b-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Custom properties\n </div>\n </div>\n\n <div class=\"inner-scroll\">\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#custom-properties\"></c8y-help>\n\n <!-- empty state -->\n <c8y-ui-empty-state\n [icon]=\"'property-script'\"\n [title]=\"'No custom properties to display.' | translate\"\n [subtitle]=\"'Add a new tenant property in Properties library.' | translate\"\n *ngIf=\"fieldDefinitions?.length === 0 && initialized\"\n >\n <p c8y-guide-docs>\n <small translate>\n Find out more in the\n <a c8y-guide-href=\"/docs/enterprise-tenant/managing-tenants/#custom-properties\">\n User guide\n </a>\n .\n </small>\n </p>\n </c8y-ui-empty-state>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let field of fieldDefinitions\">\n <c8y-custom-property-field\n [fieldDefinition]=\"field\"\n [form]=\"customPropsForm\"\n ></c8y-custom-property-field>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"card-footer separator\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n translate\n data-cy=\"custom-properties--cancel-button\"\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!(!customPropsForm.invalid && customPropsForm.dirty)\"\n translate\n data-cy=\"custom-properties--save-button\"\n >\n Save\n </button>\n </div>\n </div>\n </form>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i1.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: i1.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: i1.GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: i1.GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "component", type: i1.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: CustomPropertyFieldComponent, selector: "c8y-custom-property-field", inputs: ["fieldDefinition", "form"] }] }); }
|
|
602
1070
|
}
|
|
603
1071
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CustomPropertiesComponent, decorators: [{
|
|
604
1072
|
type: Component,
|
|
605
1073
|
args: [{ selector: 'c8y-custom-properties', standalone: true, imports: [
|
|
606
|
-
CommonModule,
|
|
1074
|
+
CommonModule$1,
|
|
607
1075
|
ReactiveFormsModule,
|
|
608
1076
|
FormsModule,
|
|
609
1077
|
CoreModule,
|
|
610
1078
|
RouterLink,
|
|
611
1079
|
CustomPropertyFieldComponent
|
|
612
1080
|
], template: "<c8y-title *ngIf=\"tenant\">\n {{ tenant.company }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<ng-container>\n <form\n [formGroup]=\"customPropsForm\"\n (ngSubmit)=\"onSubmit()\"\n >\n <div class=\"card card--fullpage m-b-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Custom properties\n </div>\n </div>\n\n <div class=\"inner-scroll\">\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#custom-properties\"></c8y-help>\n\n <!-- empty state -->\n <c8y-ui-empty-state\n [icon]=\"'property-script'\"\n [title]=\"'No custom properties to display.' | translate\"\n [subtitle]=\"'Add a new tenant property in Properties library.' | translate\"\n *ngIf=\"fieldDefinitions?.length === 0 && initialized\"\n >\n <p c8y-guide-docs>\n <small translate>\n Find out more in the\n <a c8y-guide-href=\"/docs/enterprise-tenant/managing-tenants/#custom-properties\">\n User guide\n </a>\n .\n </small>\n </p>\n </c8y-ui-empty-state>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let field of fieldDefinitions\">\n <c8y-custom-property-field\n [fieldDefinition]=\"field\"\n [form]=\"customPropsForm\"\n ></c8y-custom-property-field>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"card-footer separator\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n translate\n data-cy=\"custom-properties--cancel-button\"\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!(!customPropsForm.invalid && customPropsForm.dirty)\"\n translate\n data-cy=\"custom-properties--save-button\"\n >\n Save\n </button>\n </div>\n </div>\n </form>\n</ng-container>\n" }]
|
|
613
|
-
}], ctorParameters: () => [{ type: i1$1.TenantService }, { type: i1.AlertService }, { type:
|
|
1081
|
+
}], ctorParameters: () => [{ type: i1$1.TenantService }, { type: i1.AlertService }, { type: i5$1.ActivatedRoute }, { type: CustomPropertiesService }, { type: i1.GainsightService }] });
|
|
614
1082
|
|
|
1083
|
+
const MAX_DEVICE_STORAGE_LIMIT_MiB = Math.round(Number.MAX_SAFE_INTEGER / 1024 / 1024);
|
|
615
1084
|
/**
|
|
616
1085
|
* Define all hardTyped custom properties, and their configuration in one place.
|
|
617
1086
|
*
|
|
@@ -619,15 +1088,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
619
1088
|
* while still benefiting from hard typing, thanks to "satisfies" keyword
|
|
620
1089
|
*/
|
|
621
1090
|
const tenantLimitsCustomPropertiesDefinition = {
|
|
622
|
-
//TODO: External reference - going to be moved to the Properties tab.
|
|
623
|
-
externalReference: {
|
|
624
|
-
id: 'externalReference',
|
|
625
|
-
validators: [],
|
|
626
|
-
defaultValue: null,
|
|
627
|
-
type: 'text',
|
|
628
|
-
label: gettext$1('External reference'),
|
|
629
|
-
placeholder: gettext$1('e.g. REF12345`reference number`')
|
|
630
|
-
},
|
|
631
1091
|
limitDevicesNumber: {
|
|
632
1092
|
id: 'limit.devices.number',
|
|
633
1093
|
validators: [Validators.min(0)],
|
|
@@ -691,52 +1151,66 @@ const tenantLimitsCustomPropertiesDefinition = {
|
|
|
691
1151
|
placeholder: gettext$1('e.g. {{ example }}'),
|
|
692
1152
|
placeholderArgs: { example: 100 }
|
|
693
1153
|
},
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
1154
|
+
deviceStorageLimitMiB: {
|
|
1155
|
+
id: 'deviceStorageLimitMiB',
|
|
1156
|
+
validators: [Validators.min(0), Validators.max(MAX_DEVICE_STORAGE_LIMIT_MiB)],
|
|
1157
|
+
defaultValue: 0,
|
|
1158
|
+
type: 'number',
|
|
1159
|
+
label: gettext$1('Storage limit per device (MiB)'),
|
|
1160
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
1161
|
+
placeholderArgs: { example: 100 }
|
|
701
1162
|
}
|
|
702
1163
|
};
|
|
703
1164
|
const tenantLimitsCustomProperties = tenantLimitsCustomPropertiesDefinition;
|
|
704
1165
|
|
|
1166
|
+
const { ACTIONS, EVENTS, COMPONENTS, RESULTS } = PRODUCT_EXPERIENCE_TENANT_MANAGEMENT;
|
|
705
1167
|
class TenantLimitsComponent {
|
|
706
|
-
constructor(tenantService,
|
|
1168
|
+
constructor(tenantService, alertService, activatedRoute, applicationService, options, gainsightService) {
|
|
707
1169
|
this.tenantService = tenantService;
|
|
708
|
-
this.tenantOptionsService = tenantOptionsService;
|
|
709
1170
|
this.alertService = alertService;
|
|
710
1171
|
this.activatedRoute = activatedRoute;
|
|
711
1172
|
this.applicationService = applicationService;
|
|
1173
|
+
this.options = options;
|
|
1174
|
+
this.gainsightService = gainsightService;
|
|
712
1175
|
this.fieldDefinitions = { ...tenantLimitsCustomProperties };
|
|
713
1176
|
this.limitsForm = new FormGroup({});
|
|
714
1177
|
this.tenant = null;
|
|
715
1178
|
this.initialized = false;
|
|
1179
|
+
this.deviceStorageLimitInfoMessage = gettext('Default: 0 (unlimited storage)');
|
|
716
1180
|
}
|
|
717
1181
|
async ngOnInit() {
|
|
718
1182
|
await this.loadTenantDetails();
|
|
719
1183
|
await this.setupConditionalFields();
|
|
720
1184
|
this.generateForm();
|
|
721
1185
|
this.initialized = true;
|
|
1186
|
+
this.sendGainsightEvent(ACTIONS.TENANT_LIMITS_OPENED);
|
|
722
1187
|
}
|
|
723
1188
|
async onSubmit() {
|
|
724
1189
|
if (this.limitsForm.invalid || !this.tenant) {
|
|
725
1190
|
return;
|
|
726
1191
|
}
|
|
1192
|
+
const { deviceStorageLimitMiB, ...customProperties } = this.getDirtyValues();
|
|
727
1193
|
const updatedTenant = {
|
|
728
1194
|
...this.tenant,
|
|
729
1195
|
customProperties: {
|
|
730
1196
|
...this.tenant.customProperties,
|
|
731
|
-
...
|
|
1197
|
+
...customProperties
|
|
732
1198
|
}
|
|
733
1199
|
};
|
|
1200
|
+
if (this.storageLimitFeatureEnabled) {
|
|
1201
|
+
updatedTenant.storageLimitPerDevice = (deviceStorageLimitMiB || 0) * 1024 * 1024;
|
|
1202
|
+
}
|
|
1203
|
+
else {
|
|
1204
|
+
updatedTenant.storageLimitPerDevice = 0;
|
|
1205
|
+
}
|
|
734
1206
|
try {
|
|
735
1207
|
await this.tenantService.update(updatedTenant);
|
|
736
1208
|
this.alertService.success(gettext('Limit values saved.'));
|
|
1209
|
+
this.sendGainsightEvent(ACTIONS.TENANT_LIMITS_SAVED, { result: RESULTS.SUCCESS });
|
|
737
1210
|
}
|
|
738
1211
|
catch (error) {
|
|
739
1212
|
this.alertService.addServerFailure(error);
|
|
1213
|
+
this.sendGainsightEvent(ACTIONS.TENANT_LIMITS_SAVED, { result: RESULTS.FAILURE, error });
|
|
740
1214
|
}
|
|
741
1215
|
}
|
|
742
1216
|
async loadTenantDetails() {
|
|
@@ -756,15 +1230,15 @@ class TenantLimitsComponent {
|
|
|
756
1230
|
})).data;
|
|
757
1231
|
const cepModuleEnabled = apps.some(app => app.name === 'cep' || app.contextPath === 'cep');
|
|
758
1232
|
const dataBrokerModuleEnabled = apps.some(app => app.name === 'feature-broker' || app.contextPath === 'feature-broker');
|
|
759
|
-
|
|
1233
|
+
this.storageLimitFeatureEnabled = this.options.storageLimitationFeatureEnabled;
|
|
760
1234
|
if (!cepModuleEnabled) {
|
|
761
1235
|
delete this.fieldDefinitions.cepServerQueueLimit;
|
|
762
1236
|
}
|
|
763
1237
|
if (!dataBrokerModuleEnabled) {
|
|
764
1238
|
delete this.fieldDefinitions.dataBrokerQueueLimit;
|
|
765
1239
|
}
|
|
766
|
-
if (!
|
|
767
|
-
delete this.fieldDefinitions.
|
|
1240
|
+
if (!this.storageLimitFeatureEnabled) {
|
|
1241
|
+
delete this.fieldDefinitions.deviceStorageLimitMiB;
|
|
768
1242
|
}
|
|
769
1243
|
this.fieldKeys = Object.keys(this.fieldDefinitions);
|
|
770
1244
|
}
|
|
@@ -772,27 +1246,19 @@ class TenantLimitsComponent {
|
|
|
772
1246
|
this.alertService.addServerFailure(ex);
|
|
773
1247
|
}
|
|
774
1248
|
}
|
|
775
|
-
async isGainsightAvailable() {
|
|
776
|
-
if (get(window, 'C8Y_APP.gainsightKey')) {
|
|
777
|
-
return true;
|
|
778
|
-
}
|
|
779
|
-
try {
|
|
780
|
-
const res = await this.tenantOptionsService.detail({
|
|
781
|
-
category: 'configuration',
|
|
782
|
-
key: 'system.gainsight.api.key'
|
|
783
|
-
});
|
|
784
|
-
return !!res.data.value;
|
|
785
|
-
}
|
|
786
|
-
catch (error) {
|
|
787
|
-
return false;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
1249
|
generateForm() {
|
|
791
1250
|
for (const field of Object.values(tenantLimitsCustomProperties)) {
|
|
792
1251
|
this.limitsForm.addControl(field.id, new FormControl(field.defaultValue, field.validators));
|
|
793
1252
|
}
|
|
794
1253
|
const customProps = this.tenant?.customProperties || {};
|
|
795
1254
|
this.limitsForm.patchValue(customProps);
|
|
1255
|
+
if (this.storageLimitFeatureEnabled) {
|
|
1256
|
+
const deviceStorageLimitMiB = (this.tenant?.storageLimitPerDevice || 0) / 1024 / 1024;
|
|
1257
|
+
this.limitsForm.patchValue({ deviceStorageLimitMiB });
|
|
1258
|
+
}
|
|
1259
|
+
this.limitsForm.valueChanges.pipe(take(1)).subscribe(() => {
|
|
1260
|
+
this.sendGainsightEvent(ACTIONS.TENANT_LIMITS_STARTED_CHANGING);
|
|
1261
|
+
});
|
|
796
1262
|
}
|
|
797
1263
|
getDirtyValues() {
|
|
798
1264
|
const dirtyValues = {};
|
|
@@ -804,13 +1270,36 @@ class TenantLimitsComponent {
|
|
|
804
1270
|
});
|
|
805
1271
|
return dirtyValues;
|
|
806
1272
|
}
|
|
807
|
-
|
|
808
|
-
|
|
1273
|
+
sendGainsightEvent(action, props = {}) {
|
|
1274
|
+
this.gainsightService.triggerEvent(EVENTS.TENANT_MANAGEMENT, {
|
|
1275
|
+
component: COMPONENTS.TENANT_LIMITS,
|
|
1276
|
+
action,
|
|
1277
|
+
...props
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantLimitsComponent, deps: [{ token: i1$1.TenantService }, { token: i1.AlertService }, { token: i5$1.ActivatedRoute }, { token: i1$1.ApplicationService }, { token: i1.OptionsService }, { token: i1.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1281
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TenantLimitsComponent, isStandalone: true, selector: "c8y-tenant-limits", ngImport: i0, template: "<c8y-title *ngIf=\"tenant\">\n {{ tenant.company }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<form\n [formGroup]=\"limitsForm\"\n (ngSubmit)=\"onSubmit()\"\n>\n <div class=\"card card--fullpage m-b-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Limits\n </div>\n </div>\n\n <c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#setting-limits\"></c8y-help>\n\n <div class=\"inner-scroll\">\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let key of fieldKeys\">\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'text'\">\n <ng-container\n *ngTemplateOutlet=\"textField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'number'\">\n <ng-container\n *ngTemplateOutlet=\"numberField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'checkbox'\">\n <ng-container\n *ngTemplateOutlet=\"checkboxField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"card-footer separator\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"limitsForm.invalid\"\n translate\n >\n Save\n </button>\n </div>\n </div>\n\n <ng-template\n #textField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #numberField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <ng-container\n *ngIf=\"\n fieldDefinitions.deviceStorageLimitMiB &&\n fieldDefinitions.deviceStorageLimitMiB.id === fieldDefinition.id &&\n limitsForm.controls[fieldDefinition.id] as control\n \"\n >\n <div\n class=\"icon-flex\"\n *ngIf=\"!control.dirty || (control.dirty && !control.errors)\"\n >\n <p class=\"help-block\">\n <i\n class=\"text-info m-r-4\"\n c8yIcon=\"info-circle\"\n ></i>\n <span>{{ deviceStorageLimitInfoMessage | translate }}</span>\n </p>\n </div>\n </ng-container>\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #checkboxField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n </ng-template>\n</form>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: i1.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i1.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i1.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: i1.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: i1.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
|
|
809
1282
|
}
|
|
810
1283
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantLimitsComponent, decorators: [{
|
|
811
1284
|
type: Component,
|
|
812
|
-
args: [{ selector: 'c8y-tenant-limits', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule, CoreModule, RouterLink], template: "<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<form\n [formGroup]=\"limitsForm\"\n (ngSubmit)=\"onSubmit()\"\n>\n <div class=\"card card--fullpage m-b-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Limits\n </div>\n </div>\n\n <c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#setting-limits\"></c8y-help>\n\n <div class=\"inner-scroll\">\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let key of fieldKeys\">\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'text'\">\n <ng-container\n *ngTemplateOutlet=\"textField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'number'\">\n <ng-container\n *ngTemplateOutlet=\"numberField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'checkbox'\">\n <ng-container\n *ngTemplateOutlet=\"checkboxField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"card-footer separator\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"limitsForm.invalid\"\n translate\n >\n Save\n </button>\n </div>\n </div>\n\n <ng-template\n #textField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #numberField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #checkboxField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n </ng-template>\n</form>\n" }]
|
|
813
|
-
}], ctorParameters: () => [{ type: i1$1.TenantService }, { type: i1$1.
|
|
1285
|
+
args: [{ selector: 'c8y-tenant-limits', standalone: true, imports: [CommonModule$1, ReactiveFormsModule, FormsModule, CoreModule, RouterLink], template: "<c8y-title *ngIf=\"tenant\">\n {{ tenant.company }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Tenants' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-layers'\"\n [label]=\"'Subtenants' | translate\"\n [path]=\"'/tenants'\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<form\n [formGroup]=\"limitsForm\"\n (ngSubmit)=\"onSubmit()\"\n>\n <div class=\"card card--fullpage m-b-0\">\n <div class=\"card-header separator\">\n <div\n class=\"card-title\"\n translate\n >\n Limits\n </div>\n </div>\n\n <c8y-help src=\"/docs/enterprise-tenant/managing-tenants/#setting-limits\"></c8y-help>\n\n <div class=\"inner-scroll\">\n <div\n class=\"card-block\"\n *ngIf=\"!initialized\"\n >\n <c8y-loading></c8y-loading>\n </div>\n\n <div\n class=\"card-block\"\n *ngIf=\"initialized\"\n >\n <ng-container *ngFor=\"let key of fieldKeys\">\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'text'\">\n <ng-container\n *ngTemplateOutlet=\"textField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'number'\">\n <ng-container\n *ngTemplateOutlet=\"numberField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"fieldDefinitions[key].type === 'checkbox'\">\n <ng-container\n *ngTemplateOutlet=\"checkboxField; context: { $implicit: fieldDefinitions[key] }\"\n ></ng-container>\n </ng-container>\n </ng-container>\n </div>\n </div>\n\n <div\n class=\"card-footer separator\"\n *ngIf=\"initialized\"\n >\n <button\n class=\"btn btn-default\"\n type=\"button\"\n [routerLink]=\"['/tenants']\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"limitsForm.invalid\"\n translate\n >\n Save\n </button>\n </div>\n </div>\n\n <ng-template\n #textField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"text\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n />\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #numberField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label [for]=\"fieldDefinition.id\">\n {{ fieldDefinition.label | translate: fieldDefinition.labelArgs }}\n </label>\n <input\n class=\"form-control\"\n type=\"number\"\n [id]=\"fieldDefinition.id\"\n [placeholder]=\"fieldDefinition.placeholder | translate: fieldDefinition.placeholderArgs\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <ng-container\n *ngIf=\"\n fieldDefinitions.deviceStorageLimitMiB &&\n fieldDefinitions.deviceStorageLimitMiB.id === fieldDefinition.id &&\n limitsForm.controls[fieldDefinition.id] as control\n \"\n >\n <div\n class=\"icon-flex\"\n *ngIf=\"!control.dirty || (control.dirty && !control.errors)\"\n >\n <p class=\"help-block\">\n <i\n class=\"text-info m-r-4\"\n c8yIcon=\"info-circle\"\n ></i>\n <span>{{ deviceStorageLimitInfoMessage | translate }}</span>\n </p>\n </div>\n </ng-container>\n </c8y-form-group>\n </ng-template>\n\n <ng-template\n #checkboxField\n let-fieldDefinition\n >\n <c8y-form-group>\n <label\n class=\"c8y-checkbox\"\n [title]=\"fieldDefinition.label | translate\"\n [for]=\"fieldDefinition.id\"\n >\n <input\n type=\"checkbox\"\n [id]=\"fieldDefinition.id\"\n [formControlName]=\"fieldDefinition.id\"\n />\n <span></span>\n <span>{{ fieldDefinition.label | translate }}</span>\n </label>\n </c8y-form-group>\n </ng-template>\n</form>\n" }]
|
|
1286
|
+
}], ctorParameters: () => [{ type: i1$1.TenantService }, { type: i1.AlertService }, { type: i5$1.ActivatedRoute }, { type: i1$1.ApplicationService }, { type: i1.OptionsService }, { type: i1.GainsightService }] });
|
|
1287
|
+
|
|
1288
|
+
class ExistingTenantGuard {
|
|
1289
|
+
/**
|
|
1290
|
+
* Checks if the current route is displayed for an existing tenant.
|
|
1291
|
+
*
|
|
1292
|
+
* @returns `true` if visiting a route for an existing tenant.
|
|
1293
|
+
*/
|
|
1294
|
+
canActivate(route) {
|
|
1295
|
+
return route.params.id !== 'new';
|
|
1296
|
+
}
|
|
1297
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ExistingTenantGuard, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1298
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ExistingTenantGuard }); }
|
|
1299
|
+
}
|
|
1300
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ExistingTenantGuard, decorators: [{
|
|
1301
|
+
type: Injectable
|
|
1302
|
+
}] });
|
|
814
1303
|
|
|
815
1304
|
class TenantsModule {
|
|
816
1305
|
static config(config = {}) {
|
|
@@ -827,24 +1316,39 @@ class TenantsModule {
|
|
|
827
1316
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
828
1317
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: TenantsModule, declarations: [TenantListComponent,
|
|
829
1318
|
CreationTimeFilteringFormRendererComponent,
|
|
830
|
-
StatusFilteringFormRendererComponent
|
|
1319
|
+
StatusFilteringFormRendererComponent,
|
|
1320
|
+
TenantFormComponent], imports: [BsDatepickerModule, CoreModule, RouterModule, SupportUserAccessComponent] }); }
|
|
831
1321
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantsModule, providers: [
|
|
832
1322
|
TenantListGuard,
|
|
1323
|
+
ExistingTenantGuard,
|
|
833
1324
|
hookNavigator(TenantsNavigationFactory),
|
|
834
|
-
hookRoute({
|
|
835
|
-
path: 'tenants',
|
|
836
|
-
icon: 'c8y-layers',
|
|
837
|
-
component: TenantListComponent,
|
|
838
|
-
canActivate: [TenantListGuard]
|
|
839
|
-
}),
|
|
840
1325
|
hookRoute([
|
|
1326
|
+
{
|
|
1327
|
+
path: 'tenants',
|
|
1328
|
+
icon: 'c8y-layers',
|
|
1329
|
+
component: TenantListComponent,
|
|
1330
|
+
canActivate: [TenantListGuard]
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
path: 'tenants/new',
|
|
1334
|
+
component: TenantFormComponent
|
|
1335
|
+
},
|
|
1336
|
+
{
|
|
1337
|
+
path: 'properties',
|
|
1338
|
+
component: TenantFormComponent,
|
|
1339
|
+
icon: 'new-property',
|
|
1340
|
+
label: gettext('Properties'),
|
|
1341
|
+
context: ViewContext.Tenant,
|
|
1342
|
+
priority: 10000
|
|
1343
|
+
},
|
|
841
1344
|
{
|
|
842
1345
|
path: 'custom_properties',
|
|
843
1346
|
component: CustomPropertiesComponent,
|
|
844
1347
|
icon: 'property-script',
|
|
845
1348
|
label: gettext('Custom properties'),
|
|
846
1349
|
context: ViewContext.Tenant,
|
|
847
|
-
priority: 4
|
|
1350
|
+
priority: 4,
|
|
1351
|
+
canActivate: [ExistingTenantGuard]
|
|
848
1352
|
},
|
|
849
1353
|
{
|
|
850
1354
|
path: 'limits',
|
|
@@ -852,38 +1356,54 @@ class TenantsModule {
|
|
|
852
1356
|
icon: 'sliders',
|
|
853
1357
|
label: gettext('Limits'),
|
|
854
1358
|
context: ViewContext.Tenant,
|
|
855
|
-
priority: 3
|
|
1359
|
+
priority: 3,
|
|
1360
|
+
canActivate: [ExistingTenantGuard]
|
|
856
1361
|
}
|
|
857
1362
|
])
|
|
858
|
-
], imports: [
|
|
1363
|
+
], imports: [BsDatepickerModule, CoreModule, RouterModule, SupportUserAccessComponent] }); }
|
|
859
1364
|
}
|
|
860
1365
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TenantsModule, decorators: [{
|
|
861
1366
|
type: NgModule,
|
|
862
1367
|
args: [{
|
|
863
|
-
imports: [
|
|
1368
|
+
imports: [BsDatepickerModule, CoreModule, RouterModule, SupportUserAccessComponent],
|
|
864
1369
|
exports: [],
|
|
865
1370
|
declarations: [
|
|
866
1371
|
TenantListComponent,
|
|
867
1372
|
CreationTimeFilteringFormRendererComponent,
|
|
868
|
-
StatusFilteringFormRendererComponent
|
|
1373
|
+
StatusFilteringFormRendererComponent,
|
|
1374
|
+
TenantFormComponent
|
|
869
1375
|
],
|
|
870
1376
|
providers: [
|
|
871
1377
|
TenantListGuard,
|
|
1378
|
+
ExistingTenantGuard,
|
|
872
1379
|
hookNavigator(TenantsNavigationFactory),
|
|
873
|
-
hookRoute({
|
|
874
|
-
path: 'tenants',
|
|
875
|
-
icon: 'c8y-layers',
|
|
876
|
-
component: TenantListComponent,
|
|
877
|
-
canActivate: [TenantListGuard]
|
|
878
|
-
}),
|
|
879
1380
|
hookRoute([
|
|
1381
|
+
{
|
|
1382
|
+
path: 'tenants',
|
|
1383
|
+
icon: 'c8y-layers',
|
|
1384
|
+
component: TenantListComponent,
|
|
1385
|
+
canActivate: [TenantListGuard]
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
path: 'tenants/new',
|
|
1389
|
+
component: TenantFormComponent
|
|
1390
|
+
},
|
|
1391
|
+
{
|
|
1392
|
+
path: 'properties',
|
|
1393
|
+
component: TenantFormComponent,
|
|
1394
|
+
icon: 'new-property',
|
|
1395
|
+
label: gettext('Properties'),
|
|
1396
|
+
context: ViewContext.Tenant,
|
|
1397
|
+
priority: 10000
|
|
1398
|
+
},
|
|
880
1399
|
{
|
|
881
1400
|
path: 'custom_properties',
|
|
882
1401
|
component: CustomPropertiesComponent,
|
|
883
1402
|
icon: 'property-script',
|
|
884
1403
|
label: gettext('Custom properties'),
|
|
885
1404
|
context: ViewContext.Tenant,
|
|
886
|
-
priority: 4
|
|
1405
|
+
priority: 4,
|
|
1406
|
+
canActivate: [ExistingTenantGuard]
|
|
887
1407
|
},
|
|
888
1408
|
{
|
|
889
1409
|
path: 'limits',
|
|
@@ -891,7 +1411,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
891
1411
|
icon: 'sliders',
|
|
892
1412
|
label: gettext('Limits'),
|
|
893
1413
|
context: ViewContext.Tenant,
|
|
894
|
-
priority: 3
|
|
1414
|
+
priority: 3,
|
|
1415
|
+
canActivate: [ExistingTenantGuard]
|
|
895
1416
|
}
|
|
896
1417
|
])
|
|
897
1418
|
]
|
|
@@ -902,5 +1423,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
902
1423
|
* Generated bundle index. Do not edit.
|
|
903
1424
|
*/
|
|
904
1425
|
|
|
905
|
-
export { CreationTimeFilteringFormRendererComponent, CustomPropertiesComponent, StatusFilteringFormRendererComponent, TENANTS_MODULE_CONFIG, TenantListComponent, TenantListGuard, TenantsModule, TenantsNavigationFactory };
|
|
1426
|
+
export { CreationTimeFilteringFormRendererComponent, CustomPropertiesComponent, PRODUCT_EXPERIENCE_TENANT_MANAGEMENT, StatusFilteringFormRendererComponent, SupportUserAccessComponent, TENANTS_MODULE_CONFIG, TenantFormComponent, TenantListComponent, TenantListGuard, TenantsModule, TenantsNavigationFactory };
|
|
906
1427
|
//# sourceMappingURL=c8y-ngx-components-tenants.mjs.map
|