@sumaris-net/ngx-components 1.3.2 → 1.3.6

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.
@@ -4138,7 +4138,7 @@
4138
4138
  this.translate = translate;
4139
4139
  this.errorI18nKeys = Object.assign(Object.assign({}, SharedValidators.I18N_ERROR_KEYS), errorI18nKeys);
4140
4140
  }
4141
- FormErrorTranslator.prototype.translateErrors = function (control, opts) {
4141
+ FormErrorTranslator.prototype.translateFormErrors = function (control, opts) {
4142
4142
  var _this = this;
4143
4143
  if (!control || !control.invalid)
4144
4144
  return '';
@@ -4167,6 +4167,31 @@
4167
4167
  return res + (res.length ? separator : '') + formError;
4168
4168
  }, "");
4169
4169
  };
4170
+ FormErrorTranslator.prototype.translateErrors = function (errors, opts) {
4171
+ var _this = this;
4172
+ var separator = opts && opts.separator || ', ';
4173
+ return errors && Object.keys(errors).reduce(function (res, path) {
4174
+ var pathErrors = errors[path];
4175
+ // Should be a control map of errors
4176
+ if (pathErrors) {
4177
+ // Try to convert the control path
4178
+ var i18nPath = _this.translateControlPath(path, opts);
4179
+ // OK, we have a field name: use it
4180
+ var columnErrors = Object.keys(pathErrors).map(function (errorKey) { return _this.translateError(errorKey, pathErrors[errorKey]); });
4181
+ if (isEmptyArray(columnErrors))
4182
+ return res;
4183
+ // Add separator
4184
+ if (res.length)
4185
+ res += separator;
4186
+ return res + i18nPath + ": " + columnErrors.join(separator);
4187
+ }
4188
+ // Or try as global form error
4189
+ var formError = _this.translateError(path, pathErrors);
4190
+ if (isNil(formError))
4191
+ return res;
4192
+ return res + (res.length ? separator : '') + formError;
4193
+ }, "");
4194
+ };
4170
4195
  FormErrorTranslator.prototype.translateControlPath = function (path, opts) {
4171
4196
  if (opts === null || opts === void 0 ? void 0 : opts.controlPathTranslator) {
4172
4197
  return opts === null || opts === void 0 ? void 0 : opts.controlPathTranslator.translateControlPath(path);
@@ -4241,7 +4266,7 @@
4241
4266
  };
4242
4267
  FormErrorTranslatePipe.prototype._updateValue = function (form, opts, status) {
4243
4268
  if (status === 'INVALID' || form.invalid) {
4244
- this.value = this.adapter.translateErrors(form, opts);
4269
+ this.value = this.adapter.translateFormErrors(form, opts);
4245
4270
  this._ref.markForCheck();
4246
4271
  }
4247
4272
  else if (this.value !== undefined) {
@@ -19578,7 +19603,7 @@
19578
19603
  AppForm.prototype.getFormError = function (form, opts) {
19579
19604
  if (!form || !this.errorTranslator)
19580
19605
  return undefined;
19581
- return this.errorTranslator.translateErrors(this.form, Object.assign({ controlPathTranslator: this }, opts));
19606
+ return this.errorTranslator.translateFormErrors(this.form, Object.assign({ controlPathTranslator: this }, opts));
19582
19607
  };
19583
19608
  AppForm.prototype.getI18nFieldName = function (path) {
19584
19609
  return (this.i18nFieldPrefix || '') + changeCaseToUnderscore(path).toUpperCase();
@@ -20557,37 +20582,41 @@
20557
20582
  case 0:
20558
20583
  if (this.saving)
20559
20584
  return [2 /*return*/];
20585
+ if (!!this.form.valid) return [3 /*break*/, 2];
20560
20586
  return [4 /*yield*/, AppFormUtils.waitWhilePending(this.form)];
20561
20587
  case 1:
20562
20588
  _a.sent();
20563
20589
  if (this.form.invalid) {
20564
20590
  AppFormUtils.logFormErrors(this.form);
20591
+ this.form.markAllAsTouched();
20565
20592
  return [2 /*return*/];
20566
20593
  }
20594
+ _a.label = 2;
20595
+ case 2:
20567
20596
  this.submitted = true;
20568
20597
  this.saving = true;
20569
20598
  this.error = undefined;
20570
20599
  newAccount = exports.Account.fromObject(Object.assign(Object.assign({}, (this.accountService.account.asObject())), (this.form.value)));
20571
20600
  console.debug('[account] Saving account...', newAccount);
20572
- _a.label = 2;
20573
- case 2:
20574
- _a.trys.push([2, 4, 5, 6]);
20601
+ _a.label = 3;
20602
+ case 3:
20603
+ _a.trys.push([3, 5, 6, 7]);
20575
20604
  this.disable();
20576
20605
  return [4 /*yield*/, this.accountService.save(newAccount)];
20577
- case 3:
20606
+ case 4:
20578
20607
  _a.sent();
20579
20608
  this.markAsPristine();
20580
- return [3 /*break*/, 6];
20581
- case 4:
20609
+ return [3 /*break*/, 7];
20610
+ case 5:
20582
20611
  err_2 = _a.sent();
20583
20612
  console.error(err_2);
20584
20613
  this.error = err_2 && err_2.message || err_2;
20585
- return [3 /*break*/, 6];
20586
- case 5:
20614
+ return [3 /*break*/, 7];
20615
+ case 6:
20587
20616
  this.saving = false;
20588
20617
  this.enable();
20589
20618
  return [7 /*endfinally*/];
20590
- case 6: return [2 /*return*/];
20619
+ case 7: return [2 /*return*/];
20591
20620
  }
20592
20621
  });
20593
20622
  });
@@ -21171,27 +21200,36 @@
21171
21200
  case 0:
21172
21201
  if (this.saving)
21173
21202
  return [2 /*return*/]; // Skip
21203
+ event === null || event === void 0 ? void 0 : event.preventDefault();
21174
21204
  // Remove all empty controls
21175
21205
  this.propertiesFormHelper.removeAllEmpty();
21176
- if (this.form.invalid && this.debug) {
21206
+ if (!!this.form.valid) return [3 /*break*/, 2];
21207
+ return [4 /*yield*/, AppFormUtils.waitWhilePending(this.form)];
21208
+ case 1:
21209
+ _a.sent();
21210
+ if (this.form.invalid) {
21177
21211
  AppFormUtils.logFormErrors(this.form);
21212
+ this.form.markAllAsTouched();
21213
+ return [2 /*return*/];
21178
21214
  }
21215
+ _a.label = 2;
21216
+ case 2:
21179
21217
  console.debug('[settings] Saving local settings...');
21180
21218
  this.saving = true;
21181
21219
  this.error = undefined;
21182
21220
  return [4 /*yield*/, this.getValue()];
21183
- case 1:
21221
+ case 3:
21184
21222
  data = _a.sent();
21185
21223
  peerChanged = this.form.get('peerUrl').dirty;
21186
21224
  // Clean page history, when peer changed
21187
21225
  if (peerChanged)
21188
21226
  data.pageHistory = [];
21189
- _a.label = 2;
21190
- case 2:
21191
- _a.trys.push([2, 4, 5, 6]);
21227
+ _a.label = 4;
21228
+ case 4:
21229
+ _a.trys.push([4, 6, 7, 8]);
21192
21230
  this.disable();
21193
21231
  return [4 /*yield*/, this.settings.apply(data)];
21194
- case 3:
21232
+ case 5:
21195
21233
  _a.sent();
21196
21234
  this.data = data;
21197
21235
  this.markAsPristine();
@@ -21201,19 +21239,19 @@
21201
21239
  this.network.peer = exports.Peer.parseUrl(data.peerUrl);
21202
21240
  }
21203
21241
  return [2 /*return*/, true];
21204
- case 4:
21242
+ case 6:
21205
21243
  err_1 = _a.sent();
21206
21244
  console.error(err_1);
21207
21245
  this.error = err_1 && err_1.message || err_1;
21208
21246
  return [2 /*return*/, false];
21209
- case 5:
21247
+ case 7:
21210
21248
  this.enable({ emitEvent: false });
21211
21249
  // Apply inheritance
21212
21250
  this.setAccountInheritance(data.accountInheritance, { emitEvent: false });
21213
21251
  this.saving = false;
21214
21252
  this.markForCheck();
21215
21253
  return [7 /*endfinally*/];
21216
- case 6: return [2 /*return*/];
21254
+ case 8: return [2 /*return*/];
21217
21255
  }
21218
21256
  });
21219
21257
  });
@@ -21308,7 +21346,7 @@
21308
21346
  _a.label = 3;
21309
21347
  case 3:
21310
21348
  // Back to home
21311
- return [2 /*return*/, this.router.navigateByUrl('/', { skipLocationChange: true })];
21349
+ return [2 /*return*/, this.router.navigateByUrl('/', { replaceUrl: true })]; // back to home
21312
21350
  }
21313
21351
  });
21314
21352
  });
@@ -21367,7 +21405,7 @@
21367
21405
  SettingsPage.decorators = [
21368
21406
  { type: i0.Component, args: [{
21369
21407
  selector: 'page-settings',
21370
- 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 <ion-spinner *ngIf=\"loading || saving\"></ion-spinner>\n\n <!-- options menu -->\n <ion-button [matMenuTriggerFor]=\"optionsMenu\">\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",
21408
+ 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",
21371
21409
  providers: [
21372
21410
  { provide: ngxMaterialTable.ValidatorService, useExisting: LocalSettingsValidatorService },
21373
21411
  ],
@@ -25479,7 +25517,7 @@
25479
25517
  row = row || this.editedRow;
25480
25518
  if (!row || !this.formErrorAdapter)
25481
25519
  return undefined;
25482
- return this.formErrorAdapter.translateErrors(row.validator, Object.assign(Object.assign({}, this.errorTranslatorOptions), opts));
25520
+ return this.formErrorAdapter.translateFormErrors(row.validator, Object.assign(Object.assign({}, this.errorTranslatorOptions), opts));
25483
25521
  };
25484
25522
  AppTable.prototype.setError = function (value, opts) {
25485
25523
  if (this.errorSubject.value !== value) {
@@ -26404,7 +26442,7 @@
26404
26442
  enableListenChanges: (injector.get(ENVIRONMENT).listenRemoteChanges === true), pathIdAttribute: 'id', autoLoad: true, autoUpdateRoute: true, i18nPrefix: ''
26405
26443
  }, options);
26406
26444
  _this.settings = injector.get(LocalSettingsService);
26407
- _this.formErrorAdapter = injector.get(FormErrorTranslator);
26445
+ _this.errorTranslator = injector.get(FormErrorTranslator);
26408
26446
  _this.cd = injector.get(i0.ChangeDetectorRef);
26409
26447
  _this.dateFormat = injector.get(DateFormatPipe);
26410
26448
  _this.toastController = injector.get(i1$5.ToastController);
@@ -26966,7 +27004,7 @@
26966
27004
  var userMessage = err && err.message && this.translate.instant(err.message) || err;
26967
27005
  // Add details error (if any) under the main message
26968
27006
  var detailMessage = err && err.details && (err.details.message || err.details) || undefined;
26969
- if (detailMessage) {
27007
+ if (isNotNilString(detailMessage)) {
26970
27008
  userMessage += "<br/><small class=\"hidden-xs hidden-sm\" title=\"" + detailMessage + "\">";
26971
27009
  userMessage += detailMessage.length < 70 ? detailMessage : detailMessage.substring(0, 67) + '...';
26972
27010
  userMessage += '</small>';