@c8y/ngx-components 1006.6.36 → 1006.6.40

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.
Files changed (105) hide show
  1. package/bundles/c8y-ngx-components-connectivity.umd.js +1 -1
  2. package/bundles/c8y-ngx-components-connectivity.umd.js.map +1 -1
  3. package/bundles/c8y-ngx-components-connectivity.umd.min.js +1 -1
  4. package/bundles/c8y-ngx-components-connectivity.umd.min.js.map +1 -1
  5. package/bundles/c8y-ngx-components-context-dashboard.umd.js +1 -1
  6. package/bundles/c8y-ngx-components-context-dashboard.umd.js.map +1 -1
  7. package/bundles/c8y-ngx-components-context-dashboard.umd.min.js +1 -1
  8. package/bundles/c8y-ngx-components-context-dashboard.umd.min.js.map +1 -1
  9. package/bundles/c8y-ngx-components-repository.umd.js +1 -1
  10. package/bundles/c8y-ngx-components-repository.umd.js.map +1 -1
  11. package/bundles/c8y-ngx-components-repository.umd.min.js +1 -1
  12. package/bundles/c8y-ngx-components-repository.umd.min.js.map +1 -1
  13. package/bundles/c8y-ngx-components-sensor-phone.umd.js +1 -1
  14. package/bundles/c8y-ngx-components-sensor-phone.umd.js.map +1 -1
  15. package/bundles/c8y-ngx-components-sensor-phone.umd.min.js +1 -1
  16. package/bundles/c8y-ngx-components-sensor-phone.umd.min.js.map +1 -1
  17. package/bundles/c8y-ngx-components.umd.js +400 -131
  18. package/bundles/c8y-ngx-components.umd.js.map +1 -1
  19. package/bundles/c8y-ngx-components.umd.min.js +2 -2
  20. package/bundles/c8y-ngx-components.umd.min.js.map +1 -1
  21. package/c8y-ngx-components.d.ts +90 -87
  22. package/c8y-ngx-components.metadata.json +1 -1
  23. package/connectivity/c8y-ngx-components-connectivity.metadata.json +1 -1
  24. package/context-dashboard/c8y-ngx-components-context-dashboard.metadata.json +1 -1
  25. package/core/authentication/new-password.component.d.ts +8 -6
  26. package/core/docs/guide-docs.component.d.ts +25 -3
  27. package/core/forms/validation-pattern.d.ts +1 -0
  28. package/core/i18n/force-html-translate.directive.d.ts +32 -0
  29. package/core/login/change-password.component.d.ts +1 -1
  30. package/core/login/login.service.d.ts +15 -2
  31. package/core/login/password-strength-validator.directive.d.ts +9 -0
  32. package/core/login/strength-validator-service.d.ts +7 -0
  33. package/core/user/user-edit.component.d.ts +4 -2
  34. package/esm2015/c8y-ngx-components.js +90 -87
  35. package/esm2015/connectivity/impact/impact-provider-settings.component.js +2 -2
  36. package/esm2015/context-dashboard/legacy-welcome/legacy-welcome.component.js +2 -2
  37. package/esm2015/core/authentication/new-password.component.js +15 -20
  38. package/esm2015/core/dashboard/widgets-dashboard.component.js +2 -2
  39. package/esm2015/core/docs/guide-docs.component.js +69 -4
  40. package/esm2015/core/forms/validation-pattern.js +2 -1
  41. package/esm2015/core/i18n/force-html-translate.directive.js +99 -0
  42. package/esm2015/core/i18n/i18n.module.js +5 -3
  43. package/esm2015/core/i18n/pattern-messages.data.js +2 -2
  44. package/esm2015/core/login/change-password.component.js +5 -5
  45. package/esm2015/core/login/credentials.component.js +2 -2
  46. package/esm2015/core/login/login.module.js +4 -2
  47. package/esm2015/core/login/login.service.js +40 -6
  48. package/esm2015/core/login/password-strength-validator.directive.js +32 -0
  49. package/esm2015/core/login/strength-validator-service.js +28 -0
  50. package/esm2015/core/user/user-edit.component.js +10 -5
  51. package/esm2015/repository/configuration/configuration-list.component.js +2 -2
  52. package/esm2015/sensor-phone/sensor-phone-modal.component.js +2 -2
  53. package/esm5/c8y-ngx-components.js +90 -87
  54. package/esm5/connectivity/impact/impact-provider-settings.component.js +2 -2
  55. package/esm5/context-dashboard/legacy-welcome/legacy-welcome.component.js +2 -2
  56. package/esm5/core/authentication/new-password.component.js +21 -25
  57. package/esm5/core/dashboard/widgets-dashboard.component.js +2 -2
  58. package/esm5/core/docs/guide-docs.component.js +72 -4
  59. package/esm5/core/forms/validation-pattern.js +2 -1
  60. package/esm5/core/i18n/force-html-translate.directive.js +105 -0
  61. package/esm5/core/i18n/i18n.module.js +5 -3
  62. package/esm5/core/i18n/pattern-messages.data.js +2 -2
  63. package/esm5/core/login/change-password.component.js +5 -5
  64. package/esm5/core/login/credentials.component.js +2 -2
  65. package/esm5/core/login/login.module.js +4 -2
  66. package/esm5/core/login/login.service.js +43 -6
  67. package/esm5/core/login/password-strength-validator.directive.js +38 -0
  68. package/esm5/core/login/strength-validator-service.js +29 -0
  69. package/esm5/core/user/user-edit.component.js +19 -9
  70. package/esm5/repository/configuration/configuration-list.component.js +2 -2
  71. package/esm5/sensor-phone/sensor-phone-modal.component.js +2 -2
  72. package/fesm2015/c8y-ngx-components-connectivity.js +1 -1
  73. package/fesm2015/c8y-ngx-components-connectivity.js.map +1 -1
  74. package/fesm2015/c8y-ngx-components-context-dashboard.js +1 -1
  75. package/fesm2015/c8y-ngx-components-context-dashboard.js.map +1 -1
  76. package/fesm2015/c8y-ngx-components-repository.js +1 -1
  77. package/fesm2015/c8y-ngx-components-repository.js.map +1 -1
  78. package/fesm2015/c8y-ngx-components-sensor-phone.js +1 -1
  79. package/fesm2015/c8y-ngx-components-sensor-phone.js.map +1 -1
  80. package/fesm2015/c8y-ngx-components.js +281 -40
  81. package/fesm2015/c8y-ngx-components.js.map +1 -1
  82. package/fesm5/c8y-ngx-components-connectivity.js +1 -1
  83. package/fesm5/c8y-ngx-components-connectivity.js.map +1 -1
  84. package/fesm5/c8y-ngx-components-context-dashboard.js +1 -1
  85. package/fesm5/c8y-ngx-components-context-dashboard.js.map +1 -1
  86. package/fesm5/c8y-ngx-components-repository.js +1 -1
  87. package/fesm5/c8y-ngx-components-repository.js.map +1 -1
  88. package/fesm5/c8y-ngx-components-sensor-phone.js +1 -1
  89. package/fesm5/c8y-ngx-components-sensor-phone.js.map +1 -1
  90. package/fesm5/c8y-ngx-components.js +315 -49
  91. package/fesm5/c8y-ngx-components.js.map +1 -1
  92. package/locales/de.po +71 -60
  93. package/locales/es.po +120 -85
  94. package/locales/fr.po +107 -72
  95. package/locales/ja_JP.po +89 -78
  96. package/locales/ko.po +92 -57
  97. package/locales/locales.pot +9 -9
  98. package/locales/nl.po +95 -60
  99. package/locales/pl.po +88 -53
  100. package/locales/pt_BR.po +174 -138
  101. package/locales/ru.po +120 -85
  102. package/locales/zh_CN.po +87 -52
  103. package/package.json +2 -2
  104. package/repository/c8y-ngx-components-repository.metadata.json +1 -1
  105. package/sensor-phone/c8y-ngx-components-sensor-phone.metadata.json +1 -1
@@ -1,11 +1,11 @@
1
1
  import { __decorate, __awaiter, __param } from 'tslib';
2
- import { InjectionToken, Injector, ɵɵdefineInjectable, ɵɵinject, INJECTOR, Injectable, Optional, Inject, isDevMode, ViewContainerRef, Component, Pipe, LOCALE_ID, NgModule, ElementRef, Renderer2, Input, Directive, TemplateRef, ComponentFactoryResolver, EventEmitter, Output, HostBinding, APP_INITIALIZER, ViewChild, Attribute, ContentChild, ContentChildren, SecurityContext, HostListener, NgZone, ViewChildren, ChangeDetectorRef, Type, ChangeDetectionStrategy, forwardRef, Host } from '@angular/core';
2
+ import { InjectionToken, Injector, ɵɵdefineInjectable, ɵɵinject, INJECTOR, Injectable, Optional, Inject, isDevMode, ViewContainerRef, Component, Pipe, EventEmitter, ElementRef, ChangeDetectorRef, Input, Directive, LOCALE_ID, NgModule, Renderer2, TemplateRef, ComponentFactoryResolver, Output, HostBinding, APP_INITIALIZER, ViewChild, Attribute, ContentChild, ContentChildren, SecurityContext, HostListener, NgZone, ViewChildren, Type, ChangeDetectionStrategy, forwardRef, Host } from '@angular/core';
3
3
  import { NavigationEnd, Router, RouterModule as RouterModule$1, RouterLinkActive, PRIMARY_OUTLET, ActivatedRoute } from '@angular/router';
4
- import { of, defer, combineLatest, isObservable, from, race, Subject, BehaviorSubject, pipe, EMPTY, timer, merge as merge$1, fromEvent, fromEventPattern, NEVER } from 'rxjs';
4
+ import { of, defer, combineLatest, isObservable, from, race, Subject, BehaviorSubject, pipe, EMPTY, timer, merge as merge$1, fromEvent, fromEventPattern, ReplaySubject, NEVER } from 'rxjs';
5
5
  import { filter, merge, startWith, switchMap, map, distinctUntilChanged, shareReplay, scan, combineLatest as combineLatest$1, debounceTime, first, tap, catchError, take, debounce, finalize, takeUntil, mergeMap, expand, every, toArray } from 'rxjs/operators';
6
- import { flatten, isFunction, sortBy, camelCase, isUndefined, keys, matches, upperFirst, each, mapValues, mapKeys, get as get$1, assign, filter as filter$1, clone, map as map$1, isEmpty as isEmpty$1, find as find$1, includes, orderBy, flow, isNil, pick, omitBy, chunk, union, without, parseInt as parseInt$1, remove, transform, identity, forEach, cloneDeep, some, findIndex } from 'lodash-es';
6
+ import { flatten, isFunction, sortBy, camelCase, isUndefined, keys, matches, upperFirst, each, mapValues, mapKeys, get as get$1, isEqual, assign, filter as filter$1, isString, clone, map as map$1, isEmpty as isEmpty$1, find as find$1, includes, orderBy, flow, isNil, pick, omitBy, chunk, union, without, parseInt as parseInt$1, remove, transform, identity, forEach, cloneDeep, some, findIndex } from 'lodash-es';
7
7
  import { SystemOptionsService, TenantOptionsService, ApiService, DataModule } from '@c8y/ngx-components/api';
8
- import { ApplicationService, FetchClient, OperationStatus, UserService, InventoryService, BasicAuth, CookieAuth, TenantService, Realtime, TenantLoginOptionsService, Client, PasswordStrength, SystemOptionsService as SystemOptionsService$1, QueriesUtil } from '@c8y/client';
8
+ import { ApplicationService, FetchClient, OperationStatus, UserService, InventoryService, BasicAuth, CookieAuth, TenantService, Realtime, TenantLoginOptionsService, Client, PasswordStrength, QueriesUtil } from '@c8y/client';
9
9
  import { TranslateService as TranslateService$1, TranslateParser, TranslateDefaultParser, TranslateLoader, TranslateCompiler, TranslateFakeCompiler, MissingTranslationHandler, TranslateStore, USE_STORE, USE_DEFAULT_LANG, USE_EXTEND, DEFAULT_LANGUAGE, TranslateModule } from '@ngx-translate/core';
10
10
  import { get, find, negate, isUndefined as isUndefined$1, sortBy as sortBy$1, isEmpty } from 'lodash';
11
11
  import { formatDate, registerLocaleData, CommonModule as CommonModule$1, LocationStrategy } from '@angular/common';
@@ -3136,7 +3136,7 @@ const MESSAGES = {
3136
3136
  }
3137
3137
  },
3138
3138
  '^Error updating tenant! Cannot insert second configuration for Password code grant internal/Bad Request$': {
3139
- gettext: gettext('This login mode was already set by other admin, please refresh page to update data')
3139
+ gettext: gettext('This login mode was already set by another administrator. Refresh the page to update the data.')
3140
3140
  },
3141
3141
  };
3142
3142
 
@@ -3225,6 +3225,100 @@ TranslateParserCustom = __decorate([
3225
3225
  Injectable()
3226
3226
  ], TranslateParserCustom);
3227
3227
 
3228
+ /**
3229
+ * This is temporary fallback directive that is used to handle HTML blocks translation on maintenance versions
3230
+ * in version 10.9.4 and later, this is replaced by default translate directive.
3231
+ */
3232
+ let ForceHtmlTranslateDirective = class ForceHtmlTranslateDirective {
3233
+ constructor(translateService, element, _ref) {
3234
+ this.translateService = translateService;
3235
+ this.element = element;
3236
+ this._ref = _ref;
3237
+ /**
3238
+ * Used to trigger events when html is replaced by directive.
3239
+ */
3240
+ this.htmlUpdateEvent = new EventEmitter();
3241
+ // subscribe to onTranslationChange event, in case the translations of the current lang change
3242
+ if (!this.onTranslationChangeSub) {
3243
+ this.onTranslationChangeSub = this.translateService.onTranslationChange.subscribe((event) => {
3244
+ if (event.lang === this.translateService.currentLang) {
3245
+ this.checkNodes();
3246
+ }
3247
+ });
3248
+ }
3249
+ // subscribe to onLangChange event, in case the language changes
3250
+ if (!this.onLangChangeSub) {
3251
+ this.onLangChangeSub = this.translateService.onLangChange.subscribe((event) => {
3252
+ this.checkNodes();
3253
+ });
3254
+ }
3255
+ // subscribe to onDefaultLangChange event, in case the default language changes
3256
+ if (!this.onDefaultLangChangeSub) {
3257
+ this.onDefaultLangChangeSub = this.translateService.onDefaultLangChange.subscribe((event) => {
3258
+ this.checkNodes();
3259
+ });
3260
+ }
3261
+ }
3262
+ set translateParams(params) {
3263
+ if (!isEqual(this.currentParams, params)) {
3264
+ this.currentParams = params;
3265
+ this.checkNodes();
3266
+ }
3267
+ }
3268
+ ngAfterViewChecked() {
3269
+ this.checkNodes();
3270
+ }
3271
+ checkNodes() {
3272
+ if (this.isLookupKeyMissing()) {
3273
+ this.element.nativeElement.lookupKey = this.getLookupKey();
3274
+ }
3275
+ this.translateAndUpdateHtmlContent();
3276
+ this.htmlUpdateEvent.emit();
3277
+ }
3278
+ ngOnDestroy() {
3279
+ if (this.onLangChangeSub) {
3280
+ this.onLangChangeSub.unsubscribe();
3281
+ }
3282
+ if (this.onDefaultLangChangeSub) {
3283
+ this.onDefaultLangChangeSub.unsubscribe();
3284
+ }
3285
+ if (this.onTranslationChangeSub) {
3286
+ this.onTranslationChangeSub.unsubscribe();
3287
+ }
3288
+ this.htmlUpdateEvent.complete();
3289
+ }
3290
+ /**
3291
+ * Builds lookup key from innerHTML, removes comments (that might be added by Angular) and trims it.
3292
+ */
3293
+ getLookupKey() {
3294
+ return this.element.nativeElement.innerHTML.replace(/<!--.*?-->/gs, '').trim();
3295
+ }
3296
+ isLookupKeyMissing() {
3297
+ return !this.element.nativeElement.lookupKey;
3298
+ }
3299
+ lookupKeyExist() {
3300
+ return this.element.nativeElement.lookupKey;
3301
+ }
3302
+ translateAndUpdateHtmlContent() {
3303
+ if (this.lookupKeyExist()) {
3304
+ this.element.nativeElement.innerHTML = this.translateService.instant(this.element.nativeElement.lookupKey, this.currentParams || {});
3305
+ }
3306
+ }
3307
+ };
3308
+ ForceHtmlTranslateDirective.ctorParameters = () => [
3309
+ { type: TranslateService$1 },
3310
+ { type: ElementRef },
3311
+ { type: ChangeDetectorRef }
3312
+ ];
3313
+ __decorate([
3314
+ Input()
3315
+ ], ForceHtmlTranslateDirective.prototype, "translateParams", null);
3316
+ ForceHtmlTranslateDirective = __decorate([
3317
+ Directive({
3318
+ selector: '[forceHtmlTranslate]'
3319
+ })
3320
+ ], ForceHtmlTranslateDirective);
3321
+
3228
3322
  var I18nModule_1;
3229
3323
  // Load these as a side effect
3230
3324
  try {
@@ -3299,8 +3393,9 @@ let I18nModule = I18nModule_1 = class I18nModule {
3299
3393
  };
3300
3394
  I18nModule = I18nModule_1 = __decorate([
3301
3395
  NgModule({
3302
- exports: [TranslateModule],
3303
- imports: [HttpClientModule]
3396
+ exports: [TranslateModule, ForceHtmlTranslateDirective],
3397
+ imports: [HttpClientModule],
3398
+ declarations: [ForceHtmlTranslateDirective]
3304
3399
  })
3305
3400
  ], I18nModule);
3306
3401
 
@@ -6216,6 +6311,7 @@ let LoginService = class LoginService {
6216
6311
  };
6217
6312
  this.passwordStrengthSetting = {
6218
6313
  enforcePasswordStrength: false,
6314
+ passwordStrengthValidity: false,
6219
6315
  greenMinLength: this.GREEN_MIN_LENGTH_DEFAULT
6220
6316
  };
6221
6317
  this.localhostRegExp = new RegExp('localhost');
@@ -6283,14 +6379,47 @@ let LoginService = class LoginService {
6283
6379
  return this.passwordStrengthSetting.greenMinLength;
6284
6380
  }
6285
6381
  /**
6286
- * Checks if password strength is enforced.
6287
- * @return true if enforced.
6382
+ * Checks if password strength is enforced for system
6383
+ * by retrieving value of `enforceStrength` property from loginOptions response
6384
+ * @return boolean value, true if enforced, false otherwise.
6288
6385
  */
6289
6386
  getEnforcePasswordStrength() {
6290
6387
  const loginOption = this.getLoginOption();
6291
- this.passwordStrengthSetting.enforcePasswordStrength = get$1(loginOption, 'enforceStrength', 'false') === 'true' ? true : false;
6388
+ const enforcePasswordStrength = get$1(loginOption, 'enforceStrength');
6389
+ if (isString(enforcePasswordStrength)) {
6390
+ this.passwordStrengthSetting.enforcePasswordStrength = enforcePasswordStrength === 'true' ? true : false;
6391
+ }
6392
+ else {
6393
+ this.passwordStrengthSetting.enforcePasswordStrength = !!enforcePasswordStrength;
6394
+ }
6292
6395
  return this.passwordStrengthSetting.enforcePasswordStrength;
6293
6396
  }
6397
+ /**
6398
+ * Checks if password strength is enforced for particular tenant
6399
+ * by retrieving value of `strengthValidity` property from loginOptions response
6400
+ * @return boolean value, true if enforced, false otherwise.
6401
+ */
6402
+ getPasswordStrengthValidity() {
6403
+ return __awaiter(this, void 0, void 0, function* () {
6404
+ const loginOption = this.getLoginOption();
6405
+ const strengthValidity = get$1(loginOption, 'strengthValidity');
6406
+ if (isString(strengthValidity)) {
6407
+ this.passwordStrengthSetting.passwordStrengthValidity = strengthValidity === 'true' ? true : false;
6408
+ }
6409
+ else {
6410
+ this.passwordStrengthSetting.passwordStrengthValidity = !!strengthValidity;
6411
+ }
6412
+ return this.passwordStrengthSetting.passwordStrengthValidity;
6413
+ });
6414
+ }
6415
+ /**
6416
+ * Function determines if enforced strength checks should be enabled for current tenant
6417
+ * based on properties retrieved from loginOptions
6418
+ * @return boolean value, true if strength is enforced for tenant, false otherwise.
6419
+ */
6420
+ getPasswordStrengthEnforced() {
6421
+ return this.getEnforcePasswordStrength() || this.getPasswordStrengthValidity();
6422
+ }
6294
6423
  /**
6295
6424
  * Clears all backend errors.
6296
6425
  */
@@ -6806,7 +6935,7 @@ UserTotpSetupComponent = __decorate([
6806
6935
  ], UserTotpSetupComponent);
6807
6936
 
6808
6937
  let UserEditComponent = class UserEditComponent {
6809
- constructor(state, translate, passwordService, modalConfirmService, bsModalService, alert, userService, tenantLoginOptionsService) {
6938
+ constructor(state, translate, passwordService, modalConfirmService, bsModalService, alert, userService, tenantLoginOptionsService, tenantService) {
6810
6939
  this.state = state;
6811
6940
  this.translate = translate;
6812
6941
  this.passwordService = passwordService;
@@ -6815,6 +6944,7 @@ let UserEditComponent = class UserEditComponent {
6815
6944
  this.alert = alert;
6816
6945
  this.userService = userService;
6817
6946
  this.tenantLoginOptionsService = tenantLoginOptionsService;
6947
+ this.tenantService = tenantService;
6818
6948
  this.loading = false;
6819
6949
  this.onUser = new EventEmitter();
6820
6950
  this.onLanguage = new EventEmitter();
@@ -6829,6 +6959,9 @@ let UserEditComponent = class UserEditComponent {
6829
6959
  get user() { return this._user; }
6830
6960
  ngOnInit() {
6831
6961
  return __awaiter(this, void 0, void 0, function* () {
6962
+ const currentTenant = (yield this.tenantService.current()).data;
6963
+ const { enabledOnSystemLevel, enabledOnTenantLevel } = yield this.tenantService.getTfaSettings(currentTenant);
6964
+ this.isTfaEnabled = enabledOnSystemLevel || enabledOnTenantLevel;
6832
6965
  yield this.initializeTotpSettings();
6833
6966
  });
6834
6967
  }
@@ -6887,7 +7020,8 @@ UserEditComponent.ctorParameters = () => [
6887
7020
  { type: BsModalService },
6888
7021
  { type: AlertService },
6889
7022
  { type: UserService },
6890
- { type: TenantLoginOptionsService }
7023
+ { type: TenantLoginOptionsService },
7024
+ { type: TenantService }
6891
7025
  ];
6892
7026
  __decorate([
6893
7027
  Input()
@@ -6910,7 +7044,7 @@ __decorate([
6910
7044
  UserEditComponent = __decorate([
6911
7045
  Component({
6912
7046
  selector: 'c8y-user-edit',
6913
- template: "<form #userForm=\"ngForm\" (ngSubmit)=\"userForm.form.valid && save()\">\n <div class=\"alert alert-warning\" role=\"alert\" *ngIf=\"userIsExternal\" translate>\n You cannot edit the user since it is managed via your authorization server.\n </div>\n <c8y-form-group>\n <label translate for=\"userName\">Username (e.g. email)</label>\n <input\n id=\"userName\"\n class=\"form-control\"\n [(ngModel)]=\"user.userName\"\n name=\"userName\"\n autocomplete=\"off\"\n required\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [disabled]=\"user.id\"\n c8yDefaultValidation=\"user\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"displayName\">Login alias</label>\n <input\n id=\"displayName\"\n class=\"form-control\"\n [(ngModel)]=\"user.displayName\"\n name=\"displayName\"\n autocomplete=\"off\"\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe`LOCALIZE`' | translate }}\"\n [disabled]=\"userIsExternal\"\n c8yDefaultValidation=\"loginAlias\"\n />\n </c8y-form-group>\n\n <c8y-form-group [hasWarning]=\"!user.email\">\n <label translate for=\"userEmail\">Email</label>\n <input\n id=\"userEmail\"\n class=\"form-control\"\n type=\"email\"\n name=\"email\"\n [maxlength]=\"254\"\n autocomplete=\"off\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"user.email\"\n email\n [required]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <c8y-messages>\n <c8y-message *ngIf=\"!user.email\" translate\n >Note that email is required to reset password.</c8y-message\n >\n </c8y-messages>\n </c8y-form-group>\n\n <div class=\"row\" style=\"margin-left:-15px; margin-right:-15px\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userFirstName\">First name</label>\n <input\n id=\"userFirstName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"firstName\"\n [(ngModel)]=\"user.firstName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userLastName\">Last name</label>\n <input\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"lastName\"\n [(ngModel)]=\"user.lastName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n </div>\n\n <c8y-form-group>\n <label translate for=\"userTelephone\">Telephone</label>\n <input\n id=\"userTelephone\"\n class=\"form-control\"\n autocomplete=\"off\"\n name=\"phone\"\n maxlength=\"254\"\n [(ngModel)]=\"user.phone\"\n placeholder=\"{{ 'e.g. +49 9 876 543 210`LOCALIZE`' | translate }}\"\n c8yPhoneValidation\n c8yDefaultValidation=\"phoneNumber\"\n [required]=\"user.twoFactorAuthenticationEnabled\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"userLang\">Language</label>\n <div class=\"c8y-select-wrapper\">\n <select\n id=\"userLang\"\n class=\"form-control\"\n #selectLang\n name=\"lang\"\n [(ngModel)]=\"lang\"\n (change)=\"onLanguage.emit(selectLang.value)\"\n [disabled]=\"userIsExternal\"\n >\n <option *ngFor=\"let lang of langs\" [value]=\"lang\">{{\n translate.getNativeLanguage(lang)\n }}</option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n\n <div class=\"form-group\" *ngIf=\"!userIsExternal\">\n <label class=\"control-label\">{{ 'Login options' | translate }}</label>\n <c8y-new-password (password)=\"onNewPasswordChanged($event)\"></c8y-new-password>\n <button\n title=\"{{ 'Set up two-factor authentication' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"setupTotp()\"\n translate\n *ngIf=\"userCanSetupTotp && !userHasActiveTotp\"\n >\n Set up two-factor authentication\n </button>\n </div>\n\n <c8y-form-group *ngIf=\"!!(state.state$ | async).newsletter\">\n <label translate>Newsletter</label>\n <label class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n name=\"newsletter\"\n [(ngModel)]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <span></span>\n {{ 'Send me information about outages, maintenance or updates.' | translate }}\n </label>\n </c8y-form-group>\n\n <div class=\"modal-footer\">\n <button\n title=\"{{ 'Cancel' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"cancel()\"\n translate\n >\n Cancel\n </button>\n <button\n title=\"{{ 'Save' | translate }}\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!userForm.form.valid || userForm.form.pristine || loading || userIsExternal\"\n translate\n >\n Save\n </button>\n </div>\n</form>\n"
7047
+ template: "<form #userForm=\"ngForm\" (ngSubmit)=\"userForm.form.valid && save()\">\n <div class=\"alert alert-warning\" role=\"alert\" *ngIf=\"userIsExternal\" translate>\n You cannot edit the user since it is managed via your authorization server.\n </div>\n <c8y-form-group>\n <label translate for=\"userName\">Username (e.g. email)</label>\n <input\n id=\"userName\"\n class=\"form-control\"\n [(ngModel)]=\"user.userName\"\n name=\"userName\"\n autocomplete=\"off\"\n required\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [disabled]=\"user.id\"\n c8yDefaultValidation=\"user\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"displayName\">Login alias</label>\n <input\n id=\"displayName\"\n class=\"form-control\"\n [(ngModel)]=\"user.displayName\"\n name=\"displayName\"\n autocomplete=\"off\"\n maxlength=\"254\"\n placeholder=\"{{ 'e.g. joe.doe`LOCALIZE`' | translate }}\"\n [disabled]=\"userIsExternal\"\n c8yDefaultValidation=\"loginAlias\"\n />\n </c8y-form-group>\n\n <c8y-form-group [hasWarning]=\"!user.email\">\n <label translate for=\"userEmail\">Email</label>\n <input\n id=\"userEmail\"\n class=\"form-control\"\n type=\"email\"\n name=\"email\"\n [maxlength]=\"254\"\n autocomplete=\"off\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"user.email\"\n email\n [required]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <c8y-messages>\n <c8y-message *ngIf=\"!user.email\" translate\n >Note that email is required to reset password.</c8y-message\n >\n </c8y-messages>\n </c8y-form-group>\n\n <div class=\"row\" style=\"margin-left:-15px; margin-right:-15px\">\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userFirstName\">First name</label>\n <input\n id=\"userFirstName\"\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"firstName\"\n [(ngModel)]=\"user.firstName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n <div class=\"col-sm-6\">\n <c8y-form-group>\n <label translate for=\"userLastName\">Last name</label>\n <input\n class=\"form-control\"\n autocomplete=\"off\"\n maxlength=\"50\"\n name=\"lastName\"\n [(ngModel)]=\"user.lastName\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n </div>\n </div>\n\n <c8y-form-group>\n <label translate for=\"userTelephone\">Telephone</label>\n <input\n id=\"userTelephone\"\n class=\"form-control\"\n autocomplete=\"off\"\n name=\"phone\"\n maxlength=\"254\"\n [(ngModel)]=\"user.phone\"\n placeholder=\"{{ 'e.g. +49 9 876 543 210`LOCALIZE`' | translate }}\"\n c8yPhoneValidation\n c8yDefaultValidation=\"phoneNumber\"\n [required]=\"user.twoFactorAuthenticationEnabled\"\n [disabled]=\"userIsExternal\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate for=\"userLang\">Language</label>\n <div class=\"c8y-select-wrapper\">\n <select\n id=\"userLang\"\n class=\"form-control\"\n #selectLang\n name=\"lang\"\n [(ngModel)]=\"lang\"\n (change)=\"onLanguage.emit(selectLang.value)\"\n [disabled]=\"userIsExternal\"\n >\n <option *ngFor=\"let lang of langs\" [value]=\"lang\">{{\n translate.getNativeLanguage(lang)\n }}</option>\n </select>\n <span></span>\n </div>\n </c8y-form-group>\n\n <div class=\"form-group\" *ngIf=\"!userIsExternal\">\n <label class=\"control-label\">{{ 'Login options' | translate }}</label>\n <c8y-new-password (password)=\"onNewPasswordChanged($event)\"></c8y-new-password>\n <button\n title=\"{{ 'Set up two-factor authentication' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"setupTotp()\"\n translate\n *ngIf=\"userCanSetupTotp && !userHasActiveTotp && isTfaEnabled\"\n >\n Set up two-factor authentication\n </button>\n </div>\n\n <c8y-form-group *ngIf=\"!!(state.state$ | async).newsletter\">\n <label translate>Newsletter</label>\n <label class=\"c8y-checkbox\">\n <input\n type=\"checkbox\"\n name=\"newsletter\"\n [(ngModel)]=\"user.newsletter\"\n [disabled]=\"userIsExternal\"\n />\n <span></span>\n {{ 'Send me information about outages, maintenance or updates.' | translate }}\n </label>\n </c8y-form-group>\n\n <div class=\"modal-footer\">\n <button\n title=\"{{ 'Cancel' | translate }}\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"cancel()\"\n translate\n >\n Cancel\n </button>\n <button\n title=\"{{ 'Save' | translate }}\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"!userForm.form.valid || userForm.form.pristine || loading || userIsExternal\"\n translate\n >\n Save\n </button>\n </div>\n</form>\n"
6914
7048
  })
6915
7049
  ], UserEditComponent);
6916
7050
 
@@ -7259,15 +7393,16 @@ PasswordStrengthComponent = __decorate([
7259
7393
  ], PasswordStrengthComponent);
7260
7394
 
7261
7395
  let NewPasswordComponent = class NewPasswordComponent {
7262
- constructor(systemOptions) {
7263
- this.systemOptions = systemOptions;
7396
+ constructor(loginService) {
7397
+ this.loginService = loginService;
7264
7398
  this.password = new EventEmitter();
7265
7399
  this.model = {};
7266
- this.enforcePasswordStrength = false;
7267
7400
  this.changePassword = false;
7401
+ this.passwordEnforced = false;
7268
7402
  }
7269
7403
  ngOnInit() {
7270
- this.loadEnforcePasswordStrength();
7404
+ this.loadPasswordStrengthSettings();
7405
+ this.minlength = this.loginService.getGreenMinLength();
7271
7406
  }
7272
7407
  newPasswordChanged() {
7273
7408
  this.password.emit({
@@ -7275,20 +7410,14 @@ let NewPasswordComponent = class NewPasswordComponent {
7275
7410
  passwordStrength: this.model.strength
7276
7411
  });
7277
7412
  }
7278
- loadEnforcePasswordStrength() {
7413
+ loadPasswordStrengthSettings() {
7279
7414
  return __awaiter(this, void 0, void 0, function* () {
7280
- try {
7281
- const { data } = yield this.systemOptions.detail({
7282
- category: 'password',
7283
- key: 'enforce.strength'
7284
- });
7285
- this.enforcePasswordStrength = data.value === 'true';
7286
- }
7287
- catch (e) {
7288
- // do nothing;
7289
- }
7415
+ this.passwordEnforced = yield this.loginService.getEnforcePasswordStrength();
7290
7416
  });
7291
7417
  }
7418
+ showPasswordStrength() {
7419
+ return this.model.newPassword && this.model.newPassword.length >= this.minlength;
7420
+ }
7292
7421
  toggleChangePassword() {
7293
7422
  this.changePassword = !this.changePassword;
7294
7423
  if (!this.changePassword) {
@@ -7298,7 +7427,7 @@ let NewPasswordComponent = class NewPasswordComponent {
7298
7427
  }
7299
7428
  };
7300
7429
  NewPasswordComponent.ctorParameters = () => [
7301
- { type: SystemOptionsService$1 }
7430
+ { type: LoginService }
7302
7431
  ];
7303
7432
  __decorate([
7304
7433
  Output()
@@ -7306,7 +7435,7 @@ __decorate([
7306
7435
  NewPasswordComponent = __decorate([
7307
7436
  Component({
7308
7437
  selector: 'c8y-new-password',
7309
- template: "<div class=\"form-group\">\n <button type=\"button\" class=\"btn btn-default\" (click)=\"toggleChangePassword()\">\n <ng-container *ngIf=\"!changePassword\">\n {{ 'Change password' | translate }}\n </ng-container>\n <ng-container *ngIf=\"changePassword\">\n {{ 'Cancel password change' | translate }}\n </ng-container>\n </button>\n</div>\n\n<div *ngIf=\"changePassword\">\n <c8y-form-group>\n <label for=\"newPassword\" translate>Password</label>\n <input\n id=\"newPassword\"\n [(ngModel)]=\"model.newPassword\"\n #newPassword=\"ngModel\"\n (change)=\"newPasswordChanged()\"\n type=\"password\"\n name=\"newPassword\"\n class=\"form-control\"\n placeholder=\"{{ 'e.g. my_new_password' | translate }}\"\n required\n c8yDefaultValidation=\"password\"\n autocomplete=\"new-password\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label for=\"newConfirmPassword\" translate>Confirm password</label>\n <input\n id=\"newConfirmPassword\"\n [(ngModel)]=\"model.newPasswordConfirm\"\n #newPasswordConfirm=\"ngModel\"\n type=\"password\"\n name=\"newPasswordConfirm\"\n class=\"form-control\"\n placeholder=\"{{ 'e.g. my_new_password' | translate }}\"\n required\n passwordConfirm=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </c8y-form-group>\n\n <c8y-password-strength\n [password]=\"model.newPassword\"\n [hidden]=\"!model.newPassword\"\n (strength)=\"model.strength = $event\"\n ></c8y-password-strength>\n\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [hidden]=\"!enforcePasswordStrength\"\n ></c8y-password-check-list>\n</div>\n",
7438
+ template: "<div class=\"form-group\">\n <button type=\"button\" class=\"btn btn-default\" (click)=\"toggleChangePassword()\">\n <ng-container *ngIf=\"!changePassword\">\n {{ 'Change password' | translate }}\n </ng-container>\n <ng-container *ngIf=\"changePassword\">\n {{ 'Cancel password change' | translate }}\n </ng-container>\n </button>\n</div>\n\n<div *ngIf=\"changePassword\">\n <c8y-form-group>\n <label for=\"newPassword\" translate>Password</label>\n <input\n id=\"newPassword\"\n [(ngModel)]=\"model.newPassword\"\n #newPassword=\"ngModel\"\n (change)=\"newPasswordChanged()\"\n type=\"password\"\n name=\"newPassword\"\n class=\"form-control\"\n placeholder=\"{{ 'e.g. my_new_password' | translate }}\"\n required\n c8yDefaultValidation=\"password\"\n autocomplete=\"new-password\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label for=\"newConfirmPassword\" translate>Confirm password</label>\n <input\n id=\"newConfirmPassword\"\n [(ngModel)]=\"model.newPasswordConfirm\"\n #newPasswordConfirm=\"ngModel\"\n type=\"password\"\n name=\"newPasswordConfirm\"\n class=\"form-control\"\n placeholder=\"{{ 'e.g. my_new_password' | translate }}\"\n required\n passwordConfirm=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </c8y-form-group>\n\n <c8y-password-strength\n [password]=\"model.newPassword\"\n [hidden]=\"!showPasswordStrength()\"\n (strength)=\"model.strength = $event\"\n ></c8y-password-strength>\n\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [hidden]=\"!passwordEnforced\"\n ></c8y-password-check-list>\n</div>\n",
7310
7439
  viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]
7311
7440
  })
7312
7441
  ], NewPasswordComponent);
@@ -7361,6 +7490,7 @@ ValidationPattern.messages = {
7361
7490
  opcuaBrowsePath: gettext('Invalid OPC UA URI.'),
7362
7491
  password: gettext('Password must have at least 8 characters and no more than 32 and can only contain letters, numbers and following symbols: `~!@#$%^&*()_|+-=?;:\'",.<>{}[]\\/'),
7363
7492
  passwordConfirm: gettext('Passwords do not match.'),
7493
+ passwordStrength: gettext('Password not good enough, password must be stronger (green).'),
7364
7494
  phoneNumber: gettext('Invalid phone number format. Only digits, spaces, slashes ("/") and dashes ("-") allowed.'),
7365
7495
  required: gettext('This field is required.'),
7366
7496
  tenantId: gettext('May contain lowercase letters, digits, hyphens and underscores. ' +
@@ -9217,9 +9347,9 @@ let ChangePasswordComponent = class ChangePasswordComponent {
9217
9347
  tenantId: '',
9218
9348
  email: '',
9219
9349
  newPassword: '',
9220
- newPasswordConfirm: ''
9350
+ newPasswordConfirm: '',
9351
+ passwordStrengthEnforced: false
9221
9352
  };
9222
- this.enforcePasswordStrength = false;
9223
9353
  this.emailReadOnly = false;
9224
9354
  this.TOKEN_PARAM = 'token';
9225
9355
  this.EMAIL_PARAM = 'email';
@@ -9229,7 +9359,7 @@ let ChangePasswordComponent = class ChangePasswordComponent {
9229
9359
  this.model.tenantId = this.loginService.getTenant();
9230
9360
  this.model.email = this.options.get(this.EMAIL_PARAM, '');
9231
9361
  this.emailReadOnly = !!this.model.email;
9232
- this.enforcePasswordStrength = this.loginService.getEnforcePasswordStrength();
9362
+ this.model.passwordStrengthEnforced = this.loginService.getEnforcePasswordStrength();
9233
9363
  });
9234
9364
  }
9235
9365
  changePassword() {
@@ -9277,7 +9407,7 @@ __decorate([
9277
9407
  ChangePasswordComponent = __decorate([
9278
9408
  Component({
9279
9409
  selector: 'c8y-change-password',
9280
- template: "<form\n role=\"form\"\n class=\"loginForm\"\n (ngSubmit)=\"changePassword()\"\n #changePasswordForm=\"ngForm\"\n novalidate\n>\n <c8y-form-group class=\"tenantField\" id=\"tenantField\" *ngIf=\"loginService.showTenant()\">\n <label translate>Tenant ID</label>\n <input\n [(ngModel)]=\"model.tenantId\"\n #tenantId=\"ngModel\"\n type=\"text\"\n name=\"tenantId\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Tenant ID' | translate }}\"\n required\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Email address</label>\n <input\n [(ngModel)]=\"model.email\"\n #email=\"ngModel\"\n type=\"text\"\n name=\"email\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Email address' | translate }}\"\n email\n required\n [readonly]=\"emailReadOnly\"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>New password</label>\n <input\n [(ngModel)]=\"model.newPassword\"\n #newPassword=\"ngModel\"\n type=\"password\"\n name=\"newPassword\"\n class=\"form-control\"\n placeholder=\"{{ 'New password' | translate }}\"\n [pattern]=\"passwordPattern\"\n autocomplete=\"new-password\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"pattern\"\n [text]=\"loginService.ERROR_MESSAGES.pattern_newPassword\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Confirm password</label>\n <input\n [(ngModel)]=\"model.newPasswordConfirm\"\n #newPasswordConfirm=\"ngModel\"\n type=\"password\"\n name=\"newPasswordConfirm\"\n class=\"form-control\"\n placeholder=\"{{ 'Confirm password' | translate }}\"\n passwordConfirm=\"newPassword\"\n autocomplete=\"new-password\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"passwordConfirm\"\n [text]=\"loginService.ERROR_MESSAGES.passwordConfirm\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-password-strength\n [password]=\"model.newPassword\"\n [hidden]=\"!model.newPassword\"\n ></c8y-password-strength>\n <c8y-password-check-list\n [password]=\"model.newPassword\"\n [hidden]=\"!model.newPassword || !enforcePasswordStrength\"\n ></c8y-password-check-list>\n\n <button\n title=\"{{ 'Set password' | translate }}\"\n [disabled]=\"!changePasswordForm.form.valid || isLoading\"\n type=\"submit\"\n class=\"btn btn-primary btn-lg btn-block form-group\"\n translate\n >\n Set password\n </button>\n</form>\n"
9410
+ template: "<form\n role=\"form\"\n class=\"loginForm\"\n (ngSubmit)=\"changePassword()\"\n #changePasswordForm=\"ngForm\"\n novalidate\n>\n\n <div\n class=\"legend form-block center\"\n translate\n >\n Change password\n </div>\n\n <c8y-form-group class=\"tenantField\" id=\"tenantField\" *ngIf=\"loginService.showTenant()\">\n <label translate>Tenant ID</label>\n <input\n [(ngModel)]=\"model.tenantId\"\n #tenantId=\"ngModel\"\n type=\"text\"\n name=\"tenantId\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Tenant ID' | translate }}\"\n required\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Email address</label>\n <input\n [(ngModel)]=\"model.email\"\n #email=\"ngModel\"\n type=\"text\"\n name=\"email\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n class=\"form-control\"\n placeholder=\"{{ 'Email address' | translate }}\"\n email\n required\n [readonly]=\"emailReadOnly\"\n />\n </c8y-form-group>\n\n <div class=\"row content-flex-50\">\n <div class=\"col-7\">\n <c8y-form-group>\n <label translate>New password</label>\n <input\n [(ngModel)]=\"model.newPassword\"\n #newPassword=\"ngModel\"\n type=\"password\"\n name=\"newPassword\"\n class=\"form-control\"\n placeholder=\"{{ 'New password' | translate }}\"\n [pattern]=\"passwordPattern\"\n autocomplete=\"new-password\"\n [passwordStrengthEnforced]=\"model.passwordStrengthEnforced\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"pattern\"\n [text]=\"loginService.ERROR_MESSAGES.pattern_newPassword\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Confirm password</label>\n <input\n [(ngModel)]=\"model.newPasswordConfirm\"\n #newPasswordConfirm=\"ngModel\"\n type=\"password\"\n name=\"newPasswordConfirm\"\n class=\"form-control\"\n placeholder=\"{{ 'Confirm password' | translate }}\"\n passwordConfirm=\"newPassword\"\n autocomplete=\"new-password\"\n required\n />\n <c8y-messages>\n <c8y-message\n name=\"passwordConfirm\"\n [text]=\"loginService.ERROR_MESSAGES.passwordConfirm\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n <div class=\"col-5\">\n <c8y-password-strength\n [password]=\"model.newPassword\"\n [hidden]=\"!model.newPassword\"\n ></c8y-password-strength>\n <c8y-password-check-list\n class=\"m-t-32\"\n [password]=\"model.newPassword\"\n [hidden]=\"!model.newPassword || !model.passwordStrengthEnforced\"\n ></c8y-password-check-list>\n </div>\n </div>\n\n <button\n title=\"{{ 'Set password' | translate }}\"\n [disabled]=\"!changePasswordForm.form.valid || isLoading\"\n type=\"submit\"\n class=\"btn btn-primary btn-lg btn-block form-group\"\n translate\n >\n Set password\n </button>\n</form>\n"
9281
9411
  })
9282
9412
  ], ChangePasswordComponent);
9283
9413
 
@@ -9366,7 +9496,7 @@ let CredentialsComponent = class CredentialsComponent {
9366
9496
  }
9367
9497
  handleNoPhoneNumberProvided() {
9368
9498
  this.onChangeView.emit({ view: LoginViews.ProvidePhoneNumber, credentials: this.model });
9369
- this.alert.warning(gettext('Two-factor authentication has been turned on for this account. Please provide your phone number above to save it in your user profile and start receiving verification codes via SMS.'));
9499
+ this.alert.warning(gettext('Two-factor authentication has been turned on for this account. Provide your phone number above to save it in your user profile and start receiving verification codes via SMS.'));
9370
9500
  }
9371
9501
  };
9372
9502
  CredentialsComponent.ctorParameters = () => [
@@ -9600,6 +9730,54 @@ TotpAuthComponent = __decorate([
9600
9730
  })
9601
9731
  ], TotpAuthComponent);
9602
9732
 
9733
+ let StrengthValidatorService = class StrengthValidatorService {
9734
+ constructor(passwordService) {
9735
+ this.passwordService = passwordService;
9736
+ }
9737
+ isStrong(password) {
9738
+ return this.isPasswordGreen(this.passwordService.getStrengthColor(password).passwordStrength);
9739
+ }
9740
+ isPasswordGreen(strength) {
9741
+ return strength === PasswordStrength.GREEN;
9742
+ }
9743
+ };
9744
+ StrengthValidatorService.ctorParameters = () => [
9745
+ { type: PasswordService }
9746
+ ];
9747
+ StrengthValidatorService.ngInjectableDef = ɵɵdefineInjectable({ factory: function StrengthValidatorService_Factory() { return new StrengthValidatorService(ɵɵinject(PasswordService)); }, token: StrengthValidatorService, providedIn: "root" });
9748
+ StrengthValidatorService = __decorate([
9749
+ Injectable({
9750
+ providedIn: 'root'
9751
+ })
9752
+ ], StrengthValidatorService);
9753
+
9754
+ var PasswordStrengthValidatorDirective_1;
9755
+ let PasswordStrengthValidatorDirective = PasswordStrengthValidatorDirective_1 = class PasswordStrengthValidatorDirective {
9756
+ constructor(passwordService) {
9757
+ this.passwordService = passwordService;
9758
+ }
9759
+ set passwordStrengthEnforced(value) {
9760
+ this.forced = value;
9761
+ }
9762
+ validate(control) {
9763
+ const strengthFulfilled = this.passwordService.isStrong(control.value || '');
9764
+ const enforcementForcedAndNotFulfilled = this.forced && !strengthFulfilled;
9765
+ return enforcementForcedAndNotFulfilled ? { passwordStrength: true } : null;
9766
+ }
9767
+ };
9768
+ PasswordStrengthValidatorDirective.ctorParameters = () => [
9769
+ { type: StrengthValidatorService }
9770
+ ];
9771
+ __decorate([
9772
+ Input()
9773
+ ], PasswordStrengthValidatorDirective.prototype, "passwordStrengthEnforced", null);
9774
+ PasswordStrengthValidatorDirective = PasswordStrengthValidatorDirective_1 = __decorate([
9775
+ Directive({
9776
+ selector: '[passwordStrengthEnforced]',
9777
+ providers: [{ provide: NG_VALIDATORS, useExisting: PasswordStrengthValidatorDirective_1, multi: true }]
9778
+ })
9779
+ ], PasswordStrengthValidatorDirective);
9780
+
9603
9781
  var LoginModule_1;
9604
9782
  /**
9605
9783
  * The angular module definition for the login.
@@ -9623,7 +9801,8 @@ LoginModule = LoginModule_1 = __decorate([
9623
9801
  RecoverPasswordComponent,
9624
9802
  ChangePasswordComponent,
9625
9803
  CredentialsComponent,
9626
- TotpAuthComponent
9804
+ TotpAuthComponent,
9805
+ PasswordStrengthValidatorDirective
9627
9806
  ],
9628
9807
  imports: [
9629
9808
  FormsModule$1,
@@ -12643,24 +12822,86 @@ GuideHrefDirective = __decorate([
12643
12822
  ], GuideHrefDirective);
12644
12823
 
12645
12824
  let GuideDocsComponent = class GuideDocsComponent {
12646
- constructor(docs) {
12825
+ constructor(docs, el, renderer) {
12647
12826
  this.docs = docs;
12827
+ this.el = el;
12828
+ this.renderer = renderer;
12829
+ this.destroyed$ = new ReplaySubject(1);
12648
12830
  }
12649
12831
  ngOnInit() {
12650
12832
  this.baseUrl = this.docs.getBaseUrl();
12651
12833
  }
12834
+ /**
12835
+ * After content is initialized we subscribe for translation events, then we are able to modify
12836
+ * anchor just as C8yGuideHrefDirective does.
12837
+ */
12838
+ ngAfterContentInit() {
12839
+ if (this.translateDirective) {
12840
+ this.translateDirective.htmlUpdateEvent
12841
+ .pipe(takeUntil(this.destroyed$))
12842
+ .subscribe(() => {
12843
+ this.replaceAnchorAttributes();
12844
+ });
12845
+ }
12846
+ else {
12847
+ this.replaceAnchorAttributes();
12848
+ }
12849
+ }
12850
+ /**
12851
+ * Find and modify anchor elements
12852
+ */
12853
+ replaceAnchorAttributes() {
12854
+ const anchors = this.findGuideAnchors(this.el.nativeElement);
12855
+ anchors.forEach(a => {
12856
+ const guideHref = `${this.baseUrl}/${a.getAttribute('c8y-guide-href')}`;
12857
+ this.renderer.setAttribute(a, 'href', guideHref);
12858
+ if (!a.hasAttribute('target')) {
12859
+ this.renderer.setAttribute(a, 'target', '_blank');
12860
+ }
12861
+ });
12862
+ }
12863
+ /**
12864
+ * Recursive function, returns array of Anchor elements inside HTMLElement.
12865
+ */
12866
+ findGuideAnchors(el) {
12867
+ const isAnchor = () => el.nodeName === 'A';
12868
+ const hasGuideHrefAttr = () => !!el.attributes.getNamedItem('c8y-guide-href');
12869
+ const hasChildren = () => el.childNodes && el.childNodes.length > 0;
12870
+ let result = [];
12871
+ if (isAnchor() && hasGuideHrefAttr()) {
12872
+ result.push(el);
12873
+ }
12874
+ else if (hasChildren()) {
12875
+ el.childNodes.forEach((node) => {
12876
+ const searchResult = this.findGuideAnchors(node);
12877
+ if (searchResult) {
12878
+ result = [...result, ...searchResult];
12879
+ }
12880
+ });
12881
+ }
12882
+ return result;
12883
+ }
12652
12884
  ngAfterViewInit() {
12653
12885
  this.links.forEach(guide => {
12654
12886
  guide.baseHref = this.baseUrl;
12655
12887
  });
12656
12888
  }
12889
+ ngOnDestroy() {
12890
+ this.destroyed$.next(true);
12891
+ this.destroyed$.complete();
12892
+ }
12657
12893
  };
12658
12894
  GuideDocsComponent.ctorParameters = () => [
12659
- { type: DocsService }
12895
+ { type: DocsService },
12896
+ { type: ElementRef },
12897
+ { type: Renderer2 }
12660
12898
  ];
12661
12899
  __decorate([
12662
12900
  ContentChildren(GuideHrefDirective, { descendants: true })
12663
12901
  ], GuideDocsComponent.prototype, "links", void 0);
12902
+ __decorate([
12903
+ ContentChild(ForceHtmlTranslateDirective, { static: false })
12904
+ ], GuideDocsComponent.prototype, "translateDirective", void 0);
12664
12905
  GuideDocsComponent = __decorate([
12665
12906
  Component({
12666
12907
  selector: '[c8y-guide-docs]',
@@ -13598,7 +13839,7 @@ __decorate([
13598
13839
  WidgetsDashboardComponent = __decorate([
13599
13840
  Component({
13600
13841
  selector: 'c8y-widgets-dashboard',
13601
- template: "<c8y-title *ngIf=\"!!settings.title\">\n {{ settings.title | translate }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onAddWidget.observers.length\">\n <button\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n >\n <i c8yIcon=\"plus-circle\"></i> {{ 'Add widget' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onEditDashboard.observers.length\">\n <button\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onEditDashboard.emit()\"\n >\n <i c8yIcon=\"pencil\"></i> {{ 'Edit' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"settings.allowFullscreen\">\n <button class=\"btn btn-link\" (click)=\"toggleFullscreen()\">\n <i [c8yIcon]=\"fullScreen() ? 'compress' : 'expand'\"></i> {{ 'Full screen' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"navbar-form\"\n *ngIf=\"onFreeze.observers.length\"\n>\n <button\n title=\"{{ 'Lock/unlock this dashboard' | translate }}\"\n class=\"btn btn-default\"\n [ngClass]=\"{ active: settings.isFrozen }\"\n (click)=\"onFreeze.emit(settings)\"\n [disabled]=\"settings.isDisabled\"\n uib-btn-checkbox\n >\n <i [c8yIcon]=\"settings.isFrozen ? 'lock' : 'unlock'\"></i>\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n *ngIf=\"settings.canDelete && onDeleteDashboard.observers.length\"\n>\n <button (click)=\"onDeleteDashboard.emit()\" [disabled]=\"settings.isFrozen || settings.isDisabled\">\n <i c8yIcon=\"trash\"></i>&nbsp;<span translate>Delete dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<!-- empty state -->\n<div class=\"c8y-empty-state text-center\" *ngIf=\"!settings.isLoading && widgets.length === 0\">\n <h1 class=\"c8y-icon c8y-icon-device c8y-icon-duocolor\"></h1>\n <h3 translate>No widgets to display.</h3>\n <div *ngIf=\"!settings.isFrozen && onAddWidget.observers.length\">\n <p translate>Add widgets to this dashboard.</p>\n <div>\n <button\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n class=\"btn btn-primary\"\n translate\n >\n Add widget\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate\n >Find out more in the\n <a c8y-guide-href=\"users-guide/cockpit/#dashboards\">User guide`KEEP_ORIGINAL`</a>.</small\n >\n </p>\n </div>\n</div>\n<!-- /.empty settings -->\n\n<div class=\"col-xs-12 text-center\" *ngIf=\"settings.isLoading\">\n <div class=\"spinner\" style=\"position: relative;\">\n <div class=\"rect1\"></div>\n <div class=\"rect2\"></div>\n <div class=\"rect3\"></div>\n <div class=\"rect4\"></div>\n <div class=\"rect5\"></div>\n </div>\n</div>\n\n<c8y-dashboard\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n #dashboard\n *ngIf=\"!settings.isLoading\"\n>\n <c8y-dashboard-child\n *ngFor=\"let widget of widgets\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || settings.defaultWidth\"\n [height]=\"widget._height || settings.defaultHeight\"\n [margin]=\"settings.widgetMargin\"\n [isFrozen]=\"settings.isFrozen || settings.isDisabled\"\n [class]=\"widget.classes\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n (changeStart)=\"onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n #child\n >\n <c8y-dashboard-child-title>\n <span *ngIf=\"settings.translateWidgetTitle\"> {{ widget.title | translate }}</span>\n <span *ngIf=\"!settings.translateWidgetTitle\">\n {{ widget.title }}\n </span>\n </c8y-dashboard-child-title>\n <c8y-dashboard-child-action *ngIf=\"onEditWidget.observers.length\">\n <button (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\">\n <i c8yIcon=\"pencil\"></i>&nbsp;<span translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dashboard-child-action *ngIf=\"onDeleteWidget.observers.length\">\n <button\n (click)=\"onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"trash\"></i>&nbsp;<span translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n *ngIf=\"child.intersected\"\n ></c8y-dynamic-component>\n </c8y-dashboard-child>\n</c8y-dashboard>\n",
13842
+ template: "<c8y-title *ngIf=\"!!settings.title\">\n {{ settings.title | translate }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onAddWidget.observers.length\">\n <button\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n >\n <i c8yIcon=\"plus-circle\"></i> {{ 'Add widget' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"onEditDashboard.observers.length\">\n <button\n class=\"btn btn-link\"\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onEditDashboard.emit()\"\n >\n <i c8yIcon=\"pencil\"></i> {{ 'Edit' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\" *ngIf=\"settings.allowFullscreen\">\n <button class=\"btn btn-link\" (click)=\"toggleFullscreen()\">\n <i [c8yIcon]=\"fullScreen() ? 'compress' : 'expand'\"></i> {{ 'Full screen' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"navbar-form\"\n *ngIf=\"onFreeze.observers.length\"\n>\n <button\n title=\"{{ 'Lock/unlock this dashboard' | translate }}\"\n class=\"btn btn-default\"\n [ngClass]=\"{ active: settings.isFrozen }\"\n (click)=\"onFreeze.emit(settings)\"\n [disabled]=\"settings.isDisabled\"\n uib-btn-checkbox\n >\n <i [c8yIcon]=\"settings.isFrozen ? 'lock' : 'unlock'\"></i>\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n *ngIf=\"settings.canDelete && onDeleteDashboard.observers.length\"\n>\n <button (click)=\"onDeleteDashboard.emit()\" [disabled]=\"settings.isFrozen || settings.isDisabled\">\n <i c8yIcon=\"trash\"></i>&nbsp;<span translate>Delete dashboard</span>\n </button>\n</c8y-action-bar-item>\n\n<!-- empty state -->\n<div class=\"c8y-empty-state text-center\" *ngIf=\"!settings.isLoading && widgets.length === 0\">\n <h1 class=\"c8y-icon c8y-icon-device c8y-icon-duocolor\"></h1>\n <h3 translate>No widgets to display.</h3>\n <div *ngIf=\"!settings.isFrozen && onAddWidget.observers.length\">\n <p translate>Add widgets to this dashboard.</p>\n <div>\n <button\n [disabled]=\"settings.isFrozen || settings.isDisabled\"\n (click)=\"onAddWidget.emit()\"\n class=\"btn btn-primary\"\n translate\n >\n Add widget\n </button>\n </div>\n <p c8y-guide-docs>\n <small forceHtmlTranslate ngNonBindable\n >Find out more in the\n <a c8y-guide-href=\"users-guide/cockpit/#dashboards\">User guide`KEEP_ORIGINAL`</a>.</small\n >\n </p>\n </div>\n</div>\n<!-- /.empty settings -->\n\n<div class=\"col-xs-12 text-center\" *ngIf=\"settings.isLoading\">\n <div class=\"spinner\" style=\"position: relative;\">\n <div class=\"rect1\"></div>\n <div class=\"rect2\"></div>\n <div class=\"rect3\"></div>\n <div class=\"rect4\"></div>\n <div class=\"rect5\"></div>\n </div>\n</div>\n\n<c8y-dashboard\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n #dashboard\n *ngIf=\"!settings.isLoading\"\n>\n <c8y-dashboard-child\n *ngFor=\"let widget of widgets\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || settings.defaultWidth\"\n [height]=\"widget._height || settings.defaultHeight\"\n [margin]=\"settings.widgetMargin\"\n [isFrozen]=\"settings.isFrozen || settings.isDisabled\"\n [class]=\"widget.classes\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n (changeStart)=\"onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n #child\n >\n <c8y-dashboard-child-title>\n <span *ngIf=\"settings.translateWidgetTitle\"> {{ widget.title | translate }}</span>\n <span *ngIf=\"!settings.translateWidgetTitle\">\n {{ widget.title }}\n </span>\n </c8y-dashboard-child-title>\n <c8y-dashboard-child-action *ngIf=\"onEditWidget.observers.length\">\n <button (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\">\n <i c8yIcon=\"pencil\"></i>&nbsp;<span translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dashboard-child-action *ngIf=\"onDeleteWidget.observers.length\">\n <button\n (click)=\"onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"trash\"></i>&nbsp;<span translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n *ngIf=\"child.intersected\"\n ></c8y-dynamic-component>\n </c8y-dashboard-child>\n</c8y-dashboard>\n",
13602
13843
  host: {
13603
13844
  style: `
13604
13845
  display: block;
@@ -14580,5 +14821,5 @@ class CustomDeviceGridColumn extends BaseDeviceGridColumn {
14580
14821
  * Generated bundle index. Do not edit.
14581
14822
  */
14582
14823
 
14583
- export { ActionBarService, ActionService, AlarmsDeviceGridColumn, AlertService, AppStateService, AuthenticationModule, BaseDeviceGridColumn, BootstrapComponent, BreadcrumbService, C8yStepper, C8yStepperButtons, CachedLocaleDictionaryService, CellRendererContext, CellRendererDefDirective, CommonModule, ConfirmModalComponent, ContextRouteComponent, CoreModule, CustomDeviceGridColumn, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DefaultValidationDirective, DeviceGridComponent, DeviceGridModule, DeviceGridService, DeviceStatusComponent, DeviceStatusModule, DocsModule, DocsService, DropAreaComponent, DropAreaModule, DynamicComponentComponent, DynamicComponentModule, DynamicComponentService, EmptyComponent, FilteringActionType, FormGroupComponent, FormsModule, GroupDeviceGridColumn, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENT, HOOK_COMPONENTS, HOOK_DOCS, HOOK_NAVIGATOR_NODES, HOOK_ONCE_ROUTE, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_SEARCH, HOOK_TABS, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HighlightComponent, HumanizeAppNamePipe, HumanizePipe, ICON_LIST, ImeiDeviceGridColumn, InputGroupListComponent, JsonValidationPrettifierDirective, ListGroupComponent, ListGroupModule, LoginService, LoginViews, MaxValidationDirective, MessageDirective, MessagesComponent, MinValidationDirective, ModalModule, ModalService, ModelDeviceGridColumn, NameDeviceGridColumn, NavigatorIconComponent, NavigatorItemComponent, NavigatorNode, NavigatorNodeRoot, NavigatorService, NewPasswordComponent, OptionsService, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, Permissions, PhoneValidationDirective, PopoverConfirmComponent, ProvidePhoneNumberComponent, PushStatusLabels, QuickLinkModule, RegistrationDateDeviceGridColumn, RouterModule, RouterService, SchemaFormComponent, SearchModule, SearchService, SelectComponent, SelectModule, SendStatusLabels, SerialNumberDeviceGridColumn, SmsChallengeComponent, StateService, Status, StatusDeviceGridColumn, StepperModule, SystemIdDeviceGridColumn, TabsService, TextAreaRowHeightDirective, TitleComponent, TotpChallengeComponent, TotpSetupComponent, TranslateService, TypeaheadComponent, UserMenuService, UserTotpRevokeComponent, ValidationPattern, ViewContext, WidgetsDashboardComponent, _, deviceAvailabilityIconMap, fromFactories, fromTrigger, getActivatedRoute, gettext, initializeServices, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, ratiosByColumnTypes, resolveInjectedFactories, routes, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, tooltips, ɵ0, ApplicationOptions as ɵa, translateLoaderFactory as ɵb, ActionOutletComponent as ɵba, ActionComponent as ɵbb, AlertModule as ɵbc, AlertOutletComponent as ɵbd, AlertComponent as ɵbe, AlertDetailsComponent as ɵbf, AlertTextComponent as ɵbg, BootstrapModule as ɵbh, CookieBannerComponent as ɵbi, TitleOutletComponent as ɵbj, AppIconComponent as ɵbk, AppSwitcherComponent as ɵbl, RightDrawerComponent as ɵbm, UserModule as ɵbn, UserMenuOutletComponent as ɵbo, UserEditComponent as ɵbp, UserEditModalComponent as ɵbq, UserMenuItemComponent as ɵbr, UserTotpSetupComponent as ɵbs, InputGroupListContainerDirective as ɵbt, RequiredInputPlaceholderDirective as ɵbu, IpRangeInputListComponent as ɵbv, FilterInputComponent as ɵbw, ModalComponent as ɵbx, SearchOutletComponent as ɵby, SearchComponent as ɵbz, localePathFactory as ɵc, BreadcrumbModule as ɵca, BreadcrumbComponent as ɵcb, BreadcrumbItemComponent as ɵcc, BreadcrumbOutletComponent as ɵcd, NavigatorModule as ɵce, NavigatorOutletComponent as ɵcf, NavigatorNodeComponent as ɵcg, LoginModule as ɵch, LoginComponent as ɵci, RecoverPasswordComponent as ɵcj, ChangePasswordComponent as ɵck, CredentialsComponent as ɵcl, TotpAuthComponent as ɵcm, TabsModule as ɵcn, TabsOutletComponent as ɵco, TabComponent as ɵcp, CellRendererComponent as ɵcq, FilteringFormRendererDefDirective as ɵcr, FilteringFormRendererComponent as ɵcs, ColumnDirective as ɵct, FilteringFormComponent as ɵcu, StatusCellRendererComponent as ɵcv, NameCellRendererComponent as ɵcw, ModelCellRendererComponent as ɵcx, SerialNumberCellRendererComponent as ɵcy, GroupCellRendererComponent as ɵcz, languagesFactory as ɵd, RegistrationDateCellRendererComponent as ɵda, AlarmsCellRendererComponent as ɵdb, ListItemComponent as ɵdc, ListItemFooterComponent as ɵdd, ListItemActionComponent as ɵde, ListItemCollapseComponent as ɵdf, ListItemIconComponent as ɵdg, ListItemBodyComponent as ɵdh, ListItemCheckboxComponent as ɵdi, ListItemRadioComponent as ɵdj, C8yStepperIcon as ɵdk, C8yStepperProgress as ɵdl, RouterTabsResolver as ɵdn, ContextRouteGuard as ɵdo, QuickLinkComponent as ɵdp, localeId as ɵe, I18nModule as ɵf, MESSAGES as ɵg, LOCALE_PATH as ɵh, LANGUAGES as ɵi, TranslateCustomLoader as ɵj, TranslateParserCustom as ɵk, MissingTranslationCustomHandler as ɵl, PatternMessagesService as ɵm, IconDirective as ɵn, ICONS as ɵo, OutletDirective as ɵp, ShortenUserNamePipe as ɵq, ForOfDirective as ɵr, LoadMoreComponent as ɵs, MapFunctionPipe as ɵt, ProgressBarComponent as ɵu, UserPreferencesService as ɵv, ActionBarModule as ɵw, ActionBarComponent as ɵx, ActionBarItemComponent as ɵy, ActionModule as ɵz };
14824
+ export { ActionBarService, ActionService, AlarmsDeviceGridColumn, AlertService, AppStateService, AuthenticationModule, BaseDeviceGridColumn, BootstrapComponent, BreadcrumbService, C8yStepper, C8yStepperButtons, CachedLocaleDictionaryService, CellRendererContext, CellRendererDefDirective, CommonModule, ConfirmModalComponent, ContextRouteComponent, CoreModule, CustomDeviceGridColumn, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DefaultValidationDirective, DeviceGridComponent, DeviceGridModule, DeviceGridService, DeviceStatusComponent, DeviceStatusModule, DocsModule, DocsService, DropAreaComponent, DropAreaModule, DynamicComponentComponent, DynamicComponentModule, DynamicComponentService, EmptyComponent, FilteringActionType, FormGroupComponent, FormsModule, GroupDeviceGridColumn, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENT, HOOK_COMPONENTS, HOOK_DOCS, HOOK_NAVIGATOR_NODES, HOOK_ONCE_ROUTE, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_SEARCH, HOOK_TABS, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HighlightComponent, HumanizeAppNamePipe, HumanizePipe, ICON_LIST, ImeiDeviceGridColumn, InputGroupListComponent, JsonValidationPrettifierDirective, ListGroupComponent, ListGroupModule, LoginService, LoginViews, MaxValidationDirective, MessageDirective, MessagesComponent, MinValidationDirective, ModalModule, ModalService, ModelDeviceGridColumn, NameDeviceGridColumn, NavigatorIconComponent, NavigatorItemComponent, NavigatorNode, NavigatorNodeRoot, NavigatorService, NewPasswordComponent, OptionsService, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, Permissions, PhoneValidationDirective, PopoverConfirmComponent, ProvidePhoneNumberComponent, PushStatusLabels, QuickLinkModule, RegistrationDateDeviceGridColumn, RouterModule, RouterService, SchemaFormComponent, SearchModule, SearchService, SelectComponent, SelectModule, SendStatusLabels, SerialNumberDeviceGridColumn, SmsChallengeComponent, StateService, Status, StatusDeviceGridColumn, StepperModule, SystemIdDeviceGridColumn, TabsService, TextAreaRowHeightDirective, TitleComponent, TotpChallengeComponent, TotpSetupComponent, TranslateService, TypeaheadComponent, UserMenuService, UserTotpRevokeComponent, ValidationPattern, ViewContext, WidgetsDashboardComponent, _, deviceAvailabilityIconMap, fromFactories, fromTrigger, getActivatedRoute, gettext, initializeServices, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, ratiosByColumnTypes, resolveInjectedFactories, routes, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, tooltips, ɵ0, ApplicationOptions as ɵa, translateLoaderFactory as ɵb, ActionModule as ɵba, ActionOutletComponent as ɵbb, ActionComponent as ɵbc, AlertModule as ɵbd, AlertOutletComponent as ɵbe, AlertComponent as ɵbf, AlertDetailsComponent as ɵbg, AlertTextComponent as ɵbh, BootstrapModule as ɵbi, CookieBannerComponent as ɵbj, TitleOutletComponent as ɵbk, AppIconComponent as ɵbl, AppSwitcherComponent as ɵbm, RightDrawerComponent as ɵbn, UserModule as ɵbo, UserMenuOutletComponent as ɵbp, UserEditComponent as ɵbq, UserEditModalComponent as ɵbr, UserMenuItemComponent as ɵbs, UserTotpSetupComponent as ɵbt, InputGroupListContainerDirective as ɵbu, RequiredInputPlaceholderDirective as ɵbv, IpRangeInputListComponent as ɵbw, FilterInputComponent as ɵbx, ModalComponent as ɵby, SearchOutletComponent as ɵbz, localePathFactory as ɵc, SearchComponent as ɵca, BreadcrumbModule as ɵcb, BreadcrumbComponent as ɵcc, BreadcrumbItemComponent as ɵcd, BreadcrumbOutletComponent as ɵce, NavigatorModule as ɵcf, NavigatorOutletComponent as ɵcg, NavigatorNodeComponent as ɵch, LoginModule as ɵci, LoginComponent as ɵcj, RecoverPasswordComponent as ɵck, ChangePasswordComponent as ɵcl, CredentialsComponent as ɵcm, TotpAuthComponent as ɵcn, PasswordStrengthValidatorDirective as ɵco, StrengthValidatorService as ɵcp, TabsModule as ɵcq, TabsOutletComponent as ɵcr, TabComponent as ɵcs, CellRendererComponent as ɵct, FilteringFormRendererDefDirective as ɵcu, FilteringFormRendererComponent as ɵcv, ColumnDirective as ɵcw, FilteringFormComponent as ɵcx, StatusCellRendererComponent as ɵcy, NameCellRendererComponent as ɵcz, languagesFactory as ɵd, ModelCellRendererComponent as ɵda, SerialNumberCellRendererComponent as ɵdb, GroupCellRendererComponent as ɵdc, RegistrationDateCellRendererComponent as ɵdd, AlarmsCellRendererComponent as ɵde, ListItemComponent as ɵdf, ListItemFooterComponent as ɵdg, ListItemActionComponent as ɵdh, ListItemCollapseComponent as ɵdi, ListItemIconComponent as ɵdj, ListItemBodyComponent as ɵdk, ListItemCheckboxComponent as ɵdl, ListItemRadioComponent as ɵdm, C8yStepperIcon as ɵdn, C8yStepperProgress as ɵdo, RouterTabsResolver as ɵdq, ContextRouteGuard as ɵdr, QuickLinkComponent as ɵds, localeId as ɵe, I18nModule as ɵf, ForceHtmlTranslateDirective as ɵg, MESSAGES as ɵh, LOCALE_PATH as ɵi, LANGUAGES as ɵj, TranslateCustomLoader as ɵk, TranslateParserCustom as ɵl, MissingTranslationCustomHandler as ɵm, PatternMessagesService as ɵn, IconDirective as ɵo, ICONS as ɵp, OutletDirective as ɵq, ShortenUserNamePipe as ɵr, ForOfDirective as ɵs, LoadMoreComponent as ɵt, MapFunctionPipe as ɵu, ProgressBarComponent as ɵv, UserPreferencesService as ɵw, ActionBarModule as ɵx, ActionBarComponent as ɵy, ActionBarItemComponent as ɵz };
14584
14825
  //# sourceMappingURL=c8y-ngx-components.js.map