@sumaris-net/ngx-components 0.24.2 → 0.25.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.
Files changed (48) hide show
  1. package/bundles/{ngx-sumaris-components.umd.js → sumaris-net.ngx-components.umd.js} +1038 -926
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -0
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +25 -0
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -0
  5. package/doc/changelog.md +4 -0
  6. package/esm2015/public_api.js +2 -1
  7. package/esm2015/src/app/admin/users/list/users.js +6 -4
  8. package/esm2015/src/app/core/graphql/graphql.service.js +25 -72
  9. package/esm2015/src/app/core/graphql/graphql.utils.js +1 -1
  10. package/esm2015/src/app/core/install/install-upgrade-card.component.js +105 -46
  11. package/esm2015/src/app/core/services/account.service.js +146 -149
  12. package/esm2015/src/app/core/services/config.service.js +21 -14
  13. package/esm2015/src/app/core/services/local-settings.service.js +72 -87
  14. package/esm2015/src/app/core/services/network.service.js +136 -171
  15. package/esm2015/src/app/core/services/platform.service.js +34 -17
  16. package/esm2015/src/app/core/services/storage/entities-storage.service.js +59 -63
  17. package/esm2015/src/app/shared/audio/audio.js +10 -39
  18. package/esm2015/src/app/shared/material/boolean/material.boolean.js +1 -1
  19. package/esm2015/src/app/shared/services/startable-service.class.js +77 -0
  20. package/esm2015/src/environments/environment.class.js +1 -1
  21. package/esm2015/src/environments/environment.js +5 -1
  22. package/esm2015/sumaris-net.ngx-components.js +13 -0
  23. package/fesm2015/{ngx-sumaris-components.js → sumaris-net.ngx-components.js} +669 -646
  24. package/fesm2015/sumaris-net.ngx-components.js.map +1 -0
  25. package/package.json +13 -9
  26. package/public_api.d.ts +1 -0
  27. package/src/app/admin/users/list/users.d.ts +1 -0
  28. package/src/app/core/graphql/graphql.service.d.ts +5 -13
  29. package/src/app/core/graphql/graphql.utils.d.ts +2 -1
  30. package/src/app/core/install/install-upgrade-card.component.d.ts +12 -7
  31. package/src/app/core/services/account.service.d.ts +11 -10
  32. package/src/app/core/services/config.service.d.ts +6 -5
  33. package/src/app/core/services/local-settings.service.d.ts +4 -9
  34. package/src/app/core/services/network.service.d.ts +27 -38
  35. package/src/app/core/services/platform.service.d.ts +2 -1
  36. package/src/app/core/services/storage/entities-storage.service.d.ts +13 -13
  37. package/src/app/shared/audio/audio.d.ts +4 -8
  38. package/src/app/shared/services/startable-service.class.d.ts +26 -0
  39. package/src/assets/i18n/fr.json +2 -0
  40. package/src/environments/environment.class.d.ts +1 -0
  41. package/{ngx-sumaris-components.d.ts → sumaris-net.ngx-components.d.ts} +0 -0
  42. package/sumaris-net.ngx-components.metadata.json +1 -0
  43. package/bundles/ngx-sumaris-components.umd.js.map +0 -1
  44. package/bundles/ngx-sumaris-components.umd.min.js +0 -25
  45. package/bundles/ngx-sumaris-components.umd.min.js.map +0 -1
  46. package/esm2015/ngx-sumaris-components.js +0 -13
  47. package/fesm2015/ngx-sumaris-components.js.map +0 -1
  48. package/ngx-sumaris-components.metadata.json +0 -1
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/cdk/table'), require('@angular/cdk/a11y'), require('@angular/cdk/overlay'), require('@angular/cdk/scrolling'), require('@angular/material/core'), require('@angular/material/table'), require('@angular/material/sort'), require('@angular/material/paginator'), require('@angular/material/form-field'), require('@angular/material/input'), require('@angular/material/checkbox'), require('@angular/material/expansion'), require('@angular/material/toolbar'), require('@angular/material/icon'), require('@angular/material/button'), require('@angular/material/menu'), require('@angular/material/select'), require('@angular/material/card'), require('@angular/material/tabs'), require('@angular/material/stepper'), require('@angular/material/list'), require('@angular/material/button-toggle'), require('@angular/material/progress-spinner'), require('@angular/material/progress-bar'), require('@angular/material/radio'), require('@angular/material/badge'), require('@angular/material/slide-toggle'), require('@angular/material/dialog'), require('@angular/material/autocomplete'), require('@angular/forms'), require('rxjs'), require('rxjs/operators'), require('@ngx-translate/core'), require('@ionic/angular'), require('moment'), require('@angular/material-moment-adapter'), require('@ionic-native/keyboard/ngx'), require('angular2-text-mask'), require('ngx-material-timepicker'), require('@angular/material/datepicker'), require('@angular/animations'), require('@angular/material/divider'), require('@angular/material/tooltip'), require('@angular/material/chips'), require('@angular/router'), require('@angular/platform-browser'), require('@angular/common/http'), require('ngx-color-picker'), require('@ionic-native/native-audio/ngx'), require('@ionic-native/vibration/ngx'), require('@ionic-native/audio-management/ngx'), require('@ionic-native/native-audio/ngx/index'), require('@ionic-native/vibration/ngx/index'), require('@ionic-native/audio-management/ngx/index'), require('uuid/v4'), require('@angular/cdk/drag-drop'), require('ngx-markdown'), require('tweetnacl'), require('@ionic/storage'), require('zone.js/dist/zone-error'), require('@ionic-native/splash-screen/ngx'), require('@ionic-native/network/ngx'), require('ionic-cache'), require('ionic-cache/dist/cache.service'), require('@ionic-native/network/ngx/index'), require('@ionic-native/splash-screen/ngx/index'), require('@ionic-native/status-bar/ngx'), require('@angular/cdk/platform'), require('@ionic-native/in-app-browser/ngx'), require('@apollo/client/core'), require('apollo-angular'), require('@apollo/client/link/ws'), require('@apollo/client/utilities'), require('@apollo/client/link/retry'), require('apollo-link-queue'), require('apollo-link-serialize'), require('apollo-link-logger'), require('apollo-angular/http'), require('apollo3-cache-persist'), require('@ionic-native/downloader/ngx'), require('@ionic-native/status-bar/ngx/index'), require('@ionic-native/keyboard/ngx/index'), require('@ionic-native/in-app-browser/ngx/index'), require('@ionic-native/downloader/ngx/index'), require('@e-is/ngx-material-table'), require('@angular/cdk/collections'), require('ngx-jdenticon'), require('tweetnacl-util'), require('scrypt-async'), require('hammerjs')) :
3
3
  typeof define === 'function' && define.amd ? define('@sumaris-net/ngx-components', ['exports', '@angular/core', '@angular/common', '@angular/cdk/table', '@angular/cdk/a11y', '@angular/cdk/overlay', '@angular/cdk/scrolling', '@angular/material/core', '@angular/material/table', '@angular/material/sort', '@angular/material/paginator', '@angular/material/form-field', '@angular/material/input', '@angular/material/checkbox', '@angular/material/expansion', '@angular/material/toolbar', '@angular/material/icon', '@angular/material/button', '@angular/material/menu', '@angular/material/select', '@angular/material/card', '@angular/material/tabs', '@angular/material/stepper', '@angular/material/list', '@angular/material/button-toggle', '@angular/material/progress-spinner', '@angular/material/progress-bar', '@angular/material/radio', '@angular/material/badge', '@angular/material/slide-toggle', '@angular/material/dialog', '@angular/material/autocomplete', '@angular/forms', 'rxjs', 'rxjs/operators', '@ngx-translate/core', '@ionic/angular', 'moment', '@angular/material-moment-adapter', '@ionic-native/keyboard/ngx', 'angular2-text-mask', 'ngx-material-timepicker', '@angular/material/datepicker', '@angular/animations', '@angular/material/divider', '@angular/material/tooltip', '@angular/material/chips', '@angular/router', '@angular/platform-browser', '@angular/common/http', 'ngx-color-picker', '@ionic-native/native-audio/ngx', '@ionic-native/vibration/ngx', '@ionic-native/audio-management/ngx', '@ionic-native/native-audio/ngx/index', '@ionic-native/vibration/ngx/index', '@ionic-native/audio-management/ngx/index', 'uuid/v4', '@angular/cdk/drag-drop', 'ngx-markdown', 'tweetnacl', '@ionic/storage', 'zone.js/dist/zone-error', '@ionic-native/splash-screen/ngx', '@ionic-native/network/ngx', 'ionic-cache', 'ionic-cache/dist/cache.service', '@ionic-native/network/ngx/index', '@ionic-native/splash-screen/ngx/index', '@ionic-native/status-bar/ngx', '@angular/cdk/platform', '@ionic-native/in-app-browser/ngx', '@apollo/client/core', 'apollo-angular', '@apollo/client/link/ws', '@apollo/client/utilities', '@apollo/client/link/retry', 'apollo-link-queue', 'apollo-link-serialize', 'apollo-link-logger', 'apollo-angular/http', 'apollo3-cache-persist', '@ionic-native/downloader/ngx', '@ionic-native/status-bar/ngx/index', '@ionic-native/keyboard/ngx/index', '@ionic-native/in-app-browser/ngx/index', '@ionic-native/downloader/ngx/index', '@e-is/ngx-material-table', '@angular/cdk/collections', 'ngx-jdenticon', 'tweetnacl-util', 'scrypt-async', 'hammerjs'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global['sumaris-net'] = global['sumaris-net'] || {}, global['sumaris-net']['ngx-components'] = {}), global.ng.core, global.ng.common, global.ng.cdk.table, global.ng.cdk.a11y, global.ng.cdk.overlay, global.ng.cdk.scrolling, global.ng.material.core, global.ng.material.table, global.ng.material.sort, global.ng.material.paginator, global.ng.material.formField, global.ng.material.input, global.ng.material.checkbox, global.ng.material.expansion, global.ng.material.toolbar, global.ng.material.icon, global.ng.material.button, global.ng.material.menu, global.ng.material.select, global.ng.material.card, global.ng.material.tabs, global.ng.material.stepper, global.ng.material.list, global.ng.material.buttonToggle, global.ng.material.progressSpinner, global.ng.material.progressBar, global.ng.material.radio, global.ng.material.badge, global.ng.material.slideToggle, global.ng.material.dialog, global.ng.material.autocomplete, global.ng.forms, global.rxjs, global.rxjs.operators, global['ngx-translate'].core, global.ionic.angular, global.moment, global.ng.materialMomentAdapter, global['ionic-native'].keyboard.ngx, global['angular2-text-mask'], global['ngx-material-timepicker'], global.ng.material.datepicker, global.ng.animations, global.ng.material.divider, global.ng.material.tooltip, global.ng.material.chips, global.ng.router, global.ng.platformBrowser, global.ng.common.http, global['ngx-color-picker'], global['ionic-native']['native-audio'].ngx, global['ionic-native'].vibration.ngx, global['ionic-native']['audio-management'].ngx, global['ionic-native']['native-audio'].ngx.index, global['ionic-native'].vibration.ngx.index, global['ionic-native']['audio-management'].ngx.index, global.uuid.v4, global.ng.cdk.dragDrop, global['ngx-markdown'], global.tweetnacl, global.ionic.storage, null, global['ionic-native']['splash-screen'].ngx, global['ionic-native'].network.ngx, global['ionic-cache'], global['ionic-cache/dist/cache'].service, global['ionic-native'].network.ngx.index, global['ionic-native']['splash-screen'].ngx.index, global['ionic-native']['status-bar'].ngx, global.ng.cdk.platform, global['ionic-native']['in-app-browser'].ngx, global.apollo.client.core, global['apollo-angular'], global.apollo.client.link.ws, global.apollo.client.utilities, global.apollo.client.link.retry, global['apollo-link-queue'], global['apollo-link-serialize'], global['apollo-link-logger'], global['apollo-angular'].http, global['apollo3-cache-persist'], global.ngx$6, global['ionic-native']['status-bar'].ngx.index, global['ionic-native'].keyboard.ngx.index, global['ionic-native']['in-app-browser'].ngx.index, global.i18, global['e-is']['ngx-material-table'], global.ng.cdk.collections, global['ngx-jdenticon']));
5
- }(this, (function (exports, i0, i1$4, table$1, a11y, overlay, scrolling, i1$3, table, sort$1, paginator, formField, input, checkbox, expansion, toolbar, icon, button, menu, select, card, tabs, stepper, list, buttonToggle, progressSpinner, progressBar, radio, badge, slideToggle, i2, autocomplete, i1, rxjs, operators, i1$2, i1$5, momentImported, i1$1, ngx, angular2TextMask, ngxMaterialTimepicker, datepicker, animations, divider, tooltip, chips, i3, i1$6, i2$1, ngxColorPicker, ngx$2, ngx$3, ngx$1, i2$2, i3$1, i4, uuidv4Imported, dragDrop, ngxMarkdown, tweetnacl, i3$2, zoneError, ngx$5, ngx$4, ionicCache, i6, i9, i10, ngx$7, i2$4, ngx$8, core, i2$3, ws, utilities, retry, QueueLink, SerializingLink, loggerLink, i3$3, apollo3CachePersist, ngx$6, i14, i15, i17, i18, ngxMaterialTable, collections, ngxJdenticon) { 'use strict';
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global["sumaris-net"] = global["sumaris-net"] || {}, global["sumaris-net"]["ngx-components"] = {}), global.ng.core, global.ng.common, global.ng.cdk.table, global.ng.cdk.a11y, global.ng.cdk.overlay, global.ng.cdk.scrolling, global.ng.material.core, global.ng.material.table, global.ng.material.sort, global.ng.material.paginator, global.ng.material.formField, global.ng.material.input, global.ng.material.checkbox, global.ng.material.expansion, global.ng.material.toolbar, global.ng.material.icon, global.ng.material.button, global.ng.material.menu, global.ng.material.select, global.ng.material.card, global.ng.material.tabs, global.ng.material.stepper, global.ng.material.list, global.ng.material.buttonToggle, global.ng.material.progressSpinner, global.ng.material.progressBar, global.ng.material.radio, global.ng.material.badge, global.ng.material.slideToggle, global.ng.material.dialog, global.ng.material.autocomplete, global.ng.forms, global.rxjs, global.rxjs.operators, global["ngx-translate"].core, global.ionic.angular, global.moment, global.ng.materialMomentAdapter, global["ionic-native"].keyboard.ngx, global["angular2-text-mask"], global["ngx-material-timepicker"], global.ng.material.datepicker, global.ng.animations, global.ng.material.divider, global.ng.material.tooltip, global.ng.material.chips, global.ng.router, global.ng.platformBrowser, global.ng.common.http, global["ngx-color-picker"], global["ionic-native"]["native-audio"].ngx, global["ionic-native"].vibration.ngx, global["ionic-native"]["audio-management"].ngx, global["ionic-native"]["native-audio"].ngx.index, global["ionic-native"].vibration.ngx.index, global["ionic-native"]["audio-management"].ngx.index, global.uuid.v4, global.ng.cdk.dragDrop, global["ngx-markdown"], global.tweetnacl, global.ionic.storage, null, global["ionic-native"]["splash-screen"].ngx, global["ionic-native"].network.ngx, global["ionic-cache"], global["ionic-cache/dist/cache"].service, global["ionic-native"].network.ngx.index, global["ionic-native"]["splash-screen"].ngx.index, global["ionic-native"]["status-bar"].ngx, global.ng.cdk.platform, global["ionic-native"]["in-app-browser"].ngx, global.apollo.client.core, global["apollo-angular"], global.apollo.client.link.ws, global.apollo.client.utilities, global.apollo.client.link.retry, global["apollo-link-queue"], global["apollo-link-serialize"], global["apollo-link-logger"], global["apollo-angular"].http, global["apollo3-cache-persist"], global.ngx$6, global["ionic-native"]["status-bar"].ngx.index, global["ionic-native"].keyboard.ngx.index, global["ionic-native"]["in-app-browser"].ngx.index, global.i18, global["e-is"]["ngx-material-table"], global.ng.cdk.collections, global["ngx-jdenticon"]));
5
+ })(this, (function (exports, i0, i1$4, table$1, a11y, overlay, scrolling, i1$3, table, sort$1, paginator, formField, input, checkbox, expansion, toolbar, icon, button, menu, select, card, tabs, stepper, list, buttonToggle, progressSpinner, progressBar, radio, badge, slideToggle, i2, autocomplete, i1, rxjs, operators, i1$2, i1$5, momentImported, i1$1, ngx, angular2TextMask, ngxMaterialTimepicker, datepicker, animations, divider, tooltip, chips, i3, i1$6, i2$1, ngxColorPicker, ngx$2, ngx$3, ngx$1, i2$2, i3$1, i4, uuidv4Imported, dragDrop, ngxMarkdown, tweetnacl, i3$2, zoneError, ngx$5, ngx$4, ionicCache, i6, i9, i10, ngx$7, i2$4, ngx$8, core, i2$3, ws, utilities, retry, QueueLink, SerializingLink, loggerLink, i3$3, apollo3CachePersist, ngx$6, i14, i15, i17, i18, ngxMaterialTable, collections, ngxJdenticon) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -15,14 +15,12 @@
15
15
  var d = Object.getOwnPropertyDescriptor(e, k);
16
16
  Object.defineProperty(n, k, d.get ? d : {
17
17
  enumerable: true,
18
- get: function () {
19
- return e[k];
20
- }
18
+ get: function () { return e[k]; }
21
19
  });
22
20
  }
23
21
  });
24
22
  }
25
- n['default'] = e;
23
+ n["default"] = e;
26
24
  return Object.freeze(n);
27
25
  }
28
26
 
@@ -5583,7 +5581,7 @@
5583
5581
  DEFAULT_VALUE_ACCESSOR$1
5584
5582
  ],
5585
5583
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
5586
- styles: [":host{width:100%}.mat-form-field.mat-boolean-field-radio{margin-top:-2px}.mat-form-field.mat-boolean-field-button{margin-top:-4px}.mat-form-field .mat-form-field-buttons{width:100%;display:flex;flex-flow:row wrap;justify-content:flex-start;align-items:center}.mat-form-field .mat-form-field-buttons .mat-form-field-button{--flex-basis:calc(100% / var(--buttons-col-count, 2));flex:0 1 var(--flex-basis);max-width:calc(min(var(--flex-basis), 150px));white-space:normal;padding:0 2px;height:40px}"]
5584
+ styles: [":host{width:100%}.mat-form-field.mat-boolean-field-radio{margin-top:-2px}.mat-form-field.mat-boolean-field-button{margin-top:-4px}.mat-form-field .mat-form-field-buttons{width:100%;display:flex;flex-flow:row wrap;justify-content:flex-start;align-items:center}.mat-form-field .mat-form-field-buttons .mat-form-field-button{--flex-basis:calc(100% / var(--buttons-col-count, 2));flex:0 1 var(--flex-basis);max-width:min(var(--flex-basis),150px);white-space:normal;padding:0 2px;height:40px}"]
5587
5585
  },] }
5588
5586
  ];
5589
5587
  MatBooleanField.ctorParameters = function () { return [
@@ -7734,39 +7732,134 @@
7734
7732
  matInput: [{ type: i0.ViewChild, args: ['matInput',] }]
7735
7733
  };
7736
7734
 
7737
- var SYSTEM_SOUNDS = [
7738
- { id: 'beep-confirm', assetPath: 'assets/audio/beep-confirm.mp3', vibration: 250 },
7739
- { id: 'beep-error', assetPath: 'assets/audio/beep-error.mp3', vibration: 1000 },
7740
- { id: 'startup', assetPath: 'assets/audio/unfa-ping.mp3', vibration: [1, 500, 250, 750] },
7741
- ];
7742
- var AudioProvider = /** @class */ (function () {
7743
- function AudioProvider(platform, nativeAudio, vibration, audioManagement) {
7744
- this.platform = platform;
7745
- this.nativeAudio = nativeAudio;
7746
- this.vibration = vibration;
7747
- this.audioManagement = audioManagement;
7748
- this._started = false;
7749
- this._audioMode = ngx$1.AudioManagement.AudioMode.NORMAL;
7750
- this._preloadedSounds = {};
7751
- this._htmlAudioCache = {};
7735
+ var StartableService = /** @class */ (function () {
7736
+ function StartableService(platform) {
7752
7737
  this.onStart = new rxjs.Subject();
7753
- this.start();
7738
+ this._debug = false;
7739
+ this._data = null;
7740
+ this._started = false;
7741
+ this._startPrerequisite = platform
7742
+ ? function () { return platform.ready(); }
7743
+ : function () { return Promise.resolve(); };
7754
7744
  }
7755
- AudioProvider.prototype.ready = function () {
7745
+ StartableService.prototype.start = function () {
7746
+ var _this = this;
7747
+ if (this._startPromise)
7748
+ return this._startPromise;
7749
+ if (this._started)
7750
+ return Promise.resolve(this._data);
7751
+ this._startPromise = this._startPrerequisite()
7752
+ .then(function () { return _this.ngOnStart(); })
7753
+ .then(function (data) {
7754
+ _this._data = data;
7755
+ _this._started = true;
7756
+ _this._startPromise = undefined;
7757
+ _this.onStart.next(_this._data);
7758
+ return _this._data;
7759
+ })
7760
+ .catch(function (err) {
7761
+ console.error('Failed to start a service: ' + (err && err.message || err), err);
7762
+ _this._started = false;
7763
+ _this._startPromise = null;
7764
+ return null;
7765
+ });
7766
+ return this._startPromise;
7767
+ };
7768
+ StartableService.prototype.stop = function () {
7756
7769
  return __awaiter(this, void 0, void 0, function () {
7770
+ var err_1;
7757
7771
  return __generator(this, function (_a) {
7758
7772
  switch (_a.label) {
7759
7773
  case 0:
7760
- if (this._started)
7761
- return [2 /*return*/, Promise.resolve()];
7762
- return [4 /*yield*/, this.start()];
7774
+ _a.trys.push([0, 2, , 3]);
7775
+ return [4 /*yield*/, this.ngOnStop()];
7763
7776
  case 1:
7764
7777
  _a.sent();
7765
- return [2 /*return*/];
7778
+ this._started = false;
7779
+ this._startPromise = undefined;
7780
+ return [3 /*break*/, 3];
7781
+ case 2:
7782
+ err_1 = _a.sent();
7783
+ console.error('Failed to stop a service: ' + (err_1 && err_1.message || err_1), err_1);
7784
+ return [3 /*break*/, 3];
7785
+ case 3: return [2 /*return*/];
7786
+ }
7787
+ });
7788
+ });
7789
+ };
7790
+ StartableService.prototype.restart = function () {
7791
+ return __awaiter(this, void 0, void 0, function () {
7792
+ return __generator(this, function (_a) {
7793
+ switch (_a.label) {
7794
+ case 0:
7795
+ if (!this._startPromise) return [3 /*break*/, 2];
7796
+ return [4 /*yield*/, this._startPromise];
7797
+ case 1:
7798
+ _a.sent(); // Wait end of previous loading
7799
+ _a.label = 2;
7800
+ case 2:
7801
+ if (!this._started) return [3 /*break*/, 4];
7802
+ return [4 /*yield*/, this.stop()];
7803
+ case 3:
7804
+ _a.sent(); // Then stop if started
7805
+ _a.label = 4;
7806
+ case 4: // Then stop if started
7807
+ return [2 /*return*/, this.start()]; // Then start again
7766
7808
  }
7767
7809
  });
7768
7810
  });
7769
7811
  };
7812
+ Object.defineProperty(StartableService.prototype, "started", {
7813
+ get: function () {
7814
+ return this._started;
7815
+ },
7816
+ enumerable: false,
7817
+ configurable: true
7818
+ });
7819
+ Object.defineProperty(StartableService.prototype, "starting", {
7820
+ get: function () {
7821
+ return !!this._startPromise;
7822
+ },
7823
+ enumerable: false,
7824
+ configurable: true
7825
+ });
7826
+ StartableService.prototype.ready = function () {
7827
+ if (this._started)
7828
+ return Promise.resolve(this._data);
7829
+ return this.start();
7830
+ };
7831
+ StartableService.prototype.ngOnStop = function () {
7832
+ return __awaiter(this, void 0, void 0, function () {
7833
+ return __generator(this, function (_a) {
7834
+ return [2 /*return*/];
7835
+ });
7836
+ });
7837
+ };
7838
+ return StartableService;
7839
+ }());
7840
+ StartableService.ctorParameters = function () { return [
7841
+ { type: undefined, decorators: [{ type: i0.Optional }] }
7842
+ ]; };
7843
+
7844
+ var SYSTEM_SOUNDS = [
7845
+ { id: 'beep-confirm', assetPath: 'assets/audio/beep-confirm.mp3', vibration: 250 },
7846
+ { id: 'beep-error', assetPath: 'assets/audio/beep-error.mp3', vibration: 1000 },
7847
+ { id: 'startup', assetPath: 'assets/audio/unfa-ping.mp3', vibration: [1, 500, 250, 750] },
7848
+ ];
7849
+ var AudioProvider = /** @class */ (function (_super) {
7850
+ __extends(AudioProvider, _super);
7851
+ function AudioProvider(platform, nativeAudio, vibration, audioManagement) {
7852
+ var _this = _super.call(this, platform) || this;
7853
+ _this.platform = platform;
7854
+ _this.nativeAudio = nativeAudio;
7855
+ _this.vibration = vibration;
7856
+ _this.audioManagement = audioManagement;
7857
+ _this._audioMode = ngx$1.AudioManagement.AudioMode.NORMAL;
7858
+ _this._preloadedSounds = {};
7859
+ _this._htmlAudioCache = {};
7860
+ _this.start();
7861
+ return _this;
7862
+ }
7770
7863
  AudioProvider.prototype.playBeepConfirm = function () {
7771
7864
  return this.play('beep-confirm', {
7772
7865
  // Vibrate only if in vibration mode
@@ -7830,7 +7923,7 @@
7830
7923
  return __generator(this, function (_a) {
7831
7924
  switch (_a.label) {
7832
7925
  case 0:
7833
- if (!!this._started) return [3 /*break*/, 2];
7926
+ if (!!this.started) return [3 /*break*/, 2];
7834
7927
  return [4 /*yield*/, this.ready()];
7835
7928
  case 1:
7836
7929
  _a.sent();
@@ -7914,7 +8007,7 @@
7914
8007
  return __generator(this, function (_a) {
7915
8008
  switch (_a.label) {
7916
8009
  case 0:
7917
- if (!!this._started) return [3 /*break*/, 2];
8010
+ if (!!this.started) return [3 /*break*/, 2];
7918
8011
  return [4 /*yield*/, this.ready()];
7919
8012
  case 1:
7920
8013
  _a.sent();
@@ -7929,15 +8022,10 @@
7929
8022
  });
7930
8023
  };
7931
8024
  /* -- protected methods -- */
7932
- AudioProvider.prototype.start = function () {
7933
- var _this = this;
7934
- if (this._startPromise)
7935
- return this._startPromise;
7936
- if (this._started)
7937
- return Promise.resolve();
7938
- var cordova;
7939
- this._startPromise = this.platform.ready()
7940
- .then(function () { return __awaiter(_this, void 0, void 0, function () {
8025
+ AudioProvider.prototype.ngOnStart = function () {
8026
+ return __awaiter(this, void 0, void 0, function () {
8027
+ var cordova;
8028
+ var _this = this;
7941
8029
  return __generator(this, function (_a) {
7942
8030
  switch (_a.label) {
7943
8031
  case 0:
@@ -7949,33 +8037,21 @@
7949
8037
  case 1:
7950
8038
  _a.sent();
7951
8039
  _a.label = 2;
7952
- case 2: return [2 /*return*/];
8040
+ case 2:
8041
+ // Pre-loading system sounds
8042
+ console.debug('[audio] Preloading audio sounds...');
8043
+ return [4 /*yield*/, Promise.all(SYSTEM_SOUNDS.map(function (s) {
8044
+ // Disable vibration is cordova not enabled
8045
+ if (!cordova)
8046
+ s.vibration = undefined;
8047
+ return _this.preload(s);
8048
+ }))];
8049
+ case 3:
8050
+ _a.sent();
8051
+ return [2 /*return*/];
7953
8052
  }
7954
8053
  });
7955
- }); })
7956
- // Pre-loading system sounds
7957
- .then(function () {
7958
- console.debug('[audio] Preloading audio sounds...');
7959
- return Promise.all(SYSTEM_SOUNDS.map(function (s) {
7960
- // Disable vibration is cordova not enabled
7961
- if (!cordova)
7962
- s.vibration = undefined;
7963
- return _this.preload(s);
7964
- }));
7965
- })
7966
- .then(function () {
7967
- _this._started = true;
7968
- _this._startPromise = null;
7969
- console.info('[audio] Audio provider started');
7970
- // Emit event
7971
- _this.onStart.next();
7972
- })
7973
- .catch(function (err) {
7974
- console.error('[audio] Unable to start audio provider: ' + (err && err.message || err), err);
7975
- _this._started = false;
7976
- _this._startPromise = null;
7977
8054
  });
7978
- return this._startPromise;
7979
8055
  };
7980
8056
  AudioProvider.prototype.readAudioMode = function () {
7981
8057
  return __awaiter(this, void 0, void 0, function () {
@@ -7993,7 +8069,7 @@
7993
8069
  });
7994
8070
  };
7995
8071
  return AudioProvider;
7996
- }());
8072
+ }(StartableService));
7997
8073
  AudioProvider.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function AudioProvider_Factory() { return new AudioProvider(i0__namespace.ɵɵinject(i1__namespace$4.Platform), i0__namespace.ɵɵinject(i2__namespace.NativeAudio, 8), i0__namespace.ɵɵinject(i3__namespace.Vibration, 8), i0__namespace.ɵɵinject(i4__namespace.AudioManagement, 8)); }, token: AudioProvider, providedIn: "root" });
7998
8074
  AudioProvider.decorators = [
7999
8075
  { type: i0.Injectable, args: [{ providedIn: 'root' },] }
@@ -8979,6 +9055,10 @@
8979
9055
  {
8980
9056
  host: 'sih.sfa.sc',
8981
9057
  port: 80
9058
+ },
9059
+ {
9060
+ host: 'test.sumaris.net',
9061
+ port: 443
8982
9062
  }
8983
9063
  ],
8984
9064
  defaultAppName: 'SUMARiS',
@@ -9591,110 +9671,87 @@
9591
9671
  };
9592
9672
  var APP_LOCAL_SETTINGS = new i0.InjectionToken('DefaultLocalSettings');
9593
9673
  var APP_LOCAL_SETTINGS_OPTIONS = new i0.InjectionToken('LocalSettingsOptions');
9594
- var LocalSettingsService = /** @class */ (function () {
9674
+ var LocalSettingsService = /** @class */ (function (_super) {
9675
+ __extends(LocalSettingsService, _super);
9595
9676
  function LocalSettingsService(translate, platform, storage, environment, defaultSettings, defaultOptionsMap) {
9596
- this.translate = translate;
9597
- this.platform = platform;
9598
- this.storage = storage;
9599
- this.environment = environment;
9600
- this.defaultSettings = defaultSettings;
9601
- this._started = false;
9602
- this.onChange = new rxjs.Subject();
9603
- this.defaultSettings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), this.defaultSettings);
9604
- this._optionDefs = Object.values(defaultOptionsMap);
9605
- this.resetData();
9606
- this._debug = !environment.production;
9607
- if (this._debug)
9677
+ var _this = _super.call(this, platform) || this;
9678
+ _this.translate = translate;
9679
+ _this.platform = platform;
9680
+ _this.storage = storage;
9681
+ _this.environment = environment;
9682
+ _this.defaultSettings = defaultSettings;
9683
+ _this.onChange = new rxjs.Subject();
9684
+ _this.defaultSettings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), _this.defaultSettings);
9685
+ _this._optionDefs = Object.values(defaultOptionsMap);
9686
+ _this.resetData();
9687
+ _this._debug = !environment.production;
9688
+ if (_this._debug)
9608
9689
  console.debug('[settings] Creating service');
9690
+ return _this;
9609
9691
  }
9610
9692
  Object.defineProperty(LocalSettingsService.prototype, "settings", {
9611
9693
  get: function () {
9612
- return this.data || this.defaultSettings;
9694
+ return this._data || this.defaultSettings;
9613
9695
  },
9614
9696
  enumerable: false,
9615
9697
  configurable: true
9616
9698
  });
9617
9699
  Object.defineProperty(LocalSettingsService.prototype, "locale", {
9618
9700
  get: function () {
9619
- return this.data && this.data.locale || this.translate.currentLang || this.translate.defaultLang;
9701
+ return this._data && this._data.locale || this.translate.currentLang || this.translate.defaultLang;
9620
9702
  },
9621
9703
  enumerable: false,
9622
9704
  configurable: true
9623
9705
  });
9624
9706
  Object.defineProperty(LocalSettingsService.prototype, "latLongFormat", {
9625
9707
  get: function () {
9626
- return this.data && this.data.latLongFormat || 'DDMM';
9708
+ return this._data && this._data.latLongFormat || 'DDMM';
9627
9709
  },
9628
9710
  enumerable: false,
9629
9711
  configurable: true
9630
9712
  });
9631
9713
  Object.defineProperty(LocalSettingsService.prototype, "usageMode", {
9632
9714
  get: function () {
9633
- return (this.data && this.data.usageMode || (this.mobile ? 'FIELD' : 'DESK'));
9715
+ return (this._data && this._data.usageMode || (this.mobile ? 'FIELD' : 'DESK'));
9634
9716
  },
9635
9717
  enumerable: false,
9636
9718
  configurable: true
9637
9719
  });
9638
9720
  Object.defineProperty(LocalSettingsService.prototype, "mobile", {
9639
9721
  get: function () {
9640
- return this.data && toBoolean(this.data.mobile, this.platform.is('mobile'));
9722
+ return this._data && toBoolean(this._data.mobile, this.platform.is('mobile'));
9641
9723
  },
9642
9724
  set: function (value) {
9643
- this.data.mobile = value;
9725
+ this._data.mobile = value;
9644
9726
  },
9645
9727
  enumerable: false,
9646
9728
  configurable: true
9647
9729
  });
9648
9730
  Object.defineProperty(LocalSettingsService.prototype, "touchUi", {
9649
9731
  get: function () {
9650
- return this.data.touchUi;
9732
+ return this._data.touchUi;
9651
9733
  },
9652
9734
  set: function (value) {
9653
- this.data.touchUi = value;
9735
+ this._data.touchUi = value;
9654
9736
  },
9655
9737
  enumerable: false,
9656
9738
  configurable: true
9657
9739
  });
9658
9740
  Object.defineProperty(LocalSettingsService.prototype, "pageHistory", {
9659
9741
  get: function () {
9660
- return (this.data && this.data.pageHistory || []);
9742
+ return (this._data && this._data.pageHistory || []);
9661
9743
  },
9662
9744
  enumerable: false,
9663
9745
  configurable: true
9664
9746
  });
9665
- LocalSettingsService.prototype.start = function () {
9666
- var _this = this;
9667
- if (this._startPromise)
9668
- return this._startPromise;
9669
- if (this._started)
9670
- return Promise.resolve(this.data);
9671
- console.info('[settings] Starting settings...');
9747
+ LocalSettingsService.prototype.ngOnStart = function () {
9748
+ console.info('[settings] Starting service...');
9672
9749
  // Restoring local settings
9673
- this._startPromise = this.platform.ready()
9674
- .then(function () {
9675
- _this.data.mobile = isNotNil(_this.data.mobile) ? _this.data.mobile : _this.platform.is('mobile');
9676
- _this.data.touchUi = _this.data.mobile || _this.platform.is('phablet') || _this.platform.is('tablet');
9677
- _this.data.usageMode = _this.platform.is('android') ? 'FIELD' : 'DESK'; // FIELD by default if Android
9678
- })
9679
- .then(function () { return _this.restoreLocally(); })
9680
- .then(function (data) {
9681
- _this._started = true;
9682
- _this._startPromise = undefined;
9683
- return data;
9684
- });
9685
- return this._startPromise;
9686
- };
9687
- Object.defineProperty(LocalSettingsService.prototype, "started", {
9688
- get: function () {
9689
- return this._started;
9690
- },
9691
- enumerable: false,
9692
- configurable: true
9693
- });
9694
- LocalSettingsService.prototype.ready = function () {
9695
- if (this._started)
9696
- return Promise.resolve(this.data);
9697
- return this.start();
9750
+ this._data.mobile = isNotNil(this._data.mobile) ? this._data.mobile : this.platform.is('mobile');
9751
+ this._data.touchUi = this._data.mobile || this.platform.is('phablet') || this.platform.is('tablet');
9752
+ this._data.usageMode = this.platform.is('android') ? 'FIELD' : 'DESK'; // FIELD by default if Android
9753
+ // Restoring local settings
9754
+ return this.restoreLocally();
9698
9755
  };
9699
9756
  LocalSettingsService.prototype.isUsageMode = function (mode) {
9700
9757
  return this.usageMode === mode;
@@ -9704,10 +9761,12 @@
9704
9761
  };
9705
9762
  LocalSettingsService.prototype.restoreLocally = function () {
9706
9763
  return __awaiter(this, void 0, void 0, function () {
9707
- var settingsStr, restoredData_1;
9764
+ var data, settingsStr, restoredData_1;
9708
9765
  return __generator(this, function (_a) {
9709
9766
  switch (_a.label) {
9710
- case 0: return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
9767
+ case 0:
9768
+ data = this._data || {};
9769
+ return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
9711
9770
  case 1:
9712
9771
  settingsStr = _a.sent();
9713
9772
  // Restore local settings (or keep old settings)
@@ -9718,30 +9777,31 @@
9718
9777
  SETTINGS_TRANSIENT_PROPERTIES.forEach(function (transientKey) {
9719
9778
  delete restoredData_1[transientKey];
9720
9779
  });
9721
- this.data = Object.assign(this.data, restoredData_1);
9780
+ // Merge into existing data
9781
+ data = Object.assign(data, restoredData_1);
9722
9782
  }
9723
9783
  // Emit event
9724
- this.onChange.next(this.data);
9725
- return [2 /*return*/, this.data];
9784
+ this.onChange.next(data);
9785
+ return [2 /*return*/, data];
9726
9786
  }
9727
9787
  });
9728
9788
  });
9729
9789
  };
9730
9790
  LocalSettingsService.prototype.setProperty = function (keyOrDef, value) {
9731
- if (!this.data)
9791
+ if (!this._data)
9732
9792
  return;
9733
9793
  if (typeof keyOrDef === 'object') {
9734
9794
  this.setProperty(keyOrDef.key, value);
9735
9795
  return;
9736
9796
  }
9737
- this.data.properties = this.data.properties || {};
9738
- this.data.properties[keyOrDef] = isNil(value) ? undefined : value.toString();
9797
+ this._data.properties = this._data.properties || {};
9798
+ this._data.properties[keyOrDef] = isNil(value) ? undefined : value.toString();
9739
9799
  };
9740
9800
  LocalSettingsService.prototype.getProperty = function (keyOrDef, defaultValue) {
9741
9801
  if (typeof keyOrDef === 'object') {
9742
9802
  return this.getProperty(keyOrDef.key, isNil(defaultValue) ? keyOrDef.defaultValue : defaultValue);
9743
9803
  }
9744
- var value = this.data && this.data.properties && this.data.properties[keyOrDef];
9804
+ var value = this._data && this._data.properties && this._data.properties[keyOrDef];
9745
9805
  return isNotNil(value) ? value : defaultValue;
9746
9806
  };
9747
9807
  LocalSettingsService.prototype.getPropertyAsBoolean = function (definition, defaultValue) {
@@ -9767,19 +9827,25 @@
9767
9827
  return __generator(this, function (_a) {
9768
9828
  switch (_a.label) {
9769
9829
  case 0:
9770
- this.data = Object.assign(Object.assign({}, this.data), settings);
9771
- if (!(opts && opts.persistImmediate)) return [3 /*break*/, 2];
9772
- return [4 /*yield*/, this.persistLocally(true)];
9830
+ if (!!this.started) return [3 /*break*/, 2];
9831
+ return [4 /*yield*/, this.ready()];
9773
9832
  case 1:
9774
9833
  _a.sent();
9775
- return [3 /*break*/, 3];
9834
+ _a.label = 2;
9776
9835
  case 2:
9777
- this.persistLocally(); // No AWAIT
9778
- _a.label = 3;
9836
+ this._data = Object.assign(Object.assign({}, this._data), settings);
9837
+ if (!(opts && opts.persistImmediate)) return [3 /*break*/, 4];
9838
+ return [4 /*yield*/, this.persistLocally(true)];
9779
9839
  case 3:
9840
+ _a.sent();
9841
+ return [3 /*break*/, 5];
9842
+ case 4:
9843
+ this.persistLocally(); // No AWAIT
9844
+ _a.label = 5;
9845
+ case 5:
9780
9846
  // Emit event
9781
9847
  if (!opts || opts.emitEvent !== false) {
9782
- this.onChange.next(this.data);
9848
+ this.onChange.next(this._data);
9783
9849
  }
9784
9850
  return [2 /*return*/];
9785
9851
  }
@@ -9803,27 +9869,27 @@
9803
9869
  });
9804
9870
  };
9805
9871
  LocalSettingsService.prototype.getPageSettings = function (pageId, propertyName) {
9806
- if (!this.data || !this.data.pages)
9872
+ if (!this._data || !this._data.pages)
9807
9873
  return undefined;
9808
9874
  var key = pageId.replace(/[/]/g, '__');
9809
9875
  if (isNotNilOrBlank(propertyName)) {
9810
- return getPropertyByPath(this.data.pages, key + '.' + propertyName);
9876
+ return getPropertyByPath(this._data.pages, key + '.' + propertyName);
9811
9877
  }
9812
- return this.data.pages[key];
9878
+ return this._data.pages[key];
9813
9879
  };
9814
9880
  LocalSettingsService.prototype.savePageSetting = function (pageId, value, propertyName) {
9815
9881
  return __awaiter(this, void 0, void 0, function () {
9816
9882
  var key;
9817
9883
  return __generator(this, function (_a) {
9818
- this.data = this.data || this.defaultSettings;
9819
- this.data.pages = this.data.pages || {};
9884
+ this._data = this._data || this.defaultSettings;
9885
+ this._data.pages = this._data.pages || {};
9820
9886
  key = pageId.replace(/[/]/g, '__');
9821
9887
  if (propertyName) {
9822
- this.data.pages[key] = this.data.pages[key] || {};
9823
- this.data.pages[key][propertyName] = value;
9888
+ this._data.pages[key] = this._data.pages[key] || {};
9889
+ this._data.pages[key][propertyName] = value;
9824
9890
  }
9825
9891
  else {
9826
- this.data.pages[key] = value;
9892
+ this._data.pages[key] = value;
9827
9893
  }
9828
9894
  // Update local settings
9829
9895
  this.persistLocally();
@@ -9832,13 +9898,13 @@
9832
9898
  });
9833
9899
  };
9834
9900
  LocalSettingsService.prototype.getOfflineFeature = function (featureName) {
9835
- if (!this.data || !this.data.offlineFeatures || isEmptyArray(this.data.offlineFeatures))
9901
+ if (!this._data || !this._data.offlineFeatures || isEmptyArray(this._data.offlineFeatures))
9836
9902
  return undefined;
9837
9903
  if (!featureName)
9838
9904
  throw Error('Missing \'featureName\' argument');
9839
9905
  featureName = featureName.toLowerCase();
9840
9906
  var featurePrefix = featureName + '#';
9841
- var feature = this.data.offlineFeatures.find(function (f) {
9907
+ var feature = this._data.offlineFeatures.find(function (f) {
9842
9908
  if (typeof f === 'string')
9843
9909
  return f.toLowerCase().startsWith(featurePrefix);
9844
9910
  if (typeof f === 'object' && f.name)
@@ -9861,24 +9927,24 @@
9861
9927
  LocalSettingsService.prototype.hasOfflineFeature = function (featureName) {
9862
9928
  if (featureName)
9863
9929
  return isNotNil(this.getOfflineFeature(featureName));
9864
- return this.data && isNotEmptyArray(this.data.offlineFeatures);
9930
+ return this._data && isNotEmptyArray(this._data.offlineFeatures);
9865
9931
  };
9866
9932
  LocalSettingsService.prototype.saveOfflineFeature = function (feature) {
9867
- this.data = this.data || this.defaultSettings;
9868
- this.data.offlineFeatures = this.data.offlineFeatures || [];
9933
+ this._data = this._data || this.defaultSettings;
9934
+ this._data.offlineFeatures = this._data.offlineFeatures || [];
9869
9935
  feature.name = feature.name.toLowerCase();
9870
9936
  var featurePrefix = feature.name + '#';
9871
- var existingIndex = this.data.offlineFeatures.findIndex(function (f) {
9937
+ var existingIndex = this._data.offlineFeatures.findIndex(function (f) {
9872
9938
  if (typeof f === 'string')
9873
9939
  return f.toLowerCase().startsWith(featurePrefix);
9874
9940
  if (typeof f === 'object' && f.name)
9875
9941
  return f.name === feature.name;
9876
9942
  });
9877
9943
  if (existingIndex !== -1) {
9878
- this.data.offlineFeatures[existingIndex] = feature;
9944
+ this._data.offlineFeatures[existingIndex] = feature;
9879
9945
  }
9880
9946
  else {
9881
- this.data.offlineFeatures.push(feature);
9947
+ this._data.offlineFeatures.push(feature);
9882
9948
  }
9883
9949
  // Update local settings
9884
9950
  this.persistLocally();
@@ -9897,14 +9963,14 @@
9897
9963
  this.saveOfflineFeature(feature);
9898
9964
  };
9899
9965
  LocalSettingsService.prototype.removeOfflineFeatures = function () {
9900
- if (this.data && this.data.offlineFeatures) {
9901
- this.data.offlineFeatures = [];
9966
+ if (this._data && this._data.offlineFeatures) {
9967
+ this._data.offlineFeatures = [];
9902
9968
  // Update local settings
9903
9969
  this.persistLocally();
9904
9970
  }
9905
9971
  };
9906
9972
  LocalSettingsService.prototype.getFieldDisplayAttributes = function (fieldName, defaultAttributes) {
9907
- var value = this.data && this.data.properties && this.data.properties["sumaris.field." + fieldName + ".attributes"];
9973
+ var value = this._data && this._data.properties && this._data.properties["sumaris.field." + fieldName + ".attributes"];
9908
9974
  // Nothing found in settings: return defaults
9909
9975
  if (!value)
9910
9976
  return defaultAttributes || ['label', 'name'];
@@ -9942,7 +10008,7 @@
9942
10008
  // If not inside recursive call: fill page history defaults
9943
10009
  if (!pageHistory)
9944
10010
  this.fillPageHistoryDefaults(page, opts);
9945
- pageHistory = pageHistory || this.data.pageHistory;
10011
+ pageHistory = pageHistory || this._data.pageHistory;
9946
10012
  index = pageHistory.findIndex(function (p) { return (
9947
10013
  // same path
9948
10014
  p.path === page.path
@@ -9977,10 +10043,10 @@
9977
10043
  _a.sent();
9978
10044
  _a.label = 4;
9979
10045
  case 4:
9980
- if (!(pageHistory === this.data.pageHistory)) return [3 /*break*/, 6];
10046
+ if (!(pageHistory === this._data.pageHistory)) return [3 /*break*/, 6];
9981
10047
  // If max has been reached, remove old pages
9982
- if (this.data.pageHistory.length > this.data.pageHistoryMaxSize) {
9983
- removedPages = pageHistory.splice(this.data.pageHistoryMaxSize, pageHistory.length - this.data.pageHistoryMaxSize);
10048
+ if (this._data.pageHistory.length > this._data.pageHistoryMaxSize) {
10049
+ removedPages = pageHistory.splice(this._data.pageHistoryMaxSize, pageHistory.length - this._data.pageHistoryMaxSize);
9984
10050
  console.debug('[settings] Pages removed from history: ', removedPages);
9985
10051
  }
9986
10052
  // Apply new value
@@ -10002,7 +10068,7 @@
10002
10068
  return __generator(this, function (_a) {
10003
10069
  switch (_a.label) {
10004
10070
  case 0:
10005
- pageHistory = pageHistory || this.data.pageHistory;
10071
+ pageHistory = pageHistory || this._data.pageHistory;
10006
10072
  index = pageHistory.findIndex(function (p) { return p.path === path; });
10007
10073
  found = index !== -1;
10008
10074
  if (found) {
@@ -10017,9 +10083,9 @@
10017
10083
  .filter(isNotEmptyArray)
10018
10084
  .findIndex(function (children) { return _this.removePageHistory(path, opts, children); }) !== -1;
10019
10085
  }
10020
- if (!(found && pageHistory === this.data.pageHistory)) return [3 /*break*/, 2];
10086
+ if (!(found && pageHistory === this._data.pageHistory)) return [3 /*break*/, 2];
10021
10087
  // Apply changes
10022
- return [4 /*yield*/, this.applyProperty('pageHistory', this.data.pageHistory)];
10088
+ return [4 /*yield*/, this.applyProperty('pageHistory', this._data.pageHistory)];
10023
10089
  case 1:
10024
10090
  // Apply changes
10025
10091
  _a.sent();
@@ -10046,27 +10112,27 @@
10046
10112
  };
10047
10113
  /* -- Protected methods -- */
10048
10114
  LocalSettingsService.prototype.resetData = function () {
10049
- this.data = Object.assign(Object.assign({}, this.data), this.defaultSettings);
10050
- this.data.locale = this.translate.currentLang || this.translate.defaultLang;
10051
- this.data.mobile = undefined;
10052
- this.data.usageMode = undefined;
10053
- this.data.pageHistory = [];
10115
+ this._data = Object.assign(Object.assign({}, this._data), this.defaultSettings);
10116
+ this._data.locale = this.translate.currentLang || this.translate.defaultLang;
10117
+ this._data.mobile = undefined;
10118
+ this._data.usageMode = undefined;
10119
+ this._data.pageHistory = [];
10054
10120
  var defaultPeer = this.environment.defaultPeer && exports.Peer.fromObject(this.environment.defaultPeer);
10055
- this.data.peerUrl = defaultPeer && defaultPeer.url || undefined;
10056
- if (this._started)
10057
- this.onChange.next(this.data);
10121
+ this._data.peerUrl = defaultPeer && defaultPeer.url || undefined;
10122
+ if (this.started)
10123
+ this.onChange.next(this._data);
10058
10124
  };
10059
10125
  LocalSettingsService.prototype.persistLocally = function (immediate) {
10060
10126
  var _this = this;
10061
10127
  // Execute immediate
10062
10128
  if (immediate) {
10063
- if (!this.data) {
10129
+ if (!this._data) {
10064
10130
  console.debug('[settings] Removing local settings from storage');
10065
10131
  return this.storage.remove(SETTINGS_STORAGE_KEY);
10066
10132
  }
10067
10133
  else {
10068
- console.debug('[settings] Store local settings', this.data);
10069
- return this.storage.set(SETTINGS_STORAGE_KEY, JSON.stringify(this.data));
10134
+ console.debug('[settings] Store local settings', this._data);
10135
+ return this.storage.set(SETTINGS_STORAGE_KEY, JSON.stringify(this._data));
10070
10136
  }
10071
10137
  }
10072
10138
  // Execute with delay
@@ -10076,7 +10142,7 @@
10076
10142
  this._$persist = new i0.EventEmitter(true);
10077
10143
  this._$persist
10078
10144
  .pipe(operators.debounceTime(2000), // add a delay of 2s
10079
- operators.filter(function () { return _this._started; }))
10145
+ operators.filter(function () { return _this.started; }))
10080
10146
  .subscribe(function () { return _this.persistLocally(true); });
10081
10147
  }
10082
10148
  this._$persist.emit();
@@ -10102,7 +10168,7 @@
10102
10168
  return page;
10103
10169
  };
10104
10170
  return LocalSettingsService;
10105
- }());
10171
+ }(StartableService));
10106
10172
  LocalSettingsService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function LocalSettingsService_Factory() { return new LocalSettingsService(i0__namespace.ɵɵinject(i1__namespace$1.TranslateService), i0__namespace.ɵɵinject(i1__namespace$4.Platform), i0__namespace.ɵɵinject(i3__namespace$1.Storage), i0__namespace.ɵɵinject(ENVIRONMENT), i0__namespace.ɵɵinject(APP_LOCAL_SETTINGS, 8), i0__namespace.ɵɵinject(APP_LOCAL_SETTINGS_OPTIONS, 8)); }, token: LocalSettingsService, providedIn: "root" });
10107
10173
  LocalSettingsService.decorators = [
10108
10174
  { type: i0.Injectable, args: [{
@@ -10249,6 +10315,8 @@
10249
10315
  switch (type) {
10250
10316
  case ngx$4.Connection.NONE:
10251
10317
  return 'none';
10318
+ case ngx$4.Connection.ETHERNET:
10319
+ return 'ethernet';
10252
10320
  case ngx$4.Connection.WIFI:
10253
10321
  return 'wifi';
10254
10322
  case ngx$4.Connection.CELL:
@@ -10256,8 +10324,6 @@
10256
10324
  case ngx$4.Connection.CELL_3G:
10257
10325
  case ngx$4.Connection.CELL_4G:
10258
10326
  return 'cell';
10259
- case ngx$4.Connection.ETHERNET:
10260
- return 'ethernet';
10261
10327
  case ngx$4.Connection.UNKNOWN:
10262
10328
  return 'unknown';
10263
10329
  default:
@@ -10273,41 +10339,42 @@
10273
10339
  MOBILE: 1000,
10274
10340
  DESKTOP: 1000
10275
10341
  }*/
10276
- var NetworkService = /** @class */ (function () {
10342
+ var NetworkService = /** @class */ (function (_super) {
10343
+ __extends(NetworkService, _super);
10277
10344
  function NetworkService(_document, platform, modalCtrl, cryptoService, storage, settings, cache, http, environment, network, splashScreen, translate, toastController) {
10278
- var _this = this;
10279
- this._document = _document;
10280
- this.platform = platform;
10281
- this.modalCtrl = modalCtrl;
10282
- this.cryptoService = cryptoService;
10283
- this.storage = storage;
10284
- this.settings = settings;
10285
- this.cache = cache;
10286
- this.http = http;
10287
- this.environment = environment;
10288
- this.network = network;
10289
- this.splashScreen = splashScreen;
10290
- this.translate = translate;
10291
- this.toastController = toastController;
10292
- this._started = false;
10293
- this._subscription = new rxjs.Subscription();
10294
- this._listeners = {};
10295
- this.onStart = new rxjs.Subject();
10296
- this.onPeerChanges = this.onStart.pipe(operators.map(function (peer) { return peer && peer.url; }), operators.filter(isNotNilOrBlank), operators.distinctUntilChanged());
10297
- this.onNetworkStatusChanges = new rxjs.BehaviorSubject(null);
10298
- this.onResetNetworkCache = new i0.EventEmitter(true);
10299
- this._mobile = this.platform.is('mobile');
10300
- if (this._mobile) {
10301
- this._timerRefreshPeriod = NetworkRefreshTimerPeriod.MOBILE;
10302
- this._timerRefreshCondition = function () { return _this.online; }; // Check only when online, and stop when offline
10345
+ var _this = _super.call(this, platform) || this;
10346
+ _this._document = _document;
10347
+ _this.platform = platform;
10348
+ _this.modalCtrl = modalCtrl;
10349
+ _this.cryptoService = cryptoService;
10350
+ _this.storage = storage;
10351
+ _this.settings = settings;
10352
+ _this.cache = cache;
10353
+ _this.http = http;
10354
+ _this.environment = environment;
10355
+ _this.network = network;
10356
+ _this.splashScreen = splashScreen;
10357
+ _this.translate = translate;
10358
+ _this.toastController = toastController;
10359
+ _this.onPeerChanges = _this.onStart.pipe(operators.map(function (peer) { return peer && peer.url; }), operators.filter(isNotNilOrBlank), operators.distinctUntilChanged());
10360
+ _this.onNetworkStatusChanges = new rxjs.BehaviorSubject(null);
10361
+ _this.onResetNetworkCache = new i0.EventEmitter(true);
10362
+ _this._subscription = new rxjs.Subscription();
10363
+ _this._listeners = {};
10364
+ _this._mobile = _this.platform.is('mobile');
10365
+ if (_this._mobile) {
10366
+ _this._timerRefreshPeriod = NetworkRefreshTimerPeriod.MOBILE;
10367
+ _this._timerRefreshCondition = function () { return _this.online; }; // Check only when online, and stop when offline
10303
10368
  }
10304
10369
  else {
10305
- this._timerRefreshPeriod = NetworkRefreshTimerPeriod.DESKTOP;
10306
- this._timerRefreshCondition = function () { return true; }; // Always check
10370
+ _this._timerRefreshPeriod = NetworkRefreshTimerPeriod.DESKTOP;
10371
+ _this._timerRefreshCondition = function () { return true; }; // Always check
10307
10372
  }
10308
- this.resetData();
10373
+ _this.resetData();
10374
+ _this.onStart.subscribe(function () { return _this.ngOnAfterStart(); });
10309
10375
  // For DEV only
10310
- this._debug = !environment.production;
10376
+ _this._debug = !environment.production;
10377
+ return _this;
10311
10378
  }
10312
10379
  Object.defineProperty(NetworkService.prototype, "online", {
10313
10380
  get: function () {
@@ -10328,24 +10395,18 @@
10328
10395
  // If force offline: return 'none'
10329
10396
  return this._forceOffline && 'none'
10330
10397
  // Else, return device connection type (or unknown)
10331
- || (this._started && this._deviceConnectionType || 'unknown');
10398
+ || (this.started && this._deviceConnectionType || 'unknown');
10332
10399
  },
10333
10400
  enumerable: false,
10334
10401
  configurable: true
10335
10402
  });
10336
10403
  Object.defineProperty(NetworkService.prototype, "peer", {
10337
10404
  get: function () {
10338
- return this._peer && this._peer.clone();
10405
+ return this._data && this._data.clone();
10339
10406
  },
10340
10407
  set: function (peer) {
10341
- this.restart(peer);
10342
- },
10343
- enumerable: false,
10344
- configurable: true
10345
- });
10346
- Object.defineProperty(NetworkService.prototype, "started", {
10347
- get: function () {
10348
- return this._started;
10408
+ this._startingPeer = peer;
10409
+ this.restart();
10349
10410
  },
10350
10411
  enumerable: false,
10351
10412
  configurable: true
@@ -10370,109 +10431,11 @@
10370
10431
  return this.addListener(eventType, callback);
10371
10432
  }
10372
10433
  };
10373
- NetworkService.prototype.start = function (peer) {
10374
- return __awaiter(this, void 0, void 0, function () {
10375
- var _this = this;
10376
- return __generator(this, function (_a) {
10377
- if (this._startPromise)
10378
- return [2 /*return*/, this._startPromise];
10379
- if (this._started)
10380
- return [2 /*return*/];
10381
- console.info('[network] Starting network...');
10382
- // Restoring local settings
10383
- this._startPromise = (!peer && this.restoreLocally() || Promise.resolve(peer))
10384
- .then(function (peer) { return __awaiter(_this, void 0, void 0, function () {
10385
- return __generator(this, function (_a) {
10386
- switch (_a.label) {
10387
- case 0:
10388
- // Make sure to hide the splashscreen, before open the modal
10389
- if (!peer && this.splashScreen)
10390
- this.splashScreen.hide();
10391
- _a.label = 1;
10392
- case 1:
10393
- if (!!peer) return [3 /*break*/, 3];
10394
- console.debug('[network] No peer defined. Asking user to choose a peer.');
10395
- return [4 /*yield*/, this.showSelectPeerModal({ allowSelectDownPeer: false })];
10396
- case 2:
10397
- peer = _a.sent();
10398
- return [3 /*break*/, 1];
10399
- case 3:
10400
- this._peer = peer;
10401
- this._started = true;
10402
- this._startPromise = undefined;
10403
- this.onStart.next(peer);
10404
- console.info("[platform] Starting network [OK] {online: " + this.online + "}");
10405
- return [2 /*return*/];
10406
- }
10407
- });
10408
- }); })
10409
- .catch(function (err) {
10410
- console.error(err && err.message || err, err);
10411
- _this._started = false;
10412
- _this._startPromise = undefined;
10413
- })
10414
- // Wait settings starts, then save peer in settings
10415
- .then(function () { return _this.settings.ready(); })
10416
- .then(function () { return _this.settings.apply({ peerUrl: _this._peer.url }); })
10417
- .then(function () { return _this.onDeviceConnectionChanged(_this.network && _this.network.type || 'unknown'); })
10418
- // Start the refresh timer
10419
- .then(function () { return _this.startRefreshTimer(); });
10420
- // Listen for device network changes
10421
- if (this.network) {
10422
- this._subscription.add(this.network.onDisconnect().subscribe(function () { return _this.onDeviceConnectionChanged('none'); }));
10423
- this._subscription.add(this.network.onConnect().subscribe(function () { return _this.onDeviceConnectionChanged(_this.network.type); }));
10424
- }
10425
- return [2 /*return*/, this._startPromise];
10426
- });
10427
- });
10428
- };
10429
- NetworkService.prototype.ready = function () {
10430
- if (this._started)
10431
- return Promise.resolve();
10432
- return this.start();
10433
- };
10434
- NetworkService.prototype.stop = function () {
10435
- return __awaiter(this, void 0, void 0, function () {
10436
- return __generator(this, function (_a) {
10437
- this.resetData();
10438
- this._started = false;
10439
- this._startPromise = undefined;
10440
- // Stop timer if cannot refresh anymore
10441
- if (this._timerRefreshCondition() === false) {
10442
- this.stopRefreshTimer();
10443
- }
10444
- this._subscription.unsubscribe();
10445
- this._subscription = new rxjs.Subscription();
10446
- return [2 /*return*/];
10447
- });
10448
- });
10449
- };
10450
- NetworkService.prototype.restart = function (peer) {
10434
+ NetworkService.prototype.tryOnline = function (opts) {
10451
10435
  return __awaiter(this, void 0, void 0, function () {
10452
- var _this = this;
10453
- return __generator(this, function (_a) {
10454
- switch (_a.label) {
10455
- case 0:
10456
- if (!this._started) return [3 /*break*/, 2];
10457
- return [4 /*yield*/, this.stop()
10458
- .then(function () { return _this.start(peer); })];
10459
- case 1:
10460
- _a.sent();
10461
- return [3 /*break*/, 4];
10462
- case 2: return [4 /*yield*/, this.start(peer)];
10463
- case 3:
10464
- _a.sent();
10465
- _a.label = 4;
10466
- case 4: return [2 /*return*/];
10467
- }
10468
- });
10469
- });
10470
- };
10471
- NetworkService.prototype.tryOnline = function (opts) {
10472
- return __awaiter(this, void 0, void 0, function () {
10473
- var now, showLoadingToast, loadingToast, settings, peer, peerInfo, peerAliveAndCompatible, _a, err_1, online;
10474
- return __generator(this, function (_b) {
10475
- switch (_b.label) {
10436
+ var now, showLoadingToast, loadingToast, settings, peer, peerInfo, peerAliveAndCompatible, _b, err_1, online;
10437
+ return __generator(this, function (_c) {
10438
+ switch (_c.label) {
10476
10439
  case 0:
10477
10440
  // If offline mode not forced, and device says there is no connection: skip
10478
10441
  if (!this._forceOffline || this._deviceConnectionType === 'none')
@@ -10483,57 +10446,57 @@
10483
10446
  return [4 /*yield*/, this.showToast({ message: 'NETWORK.INFO.RETRY_TO_CONNECT',
10484
10447
  duration: 10000, onWillPresent: function (t) { return loadingToast = t; } })];
10485
10448
  case 1:
10486
- _b.sent();
10487
- _b.label = 2;
10449
+ _c.sent();
10450
+ _c.label = 2;
10488
10451
  case 2:
10489
- _b.trys.push([2, 10, , 11]);
10452
+ _c.trys.push([2, 10, , 11]);
10490
10453
  console.info('[network] Checking connection to pod...');
10491
10454
  return [4 /*yield*/, this.settings.ready()];
10492
10455
  case 3:
10493
- settings = _b.sent();
10456
+ settings = _c.sent();
10494
10457
  if (!settings.peerUrl)
10495
10458
  return [2 /*return*/, false]; // No peer define. Skip
10496
10459
  peer = exports.Peer.parseUrl(settings.peerUrl);
10497
10460
  return [4 /*yield*/, this.checkPeerAlive(peer)];
10498
10461
  case 4:
10499
- peerInfo = _b.sent();
10500
- _a = peerInfo;
10501
- if (!_a) return [3 /*break*/, 6];
10462
+ peerInfo = _c.sent();
10463
+ _b = peerInfo;
10464
+ if (!_b) return [3 /*break*/, 6];
10502
10465
  return [4 /*yield*/, this.checkPeerCompatible(peerInfo)];
10503
10466
  case 5:
10504
- _a = (_b.sent());
10505
- _b.label = 6;
10467
+ _b = (_c.sent());
10468
+ _c.label = 6;
10506
10469
  case 6:
10507
- peerAliveAndCompatible = _a;
10470
+ peerAliveAndCompatible = _b;
10508
10471
  if (!peerAliveAndCompatible) return [3 /*break*/, 9];
10509
10472
  // Disable the offline mode
10510
10473
  this.setForceOffline(false);
10511
10474
  // Restart
10512
- return [4 /*yield*/, this.restart(peer)];
10475
+ this._startingPeer = peer;
10476
+ return [4 /*yield*/, this.restart()];
10513
10477
  case 7:
10514
- // Restart
10515
- _b.sent();
10478
+ _c.sent();
10516
10479
  // Wait a promise, before recheck
10517
10480
  return [4 /*yield*/, this.emit('beforeTryOnlineFinish', this.online)];
10518
10481
  case 8:
10519
10482
  // Wait a promise, before recheck
10520
- _b.sent();
10521
- _b.label = 9;
10483
+ _c.sent();
10484
+ _c.label = 9;
10522
10485
  case 9: return [3 /*break*/, 11];
10523
10486
  case 10:
10524
- err_1 = _b.sent();
10487
+ err_1 = _c.sent();
10525
10488
  console.error(err_1 && err_1.message || err_1);
10526
10489
  return [3 /*break*/, 11];
10527
10490
  case 11:
10528
10491
  if (!showLoadingToast) return [3 /*break*/, 14];
10529
10492
  return [4 /*yield*/, sleep(2000 - (Date.now() - now))];
10530
10493
  case 12:
10531
- _b.sent();
10494
+ _c.sent();
10532
10495
  if (!loadingToast) return [3 /*break*/, 14];
10533
10496
  return [4 /*yield*/, loadingToast.dismiss()];
10534
10497
  case 13:
10535
- _b.sent();
10536
- _b.label = 14;
10498
+ _c.sent();
10499
+ _c.label = 14;
10537
10500
  case 14:
10538
10501
  online = this.online;
10539
10502
  // Display a toast to user
@@ -10547,7 +10510,7 @@
10547
10510
  // Display toast (without await, because not need to wait toast close event)
10548
10511
  return [2 /*return*/, this.showOfflineToast({ showRetryButton: false })];
10549
10512
  }
10550
- return [2 /*return*/, this._started && online];
10513
+ return [2 /*return*/, this.started && online];
10551
10514
  }
10552
10515
  });
10553
10516
  });
@@ -10555,8 +10518,8 @@
10555
10518
  NetworkService.prototype.showOfflineToast = function (opts) {
10556
10519
  return __awaiter(this, void 0, void 0, function () {
10557
10520
  var toastResult, online;
10558
- return __generator(this, function (_a) {
10559
- switch (_a.label) {
10521
+ return __generator(this, function (_b) {
10522
+ switch (_b.label) {
10560
10523
  case 0:
10561
10524
  if (this.online)
10562
10525
  return [2 /*return*/]; // Skip if online
@@ -10575,7 +10538,7 @@
10575
10538
  ]
10576
10539
  })];
10577
10540
  case 1:
10578
- toastResult = _a.sent();
10541
+ toastResult = _b.sent();
10579
10542
  // User don't click reconnect: return
10580
10543
  if (!toastResult || toastResult.role !== 'refresh')
10581
10544
  return [2 /*return*/, false];
@@ -10588,7 +10551,7 @@
10588
10551
  showLoadingToast: toBoolean(opts && opts.showRetryLoadingToast, true)
10589
10552
  })];
10590
10553
  case 2:
10591
- online = _a.sent();
10554
+ online = _b.sent();
10592
10555
  if (online) {
10593
10556
  // Call success callback (async)
10594
10557
  if (opts && opts.onRetrySuccess) {
@@ -10597,7 +10560,7 @@
10597
10560
  return [2 /*return*/, true];
10598
10561
  }
10599
10562
  opts = Object.assign(Object.assign({}, opts), { showRetryButton: false, showCloseButton: true });
10600
- _a.label = 3;
10563
+ _b.label = 3;
10601
10564
  case 3:
10602
10565
  // Simple toast, without 'await', because not need to wait toast's dismiss
10603
10566
  this.showToast(Object.assign({ message: 'ERROR.NETWORK_REQUIRED', type: 'error' }, opts));
@@ -10606,97 +10569,6 @@
10606
10569
  });
10607
10570
  });
10608
10571
  };
10609
- /**
10610
- * Try to restore peer from the local storage
10611
- */
10612
- NetworkService.prototype.restoreLocally = function () {
10613
- return __awaiter(this, void 0, void 0, function () {
10614
- var settingsStr, settings, location, hostname, detectedPeer;
10615
- return __generator(this, function (_a) {
10616
- switch (_a.label) {
10617
- case 0: return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
10618
- case 1:
10619
- settingsStr = _a.sent();
10620
- settings = settingsStr && JSON.parse(settingsStr) || undefined;
10621
- if (settings && settings.peerUrl) {
10622
- console.debug("[network] Use peer {" + settings.peerUrl + "} (found in the local storage)");
10623
- return [2 /*return*/, exports.Peer.parseUrl(settings.peerUrl)];
10624
- }
10625
- // Else, use default peer in env, if exists
10626
- if (this.environment.defaultPeer) {
10627
- return [2 /*return*/, exports.Peer.fromObject(this.environment.defaultPeer)];
10628
- }
10629
- location = this._document && this._document.location;
10630
- if (!(location && location.protocol && location.protocol.startsWith('http'))) return [3 /*break*/, 3];
10631
- hostname = this._document.location.host;
10632
- detectedPeer = exports.Peer.parseUrl("" + this._document.location.protocol + hostname + this.environment.baseUrl);
10633
- return [4 /*yield*/, this.checkPeerAlive(detectedPeer)];
10634
- case 2:
10635
- if (_a.sent()) {
10636
- return [2 /*return*/, detectedPeer];
10637
- }
10638
- _a.label = 3;
10639
- case 3: return [2 /*return*/, undefined];
10640
- }
10641
- });
10642
- });
10643
- };
10644
- /**
10645
- * Refresh network state, using a ping to pod
10646
- */
10647
- NetworkService.prototype.refreshPeerState = function (opts) {
10648
- return __awaiter(this, void 0, void 0, function () {
10649
- return __generator(this, function (_a) {
10650
- return [2 /*return*/];
10651
- });
10652
- });
10653
- };
10654
- /**
10655
- * Stop to network state
10656
- *
10657
- * @protected
10658
- */
10659
- NetworkService.prototype.stopRefreshTimer = function () {
10660
- if (this._timerSubscription) {
10661
- this._timerSubscription.unsubscribe();
10662
- this._timerSubscription = undefined;
10663
- }
10664
- };
10665
- /**
10666
- * Refresh the network state
10667
- *
10668
- * @protected
10669
- */
10670
- NetworkService.prototype.startRefreshTimer = function () {
10671
- var _this = this;
10672
- if (this._timerSubscription)
10673
- return; // Already running: skip
10674
- console.info("[network] Starting refresh timer, every " + this._timerRefreshPeriod + "ms...");
10675
- var lastInfo;
10676
- this._timerSubscription = rxjs.timer(this._timerRefreshPeriod, this._timerRefreshPeriod)
10677
- .pipe(
10678
- // Skip some timer event (see constructor)
10679
- operators.filter(this._timerRefreshCondition),
10680
- // Checkin if peer alive
10681
- operators.tap(function () { return console.debug('[network] Checking connection to pod...'); }), operators.mergeMap(function () { return _this.checkPeerAlive(_this.peer); }),
10682
- // Filter to keep only changes
10683
- operators.filter(function (info) { return !!info !== !!lastInfo; }), operators.tap(function (info) { return lastInfo = info; }),
10684
- // Check compatibility
10685
- operators.mergeMap(function (info) { return _this.checkPeerCompatible(info, { showToast: true }); }))
10686
- .subscribe(function (alive) {
10687
- if (alive && _this.offline) {
10688
- _this.setForceOffline(false);
10689
- // Restart the service (to force re auth)
10690
- _this.restart();
10691
- }
10692
- else if (!alive && _this.online) {
10693
- _this.setForceOffline(true);
10694
- // Stop the service
10695
- _this.stop();
10696
- }
10697
- });
10698
- this._timerSubscription.add(function () { return console.debug('[network] Refresh timer stopped'); });
10699
- };
10700
10572
  /**
10701
10573
  * Check if the peer is alive
10702
10574
  *
@@ -10705,24 +10577,24 @@
10705
10577
  NetworkService.prototype.checkPeerAlive = function (peer, opts) {
10706
10578
  return __awaiter(this, void 0, void 0, function () {
10707
10579
  var settings, err_2;
10708
- return __generator(this, function (_a) {
10709
- switch (_a.label) {
10580
+ return __generator(this, function (_b) {
10581
+ switch (_b.label) {
10710
10582
  case 0:
10711
10583
  peer = peer || this.peer;
10712
10584
  if (!!peer) return [3 /*break*/, 2];
10713
10585
  return [4 /*yield*/, this.settings.ready()];
10714
10586
  case 1:
10715
- settings = _a.sent();
10587
+ settings = _b.sent();
10716
10588
  if (!settings.peerUrl)
10717
10589
  return [2 /*return*/, undefined]; // No peer define. Skip
10718
10590
  peer = exports.Peer.parseUrl(settings.peerUrl);
10719
- _a.label = 2;
10591
+ _b.label = 2;
10720
10592
  case 2:
10721
- _a.trys.push([2, 4, , 5]);
10593
+ _b.trys.push([2, 4, , 5]);
10722
10594
  return [4 /*yield*/, this.getNodeInfo(peer)];
10723
- case 3: return [2 /*return*/, _a.sent()];
10595
+ case 3: return [2 /*return*/, _b.sent()];
10724
10596
  case 4:
10725
- err_2 = _a.sent();
10597
+ err_2 = _b.sent();
10726
10598
  console.debug('[network] Cannot get /api/node/info from peer: ' + (err_2 && err_2.message || err_2), err_2);
10727
10599
  return [2 /*return*/, undefined];
10728
10600
  case 5: return [2 /*return*/];
@@ -10733,8 +10605,8 @@
10733
10605
  NetworkService.prototype.checkPeerCompatible = function (peerInfo, opts) {
10734
10606
  return __awaiter(this, void 0, void 0, function () {
10735
10607
  var isCompatible;
10736
- return __generator(this, function (_a) {
10737
- switch (_a.label) {
10608
+ return __generator(this, function (_b) {
10609
+ switch (_b.label) {
10738
10610
  case 0:
10739
10611
  if (!this.environment.peerMinVersion)
10740
10612
  return [2 /*return*/, true]; // Skip compatibility check
@@ -10749,8 +10621,8 @@
10749
10621
  showCloseButton: true
10750
10622
  })];
10751
10623
  case 1:
10752
- _a.sent();
10753
- _a.label = 2;
10624
+ _b.sent();
10625
+ _b.label = 2;
10754
10626
  case 2: return [2 /*return*/, isCompatible];
10755
10627
  }
10756
10628
  });
@@ -10790,8 +10662,8 @@
10790
10662
  return __awaiter(this, void 0, void 0, function () {
10791
10663
  var $onRefresh, peers$, modal, data;
10792
10664
  var _this = this;
10793
- return __generator(this, function (_a) {
10794
- switch (_a.label) {
10665
+ return __generator(this, function (_b) {
10666
+ switch (_b.label) {
10795
10667
  case 0:
10796
10668
  opts = opts || {};
10797
10669
  $onRefresh = new i0.EventEmitter();
@@ -10808,14 +10680,14 @@
10808
10680
  showBackdrop: true
10809
10681
  })];
10810
10682
  case 1:
10811
- modal = _a.sent();
10683
+ modal = _b.sent();
10812
10684
  return [4 /*yield*/, modal.present()];
10813
10685
  case 2:
10814
- _a.sent();
10686
+ _b.sent();
10815
10687
  $onRefresh.emit();
10816
10688
  return [4 /*yield*/, modal.onWillDismiss()];
10817
10689
  case 3:
10818
- data = (_a.sent()).data;
10690
+ data = (_b.sent()).data;
10819
10691
  $onRefresh.complete();
10820
10692
  return [2 /*return*/, data && data || undefined];
10821
10693
  }
@@ -10826,7 +10698,7 @@
10826
10698
  return __awaiter(this, void 0, void 0, function () {
10827
10699
  var now;
10828
10700
  var _this = this;
10829
- return __generator(this, function (_a) {
10701
+ return __generator(this, function (_b) {
10830
10702
  now = this._debug && Date.now();
10831
10703
  console.info('[network] Clearing all caches...');
10832
10704
  return [2 /*return*/, this.cache.clearAll()
@@ -10845,10 +10717,164 @@
10845
10717
  });
10846
10718
  });
10847
10719
  };
10720
+ /* -- protected functions -- */
10721
+ NetworkService.prototype.ngOnStart = function () {
10722
+ return __awaiter(this, void 0, void 0, function () {
10723
+ var peer, _b;
10724
+ return __generator(this, function (_c) {
10725
+ switch (_c.label) {
10726
+ case 0:
10727
+ console.info('[network] Starting network...', this._startingPeer);
10728
+ _b = this._startingPeer;
10729
+ if (_b) return [3 /*break*/, 2];
10730
+ return [4 /*yield*/, this.restoreLocally()];
10731
+ case 1:
10732
+ _b = (_c.sent());
10733
+ _c.label = 2;
10734
+ case 2:
10735
+ peer = _b;
10736
+ // Make sure to hide the splashscreen, before open the modal
10737
+ if (!peer && this.splashScreen)
10738
+ this.splashScreen.hide();
10739
+ _c.label = 3;
10740
+ case 3:
10741
+ if (!!peer) return [3 /*break*/, 5];
10742
+ console.debug('[network] No peer defined. Asking user to choose a peer.');
10743
+ return [4 /*yield*/, this.showSelectPeerModal({ allowSelectDownPeer: false })];
10744
+ case 4:
10745
+ peer = _c.sent();
10746
+ return [3 /*break*/, 3];
10747
+ case 5:
10748
+ console.info("[network] Starting service [OK] {peer: '" + peer.url + "', online: " + this.online + "}");
10749
+ return [2 /*return*/, peer];
10750
+ }
10751
+ });
10752
+ });
10753
+ };
10754
+ NetworkService.prototype.ngOnAfterStart = function () {
10755
+ var _a;
10756
+ return __awaiter(this, void 0, void 0, function () {
10757
+ var _this = this;
10758
+ return __generator(this, function (_b) {
10759
+ switch (_b.label) {
10760
+ case 0:
10761
+ // Wait settings starts, then save peer in settings
10762
+ return [4 /*yield*/, this.settings.apply({ peerUrl: this._data.url })];
10763
+ case 1:
10764
+ // Wait settings starts, then save peer in settings
10765
+ _b.sent();
10766
+ this.onDeviceConnectionChanged(((_a = this.network) === null || _a === void 0 ? void 0 : _a.type) || 'unknown');
10767
+ // Start the refresh timer
10768
+ this.startRefreshTimer();
10769
+ // Listen for device network changes
10770
+ if (this.network) {
10771
+ this._subscription.add(this.network.onDisconnect().subscribe(function () { return _this.onDeviceConnectionChanged('none'); }));
10772
+ this._subscription.add(this.network.onConnect().subscribe(function () { return _this.onDeviceConnectionChanged(_this.network.type); }));
10773
+ }
10774
+ return [2 /*return*/];
10775
+ }
10776
+ });
10777
+ });
10778
+ };
10779
+ NetworkService.prototype.ngOnStop = function () {
10780
+ return __awaiter(this, void 0, void 0, function () {
10781
+ return __generator(this, function (_b) {
10782
+ this.resetData();
10783
+ // Stop timer if cannot refresh anymore
10784
+ if (this._timerRefreshCondition() === false) {
10785
+ this.stopRefreshTimer();
10786
+ }
10787
+ this._subscription.unsubscribe();
10788
+ this._subscription = new rxjs.Subscription();
10789
+ return [2 /*return*/];
10790
+ });
10791
+ });
10792
+ };
10793
+ /**
10794
+ * Try to restore peer from the local storage
10795
+ */
10796
+ NetworkService.prototype.restoreLocally = function () {
10797
+ return __awaiter(this, void 0, void 0, function () {
10798
+ var settingsStr, settings, location, hostname, detectedPeer;
10799
+ return __generator(this, function (_b) {
10800
+ switch (_b.label) {
10801
+ case 0: return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
10802
+ case 1:
10803
+ settingsStr = _b.sent();
10804
+ settings = settingsStr && JSON.parse(settingsStr) || undefined;
10805
+ if (settings && settings.peerUrl) {
10806
+ console.debug("[network] Use peer {" + settings.peerUrl + "} (found in the local storage)");
10807
+ return [2 /*return*/, exports.Peer.parseUrl(settings.peerUrl)];
10808
+ }
10809
+ // Else, use default peer in env, if exists
10810
+ if (this.environment.defaultPeer) {
10811
+ return [2 /*return*/, exports.Peer.fromObject(this.environment.defaultPeer)];
10812
+ }
10813
+ location = this._document && this._document.location;
10814
+ if (!(location && location.protocol && location.protocol.startsWith('http'))) return [3 /*break*/, 3];
10815
+ hostname = this._document.location.host;
10816
+ detectedPeer = exports.Peer.parseUrl("" + this._document.location.protocol + hostname + this.environment.baseUrl);
10817
+ return [4 /*yield*/, this.checkPeerAlive(detectedPeer)];
10818
+ case 2:
10819
+ if (_b.sent()) {
10820
+ return [2 /*return*/, detectedPeer];
10821
+ }
10822
+ _b.label = 3;
10823
+ case 3: return [2 /*return*/, undefined];
10824
+ }
10825
+ });
10826
+ });
10827
+ };
10828
+ /**
10829
+ * Stop to network state
10830
+ *
10831
+ * @protected
10832
+ */
10833
+ NetworkService.prototype.stopRefreshTimer = function () {
10834
+ if (this._timerSubscription) {
10835
+ this._timerSubscription.unsubscribe();
10836
+ this._timerSubscription = undefined;
10837
+ }
10838
+ };
10839
+ /**
10840
+ * Refresh the network state
10841
+ *
10842
+ * @protected
10843
+ */
10844
+ NetworkService.prototype.startRefreshTimer = function () {
10845
+ var _this = this;
10846
+ if (this._timerSubscription)
10847
+ return; // Already running: skip
10848
+ console.info("[network] Starting refresh timer, every " + this._timerRefreshPeriod + "ms...");
10849
+ var lastInfo;
10850
+ this._timerSubscription = rxjs.timer(this._timerRefreshPeriod, this._timerRefreshPeriod)
10851
+ .pipe(
10852
+ // Skip some timer event (see constructor)
10853
+ operators.filter(this._timerRefreshCondition),
10854
+ // Checkin if peer alive
10855
+ operators.tap(function () { return console.debug('[network] Checking connection to pod...'); }), operators.mergeMap(function () { return _this.checkPeerAlive(_this.peer); }),
10856
+ // Filter to keep only changes
10857
+ operators.filter(function (info) { return !!info !== !!lastInfo; }), operators.tap(function (info) { return lastInfo = info; }),
10858
+ // Check compatibility
10859
+ operators.mergeMap(function (info) { return _this.checkPeerCompatible(info, { showToast: true }); }))
10860
+ .subscribe(function (alive) {
10861
+ if (alive && _this.offline) {
10862
+ _this.setForceOffline(false);
10863
+ // Restart the service (to force re auth)
10864
+ _this.restart();
10865
+ }
10866
+ else if (!alive && _this.online) {
10867
+ _this.setForceOffline(true);
10868
+ // Stop the service
10869
+ _this.stop();
10870
+ }
10871
+ });
10872
+ this._timerSubscription.add(function () { return console.debug('[network] Refresh timer stopped'); });
10873
+ };
10848
10874
  NetworkService.prototype.get = function (path, opts) {
10849
10875
  return __awaiter(this, void 0, void 0, function () {
10850
10876
  var uri, peerUrl;
10851
- return __generator(this, function (_a) {
10877
+ return __generator(this, function (_b) {
10852
10878
  uri = path;
10853
10879
  // If path is not an URI: prepend with peer URL
10854
10880
  if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
@@ -10899,7 +10925,7 @@
10899
10925
  }
10900
10926
  };
10901
10927
  NetworkService.prototype.resetData = function () {
10902
- this._peer = null;
10928
+ this._data = null;
10903
10929
  };
10904
10930
  /**
10905
10931
  * Get default peers, from environment
@@ -10907,7 +10933,7 @@
10907
10933
  NetworkService.prototype.getDefaultPeers = function () {
10908
10934
  return __awaiter(this, void 0, void 0, function () {
10909
10935
  var peers;
10910
- return __generator(this, function (_a) {
10936
+ return __generator(this, function (_b) {
10911
10937
  peers = (this.environment.defaultPeers || []).map(exports.Peer.fromObject);
10912
10938
  return [2 /*return*/, Promise.resolve(peers)];
10913
10939
  });
@@ -10920,7 +10946,7 @@
10920
10946
  var _this = this;
10921
10947
  this._listeners[name] = this._listeners[name] || [];
10922
10948
  this._listeners[name].push(callback);
10923
- // When unsubcribe, remove from the listener
10949
+ // When unsubscribe, remove from the listener
10924
10950
  return new rxjs.Subscription(function () {
10925
10951
  var index = _this._listeners[name].indexOf(callback);
10926
10952
  if (index !== -1) {
@@ -10931,7 +10957,7 @@
10931
10957
  NetworkService.prototype.emit = function (name, data) {
10932
10958
  return __awaiter(this, void 0, void 0, function () {
10933
10959
  var hooks;
10934
- return __generator(this, function (_a) {
10960
+ return __generator(this, function (_b) {
10935
10961
  hooks = this._listeners[name];
10936
10962
  if (isNotEmptyArray(hooks)) {
10937
10963
  console.info("[network-service] Trigger " + name + " hook: Executing " + hooks.length + " callbacks...");
@@ -10947,7 +10973,7 @@
10947
10973
  });
10948
10974
  };
10949
10975
  return NetworkService;
10950
- }());
10976
+ }(StartableService));
10951
10977
  NetworkService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function NetworkService_Factory() { return new NetworkService(i0__namespace.ɵɵinject(i1__namespace$3.DOCUMENT), i0__namespace.ɵɵinject(i1__namespace$4.Platform), i0__namespace.ɵɵinject(i1__namespace$4.ModalController), i0__namespace.ɵɵinject(CryptoService), i0__namespace.ɵɵinject(i3__namespace$1.Storage), i0__namespace.ɵɵinject(LocalSettingsService), i0__namespace.ɵɵinject(i6__namespace.CacheService), i0__namespace.ɵɵinject(i2__namespace$2.HttpClient), i0__namespace.ɵɵinject(ENVIRONMENT), i0__namespace.ɵɵinject(i9__namespace.Network, 8), i0__namespace.ɵɵinject(i10__namespace.SplashScreen, 8), i0__namespace.ɵɵinject(i1__namespace$1.TranslateService, 8), i0__namespace.ɵɵinject(i1__namespace$4.ToastController, 8)); }, token: NetworkService, providedIn: "root" });
10952
10978
  NetworkService.decorators = [
10953
10979
  { type: i0.Injectable, args: [{ providedIn: 'root' },] }
@@ -11550,31 +11576,31 @@
11550
11576
  }());
11551
11577
 
11552
11578
  var APP_LOCAL_STORAGE_TYPE_POLICIES = new i0.InjectionToken('localStorageTypePolicies');
11553
- var EntitiesStorage = /** @class */ (function () {
11579
+ ;
11580
+ var EntitiesStorage = /** @class */ (function (_super) {
11581
+ __extends(EntitiesStorage, _super);
11554
11582
  function EntitiesStorage(platform, progressBarService, storage, environment, typePolicies) {
11555
- this.platform = platform;
11556
- this.progressBarService = progressBarService;
11557
- this.storage = storage;
11558
- this.environment = environment;
11559
- this._started = false;
11560
- this._subscription = new rxjs.Subscription();
11561
- this._stores = {};
11562
- this._$save = new i0.EventEmitter(true);
11563
- this._dirty = false;
11564
- this._saving = false;
11565
- this.onStart = new rxjs.Subject();
11566
- this._typePolicies = typePolicies || {};
11583
+ var _this = _super.call(this, platform) || this;
11584
+ _this.platform = platform;
11585
+ _this.progressBarService = progressBarService;
11586
+ _this.storage = storage;
11587
+ _this.environment = environment;
11588
+ _this._subscription = new rxjs.Subscription();
11589
+ _this._$save = new i0.EventEmitter(true);
11590
+ _this._dirty = false;
11591
+ _this._saving = false;
11592
+ _this._typePolicies = typePolicies || {};
11593
+ _this._saveTimerPeriod = environment.storageSavePeriodMs || 10000 /* = 10s */;
11594
+ _this._data = {};
11567
11595
  // For DEV only
11568
- this._debug = !environment.production;
11569
- if (this._debug)
11596
+ _this._debug = !environment.production;
11597
+ if (_this._debug)
11570
11598
  console.debug('[entities-storage] Creating service');
11599
+ return _this;
11571
11600
  }
11572
11601
  Object.defineProperty(EntitiesStorage.prototype, "dirty", {
11573
11602
  get: function () {
11574
- return this._dirty || Object.entries(this._stores).find(function (_a) {
11575
- var _b = __read(_a, 2), _ = _b[0], store = _b[1];
11576
- return store.dirty;
11577
- }) !== undefined;
11603
+ return this._dirty || Object.values(this._data).some(function (store) { return store.dirty; });
11578
11604
  },
11579
11605
  enumerable: false,
11580
11606
  configurable: true
@@ -11582,7 +11608,7 @@
11582
11608
  EntitiesStorage.prototype.watchAll = function (entityName, variables, opts) {
11583
11609
  var _this = this;
11584
11610
  // Make sure store is ready
11585
- if (!this._started) {
11611
+ if (!this.started) {
11586
11612
  return rxjs.defer(function () { return _this.ready(); })
11587
11613
  .pipe(operators.switchMap(function () { return _this.watchAll(entityName, variables, opts); })); // Loop
11588
11614
  }
@@ -11599,7 +11625,7 @@
11599
11625
  return __generator(this, function (_a) {
11600
11626
  switch (_a.label) {
11601
11627
  case 0:
11602
- if (!!this._started) return [3 /*break*/, 2];
11628
+ if (!!this.started) return [3 /*break*/, 2];
11603
11629
  return [4 /*yield*/, this.ready()];
11604
11630
  case 1:
11605
11631
  _a.sent();
@@ -11702,9 +11728,12 @@
11702
11728
  case 0:
11703
11729
  if (!entity)
11704
11730
  return [2 /*return*/]; // skip
11731
+ if (!!this.started) return [3 /*break*/, 2];
11705
11732
  return [4 /*yield*/, this.ready()];
11706
11733
  case 1:
11707
11734
  _a.sent();
11735
+ _a.label = 2;
11736
+ case 2:
11708
11737
  try {
11709
11738
  this.progressBarService.increase();
11710
11739
  this._dirty = true;
@@ -11731,9 +11760,12 @@
11731
11760
  case 0:
11732
11761
  if (isEmptyArray(entities) && (!opts || opts.reset !== true))
11733
11762
  return [2 /*return*/, entities]; // Skip (nothing to save)
11763
+ if (!!this.started) return [3 /*break*/, 2];
11734
11764
  return [4 /*yield*/, this.ready()];
11735
11765
  case 1:
11736
11766
  _a.sent();
11767
+ _a.label = 2;
11768
+ case 2:
11737
11769
  try {
11738
11770
  this.progressBarService.increase();
11739
11771
  this._dirty = true;
@@ -11755,10 +11787,12 @@
11755
11787
  case 0:
11756
11788
  if (!entity)
11757
11789
  return [2 /*return*/, undefined]; // skip
11790
+ if (!!this.started) return [3 /*break*/, 2];
11758
11791
  return [4 /*yield*/, this.ready()];
11759
11792
  case 1:
11760
11793
  _a.sent();
11761
- return [2 /*return*/, this.deleteById(entity.id, Object.assign(Object.assign({}, opts), { entityName: opts && opts.entityName || this.detectEntityName(entity) }))];
11794
+ _a.label = 2;
11795
+ case 2: return [2 /*return*/, this.deleteById(entity.id, Object.assign(Object.assign({}, opts), { entityName: opts && opts.entityName || this.detectEntityName(entity) }))];
11762
11796
  }
11763
11797
  });
11764
11798
  });
@@ -11768,9 +11802,13 @@
11768
11802
  var entityStore, deletedEntity;
11769
11803
  return __generator(this, function (_a) {
11770
11804
  switch (_a.label) {
11771
- case 0: return [4 /*yield*/, this.ready()];
11805
+ case 0:
11806
+ if (!!this.started) return [3 /*break*/, 2];
11807
+ return [4 /*yield*/, this.ready()];
11772
11808
  case 1:
11773
11809
  _a.sent();
11810
+ _a.label = 2;
11811
+ case 2:
11774
11812
  if (!opts || isNilOrBlank(opts.entityName))
11775
11813
  throw new Error('Missing argument \'opts\' or \'entityName\'');
11776
11814
  //if (id >= 0) throw new Error('Invalid id a local entity (not a negative number): ' + id);
@@ -11802,9 +11840,13 @@
11802
11840
  var entityStore, deletedEntities;
11803
11841
  return __generator(this, function (_a) {
11804
11842
  switch (_a.label) {
11805
- case 0: return [4 /*yield*/, this.ready()];
11843
+ case 0:
11844
+ if (!!this.started) return [3 /*break*/, 2];
11845
+ return [4 /*yield*/, this.ready()];
11806
11846
  case 1:
11807
11847
  _a.sent();
11848
+ _a.label = 2;
11849
+ case 2:
11808
11850
  if (!opts || isNilOrBlank(opts.entityName))
11809
11851
  throw new Error('Missing argument \'opts\' or \'opts.entityName\'');
11810
11852
  try {
@@ -11837,10 +11879,12 @@
11837
11879
  case 0:
11838
11880
  if (!entity)
11839
11881
  return [2 /*return*/, undefined]; // skip
11882
+ if (!!this.started) return [3 /*break*/, 2];
11840
11883
  return [4 /*yield*/, this.ready()];
11841
11884
  case 1:
11842
11885
  _a.sent();
11843
- return [2 /*return*/, this.deleteFromTrashById(entity.id, Object.assign(Object.assign({}, opts), { entityName: opts && opts.entityName || this.detectEntityName(entity) }))];
11886
+ _a.label = 2;
11887
+ case 2: return [2 /*return*/, this.deleteFromTrashById(entity.id, Object.assign(Object.assign({}, opts), { entityName: opts && opts.entityName || this.detectEntityName(entity) }))];
11844
11888
  }
11845
11889
  });
11846
11890
  });
@@ -11867,9 +11911,12 @@
11867
11911
  case 0:
11868
11912
  if (!entity)
11869
11913
  return [2 /*return*/, undefined]; // skip
11914
+ if (!!this.started) return [3 /*break*/, 2];
11870
11915
  return [4 /*yield*/, this.ready()];
11871
11916
  case 1:
11872
11917
  _a.sent();
11918
+ _a.label = 2;
11919
+ case 2:
11873
11920
  entityName = opts && opts.entityName || this.detectEntityName(entity);
11874
11921
  entityStore = this.getEntityStore(entityName);
11875
11922
  if (entityStore)
@@ -11889,9 +11936,13 @@
11889
11936
  var entityStore, deletedEntities, trashName;
11890
11937
  return __generator(this, function (_a) {
11891
11938
  switch (_a.label) {
11892
- case 0: return [4 /*yield*/, this.ready()];
11939
+ case 0:
11940
+ if (!!this.started) return [3 /*break*/, 2];
11941
+ return [4 /*yield*/, this.ready()];
11893
11942
  case 1:
11894
11943
  _a.sent();
11944
+ _a.label = 2;
11945
+ case 2:
11895
11946
  if (!opts || isNilOrBlank(opts.entityName))
11896
11947
  throw new Error('Missing argument \'opts.entityName\'');
11897
11948
  entityStore = this.getEntityStore(opts.entityName, { create: false });
@@ -11923,9 +11974,12 @@
11923
11974
  case 0:
11924
11975
  if (!entity)
11925
11976
  return [2 /*return*/, undefined]; // skip
11977
+ if (!!this.started) return [3 /*break*/, 2];
11926
11978
  return [4 /*yield*/, this.ready()];
11927
11979
  case 1:
11928
11980
  _a.sent();
11981
+ _a.label = 2;
11982
+ case 2:
11929
11983
  entityName = opts && opts.entityName || this.detectEntityName(entity);
11930
11984
  trashName = EntitiesStorage.TRASH_PREFIX + entityName;
11931
11985
  this.getEntityStore(trashName).save(entity, opts);
@@ -11940,9 +11994,13 @@
11940
11994
  var trashName, entityStore;
11941
11995
  return __generator(this, function (_a) {
11942
11996
  switch (_a.label) {
11943
- case 0: return [4 /*yield*/, this.ready()];
11997
+ case 0:
11998
+ if (!!this.started) return [3 /*break*/, 2];
11999
+ return [4 /*yield*/, this.ready()];
11944
12000
  case 1:
11945
12001
  _a.sent();
12002
+ _a.label = 2;
12003
+ case 2:
11946
12004
  trashName = EntitiesStorage.TRASH_PREFIX + entityName;
11947
12005
  entityStore = this.getEntityStore(trashName, { create: false });
11948
12006
  if (!entityStore)
@@ -11961,79 +12019,58 @@
11961
12019
  }
11962
12020
  return Promise.resolve();
11963
12021
  };
11964
- EntitiesStorage.prototype.ready = function () {
11965
- if (this._started)
11966
- return Promise.resolve();
11967
- return this.start();
11968
- };
11969
- EntitiesStorage.prototype.start = function () {
11970
- var _this = this;
11971
- if (this._startPromise)
11972
- return this._startPromise;
11973
- if (this._started)
11974
- return Promise.resolve();
11975
- var now = Date.now();
11976
- console.info("[entities-storage] Starting entity storage...");
11977
- // Restore sequences
11978
- this._startPromise = this.restoreLocally()
11979
- .then(function () {
11980
- // Start a save timer
11981
- _this._subscription.add(rxjs.merge(_this._$save, rxjs.timer(2000, 10000))
11982
- .pipe(operators.throttleTime(10000))
11983
- .subscribe(function () { return _this.storeLocally(); }));
11984
- _this._started = true;
11985
- _this._startPromise = undefined;
11986
- console.info("[entities-storage] Starting [OK] in " + (Date.now() - now) + "ms");
11987
- // Emit event
11988
- _this.onStart.next();
11989
- });
11990
- return this._startPromise;
11991
- };
11992
- EntitiesStorage.prototype.stop = function () {
12022
+ EntitiesStorage.prototype.ngOnStart = function () {
11993
12023
  return __awaiter(this, void 0, void 0, function () {
12024
+ var now;
12025
+ var _this = this;
11994
12026
  return __generator(this, function (_a) {
11995
12027
  switch (_a.label) {
11996
12028
  case 0:
11997
- this._started = false;
11998
- this._subscription.unsubscribe();
11999
- this._subscription = new rxjs.Subscription();
12000
- if (!this.dirty) return [3 /*break*/, 2];
12001
- return [4 /*yield*/, this.storeLocally()];
12029
+ now = Date.now();
12030
+ console.info("[entities-storage] Starting entity storage...");
12031
+ // Restore sequences
12032
+ return [4 /*yield*/, this.restoreLocally()];
12002
12033
  case 1:
12034
+ // Restore sequences
12003
12035
  _a.sent();
12004
- _a.label = 2;
12005
- case 2: return [2 /*return*/];
12036
+ // Start a save timer
12037
+ this._subscription.add(rxjs.merge(this._$save, rxjs.timer(this._saveTimerPeriod, this._saveTimerPeriod))
12038
+ .pipe(
12039
+ // Avoid to many call (e.g. when $save AND timer are triggered
12040
+ operators.throttleTime(this._saveTimerPeriod))
12041
+ .subscribe(function () { return _this.storeLocally(); }));
12042
+ console.info("[entities-storage] Starting [OK] in " + (Date.now() - now) + "ms");
12043
+ return [2 /*return*/, this._data];
12006
12044
  }
12007
12045
  });
12008
12046
  });
12009
12047
  };
12010
- EntitiesStorage.prototype.restart = function () {
12048
+ EntitiesStorage.prototype.ngOnStop = function () {
12011
12049
  return __awaiter(this, void 0, void 0, function () {
12012
12050
  return __generator(this, function (_a) {
12013
12051
  switch (_a.label) {
12014
12052
  case 0:
12015
- if (!this._started) return [3 /*break*/, 2];
12016
- return [4 /*yield*/, this.stop()];
12053
+ this._subscription.unsubscribe();
12054
+ this._subscription = new rxjs.Subscription();
12055
+ if (!this.dirty) return [3 /*break*/, 2];
12056
+ return [4 /*yield*/, this.storeLocally()];
12017
12057
  case 1:
12018
12058
  _a.sent();
12019
12059
  _a.label = 2;
12020
- case 2: return [4 /*yield*/, this.start()];
12021
- case 3:
12022
- _a.sent();
12023
- return [2 /*return*/];
12060
+ case 2: return [2 /*return*/];
12024
12061
  }
12025
12062
  });
12026
12063
  });
12027
12064
  };
12028
12065
  /* -- protected methods -- */
12029
12066
  EntitiesStorage.prototype.getEntityStore = function (name, opts) {
12030
- var store = this._stores[name];
12067
+ var store = this._data[name];
12031
12068
  if (!store && (!opts || opts.create !== false)) {
12032
12069
  if (this._debug)
12033
12070
  console.debug("[entities-storage] Creating store " + name);
12034
12071
  var typePolicy = this._typePolicies[name];
12035
12072
  store = new EntityStore(name, this.storage, typePolicy);
12036
- this._stores[name] = store;
12073
+ this._data[name] = store;
12037
12074
  }
12038
12075
  return store;
12039
12076
  };
@@ -12090,11 +12127,11 @@
12090
12127
  this._saving = true;
12091
12128
  this._dirty = false;
12092
12129
  this.progressBarService.increase();
12093
- entityNames = this._stores && Object.keys(this._stores) || [];
12130
+ entityNames = this._data && Object.keys(this._data) || [];
12094
12131
  now = Date.now();
12095
12132
  if (this._debug)
12096
12133
  console.debug('[entities-storage] Persisting...');
12097
- return [2 /*return*/, rxjs.concat.apply(void 0, __spread(entityNames.map(function (entityName) { return rxjs.defer(function () {
12134
+ return [2 /*return*/, chainPromises(entityNames.map(function (entityName) { return function () {
12098
12135
  currentEntityName = entityName;
12099
12136
  var entityStore = _this.getEntityStore(entityName, { create: false });
12100
12137
  if (!entityStore) {
@@ -12108,17 +12145,20 @@
12108
12145
  entityNames.splice(entityNames.findIndex(function (e) { return e === entityName; }), 1);
12109
12146
  }
12110
12147
  });
12111
- }); }), [rxjs.defer(function () {
12112
- currentEntityName = undefined;
12113
- return isEmptyArray(entityNames) ?
12114
- _this.storage.remove(ENTITIES_STORAGE_KEY_PREFIX) :
12115
- _this.storage.set(ENTITIES_STORAGE_KEY_PREFIX, entityNames);
12116
- }), rxjs.defer(function () {
12117
- if (_this._debug)
12118
- console.debug("[entities-storage] Persisting [OK] " + entityNames.length + " stores saved in " + (Date.now() - now) + "ms...");
12119
- _this._saving = false;
12120
- _this.progressBarService.decrease();
12121
- })])).pipe(operators.catchError(function (err) {
12148
+ }; }))
12149
+ .then(function () {
12150
+ currentEntityName = undefined;
12151
+ return isEmptyArray(entityNames) ?
12152
+ _this.storage.remove(ENTITIES_STORAGE_KEY_PREFIX) :
12153
+ _this.storage.set(ENTITIES_STORAGE_KEY_PREFIX, entityNames);
12154
+ })
12155
+ .then(function () {
12156
+ if (_this._debug)
12157
+ console.debug("[entities-storage] Persisting [OK] " + entityNames.length + " stores saved in " + (Date.now() - now) + "ms...");
12158
+ _this._saving = false;
12159
+ _this.progressBarService.decrease();
12160
+ })
12161
+ .catch(function (err) {
12122
12162
  _this._saving = false;
12123
12163
  _this.progressBarService.decrease();
12124
12164
  if (currentEntityName) {
@@ -12127,13 +12167,13 @@
12127
12167
  else {
12128
12168
  console.error("[entities-storage] Error while persisting: " + (err && err.message || err), err);
12129
12169
  }
12130
- return err;
12131
- })).toPromise()];
12170
+ throw err;
12171
+ })];
12132
12172
  });
12133
12173
  });
12134
12174
  };
12135
12175
  return EntitiesStorage;
12136
- }());
12176
+ }(StartableService));
12137
12177
  EntitiesStorage.TRASH_PREFIX = 'Trash#';
12138
12178
  EntitiesStorage.REMOTE_PREFIX = 'Remote#';
12139
12179
  EntitiesStorage.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function EntitiesStorage_Factory() { return new EntitiesStorage(i0__namespace.ɵɵinject(i1__namespace$4.Platform), i0__namespace.ɵɵinject(ProgressBarService), i0__namespace.ɵɵinject(i3__namespace$1.Storage), i0__namespace.ɵɵinject(ENVIRONMENT), i0__namespace.ɵɵinject(APP_LOCAL_STORAGE_TYPE_POLICIES, 8)); }, token: EntitiesStorage, providedIn: "root" });
@@ -12144,7 +12184,7 @@
12144
12184
  { type: i1$5.Platform },
12145
12185
  { type: ProgressBarService },
12146
12186
  { type: i3$2.Storage },
12147
- { type: undefined, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] },
12187
+ { type: Environment, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] },
12148
12188
  { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [APP_LOCAL_STORAGE_TYPE_POLICIES,] }] }
12149
12189
  ]; };
12150
12190
 
@@ -12669,59 +12709,36 @@
12669
12709
  }
12670
12710
 
12671
12711
  var APP_GRAPHQL_TYPE_POLICIES = new i0.InjectionToken('graphqlTypePolicies');
12672
- var GraphqlService = /** @class */ (function () {
12712
+ var GraphqlService = /** @class */ (function (_super) {
12713
+ __extends(GraphqlService, _super);
12673
12714
  function GraphqlService(platform, apollo, httpLink, network, storage, cryptoService, environment, typePolicies) {
12674
- var _this = this;
12675
- this.platform = platform;
12676
- this.apollo = apollo;
12677
- this.httpLink = httpLink;
12678
- this.network = network;
12679
- this.storage = storage;
12680
- this.cryptoService = cryptoService;
12681
- this.environment = environment;
12682
- this.typePolicies = typePolicies;
12683
- this._started = false;
12684
- this._subscription = new rxjs.Subscription();
12685
- this.connectionParams = {};
12686
- this.onNetworkError = new rxjs.Subject();
12687
- this.customErrors = {};
12688
- this.onStart = new rxjs.Subject();
12689
- this._debug = !environment.production;
12690
- this._defaultFetchPolicy = environment.apolloFetchPolicy;
12691
- // Restart if network restart
12692
- this.network.on('start', function () { return _this.restart(); });
12693
- // Clear cache
12694
- this.network.on('resetCache', function () { return __awaiter(_this, void 0, void 0, function () {
12695
- return __generator(this, function (_a) {
12696
- switch (_a.label) {
12697
- case 0: return [4 /*yield*/, this.ready()];
12698
- case 1:
12699
- _a.sent();
12700
- return [4 /*yield*/, this.clearCache()];
12701
- case 2:
12702
- _a.sent();
12703
- return [2 /*return*/];
12704
- }
12705
- });
12706
- }); });
12715
+ var _this = _super.call(this, platform) || this;
12716
+ _this.platform = platform;
12717
+ _this.apollo = apollo;
12718
+ _this.httpLink = httpLink;
12719
+ _this.network = network;
12720
+ _this.storage = storage;
12721
+ _this.cryptoService = cryptoService;
12722
+ _this.environment = environment;
12723
+ _this.typePolicies = typePolicies;
12724
+ _this._subscription = new rxjs.Subscription();
12725
+ _this.connectionParams = {};
12726
+ _this.onNetworkError = new rxjs.Subject();
12727
+ _this.customErrors = {};
12728
+ _this._debug = !environment.production;
12729
+ _this._defaultFetchPolicy = environment.apolloFetchPolicy;
12707
12730
  // Listen network status
12708
- this._networkStatusChanged$ = network.onNetworkStatusChanges
12731
+ _this._networkStatusChanged$ = network.onNetworkStatusChanges
12709
12732
  .pipe(operators.filter(isNotNil), operators.distinctUntilChanged());
12710
12733
  // When getting network error: try to ping peer, and toggle to offline
12711
- this.onNetworkError
12734
+ _this.onNetworkError
12712
12735
  .pipe(operators.throttleTime(300), operators.filter(function () { return _this.network.online; }), operators.mergeMap(function () { return _this.network.checkPeerAlive(); }), operators.filter(function (alive) { return !alive; }))
12713
12736
  .subscribe(function () { return _this.network.setForceOffline(true, { showToast: true }); });
12737
+ return _this;
12714
12738
  }
12715
- Object.defineProperty(GraphqlService.prototype, "started", {
12716
- get: function () {
12717
- return this._started;
12718
- },
12719
- enumerable: false,
12720
- configurable: true
12721
- });
12722
12739
  Object.defineProperty(GraphqlService.prototype, "client", {
12723
12740
  get: function () {
12724
- return this.apollo.client;
12741
+ return this._data;
12725
12742
  },
12726
12743
  enumerable: false,
12727
12744
  configurable: true
@@ -12740,34 +12757,6 @@
12740
12757
  enumerable: false,
12741
12758
  configurable: true
12742
12759
  });
12743
- GraphqlService.prototype.ready = function () {
12744
- if (this._started)
12745
- return Promise.resolve();
12746
- return this.start();
12747
- };
12748
- GraphqlService.prototype.start = function () {
12749
- var _this = this;
12750
- if (this._startPromise)
12751
- return this._startPromise;
12752
- if (this._started)
12753
- return Promise.resolve();
12754
- console.info('[graphql] Starting graphql...');
12755
- // Waiting for network service
12756
- this._startPromise = this.network.ready()
12757
- .then(function () { return _this.initApollo(); })
12758
- .then(function () {
12759
- _this._started = true;
12760
- _this._startPromise = undefined;
12761
- // Emit event
12762
- _this.onStart.next();
12763
- console.info('[graphql] Starting graphql [OK]');
12764
- })
12765
- .catch(function (err) {
12766
- console.error(err && err.message || err, err);
12767
- _this._startPromise = undefined;
12768
- });
12769
- return this._startPromise;
12770
- };
12771
12760
  GraphqlService.prototype.setAuthToken = function (token) {
12772
12761
  if (token) {
12773
12762
  console.debug('[graphql] Apply token authentication to headers');
@@ -12800,15 +12789,18 @@
12800
12789
  */
12801
12790
  GraphqlService.prototype.addResolver = function (resolvers) {
12802
12791
  return __awaiter(this, void 0, void 0, function () {
12803
- var client;
12804
- var _this = this;
12805
12792
  return __generator(this, function (_a) {
12806
- if (!this._started) {
12807
- this.onStart.toPromise().then(function () { return _this.addResolver(resolvers); }); // Loop
12793
+ switch (_a.label) {
12794
+ case 0:
12795
+ if (!!this.started) return [3 /*break*/, 2];
12796
+ return [4 /*yield*/, this.ready()];
12797
+ case 1:
12798
+ _a.sent();
12799
+ _a.label = 2;
12800
+ case 2:
12801
+ this.apollo.client.addResolvers(resolvers);
12802
+ return [2 /*return*/];
12808
12803
  }
12809
- client = this.apollo.getClient();
12810
- client.addResolvers(resolvers);
12811
- return [2 /*return*/];
12812
12804
  });
12813
12805
  });
12814
12806
  };
@@ -12818,21 +12810,26 @@
12818
12810
  return __generator(this, function (_a) {
12819
12811
  switch (_a.label) {
12820
12812
  case 0:
12821
- _a.trys.push([0, 3, , 4]);
12822
- return [4 /*yield*/, this.getApollo()];
12823
- case 1: return [4 /*yield*/, (_a.sent()).query({
12824
- query: opts.query,
12825
- variables: opts.variables,
12826
- fetchPolicy: opts.fetchPolicy || this._defaultFetchPolicy || undefined
12827
- }).toPromise()];
12813
+ if (!!this.started) return [3 /*break*/, 2];
12814
+ return [4 /*yield*/, this.ready()];
12815
+ case 1:
12816
+ _a.sent();
12817
+ _a.label = 2;
12828
12818
  case 2:
12829
- res = _a.sent();
12830
- return [3 /*break*/, 4];
12819
+ _a.trys.push([2, 4, , 5]);
12820
+ return [4 /*yield*/, this.client.query({
12821
+ query: opts.query,
12822
+ variables: opts.variables,
12823
+ fetchPolicy: opts.fetchPolicy || this._defaultFetchPolicy || undefined
12824
+ })];
12831
12825
  case 3:
12826
+ res = _a.sent();
12827
+ return [3 /*break*/, 5];
12828
+ case 4:
12832
12829
  err_1 = _a.sent();
12833
12830
  res = this.toApolloError(err_1, opts.error);
12834
- return [3 /*break*/, 4];
12835
- case 4:
12831
+ return [3 /*break*/, 5];
12832
+ case 5:
12836
12833
  if (res.errors) {
12837
12834
  throw res.errors[0];
12838
12835
  }
@@ -13190,12 +13187,14 @@
13190
13187
  return __generator(this, function (_a) {
13191
13188
  switch (_a.label) {
13192
13189
  case 0:
13193
- client = (client || this.apollo.client);
13190
+ client = (client || this.client);
13194
13191
  if (!client) return [3 /*break*/, 2];
13195
- now = this._debug && Date.now();
13196
13192
  console.info('[graphql] Clearing Apollo client\'s cache... ');
13193
+ now = this._debug && Date.now();
13194
+ // Clearing the cache
13197
13195
  return [4 /*yield*/, client.cache.reset()];
13198
13196
  case 1:
13197
+ // Clearing the cache
13199
13198
  _a.sent();
13200
13199
  if (this._debug)
13201
13200
  console.debug("[graphql] Apollo client's cache cleared, in " + (Date.now() - now) + "ms");
@@ -13209,13 +13208,16 @@
13209
13208
  this.customErrors = Object.assign(Object.assign({}, this.customErrors), error);
13210
13209
  };
13211
13210
  /* -- protected methods -- */
13212
- GraphqlService.prototype.initApollo = function () {
13211
+ GraphqlService.prototype.ngOnStart = function () {
13213
13212
  return __awaiter(this, void 0, void 0, function () {
13214
13213
  var mobile, enableTrackMutationQueries, peer, uri, wsUri, storage, client, wsLink, retryLink, authLink, httpLink, cache, mutationLinks, serializingLink, trackerLink, queueLink_1, err_2;
13215
13214
  var _this = this;
13216
13215
  return __generator(this, function (_a) {
13217
13216
  switch (_a.label) {
13218
- case 0:
13217
+ case 0: return [4 /*yield*/, this.network.ready()];
13218
+ case 1:
13219
+ _a.sent();
13220
+ console.info('[graphql] Starting graphql...');
13219
13221
  mobile = this.platform.is('mobile') || this.platform.is('mobileweb');
13220
13222
  enableTrackMutationQueries = !mobile;
13221
13223
  peer = this.network.peer;
@@ -13234,7 +13236,7 @@
13234
13236
  }, webSocketImpl: AppWebSocket, uri: wsUri });
13235
13237
  storage = new apollo3CachePersist.IonicStorageWrapper(this.storage);
13236
13238
  client = this.apollo.client;
13237
- if (!!client) return [3 /*break*/, 3];
13239
+ if (!!client) return [3 /*break*/, 4];
13238
13240
  console.debug('[apollo] Creating GraphQL client...');
13239
13241
  wsLink = new ws.WebSocketLink(this.wsParams);
13240
13242
  retryLink = new retry.RetryLink();
@@ -13260,7 +13262,7 @@
13260
13262
  cache = new core.InMemoryCache({
13261
13263
  typePolicies: this.typePolicies
13262
13264
  });
13263
- if (!this.environment.persistCache) return [3 /*break*/, 2];
13265
+ if (!this.environment.persistCache) return [3 /*break*/, 3];
13264
13266
  console.debug('[graphql] Starting persistence cache...');
13265
13267
  return [4 /*yield*/, apollo3CachePersist.persistCache({
13266
13268
  cache: cache,
@@ -13269,21 +13271,21 @@
13269
13271
  debounce: 1000,
13270
13272
  debug: true
13271
13273
  })];
13272
- case 1:
13273
- _a.sent();
13274
- _a.label = 2;
13275
13274
  case 2:
13275
+ _a.sent();
13276
+ _a.label = 3;
13277
+ case 3:
13276
13278
  mutationLinks = void 0;
13277
13279
  // Add queue to store tracked queries, when offline
13278
13280
  if (enableTrackMutationQueries) {
13279
- serializingLink = new SerializingLink__default['default']();
13281
+ serializingLink = new SerializingLink__default["default"]();
13280
13282
  trackerLink = createTrackerLink({
13281
13283
  storage: storage,
13282
13284
  onNetworkStatusChange: this._networkStatusChanged$,
13283
13285
  debounce: 1000,
13284
13286
  debug: true
13285
13287
  });
13286
- queueLink_1 = new QueueLink__default['default']();
13288
+ queueLink_1 = new QueueLink__default["default"]();
13287
13289
  this._subscription.add(this._networkStatusChanged$
13288
13290
  .subscribe(function (type) {
13289
13291
  // Network is offline: start buffering into queue
@@ -13298,7 +13300,7 @@
13298
13300
  }
13299
13301
  }));
13300
13302
  mutationLinks = [
13301
- loggerLink__default['default'],
13303
+ loggerLink__default["default"],
13302
13304
  queueLink_1,
13303
13305
  trackerLink,
13304
13306
  queueLink_1,
@@ -13332,30 +13334,36 @@
13332
13334
  connectToDevTools: !this.environment.production
13333
13335
  });
13334
13336
  this.apollo.client = client;
13335
- _a.label = 3;
13336
- case 3:
13337
- if (!(enableTrackMutationQueries && this.environment.persistCache)) return [3 /*break*/, 7];
13338
13337
  _a.label = 4;
13339
13338
  case 4:
13340
- _a.trys.push([4, 6, , 7]);
13339
+ if (!(enableTrackMutationQueries && this.environment.persistCache)) return [3 /*break*/, 8];
13340
+ _a.label = 5;
13341
+ case 5:
13342
+ _a.trys.push([5, 7, , 8]);
13341
13343
  return [4 /*yield*/, restoreTrackedQueries({
13342
13344
  apolloClient: client,
13343
13345
  storage: storage,
13344
13346
  debug: true
13345
13347
  })];
13346
- case 5:
13347
- _a.sent();
13348
- return [3 /*break*/, 7];
13349
13348
  case 6:
13349
+ _a.sent();
13350
+ return [3 /*break*/, 8];
13351
+ case 7:
13350
13352
  err_2 = _a.sent();
13351
13353
  console.error('[graphql] Failed to restore tracked queries from storage: ' + (err_2 && err_2.message || err_2), err_2);
13352
- return [3 /*break*/, 7];
13353
- case 7: return [2 /*return*/];
13354
+ return [3 /*break*/, 8];
13355
+ case 8:
13356
+ // Listen for network restart
13357
+ this._subscription.add(this.network.on('start', function () { return _this.restart(); }));
13358
+ // Listen for clear cache request, from network
13359
+ this._subscription.add(this.network.on('resetCache', function () { return _this.clearCache(); }));
13360
+ console.info('[graphql] Starting graphql [OK]');
13361
+ return [2 /*return*/, client];
13354
13362
  }
13355
13363
  });
13356
13364
  });
13357
13365
  };
13358
- GraphqlService.prototype.stop = function () {
13366
+ GraphqlService.prototype.ngOnStop = function () {
13359
13367
  return __awaiter(this, void 0, void 0, function () {
13360
13368
  return __generator(this, function (_a) {
13361
13369
  switch (_a.label) {
@@ -13366,24 +13374,11 @@
13366
13374
  return [4 /*yield*/, this.resetClient()];
13367
13375
  case 1:
13368
13376
  _a.sent();
13369
- this._started = false;
13370
- this._startPromise = undefined;
13371
13377
  return [2 /*return*/];
13372
13378
  }
13373
13379
  });
13374
13380
  });
13375
13381
  };
13376
- GraphqlService.prototype.restart = function () {
13377
- return __awaiter(this, void 0, void 0, function () {
13378
- var _this = this;
13379
- return __generator(this, function (_a) {
13380
- if (this.started) {
13381
- return [2 /*return*/, this.stop().then(function () { return _this.start(); })];
13382
- }
13383
- return [2 /*return*/, this.start()];
13384
- });
13385
- });
13386
- };
13387
13382
  GraphqlService.prototype.resetClient = function (client) {
13388
13383
  return __awaiter(this, void 0, void 0, function () {
13389
13384
  return __generator(this, function (_a) {
@@ -13485,24 +13480,8 @@
13485
13480
  }
13486
13481
  return undefined;
13487
13482
  };
13488
- GraphqlService.prototype.getApollo = function () {
13489
- return __awaiter(this, void 0, void 0, function () {
13490
- return __generator(this, function (_a) {
13491
- switch (_a.label) {
13492
- case 0:
13493
- if (!!this._started) return [3 /*break*/, 2];
13494
- console.debug('[graphql] Waiting apollo client... ');
13495
- return [4 /*yield*/, this.onStart.toPromise()];
13496
- case 1:
13497
- _a.sent();
13498
- _a.label = 2;
13499
- case 2: return [2 /*return*/, this.apollo];
13500
- }
13501
- });
13502
- });
13503
- };
13504
13483
  return GraphqlService;
13505
- }());
13484
+ }(StartableService));
13506
13485
  GraphqlService.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function GraphqlService_Factory() { return new GraphqlService(i0__namespace.ɵɵinject(i1__namespace$4.Platform), i0__namespace.ɵɵinject(i2__namespace$3.Apollo), i0__namespace.ɵɵinject(i3__namespace$2.HttpLink), i0__namespace.ɵɵinject(NetworkService), i0__namespace.ɵɵinject(i3__namespace$1.Storage), i0__namespace.ɵɵinject(CryptoService), i0__namespace.ɵɵinject(ENVIRONMENT), i0__namespace.ɵɵinject(APP_GRAPHQL_TYPE_POLICIES, 8)); }, token: GraphqlService, providedIn: "root" });
13507
13486
  GraphqlService.decorators = [
13508
13487
  { type: i0.Injectable, args: [{
@@ -13785,7 +13764,12 @@
13785
13764
  _this.storage = storage;
13786
13765
  _this.file = file;
13787
13766
  _this.environment = environment;
13788
- _this.data = {
13767
+ _this.onLogin = new rxjs.Subject();
13768
+ _this.onLogout = new rxjs.Subject();
13769
+ _this.onChange = new rxjs.Subject();
13770
+ _this.onAuthTokenChange = new rxjs.Subject();
13771
+ _this.onAuthBasicChange = new rxjs.Subject();
13772
+ _this._data = {
13789
13773
  loaded: false,
13790
13774
  keypair: null,
13791
13775
  authToken: null,
@@ -13799,11 +13783,6 @@
13799
13783
  _this._started = false;
13800
13784
  _this._$additionalFields = new rxjs.BehaviorSubject([]);
13801
13785
  _this._tokenType$ = new rxjs.BehaviorSubject(undefined);
13802
- _this.onLogin = new rxjs.Subject();
13803
- _this.onLogout = new rxjs.Subject();
13804
- _this.onChange = new rxjs.Subject();
13805
- _this.onAuthTokenChange = new rxjs.Subject();
13806
- _this.onAuthBasicChange = new rxjs.Subject();
13807
13786
  _this._debug = !environment.production;
13808
13787
  if (_this._debug)
13809
13788
  console.debug('[account-service] Creating service');
@@ -13811,7 +13790,7 @@
13811
13790
  // Send auth token to the graphql layer, when changed
13812
13791
  _this.onAuthTokenChange.subscribe(function (token) { return _this.graphql.setAuthToken(token); });
13813
13792
  _this.onAuthBasicChange.subscribe(function (basic) { return _this.graphql.setAuthBasic(basic); });
13814
- // Listen network restart
13793
+ // Listen graphql start (or restart)
13815
13794
  _this.graphql.onStart.subscribe(function () { return __awaiter(_this, void 0, void 0, function () {
13816
13795
  return __generator(this, function (_b) {
13817
13796
  if (!this._started) {
@@ -13845,27 +13824,27 @@
13845
13824
  }
13846
13825
  Object.defineProperty(AccountService.prototype, "account", {
13847
13826
  get: function () {
13848
- return this.data.loaded ? this.data.account : undefined;
13827
+ return this._data.loaded ? this._data.account : undefined;
13849
13828
  },
13850
13829
  enumerable: false,
13851
13830
  configurable: true
13852
13831
  });
13853
13832
  Object.defineProperty(AccountService.prototype, "person", {
13854
13833
  get: function () {
13855
- if (this.data.loaded && !this.data.person) {
13856
- this.data.person = this.data.loaded ? this.data.account.asPerson() : undefined;
13834
+ if (this._data.loaded && !this._data.person) {
13835
+ this._data.person = this._data.loaded ? this._data.account.asPerson() : undefined;
13857
13836
  }
13858
- return this.data.person;
13837
+ return this._data.person;
13859
13838
  },
13860
13839
  enumerable: false,
13861
13840
  configurable: true
13862
13841
  });
13863
13842
  Object.defineProperty(AccountService.prototype, "department", {
13864
13843
  get: function () {
13865
- if (this.data.loaded && !this.data.department) {
13866
- this.data.department = this.data.loaded ? this.data.account.asPerson().department : undefined;
13844
+ if (this._data.loaded && !this._data.department) {
13845
+ this._data.department = this._data.loaded ? this._data.account.asPerson().department : undefined;
13867
13846
  }
13868
- return this.data.department;
13847
+ return this._data.department;
13869
13848
  },
13870
13849
  enumerable: false,
13871
13850
  configurable: true
@@ -13879,32 +13858,21 @@
13879
13858
  console.info('[account] Using authentication token type: ' + value);
13880
13859
  this._tokenType$.next(value);
13881
13860
  // Reset values
13882
- this.data.authToken = undefined;
13861
+ this._data.authToken = undefined;
13883
13862
  this.onAuthTokenChange.next(undefined);
13884
- this.data.authBasic = undefined;
13863
+ this._data.authBasic = undefined;
13885
13864
  this.onAuthBasicChange.next(undefined);
13886
13865
  }
13887
13866
  },
13888
13867
  enumerable: false,
13889
13868
  configurable: true
13890
13869
  });
13891
- AccountService.prototype.resetData = function () {
13892
- this.data.loaded = false;
13893
- this.data.keypair = null;
13894
- this.data.authToken = null;
13895
- this.data.authBasic = null;
13896
- this.data.pubkey = null;
13897
- this.data.mainProfile = null;
13898
- this.data.account = new exports.Account();
13899
- this.data.person = null;
13900
- this.data.department = null;
13901
- };
13902
13870
  AccountService.prototype.start = function () {
13903
13871
  var _this = this;
13904
13872
  if (this._startPromise)
13905
13873
  return this._startPromise;
13906
13874
  if (this._started)
13907
- return Promise.resolve();
13875
+ return Promise.resolve(this.account);
13908
13876
  // Restoring local settings
13909
13877
  this._startPromise = Promise.all([
13910
13878
  this.settings.ready(),
@@ -13915,6 +13883,7 @@
13915
13883
  .then(function () {
13916
13884
  _this._started = true;
13917
13885
  _this._startPromise = undefined;
13886
+ return _this.account;
13918
13887
  });
13919
13888
  return this._startPromise;
13920
13889
  };
@@ -13932,8 +13901,8 @@
13932
13901
  if (this._started || this._startPromise) {
13933
13902
  this._started = false;
13934
13903
  this._startPromise = undefined;
13935
- hadAuthToken = this.data.authToken && true;
13936
- hadAuthBasic = this.data.authBasic && true;
13904
+ hadAuthToken = this._data.authToken && true;
13905
+ hadAuthBasic = this._data.authBasic && true;
13937
13906
  hadAuth = hadAuthToken || hadAuthBasic;
13938
13907
  this.resetData();
13939
13908
  if (hadAuth) {
@@ -13963,35 +13932,35 @@
13963
13932
  };
13964
13933
  AccountService.prototype.ready = function () {
13965
13934
  if (this._started)
13966
- return Promise.resolve();
13935
+ return Promise.resolve(this.account);
13967
13936
  return this.start();
13968
13937
  };
13969
13938
  AccountService.prototype.isLogin = function () {
13970
- return !!(this.data.pubkey && this.data.loaded);
13939
+ return !!(this._data.pubkey && this._data.loaded);
13971
13940
  };
13972
13941
  AccountService.prototype.isAuth = function () {
13973
- return !!(this.data.pubkey && this.data.keypair && this.data.keypair.secretKey);
13942
+ return !!(this._data.pubkey && this._data.keypair && this._data.keypair.secretKey);
13974
13943
  };
13975
13944
  AccountService.prototype.hasMinProfile = function (userProfile) {
13976
13945
  // should be login, and status ENABLE or TEMPORARY
13977
- if (!this.data.account || !this.data.account.pubkey ||
13978
- (this.data.account.statusId !== StatusIds.ENABLE && this.data.account.statusId !== StatusIds.TEMPORARY)) {
13946
+ if (!this._data.account || !this._data.account.pubkey ||
13947
+ (this._data.account.statusId !== StatusIds.ENABLE && this._data.account.statusId !== StatusIds.TEMPORARY)) {
13979
13948
  return false;
13980
13949
  }
13981
- return PersonUtils.hasUpperOrEqualsProfile(this.data.account.profiles, userProfile);
13950
+ return PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, userProfile);
13982
13951
  };
13983
13952
  AccountService.prototype.hasExactProfile = function (label) {
13984
13953
  // should be login, and status ENABLE or TEMPORARY
13985
- if (!this.data.account || !this.data.account.pubkey ||
13986
- (this.data.account.statusId !== StatusIds.ENABLE && this.data.account.statusId !== StatusIds.TEMPORARY))
13954
+ if (!this._data.account || !this._data.account.pubkey ||
13955
+ (this._data.account.statusId !== StatusIds.ENABLE && this._data.account.statusId !== StatusIds.TEMPORARY))
13987
13956
  return false;
13988
- return this.data.account.profiles.some(function (profile) { return profile === label; });
13957
+ return this._data.account.profiles.some(function (profile) { return profile === label; });
13989
13958
  };
13990
13959
  AccountService.prototype.hasProfileAndIsEnable = function (userProfile) {
13991
13960
  // should be login, and status ENABLE
13992
- if (!this.data.account || !this.data.account.pubkey || this.data.account.statusId !== StatusIds.ENABLE)
13961
+ if (!this._data.account || !this._data.account.pubkey || this._data.account.statusId !== StatusIds.ENABLE)
13993
13962
  return false;
13994
- return PersonUtils.hasUpperOrEqualsProfile(this.data.account.profiles, userProfile);
13963
+ return PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, userProfile);
13995
13964
  };
13996
13965
  AccountService.prototype.isAdmin = function () {
13997
13966
  return this.hasProfileAndIsEnable('ADMIN');
@@ -14011,11 +13980,11 @@
14011
13980
  };
14012
13981
  AccountService.prototype.isOnlyGuest = function () {
14013
13982
  // Should be login, and status ENABLE or TEMPORARY
14014
- if (!this.data.account || !this.data.account.pubkey ||
14015
- (this.data.account.statusId !== StatusIds.ENABLE && this.data.account.statusId !== StatusIds.TEMPORARY))
13983
+ if (!this._data.account || !this._data.account.pubkey ||
13984
+ (this._data.account.statusId !== StatusIds.ENABLE && this._data.account.statusId !== StatusIds.TEMPORARY))
14016
13985
  return false;
14017
13986
  // Profile less then user
14018
- return !PersonUtils.hasUpperOrEqualsProfile(this.data.account.profiles, 'USER');
13987
+ return !PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, 'USER');
14019
13988
  };
14020
13989
  AccountService.prototype.canUserWriteDataForDepartment = function (recorderDepartment) {
14021
13990
  if (ReferentialUtils.isEmpty(recorderDepartment)) {
@@ -14024,17 +13993,17 @@
14024
13993
  return this.isAdmin();
14025
13994
  }
14026
13995
  // Should be login, and status ENABLE
14027
- if (!this.data.account || !this.data.account.pubkey || this.data.account.statusId !== StatusIds.ENABLE)
13996
+ if (!this._data.account || !this._data.account.pubkey || this._data.account.statusId !== StatusIds.ENABLE)
14028
13997
  return false;
14029
- if (!this.data.account.department || !this.data.account.department.id) {
13998
+ if (!this._data.account.department || !this._data.account.department.id) {
14030
13999
  console.warn('User account has no department ! Unable to check write right against recorderDepartment');
14031
14000
  return false;
14032
14001
  }
14033
14002
  // Same recorder department: OK, user can write
14034
- if (this.data.account.department.id === recorderDepartment.id)
14003
+ if (this._data.account.department.id === recorderDepartment.id)
14035
14004
  return true;
14036
14005
  // Else, check if supervisor (or more)
14037
- return PersonUtils.hasUpperOrEqualsProfile(this.data.account.profiles, 'SUPERVISOR');
14006
+ return PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, 'SUPERVISOR');
14038
14007
  };
14039
14008
  AccountService.prototype.register = function (data) {
14040
14009
  return __awaiter(this, void 0, void 0, function () {
@@ -14049,7 +14018,7 @@
14049
14018
  throw new Error('Missing required username or password');
14050
14019
  if (this._debug)
14051
14020
  console.debug('[account] Register new user account...', data.account);
14052
- this.data.loaded = false;
14021
+ this._data.loaded = false;
14053
14022
  now = Date.now();
14054
14023
  _b.label = 1;
14055
14024
  case 1:
@@ -14063,29 +14032,29 @@
14063
14032
  data.account.settings.locale = this.settings.locale;
14064
14033
  data.account.settings.latLongFormat = this.settings.latLongFormat;
14065
14034
  data.account.department.id = data.account.department.id || this.environment.defaultDepartmentId;
14066
- this.data.keypair = keypair;
14035
+ this._data.keypair = keypair;
14067
14036
  return [4 /*yield*/, this.saveRemotely(data.account, keypair)];
14068
14037
  case 3:
14069
14038
  account = _b.sent();
14070
14039
  // Default values
14071
14040
  account.avatar = account.avatar || (this.environment.baseUrl + DEFAULT_AVATAR_IMAGE);
14072
- this.data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14073
- this.data.account = account;
14074
- this.data.pubkey = account.pubkey;
14041
+ this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14042
+ this._data.account = account;
14043
+ this._data.pubkey = account.pubkey;
14075
14044
  // Try to auth on pod
14076
14045
  return [4 /*yield*/, this.authenticate(data)];
14077
14046
  case 4:
14078
14047
  // Try to auth on pod
14079
14048
  _b.sent();
14080
- this.data.loaded = true;
14049
+ this._data.loaded = true;
14081
14050
  return [4 /*yield*/, this.saveLocally()];
14082
14051
  case 5:
14083
14052
  _b.sent();
14084
14053
  console.debug("[account] Account successfully registered in " + (Date.now() - now) + "ms");
14085
14054
  // Emit events
14086
- this.onLogin.next(this.data.account);
14087
- this.onChange.next(this.data.account);
14088
- return [2 /*return*/, this.data.account];
14055
+ this.onLogin.next(this._data.account);
14056
+ this.onChange.next(this._data.account);
14057
+ return [2 /*return*/, this._data.account];
14089
14058
  case 6:
14090
14059
  error_1 = _b.sent();
14091
14060
  console.error(error_1 && error_1.message || error_1);
@@ -14107,22 +14076,22 @@
14107
14076
  // Basic auth
14108
14077
  if (tokenType === 'basic' || tokenType === 'basic-and-token') {
14109
14078
  // Generate the authBasic, if used
14110
- if (!this.data.authBasic) {
14079
+ if (!this._data.authBasic) {
14111
14080
  // Skip if token already provided
14112
- if (!(this.data.authToken && tokenType === 'basic-and-token')) {
14081
+ if (!(this._data.authToken && tokenType === 'basic-and-token')) {
14113
14082
  if (!data || !data.username || !data.password)
14114
14083
  throw new Error('Missing username and password');
14115
- this.data.authBasic = this.cryptoService.encodeBase64(data.username + ":" + data.password);
14084
+ this._data.authBasic = this.cryptoService.encodeBase64(data.username + ":" + data.password);
14116
14085
  }
14117
14086
  }
14118
- this.onAuthBasicChange.next(this.data.authBasic);
14087
+ this.onAuthBasicChange.next(this._data.authBasic);
14119
14088
  }
14120
14089
  if (!(tokenType === 'token' || tokenType === 'basic-and-token')) return [3 /*break*/, 5];
14121
14090
  _c.label = 2;
14122
14091
  case 2:
14123
14092
  _c.trys.push([2, 4, , 5]);
14124
- _b = this.data;
14125
- return [4 /*yield*/, this.authenticateAndGetToken(this.data.authToken)];
14093
+ _b = this._data;
14094
+ return [4 /*yield*/, this.authenticateAndGetToken(this._data.authToken)];
14126
14095
  case 3:
14127
14096
  _b.authToken = _c.sent();
14128
14097
  return [3 /*break*/, 5];
@@ -14135,7 +14104,7 @@
14135
14104
  case 5:
14136
14105
  // Forget authBasic, to switch to authToken
14137
14106
  if (tokenType === 'basic-and-token') {
14138
- this.data.authBasic = undefined;
14107
+ this._data.authBasic = undefined;
14139
14108
  this.onAuthBasicChange.next(undefined);
14140
14109
  }
14141
14110
  return [2 /*return*/];
@@ -14166,18 +14135,18 @@
14166
14135
  throw { code: ErrorCodes$2.UNKNOWN_ERROR, message: 'ERROR.SCRYPT_ERROR' };
14167
14136
  case 4:
14168
14137
  // Store pubkey+keypair
14169
- this.data.pubkey = Base58.encode(keypair.publicKey);
14170
- this.data.keypair = keypair;
14138
+ this._data.pubkey = Base58.encode(keypair.publicKey);
14139
+ this._data.keypair = keypair;
14171
14140
  return [4 /*yield*/, this.storage.get(TOKEN_STORAGE_KEY)];
14172
14141
  case 5:
14173
14142
  previousToken = _b.sent();
14174
- previousToken = previousToken && previousToken.startsWith(this.data.pubkey) && previousToken || null;
14143
+ previousToken = previousToken && previousToken.startsWith(this._data.pubkey) && previousToken || null;
14175
14144
  offline = this.settings.hasOfflineFeature() && (this.network.offline || data.offline === true);
14176
14145
  if (!offline) return [3 /*break*/, 6];
14177
- this.data.authToken = previousToken;
14146
+ this._data.authToken = previousToken;
14178
14147
  // Make sure network if set as offline
14179
14148
  this.network.setForceOffline(true, { showToast: false });
14180
- console.info("[account] Login [OK] {pubkey: " + this.data.pubkey.substr(0, 8) + "}, {offline: true}");
14149
+ console.info("[account] Login [OK] {pubkey: " + this._data.pubkey.substr(0, 8) + "}, {offline: true}");
14181
14150
  return [3 /*break*/, 9];
14182
14151
  case 6:
14183
14152
  _b.trys.push([6, 8, , 9]);
@@ -14237,9 +14206,9 @@
14237
14206
  throw error_5;
14238
14207
  case 21:
14239
14208
  // Emit event to observers
14240
- this.onLogin.next(this.data.account);
14241
- this.onChange.next(this.data.account);
14242
- return [2 /*return*/, this.data.account];
14209
+ this.onLogin.next(this._data.account);
14210
+ this.onChange.next(this._data.account);
14211
+ return [2 /*return*/, this._data.account];
14243
14212
  }
14244
14213
  });
14245
14214
  });
@@ -14249,7 +14218,7 @@
14249
14218
  return __generator(this, function (_b) {
14250
14219
  switch (_b.label) {
14251
14220
  case 0:
14252
- if (!this.data.pubkey)
14221
+ if (!this._data.pubkey)
14253
14222
  throw new Error('User not logged');
14254
14223
  if (this.network.offline)
14255
14224
  throw new Error('Cannot check account in offline mode');
@@ -14261,9 +14230,9 @@
14261
14230
  _b.sent();
14262
14231
  console.debug('[account] Successfully reload account');
14263
14232
  // Emit login event to subscribers
14264
- this.onLogin.next(this.data.account);
14265
- this.onChange.next(this.data.account);
14266
- return [2 /*return*/, this.data.account];
14233
+ this.onLogin.next(this._data.account);
14234
+ this.onChange.next(this._data.account);
14235
+ return [2 /*return*/, this._data.account];
14267
14236
  }
14268
14237
  });
14269
14238
  });
@@ -14278,27 +14247,27 @@
14278
14247
  return __generator(this, function (_b) {
14279
14248
  switch (_b.label) {
14280
14249
  case 0:
14281
- if (!this.data.pubkey)
14250
+ if (!this._data.pubkey)
14282
14251
  return [2 /*return*/, Promise.reject('User not logged')];
14283
- if (this.data.pubkey !== account.pubkey)
14252
+ if (this._data.pubkey !== account.pubkey)
14284
14253
  return [2 /*return*/, Promise.reject('Not user account')];
14285
- return [4 /*yield*/, this.saveRemotely(account, this.data.keypair)];
14254
+ return [4 /*yield*/, this.saveRemotely(account, this._data.keypair)];
14286
14255
  case 1:
14287
14256
  account = _b.sent();
14288
14257
  // Set defaults
14289
14258
  account.avatar = account.avatar || (this.environment.baseUrl + DEFAULT_AVATAR_IMAGE);
14290
- this.data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14291
- this.data.account = account;
14292
- this.data.loaded = true;
14259
+ this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14260
+ this._data.account = account;
14261
+ this._data.loaded = true;
14293
14262
  // Save locally (in storage)
14294
14263
  return [4 /*yield*/, this.saveLocally()];
14295
14264
  case 2:
14296
14265
  // Save locally (in storage)
14297
14266
  _b.sent();
14298
14267
  // Send event
14299
- this.onLogin.next(this.data.account);
14300
- this.onChange.next(this.data.account);
14301
- return [2 /*return*/, this.data.account];
14268
+ this.onLogin.next(this._data.account);
14269
+ this.onChange.next(this._data.account);
14270
+ return [2 /*return*/, this._data.account];
14302
14271
  }
14303
14272
  });
14304
14273
  });
@@ -14309,9 +14278,9 @@
14309
14278
  return __generator(this, function (_b) {
14310
14279
  switch (_b.label) {
14311
14280
  case 0:
14312
- hadAuthToken = this.data.authToken && true;
14313
- hadAuthBasic = this.data.authBasic && true;
14314
- pubkey = this.data && this.data.pubkey;
14281
+ hadAuthToken = this._data.authToken && true;
14282
+ hadAuthBasic = this._data.authBasic && true;
14283
+ pubkey = this._data && this._data.pubkey;
14315
14284
  this.resetData();
14316
14285
  if (!!this.settings.hasOfflineFeature()) return [3 /*break*/, 2];
14317
14286
  // Remove all data from the local storage
@@ -14383,9 +14352,9 @@
14383
14352
  case 1:
14384
14353
  json = _b.sent();
14385
14354
  json = json && (typeof json === 'string') && JSON.parse(json) || json;
14386
- json = json && this.data.pubkey && (json.pubkey === this.data.pubkey) && json || null;
14387
- if (!(!json && this.data.pubkey)) return [3 /*break*/, 3];
14388
- return [4 /*yield*/, this.storage.get(ACCOUNT_STORAGE_KEY + '#' + this.data.pubkey)];
14355
+ json = json && this._data.pubkey && (json.pubkey === this._data.pubkey) && json || null;
14356
+ if (!(!json && this._data.pubkey)) return [3 /*break*/, 3];
14357
+ return [4 /*yield*/, this.storage.get(ACCOUNT_STORAGE_KEY + '#' + this._data.pubkey)];
14389
14358
  case 2:
14390
14359
  json = _b.sent();
14391
14360
  json = json && (typeof json === 'string') && JSON.parse(json) || json;
@@ -14516,7 +14485,8 @@
14516
14485
  });
14517
14486
  };
14518
14487
  AccountService.prototype.listenChanges = function () {
14519
- if (!this.data.pubkey)
14488
+ var _this = this;
14489
+ if (!this._data.pubkey)
14520
14490
  return rxjs.Subscription.EMPTY;
14521
14491
  var self = this;
14522
14492
  console.debug('[account] [WS] Listening account changes');
@@ -14532,15 +14502,14 @@
14532
14502
  }).subscribe({
14533
14503
  next: function (_b) {
14534
14504
  var data = _b.data;
14535
- var _a;
14536
- return __awaiter(this, void 0, void 0, function () {
14537
- var existingUpdateDate;
14505
+ return __awaiter(_this, void 0, void 0, function () {
14506
+ var _a, existingUpdateDate;
14538
14507
  return __generator(this, function (_b) {
14539
14508
  switch (_b.label) {
14540
14509
  case 0:
14541
14510
  if (!data)
14542
14511
  return [2 /*return*/];
14543
- existingUpdateDate = toDateISOString((_a = self.data.account) === null || _a === void 0 ? void 0 : _a.updateDate);
14512
+ existingUpdateDate = toDateISOString((_a = self._data.account) === null || _a === void 0 ? void 0 : _a.updateDate);
14544
14513
  if (!(existingUpdateDate !== data.updateDate)) return [3 /*break*/, 2];
14545
14514
  console.debug("[account] [WS] Detected update on {" + data.updateDate + "}");
14546
14515
  return [4 /*yield*/, self.refresh()];
@@ -14552,32 +14521,30 @@
14552
14521
  });
14553
14522
  });
14554
14523
  },
14555
- error: function (err) {
14556
- return __awaiter(this, void 0, void 0, function () {
14557
- return __generator(this, function (_b) {
14558
- switch (_b.label) {
14559
- case 0:
14560
- if (!(err && +err.code === ServerErrorCodes.NOT_FOUND)) return [3 /*break*/, 2];
14561
- console.info('[account] Account not exists anymore: force user to logout...', err);
14562
- return [4 /*yield*/, self.logout()];
14563
- case 1:
14564
- _b.sent();
14565
- return [3 /*break*/, 5];
14566
- case 2:
14567
- if (!(err && +err.code === ServerErrorCodes.UNAUTHORIZED)) return [3 /*break*/, 4];
14568
- console.info('[account] Account not authorized: force user to logout...', err);
14569
- return [4 /*yield*/, self.logout()];
14570
- case 3:
14571
- _b.sent();
14572
- return [3 /*break*/, 5];
14573
- case 4:
14574
- console.warn('[account] [WS] Received error:', err);
14575
- _b.label = 5;
14576
- case 5: return [2 /*return*/];
14577
- }
14578
- });
14524
+ error: function (err) { return __awaiter(_this, void 0, void 0, function () {
14525
+ return __generator(this, function (_b) {
14526
+ switch (_b.label) {
14527
+ case 0:
14528
+ if (!(err && +err.code === ServerErrorCodes.NOT_FOUND)) return [3 /*break*/, 2];
14529
+ console.info('[account] Account not exists anymore: force user to logout...', err);
14530
+ return [4 /*yield*/, self.logout()];
14531
+ case 1:
14532
+ _b.sent();
14533
+ return [3 /*break*/, 5];
14534
+ case 2:
14535
+ if (!(err && +err.code === ServerErrorCodes.UNAUTHORIZED)) return [3 /*break*/, 4];
14536
+ console.info('[account] Account not authorized: force user to logout...', err);
14537
+ return [4 /*yield*/, self.logout()];
14538
+ case 3:
14539
+ _b.sent();
14540
+ return [3 /*break*/, 5];
14541
+ case 4:
14542
+ console.warn('[account] [WS] Received error:', err);
14543
+ _b.label = 5;
14544
+ case 5: return [2 /*return*/];
14545
+ }
14579
14546
  });
14580
- },
14547
+ }); },
14581
14548
  complete: function () {
14582
14549
  console.debug('[account] [WS] Completed');
14583
14550
  }
@@ -14634,15 +14601,26 @@
14634
14601
  this._$additionalFields.next(values.concat(field));
14635
14602
  };
14636
14603
  /* -- protected method -- */
14604
+ AccountService.prototype.resetData = function () {
14605
+ this._data.loaded = false;
14606
+ this._data.keypair = null;
14607
+ this._data.authToken = null;
14608
+ this._data.authBasic = null;
14609
+ this._data.pubkey = null;
14610
+ this._data.mainProfile = null;
14611
+ this._data.account = new exports.Account();
14612
+ this._data.person = null;
14613
+ this._data.department = null;
14614
+ };
14637
14615
  AccountService.prototype.loadData = function (opts) {
14638
14616
  return __awaiter(this, void 0, void 0, function () {
14639
14617
  var account, error_6;
14640
14618
  return __generator(this, function (_b) {
14641
14619
  switch (_b.label) {
14642
14620
  case 0:
14643
- if (!this.data.pubkey)
14621
+ if (!this._data.pubkey)
14644
14622
  throw new Error('User not logged');
14645
- this.data.loaded = false;
14623
+ this._data.loaded = false;
14646
14624
  _b.label = 1;
14647
14625
  case 1:
14648
14626
  _b.trys.push([1, 3, , 4]);
@@ -14655,16 +14633,16 @@
14655
14633
  account.settings.locale = account.settings.locale || this.settings.locale;
14656
14634
  account.settings.latLongFormat = account.settings.latLongFormat || this.settings.latLongFormat || 'DDMM';
14657
14635
  // Read main profile
14658
- this.data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14636
+ this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14659
14637
  // Update, instead of replace it
14660
- if (this.data.account) {
14661
- this.data.account.fromObject(account);
14638
+ if (this._data.account) {
14639
+ this._data.account.fromObject(account);
14662
14640
  }
14663
14641
  else {
14664
- this.data.account = account;
14642
+ this._data.account = account;
14665
14643
  }
14666
- this.data.loaded = true;
14667
- return [2 /*return*/, this.data.account];
14644
+ this._data.loaded = true;
14645
+ return [2 /*return*/, this._data.account];
14668
14646
  case 3:
14669
14647
  error_6 = _b.sent();
14670
14648
  this.resetData();
@@ -14703,9 +14681,9 @@
14703
14681
  return [2 /*return*/];
14704
14682
  if (this._debug)
14705
14683
  console.debug("[account] Account restoration...");
14706
- this.data.authToken = token;
14707
- this.data.pubkey = pubkey;
14708
- this.data.keypair = seckey && {
14684
+ this._data.authToken = token;
14685
+ this._data.pubkey = pubkey;
14686
+ this._data.keypair = seckey && {
14709
14687
  publicKey: Base58.decode(pubkey),
14710
14688
  secretKey: Base58.decode(seckey)
14711
14689
  } || null;
@@ -14716,7 +14694,7 @@
14716
14694
  return [4 /*yield*/, this.authenticate()];
14717
14695
  case 3:
14718
14696
  _b.sent();
14719
- if (!this.data.authToken && !this.data.authBasic)
14697
+ if (!this._data.authToken && !this._data.authBasic)
14720
14698
  throw new Error('Authentication failed');
14721
14699
  return [3 /*break*/, 5];
14722
14700
  case 4:
@@ -14749,14 +14727,14 @@
14749
14727
  return [2 /*return*/];
14750
14728
  account = exports.Account.fromObject(jsonAccount);
14751
14729
  // Update data
14752
- this.data.account = account;
14753
- this.data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14754
- this.data.loaded = true;
14730
+ this._data.account = account;
14731
+ this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
14732
+ this._data.loaded = true;
14755
14733
  // Emit event
14756
- this.onLogin.next(this.data.account);
14757
- this.onChange.next(this.data.account);
14734
+ this.onLogin.next(this._data.account);
14735
+ this.onChange.next(this._data.account);
14758
14736
  if (this._debug)
14759
- console.debug("[account] Account restoration [OK] {pubkey: " + pubkey.substr(0, 8) + "}, {profile: " + this.data.mainProfile + "}");
14737
+ console.debug("[account] Account restoration [OK] {pubkey: " + pubkey.substr(0, 8) + "}, {profile: " + this._data.mainProfile + "}");
14760
14738
  return [2 /*return*/, account];
14761
14739
  }
14762
14740
  });
@@ -14772,12 +14750,12 @@
14772
14750
  return __generator(this, function (_b) {
14773
14751
  switch (_b.label) {
14774
14752
  case 0:
14775
- if (!this.data.pubkey)
14753
+ if (!this._data.pubkey)
14776
14754
  throw new Error('User not logged');
14777
14755
  if (this._debug)
14778
- console.debug("[account] Saving account {" + this.data.pubkey.substring(0, 6) + "} in local storage...");
14779
- json = this.data.account.asObject({ keepTypename: true });
14780
- seckey = this.data.keypair && this.data.keypair.secretKey && Base58.encode(this.data.keypair.secretKey) || null;
14756
+ console.debug("[account] Saving account {" + this._data.pubkey.substring(0, 6) + "} in local storage...");
14757
+ json = this._data.account.asObject({ keepTypename: true });
14758
+ seckey = this._data.keypair && this._data.keypair.secretKey && Base58.encode(this._data.keypair.secretKey) || null;
14781
14759
  hasAvatarUrl = json.avatar && !json.avatar.endsWith(DEFAULT_AVATAR_IMAGE) &&
14782
14760
  (json.avatar.startsWith('http://') || (json.avatar.startsWith('https://')));
14783
14761
  if (!(hasAvatarUrl && this.network.online)) return [3 /*break*/, 2];
@@ -14800,9 +14778,9 @@
14800
14778
  case 2:
14801
14779
  _b.trys.push([2, 4, , 5]);
14802
14780
  return [4 /*yield*/, Promise.all([
14803
- this.storage.set(PUBKEY_STORAGE_KEY, this.data.pubkey),
14804
- this.storage.set(TOKEN_STORAGE_KEY, this.data.authToken),
14805
- this.storage.set(ACCOUNT_STORAGE_KEY + "#" + this.data.pubkey, json),
14781
+ this.storage.set(PUBKEY_STORAGE_KEY, this._data.pubkey),
14782
+ this.storage.set(TOKEN_STORAGE_KEY, this._data.authToken),
14783
+ this.storage.set(ACCOUNT_STORAGE_KEY + "#" + this._data.pubkey, json),
14806
14784
  // Secret key (optional)
14807
14785
  seckey && this.storage.set(SECKEY_STORAGE_KEY, seckey) || this.storage.remove(SECKEY_STORAGE_KEY),
14808
14786
  // Remove old storage key
@@ -14879,7 +14857,7 @@
14879
14857
  return __generator(this, function (_b) {
14880
14858
  switch (_b.label) {
14881
14859
  case 0:
14882
- if (!this.data.pubkey)
14860
+ if (!this._data.pubkey)
14883
14861
  throw new Error('User not logged');
14884
14862
  if (!counter)
14885
14863
  console.info('[account] Authentication on pod...');
@@ -14906,7 +14884,7 @@
14906
14884
  if (data_1 && data_1.authenticate) {
14907
14885
  // Store the token
14908
14886
  this.onAuthTokenChange.next(token);
14909
- console.info("[account] Authentication on pod [OK] {pubkey: '" + this.data.pubkey.substr(0, 8) + "'}");
14887
+ console.info("[account] Authentication on pod [OK] {pubkey: '" + this._data.pubkey.substr(0, 8) + "'}");
14910
14888
  return [2 /*return*/, token]; // return the token
14911
14889
  }
14912
14890
  _b.label = 2;
@@ -14932,10 +14910,10 @@
14932
14910
  if (!signatureOK) {
14933
14911
  console.warn('FIXME: Bad peer signature on auth challenge !', data.authChallenge);
14934
14912
  }
14935
- return [4 /*yield*/, this.cryptoService.sign(data.authChallenge.challenge, this.data.keypair)];
14913
+ return [4 /*yield*/, this.cryptoService.sign(data.authChallenge.challenge, this._data.keypair)];
14936
14914
  case 5:
14937
14915
  signature = _b.sent();
14938
- newToken = this.data.pubkey + ":" + data.authChallenge.challenge + "|" + signature;
14916
+ newToken = this._data.pubkey + ":" + data.authChallenge.challenge + "|" + signature;
14939
14917
  return [4 /*yield*/, this.authenticateAndGetToken(newToken, (counter || 1) + 1 /* increment */)];
14940
14918
  case 6:
14941
14919
  // iterate with the new token
@@ -15265,9 +15243,8 @@
15265
15243
  Object.defineProperty(ConfigService.prototype, "config", {
15266
15244
  get: function () {
15267
15245
  // If first call: start loading
15268
- if (!this._started) {
15246
+ if (!this._started)
15269
15247
  this.start();
15270
- }
15271
15248
  return this.$data.pipe(operators.filter(isNotNil));
15272
15249
  },
15273
15250
  enumerable: false,
@@ -15282,30 +15259,49 @@
15282
15259
  console.info('[config] Starting configuration...');
15283
15260
  this._startPromise = this.graphql.ready()
15284
15261
  .then(function () { return _this.loadOrRestoreLocally(); })
15285
- .then(function () {
15262
+ .then(function (data) {
15286
15263
  _this._started = true;
15287
15264
  _this._startPromise = undefined;
15265
+ _this.$data.next(data);
15266
+ return data;
15288
15267
  })
15289
15268
  .catch(function (err) {
15290
15269
  console.error(err && err.message || err, err);
15270
+ _this._started = false;
15291
15271
  _this._startPromise = undefined;
15272
+ return null;
15292
15273
  });
15293
15274
  return this._startPromise;
15294
15275
  };
15295
15276
  ConfigService.prototype.stop = function () {
15296
- this._subscription.unsubscribe();
15297
- this._subscription = new rxjs.Subscription();
15298
- this._started = false;
15299
- this._startPromise = undefined;
15277
+ return __awaiter(this, void 0, void 0, function () {
15278
+ return __generator(this, function (_a) {
15279
+ this._subscription.unsubscribe();
15280
+ this._subscription = new rxjs.Subscription();
15281
+ this._started = false;
15282
+ this._startPromise = undefined;
15283
+ return [2 /*return*/];
15284
+ });
15285
+ });
15300
15286
  };
15301
15287
  ConfigService.prototype.restart = function () {
15302
- if (this.started)
15303
- this.stop();
15304
- return this.start();
15288
+ return __awaiter(this, void 0, void 0, function () {
15289
+ return __generator(this, function (_a) {
15290
+ switch (_a.label) {
15291
+ case 0:
15292
+ if (!this.started) return [3 /*break*/, 2];
15293
+ return [4 /*yield*/, this.stop()];
15294
+ case 1:
15295
+ _a.sent();
15296
+ _a.label = 2;
15297
+ case 2: return [2 /*return*/, this.start()];
15298
+ }
15299
+ });
15300
+ });
15305
15301
  };
15306
15302
  ConfigService.prototype.ready = function () {
15307
15303
  if (this._started)
15308
- return Promise.resolve();
15304
+ return Promise.resolve(this.$data.value);
15309
15305
  if (this._startPromise)
15310
15306
  return this._startPromise;
15311
15307
  return this.start();
@@ -15376,7 +15372,7 @@
15376
15372
  return [4 /*yield*/, this.loadDefault({ fetchPolicy: 'network-only' })];
15377
15373
  case 2:
15378
15374
  reloadedConfig = _a.sent();
15379
- defaultConfig = this.$data.getValue();
15375
+ defaultConfig = this.$data.value;
15380
15376
  if (isNotNil(defaultConfig) && reloadedConfig.label === defaultConfig.label) {
15381
15377
  // Emit update event when is default config
15382
15378
  this.$data.next(reloadedConfig);
@@ -15485,8 +15481,7 @@
15485
15481
  if (wasJustLoaded) {
15486
15482
  // TODO
15487
15483
  }
15488
- this.$data.next(data);
15489
- return [2 /*return*/];
15484
+ return [2 /*return*/, data];
15490
15485
  }
15491
15486
  });
15492
15487
  });
@@ -15697,6 +15692,13 @@
15697
15692
  PlatformService.prototype.isAndroidCordova = function () {
15698
15693
  return this._android && this._cordova;
15699
15694
  };
15695
+ Object.defineProperty(PlatformService.prototype, "canDownload", {
15696
+ get: function () {
15697
+ return this._android && !!this.downloader;
15698
+ },
15699
+ enumerable: false,
15700
+ configurable: true
15701
+ });
15700
15702
  PlatformService.prototype.width = function () {
15701
15703
  return this.platform.width();
15702
15704
  };
@@ -15739,7 +15741,7 @@
15739
15741
  .then(function () {
15740
15742
  _this._started = true;
15741
15743
  _this._startPromise = undefined;
15742
- console.info("[platform] Starting platform [OK] {mobile: " + _this._mobile + ", touchUi: " + _this.touchUi + "} in " + (Date.now() - now) + "ms");
15744
+ console.info("[platform] Starting platform [OK] {mobile: " + _this._mobile + ", touchUi: " + _this.touchUi + ", canDownload: " + _this.canDownload + "} in " + (Date.now() - now) + "ms");
15743
15745
  // Update cache configuration when network changed
15744
15746
  _this.networkService.onNetworkStatusChanges.subscribe(function (type) { return _this.configureCache(type !== 'none'); });
15745
15747
  // Update authentication type
@@ -15788,18 +15790,37 @@
15788
15790
  }
15789
15791
  };
15790
15792
  PlatformService.prototype.download = function (request) {
15791
- if (!request || !request.uri)
15792
- throw new Error('Missing argument \'request\' or \'request.uri\'');
15793
- if (this._android && this._cordova) {
15794
- request = Object.assign(Object.assign({ visibleInDownloadsUi: true, notificationVisibility: ngx$6.NotificationVisibility.VisibleNotifyCompleted, title: request.filename || '' }, request), { destinationInExternalFilesDir: Object.assign({ dirType: 'Downloads', subPath: request.filename || request.title || '' }, request.destinationInExternalFilesDir) });
15795
- this.downloader.download(request)
15796
- .then(function (location) { return console.info('[platform] File successfully downloaded at:' + location); })
15797
- .catch(function (error) { return console.error(error); });
15798
- }
15799
- // Web mode: open URI using the browser
15800
- else {
15801
- this.open(request.uri, '_system', 'location=yes');
15802
- }
15793
+ return __awaiter(this, void 0, void 0, function () {
15794
+ var location, err_1;
15795
+ return __generator(this, function (_a) {
15796
+ switch (_a.label) {
15797
+ case 0:
15798
+ if (!request || !request.uri)
15799
+ throw new Error('Missing argument \'request\' or \'request.uri\'');
15800
+ if (!(this._android && this.downloader)) return [3 /*break*/, 5];
15801
+ request = Object.assign({ visibleInDownloadsUi: true, notificationVisibility: ngx$6.NotificationVisibility.VisibleNotifyCompleted }, request);
15802
+ _a.label = 1;
15803
+ case 1:
15804
+ _a.trys.push([1, 3, , 4]);
15805
+ console.debug('[platform] Downloading, using request: ' + JSON.stringify(request));
15806
+ return [4 /*yield*/, this.downloader.download(request)];
15807
+ case 2:
15808
+ location = _a.sent();
15809
+ console.info('[platform] File successfully downloaded at:' + location);
15810
+ return [2 /*return*/, location];
15811
+ case 3:
15812
+ err_1 = _a.sent();
15813
+ console.error('[platform] Unable to download: ' + (err_1 && err_1.message || err_1));
15814
+ throw err_1;
15815
+ case 4: return [3 /*break*/, 6];
15816
+ case 5:
15817
+ console.warn('[platform] Cannot use Cordova downloader: using browser open()');
15818
+ this.open(request.uri, '_system', 'location=no', true);
15819
+ return [2 /*return*/, undefined];
15820
+ case 6: return [2 /*return*/];
15821
+ }
15822
+ });
15823
+ });
15803
15824
  };
15804
15825
  /* -- protected methods -- */
15805
15826
  PlatformService.prototype.configureCordovaPlugins = function (mobile) {
@@ -15895,7 +15916,7 @@
15895
15916
  };
15896
15917
  PlatformService.prototype.migrateStorage = function (forage) {
15897
15918
  return __awaiter(this, void 0, void 0, function () {
15898
- var canMigrate, oldForage, keys, now, toast_1, duration, err_1;
15919
+ var canMigrate, oldForage, keys, now, toast_1, duration, err_2;
15899
15920
  return __generator(this, function (_a) {
15900
15921
  switch (_a.label) {
15901
15922
  case 0:
@@ -15913,8 +15934,8 @@
15913
15934
  case 1:
15914
15935
  keys = _a.sent();
15915
15936
  if (!isEmptyArray(keys)) return [3 /*break*/, 3];
15916
- // Drop the old instance
15917
- console.info("[platform] Drop old storage {name: '" + forage.config().name + "', driver: '" + oldForage.driver() + "'}");
15937
+ // Drop the old instance (not need anymore)
15938
+ console.debug("[platform] Old storage is empty: dropping unused instance {name: '" + forage.config().name + "', driver: '" + oldForage.driver() + "'}");
15918
15939
  return [4 /*yield*/, oldForage.dropInstance()];
15919
15940
  case 2:
15920
15941
  _a.sent();
@@ -15948,8 +15969,8 @@
15948
15969
  _a.sent();
15949
15970
  return [3 /*break*/, 12];
15950
15971
  case 9:
15951
- err_1 = _a.sent();
15952
- console.error(err_1 && err_1.message || err_1, err_1);
15972
+ err_2 = _a.sent();
15973
+ console.error(err_2 && err_2.message || err_2, err_2);
15953
15974
  return [4 /*yield*/, toast_1.dismiss()];
15954
15975
  case 10:
15955
15976
  _a.sent();
@@ -21258,22 +21279,24 @@
21258
21279
  ANDROID_APK: 'application/vnd.android.package-archive'
21259
21280
  });
21260
21281
  var AppInstallUpgradeCard = /** @class */ (function () {
21261
- function AppInstallUpgradeCard(modalCtrl, configService, platform, cd, network, environment) {
21282
+ function AppInstallUpgradeCard(modalCtrl, configService, toastController, translate, cd, platform, network, environment) {
21262
21283
  this.modalCtrl = modalCtrl;
21263
21284
  this.configService = configService;
21264
- this.platform = platform;
21285
+ this.toastController = toastController;
21286
+ this.translate = translate;
21265
21287
  this.cd = cd;
21288
+ this.platform = platform;
21266
21289
  this.network = network;
21267
21290
  this.environment = environment;
21268
21291
  this._subscription = new rxjs.Subscription();
21269
21292
  this._showUpdateOfflineFeature = false;
21270
21293
  this.loading = true;
21294
+ this.downloading = false;
21271
21295
  this.waitingNetwork = false;
21272
21296
  this.showUpgradeWarning = true;
21273
21297
  this.showOfflineWarning = true;
21274
21298
  this.showInstallButton = false;
21275
21299
  this.onUpdateOfflineModeClick = new i0.EventEmitter();
21276
- this.isAndroidCordova = platform.isAndroidCordova();
21277
21300
  }
21278
21301
  Object.defineProperty(AppInstallUpgradeCard.prototype, "showUpdateOfflineFeature", {
21279
21302
  get: function () {
@@ -21299,18 +21322,8 @@
21299
21322
  this.offline = this.network.offline;
21300
21323
  // Listen pod config
21301
21324
  this._subscription.add(this.configService.config
21302
- .subscribe(function (config) {
21303
- console.info('[install] Checking if upgrade or install is need...');
21304
- var installLinks = _this.getAllInstallLinks(config);
21305
- // Check for upgrade
21306
- _this.updateLinks = _this.getCompatibleUpgradeLinks(installLinks, config);
21307
- // Check for install links (if no upgrade need)
21308
- _this.installLinks = !_this.updateLinks && _this.getCompatibleInstallLinks(installLinks);
21309
- setTimeout(function () {
21310
- _this.loading = false;
21311
- _this.markForCheck();
21312
- }, 2000); // Add a delay, for animation
21313
- }));
21325
+ .pipe(operators.debounceTime(1000))
21326
+ .subscribe(function (config) { return _this.checkNeedInstallOrUpdate(config); }));
21314
21327
  // Listen network changes
21315
21328
  this._subscription.add(this.network.onNetworkStatusChanges
21316
21329
  .pipe(
@@ -21318,8 +21331,10 @@
21318
21331
  //tap(() => this.waitingNetwork = false),
21319
21332
  operators.map(function (connectionType) { return connectionType === 'none'; }), operators.distinctUntilChanged())
21320
21333
  .subscribe(function (offline) {
21321
- _this.offline = offline;
21322
- _this.markForCheck();
21334
+ if (_this.offline !== offline) {
21335
+ _this.offline = offline;
21336
+ _this.markForCheck();
21337
+ }
21323
21338
  }));
21324
21339
  return [2 /*return*/];
21325
21340
  }
@@ -21329,27 +21344,74 @@
21329
21344
  AppInstallUpgradeCard.prototype.ngOnDestroy = function () {
21330
21345
  this._subscription.unsubscribe();
21331
21346
  };
21332
- AppInstallUpgradeCard.prototype.downloadLink = function (event, link) {
21333
- if (!link || !link.url)
21334
- return; // Skip
21335
- this.platform.download({
21336
- uri: link.url,
21337
- filename: link.downloadFilename,
21338
- mimeType: link.mimeType
21347
+ AppInstallUpgradeCard.prototype.download = function (event, link) {
21348
+ return __awaiter(this, void 0, void 0, function () {
21349
+ var location;
21350
+ return __generator(this, function (_a) {
21351
+ if (!link || !link.url) {
21352
+ console.error('[install-upgrade-card] Missing required argument \'link.url\'');
21353
+ return [2 /*return*/]; // Skip
21354
+ }
21355
+ this.downloading = true;
21356
+ try {
21357
+ console.info('[install-upgrade-card] User ask download of: ' + link.url);
21358
+ location = this.platform.download({
21359
+ uri: link.url,
21360
+ title: link.name,
21361
+ filename: link.downloadFilename,
21362
+ mimeType: link.mimeType
21363
+ });
21364
+ console.info('[install-upgrade-card] File downloaded at: ' + location);
21365
+ }
21366
+ // Failed: display a toast
21367
+ catch (err) {
21368
+ console.error('[install-upgrade] Download failed: ' + (err && err.message || err));
21369
+ this.showToast({
21370
+ message: 'ERROR.DOWNLOAD_FAILED',
21371
+ messageParams: { error: err },
21372
+ type: 'error',
21373
+ showCloseButton: true
21374
+ });
21375
+ return [2 /*return*/]; // Stop here
21376
+ }
21377
+ finally {
21378
+ this.downloading = false;
21379
+ this.markForCheck();
21380
+ }
21381
+ this.showToast({
21382
+ message: 'INFO.DOWNLOAD_UPDATE_SUCCEED',
21383
+ type: 'info',
21384
+ showCloseButton: true
21385
+ });
21386
+ return [2 /*return*/];
21387
+ });
21339
21388
  });
21340
21389
  };
21341
21390
  AppInstallUpgradeCard.prototype.tryOnline = function () {
21342
- var _this = this;
21343
- this.waitingNetwork = true;
21344
- this.markForCheck();
21345
- this.network.tryOnline({
21346
- showLoadingToast: false,
21347
- showOnlineToast: true,
21348
- showOfflineToast: false
21349
- })
21350
- .then(function () {
21351
- _this.waitingNetwork = false;
21352
- _this.markForCheck();
21391
+ return __awaiter(this, void 0, void 0, function () {
21392
+ return __generator(this, function (_a) {
21393
+ switch (_a.label) {
21394
+ case 0:
21395
+ this.waitingNetwork = true;
21396
+ this.markForCheck();
21397
+ _a.label = 1;
21398
+ case 1:
21399
+ _a.trys.push([1, , 3, 4]);
21400
+ return [4 /*yield*/, this.network.tryOnline({
21401
+ showLoadingToast: false,
21402
+ showOnlineToast: true,
21403
+ showOfflineToast: false
21404
+ })];
21405
+ case 2:
21406
+ _a.sent();
21407
+ return [3 /*break*/, 4];
21408
+ case 3:
21409
+ this.waitingNetwork = false;
21410
+ this.markForCheck();
21411
+ return [7 /*endfinally*/];
21412
+ case 4: return [2 /*return*/];
21413
+ }
21414
+ });
21353
21415
  });
21354
21416
  };
21355
21417
  AppInstallUpgradeCard.prototype.getPlatformName = function (platform) {
@@ -21366,6 +21428,34 @@
21366
21428
  return value;
21367
21429
  };
21368
21430
  /* -- private method -- */
21431
+ AppInstallUpgradeCard.prototype.checkNeedInstallOrUpdate = function (config) {
21432
+ return __awaiter(this, void 0, void 0, function () {
21433
+ var installLinks;
21434
+ return __generator(this, function (_a) {
21435
+ switch (_a.label) {
21436
+ case 0:
21437
+ console.info('[install] Check if need to install or upgrade...');
21438
+ _a.label = 1;
21439
+ case 1:
21440
+ _a.trys.push([1, , 3, 4]);
21441
+ installLinks = this.getAllInstallLinks(config);
21442
+ // Check for upgrade
21443
+ this.updateLinks = this.getCompatibleUpgradeLinks(installLinks, config);
21444
+ // Check for install links (if no upgrade need)
21445
+ this.installLinks = !this.updateLinks && this.getCompatibleInstallLinks(installLinks);
21446
+ return [4 /*yield*/, sleep(500)];
21447
+ case 2:
21448
+ _a.sent(); // Add a delay, for animation
21449
+ return [3 /*break*/, 4];
21450
+ case 3:
21451
+ this.loading = false;
21452
+ this.markForCheck();
21453
+ return [7 /*endfinally*/];
21454
+ case 4: return [2 /*return*/];
21455
+ }
21456
+ });
21457
+ });
21458
+ };
21369
21459
  AppInstallUpgradeCard.prototype.getCompatibleInstallLinks = function (installLinks) {
21370
21460
  // Cordova already running: not need to install
21371
21461
  if (this.platform.is('cordova'))
@@ -21378,15 +21468,20 @@
21378
21468
  };
21379
21469
  AppInstallUpgradeCard.prototype.getCompatibleUpgradeLinks = function (installLinks, config) {
21380
21470
  var _this = this;
21381
- var appMinVersion = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
21382
- var needUpgrade = appMinVersion && !VersionUtils.isCompatible(appMinVersion, this.environment.version);
21471
+ var appVersion = this.environment.version;
21472
+ var appMinVersionFromPod = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
21473
+ if (!appVersion) {
21474
+ console.error('Missing value for \'environment.version\': cannot check app compatibility!');
21475
+ return undefined;
21476
+ }
21477
+ var needUpgrade = appMinVersionFromPod && !VersionUtils.isCompatible(appMinVersionFromPod, appVersion);
21383
21478
  if (!needUpgrade)
21384
21479
  return undefined;
21385
21480
  var upgradeLinks = installLinks
21386
21481
  .filter(function (link) { return _this.platform.is('mobileweb') || (link.platform && _this.platform.is(link.platform)); });
21387
21482
  // Use min version as default version
21388
21483
  upgradeLinks.forEach(function (link) {
21389
- link.version = link.version || appMinVersion;
21484
+ link.version = link.version || appMinVersionFromPod;
21390
21485
  });
21391
21486
  return isNotEmptyArray(upgradeLinks) ? upgradeLinks : undefined;
21392
21487
  };
@@ -21398,6 +21493,7 @@
21398
21493
  var url = config.getProperty(CORE_CONFIG_OPTIONS.ANDROID_INSTALL_URL);
21399
21494
  if (isNilOrBlank(url))
21400
21495
  url = this.environment.defaultAndroidInstallUrl || null;
21496
+ var minVersion = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
21401
21497
  // Compute App name
21402
21498
  var name = isNotNilOrBlank(url) && config.label || this.environment.defaultAppName || 'SUMARiS';
21403
21499
  if (url) {
@@ -21406,7 +21502,7 @@
21406
21502
  var mimeType = void 0;
21407
21503
  // Get file name
21408
21504
  var filename = this.getFilename(url);
21409
- version = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
21505
+ version = minVersion || 'latest';
21410
21506
  // OK, this is a downloadable APK file (e.g. NOT a link to a playstore)
21411
21507
  if (filename === null || filename === void 0 ? void 0 : filename.endsWith('.apk')) {
21412
21508
  // Define mime type
@@ -21416,13 +21512,12 @@
21416
21512
  version = versionMatches && versionMatches[1] || version;
21417
21513
  // Compute a new file name, with the version
21418
21514
  if (isNotNilOrBlank(name)) {
21419
- downloadFilename = name + "-" + version + ".apk";
21515
+ downloadFilename = (name + "-v" + version + ".apk").toLowerCase();
21420
21516
  }
21421
21517
  else {
21422
21518
  downloadFilename = filename;
21423
- // Replace 'latest' with the app min version
21519
+ // Replace 'latest' with the app version, if present
21424
21520
  if (downloadFilename.indexOf('latest')) {
21425
- version = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
21426
21521
  downloadFilename = downloadFilename.replace('latest', version);
21427
21522
  }
21428
21523
  }
@@ -21451,12 +21546,24 @@
21451
21546
  AppInstallUpgradeCard.prototype.markForCheck = function () {
21452
21547
  this.cd.markForCheck();
21453
21548
  };
21549
+ AppInstallUpgradeCard.prototype.showToast = function (opts) {
21550
+ return __awaiter(this, void 0, void 0, function () {
21551
+ return __generator(this, function (_a) {
21552
+ switch (_a.label) {
21553
+ case 0: return [4 /*yield*/, Toasts.show(this.toastController, this.translate, opts)];
21554
+ case 1:
21555
+ _a.sent();
21556
+ return [2 /*return*/];
21557
+ }
21558
+ });
21559
+ });
21560
+ };
21454
21561
  return AppInstallUpgradeCard;
21455
21562
  }());
21456
21563
  AppInstallUpgradeCard.decorators = [
21457
21564
  { type: i0.Component, args: [{
21458
21565
  selector: 'app-install-upgrade-card',
21459
- template: "\n\n<!-- Offline mode card-->\n<ion-card *ngIf=\"showOfflineWarning && (!loading && offline || waitingNetwork)\"\n color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\" *ngIf=\"!waitingNetwork; else waitingNetworkText\">\n <h4>\n <b *ngIf=\"isLogin; else notLogin\" [innerHTML]=\"'NETWORK.INFO.OFFLINE_OR_UNAUTHORIZED'| translate\"></b>\n <ng-template #notLogin>\n <b [innerHTML]=\"'NETWORK.INFO.OFFLINE'| translate\"></b>\n </ng-template>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.OFFLINE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n <ng-template #waitingNetworkText>\n <ion-text class=\"ion-text-wrap\" [innerHTML]=\"'NETWORK.INFO.RETRY_TO_CONNECT'| translate\"></ion-text>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\">\n\n <!-- Retry button -->\n <ion-button *ngIf=\"!waitingNetwork; else waitingSpinner\" color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"tryOnline()\">\n <span translate>NETWORK.BTN_CHECK_ALIVE</span>\n </ion-button>\n\n <!-- Waiting spinner -->\n <ng-template #waitingSpinner>\n <ion-spinner *ngIf=\"waitingNetwork\" color=\"light\"></ion-spinner>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Upgrade links -->\n<ion-card *ngIf=\"showUpgradeWarning && !loading && !offline && updateLinks\"\n color=\"accent\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of updateLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3>\n <span *ngIf=\"link.version\" [innerHTML]=\"'INFO.UPDATE_APP_TO_VERSION'| translate: link\"></span>\n <span *ngIf=\"!link.version\" [innerHTML]=\"'INFO.UPDATE_APP'| translate: link\"></span>\n </h3>\n <h4>\n <small *ngIf=\"last\" [innerHTML]=\"'INFO.UPDATE_APP_HELP'|translate\"></small>\n </h4>\n </ion-text>\n </ion-col>\n\n <ion-col size=\"auto\">\n\n <!-- Download button -->\n <ion-button *ngIf=\"link.downloadFilename; else redirectButton\"\n [download]=\"link.downloadFilename\"\n [href]=\"link.url\"\n color=\"tertiary\" class=\"ion-float-end\" >\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n\n <!-- Redirect button -->\n <ng-template #redirectButton>\n <ion-button [href]=\"link.url\" rel=\"external\" color=\"tertiary\" class=\"ion-float-end\" target=\"_blank\">\n <ion-label translate>COMMON.BTN_SHOW_MORE</ion-label>\n </ion-button>\n </ng-template>\n\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Install links -->\n<ion-card *ngIf=\"showInstallButton && !loading && !offline && installLinks\"\n color=\"secondary\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of installLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3 [innerHTML]=\"'INFO.DOWNLOAD_APP_TITLE'| translate: {name: link.name, platform: getPlatformName(link.platform) }\"></h3>\n <h4><small *ngIf=\"last\" [innerHTML]=\"'INFO.DOWNLOAD_APP_HELP'|translate\"></small></h4>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Update offline feature card-->\n<ion-card *ngIf=\"showUpdateOfflineFeature && !loading && !offline\"\n color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h4>\n <b [innerHTML]=\"'NETWORK.INFO.UPDATE_OFFLINE_MODE'| translate\"></b>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.UPDATE_OFFLINE_MODE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n\n <!-- Retry button -->\n <ion-button color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"onUpdateOfflineModeClick.emit($event)\">\n <span translate>NETWORK.BTN_UPDATE</span>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Display a download button, depending on the link URL, and the device platform -->\n<ng-template #downloadButton let-link>\n\n <ng-container *ngIf=\"link.downloadFilename; else redirectButton\">\n\n <!-- Cordova download button -->\n <ion-button *ngIf=\"isAndroidCordova; else webDownloadButton\"\n (click)=\"downloadLink($event, asLink(link))\"\n color=\"tertiary\" class=\"ion-float-end\" >\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n\n <!-- Web download button -->\n <ng-template #webDownloadButton>\n <ion-button [download]=\"link.downloadFilename\"\n [href]=\"link.url\"\n color=\"tertiary\" class=\"ion-float-end\" >\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n </ng-template>\n </ng-container>\n\n <!-- Web redirect button -->\n <ng-template #redirectButton>\n <ion-button [href]=\"link.url\" rel=\"external\" color=\"tertiary\" class=\"ion-float-end\" target=\"_blank\">\n <ion-label translate>COMMON.BTN_SHOW_MORE</ion-label>\n </ion-button>\n </ng-template>\n</ng-template>\n",
21566
+ template: "\n\n<!-- Offline mode card-->\n<ion-card *ngIf=\"showOfflineWarning && (!loading && offline || waitingNetwork)\"\n color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\" *ngIf=\"!waitingNetwork; else waitingNetworkText\">\n <h4>\n <b *ngIf=\"isLogin; else notLogin\" [innerHTML]=\"'NETWORK.INFO.OFFLINE_OR_UNAUTHORIZED'| translate\"></b>\n <ng-template #notLogin>\n <b [innerHTML]=\"'NETWORK.INFO.OFFLINE'| translate\"></b>\n </ng-template>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.OFFLINE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n <ng-template #waitingNetworkText>\n <ion-text class=\"ion-text-wrap\" [innerHTML]=\"'NETWORK.INFO.RETRY_TO_CONNECT'| translate\"></ion-text>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\">\n\n <!-- Retry button -->\n <ion-button *ngIf=\"!waitingNetwork; else waitingSpinner\" color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"tryOnline()\">\n <span translate>NETWORK.BTN_CHECK_ALIVE</span>\n </ion-button>\n\n <!-- Waiting spinner -->\n <ng-template #waitingSpinner>\n <ion-spinner *ngIf=\"waitingNetwork\" color=\"light\"></ion-spinner>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Upgrade links -->\n<ion-card *ngIf=\"showUpgradeWarning && !loading && !offline && updateLinks\"\n color=\"accent\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of updateLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3>\n <span *ngIf=\"link.version\" [innerHTML]=\"'INFO.UPDATE_APP_TO_VERSION'| translate: link\"></span>\n <span *ngIf=\"!link.version\" [innerHTML]=\"'INFO.UPDATE_APP'| translate: link\"></span>\n </h3>\n <h4>\n <small *ngIf=\"last\" [innerHTML]=\"'INFO.UPDATE_APP_HELP'|translate\"></small>\n </h4>\n </ion-text>\n </ion-col>\n\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Install links -->\n<ion-card *ngIf=\"showInstallButton && !loading && !offline && installLinks\"\n color=\"secondary\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of installLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3 [innerHTML]=\"'INFO.DOWNLOAD_APP_TITLE'| translate: {name: link.name, platform: getPlatformName(link.platform) }\"></h3>\n <h4><small *ngIf=\"last\" [innerHTML]=\"'INFO.DOWNLOAD_APP_HELP'|translate\"></small></h4>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Update offline feature card-->\n<ion-card *ngIf=\"showUpdateOfflineFeature && !loading && !offline\"\n color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h4>\n <b [innerHTML]=\"'NETWORK.INFO.UPDATE_OFFLINE_MODE'| translate\"></b>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.UPDATE_OFFLINE_MODE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n\n <!-- Retry button -->\n <ion-button color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"onUpdateOfflineModeClick.emit($event)\">\n <span translate>NETWORK.BTN_UPDATE</span>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Display a download button, depending on the link URL, and the device platform -->\n<ng-template #downloadButton let-link>\n\n <ng-container *ngIf=\"link.downloadFilename; else redirectButton\">\n\n <!-- Download using platform -->\n <ion-button *ngIf=\"platform.canDownload; else webDownloadButton\"\n (click)=\"download($event, asLink(link))\"\n [disabled]=\"downloading\"\n color=\"tertiary\" class=\"ion-float-end\">\n <ion-icon slot=\"start\" *ngIf=\"!downloading\" name=\"download\"></ion-icon>\n <ion-spinner slot=\"start\" class=\"ion-no-padding\" *ngIf=\"downloading\"></ion-spinner>\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n\n <!-- Web download button -->\n <ng-template #webDownloadButton>\n <ion-button [download]=\"link.downloadFilename\"\n [href]=\"link.url\"\n color=\"tertiary\" class=\"ion-float-end\" >\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n </ng-template>\n </ng-container>\n\n <!-- Web redirect button -->\n <ng-template #redirectButton>\n <ion-button [href]=\"link.url\" rel=\"external\" color=\"tertiary\" class=\"ion-float-end\" target=\"_blank\">\n <ion-label translate>COMMON.BTN_SHOW_MORE</ion-label>\n </ion-button>\n </ng-template>\n</ng-template>\n",
21460
21567
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
21461
21568
  animations: [slideUpDownAnimation],
21462
21569
  styles: ["ion-text small{font-size:85%}"]
@@ -21465,8 +21572,10 @@
21465
21572
  AppInstallUpgradeCard.ctorParameters = function () { return [
21466
21573
  { type: i1$5.ModalController },
21467
21574
  { type: ConfigService },
21468
- { type: PlatformService },
21575
+ { type: i1$5.ToastController },
21576
+ { type: i1$2.TranslateService },
21469
21577
  { type: i0.ChangeDetectorRef },
21578
+ { type: PlatformService },
21470
21579
  { type: NetworkService },
21471
21580
  { type: undefined, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] }
21472
21581
  ]; };
@@ -27156,6 +27265,7 @@
27156
27265
  _this.filterCriteriaCount = 0;
27157
27266
  _this.statusList = StatusList;
27158
27267
  _this.statusById = StatusById;
27268
+ _this.useSticky = false;
27159
27269
  _this.referentialToString = referentialToString;
27160
27270
  _this.inlineEdition = accountService.isAdmin(); // Allow inline edition only if admin
27161
27271
  _this.canEdit = accountService.isAdmin();
@@ -27274,13 +27384,13 @@
27274
27384
  UsersPage.decorators = [
27275
27385
  { type: i0.Component, args: [{
27276
27386
  selector: 'app-users-table',
27277
- template: "<app-toolbar [title]=\"'USER.LIST.TITLE'|translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"!(loadingSubject|async) && dirty\"\n (onValidate)=\"save()\">\n <ion-buttons slot=\"end\">\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n <!-- Add -->\n <button mat-icon-button\n *ngIf=\"canEdit && !mobile\"\n [title]=\"'COMMON.BTN_ADD'|translate\"\n (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\"\n [title]=\"'COMMON.BTN_REFRESH'|translate\"\n (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\"\n *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold;\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\">filter_list_alt</mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n </ng-container>\n\n <ng-template #hasSelection>\n <!-- delete -->\n <button mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n (click)=\"deleteSelection($event)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content class=\"ion-no-padding\">\n\n <!-- error -->\n <ion-item *ngIf=\"errorSubject|async ; let error\" lines=\"none\" @slideUpDownAnimation>\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 <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"onRefresh.emit()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.LIST.FILTER.SEARCH'|translate\" formControlName=\"searchText\">\n\n <button mat-icon-button matSuffix tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-select formControlName=\"statusId\" [placeholder]=\"'USER.STATUS'|translate\" >\n <mat-option [value]=\"null\"><i><span translate>COMMON.EMPTY_OPTION</span></i></mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </mat-select>\n\n <button mat-icon-button matSuffix tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label [hidden]=\"(loadingSubject|async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\">\n {{ (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT') | translate: {count: (totalRowCount |\n numberFormat)} }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject|async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject|async\">\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" visible-xs visible-sm visible-mobile 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 <div class=\"table-container\">\n <table #table mat-table matSort\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\" [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear [trackBy]=\"trackByFn\">\n\n <ng-container matColumnDef=\"select\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\" [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">{{ row.currentData.id }}</td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <div class=\"avatar\" *ngIf=\"row.currentData.avatar; else generateIcon\"\n [ngStyle]=\"{'background-image':'url('+row.currentData.avatar+')'}\"></div>\n <ng-template #generateIcon>\n <div class=\"avatar\">\n <svg width=\"38\" width=\"38\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </div>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls['lastName']\" [placeholder]=\"'USER.LAST_NAME'|translate\"\n [readonly]=\"!row.editing\" [appAutofocus]=\"row == -1 && row.editing\">\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n </td>\n\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls['firstName']\" [placeholder]=\"'USER.FIRST_NAME'|translate\"\n [readonly]=\"!row.editing\">\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls['email']\" [placeholder]=\"'USER.EMAIL'|translate\"\n [readonly]=\"!row.editing\">\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{definition.label|translate}}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <app-form-field floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\">\n </app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">\n <mat-form-field floatLabel=\"never\">\n <mat-select [formControl]=\"row.validator.controls['mainProfile']\" [placeholder]=\"'USER.PROFILE'|translate\">\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ ('USER.PROFILE_ENUM.' + item) | uppercase |translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">\n <mat-form-field floatLabel=\"never\">\n <ion-icon matPrefix *ngIf=\"row.validator.controls['statusId'].value &gt;=0\" [name]=\"statusById[row.validator.controls['statusId'].value]?.icon\"></ion-icon>\n\n <mat-select [formControl]=\"row.validator.controls['statusId']\" [placeholder]=\"'REFERENTIAL.STATUS'|translate\">\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value &gt;=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate}}</span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls.username\" [placeholder]=\"'USER.USERNAME'|translate\"\n [readonly]=\"!row.editing\">\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls.usernameExtranet\" [placeholder]=\"'USER.USERNAME_EXTRANET'|translate\"\n [readonly]=\"!row.editing\">\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\" [title]=\"row.validator.controls['pubkey'].value\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls['pubkey']\" [placeholder]=\"'USER.PUBKEY'|translate\"\n [readonly]=\"!row.editing\" autocomplete=\"off\">\n <mat-error *ngIf=\"row.validator.controls['pubkey'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['pubkey'].hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column [stickyEnd]=\"true\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\">\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject|async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n </div>\n</ion-content>\n\n<ion-footer>\n <mat-paginator class=\"mat-paginator-footer\"\n [length]=\"totalRowCount\" [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\" showFirstLastButtons>\n </mat-paginator>\n\n <app-form-buttons-bar *ngIf=\"!mobile && inlineEdition\"\n (onCancel)=\"onRefresh.emit()\" (onSave)=\"save()\" [disabled]=\"(loadingSubject|async) || !dirty\"></app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n",
27387
+ template: "<app-toolbar [title]=\"'USER.LIST.TITLE'|translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"!(loadingSubject|async) && dirty\"\n (onValidate)=\"save()\">\n <ion-buttons slot=\"end\">\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n <!-- Add -->\n <button mat-icon-button\n *ngIf=\"canEdit && !mobile\"\n [title]=\"'COMMON.BTN_ADD'|translate\"\n (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\"\n [title]=\"'COMMON.BTN_REFRESH'|translate\"\n (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\"\n *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold;\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\">filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n </ng-container>\n\n <ng-template #hasSelection>\n <!-- delete -->\n <button mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n (click)=\"deleteSelection($event)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n </ion-buttons>\n</app-toolbar>\n\n<ion-content class=\"ion-no-padding\">\n\n <!-- error -->\n <ion-item *ngIf=\"errorSubject|async ; let error\" lines=\"none\" @slideUpDownAnimation>\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 <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"onRefresh.emit()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <input matInput [placeholder]=\"'USER.LIST.FILTER.SEARCH'|translate\" formControlName=\"searchText\">\n\n <button mat-icon-button matSuffix tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-select formControlName=\"statusId\" [placeholder]=\"'USER.STATUS'|translate\">\n <mat-option [value]=\"null\"><i><span translate>COMMON.EMPTY_OPTION</span></i></mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </mat-select>\n\n <button mat-icon-button matSuffix tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label [hidden]=\"(loadingSubject|async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\">\n {{ (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT') | translate: {\n count: (totalRowCount |\n numberFormat)\n } }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject|async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject|async\">\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" visible-xs visible-sm visible-mobile 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 <div class=\"table-container\">\n <table #table mat-table matSort\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\" [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear [trackBy]=\"trackByFn\">\n\n <ng-container matColumnDef=\"select\" [sticky]=\"useSticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\n </mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\" [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"useSticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">{{ row.currentData.id }}</td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"useSticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <div class=\"avatar\" *ngIf=\"row.currentData.avatar; else generateIcon\"\n [ngStyle]=\"{'background-image':'url('+row.currentData.avatar+')'}\"></div>\n <ng-template #generateIcon>\n <div class=\"avatar\">\n <svg width=\"38\" width=\"38\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </div>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn='lastName'\">\n <mat-form-field floatLabel=\"never\">\n <input matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME'|translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn==='lastName'\">\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n\n </td>\n\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n\n (click)=\"focusColumn='firstName'\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME'|translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn==='firstName'\">\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{'ERROR.FIELD_MIN_LENGTH' | translate: {minLength: 2} }}</span>\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn='email'\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL'|translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn==='email'\">\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{definition.label|translate}}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n (click)=\"focusColumn=definition.key\">\n <app-form-field floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn===definition.ke\">\n </app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n (click)=\"focusColumn='profile'\">\n <mat-form-field floatLabel=\"never\">\n <mat-select [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE'|translate\">\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ ('USER.PROFILE_ENUM.' + item) | uppercase |translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n (click)=\"focusColumn='status'\">\n <mat-form-field floatLabel=\"never\">\n <ion-icon matPrefix *ngIf=\"row.validator.controls['statusId'].value &gt;=0\" [name]=\"statusById[row.validator.controls['statusId'].value]?.icon\"></ion-icon>\n\n <mat-select [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS'|translate\">\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value &gt;=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate}}</span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label |translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n (click)=\"focusColumn='username'\">\n <mat-form-field floatLabel=\"never\" >\n <input matInput [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME'|translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn==='username'\">\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n (click)=\"focusColumn='usernameExtranet'\">\n <mat-form-field floatLabel=\"never\">\n <input matInput [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET'|translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn==='usernameExtranet'\">\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td mat-cell *matCellDef=\"let row\"\n [title]=\"row.validator.controls['pubkey'].value\"\n (click)=\"focusColumn='pubkey'\">\n <mat-form-field floatLabel=\"never\" >\n <input matInput [formControl]=\"row.validator.controls['pubkey']\" [placeholder]=\"'USER.PUBKEY'|translate\"\n [readonly]=\"!row.editing\" autocomplete=\"off\">\n <mat-error *ngIf=\"row.validator.controls['pubkey'].hasError('required')\" translate>ERROR.FIELD_REQUIRED</mat-error>\n <mat-error *ngIf=\"row.validator.controls['pubkey'].hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column [stickyEnd]=\"useSticky\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [canCancel]=\"false\">\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.validator.invalid\"></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject|async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n </div>\n</ion-content>\n\n<ion-footer>\n <mat-paginator class=\"mat-paginator-footer\"\n [length]=\"totalRowCount\" [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\" showFirstLastButtons>\n </mat-paginator>\n\n <app-form-buttons-bar *ngIf=\"!mobile && inlineEdition\"\n (onCancel)=\"onRefresh.emit()\" (onSave)=\"save()\" [disabled]=\"(loadingSubject|async) || !dirty\"></app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n",
27278
27388
  providers: [
27279
27389
  { provide: ngxMaterialTable.ValidatorService, useExisting: PersonValidatorService }
27280
27390
  ],
27281
27391
  animations: [slideUpDownAnimation],
27282
27392
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
27283
- styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:calc(100%)}.mat-table .mat-cell .avatar{height:40px;width:40px;margin:2px 0 0;background-size:cover;background-repeat:no-repeat;background-position:50%}.mat-table .mat-column-avatar{min-width:50px}.mat-table .mat-column-profile{min-width:110px}.mat-table .mat-column-status{min-width:130px}.mat-table .mat-column-department{min-width:150px}"]
27393
+ styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-table .mat-cell .avatar{height:40px;width:40px;margin:2px 0 0;background-size:cover;background-repeat:no-repeat;background-position:50%}.mat-table .mat-column-id{width:30px}.mat-table .mat-column-avatar{width:50px}.mat-table .mat-column-avatar .avatar{border-radius:5px;border:1px solid rgba(var(--ion-color-secondary-rgb),.5)}.mat-table .mat-column-firstName,.mat-table .mat-column-lastName{min-width:80px}.mat-table .mat-column-email{min-width:120px}.mat-table .mat-column-profile{min-width:110px}.mat-table .mat-column-status{min-width:130px}.mat-table .mat-column-department{min-width:150px}"]
27284
27394
  },] }
27285
27395
  ];
27286
27396
  UsersPage.ctorParameters = function () { return [
@@ -27300,6 +27410,7 @@
27300
27410
  { type: undefined, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] }
27301
27411
  ]; };
27302
27412
  UsersPage.propDecorators = {
27413
+ useSticky: [{ type: i0.Input }],
27303
27414
  filterExpansionPanel: [{ type: i0.ViewChild, args: [expansion.MatExpansionPanel, { static: true },] }]
27304
27415
  };
27305
27416
 
@@ -27573,6 +27684,7 @@
27573
27684
  exports.SharedTestingModule = SharedTestingModule;
27574
27685
  exports.SharedValidators = SharedValidators;
27575
27686
  exports.SocialModule = SocialModule;
27687
+ exports.StartableService = StartableService;
27576
27688
  exports.StatusById = StatusById;
27577
27689
  exports.StatusIds = StatusIds;
27578
27690
  exports.StatusList = StatusList;
@@ -27721,17 +27833,17 @@
27721
27833
  exports.waitFor = waitFor;
27722
27834
  exports.waitIdle = waitIdle;
27723
27835
  exports.waitWhilePending = waitWhilePending;
27724
- exports0 = ɵ0$5;
27725
- exports.ɵa = CustomReuseStrategy;
27726
- exports.ɵb = MatNumpadDomService;
27727
- exports.ɵc = isFocusableElement;
27728
- exports.ɵd = RegisterForm;
27729
- exports.ɵe = AccountValidatorService;
27730
- exports.ɵf = RegisterModal;
27731
- exports.ɵg = UserSettingsValidatorService;
27732
- exports.ɵh = LocalSettingsValidatorService;
27836
+ exports["ɵ0"] = ɵ0$5;
27837
+ exports["ɵa"] = CustomReuseStrategy;
27838
+ exports["ɵb"] = MatNumpadDomService;
27839
+ exports["ɵc"] = isFocusableElement;
27840
+ exports["ɵd"] = RegisterForm;
27841
+ exports["ɵe"] = AccountValidatorService;
27842
+ exports["ɵf"] = RegisterModal;
27843
+ exports["ɵg"] = UserSettingsValidatorService;
27844
+ exports["ɵh"] = LocalSettingsValidatorService;
27733
27845
 
27734
27846
  Object.defineProperty(exports, '__esModule', { value: true });
27735
27847
 
27736
- })));
27737
- //# sourceMappingURL=ngx-sumaris-components.umd.js.map
27848
+ }));
27849
+ //# sourceMappingURL=sumaris-net.ngx-components.umd.js.map