@sumaris-net/ngx-components 1.4.4 → 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.
- package/bundles/sumaris-net.ngx-components.umd.js +132 -87
- 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/storage/entities-storage.service.js +9 -3
- package/esm2015/src/app/core/services/storage/entity-store.class.js +5 -1
- package/esm2015/src/app/core/settings/settings.page.js +3 -2
- package/esm2015/src/app/core/table/table.class.js +1 -1
- package/esm2015/src/app/shared/functions.js +2 -4
- package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +11 -13
- package/fesm2015/sumaris-net.ngx-components.js +67 -28
- 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/services/storage/entity-store.class.d.ts +1 -0
- package/src/app/core/table/table.class.d.ts +1 -1
- package/src/theme/_ngx-components.scss +7 -1
- package/sumaris-net.ngx-components.metadata.json +1 -1
|
@@ -243,9 +243,7 @@ function changeCaseToUnderscore(value) {
|
|
|
243
243
|
return value.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
|
|
244
244
|
}
|
|
245
245
|
function removeDiacritics(text) {
|
|
246
|
-
return text.normalize('NFD')
|
|
247
|
-
//
|
|
248
|
-
.replace(/[\u0300-\u036f]/g, '');
|
|
246
|
+
return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
249
247
|
}
|
|
250
248
|
function suggestFromArray(items, value, opts) {
|
|
251
249
|
if (isNotNil(value) && typeof value === 'object')
|
|
@@ -984,7 +982,6 @@ class MatAutocompleteField {
|
|
|
984
982
|
this.debounceTime = null;
|
|
985
983
|
this.i18nPrefix = 'REFERENTIAL.';
|
|
986
984
|
this.noResultMessage = 'COMMON.NO_RESULT';
|
|
987
|
-
this.matAutocompletePosition = 'auto';
|
|
988
985
|
this.multiple = false;
|
|
989
986
|
this.itemSize = '48px';
|
|
990
987
|
this.fetchMoreThreshold = '15%';
|
|
@@ -1112,6 +1109,7 @@ class MatAutocompleteField {
|
|
|
1112
1109
|
this.debounceTime = toNumber(this.debounceTime, 250);
|
|
1113
1110
|
this.highlightAccent = toBoolean(this.highlightAccent, false);
|
|
1114
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)
|
|
1115
1113
|
// No suggestFn: filter on the given items
|
|
1116
1114
|
if (!this.suggestFn) {
|
|
1117
1115
|
const suggestFromArrayFn = (value, filter) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1153,9 +1151,10 @@ class MatAutocompleteField {
|
|
|
1153
1151
|
// Filter if not enough character
|
|
1154
1152
|
filter(value => value.length >= this.suggestLengthThreshold),
|
|
1155
1153
|
// Wait a debounce time
|
|
1156
|
-
debounceTime(this.debounceTime)
|
|
1154
|
+
debounceTime(this.debounceTime)
|
|
1157
1155
|
// DEBUG
|
|
1158
|
-
tap((value) => console.debug(this.logPrefix + ' Search text changes:', value))
|
|
1156
|
+
//tap((value) => console.debug(this.logPrefix + ' Search text changes:', value)),
|
|
1157
|
+
),
|
|
1159
1158
|
// Object set: use it (no distinctUntilChanged() pipe need)
|
|
1160
1159
|
this.formControl.valueChanges
|
|
1161
1160
|
.pipe(startWith(this.formControl.value), filter(value => (this.searchable && isNotNil(value) && typeof value === 'object')), tap(value => {
|
|
@@ -1170,9 +1169,10 @@ class MatAutocompleteField {
|
|
|
1170
1169
|
this.matInputText.nativeElement.value = this.displayValue;
|
|
1171
1170
|
}
|
|
1172
1171
|
}
|
|
1173
|
-
})
|
|
1172
|
+
})
|
|
1174
1173
|
// DEBUG
|
|
1175
|
-
tap(value => console.debug(this.logPrefix + ' Received an object value: ', value))
|
|
1174
|
+
//tap(value => console.debug(this.logPrefix + ' Received an object value: ', value))
|
|
1175
|
+
),
|
|
1176
1176
|
// Merge some observables, with a common distinctUntilChanged() pipe, and NO debounceTime
|
|
1177
1177
|
merge(
|
|
1178
1178
|
// Focus or click => Load all
|
|
@@ -1181,16 +1181,12 @@ class MatAutocompleteField {
|
|
|
1181
1181
|
// On dropdown button click
|
|
1182
1182
|
this.onDropButtonClick
|
|
1183
1183
|
.pipe(filter(event => this.enabled && this.searchable && (!event || !event.defaultPrevented)), map(_ => this.showAllOnFocus ? '*' : this.formControl.value)), merge(this.$inputItems, this._filter$)
|
|
1184
|
-
.pipe(filter(event => this.enabled && this.searchable), map(_ => this.formControl.value)
|
|
1185
|
-
// DEBUG
|
|
1186
|
-
tap(value => console.debug(this.logPrefix + ' Received $inputItems or filter event: ', value))))
|
|
1184
|
+
.pipe(filter(event => this.enabled && this.searchable), map(_ => this.formControl.value)))
|
|
1187
1185
|
.pipe(
|
|
1188
1186
|
// If value is a string (and is not = '*'), filter if not enough character
|
|
1189
1187
|
filter(value => value === '*' || !(typeof value === 'string') || value.length >= this.suggestLengthThreshold),
|
|
1190
1188
|
// Distinguish changes
|
|
1191
|
-
distinctUntilChanged()
|
|
1192
|
-
// DEBUG
|
|
1193
|
-
tap(value => console.debug(this.logPrefix + ' Received update event: ', value))))
|
|
1189
|
+
distinctUntilChanged()))
|
|
1194
1190
|
.pipe(
|
|
1195
1191
|
// Suggest values
|
|
1196
1192
|
mergeMap(value => this.suggest(value, this.filter)),
|
|
@@ -1354,7 +1350,7 @@ class MatAutocompleteField {
|
|
|
1354
1350
|
// If combo is empty, or if has content but should force to show panel on focus
|
|
1355
1351
|
if (!hasContent || (this.showPanelOnFocus && this.showAllOnFocus)) {
|
|
1356
1352
|
// DEBUG
|
|
1357
|
-
console.debug(this.logPrefix + ' Emit focus event');
|
|
1353
|
+
//console.debug(this.logPrefix + ' Emit focus event');
|
|
1358
1354
|
this.onFocus.emit(event);
|
|
1359
1355
|
return true;
|
|
1360
1356
|
}
|
|
@@ -10685,6 +10681,10 @@ class EntityStore {
|
|
|
10685
10681
|
this._storageKey = ENTITIES_STORAGE_KEY_PREFIX + '#' + name;
|
|
10686
10682
|
this._mapToLightEntity = this.createLightEntityMapFn(this.policy);
|
|
10687
10683
|
}
|
|
10684
|
+
get length() {
|
|
10685
|
+
var _a;
|
|
10686
|
+
return ((_a = this._cache) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
10687
|
+
}
|
|
10688
10688
|
get cache() {
|
|
10689
10689
|
return this._cache;
|
|
10690
10690
|
}
|
|
@@ -11502,11 +11502,17 @@ class EntitiesStorage extends StartableService {
|
|
|
11502
11502
|
console.warn(`[entities-storage] Persisting ${entityName}: store not found!`);
|
|
11503
11503
|
return;
|
|
11504
11504
|
}
|
|
11505
|
-
|
|
11505
|
+
// SKip store if not dirty
|
|
11506
|
+
if (!entityStore.dirty)
|
|
11507
|
+
return Promise.resolve(); // Skip
|
|
11508
|
+
// Persist store
|
|
11509
|
+
return (entityStore.dirty ? entityStore.persist() : Promise.resolve(entityStore.length))
|
|
11506
11510
|
.then(count => {
|
|
11507
11511
|
// If no entity found, remove from the entity names array
|
|
11508
11512
|
if (!count) {
|
|
11509
|
-
entityNames.
|
|
11513
|
+
const entityNameIndex = entityNames.findIndex(e => e === entityName);
|
|
11514
|
+
if (entityNameIndex !== -1)
|
|
11515
|
+
entityNames.splice(entityNameIndex, 1);
|
|
11510
11516
|
}
|
|
11511
11517
|
});
|
|
11512
11518
|
}))
|
|
@@ -17061,6 +17067,9 @@ class AppForm {
|
|
|
17061
17067
|
registerSubscription(sub) {
|
|
17062
17068
|
return this._subscription.add(sub);
|
|
17063
17069
|
}
|
|
17070
|
+
unregisterSubscription(sub) {
|
|
17071
|
+
this._subscription.remove(sub);
|
|
17072
|
+
}
|
|
17064
17073
|
registerAutocompleteField(fieldName, opts) {
|
|
17065
17074
|
return this.autocompleteHelper.add(fieldName, opts);
|
|
17066
17075
|
}
|
|
@@ -17779,11 +17788,12 @@ AccountValidatorService.ctorParameters = () => [
|
|
|
17779
17788
|
];
|
|
17780
17789
|
|
|
17781
17790
|
class AccountPage extends AppForm {
|
|
17782
|
-
constructor(injector,
|
|
17791
|
+
constructor(injector, formBuilder, accountService, network, router, validatorService, settingsValidatorService, translate, settings, cd, locales) {
|
|
17783
17792
|
super(injector, validatorService.getFormGroup(accountService.account));
|
|
17784
|
-
this.router = router;
|
|
17785
17793
|
this.formBuilder = formBuilder;
|
|
17786
17794
|
this.accountService = accountService;
|
|
17795
|
+
this.network = network;
|
|
17796
|
+
this.router = router;
|
|
17787
17797
|
this.validatorService = validatorService;
|
|
17788
17798
|
this.settingsValidatorService = settingsValidatorService;
|
|
17789
17799
|
this.translate = translate;
|
|
@@ -17823,21 +17833,37 @@ class AccountPage extends AppForm {
|
|
|
17823
17833
|
}));
|
|
17824
17834
|
}
|
|
17825
17835
|
ngOnDestroy() {
|
|
17836
|
+
var _a;
|
|
17826
17837
|
super.ngOnDestroy();
|
|
17827
17838
|
this.stopListenChanges();
|
|
17839
|
+
(_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
17828
17840
|
}
|
|
17829
17841
|
onLogin(account) {
|
|
17842
|
+
var _a;
|
|
17830
17843
|
console.debug('[account] Logged account: ', account);
|
|
17831
17844
|
this.isLogin = true;
|
|
17832
17845
|
this.setValue(account);
|
|
17833
17846
|
this.email.confirmed = account && account.email && (account.statusId !== StatusIds.TEMPORARY);
|
|
17834
17847
|
this.email.notConfirmed = account && account.email && (!account.statusId || account.statusId === StatusIds.TEMPORARY);
|
|
17835
|
-
this.
|
|
17836
|
-
this.
|
|
17837
|
-
|
|
17838
|
-
|
|
17848
|
+
(_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
17849
|
+
this.networkSubscription = this.network.onNetworkStatusChanges
|
|
17850
|
+
.pipe(map(connectionType => connectionType !== 'none'))
|
|
17851
|
+
.subscribe(online => {
|
|
17852
|
+
if (online) {
|
|
17853
|
+
this.enable();
|
|
17854
|
+
this.markAsPristine();
|
|
17855
|
+
this.startListenChanges();
|
|
17856
|
+
}
|
|
17857
|
+
else {
|
|
17858
|
+
this.disable();
|
|
17859
|
+
this.markAsPristine();
|
|
17860
|
+
this.stopListenChanges();
|
|
17861
|
+
}
|
|
17862
|
+
this.markAsLoaded();
|
|
17863
|
+
});
|
|
17839
17864
|
}
|
|
17840
17865
|
onLogout() {
|
|
17866
|
+
var _a;
|
|
17841
17867
|
this.isLogin = false;
|
|
17842
17868
|
this.email.confirmed = false;
|
|
17843
17869
|
this.email.notConfirmed = false;
|
|
@@ -17845,6 +17871,7 @@ class AccountPage extends AppForm {
|
|
|
17845
17871
|
this.email.error = undefined;
|
|
17846
17872
|
this.form.reset();
|
|
17847
17873
|
this.disable();
|
|
17874
|
+
(_a = this.networkSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
17848
17875
|
this.stopListenChanges();
|
|
17849
17876
|
// Back to home
|
|
17850
17877
|
this.router.navigateByUrl('/');
|
|
@@ -17891,13 +17918,13 @@ class AccountPage extends AppForm {
|
|
|
17891
17918
|
save(event) {
|
|
17892
17919
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17893
17920
|
if (this.saving)
|
|
17894
|
-
return;
|
|
17921
|
+
return false;
|
|
17895
17922
|
if (!this.form.valid) {
|
|
17896
17923
|
yield AppFormUtils.waitWhilePending(this.form);
|
|
17897
17924
|
if (this.form.invalid) {
|
|
17898
17925
|
AppFormUtils.logFormErrors(this.form);
|
|
17899
17926
|
this.form.markAllAsTouched();
|
|
17900
|
-
return;
|
|
17927
|
+
return false;
|
|
17901
17928
|
}
|
|
17902
17929
|
}
|
|
17903
17930
|
this.submitted = true;
|
|
@@ -17909,10 +17936,12 @@ class AccountPage extends AppForm {
|
|
|
17909
17936
|
this.disable();
|
|
17910
17937
|
yield this.accountService.save(newAccount);
|
|
17911
17938
|
this.markAsPristine();
|
|
17939
|
+
return true;
|
|
17912
17940
|
}
|
|
17913
17941
|
catch (err) {
|
|
17914
17942
|
console.error(err);
|
|
17915
17943
|
this.error = err && err.message || err;
|
|
17944
|
+
return false;
|
|
17916
17945
|
}
|
|
17917
17946
|
finally {
|
|
17918
17947
|
this.saving = false;
|
|
@@ -17934,6 +17963,14 @@ class AccountPage extends AppForm {
|
|
|
17934
17963
|
});
|
|
17935
17964
|
this.markForCheck();
|
|
17936
17965
|
}
|
|
17966
|
+
cancel() {
|
|
17967
|
+
const _super = Object.create(null, {
|
|
17968
|
+
cancel: { get: () => super.cancel }
|
|
17969
|
+
});
|
|
17970
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17971
|
+
_super.cancel.call(this);
|
|
17972
|
+
});
|
|
17973
|
+
}
|
|
17937
17974
|
markForCheck() {
|
|
17938
17975
|
this.cd.markForCheck();
|
|
17939
17976
|
}
|
|
@@ -17941,16 +17978,17 @@ class AccountPage extends AppForm {
|
|
|
17941
17978
|
AccountPage.decorators = [
|
|
17942
17979
|
{ type: Component, args: [{
|
|
17943
17980
|
selector: 'app-page-account',
|
|
17944
|
-
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",
|
|
17981
|
+
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",
|
|
17945
17982
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
17946
17983
|
styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form,form mat-form-field{width:100%}"]
|
|
17947
17984
|
},] }
|
|
17948
17985
|
];
|
|
17949
17986
|
AccountPage.ctorParameters = () => [
|
|
17950
17987
|
{ type: Injector },
|
|
17951
|
-
{ type: Router },
|
|
17952
17988
|
{ type: FormBuilder },
|
|
17953
17989
|
{ type: AccountService },
|
|
17990
|
+
{ type: NetworkService },
|
|
17991
|
+
{ type: Router },
|
|
17954
17992
|
{ type: AccountValidatorService },
|
|
17955
17993
|
{ type: UserSettingsValidatorService },
|
|
17956
17994
|
{ type: TranslateService },
|
|
@@ -18427,6 +18465,7 @@ class SettingsPage extends AppForm {
|
|
|
18427
18465
|
if (this.saving)
|
|
18428
18466
|
return; // Skip
|
|
18429
18467
|
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
18468
|
+
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
18430
18469
|
// Remove all empty controls
|
|
18431
18470
|
this.propertiesFormHelper.removeAllEmpty();
|
|
18432
18471
|
if (!this.form.valid) {
|
|
@@ -18579,7 +18618,7 @@ class SettingsPage extends AppForm {
|
|
|
18579
18618
|
SettingsPage.decorators = [
|
|
18580
18619
|
{ type: Component, args: [{
|
|
18581
18620
|
selector: 'page-settings',
|
|
18582
|
-
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",
|
|
18621
|
+
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> \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",
|
|
18583
18622
|
providers: [
|
|
18584
18623
|
{ provide: ValidatorService, useExisting: LocalSettingsValidatorService },
|
|
18585
18624
|
],
|