@c8y/ngx-components 1017.0.377 → 1017.0.382

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.
@@ -27,7 +27,7 @@ import * as i1$2 from '@c8y/client';
27
27
  import { TenantLoginOptionType, UserManagementSource, GrantType, ApplicationType, OperationStatus, InventoryService, UserService, ApplicationService, TenantService, FetchClient, Client, PasswordStrength, QueriesUtil, ApplicationAvailability, Service } from '@c8y/client';
28
28
  import { satisfies, compare, coerce } from 'semver';
29
29
  import * as i6 from 'ngx-bootstrap/datepicker';
30
- import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
30
+ import { BsDatepickerModule, BsDatepickerDirective } from 'ngx-bootstrap/datepicker';
31
31
  import { defineLocale, enGbLocale, zhCnLocale, ruLocale, ptBrLocale, plLocale, nlLocale, koLocale, jaLocale, frLocale, esLocale, deLocale } from 'ngx-bootstrap/chronos';
32
32
  import { saveAs } from 'file-saver';
33
33
  import { coerceNumberProperty } from '@angular/cdk/coercion';
@@ -10927,160 +10927,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
10927
10927
  args: [{ selector: 'c8y-app-switcher', template: "<div\n class=\"app-switcher-dropdown\"\n dropdown\n #appSwitcherDropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"appSwitcherDropdown.isOpen\"\n>\n <button\n class=\"main-header-button c8y-dropdown dropdown-toggle\"\n id=\"appSwitcherDropdown\"\n dropdownToggle\n title=\"{{ 'Application switcher' | translate }}\"\n type=\"button\"\n >\n <i c8yIcon=\"th\" class=\"icon-2x\"></i>\n </button>\n <div\n *dropdownMenu\n class=\"app-switcher-dropdown-menu dropdown-menu\"\n aria-labelledby=\"appSwitcherDropdown\"\n role=\"group\"\n >\n <div\n *ngIf=\"!(switcherService.finishedLoading$ | async)\"\n class=\"d-flex a-i-center j-c-center p-4\"\n >\n <c8y-loading></c8y-loading>\n </div>\n <ng-container *ngIf=\"switcherService.oneCloudApps$ | async as oneCloudApps\">\n <div class=\"app-switcher-sagcloud\" *ngIf=\"oneCloudApps.length > 0\">\n <a\n title=\"{{ app.name | humanizeAppName | async }}\"\n class=\"appLink\"\n *ngFor=\"let app of oneCloudApps\"\n [href]=\"app | appHref\"\n c8yProductExperience\n [actionName]=\"'appSwitched'\"\n [actionData]=\"{ applicationName: app && app.name }\"\n >\n <c8y-app-icon\n [app]=\"app\"\n [name]=\"app.name\"\n [contextPath]=\"app.contextPath\"\n ></c8y-app-icon>\n <span class=\"text-truncate-wrap\">{{ app | humanizeAppName | async }}</span>\n </a>\n </div>\n </ng-container>\n <div class=\"app-switcher\" *ngIf=\"switcherService.apps$ | async as apps\">\n <a\n title=\"{{ app.name | humanizeAppName | async }}\"\n class=\"appLink\"\n [ngClass]=\"(app | isActiveApp | async) ? 'active' : ''\"\n *ngFor=\"let app of apps\"\n [href]=\"app | appHref\"\n [rel]=\"app.type === 'EXTERNAL' ? 'noopener noreferrer' : ''\"\n c8yProductExperience\n [actionName]=\"'appSwitched'\"\n [actionData]=\"{ applicationName: app && app.name }\"\n >\n <c8y-app-icon [app]=\"app\" [name]=\"app.name\" [contextPath]=\"app.contextPath\"></c8y-app-icon>\n <span class=\"text-truncate-wrap\">{{ app | humanizeAppName | async }}</span>\n </a>\n </div>\n </div>\n</div>\n" }]
10928
10928
  }], ctorParameters: function () { return [{ type: AppSwitcherService }]; } });
10929
10929
 
10930
- class ConfirmModalComponent {
10931
- constructor(modal) {
10932
- this.modal = modal;
10933
- this.status = Status.INFO;
10934
- this._labels = {
10935
- ok: 'OK',
10936
- cancel: 'Cancel'
10937
- };
10938
- this.result = new Promise((resolve, reject) => {
10939
- this.dismiss = () => {
10940
- reject();
10941
- this.modal.hide();
10942
- };
10943
- this.close = () => {
10944
- resolve(isEmpty(this.confirmOptions)
10945
- ? true
10946
- : {
10947
- confirmed: true,
10948
- confirmOptions: mapValues(this.confirmOptions, option => option.checked)
10949
- });
10950
- this.modal.hide();
10951
- };
10952
- });
10953
- }
10954
- set labels(labels) {
10955
- const { ok = 'OK', cancel = 'Cancel' } = labels || {};
10956
- this._labels = { ok, cancel };
10957
- }
10958
- get labels() {
10959
- return this._labels;
10960
- }
10961
- get classIcon() {
10962
- return `dlt-c8y-icon-${statusIcons[this.status]}`;
10963
- }
10964
- get classAlert() {
10965
- return statusAlert[this.status];
10966
- }
10967
- ngOnDestroy() {
10968
- this.dismiss();
10969
- }
10970
- }
10971
- ConfirmModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ConfirmModalComponent, deps: [{ token: i1$8.BsModalRef }], target: i0.ɵɵFactoryTarget.Component });
10972
- ConfirmModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: { title: "title", body: "body", confirmOptions: "confirmOptions", status: "status", labels: "labels" }, ngImport: i0, template: "<div class=\"c8y-prompt alert\" [ngClass]=\"[classAlert]\" data-cy=\"prompt-alert\">\n <h3 class=\"m-b-16 d-flex a-i-center\" *ngIf=\"title\">\n <i class=\"dlt-c8y-icon\" [ngClass]=\"[classIcon]\"></i>\n <span *ngIf=\"title\">{{ title | translate }}</span>\n </h3>\n <p class=\"text-break-word m-b-16\">{{ body | translate }}</p>\n <div\n class=\"c8y-checkbox plain m-b-8\"\n *ngFor=\"let co of confirmOptions | showIfFilter | async | keyvalue\"\n >\n <label [title]=\"co.value.text | translate\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span class=\"text-muted\">{{ co.value.text | translate }}</span>\n </label>\n </div>\n <ng-content></ng-content>\n <div class=\"alert-footer\">\n <button\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n *ngIf=\"labels.cancel !== null\"\n (click)=\"dismiss()\"\n >\n {{ labels.cancel | translate }}\n </button>\n <button\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"close()\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: ShowIfFilterPipe, name: "showIfFilter" }] });
10973
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ConfirmModalComponent, decorators: [{
10974
- type: Component,
10975
- args: [{ selector: 'c8y-confirm-modal', template: "<div class=\"c8y-prompt alert\" [ngClass]=\"[classAlert]\" data-cy=\"prompt-alert\">\n <h3 class=\"m-b-16 d-flex a-i-center\" *ngIf=\"title\">\n <i class=\"dlt-c8y-icon\" [ngClass]=\"[classIcon]\"></i>\n <span *ngIf=\"title\">{{ title | translate }}</span>\n </h3>\n <p class=\"text-break-word m-b-16\">{{ body | translate }}</p>\n <div\n class=\"c8y-checkbox plain m-b-8\"\n *ngFor=\"let co of confirmOptions | showIfFilter | async | keyvalue\"\n >\n <label [title]=\"co.value.text | translate\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span class=\"text-muted\">{{ co.value.text | translate }}</span>\n </label>\n </div>\n <ng-content></ng-content>\n <div class=\"alert-footer\">\n <button\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n *ngIf=\"labels.cancel !== null\"\n (click)=\"dismiss()\"\n >\n {{ labels.cancel | translate }}\n </button>\n <button\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"close()\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n" }]
10976
- }], ctorParameters: function () { return [{ type: i1$8.BsModalRef }]; }, propDecorators: { title: [{
10977
- type: Input
10978
- }], body: [{
10979
- type: Input
10980
- }], confirmOptions: [{
10981
- type: Input
10982
- }], status: [{
10983
- type: Input
10984
- }], labels: [{
10985
- type: Input
10986
- }] } });
10987
-
10988
- /**
10989
- * Service to show a modal.
10990
- */
10991
- class ModalService {
10992
- constructor(modalService, gainsightService) {
10993
- this.modalService = modalService;
10994
- this.gainsightService = gainsightService;
10995
- }
10996
- /**
10997
- * Shows a quick confirm message modal.
10998
- * @param title The title of that modal.
10999
- * @param body The text body to display.
11000
- * @param status The status.
11001
- * @param labels The labels to use. Default: { ok: 'Confirm', cancel: 'Cancel'}
11002
- * @param confirmOptions Selection options to display as checkbox list.
11003
- * @param productExperienceEvent Additional data to attach to custom product experience events.
11004
- */
11005
- async confirm(title, body, status = Status.INFO, labels = {}, confirmOptions = {}, productExperienceEvent = { eventName: 'confirmModal' }) {
11006
- const modalLabels = {
11007
- ok: labels.ok || gettext('Confirm'),
11008
- cancel: labels.cancel || gettext('Cancel')
11009
- };
11010
- const modalRef = this.modalService.show(ConfirmModalComponent, {
11011
- initialState: { title, body, labels: modalLabels, status, confirmOptions },
11012
- ariaDescribedby: 'modal-body',
11013
- ariaLabelledBy: 'modal-title',
11014
- ignoreBackdropClick: true
11015
- });
11016
- if (productExperienceEvent) {
11017
- productExperienceEvent.data = { ...productExperienceEvent.data, title };
11018
- }
11019
- this.triggerEvent(modalRef.content.result, modalLabels, productExperienceEvent);
11020
- return await modalRef.content.result;
11021
- }
11022
- /**
11023
- * Shows a quick acknowledge message modal.
11024
- * @param title The title of that modal.
11025
- * @param body The text body to display.
11026
- * @param status The status.
11027
- * @param acknowledgeLabel The label to use.
11028
- * @param productExperienceEvent Additional data to attach to custom product experience events.
11029
- */
11030
- async acknowledge(title, body, status = Status.INFO, acknowledgeLabel = gettext('Confirm'), productExperienceEvent = { eventName: 'confirmModal' }) {
11031
- const labels = { ok: acknowledgeLabel, cancel: null };
11032
- const modalRef = this.modalService.show(ConfirmModalComponent, {
11033
- initialState: { title, body, labels, status },
11034
- ariaDescribedby: 'modal-body',
11035
- ariaLabelledBy: 'modal-title',
11036
- ignoreBackdropClick: true
11037
- });
11038
- if (productExperienceEvent) {
11039
- productExperienceEvent.data = { ...productExperienceEvent.data, title };
11040
- }
11041
- this.triggerEvent(modalRef.content.result, labels, productExperienceEvent);
11042
- return await modalRef.content.result;
11043
- }
11044
- /**
11045
- * Shows a quick logout confirmation modal.
11046
- * @param body The text body to display. Default: 'You will be logged out to apply your changes. Do you want to proceed?'
11047
- * @param status The status.
11048
- * @param labels The labels to use. Default: { ok: 'Confirm and log out', cancel: 'Cancel' }
11049
- */
11050
- async confirmLogout(body, status = Status.WARNING, labels = {}) {
11051
- const modalLabels = {
11052
- ok: labels.ok || gettext('Confirm and log out'),
11053
- cancel: labels.cancel || gettext('Cancel')
11054
- };
11055
- const modalBody = body || gettext('You must log out to apply your changes. Do you want to proceed?');
11056
- return await this.confirm(gettext('Logout required'), modalBody, status, modalLabels);
11057
- }
11058
- triggerEvent(result, labels, productExperienceEvent) {
11059
- const data = { ...productExperienceEvent.data, url: window.location.href };
11060
- result
11061
- .then(() => {
11062
- this.gainsightService.triggerEvent(productExperienceEvent.eventName, {
11063
- ...data,
11064
- result: labels.ok
11065
- });
11066
- })
11067
- .catch(() => {
11068
- this.gainsightService.triggerEvent(productExperienceEvent.eventName, {
11069
- ...data,
11070
- result: labels.cancel
11071
- });
11072
- });
11073
- }
11074
- }
11075
- ModalService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ModalService, deps: [{ token: i1$8.BsModalService }, { token: GainsightService }], target: i0.ɵɵFactoryTarget.Injectable });
11076
- ModalService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ModalService, providedIn: 'root' });
11077
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ModalService, decorators: [{
11078
- type: Injectable,
11079
- args: [{
11080
- providedIn: 'root'
11081
- }]
11082
- }], ctorParameters: function () { return [{ type: i1$8.BsModalService }, { type: GainsightService }]; } });
11083
-
11084
10930
  /**
11085
10931
  * Service to manage the login.
11086
10932
  */
@@ -11313,7 +11159,6 @@ class LoginService {
11313
11159
  if (credentials) {
11314
11160
  credentials.tenant = tenant.name;
11315
11161
  }
11316
- await this.shouldRedirectDomain(credentials);
11317
11162
  if (await this.switchLoginMode(credentials)) {
11318
11163
  auth = this.cookieAuth;
11319
11164
  }
@@ -11618,20 +11463,6 @@ class LoginService {
11618
11463
  const managementLoginOptions = (await this.tenantLoginOptionsService.listForManagement()).data;
11619
11464
  return this.tenantUiService.getPreferredLoginOption(managementLoginOptions);
11620
11465
  }
11621
- async shouldRedirectDomain(credentials) {
11622
- const isPasswordGrantLogin = await this.isPasswordGrantLogin(credentials);
11623
- if (this.isSupportUser(credentials) &&
11624
- isPasswordGrantLogin &&
11625
- this.managementLoginMode.loginRedirectDomain !== window.location.hostname &&
11626
- !this.isLocal()) {
11627
- const title = gettext('Redirect required');
11628
- const body = gettext('Redirect to correct domain is required to log in as support user.');
11629
- // avoids circular dependency NG0200 error when BsModalService is injected into APP_INITIALIZER (via LoginService -> ModalService -> BsModalService)
11630
- const modalService = this.injector.get(ModalService);
11631
- await modalService.acknowledge(title, body, Status.INFO, gettext('Redirect'));
11632
- this.redirectToDomain(this.managementLoginMode.loginRedirectDomain);
11633
- }
11634
- }
11635
11466
  }
11636
11467
  LoginService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: LoginService, deps: [{ token: i0.Injector }, { token: i1$2.FetchClient }, { token: i1$2.BasicAuth }, { token: i1$2.CookieAuth }, { token: AppStateService }, { token: i1$2.UserService }, { token: i1$2.TenantService }, { token: i1$2.Realtime }, { token: AlertService }, { token: i1$1.ApiService }, { token: TenantUiService }, { token: i1$2.TenantLoginOptionsService }, { token: i1$3.TranslateService }, { token: i2.LocationStrategy, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
11637
11468
  LoginService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: LoginService });
@@ -11641,6 +11472,160 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
11641
11472
  type: Optional
11642
11473
  }] }]; } });
11643
11474
 
11475
+ class ConfirmModalComponent {
11476
+ constructor(modal) {
11477
+ this.modal = modal;
11478
+ this.status = Status.INFO;
11479
+ this._labels = {
11480
+ ok: 'OK',
11481
+ cancel: 'Cancel'
11482
+ };
11483
+ this.result = new Promise((resolve, reject) => {
11484
+ this.dismiss = () => {
11485
+ reject();
11486
+ this.modal.hide();
11487
+ };
11488
+ this.close = () => {
11489
+ resolve(isEmpty(this.confirmOptions)
11490
+ ? true
11491
+ : {
11492
+ confirmed: true,
11493
+ confirmOptions: mapValues(this.confirmOptions, option => option.checked)
11494
+ });
11495
+ this.modal.hide();
11496
+ };
11497
+ });
11498
+ }
11499
+ set labels(labels) {
11500
+ const { ok = 'OK', cancel = 'Cancel' } = labels || {};
11501
+ this._labels = { ok, cancel };
11502
+ }
11503
+ get labels() {
11504
+ return this._labels;
11505
+ }
11506
+ get classIcon() {
11507
+ return `dlt-c8y-icon-${statusIcons[this.status]}`;
11508
+ }
11509
+ get classAlert() {
11510
+ return statusAlert[this.status];
11511
+ }
11512
+ ngOnDestroy() {
11513
+ this.dismiss();
11514
+ }
11515
+ }
11516
+ ConfirmModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ConfirmModalComponent, deps: [{ token: i1$8.BsModalRef }], target: i0.ɵɵFactoryTarget.Component });
11517
+ ConfirmModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: ConfirmModalComponent, selector: "c8y-confirm-modal", inputs: { title: "title", body: "body", confirmOptions: "confirmOptions", status: "status", labels: "labels" }, ngImport: i0, template: "<div class=\"c8y-prompt alert\" [ngClass]=\"[classAlert]\" data-cy=\"prompt-alert\">\n <h3 class=\"m-b-16 d-flex a-i-center\" *ngIf=\"title\">\n <i class=\"dlt-c8y-icon\" [ngClass]=\"[classIcon]\"></i>\n <span *ngIf=\"title\">{{ title | translate }}</span>\n </h3>\n <p class=\"text-break-word m-b-16\">{{ body | translate }}</p>\n <div\n class=\"c8y-checkbox plain m-b-8\"\n *ngFor=\"let co of confirmOptions | showIfFilter | async | keyvalue\"\n >\n <label [title]=\"co.value.text | translate\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span class=\"text-muted\">{{ co.value.text | translate }}</span>\n </label>\n </div>\n <ng-content></ng-content>\n <div class=\"alert-footer\">\n <button\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n *ngIf=\"labels.cancel !== null\"\n (click)=\"dismiss()\"\n >\n {{ labels.cancel | translate }}\n </button>\n <button\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"close()\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: ShowIfFilterPipe, name: "showIfFilter" }] });
11518
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ConfirmModalComponent, decorators: [{
11519
+ type: Component,
11520
+ args: [{ selector: 'c8y-confirm-modal', template: "<div class=\"c8y-prompt alert\" [ngClass]=\"[classAlert]\" data-cy=\"prompt-alert\">\n <h3 class=\"m-b-16 d-flex a-i-center\" *ngIf=\"title\">\n <i class=\"dlt-c8y-icon\" [ngClass]=\"[classIcon]\"></i>\n <span *ngIf=\"title\">{{ title | translate }}</span>\n </h3>\n <p class=\"text-break-word m-b-16\">{{ body | translate }}</p>\n <div\n class=\"c8y-checkbox plain m-b-8\"\n *ngFor=\"let co of confirmOptions | showIfFilter | async | keyvalue\"\n >\n <label [title]=\"co.value.text | translate\" class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"co.value.checked\"\n (change)=\"co.value.checked = !co.value.checked\"\n [disabled]=\"confirmOptions[co.value.disabledByKey]?.checked\"\n />\n <span></span>\n <span class=\"text-muted\">{{ co.value.text | translate }}</span>\n </label>\n </div>\n <ng-content></ng-content>\n <div class=\"alert-footer\">\n <button\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n class=\"btn btn-default\"\n *ngIf=\"labels.cancel !== null\"\n (click)=\"dismiss()\"\n >\n {{ labels.cancel | translate }}\n </button>\n <button\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"close()\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n" }]
11521
+ }], ctorParameters: function () { return [{ type: i1$8.BsModalRef }]; }, propDecorators: { title: [{
11522
+ type: Input
11523
+ }], body: [{
11524
+ type: Input
11525
+ }], confirmOptions: [{
11526
+ type: Input
11527
+ }], status: [{
11528
+ type: Input
11529
+ }], labels: [{
11530
+ type: Input
11531
+ }] } });
11532
+
11533
+ /**
11534
+ * Service to show a modal.
11535
+ */
11536
+ class ModalService {
11537
+ constructor(modalService, gainsightService) {
11538
+ this.modalService = modalService;
11539
+ this.gainsightService = gainsightService;
11540
+ }
11541
+ /**
11542
+ * Shows a quick confirm message modal.
11543
+ * @param title The title of that modal.
11544
+ * @param body The text body to display.
11545
+ * @param status The status.
11546
+ * @param labels The labels to use. Default: { ok: 'Confirm', cancel: 'Cancel'}
11547
+ * @param confirmOptions Selection options to display as checkbox list.
11548
+ * @param productExperienceEvent Additional data to attach to custom product experience events.
11549
+ */
11550
+ async confirm(title, body, status = Status.INFO, labels = {}, confirmOptions = {}, productExperienceEvent = { eventName: 'confirmModal' }) {
11551
+ const modalLabels = {
11552
+ ok: labels.ok || gettext('Confirm'),
11553
+ cancel: labels.cancel || gettext('Cancel')
11554
+ };
11555
+ const modalRef = this.modalService.show(ConfirmModalComponent, {
11556
+ initialState: { title, body, labels: modalLabels, status, confirmOptions },
11557
+ ariaDescribedby: 'modal-body',
11558
+ ariaLabelledBy: 'modal-title',
11559
+ ignoreBackdropClick: true
11560
+ });
11561
+ if (productExperienceEvent) {
11562
+ productExperienceEvent.data = { ...productExperienceEvent.data, title };
11563
+ }
11564
+ this.triggerEvent(modalRef.content.result, modalLabels, productExperienceEvent);
11565
+ return await modalRef.content.result;
11566
+ }
11567
+ /**
11568
+ * Shows a quick acknowledge message modal.
11569
+ * @param title The title of that modal.
11570
+ * @param body The text body to display.
11571
+ * @param status The status.
11572
+ * @param acknowledgeLabel The label to use.
11573
+ * @param productExperienceEvent Additional data to attach to custom product experience events.
11574
+ */
11575
+ async acknowledge(title, body, status = Status.INFO, acknowledgeLabel = gettext('Confirm'), productExperienceEvent = { eventName: 'confirmModal' }) {
11576
+ const labels = { ok: acknowledgeLabel, cancel: null };
11577
+ const modalRef = this.modalService.show(ConfirmModalComponent, {
11578
+ initialState: { title, body, labels, status },
11579
+ ariaDescribedby: 'modal-body',
11580
+ ariaLabelledBy: 'modal-title',
11581
+ ignoreBackdropClick: true
11582
+ });
11583
+ if (productExperienceEvent) {
11584
+ productExperienceEvent.data = { ...productExperienceEvent.data, title };
11585
+ }
11586
+ this.triggerEvent(modalRef.content.result, labels, productExperienceEvent);
11587
+ return await modalRef.content.result;
11588
+ }
11589
+ /**
11590
+ * Shows a quick logout confirmation modal.
11591
+ * @param body The text body to display. Default: 'You will be logged out to apply your changes. Do you want to proceed?'
11592
+ * @param status The status.
11593
+ * @param labels The labels to use. Default: { ok: 'Confirm and log out', cancel: 'Cancel' }
11594
+ */
11595
+ async confirmLogout(body, status = Status.WARNING, labels = {}) {
11596
+ const modalLabels = {
11597
+ ok: labels.ok || gettext('Confirm and log out'),
11598
+ cancel: labels.cancel || gettext('Cancel')
11599
+ };
11600
+ const modalBody = body || gettext('You must log out to apply your changes. Do you want to proceed?');
11601
+ return await this.confirm(gettext('Logout required'), modalBody, status, modalLabels);
11602
+ }
11603
+ triggerEvent(result, labels, productExperienceEvent) {
11604
+ const data = { ...productExperienceEvent.data, url: window.location.href };
11605
+ result
11606
+ .then(() => {
11607
+ this.gainsightService.triggerEvent(productExperienceEvent.eventName, {
11608
+ ...data,
11609
+ result: labels.ok
11610
+ });
11611
+ })
11612
+ .catch(() => {
11613
+ this.gainsightService.triggerEvent(productExperienceEvent.eventName, {
11614
+ ...data,
11615
+ result: labels.cancel
11616
+ });
11617
+ });
11618
+ }
11619
+ }
11620
+ ModalService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ModalService, deps: [{ token: i1$8.BsModalService }, { token: GainsightService }], target: i0.ɵɵFactoryTarget.Injectable });
11621
+ ModalService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ModalService, providedIn: 'root' });
11622
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: ModalService, decorators: [{
11623
+ type: Injectable,
11624
+ args: [{
11625
+ providedIn: 'root'
11626
+ }]
11627
+ }], ctorParameters: function () { return [{ type: i1$8.BsModalService }, { type: GainsightService }]; } });
11628
+
11644
11629
  /**
11645
11630
  * C8y modal component.
11646
11631
  * ## Example:
@@ -20958,8 +20943,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
20958
20943
  type: Output
20959
20944
  }] } });
20960
20945
 
20946
+ class CloseDatePickerDirective {
20947
+ constructor(el) {
20948
+ this.el = el;
20949
+ this.destroy$ = new Subject();
20950
+ }
20951
+ ngOnInit() {
20952
+ const element = this.el.nativeElement.closest('.dropdown-menu');
20953
+ const clickEvent$ = element
20954
+ ? merge(fromEvent(element, 'click'), fromEvent(document, 'click'))
20955
+ : fromEvent(document, 'click');
20956
+ clickEvent$
20957
+ .pipe(map((event) => event.target), filter(target => !this.el.nativeElement.contains(target)), // i.e. anything which is not inside this `c8y-date-time-picker`
20958
+ takeUntil(this.destroy$))
20959
+ .subscribe(() => this.closeDatepicker.hide());
20960
+ }
20961
+ ngOnDestroy() {
20962
+ this.destroy$.next();
20963
+ this.destroy$.complete();
20964
+ }
20965
+ }
20966
+ CloseDatePickerDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: CloseDatePickerDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
20967
+ CloseDatePickerDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.6", type: CloseDatePickerDirective, selector: "[closeDatepicker]", inputs: { closeDatepicker: "closeDatepicker" }, ngImport: i0 });
20968
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: CloseDatePickerDirective, decorators: [{
20969
+ type: Directive,
20970
+ args: [{
20971
+ selector: '[closeDatepicker]'
20972
+ }]
20973
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { closeDatepicker: [{
20974
+ type: Input
20975
+ }] } });
20976
+
20961
20977
  class DateTimePickerComponent {
20962
- constructor() {
20978
+ constructor(cd) {
20979
+ this.cd = cd;
20963
20980
  this.defaultPlaceholder = gettext('Select a date…');
20964
20981
  this.destroy$ = new Subject();
20965
20982
  this.form = new FormGroup({});
@@ -20986,6 +21003,9 @@ class DateTimePickerComponent {
20986
21003
  this.destroy$.next();
20987
21004
  this.destroy$.complete();
20988
21005
  }
21006
+ ngAfterViewInit() {
21007
+ this.cd.detectChanges();
21008
+ }
20989
21009
  /**
20990
21010
  * Control Value Accessor - If form value changes by external factor, update date property and internal form with new value.
20991
21011
  */
@@ -21029,12 +21049,23 @@ class DateTimePickerComponent {
21029
21049
  }
21030
21050
  }
21031
21051
  previousDay() {
21052
+ const isOpen = this.datepicker.isOpen;
21032
21053
  this.date.setDate(this.date.getDate() - 1);
21033
21054
  this.setDatetime({ date: this.date, time: this.form.get('time').value });
21055
+ if (isOpen) {
21056
+ this.datepicker.show();
21057
+ }
21034
21058
  }
21035
21059
  nextDay() {
21060
+ const isOpen = this.datepicker.isOpen;
21036
21061
  this.date.setDate(this.date.getDate() + 1);
21037
21062
  this.setDatetime({ date: this.date, time: this.form.get('time').value });
21063
+ if (isOpen) {
21064
+ this.datepicker.show();
21065
+ }
21066
+ }
21067
+ hide() {
21068
+ this.datepicker.hide();
21038
21069
  }
21039
21070
  /**
21040
21071
  * If internal form changes its value, then combine date and time into one Date and pass its ISO string value to onChange method
@@ -21062,7 +21093,7 @@ class DateTimePickerComponent {
21062
21093
  this.onChange(this.date.toISOString());
21063
21094
  }
21064
21095
  }
21065
- DateTimePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DateTimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21096
+ DateTimePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DateTimePickerComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
21066
21097
  DateTimePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: DateTimePickerComponent, selector: "c8y-date-time-picker", inputs: { _minDate: ["minDate", "_minDate"], _maxDate: ["maxDate", "_maxDate"], placeholder: "placeholder" }, providers: [
21067
21098
  {
21068
21099
  provide: NG_VALUE_ACCESSOR,
@@ -21074,7 +21105,7 @@ DateTimePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0"
21074
21105
  useExisting: forwardRef(() => DateTimePickerComponent),
21075
21106
  multi: true
21076
21107
  }
21077
- ], ngImport: i0, template: "<div class=\"datetime-picker\">\n <div class=\"form-group datepicker\">\n <input\n class=\"form-control\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [bsConfig]=\"{ customTodayClass: 'today', dateInputFormat: 'YYYY-MM-DD' }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n <c8y-time-picker\n [formControl]=\"form.get('time')\"\n (dayBackward)=\"previousDay()\"\n (dayForward)=\"nextDay()\"\n ></c8y-time-picker>\n</div>\n", dependencies: [{ 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.BsDatepickerDirective, selector: "[bsDatepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isDisabled", "minDate", "maxDate", "minMode", "daysDisabled", "datesDisabled", "datesEnabled", "dateCustomClasses", "dateTooltipTexts", "isOpen", "bsValue", "bsConfig"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDatepicker"] }, { kind: "directive", type: i6.BsDatepickerInputDirective, selector: "input[bsDatepicker]" }, { kind: "component", type: TimePickerComponent, selector: "c8y-time-picker", inputs: ["minDate", "maxDate", "placeholder"], outputs: ["dayForward", "dayBackward"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] });
21108
+ ], viewQueries: [{ propertyName: "datepicker", first: true, predicate: BsDatepickerDirective, descendants: true }], ngImport: i0, template: "<div class=\"datetime-picker\" [closeDatepicker]=\"datepicker\">\n <div class=\"form-group datepicker\">\n <input\n class=\"form-control\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [outsideClick]=\"false\"\n [bsConfig]=\"{ customTodayClass: 'today', dateInputFormat: 'YYYY-MM-DD' }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n <c8y-time-picker\n [formControl]=\"form.get('time')\"\n (dayBackward)=\"previousDay()\"\n (dayForward)=\"nextDay()\"\n ></c8y-time-picker>\n</div>\n", dependencies: [{ 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.BsDatepickerDirective, selector: "[bsDatepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isDisabled", "minDate", "maxDate", "minMode", "daysDisabled", "datesDisabled", "datesEnabled", "dateCustomClasses", "dateTooltipTexts", "isOpen", "bsValue", "bsConfig"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDatepicker"] }, { kind: "directive", type: i6.BsDatepickerInputDirective, selector: "input[bsDatepicker]" }, { kind: "component", type: TimePickerComponent, selector: "c8y-time-picker", inputs: ["minDate", "maxDate", "placeholder"], outputs: ["dayForward", "dayBackward"] }, { kind: "directive", type: CloseDatePickerDirective, selector: "[closeDatepicker]", inputs: ["closeDatepicker"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] });
21078
21109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DateTimePickerComponent, decorators: [{
21079
21110
  type: Component,
21080
21111
  args: [{ selector: 'c8y-date-time-picker', providers: [
@@ -21088,8 +21119,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
21088
21119
  useExisting: forwardRef(() => DateTimePickerComponent),
21089
21120
  multi: true
21090
21121
  }
21091
- ], template: "<div class=\"datetime-picker\">\n <div class=\"form-group datepicker\">\n <input\n class=\"form-control\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [bsConfig]=\"{ customTodayClass: 'today', dateInputFormat: 'YYYY-MM-DD' }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n <c8y-time-picker\n [formControl]=\"form.get('time')\"\n (dayBackward)=\"previousDay()\"\n (dayForward)=\"nextDay()\"\n ></c8y-time-picker>\n</div>\n" }]
21092
- }], ctorParameters: function () { return []; }, propDecorators: { _minDate: [{
21122
+ ], template: "<div class=\"datetime-picker\" [closeDatepicker]=\"datepicker\">\n <div class=\"form-group datepicker\">\n <input\n class=\"form-control\"\n [placeholder]=\"placeholder || defaultPlaceholder | translate\"\n bsDatepicker\n [outsideClick]=\"false\"\n [bsConfig]=\"{ customTodayClass: 'today', dateInputFormat: 'YYYY-MM-DD' }\"\n [formControl]=\"form.get('date')\"\n (blur)=\"onTouched()\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n />\n </div>\n <c8y-time-picker\n [formControl]=\"form.get('time')\"\n (dayBackward)=\"previousDay()\"\n (dayForward)=\"nextDay()\"\n ></c8y-time-picker>\n</div>\n" }]
21123
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { _minDate: [{
21093
21124
  type: Input,
21094
21125
  args: ['minDate']
21095
21126
  }], _maxDate: [{
@@ -21097,6 +21128,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
21097
21128
  args: ['maxDate']
21098
21129
  }], placeholder: [{
21099
21130
  type: Input
21131
+ }], datepicker: [{
21132
+ type: ViewChild,
21133
+ args: [BsDatepickerDirective]
21100
21134
  }] } });
21101
21135
 
21102
21136
  class FieldDateTime extends FieldType {
@@ -21156,7 +21190,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
21156
21190
  class DateTimePickerModule {
21157
21191
  }
21158
21192
  DateTimePickerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DateTimePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
21159
- DateTimePickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.6", ngImport: i0, type: DateTimePickerModule, declarations: [DateTimePickerComponent], imports: [FormsModule,
21193
+ DateTimePickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.6", ngImport: i0, type: DateTimePickerModule, declarations: [DateTimePickerComponent, CloseDatePickerDirective], imports: [FormsModule,
21160
21194
  CommonModule$1,
21161
21195
  FormsModule$1,
21162
21196
  ReactiveFormsModule, i6.BsDatepickerModule, CommonModule,
@@ -21181,7 +21215,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
21181
21215
  TimePickerModule
21182
21216
  ],
21183
21217
  exports: [DateTimePickerComponent],
21184
- declarations: [DateTimePickerComponent]
21218
+ declarations: [DateTimePickerComponent, CloseDatePickerDirective]
21185
21219
  }]
21186
21220
  }] });
21187
21221