@sumaris-net/ngx-components 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1266,7 +1266,6 @@
1266
1266
  this.debounceTime = null;
1267
1267
  this.i18nPrefix = 'REFERENTIAL.';
1268
1268
  this.noResultMessage = 'COMMON.NO_RESULT';
1269
- this.matAutocompletePosition = 'auto';
1270
1269
  this.multiple = false;
1271
1270
  this.itemSize = '48px';
1272
1271
  this.fetchMoreThreshold = '15%';
@@ -1433,6 +1432,7 @@
1433
1432
  this.debounceTime = toNumber(this.debounceTime, 250);
1434
1433
  this.highlightAccent = toBoolean(this.highlightAccent, false);
1435
1434
  this.suggestLengthThreshold = this.suggestLengthThreshold || 0;
1435
+ this.matAutocompletePosition = this.matAutocompletePosition || (this.mobile && this.searchable ? 'above' : 'auto'); // On mobile, set position to above (because of bottom keyboard)
1436
1436
  // No suggestFn: filter on the given items
1437
1437
  if (!this.suggestFn) {
1438
1438
  var suggestFromArrayFn_1 = function (value, filter) { return __awaiter(_this, void 0, void 0, function () {
@@ -19639,6 +19639,9 @@
19639
19639
  AppForm.prototype.registerSubscription = function (sub) {
19640
19640
  return this._subscription.add(sub);
19641
19641
  };
19642
+ AppForm.prototype.unregisterSubscription = function (sub) {
19643
+ this._subscription.remove(sub);
19644
+ };
19642
19645
  AppForm.prototype.registerAutocompleteField = function (fieldName, opts) {
19643
19646
  return this.autocompleteHelper.add(fieldName, opts);
19644
19647
  };
@@ -20476,13 +20479,14 @@
20476
20479
  { type: AccountService }
20477
20480
  ]; };
20478
20481
 
20479
- var AccountPage = /** @class */ (function (_super) {
20480
- __extends(AccountPage, _super);
20481
- function AccountPage(injector, router, formBuilder, accountService, validatorService, settingsValidatorService, translate, settings, cd, locales) {
20482
- var _this = _super.call(this, injector, validatorService.getFormGroup(accountService.account)) || this;
20483
- _this.router = router;
20482
+ var AccountPage = /** @class */ (function (_super_1) {
20483
+ __extends(AccountPage, _super_1);
20484
+ function AccountPage(injector, formBuilder, accountService, network, router, validatorService, settingsValidatorService, translate, settings, cd, locales) {
20485
+ var _this = _super_1.call(this, injector, validatorService.getFormGroup(accountService.account)) || this;
20484
20486
  _this.formBuilder = formBuilder;
20485
20487
  _this.accountService = accountService;
20488
+ _this.network = network;
20489
+ _this.router = router;
20486
20490
  _this.validatorService = validatorService;
20487
20491
  _this.settingsValidatorService = settingsValidatorService;
20488
20492
  _this.translate = translate;
@@ -20523,21 +20527,38 @@
20523
20527
  return _this;
20524
20528
  }
20525
20529
  AccountPage.prototype.ngOnDestroy = function () {
20526
- _super.prototype.ngOnDestroy.call(this);
20530
+ var _a;
20531
+ _super_1.prototype.ngOnDestroy.call(this);
20527
20532
  this.stopListenChanges();
20533
+ (_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
20528
20534
  };
20529
20535
  AccountPage.prototype.onLogin = function (account) {
20536
+ var _this = this;
20537
+ var _a;
20530
20538
  console.debug('[account] Logged account: ', account);
20531
20539
  this.isLogin = true;
20532
20540
  this.setValue(account);
20533
20541
  this.email.confirmed = account && account.email && (account.statusId !== StatusIds.TEMPORARY);
20534
20542
  this.email.notConfirmed = account && account.email && (!account.statusId || account.statusId === StatusIds.TEMPORARY);
20535
- this.enable();
20536
- this.markAsPristine();
20537
- this.startListenChanges();
20538
- this.markAsLoaded();
20543
+ (_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
20544
+ this.networkSubscription = this.network.onNetworkStatusChanges
20545
+ .pipe(operators.map(function (connectionType) { return connectionType !== 'none'; }))
20546
+ .subscribe(function (online) {
20547
+ if (online) {
20548
+ _this.enable();
20549
+ _this.markAsPristine();
20550
+ _this.startListenChanges();
20551
+ }
20552
+ else {
20553
+ _this.disable();
20554
+ _this.markAsPristine();
20555
+ _this.stopListenChanges();
20556
+ }
20557
+ _this.markAsLoaded();
20558
+ });
20539
20559
  };
20540
20560
  AccountPage.prototype.onLogout = function () {
20561
+ var _a;
20541
20562
  this.isLogin = false;
20542
20563
  this.email.confirmed = false;
20543
20564
  this.email.notConfirmed = false;
@@ -20545,13 +20566,14 @@
20545
20566
  this.email.error = undefined;
20546
20567
  this.form.reset();
20547
20568
  this.disable();
20569
+ (_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
20548
20570
  this.stopListenChanges();
20549
20571
  // Back to home
20550
20572
  this.router.navigateByUrl('/');
20551
20573
  };
20552
20574
  AccountPage.prototype.refresh = function (event) {
20553
20575
  return __awaiter(this, void 0, void 0, function () {
20554
- return __generator(this, function (_a) {
20576
+ return __generator(this, function (_b) {
20555
20577
  this.disable();
20556
20578
  this.markAsLoading();
20557
20579
  return [2 /*return*/, this.accountService.refresh()];
@@ -20572,8 +20594,8 @@
20572
20594
  AccountPage.prototype.sendConfirmationEmail = function (event) {
20573
20595
  return __awaiter(this, void 0, void 0, function () {
20574
20596
  var json, err_1;
20575
- return __generator(this, function (_a) {
20576
- switch (_a.label) {
20597
+ return __generator(this, function (_b) {
20598
+ switch (_b.label) {
20577
20599
  case 0:
20578
20600
  json = this.form.value;
20579
20601
  json.email = this.form.controls['email'].value;
@@ -20583,17 +20605,17 @@
20583
20605
  }
20584
20606
  this.email.sending = true;
20585
20607
  console.debug('[account] Sending confirmation email...');
20586
- _a.label = 1;
20608
+ _b.label = 1;
20587
20609
  case 1:
20588
- _a.trys.push([1, 3, , 4]);
20610
+ _b.trys.push([1, 3, , 4]);
20589
20611
  return [4 /*yield*/, this.accountService.sendConfirmationEmail(json.email, json.settings && json.settings.locale || this.translate.currentLang)];
20590
20612
  case 2:
20591
- _a.sent();
20613
+ _b.sent();
20592
20614
  console.debug('[account] Confirmation email sent.');
20593
20615
  this.email.sending = false;
20594
20616
  return [3 /*break*/, 4];
20595
20617
  case 3:
20596
- err_1 = _a.sent();
20618
+ err_1 = _b.sent();
20597
20619
  this.email.sending = false;
20598
20620
  this.email.error = err_1 && err_1.message || err_1;
20599
20621
  return [3 /*break*/, 4];
@@ -20605,41 +20627,41 @@
20605
20627
  AccountPage.prototype.save = function (event) {
20606
20628
  return __awaiter(this, void 0, void 0, function () {
20607
20629
  var newAccount, err_2;
20608
- return __generator(this, function (_a) {
20609
- switch (_a.label) {
20630
+ return __generator(this, function (_b) {
20631
+ switch (_b.label) {
20610
20632
  case 0:
20611
20633
  if (this.saving)
20612
- return [2 /*return*/];
20634
+ return [2 /*return*/, false];
20613
20635
  if (!!this.form.valid) return [3 /*break*/, 2];
20614
20636
  return [4 /*yield*/, AppFormUtils.waitWhilePending(this.form)];
20615
20637
  case 1:
20616
- _a.sent();
20638
+ _b.sent();
20617
20639
  if (this.form.invalid) {
20618
20640
  AppFormUtils.logFormErrors(this.form);
20619
20641
  this.form.markAllAsTouched();
20620
- return [2 /*return*/];
20642
+ return [2 /*return*/, false];
20621
20643
  }
20622
- _a.label = 2;
20644
+ _b.label = 2;
20623
20645
  case 2:
20624
20646
  this.submitted = true;
20625
20647
  this.saving = true;
20626
20648
  this.error = undefined;
20627
20649
  newAccount = exports.Account.fromObject(Object.assign(Object.assign({}, (this.accountService.account.asObject())), (this.form.value)));
20628
20650
  console.debug('[account] Saving account...', newAccount);
20629
- _a.label = 3;
20651
+ _b.label = 3;
20630
20652
  case 3:
20631
- _a.trys.push([3, 5, 6, 7]);
20653
+ _b.trys.push([3, 5, 6, 7]);
20632
20654
  this.disable();
20633
20655
  return [4 /*yield*/, this.accountService.save(newAccount)];
20634
20656
  case 4:
20635
- _a.sent();
20657
+ _b.sent();
20636
20658
  this.markAsPristine();
20637
- return [3 /*break*/, 7];
20659
+ return [2 /*return*/, true];
20638
20660
  case 5:
20639
- err_2 = _a.sent();
20661
+ err_2 = _b.sent();
20640
20662
  console.error(err_2);
20641
20663
  this.error = err_2 && err_2.message || err_2;
20642
- return [3 /*break*/, 7];
20664
+ return [2 /*return*/, false];
20643
20665
  case 6:
20644
20666
  this.saving = false;
20645
20667
  this.enable();
@@ -20651,7 +20673,7 @@
20651
20673
  };
20652
20674
  AccountPage.prototype.enable = function () {
20653
20675
  var _this = this;
20654
- _super.prototype.enable.call(this);
20676
+ _super_1.prototype.enable.call(this);
20655
20677
  // Some fields are always disable
20656
20678
  this.form.controls.email.disable();
20657
20679
  this.form.controls.mainProfile.disable();
@@ -20664,6 +20686,17 @@
20664
20686
  });
20665
20687
  this.markForCheck();
20666
20688
  };
20689
+ AccountPage.prototype.cancel = function () {
20690
+ var _super = Object.create(null, {
20691
+ cancel: { get: function () { return _super_1.prototype.cancel; } }
20692
+ });
20693
+ return __awaiter(this, void 0, void 0, function () {
20694
+ return __generator(this, function (_b) {
20695
+ _super.cancel.call(this);
20696
+ return [2 /*return*/];
20697
+ });
20698
+ });
20699
+ };
20667
20700
  AccountPage.prototype.markForCheck = function () {
20668
20701
  this.cd.markForCheck();
20669
20702
  };
@@ -20672,16 +20705,17 @@
20672
20705
  AccountPage.decorators = [
20673
20706
  { type: i0.Component, args: [{
20674
20707
  selector: 'app-page-account',
20675
- template: "<app-toolbar [title]=\"'ACCOUNT.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"form.dirty && !saving\"\n (onValidate)=\"save($event)\"\n [canGoBack]=\"false\">\n\n <ion-buttons slot=\"end\">\n <!-- loader -->\n <ion-spinner *ngIf=\"loading || saving; else endButtons\"></ion-spinner>\n\n <ng-template #endButtons>\n <!-- refresh button -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH'|translate\"\n (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n\n <mat-tab-group>\n\n <!-- TAB: user details -->\n <mat-tab label=\"{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;</ion-col>\n\n <ion-col class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION'|translate\"></p>\n\n <!--h1>Identit\u00E9</h1-->\n\n <!-- Email -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.EMAIL'|translate\"\n formControlName=\"email\" autocomplete=\"section-red email\">\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n\n <ion-grid *ngIf=\"email.notConfirmed\" class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\" color=\"danger\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL'|translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px;\">\n <ion-col style=\"text-align: right;\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION'|translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"secondary\" *ngIf=\"!email.sending\" (click)=\"sendConfirmationEmail($event)\">\n {{'ACCOUNT.BTN_RESEND'|translate}}\n </ion-button>\n <ion-spinner class=\"ion-no-padding\" *ngIf=\"email.sending\"></ion-spinner>\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error|translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Last name -->\n <mat-form-field>\n <input matInput [appAutofocus]=\"true\" [autofocusDelay]=\"500\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required>\n <mat-error *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.FIRST_NAME'|translate\" formControlName=\"firstName\" autocomplete=\"section-blue given-name\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n\n <!-- Additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\">\n <app-form-field [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"definition.extra && definition.extra.account && definition.extra.account.required || false\">\n </app-form-field>\n </ng-container>\n\n <h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3>\n\n <!-- profile -->\n <mat-form-field>\n <input matInput hidden readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PROFILE'|translate\"\n formControlName=\"mainProfile\" required>\n <span>{{'USER.PROFILE_ENUM.'+form.controls.mainProfile.value | translate}}</span>\n <mat-error *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- pubkey -->\n <mat-form-field>\n <input matInput readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PUBKEY'|translate\" formControlName=\"pubkey\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;</ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab label=\"{{'ACCOUNT.SETTINGS.TITLE'|translate}}\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;\n </ion-col>\n\n <ion-col class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION'|translate\"></p>\n\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm.controls.locale.hasError('required') && settingsForm.controls.locale.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.'+item+'_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm.controls.latLongFormat.hasError('required') && settingsForm.controls.latLongFormat.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <form formGroupName=\"content\">\n\n\n </form>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;\n </ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n </mat-tab-group>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || saving\"></app-form-buttons-bar>\n</ion-footer>\n",
20708
+ template: "<app-toolbar [title]=\"'ACCOUNT.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"form.dirty && !saving\"\n (onValidate)=\"save($event)\"\n [canGoBack]=\"false\">\n\n <ion-buttons slot=\"end\">\n <!-- loader -->\n <ion-spinner *ngIf=\"loading || saving; else endButtons\"></ion-spinner>\n\n <ng-template #endButtons>\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH'|translate\"\n *ngIf=\"network.online\"\n (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n\n <mat-tab-group>\n\n <!-- TAB: user details -->\n <mat-tab label=\"{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{'ACCOUNT.USER_DETAILS.TITLE'|translate}}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;</ion-col>\n\n <ion-col class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION'|translate\"></p>\n\n <!--h1>Identit\u00E9</h1-->\n\n <!-- Email -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.EMAIL'|translate\"\n formControlName=\"email\" autocomplete=\"section-red email\">\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n\n <ion-grid *ngIf=\"email.notConfirmed\" class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\" color=\"danger\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL'|translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px;\">\n <ion-col style=\"text-align: right;\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION'|translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"secondary\" *ngIf=\"!email.sending\" (click)=\"sendConfirmationEmail($event)\">\n {{'ACCOUNT.BTN_RESEND'|translate}}\n </ion-button>\n <ion-spinner class=\"ion-no-padding\" *ngIf=\"email.sending\"></ion-spinner>\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error|translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Last name -->\n <mat-form-field>\n <input matInput [appAutofocus]=\"true\" [autofocusDelay]=\"500\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required>\n <mat-error *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n <!-- First name -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.FIRST_NAME'|translate\" formControlName=\"firstName\" autocomplete=\"section-blue given-name\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n\n <!-- Additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\">\n <app-form-field [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"definition.extra && definition.extra.account && definition.extra.account.required || false\">\n </app-form-field>\n </ng-container>\n\n <h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3>\n\n <!-- profile -->\n <mat-form-field>\n <input matInput hidden readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PROFILE'|translate\"\n formControlName=\"mainProfile\" required>\n <span>{{'USER.PROFILE_ENUM.'+form.controls.mainProfile.value | translate}}</span>\n <mat-error *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- pubkey -->\n <mat-form-field>\n <input matInput readonly=\"true\" [placeholder]=\"'ACCOUNT.USER_DETAILS.PUBKEY'|translate\" formControlName=\"pubkey\"\n required>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;</ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab label=\"{{'ACCOUNT.SETTINGS.TITLE'|translate}}\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;\n </ion-col>\n\n <ion-col class=\"ion-padding\">\n\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION'|translate\"></p>\n\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm.controls.locale.hasError('required') && settingsForm.controls.locale.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'ACCOUNT.SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.'+item+'_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"settingsForm.controls.latLongFormat.hasError('required') && settingsForm.controls.latLongFormat.dirty\"\n translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <form formGroupName=\"content\">\n\n\n </form>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"3\">&nbsp;\n </ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n </mat-tab-group>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || saving\"></app-form-buttons-bar>\n</ion-footer>\n",
20676
20709
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
20677
20710
  styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form,form mat-form-field{width:100%}"]
20678
20711
  },] }
20679
20712
  ];
20680
20713
  AccountPage.ctorParameters = function () { return [
20681
20714
  { type: i0.Injector },
20682
- { type: i3.Router },
20683
20715
  { type: i1.FormBuilder },
20684
20716
  { type: AccountService },
20717
+ { type: NetworkService },
20718
+ { type: i3.Router },
20685
20719
  { type: AccountValidatorService },
20686
20720
  { type: UserSettingsValidatorService },
20687
20721
  { type: i1$2.TranslateService },
@@ -21229,6 +21263,7 @@
21229
21263
  if (this.saving)
21230
21264
  return [2 /*return*/]; // Skip
21231
21265
  event === null || event === void 0 ? void 0 : event.preventDefault();
21266
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
21232
21267
  // Remove all empty controls
21233
21268
  this.propertiesFormHelper.removeAllEmpty();
21234
21269
  if (!!this.form.valid) return [3 /*break*/, 2];
@@ -21433,7 +21468,7 @@
21433
21468
  SettingsPage.decorators = [
21434
21469
  { type: i0.Component, args: [{
21435
21470
  selector: 'page-settings',
21436
- template: "<app-toolbar [title]=\"'SETTINGS.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"form.dirty && !saving\"\n [hasClose]=\"!form.dirty && !saving\"\n (onValidate)=\"save($event)\"\n (onClose)=\"close($event)\">\n\n <ion-buttons slot=\"end\">\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\" [disabled]=\"saving\">\n <mat-icon slot=\"icon-only\">more_vert</mat-icon>\n </ion-button>\n </ion-buttons>\n</app-toolbar>\n\n<!-- Options menu -->\n<mat-menu #optionsMenu=\"matMenu\">\n <!-- Clear cache -->\n <button mat-menu-item (click)=\"clearCache($event)\">\n <ion-label translate>SETTINGS.BTN_CLEAR_CACHE</ion-label>\n </button>\n\n <!-- Reset -->\n <button mat-menu-item\n [disabled]=\"!dirty\"\n (click)=\"cancel($event)\">\n <ion-label>\n <mat-icon><ion-icon slot=\"start\" name=\"refresh\"></ion-icon></mat-icon>&nbsp;\n <span translate>COMMON.BTN_RESET</span>\n </ion-label>\n </button>\n</mat-menu>\n\n<ion-content>\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"2\">&nbsp;\n </ion-col>\n\n <ion-col class=\"ion-padding\">\n\n <!-- error -->\n <ion-item *ngIf=\"error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <p [innerHTML]=\"'SETTINGS.DESCRIPTION'|translate\"></p>\n\n <!-- account inheritance (desktop) -->\n <mat-form-field [hidden]=\"!isLogin\" *ngIf=\"!mobile; else accountInheritanceMobile\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\">\n\n <!-- check box (if desktop) -->\n <mat-checkbox\n *ngIf=\"!mobile; else accountInheritanceMobile\"\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\">\n <span translate>SETTINGS.INHERIT_FROM_ACCOUNT</span>\n </mat-checkbox>\n\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- account inheritance (if mobile) -->\n <ng-template #accountInheritanceMobile>\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\">\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.INHERIT_FROM_ACCOUNT</ion-text>\n <mat-slide-toggle matSuffix\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\">\n\n </mat-slide-toggle>\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ng-template>\n\n <!-- locale -->\n <mat-form-field>\n <mat-select [placeholder]=\"'SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.locale.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- Network entry -->\n <h3>\n <ion-text translate>SETTINGS.NETWORK_DIVIDER</ion-text>\n </h3>\n\n <!-- Peer address -->\n <mat-form-field>\n <input matInput type=\"text\" [placeholder]=\"'SETTINGS.PEER_URL'|translate\" formControlName=\"peerUrl\"\n required>\n\n <button mat-icon-button type=\"button\" matSuffix (click)=\"showSelectPeerModal()\" tabindex=\"-1\"\n [title]=\"'SETTINGS.BTN_CHANGE_PEER'|translate\">\n <mat-icon>search</mat-icon>\n </button>\n\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('required')\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerAlive')\"\n translate>SETTINGS.ERROR.PEER_NOT_REACHABLE\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerNotCompatible')\"\n translate>SETTINGS.ERROR.PEER_NOT_COMPATIBLE\n </mat-error>\n </mat-form-field>\n\n <!-- Offline mode (if mobile) -->\n <mat-form-field *ngIf=\"mobile\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\">\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.OFFLINE_MODE</ion-text>\n <mat-slide-toggle matSuffix\n (change)=\"network.setForceOffline($event.checked)\"\n [checked]=\"network.offline\">\n\n </mat-slide-toggle>\n </mat-form-field>\n\n <!-- Data entry -->\n <h3>\n <ion-text translate>SETTINGS.DATA_ENTRY_DIVIDER</ion-text>\n </h3>\n\n <!-- Usage mode -->\n <mat-form-field>\n <mat-select [placeholder]=\"'SETTINGS.USAGE_MODE'|translate\" formControlName=\"usageMode\"\n required>\n <mat-option *ngFor=\"let item of usageModes\" [value]=\"item\">\n {{'SETTINGS.USAGE_MODES.'+item|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.usageMode.hasError('required')\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.'+item+'_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error\n *ngIf=\"form.controls.latLongFormat.hasError('required')\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- fields options -->\n <ion-grid formArrayName=\"properties\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding ion-align-self-end\" size=\"12\">\n <span class=\"toolbar-spacer\"></span>\n\n <!-- Show more options -->\n <ion-button color=\"light\" *ngIf=\"propertiesForm?.length === 0\"\n [title]=\"'SETTINGS.BTN_SHOW_MORE_HELP'|translate\"\n (click)=\"propertiesFormHelper.add()\">\n <ion-label translate>COMMON.BTN_SHOW_MORE</ion-label>\n <mat-icon slot=\"end\">arrow_drop_down</mat-icon>\n </ion-button>\n </ion-col>\n </ion-row>\n\n <!-- Fields options -->\n <ng-container *ngFor=\"let propertyForm of propertiesForm?.controls; let i=index\">\n <ion-row class=\"ion-no-padding\" [formGroupName]=\"i\">\n\n <!-- property key -->\n <ion-col class=\"ion-no-padding\">\n <mat-form-field>\n <mat-select formControlName=\"key\"\n [placeholder]=\" 'SETTINGS.PROPERTY_KEY'|translate\">\n <mat-option *ngFor=\"let item of propertyDefinitions\" [value]=\"item.key\">{{ item.label | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n\n <!-- property value -->\n <ion-col class=\"ion-no-padding\" padding-left>\n <app-form-field *ngIf=\"getPropertyDefinition(i); let definition\"\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"propertyForm.controls.value\"\n [placeholder]=\"'SETTINGS.PROPERTY_VALUE' | translate\"\n [required]=\"true\">\n </app-form-field>\n </ion-col>\n <ion-col size=\"2\" class=\"ion-no-padding\">\n <button type=\"button\" mat-icon-button color=\"light\"\n [disabled]=\"loading\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n (click)=\"removePropertyAt(i)\">\n <mat-icon>close</mat-icon>\n </button>\n <button *ngIf=\"propertiesFormHelper.isLast(i)\"\n type=\"button\"\n mat-icon-button\n color=\"light\"\n [disabled]=\"loading\"\n [title]=\"'SETTINGS.BTN_ADD_PROPERTY'|translate\"\n (click)=\"propertiesFormHelper.add()\">\n <mat-icon>add</mat-icon>\n </button>\n </ion-col>\n </ion-row>\n </ng-container>\n </ion-grid>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"2\">&nbsp;\n </ion-col>\n </ion-row>\n </ion-grid>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || saving\"></app-form-buttons-bar>\n</ion-footer>\n",
21471
+ template: "<app-toolbar [title]=\"'SETTINGS.TITLE'|translate\" color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save($event)\"\n (onClose)=\"close($event)\">\n\n <ion-buttons slot=\"end\">\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\" [disabled]=\"saving\">\n <mat-icon slot=\"icon-only\">more_vert</mat-icon>\n </ion-button>\n </ion-buttons>\n</app-toolbar>\n\n<!-- Options menu -->\n<mat-menu #optionsMenu=\"matMenu\">\n <!-- Clear cache -->\n <button mat-menu-item (click)=\"clearCache($event)\">\n <ion-label translate>SETTINGS.BTN_CLEAR_CACHE</ion-label>\n </button>\n\n <!-- Reset -->\n <button mat-menu-item\n [disabled]=\"!dirty\"\n (click)=\"cancel($event)\">\n <ion-label>\n <mat-icon><ion-icon slot=\"start\" name=\"refresh\"></ion-icon></mat-icon>&nbsp;\n <span translate>COMMON.BTN_RESET</span>\n </ion-label>\n </button>\n</mat-menu>\n\n<ion-content>\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"save($event)\" class=\"form-container\">\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"2\">&nbsp;\n </ion-col>\n\n <ion-col class=\"ion-padding\">\n\n <!-- error -->\n <ion-item *ngIf=\"error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <p [innerHTML]=\"'SETTINGS.DESCRIPTION'|translate\"></p>\n\n <!-- account inheritance (desktop) -->\n <mat-form-field [hidden]=\"!isLogin\" *ngIf=\"!mobile; else accountInheritanceMobile\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\">\n\n <!-- check box (if desktop) -->\n <mat-checkbox\n *ngIf=\"!mobile; else accountInheritanceMobile\"\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\">\n <span translate>SETTINGS.INHERIT_FROM_ACCOUNT</span>\n </mat-checkbox>\n\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- account inheritance (if mobile) -->\n <ng-template #accountInheritanceMobile>\n <mat-form-field [hidden]=\"!isLogin\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\">\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.INHERIT_FROM_ACCOUNT</ion-text>\n <mat-slide-toggle matSuffix\n (change)=\"setAccountInheritance($event.checked)\"\n [checked]=\"accountInheritance\">\n\n </mat-slide-toggle>\n <mat-error *ngIf=\"form.controls.accountInheritance.hasError('required')\" translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ng-template>\n\n <!-- locale -->\n <mat-form-field>\n <mat-select [placeholder]=\"'SETTINGS.LOCALE'|translate\" formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{item.value}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.locale.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n\n <!-- Network entry -->\n <h3>\n <ion-text translate>SETTINGS.NETWORK_DIVIDER</ion-text>\n </h3>\n\n <!-- Peer address -->\n <mat-form-field>\n <input matInput type=\"text\" [placeholder]=\"'SETTINGS.PEER_URL'|translate\" formControlName=\"peerUrl\"\n required>\n\n <button mat-icon-button type=\"button\" matSuffix (click)=\"showSelectPeerModal()\" tabindex=\"-1\"\n [title]=\"'SETTINGS.BTN_CHANGE_PEER'|translate\">\n <mat-icon>search</mat-icon>\n </button>\n\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('required')\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerAlive')\"\n translate>SETTINGS.ERROR.PEER_NOT_REACHABLE\n </mat-error>\n <mat-error *ngIf=\"form.controls.peerUrl.hasError('peerNotCompatible')\"\n translate>SETTINGS.ERROR.PEER_NOT_COMPATIBLE\n </mat-error>\n </mat-form-field>\n\n <!-- Offline mode (if mobile) -->\n <mat-form-field *ngIf=\"mobile\">\n <input matInput hidden formControlName=\"accountInheritance\" type=\"text\">\n\n <!-- slide toggle -->\n <ion-text translate>SETTINGS.OFFLINE_MODE</ion-text>\n <mat-slide-toggle matSuffix\n (change)=\"network.setForceOffline($event.checked)\"\n [checked]=\"network.offline\">\n\n </mat-slide-toggle>\n </mat-form-field>\n\n <!-- Data entry -->\n <h3>\n <ion-text translate>SETTINGS.DATA_ENTRY_DIVIDER</ion-text>\n </h3>\n\n <!-- Usage mode -->\n <mat-form-field>\n <mat-select [placeholder]=\"'SETTINGS.USAGE_MODE'|translate\" formControlName=\"usageMode\"\n required>\n <mat-option *ngFor=\"let item of usageModes\" [value]=\"item\">\n {{'SETTINGS.USAGE_MODES.'+item|translate}}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"form.controls.usageMode.hasError('required')\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n <mat-form-field>\n <mat-select [placeholder]=\"'SETTINGS.LAT_LONG_FORMAT'|translate\" formControlName=\"latLongFormat\"\n required>\n <mat-option *ngFor=\"let item of latLongFormats\" [value]=\"item\">\n {{'COMMON.LAT_LONG.'+item+'_PLACEHOLDER'|translate}}\n </mat-option>\n </mat-select>\n <mat-error\n *ngIf=\"form.controls.latLongFormat.hasError('required')\"\n translate>ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- fields options -->\n <ion-grid formArrayName=\"properties\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding ion-align-self-end\" size=\"12\">\n <span class=\"toolbar-spacer\"></span>\n\n <!-- Show more options -->\n <ion-button color=\"light\" *ngIf=\"propertiesForm?.length === 0\"\n [title]=\"'SETTINGS.BTN_SHOW_MORE_HELP'|translate\"\n (click)=\"propertiesFormHelper.add()\">\n <ion-label translate>COMMON.BTN_SHOW_MORE</ion-label>\n <mat-icon slot=\"end\">arrow_drop_down</mat-icon>\n </ion-button>\n </ion-col>\n </ion-row>\n\n <!-- Fields options -->\n <ng-container *ngFor=\"let propertyForm of propertiesForm?.controls; let i=index\">\n <ion-row class=\"ion-no-padding\" [formGroupName]=\"i\">\n\n <!-- property key -->\n <ion-col class=\"ion-no-padding\">\n <mat-form-field>\n <mat-select formControlName=\"key\"\n [placeholder]=\" 'SETTINGS.PROPERTY_KEY'|translate\">\n <mat-option *ngFor=\"let item of propertyDefinitions\" [value]=\"item.key\">{{ item.label | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n\n <!-- property value -->\n <ion-col class=\"ion-no-padding\" padding-left>\n <app-form-field *ngIf=\"getPropertyDefinition(i); let definition\"\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"propertyForm.controls.value\"\n [placeholder]=\"'SETTINGS.PROPERTY_VALUE' | translate\"\n [required]=\"true\">\n </app-form-field>\n </ion-col>\n <ion-col size=\"2\" class=\"ion-no-padding\">\n <button type=\"button\" mat-icon-button color=\"light\"\n [disabled]=\"loading\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n (click)=\"removePropertyAt(i)\">\n <mat-icon>close</mat-icon>\n </button>\n <button *ngIf=\"propertiesFormHelper.isLast(i)\"\n type=\"button\"\n mat-icon-button\n color=\"light\"\n [disabled]=\"loading\"\n [title]=\"'SETTINGS.BTN_ADD_PROPERTY'|translate\"\n (click)=\"propertiesFormHelper.add()\">\n <mat-icon>add</mat-icon>\n </button>\n </ion-col>\n </ion-row>\n </ng-container>\n </ion-grid>\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"2\">&nbsp;\n </ion-col>\n </ion-row>\n </ion-grid>\n\n\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save($event)\" [disabled]=\"!form.dirty || saving\"></app-form-buttons-bar>\n</ion-footer>\n",
21437
21472
  providers: [
21438
21473
  { provide: ngxMaterialTable.ValidatorService, useExisting: LocalSettingsValidatorService },
21439
21474
  ],