@c8y/ngx-components 1021.7.0 → 1021.13.3
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/alarms-date-filter.component.d.ts +34 -0
- package/alarms/alarms-date-filter.component.d.ts.map +1 -0
- package/alarms/alarms-filter.component.d.ts +2 -1
- package/alarms/alarms-filter.component.d.ts.map +1 -1
- package/alarms/alarms-view.service.d.ts +4 -2
- package/alarms/alarms-view.service.d.ts.map +1 -1
- package/alarms/alarms.component.d.ts +3 -1
- package/alarms/alarms.component.d.ts.map +1 -1
- package/alarms/alarms.model.d.ts +17 -1
- package/alarms/alarms.model.d.ts.map +1 -1
- package/alarms/alarms.module.d.ts +15 -13
- package/alarms/alarms.module.d.ts.map +1 -1
- package/branding/shared/data/store-branding.service.d.ts +5 -0
- package/branding/shared/data/store-branding.service.d.ts.map +1 -1
- package/branding/shared/lazy/branding/branding.component.d.ts.map +1 -1
- package/cockpit-config/cockpit-config.model.d.ts +1 -0
- package/cockpit-config/cockpit-config.model.d.ts.map +1 -1
- package/context-dashboard/dashboard-manager/dashboard-manager.module.d.ts.map +1 -1
- package/core/common/options.service.d.ts +1 -1
- package/core/common/options.service.d.ts.map +1 -1
- package/core/dashboard/dashboard.module.d.ts +19 -19
- package/core/dashboard/widget-change-event.model.d.ts +1 -1
- package/core/dashboard/widget-change-event.model.d.ts.map +1 -1
- package/core/dashboard/wiget-time-context/widget-time-context-helper.service.d.ts +2 -1
- package/core/dashboard/wiget-time-context/widget-time-context-helper.service.d.ts.map +1 -1
- package/core/dashboard/wiget-time-context/widget-time-context-query.service.d.ts.map +1 -1
- package/core/dashboard/wiget-time-context/widget-time-context.component.d.ts +2 -1
- package/core/dashboard/wiget-time-context/widget-time-context.component.d.ts.map +1 -1
- package/core/dashboard/wiget-time-context/widget-time-context.model.d.ts +1 -14
- package/core/dashboard/wiget-time-context/widget-time-context.model.d.ts.map +1 -1
- package/core/date-time-picker/date-time-picker.component.d.ts.map +1 -1
- package/core/forms/validation-pattern.d.ts +4 -0
- package/core/forms/validation-pattern.d.ts.map +1 -1
- package/core/plugins/plugins.service.d.ts +1 -1
- package/core/plugins/plugins.service.d.ts.map +1 -1
- package/esm2022/alarm-event-selector/alarm-event-selection-list/alarm-event-selection-list.component.mjs +4 -4
- package/esm2022/alarm-event-selector/alarm-event-selector-list-item/alarm-event-selector-list-item.component.mjs +3 -3
- package/esm2022/alarms/alarms-date-filter.component.mjs +139 -0
- package/esm2022/alarms/alarms-filter.component.mjs +11 -5
- package/esm2022/alarms/alarms-type-filter.component.mjs +3 -3
- package/esm2022/alarms/alarms-view.service.mjs +15 -2
- package/esm2022/alarms/alarms.component.mjs +12 -6
- package/esm2022/alarms/alarms.model.mjs +17 -1
- package/esm2022/alarms/alarms.module.mjs +11 -4
- package/esm2022/assets-navigator/asset-selector/asset-selector-node.component.mjs +3 -3
- package/esm2022/branding/shared/data/store-branding.service.mjs +24 -1
- package/esm2022/branding/shared/lazy/branding/branding.component.mjs +3 -1
- package/esm2022/cockpit-config/cockpit-config.model.mjs +3 -2
- package/esm2022/cockpit-config/feature-config.component.mjs +3 -3
- package/esm2022/context-dashboard/dashboard-manager/dashboard-manager.module.mjs +5 -3
- package/esm2022/core/action-bar/action-bar.component.mjs +3 -3
- package/esm2022/core/common/options.service.mjs +3 -3
- package/esm2022/core/dashboard/dashboard.module.mjs +5 -4
- package/esm2022/core/dashboard/widget-change-event.model.mjs +1 -1
- package/esm2022/core/dashboard/wiget-time-context/widget-time-context-helper.service.mjs +3 -2
- package/esm2022/core/dashboard/wiget-time-context/widget-time-context-query.service.mjs +1 -1
- package/esm2022/core/dashboard/wiget-time-context/widget-time-context.component.mjs +6 -5
- package/esm2022/core/dashboard/wiget-time-context/widget-time-context.model.mjs +3 -47
- package/esm2022/core/date-time-picker/date-time-picker.component.mjs +7 -1
- package/esm2022/core/docs/defaults.items.mjs +2 -2
- package/esm2022/core/forms/validation-pattern.mjs +5 -1
- package/esm2022/core/list-display-switch/list-display-switch.component.mjs +3 -3
- package/esm2022/core/plugins/plugins.service.mjs +3 -3
- package/esm2022/core/router/context-route.guard.mjs +2 -2
- package/esm2022/core/search/search-input.component.mjs +3 -3
- package/esm2022/interval-picker/c8y-ngx-components-interval-picker.mjs +5 -0
- package/esm2022/interval-picker/index.mjs +3 -0
- package/esm2022/interval-picker/interval-picker.component.mjs +68 -0
- package/esm2022/interval-picker/interval-picker.model.mjs +47 -0
- package/esm2022/operations/bulk-operation-scheduler/operation-scheduler.component.mjs +7 -5
- package/esm2022/search/search-action.component.mjs +3 -3
- package/esm2022/tenants/custom-properties/custom-properties.component.mjs +90 -0
- package/esm2022/tenants/custom-properties/custom-properties.service.mjs +76 -0
- package/esm2022/tenants/custom-properties/custom-property-field/custom-property-field.component.mjs +29 -0
- package/esm2022/tenants/index.mjs +2 -1
- package/esm2022/tenants/tenant-limits/tenant-limits-definitions.mjs +92 -0
- package/esm2022/tenants/tenant-limits/tenant-limits.component.mjs +124 -0
- package/esm2022/tenants/tenants.module.mjs +42 -4
- package/esm2022/widgets/implementations/help-and-service-widget/help-and-service-view/help-and-service-view.component.mjs +2 -2
- package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs +5 -5
- package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-alarms.mjs +184 -16
- package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-assets-navigator.mjs +2 -2
- package/fesm2022/c8y-ngx-components-assets-navigator.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-shared-data.mjs +23 -0
- package/fesm2022/c8y-ngx-components-branding-shared-data.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs +2 -0
- package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-cockpit-config.mjs +4 -3
- package/fesm2022/c8y-ngx-components-cockpit-config.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs +4 -2
- package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-interval-picker.mjs +120 -0
- package/fesm2022/c8y-ngx-components-interval-picker.mjs.map +1 -0
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs +6 -4
- package/fesm2022/c8y-ngx-components-operations-bulk-operation-scheduler.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-search.mjs +2 -2
- package/fesm2022/c8y-ngx-components-search.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-tenants.mjs +416 -11
- package/fesm2022/c8y-ngx-components-tenants.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-help-and-service-widget.mjs +1 -1
- package/fesm2022/c8y-ngx-components-widgets-implementations-help-and-service-widget.mjs.map +1 -1
- package/fesm2022/c8y-ngx-components.mjs +292 -372
- package/fesm2022/c8y-ngx-components.mjs.map +1 -1
- package/interval-picker/c8y-ngx-components-interval-picker.d.ts.map +1 -0
- package/interval-picker/index.d.ts +3 -0
- package/interval-picker/index.d.ts.map +1 -0
- package/{core/dashboard/wiget-time-context/interval-picker → interval-picker}/interval-picker.component.d.ts +10 -2
- package/interval-picker/interval-picker.component.d.ts.map +1 -0
- package/interval-picker/interval-picker.model.d.ts +15 -0
- package/interval-picker/interval-picker.model.d.ts.map +1 -0
- package/locales/de.po +4 -1
- package/locales/en.po +3 -0
- package/locales/en_US.po +3 -0
- package/locales/es.po +3 -0
- package/locales/fr.po +3 -0
- package/locales/ja_JP.po +3 -0
- package/locales/locales.pot +47 -3
- package/locales/nl.po +3 -0
- package/locales/pl.po +3 -0
- package/locales/pt_BR.po +3 -0
- package/operations/bulk-operation-scheduler/operation-scheduler.component.d.ts.map +1 -1
- package/package.json +1 -1
- package/tenants/custom-properties/custom-properties.component.d.ts +26 -0
- package/tenants/custom-properties/custom-properties.component.d.ts.map +1 -0
- package/tenants/custom-properties/custom-properties.service.d.ts +26 -0
- package/tenants/custom-properties/custom-properties.service.d.ts.map +1 -0
- package/tenants/custom-properties/custom-property-field/custom-property-field.component.d.ts +10 -0
- package/tenants/custom-properties/custom-property-field/custom-property-field.component.d.ts.map +1 -0
- package/tenants/index.d.ts +1 -0
- package/tenants/index.d.ts.map +1 -1
- package/tenants/tenant-limits/tenant-limits-definitions.d.ts +117 -0
- package/tenants/tenant-limits/tenant-limits-definitions.d.ts.map +1 -0
- package/tenants/tenant-limits/tenant-limits.component.d.ts +39 -0
- package/tenants/tenant-limits/tenant-limits.component.d.ts.map +1 -0
- package/tenants/tenants.module.d.ts.map +1 -1
- package/core/dashboard/wiget-time-context/interval-picker/interval-picker.component.d.ts.map +0 -1
- package/esm2022/core/dashboard/wiget-time-context/interval-picker/interval-picker.component.mjs +0 -55
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, InjectionToken, Optional, Inject, Component, NgModule } from '@angular/core';
|
|
3
|
-
import * as
|
|
4
|
-
import { RouterModule } from '@angular/router';
|
|
2
|
+
import { Injectable, InjectionToken, Optional, Inject, Component, Input, NgModule } from '@angular/core';
|
|
3
|
+
import * as i3$1 from '@angular/router';
|
|
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, CoreModule, hookNavigator, hookRoute } from '@c8y/ngx-components';
|
|
8
|
+
import { NavigatorNode, gettext, Permissions, BuiltInActionType, Status, ValidationPattern, 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
11
|
import * as i3 from '@ngx-translate/core';
|
|
11
12
|
import { saveAs } from 'file-saver';
|
|
12
13
|
import { BehaviorSubject, from } from 'rxjs';
|
|
13
14
|
import { expand, takeWhile, reduce, shareReplay } from 'rxjs/operators';
|
|
14
|
-
import * as
|
|
15
|
+
import * as i1$1 from '@c8y/client';
|
|
15
16
|
import { TenantStatus } from '@c8y/client';
|
|
16
17
|
import * as i5 from '@angular/forms';
|
|
18
|
+
import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
19
|
+
import { gettext as gettext$1 } from '@c8y/ngx-components/gettext';
|
|
20
|
+
import { get } from 'lodash-es';
|
|
17
21
|
|
|
18
22
|
class TenantListGuard {
|
|
19
23
|
constructor(tenantUiService) {
|
|
@@ -431,13 +435,378 @@ class TenantListComponent {
|
|
|
431
435
|
const blob = new Blob([data], { type: contentType });
|
|
432
436
|
saveAs(blob, filename);
|
|
433
437
|
}
|
|
434
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TenantListComponent, deps: [{ token: i1.AppStateService }, { token: i1.AlertService }, { token: i1.ModalService }, { token: i3.TranslateService }, { token:
|
|
435
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", 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: "directive", type:
|
|
438
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", 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.9", 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: "directive", type: i3$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { 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: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.DatePipe, name: "c8yDate" }] }); }
|
|
436
440
|
}
|
|
437
441
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TenantListComponent, decorators: [{
|
|
438
442
|
type: Component,
|
|
439
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" }]
|
|
440
|
-
}], ctorParameters: () => [{ type: i1.AppStateService }, { type: i1.AlertService }, { type: i1.ModalService }, { type: i3.TranslateService }, { type:
|
|
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 }] });
|
|
445
|
+
|
|
446
|
+
const defaultFilters = { pageSize: 1000, type: 'c8y_JsonSchema', withTotalPages: true };
|
|
447
|
+
class CustomPropertiesService {
|
|
448
|
+
constructor(inventoryService) {
|
|
449
|
+
this.inventoryService = inventoryService;
|
|
450
|
+
}
|
|
451
|
+
async getFormAndFieldList() {
|
|
452
|
+
const schema = await this.getCustomProperties();
|
|
453
|
+
const formGroup = this.buildFormGroup(schema);
|
|
454
|
+
const fields = this.buildFieldList(formGroup, schema);
|
|
455
|
+
return { form: formGroup, fields };
|
|
456
|
+
}
|
|
457
|
+
async getCustomProperties() {
|
|
458
|
+
let customFieldsSchema = {};
|
|
459
|
+
const customProperties = await this.inventoryService.list(defaultFilters);
|
|
460
|
+
customProperties.data.forEach(item => {
|
|
461
|
+
const fieldSchema = item['c8y_JsonSchema'].properties;
|
|
462
|
+
customFieldsSchema = { ...customFieldsSchema, ...fieldSchema };
|
|
463
|
+
});
|
|
464
|
+
return customFieldsSchema;
|
|
465
|
+
}
|
|
466
|
+
buildFormGroup(schema) {
|
|
467
|
+
const fg = new FormGroup({});
|
|
468
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
469
|
+
const control = new FormControl(value.default, []);
|
|
470
|
+
this.applyValidators(control, value);
|
|
471
|
+
fg.addControl(key, control);
|
|
472
|
+
}
|
|
473
|
+
return fg;
|
|
474
|
+
}
|
|
475
|
+
applyValidators(control, props) {
|
|
476
|
+
const validatorsMap = {
|
|
477
|
+
required: Validators.required,
|
|
478
|
+
minimum: Validators.min(props.minimum),
|
|
479
|
+
maximum: Validators.max(props.maximum),
|
|
480
|
+
minLength: Validators.minLength(props.minLength),
|
|
481
|
+
maxLength: Validators.maxLength(props.maxLength),
|
|
482
|
+
pattern: Validators.pattern(props.pattern)
|
|
483
|
+
};
|
|
484
|
+
Object.entries(validatorsMap).forEach(([key, validator]) => {
|
|
485
|
+
if (props[key] !== undefined) {
|
|
486
|
+
control.addValidators(validator);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
if (props.type === 'integer') {
|
|
490
|
+
control.addValidators(Validators.pattern(ValidationPattern.rules.integer.pattern));
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
buildFieldList(form, schema) {
|
|
494
|
+
const fieldList = [];
|
|
495
|
+
Object.entries(schema).forEach(([key, value]) => {
|
|
496
|
+
fieldList.push({
|
|
497
|
+
id: key,
|
|
498
|
+
label: value.title,
|
|
499
|
+
type: value.type,
|
|
500
|
+
format: value.format,
|
|
501
|
+
formControlReference: form.get(key)
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
return fieldList;
|
|
505
|
+
}
|
|
506
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertiesService, deps: [{ token: i1$1.InventoryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
507
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertiesService, providedIn: 'root' }); }
|
|
508
|
+
}
|
|
509
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertiesService, decorators: [{
|
|
510
|
+
type: Injectable,
|
|
511
|
+
args: [{
|
|
512
|
+
providedIn: 'root'
|
|
513
|
+
}]
|
|
514
|
+
}], ctorParameters: () => [{ type: i1$1.InventoryService }] });
|
|
515
|
+
|
|
516
|
+
class CustomPropertyFieldComponent {
|
|
517
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertyFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
518
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", 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"] }] }); }
|
|
519
|
+
}
|
|
520
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertyFieldComponent, decorators: [{
|
|
521
|
+
type: Component,
|
|
522
|
+
args: [{ selector: 'c8y-custom-property-field', standalone: true, imports: [
|
|
523
|
+
CommonModule,
|
|
524
|
+
C8yTranslatePipe,
|
|
525
|
+
FormGroupComponent,
|
|
526
|
+
FormsModule,
|
|
527
|
+
ReactiveFormsModule,
|
|
528
|
+
DateTimePickerModule
|
|
529
|
+
], 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" }]
|
|
530
|
+
}], propDecorators: { fieldDefinition: [{
|
|
531
|
+
type: Input
|
|
532
|
+
}], form: [{
|
|
533
|
+
type: Input
|
|
534
|
+
}] } });
|
|
535
|
+
|
|
536
|
+
class CustomPropertiesComponent {
|
|
537
|
+
constructor(tenantService, alertService, activatedRoute, customPropertiesService) {
|
|
538
|
+
this.tenantService = tenantService;
|
|
539
|
+
this.alertService = alertService;
|
|
540
|
+
this.activatedRoute = activatedRoute;
|
|
541
|
+
this.customPropertiesService = customPropertiesService;
|
|
542
|
+
this.customPropsForm = new FormGroup({});
|
|
543
|
+
this.tenant = null;
|
|
544
|
+
this.initialized = false;
|
|
545
|
+
}
|
|
546
|
+
async ngOnInit() {
|
|
547
|
+
await this.loadTenantDetails();
|
|
548
|
+
const { form, fields } = await this.customPropertiesService.getFormAndFieldList();
|
|
549
|
+
this.customPropsForm = form;
|
|
550
|
+
this.fieldDefinitions = fields;
|
|
551
|
+
this.applyValuesFromTenant();
|
|
552
|
+
this.initialized = true;
|
|
553
|
+
}
|
|
554
|
+
async onSubmit() {
|
|
555
|
+
if (this.customPropsForm.invalid || !this.tenant) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const updatedTenant = {
|
|
559
|
+
...this.tenant,
|
|
560
|
+
customProperties: {
|
|
561
|
+
...this.tenant.customProperties,
|
|
562
|
+
...this.getDirtyValues()
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
try {
|
|
566
|
+
await this.tenantService.update(updatedTenant);
|
|
567
|
+
this.alertService.success(gettext('Custom properties values saved.'));
|
|
568
|
+
}
|
|
569
|
+
catch (error) {
|
|
570
|
+
this.alertService.addServerFailure(error);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
async loadTenantDetails() {
|
|
574
|
+
try {
|
|
575
|
+
const result = await this.tenantService.detail(this.activatedRoute.snapshot.parent.data.contextData.id);
|
|
576
|
+
this.tenant = result.data;
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
this.alertService.addServerFailure(error);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
applyValuesFromTenant() {
|
|
583
|
+
const customProps = this.tenant?.customProperties || {};
|
|
584
|
+
this.customPropsForm.patchValue(customProps);
|
|
585
|
+
}
|
|
586
|
+
getDirtyValues() {
|
|
587
|
+
const dirtyValues = {};
|
|
588
|
+
Object.keys(this.customPropsForm.controls).forEach(key => {
|
|
589
|
+
const control = this.customPropsForm.controls[key];
|
|
590
|
+
if (control && control.dirty && control.value !== null) {
|
|
591
|
+
dirtyValues[key] = control.value;
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
return dirtyValues;
|
|
595
|
+
}
|
|
596
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertiesComponent, deps: [{ token: i1$1.TenantService }, { token: i1.AlertService }, { token: i3$1.ActivatedRoute }, { token: CustomPropertiesService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
597
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", 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 }, { 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"] }] }); }
|
|
598
|
+
}
|
|
599
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: CustomPropertiesComponent, decorators: [{
|
|
600
|
+
type: Component,
|
|
601
|
+
args: [{ selector: 'c8y-custom-properties', standalone: true, imports: [
|
|
602
|
+
CommonModule,
|
|
603
|
+
ReactiveFormsModule,
|
|
604
|
+
FormsModule,
|
|
605
|
+
CoreModule,
|
|
606
|
+
RouterLink,
|
|
607
|
+
CustomPropertyFieldComponent
|
|
608
|
+
], 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" }]
|
|
609
|
+
}], ctorParameters: () => [{ type: i1$1.TenantService }, { type: i1.AlertService }, { type: i3$1.ActivatedRoute }, { type: CustomPropertiesService }] });
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Define all hardTyped custom properties, and their configuration in one place.
|
|
613
|
+
*
|
|
614
|
+
* This exported const utilizes typescript inferring,
|
|
615
|
+
* while still benefiting from hard typing, thanks to "satisfies" keyword
|
|
616
|
+
*/
|
|
617
|
+
const tenantLimitsCustomPropertiesDefinition = {
|
|
618
|
+
//TODO: External reference - going to be moved to the Properties tab.
|
|
619
|
+
externalReference: {
|
|
620
|
+
id: 'externalReference',
|
|
621
|
+
validators: [],
|
|
622
|
+
defaultValue: null,
|
|
623
|
+
type: 'text',
|
|
624
|
+
label: gettext$1('External reference'),
|
|
625
|
+
placeholder: gettext$1('e.g. REF12345`reference number`')
|
|
626
|
+
},
|
|
627
|
+
limitDevicesNumber: {
|
|
628
|
+
id: 'limit.devices.number',
|
|
629
|
+
validators: [Validators.min(0)],
|
|
630
|
+
defaultValue: null,
|
|
631
|
+
type: 'number',
|
|
632
|
+
label: gettext$1('Limit number of devices'),
|
|
633
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
634
|
+
placeholderArgs: { example: 1000 }
|
|
635
|
+
},
|
|
636
|
+
limitHttpRequests: {
|
|
637
|
+
id: 'limit.http.requests',
|
|
638
|
+
validators: [Validators.min(-1)],
|
|
639
|
+
defaultValue: null,
|
|
640
|
+
type: 'number',
|
|
641
|
+
label: gettext$1('Limit HTTP requests'),
|
|
642
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
643
|
+
placeholderArgs: { example: 10000 }
|
|
644
|
+
},
|
|
645
|
+
limitHttpQueue: {
|
|
646
|
+
id: 'limit.http.queue',
|
|
647
|
+
validators: [Validators.min(-1)],
|
|
648
|
+
defaultValue: null,
|
|
649
|
+
type: 'number',
|
|
650
|
+
label: gettext$1('Limit HTTP queue'),
|
|
651
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
652
|
+
placeholderArgs: { example: 100 }
|
|
653
|
+
},
|
|
654
|
+
limitStreamRequests: {
|
|
655
|
+
id: 'limit.stream.requests',
|
|
656
|
+
validators: [Validators.min(-1)],
|
|
657
|
+
defaultValue: null,
|
|
658
|
+
type: 'number',
|
|
659
|
+
label: gettext$1('Limit stream requests'),
|
|
660
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
661
|
+
placeholderArgs: { example: 100 }
|
|
662
|
+
},
|
|
663
|
+
limitStreamQueue: {
|
|
664
|
+
id: 'limit.stream.queue',
|
|
665
|
+
validators: [Validators.min(-1)],
|
|
666
|
+
defaultValue: null,
|
|
667
|
+
type: 'number',
|
|
668
|
+
label: gettext$1('Limit stream queue'),
|
|
669
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
670
|
+
placeholderArgs: { example: 100 }
|
|
671
|
+
},
|
|
672
|
+
cepServerQueueLimit: {
|
|
673
|
+
id: 'cepServer.queue.limit',
|
|
674
|
+
validators: [Validators.min(-1)],
|
|
675
|
+
defaultValue: null,
|
|
676
|
+
type: 'number',
|
|
677
|
+
label: gettext$1('Limit CEP server queue'),
|
|
678
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
679
|
+
placeholderArgs: { example: 100 }
|
|
680
|
+
},
|
|
681
|
+
dataBrokerQueueLimit: {
|
|
682
|
+
id: 'data-broker.queue.limit',
|
|
683
|
+
validators: [Validators.min(0)],
|
|
684
|
+
defaultValue: null,
|
|
685
|
+
type: 'number',
|
|
686
|
+
label: gettext$1('Limit data broker queue'),
|
|
687
|
+
placeholder: gettext$1('e.g. {{ example }}'),
|
|
688
|
+
placeholderArgs: { example: 100 }
|
|
689
|
+
},
|
|
690
|
+
// TODO: Gainsight checkbox - going to be moved to the Properties tab.
|
|
691
|
+
gainsightEnabled: {
|
|
692
|
+
id: 'gainsightEnabled',
|
|
693
|
+
validators: [],
|
|
694
|
+
defaultValue: false,
|
|
695
|
+
type: 'checkbox',
|
|
696
|
+
label: gettext$1('Enable Gainsight product experience tracking')
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
const tenantLimitsCustomProperties = tenantLimitsCustomPropertiesDefinition;
|
|
700
|
+
|
|
701
|
+
class TenantLimitsComponent {
|
|
702
|
+
constructor(tenantService, tenantOptionsService, alertService, activatedRoute, applicationService) {
|
|
703
|
+
this.tenantService = tenantService;
|
|
704
|
+
this.tenantOptionsService = tenantOptionsService;
|
|
705
|
+
this.alertService = alertService;
|
|
706
|
+
this.activatedRoute = activatedRoute;
|
|
707
|
+
this.applicationService = applicationService;
|
|
708
|
+
this.fieldDefinitions = { ...tenantLimitsCustomProperties };
|
|
709
|
+
this.limitsForm = new FormGroup({});
|
|
710
|
+
this.tenant = null;
|
|
711
|
+
this.initialized = false;
|
|
712
|
+
}
|
|
713
|
+
async ngOnInit() {
|
|
714
|
+
await this.loadTenantDetails();
|
|
715
|
+
await this.setupConditionalFields();
|
|
716
|
+
this.generateForm();
|
|
717
|
+
this.initialized = true;
|
|
718
|
+
}
|
|
719
|
+
async onSubmit() {
|
|
720
|
+
if (this.limitsForm.invalid || !this.tenant) {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
const updatedTenant = {
|
|
724
|
+
...this.tenant,
|
|
725
|
+
customProperties: {
|
|
726
|
+
...this.tenant.customProperties,
|
|
727
|
+
...this.getDirtyValues()
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
try {
|
|
731
|
+
await this.tenantService.update(updatedTenant);
|
|
732
|
+
this.alertService.success(gettext('Limit values saved.'));
|
|
733
|
+
}
|
|
734
|
+
catch (error) {
|
|
735
|
+
this.alertService.addServerFailure(error);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
async loadTenantDetails() {
|
|
739
|
+
try {
|
|
740
|
+
const result = await this.tenantService.detail(this.activatedRoute.snapshot.parent.data.contextData.id);
|
|
741
|
+
this.tenant = result.data;
|
|
742
|
+
}
|
|
743
|
+
catch (error) {
|
|
744
|
+
this.alertService.addServerFailure(error);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
async setupConditionalFields() {
|
|
748
|
+
try {
|
|
749
|
+
const apps = (await this.applicationService.listByUser(undefined, {
|
|
750
|
+
dropOverwrittenApps: true,
|
|
751
|
+
noPaging: true
|
|
752
|
+
})).data;
|
|
753
|
+
const cepModuleEnabled = apps.some(app => app.name === 'cep' || app.contextPath === 'cep');
|
|
754
|
+
const dataBrokerModuleEnabled = apps.some(app => app.name === 'feature-broker' || app.contextPath === 'feature-broker');
|
|
755
|
+
const gainsightAvailable = await this.isGainsightAvailable();
|
|
756
|
+
if (!cepModuleEnabled) {
|
|
757
|
+
delete this.fieldDefinitions.cepServerQueueLimit;
|
|
758
|
+
}
|
|
759
|
+
if (!dataBrokerModuleEnabled) {
|
|
760
|
+
delete this.fieldDefinitions.dataBrokerQueueLimit;
|
|
761
|
+
}
|
|
762
|
+
if (!gainsightAvailable) {
|
|
763
|
+
delete this.fieldDefinitions.gainsightEnabled;
|
|
764
|
+
}
|
|
765
|
+
this.fieldKeys = Object.keys(this.fieldDefinitions);
|
|
766
|
+
}
|
|
767
|
+
catch (ex) {
|
|
768
|
+
this.alertService.addServerFailure(ex);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
async isGainsightAvailable() {
|
|
772
|
+
if (get(window, 'C8Y_APP.gainsightKey')) {
|
|
773
|
+
return true;
|
|
774
|
+
}
|
|
775
|
+
try {
|
|
776
|
+
const res = await this.tenantOptionsService.detail({
|
|
777
|
+
category: 'configuration',
|
|
778
|
+
key: 'system.gainsight.api.key'
|
|
779
|
+
});
|
|
780
|
+
return !!res.data.value;
|
|
781
|
+
}
|
|
782
|
+
catch (error) {
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
generateForm() {
|
|
787
|
+
for (const field of Object.values(tenantLimitsCustomProperties)) {
|
|
788
|
+
this.limitsForm.addControl(field.id, new FormControl(field.defaultValue, field.validators));
|
|
789
|
+
}
|
|
790
|
+
const customProps = this.tenant?.customProperties || {};
|
|
791
|
+
this.limitsForm.patchValue(customProps);
|
|
792
|
+
}
|
|
793
|
+
getDirtyValues() {
|
|
794
|
+
const dirtyValues = {};
|
|
795
|
+
Object.keys(this.limitsForm.controls).forEach(key => {
|
|
796
|
+
const control = this.limitsForm.controls[key];
|
|
797
|
+
if (control && control.dirty) {
|
|
798
|
+
dirtyValues[key] = control.value;
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
return dirtyValues;
|
|
802
|
+
}
|
|
803
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TenantLimitsComponent, deps: [{ token: i1$1.TenantService }, { token: i1$1.TenantOptionsService }, { token: i1.AlertService }, { token: i3$1.ActivatedRoute }, { token: i1$1.ApplicationService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
804
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: TenantLimitsComponent, isStandalone: true, selector: "c8y-tenant-limits", ngImport: i0, 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", dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "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.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"] }] }); }
|
|
805
|
+
}
|
|
806
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TenantLimitsComponent, decorators: [{
|
|
807
|
+
type: Component,
|
|
808
|
+
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" }]
|
|
809
|
+
}], ctorParameters: () => [{ type: i1$1.TenantService }, { type: i1$1.TenantOptionsService }, { type: i1.AlertService }, { type: i3$1.ActivatedRoute }, { type: i1$1.ApplicationService }] });
|
|
441
810
|
|
|
442
811
|
class TenantsModule {
|
|
443
812
|
static config(config = {}) {
|
|
@@ -463,7 +832,25 @@ class TenantsModule {
|
|
|
463
832
|
icon: 'c8y-layers',
|
|
464
833
|
component: TenantListComponent,
|
|
465
834
|
canActivate: [TenantListGuard]
|
|
466
|
-
})
|
|
835
|
+
}),
|
|
836
|
+
hookRoute([
|
|
837
|
+
{
|
|
838
|
+
path: 'custom_properties',
|
|
839
|
+
component: CustomPropertiesComponent,
|
|
840
|
+
icon: 'property-script',
|
|
841
|
+
label: gettext('Custom properties'),
|
|
842
|
+
context: ViewContext.Tenant,
|
|
843
|
+
priority: 4
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
path: 'limits',
|
|
847
|
+
component: TenantLimitsComponent,
|
|
848
|
+
icon: 'sliders',
|
|
849
|
+
label: gettext('Limits'),
|
|
850
|
+
context: ViewContext.Tenant,
|
|
851
|
+
priority: 3
|
|
852
|
+
}
|
|
853
|
+
])
|
|
467
854
|
], imports: [RouterModule, BsDatepickerModule, CoreModule] }); }
|
|
468
855
|
}
|
|
469
856
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TenantsModule, decorators: [{
|
|
@@ -484,7 +871,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
|
|
|
484
871
|
icon: 'c8y-layers',
|
|
485
872
|
component: TenantListComponent,
|
|
486
873
|
canActivate: [TenantListGuard]
|
|
487
|
-
})
|
|
874
|
+
}),
|
|
875
|
+
hookRoute([
|
|
876
|
+
{
|
|
877
|
+
path: 'custom_properties',
|
|
878
|
+
component: CustomPropertiesComponent,
|
|
879
|
+
icon: 'property-script',
|
|
880
|
+
label: gettext('Custom properties'),
|
|
881
|
+
context: ViewContext.Tenant,
|
|
882
|
+
priority: 4
|
|
883
|
+
},
|
|
884
|
+
{
|
|
885
|
+
path: 'limits',
|
|
886
|
+
component: TenantLimitsComponent,
|
|
887
|
+
icon: 'sliders',
|
|
888
|
+
label: gettext('Limits'),
|
|
889
|
+
context: ViewContext.Tenant,
|
|
890
|
+
priority: 3
|
|
891
|
+
}
|
|
892
|
+
])
|
|
488
893
|
]
|
|
489
894
|
}]
|
|
490
895
|
}] });
|
|
@@ -493,5 +898,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
|
|
|
493
898
|
* Generated bundle index. Do not edit.
|
|
494
899
|
*/
|
|
495
900
|
|
|
496
|
-
export { CreationTimeFilteringFormRendererComponent, StatusFilteringFormRendererComponent, TENANTS_MODULE_CONFIG, TenantListComponent, TenantListGuard, TenantsModule, TenantsNavigationFactory };
|
|
901
|
+
export { CreationTimeFilteringFormRendererComponent, CustomPropertiesComponent, StatusFilteringFormRendererComponent, TENANTS_MODULE_CONFIG, TenantListComponent, TenantListGuard, TenantsModule, TenantsNavigationFactory };
|
|
497
902
|
//# sourceMappingURL=c8y-ngx-components-tenants.mjs.map
|