@sumaris-net/ngx-components 1.4.7 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/sumaris-net.ngx-components.umd.js +94 -60
- package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
- package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
- package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
- package/doc/changelog.md +7 -0
- package/esm2015/src/app/core/account/account.js +42 -11
- package/esm2015/src/app/core/form/form.class.js +4 -1
- package/esm2015/src/app/core/services/local-settings.service.js +3 -3
- package/esm2015/src/app/core/settings/settings.page.js +10 -12
- package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +13 -5
- package/fesm2015/sumaris-net.ngx-components.js +65 -27
- package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
- package/package.json +1 -1
- package/src/app/core/account/account.d.ts +9 -4
- package/src/app/core/form/form.class.d.ts +1 -0
- package/src/app/core/settings/settings.page.d.ts +3 -3
- package/src/theme/_ngx-components.scss +7 -1
- package/sumaris-net.ngx-components.metadata.json +1 -1
|
@@ -982,7 +982,6 @@ class MatAutocompleteField {
|
|
|
982
982
|
this.debounceTime = null;
|
|
983
983
|
this.i18nPrefix = 'REFERENTIAL.';
|
|
984
984
|
this.noResultMessage = 'COMMON.NO_RESULT';
|
|
985
|
-
this.matAutocompletePosition = 'auto';
|
|
986
985
|
this.multiple = false;
|
|
987
986
|
this.itemSize = '48px';
|
|
988
987
|
this.fetchMoreThreshold = '15%';
|
|
@@ -1075,7 +1074,7 @@ class MatAutocompleteField {
|
|
|
1075
1074
|
this.displayWith = this.displayWith || this.config.displayWith;
|
|
1076
1075
|
this.mobile = toBoolean(this.mobile, this.config.mobile);
|
|
1077
1076
|
this.suggestLengthThreshold = toNumber(this.suggestLengthThreshold, this.config.suggestLengthThreshold || 0);
|
|
1078
|
-
this.showAllOnFocus = toBoolean(this.showAllOnFocus, toBoolean(this.config.showAllOnFocus, this.suggestLengthThreshold
|
|
1077
|
+
this.showAllOnFocus = toBoolean(this.showAllOnFocus, toBoolean(this.config.showAllOnFocus, this.suggestLengthThreshold <= 0));
|
|
1079
1078
|
this.showPanelOnFocus = toBoolean(this.showPanelOnFocus, toBoolean(this.config.showPanelOnFocus));
|
|
1080
1079
|
this.classList = this.classList || this.config.class;
|
|
1081
1080
|
this.debounceTime = toNumber(this.debounceTime, this.config.debounceTime);
|
|
@@ -1110,6 +1109,7 @@ class MatAutocompleteField {
|
|
|
1110
1109
|
this.debounceTime = toNumber(this.debounceTime, 250);
|
|
1111
1110
|
this.highlightAccent = toBoolean(this.highlightAccent, false);
|
|
1112
1111
|
this.suggestLengthThreshold = this.suggestLengthThreshold || 0;
|
|
1112
|
+
this.matAutocompletePosition = this.matAutocompletePosition || (this.mobile && this.searchable ? 'above' : 'auto'); // On mobile, set position to above (because of bottom keyboard)
|
|
1113
1113
|
// No suggestFn: filter on the given items
|
|
1114
1114
|
if (!this.suggestFn) {
|
|
1115
1115
|
const suggestFromArrayFn = (value, filter) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1183,8 +1183,16 @@ class MatAutocompleteField {
|
|
|
1183
1183
|
.pipe(filter(event => this.enabled && this.searchable && (!event || !event.defaultPrevented)), map(_ => this.showAllOnFocus ? '*' : this.formControl.value)), merge(this.$inputItems, this._filter$)
|
|
1184
1184
|
.pipe(filter(event => this.enabled && this.searchable), map(_ => this.formControl.value)))
|
|
1185
1185
|
.pipe(
|
|
1186
|
-
//
|
|
1187
|
-
|
|
1186
|
+
// Start to suggest when :
|
|
1187
|
+
// - '*'
|
|
1188
|
+
// - is nil, and there is no min length threshold
|
|
1189
|
+
// - is not nil and not a string type (e.g. object)
|
|
1190
|
+
// - is not nil and is a string, and has enough character
|
|
1191
|
+
filter(value => value === '*'
|
|
1192
|
+
|| (isNil(value)
|
|
1193
|
+
? (this.suggestLengthThreshold <= 0)
|
|
1194
|
+
: (!(typeof value === 'string')
|
|
1195
|
+
|| value.length >= this.suggestLengthThreshold))),
|
|
1188
1196
|
// Distinguish changes
|
|
1189
1197
|
distinctUntilChanged()))
|
|
1190
1198
|
.pipe(
|
|
@@ -9577,9 +9585,9 @@ class LocalSettingsService extends StartableService {
|
|
|
9577
9585
|
ngOnStart() {
|
|
9578
9586
|
console.info('[settings] Starting service...');
|
|
9579
9587
|
// Restoring local settings
|
|
9580
|
-
this._data.mobile =
|
|
9588
|
+
this._data.mobile = toBoolean(this._data.mobile, this.platform.is('mobile'));
|
|
9581
9589
|
this._data.touchUi = this._data.mobile || this.platform.is('phablet') || this.platform.is('tablet');
|
|
9582
|
-
this._data.usageMode = this.platform.is('android') ? 'FIELD' : 'DESK'; // FIELD by default if Android
|
|
9590
|
+
this._data.usageMode = this.platform.is('android') || this.platform.is('ios') ? 'FIELD' : 'DESK'; // FIELD by default if Android or iOs
|
|
9583
9591
|
// Restoring local settings
|
|
9584
9592
|
return this.restoreLocally();
|
|
9585
9593
|
}
|
|
@@ -17067,6 +17075,9 @@ class AppForm {
|
|
|
17067
17075
|
registerSubscription(sub) {
|
|
17068
17076
|
return this._subscription.add(sub);
|
|
17069
17077
|
}
|
|
17078
|
+
unregisterSubscription(sub) {
|
|
17079
|
+
this._subscription.remove(sub);
|
|
17080
|
+
}
|
|
17070
17081
|
registerAutocompleteField(fieldName, opts) {
|
|
17071
17082
|
return this.autocompleteHelper.add(fieldName, opts);
|
|
17072
17083
|
}
|
|
@@ -17785,11 +17796,12 @@ AccountValidatorService.ctorParameters = () => [
|
|
|
17785
17796
|
];
|
|
17786
17797
|
|
|
17787
17798
|
class AccountPage extends AppForm {
|
|
17788
|
-
constructor(injector,
|
|
17799
|
+
constructor(injector, formBuilder, accountService, network, router, validatorService, settingsValidatorService, translate, settings, cd, locales) {
|
|
17789
17800
|
super(injector, validatorService.getFormGroup(accountService.account));
|
|
17790
|
-
this.router = router;
|
|
17791
17801
|
this.formBuilder = formBuilder;
|
|
17792
17802
|
this.accountService = accountService;
|
|
17803
|
+
this.network = network;
|
|
17804
|
+
this.router = router;
|
|
17793
17805
|
this.validatorService = validatorService;
|
|
17794
17806
|
this.settingsValidatorService = settingsValidatorService;
|
|
17795
17807
|
this.translate = translate;
|
|
@@ -17829,21 +17841,37 @@ class AccountPage extends AppForm {
|
|
|
17829
17841
|
}));
|
|
17830
17842
|
}
|
|
17831
17843
|
ngOnDestroy() {
|
|
17844
|
+
var _a;
|
|
17832
17845
|
super.ngOnDestroy();
|
|
17833
17846
|
this.stopListenChanges();
|
|
17847
|
+
(_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
17834
17848
|
}
|
|
17835
17849
|
onLogin(account) {
|
|
17850
|
+
var _a;
|
|
17836
17851
|
console.debug('[account] Logged account: ', account);
|
|
17837
17852
|
this.isLogin = true;
|
|
17838
17853
|
this.setValue(account);
|
|
17839
17854
|
this.email.confirmed = account && account.email && (account.statusId !== StatusIds.TEMPORARY);
|
|
17840
17855
|
this.email.notConfirmed = account && account.email && (!account.statusId || account.statusId === StatusIds.TEMPORARY);
|
|
17841
|
-
this.
|
|
17842
|
-
this.
|
|
17843
|
-
|
|
17844
|
-
|
|
17856
|
+
(_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
17857
|
+
this.networkSubscription = this.network.onNetworkStatusChanges
|
|
17858
|
+
.pipe(map(connectionType => connectionType !== 'none'))
|
|
17859
|
+
.subscribe(online => {
|
|
17860
|
+
if (online) {
|
|
17861
|
+
this.enable();
|
|
17862
|
+
this.markAsPristine();
|
|
17863
|
+
this.startListenChanges();
|
|
17864
|
+
}
|
|
17865
|
+
else {
|
|
17866
|
+
this.disable();
|
|
17867
|
+
this.markAsPristine();
|
|
17868
|
+
this.stopListenChanges();
|
|
17869
|
+
}
|
|
17870
|
+
this.markAsLoaded();
|
|
17871
|
+
});
|
|
17845
17872
|
}
|
|
17846
17873
|
onLogout() {
|
|
17874
|
+
var _a;
|
|
17847
17875
|
this.isLogin = false;
|
|
17848
17876
|
this.email.confirmed = false;
|
|
17849
17877
|
this.email.notConfirmed = false;
|
|
@@ -17851,6 +17879,7 @@ class AccountPage extends AppForm {
|
|
|
17851
17879
|
this.email.error = undefined;
|
|
17852
17880
|
this.form.reset();
|
|
17853
17881
|
this.disable();
|
|
17882
|
+
(_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
17854
17883
|
this.stopListenChanges();
|
|
17855
17884
|
// Back to home
|
|
17856
17885
|
this.router.navigateByUrl('/');
|
|
@@ -17897,13 +17926,13 @@ class AccountPage extends AppForm {
|
|
|
17897
17926
|
save(event) {
|
|
17898
17927
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17899
17928
|
if (this.saving)
|
|
17900
|
-
return;
|
|
17929
|
+
return false;
|
|
17901
17930
|
if (!this.form.valid) {
|
|
17902
17931
|
yield AppFormUtils.waitWhilePending(this.form);
|
|
17903
17932
|
if (this.form.invalid) {
|
|
17904
17933
|
AppFormUtils.logFormErrors(this.form);
|
|
17905
17934
|
this.form.markAllAsTouched();
|
|
17906
|
-
return;
|
|
17935
|
+
return false;
|
|
17907
17936
|
}
|
|
17908
17937
|
}
|
|
17909
17938
|
this.submitted = true;
|
|
@@ -17915,10 +17944,12 @@ class AccountPage extends AppForm {
|
|
|
17915
17944
|
this.disable();
|
|
17916
17945
|
yield this.accountService.save(newAccount);
|
|
17917
17946
|
this.markAsPristine();
|
|
17947
|
+
return true;
|
|
17918
17948
|
}
|
|
17919
17949
|
catch (err) {
|
|
17920
17950
|
console.error(err);
|
|
17921
17951
|
this.error = err && err.message || err;
|
|
17952
|
+
return false;
|
|
17922
17953
|
}
|
|
17923
17954
|
finally {
|
|
17924
17955
|
this.saving = false;
|
|
@@ -17940,6 +17971,14 @@ class AccountPage extends AppForm {
|
|
|
17940
17971
|
});
|
|
17941
17972
|
this.markForCheck();
|
|
17942
17973
|
}
|
|
17974
|
+
cancel() {
|
|
17975
|
+
const _super = Object.create(null, {
|
|
17976
|
+
cancel: { get: () => super.cancel }
|
|
17977
|
+
});
|
|
17978
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17979
|
+
_super.cancel.call(this);
|
|
17980
|
+
});
|
|
17981
|
+
}
|
|
17943
17982
|
markForCheck() {
|
|
17944
17983
|
this.cd.markForCheck();
|
|
17945
17984
|
}
|
|
@@ -17947,16 +17986,17 @@ class AccountPage extends AppForm {
|
|
|
17947
17986
|
AccountPage.decorators = [
|
|
17948
17987
|
{ type: Component, args: [{
|
|
17949
17988
|
selector: 'app-page-account',
|
|
17950
|
-
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\"> </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\"> </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\"> \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\"> \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",
|
|
17989
|
+
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\"> </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\"> </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\"> \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\"> \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",
|
|
17951
17990
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
17952
17991
|
styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form,form mat-form-field{width:100%}"]
|
|
17953
17992
|
},] }
|
|
17954
17993
|
];
|
|
17955
17994
|
AccountPage.ctorParameters = () => [
|
|
17956
17995
|
{ type: Injector },
|
|
17957
|
-
{ type: Router },
|
|
17958
17996
|
{ type: FormBuilder },
|
|
17959
17997
|
{ type: AccountService },
|
|
17998
|
+
{ type: NetworkService },
|
|
17999
|
+
{ type: Router },
|
|
17960
18000
|
{ type: AccountValidatorService },
|
|
17961
18001
|
{ type: UserSettingsValidatorService },
|
|
17962
18002
|
{ type: TranslateService },
|
|
@@ -18432,7 +18472,8 @@ class SettingsPage extends AppForm {
|
|
|
18432
18472
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18433
18473
|
if (this.saving)
|
|
18434
18474
|
return; // Skip
|
|
18435
|
-
|
|
18475
|
+
if (event)
|
|
18476
|
+
event.preventDefault();
|
|
18436
18477
|
// Remove all empty controls
|
|
18437
18478
|
this.propertiesFormHelper.removeAllEmpty();
|
|
18438
18479
|
if (!this.form.valid) {
|
|
@@ -18446,6 +18487,7 @@ class SettingsPage extends AppForm {
|
|
|
18446
18487
|
console.debug('[settings] Saving local settings...');
|
|
18447
18488
|
this.saving = true;
|
|
18448
18489
|
this.error = undefined;
|
|
18490
|
+
this.markForCheck();
|
|
18449
18491
|
const data = yield this.getValue();
|
|
18450
18492
|
// Check peer alive, before saving
|
|
18451
18493
|
const peerChanged = this.form.get('peerUrl').dirty;
|
|
@@ -18473,8 +18515,11 @@ class SettingsPage extends AppForm {
|
|
|
18473
18515
|
this.enable({ emitEvent: false });
|
|
18474
18516
|
// Apply inheritance
|
|
18475
18517
|
this.setAccountInheritance(data.accountInheritance, { emitEvent: false });
|
|
18476
|
-
|
|
18477
|
-
|
|
18518
|
+
// Add a delay, because of option menu that is always opened after save!!
|
|
18519
|
+
setTimeout(() => {
|
|
18520
|
+
this.saving = false;
|
|
18521
|
+
this.markForCheck();
|
|
18522
|
+
}, 400);
|
|
18478
18523
|
}
|
|
18479
18524
|
});
|
|
18480
18525
|
}
|
|
@@ -18538,13 +18583,6 @@ class SettingsPage extends AppForm {
|
|
|
18538
18583
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18539
18584
|
if (this.saving)
|
|
18540
18585
|
return;
|
|
18541
|
-
if (this.dirty) {
|
|
18542
|
-
// Ask user confirmation
|
|
18543
|
-
const confirmation = yield Alerts.askSaveBeforeLeave(this.alertCtrl, this.translate);
|
|
18544
|
-
if (confirmation) {
|
|
18545
|
-
yield this.save(event);
|
|
18546
|
-
}
|
|
18547
|
-
}
|
|
18548
18586
|
// Back to home
|
|
18549
18587
|
return this.router.navigateByUrl('/', { replaceUrl: true }); // back to home
|
|
18550
18588
|
});
|
|
@@ -18585,7 +18623,7 @@ class SettingsPage extends AppForm {
|
|
|
18585
18623
|
SettingsPage.decorators = [
|
|
18586
18624
|
{ type: Component, args: [{
|
|
18587
18625
|
selector: 'page-settings',
|
|
18588
|
-
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> \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\"> \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\"> \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",
|
|
18626
|
+
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\"\n *ngIf=\"!saving\"\n [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> \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\"> \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\"> \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",
|
|
18589
18627
|
providers: [
|
|
18590
18628
|
{ provide: ValidatorService, useExisting: LocalSettingsValidatorService },
|
|
18591
18629
|
],
|