@sumaris-net/ngx-components 1.7.3 → 1.8.2
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 +59 -57
- 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 +6 -1
- package/esm2015/src/app/core/form/entity-editor.class.js +5 -1
- package/esm2015/src/app/core/services/account.service.js +38 -27
- package/esm2015/src/app/core/services/base-entity-service.class.js +4 -1
- package/esm2015/src/app/core/services/config.service.js +11 -4
- package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +2 -2
- package/esm2015/src/app/shared/services/entity-service.class.js +1 -1
- package/esm2015/src/app/shared/services/progress-bar.service.js +1 -1
- package/fesm2015/sumaris-net.ngx-components.js +49 -26
- package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
- package/package.json +1 -1
- package/src/app/core/form/entity-editor.class.d.ts +1 -1
- package/src/app/core/services/account.service.d.ts +2 -0
- package/src/app/core/services/base-entity-service.class.d.ts +1 -0
- package/src/app/core/services/config.service.d.ts +4 -1
- package/src/app/shared/services/entity-service.class.d.ts +1 -0
- package/sumaris-net.ngx-components.metadata.json +1 -1
|
@@ -1636,7 +1636,7 @@ MatAutocompleteField.decorators = [
|
|
|
1636
1636
|
{ type: Component, args: [{
|
|
1637
1637
|
// eslint-disable-next-line @angular-eslint/component-selector
|
|
1638
1638
|
selector: 'mat-autocomplete-field',
|
|
1639
|
-
template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <!-- readonly -->\n <mat-form-field *ngIf=\"_readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n [title]=\"displayValue\"\n class=\"mat-form-field-disabled\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <input matInput hidden type=\"text\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\" readonly>\n <ion-text>{{displayWith(value)}}</ion-text>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n\n <ng-template #writable>\n <mat-form-field [floatLabel]=\"floatLabel\"\n [class.mat-form-field-disabled]=\"disabled\"\n [title]=\"displayValue\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- Basic select -->\n <mat-select #matSelect\n *ngIf=\"!searchable; else searchableTemplate\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\"\n [tabindex]=\"_tabindex\"\n [panelClass]=\"classList\"\n [style.width]=\"panelWidth\"\n (focus)=\"filterMatSelectFocusEvent($event)\"\n (blur)=\"filterMatSelectBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n [compareWith]=\"equals\"\n [multiple]=\"multiple\"\n [required]=\"required\">\n <mat-select-trigger>{{ displayWith(value) }}</mat-select-trigger>\n\n <!-- header -->\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as isLast\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n </ion-col>\n </ion-row>\n\n <!-- None option -->\n <mat-option *ngIf=\"!required\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding\">\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <ng-container *ngIf=\"$filteredItems | async; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <!-- options -->\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text>{{item | propertyGet: path }}</ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initMatSelectInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n </mat-select>\n\n\n <!--\n NOTE :\n - \"selectInputContent($event) || onFocus.emit($event)\" : call onFocus only when to the input is empty (nothing to select)\n -->\n <ng-template #searchableTemplate>\n <input matInput #matInputText type=\"text\"\n [matAutocomplete]=\"autocomplete\"\n [matAutocompletePosition]=\"matAutocompletePosition\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [appAutofocus]=\"autofocus\"\n [tabindex]=\"_tabindex\"\n [required]=\"required\"\n (click)=\"clicked.emit($event)\"\n (focus)=\"filterInputTextFocusEvent($event)\"\n (blur)=\"filterInputTextBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n (keyup.arrowdown)=\"dropButtonClick.emit($event)\">\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\n [panelWidth]=\"panelWidth\">\n\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as last\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n <ion-text color=\"light\" *ngIf=\"last && itemCount; let count\" class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n <ng-container *ngIf=\"$filteredItems | async; else loadingTemplate; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label><i>{{noResultMessage | translate}}</i></ion-label>\n </mat-option>\n\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text [innerHTML]=\"item | propertyGet: path | highlight: { search: formControl.value, withAccent: highlightAccent }\"></ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initAutocompleteInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n\n <!-- Loading spinner -->\n <ng-template #loadingTemplate>\n <mat-option *ngIf=\"(matInputText.value | strLength) >= suggestLengthThreshold; else waitMoreCharacterTemplate\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-template>\n\n <!-- Need more characters -->\n <ng-template #waitMoreCharacterTemplate>\n <mat-option class=\"ion-padding text-italic\" disabled>\n <ion-label>\n {{'INFO.PLEASE_TYPE_MORE_CHARACTERS'|translate:{minLength: suggestLengthThreshold} }}\n </ion-label>\n </mat-option>\n </ng-template>\n </mat-autocomplete>\n\n </ng-template>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('entity')\" translate>ERROR.FIELD_INVALID</mat-error>\n <ng-content select=\"[matError]\"></ng-content>\n\n </mat-form-field>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\" class=\"ion-align-self-center\">\n <ng-content select=\"[matAfter]\"></ng-content>\n </ion-col>\n </ion-row>\n</ion-grid>\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n\n\n<ng-template #matSuffixTemplate>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"searchable\"\n (click)=\"dropButtonClick.emit($event)\"\n [hidden]=\"disabled\">\n <mat-icon class=\"large select-arrow\">arrow_drop_down</mat-icon>\n </button>\n <button matSuffix type=\"button\" mat-icon-button tabindex=\"-1\"\n *ngIf=\"enabled && mobile && !searchable && !multiple\"\n [title]=\"'COMMON.BTN_SEARCH'|translate\"\n (click)=\"toggleSearch($event)\">\n <mat-icon>search</mat-icon>\n </button>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"clearable\"\n (click)=\"clearValue($event)\"\n [hidden]=\"disabled || !formControl.value\">\n <mat-icon>close</mat-icon>\n </button>\n\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
|
|
1639
|
+
template: "<ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col class=\"ion-no-padding\">\n <!-- readonly -->\n <mat-form-field *ngIf=\"_readonly; else writable\"\n [floatLabel]=\"floatLabel\"\n [title]=\"displayValue\"\n class=\"mat-form-field-disabled\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <input matInput hidden type=\"text\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\" readonly>\n <ion-text>{{displayWith(value)}}</ion-text>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n </mat-form-field>\n\n <ng-template #writable>\n <mat-form-field [floatLabel]=\"floatLabel\"\n [class.mat-form-field-disabled]=\"disabled\"\n [title]=\"displayValue\">\n\n <div matPrefix>\n <ng-container *ngTemplateOutlet=\"matPrefixTemplate\"></ng-container>\n </div>\n\n <!-- Basic select -->\n <mat-select #matSelect\n *ngIf=\"!searchable; else searchableTemplate\"\n [placeholder]=\"placeholder\"\n [formControl]=\"formControl\"\n [tabindex]=\"_tabindex\"\n [panelClass]=\"classList\"\n [style.width]=\"panelWidth\"\n (focus)=\"filterMatSelectFocusEvent($event)\"\n (blur)=\"filterMatSelectBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n [compareWith]=\"equals\"\n [multiple]=\"multiple\"\n [required]=\"required\">\n <mat-select-trigger>{{ displayWith(value) }}</mat-select-trigger>\n\n <!-- header -->\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as isLast\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n </ion-col>\n </ion-row>\n\n <!-- None option -->\n <mat-option *ngIf=\"!required\" class=\"ion-no-padding\">\n <ion-row class=\"ion-no-padding\">\n <ion-col class=\"ion-no-padding\">\n <ion-label><i translate>COMMON.EMPTY_OPTION</i></ion-label>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <ng-container *ngIf=\"$filteredItems | async; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label>{{noResultMessage | translate}}</ion-label>\n </mat-option>\n\n <!-- options -->\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text>{{item | propertyGet: path }}</ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initMatSelectInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n </mat-select>\n\n\n <!--\n NOTE :\n - \"selectInputContent($event) || onFocus.emit($event)\" : call onFocus only when to the input is empty (nothing to select)\n -->\n <ng-template #searchableTemplate>\n <input matInput #matInputText type=\"text\"\n [matAutocomplete]=\"autocomplete\"\n [matAutocompletePosition]=\"matAutocompletePosition\"\n [formControl]=\"formControl\"\n [placeholder]=\"placeholder\"\n [appAutofocus]=\"autofocus\"\n [tabindex]=\"_tabindex\"\n [required]=\"required\"\n (click)=\"clicked.emit($event)\"\n (focus)=\"filterInputTextFocusEvent($event)\"\n (blur)=\"filterInputTextBlurEvent($event)\"\n (keydown.escape)=\"keydownEscape.emit($event)\"\n (keyup.enter)=\"keyupEnter.emit($event)\"\n (keyup.arrowdown)=\"!autocomplete.showPanel && dropButtonClick.emit($event)\">\n\n <!-- autocomplete -->\n <mat-autocomplete #autocomplete=\"matAutocomplete\"\n autoActiveFirstOption\n [displayWith]=\"displayWith\"\n [class]=\"classList\"\n [panelWidth]=\"panelWidth\">\n\n <ion-row class=\"mat-autocomplete-header ion-no-padding\">\n <ion-col *ngFor=\"let attr of displayAttributes; index as i; last as last\" [size]=\"displayColumnSizes[i]\">\n <ion-label [innerHTML]=\"displayColumnNames[i] | translate\"></ion-label>\n <ion-text color=\"light\" *ngIf=\"last && itemCount; let count\" class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n <ng-container *ngIf=\"$filteredItems | async; else loadingTemplate; let items\">\n <!-- No item option -->\n <mat-option *ngIf=\"items | isEmptyArray\" class=\"ion-padding text-italic\" disabled>\n <ion-label><i>{{noResultMessage | translate}}</i></ion-label>\n </mat-option>\n\n <mat-option *ngFor=\"let item of items\" [value]=\"item\" class=\"ion-no-padding\">\n <ion-row [classList]=\"item.classList\">\n <ion-col *ngFor=\"let path of displayAttributes; index as i;\"\n [size]=\"displayColumnSizes[i]\">\n <ion-text [innerHTML]=\"item | propertyGet: path | highlight: { search: formControl.value, withAccent: highlightAccent }\"></ion-text>\n </ion-col>\n </ion-row>\n </mat-option>\n\n <!-- More item -->\n <mat-option *ngIf=\"_moreItemsCount\" (ngInit)=\"_initAutocompleteInfiniteScroll()\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-container>\n\n <!-- Loading spinner -->\n <ng-template #loadingTemplate>\n <mat-option *ngIf=\"(matInputText.value | strLength) >= suggestLengthThreshold; else waitMoreCharacterTemplate\"\n class=\"ion-padding\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </mat-option>\n </ng-template>\n\n <!-- Need more characters -->\n <ng-template #waitMoreCharacterTemplate>\n <mat-option class=\"ion-padding text-italic\" disabled>\n <ion-label>\n {{'INFO.PLEASE_TYPE_MORE_CHARACTERS'|translate:{minLength: suggestLengthThreshold} }}\n </ion-label>\n </mat-option>\n </ng-template>\n </mat-autocomplete>\n\n </ng-template>\n\n <div matSuffix>\n <ng-container *ngTemplateOutlet=\"matSuffixTemplate\"></ng-container>\n </div>\n\n <mat-error *ngIf=\"formControl.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"formControl.hasError('entity')\" translate>ERROR.FIELD_INVALID</mat-error>\n <ng-content select=\"[matError]\"></ng-content>\n\n </mat-form-field>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\" class=\"ion-align-self-center\">\n <ng-content select=\"[matAfter]\"></ng-content>\n </ion-col>\n </ion-row>\n</ion-grid>\n\n<ng-template #matPrefixTemplate>\n <ng-content select=\"[matPrefix]\"></ng-content>\n</ng-template>\n\n\n<ng-template #matSuffixTemplate>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"searchable\"\n (click)=\"dropButtonClick.emit($event)\"\n [hidden]=\"disabled\">\n <mat-icon class=\"large select-arrow\">arrow_drop_down</mat-icon>\n </button>\n <button matSuffix type=\"button\" mat-icon-button tabindex=\"-1\"\n *ngIf=\"enabled && mobile && !searchable && !multiple\"\n [title]=\"'COMMON.BTN_SEARCH'|translate\"\n (click)=\"toggleSearch($event)\">\n <mat-icon>search</mat-icon>\n </button>\n <button matSuffix mat-icon-button tabindex=\"-1\"\n type=\"button\"\n *ngIf=\"clearable\"\n (click)=\"clearValue($event)\"\n [hidden]=\"disabled || !formControl.value\">\n <mat-icon>close</mat-icon>\n </button>\n\n <ng-content select=\"[matSuffix]\"></ng-content>\n</ng-template>\n",
|
|
1640
1640
|
providers: [{
|
|
1641
1641
|
provide: NG_VALUE_ACCESSOR,
|
|
1642
1642
|
multi: true,
|
|
@@ -13561,6 +13561,7 @@ class AccountService extends BaseGraphqlService {
|
|
|
13561
13561
|
this.onChange = new Subject();
|
|
13562
13562
|
this.onAuthTokenChange = new Subject();
|
|
13563
13563
|
this.onAuthBasicChange = new Subject();
|
|
13564
|
+
this._stopWatching$ = new Subject();
|
|
13564
13565
|
this._cache = {
|
|
13565
13566
|
loaded: false,
|
|
13566
13567
|
keypair: null,
|
|
@@ -13963,6 +13964,7 @@ class AccountService extends BaseGraphqlService {
|
|
|
13963
13964
|
if (hadAuthBasic)
|
|
13964
13965
|
this.onAuthBasicChange.next(undefined);
|
|
13965
13966
|
this.onChange.next(undefined);
|
|
13967
|
+
this._stopWatching$.next();
|
|
13966
13968
|
});
|
|
13967
13969
|
}
|
|
13968
13970
|
/**
|
|
@@ -14079,12 +14081,17 @@ class AccountService extends BaseGraphqlService {
|
|
|
14079
14081
|
return res && res.confirmAccountEmail;
|
|
14080
14082
|
});
|
|
14081
14083
|
}
|
|
14082
|
-
|
|
14084
|
+
watch() {
|
|
14083
14085
|
if (!this._cache.pubkey)
|
|
14084
|
-
|
|
14085
|
-
|
|
14086
|
-
|
|
14087
|
-
|
|
14086
|
+
throw new Error('Not logged in');
|
|
14087
|
+
if (!this.started) {
|
|
14088
|
+
// Wait service ready, then loop
|
|
14089
|
+
return from(this.ready())
|
|
14090
|
+
.pipe(switchMap(() => this.watch()));
|
|
14091
|
+
}
|
|
14092
|
+
this._stopWatching$.next(); // Stop previous listening
|
|
14093
|
+
console.debug('[account] [WS] Watching changes');
|
|
14094
|
+
return this.graphql.subscribe({
|
|
14088
14095
|
query: AccountSubscriptions.listenChanges,
|
|
14089
14096
|
variables: {
|
|
14090
14097
|
interval: 10
|
|
@@ -14093,35 +14100,39 @@ class AccountService extends BaseGraphqlService {
|
|
|
14093
14100
|
code: ErrorCodes$2.SUBSCRIBE_ACCOUNT_ERROR,
|
|
14094
14101
|
message: 'ERROR.ACCOUNT.SUBSCRIBE_ACCOUNT_ERROR'
|
|
14095
14102
|
}
|
|
14096
|
-
})
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
})
|
|
14107
|
-
|
|
14103
|
+
})
|
|
14104
|
+
.pipe(
|
|
14105
|
+
// Stop this pipe next time we call watch()
|
|
14106
|
+
takeUntil(this._stopWatching$), map(({ data }) => {
|
|
14107
|
+
var _a;
|
|
14108
|
+
if (!data)
|
|
14109
|
+
return;
|
|
14110
|
+
const existingUpdateDate = toDateISOString((_a = this._data) === null || _a === void 0 ? void 0 : _a.updateDate);
|
|
14111
|
+
if (existingUpdateDate === data.updateDate)
|
|
14112
|
+
return;
|
|
14113
|
+
console.debug(`[account] [WS] Detected update on {${data.updateDate}}`);
|
|
14114
|
+
return Account.fromObject(data);
|
|
14115
|
+
}), filter(isNotNil));
|
|
14116
|
+
}
|
|
14117
|
+
listenChanges() {
|
|
14118
|
+
const self = this;
|
|
14119
|
+
const subscription = this.watch()
|
|
14120
|
+
.subscribe({
|
|
14121
|
+
next: (data) => self.refresh(),
|
|
14122
|
+
error: (err) => {
|
|
14108
14123
|
if (err && +err.code === ServerErrorCodes.NOT_FOUND) {
|
|
14109
14124
|
console.info('[account] Account not exists anymore: force user to logout...', err);
|
|
14110
|
-
|
|
14125
|
+
self.logout();
|
|
14111
14126
|
}
|
|
14112
14127
|
else if (err && +err.code === ServerErrorCodes.UNAUTHORIZED) {
|
|
14113
14128
|
console.info('[account] Account not authorized: force user to logout...', err);
|
|
14114
|
-
|
|
14129
|
+
self.logout();
|
|
14115
14130
|
}
|
|
14116
14131
|
else {
|
|
14117
14132
|
console.warn('[account] [WS] Received error:', err);
|
|
14118
14133
|
}
|
|
14119
|
-
}),
|
|
14120
|
-
complete: () => {
|
|
14121
|
-
console.debug('[account] [WS] Completed');
|
|
14122
14134
|
}
|
|
14123
14135
|
});
|
|
14124
|
-
// Add log when closing WS
|
|
14125
14136
|
subscription.add(() => console.debug('[account] [WS] Stop listening changes'));
|
|
14126
14137
|
return subscription;
|
|
14127
14138
|
}
|
|
@@ -14801,7 +14812,7 @@ const CacheStatistics = gql `
|
|
|
14801
14812
|
`;
|
|
14802
14813
|
const APP_CONFIG_OPTIONS = new InjectionToken('defaultOptions');
|
|
14803
14814
|
class ConfigService extends BaseGraphqlService {
|
|
14804
|
-
constructor(platform, graphql, storage, network, file, toastController, translate, environment, defaultOptionsMap) {
|
|
14815
|
+
constructor(platform, graphql, storage, network, file, toastController, translate, accountService, environment, defaultOptionsMap) {
|
|
14805
14816
|
super(graphql, environment);
|
|
14806
14817
|
this.platform = platform;
|
|
14807
14818
|
this.graphql = graphql;
|
|
@@ -14810,6 +14821,7 @@ class ConfigService extends BaseGraphqlService {
|
|
|
14810
14821
|
this.file = file;
|
|
14811
14822
|
this.toastController = toastController;
|
|
14812
14823
|
this.translate = translate;
|
|
14824
|
+
this.accountService = accountService;
|
|
14813
14825
|
this.environment = environment;
|
|
14814
14826
|
this.$data = new BehaviorSubject(null);
|
|
14815
14827
|
this._debug = !environment.production;
|
|
@@ -14856,6 +14868,9 @@ class ConfigService extends BaseGraphqlService {
|
|
|
14856
14868
|
return this.loadDefault();
|
|
14857
14869
|
});
|
|
14858
14870
|
}
|
|
14871
|
+
canUserWrite(data, opts) {
|
|
14872
|
+
return this.accountService.isAdmin();
|
|
14873
|
+
}
|
|
14859
14874
|
/**
|
|
14860
14875
|
* Save a configuration
|
|
14861
14876
|
*
|
|
@@ -15073,7 +15088,7 @@ class ConfigService extends BaseGraphqlService {
|
|
|
15073
15088
|
});
|
|
15074
15089
|
}
|
|
15075
15090
|
}
|
|
15076
|
-
ConfigService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ConfigService_Factory() { return new ConfigService(i0.ɵɵinject(i1$4.Platform), i0.ɵɵinject(GraphqlService), i0.ɵɵinject(i3$1.Storage), i0.ɵɵinject(NetworkService), i0.ɵɵinject(FileService), i0.ɵɵinject(i1$4.ToastController), i0.ɵɵinject(i1$1.TranslateService), i0.ɵɵinject(ENVIRONMENT), i0.ɵɵinject(APP_CONFIG_OPTIONS, 8)); }, token: ConfigService, providedIn: "root" });
|
|
15091
|
+
ConfigService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ConfigService_Factory() { return new ConfigService(i0.ɵɵinject(i1$4.Platform), i0.ɵɵinject(GraphqlService), i0.ɵɵinject(i3$1.Storage), i0.ɵɵinject(NetworkService), i0.ɵɵinject(FileService), i0.ɵɵinject(i1$4.ToastController), i0.ɵɵinject(i1$1.TranslateService), i0.ɵɵinject(AccountService), i0.ɵɵinject(ENVIRONMENT), i0.ɵɵinject(APP_CONFIG_OPTIONS, 8)); }, token: ConfigService, providedIn: "root" });
|
|
15077
15092
|
ConfigService.decorators = [
|
|
15078
15093
|
{ type: Injectable, args: [{
|
|
15079
15094
|
providedIn: 'root',
|
|
@@ -15088,6 +15103,7 @@ ConfigService.ctorParameters = () => [
|
|
|
15088
15103
|
{ type: FileService },
|
|
15089
15104
|
{ type: ToastController },
|
|
15090
15105
|
{ type: TranslateService },
|
|
15106
|
+
{ type: AccountService },
|
|
15091
15107
|
{ type: undefined, decorators: [{ type: Inject, args: [ENVIRONMENT,] }] },
|
|
15092
15108
|
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [APP_CONFIG_OPTIONS,] }] }
|
|
15093
15109
|
];
|
|
@@ -20633,6 +20649,9 @@ class BaseEntityService extends BaseGraphqlService {
|
|
|
20633
20649
|
return res.total;
|
|
20634
20650
|
});
|
|
20635
20651
|
}
|
|
20652
|
+
canUserWrite(data, opts) {
|
|
20653
|
+
return !!data;
|
|
20654
|
+
}
|
|
20636
20655
|
saveAll(entities, opts) {
|
|
20637
20656
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20638
20657
|
if (isEmptyArray(entities))
|
|
@@ -23859,6 +23878,10 @@ class AppEntityEditor extends AppTabEditor {
|
|
|
23859
23878
|
if (!opts || opts.emitEvent !== false)
|
|
23860
23879
|
this.markForCheck();
|
|
23861
23880
|
}
|
|
23881
|
+
/* -- public abstract methods (to override) -- */
|
|
23882
|
+
canUserWrite(data, opts) {
|
|
23883
|
+
return this.dataService.canUserWrite(data, opts);
|
|
23884
|
+
}
|
|
23862
23885
|
/* -- protected methods -- */
|
|
23863
23886
|
/**
|
|
23864
23887
|
* Return undefined to keep same tab
|