@sumaris-net/ngx-components 0.24.3 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/sumaris-net.ngx-components.umd.js +860 -835
- package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
- package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
- package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
- package/doc/changelog.md +4 -0
- package/esm2015/public_api.js +2 -1
- package/esm2015/src/app/admin/users/list/users.js +6 -4
- package/esm2015/src/app/core/graphql/graphql.service.js +18 -65
- package/esm2015/src/app/core/install/install-upgrade-card.component.js +14 -8
- package/esm2015/src/app/core/services/account.service.js +146 -149
- package/esm2015/src/app/core/services/config.service.js +21 -14
- package/esm2015/src/app/core/services/local-settings.service.js +72 -87
- package/esm2015/src/app/core/services/network.service.js +133 -168
- package/esm2015/src/app/core/services/platform.service.js +26 -14
- package/esm2015/src/app/core/services/storage/entities-storage.service.js +59 -63
- package/esm2015/src/app/shared/audio/audio.js +10 -39
- package/esm2015/src/app/shared/material/autocomplete/testing/autocomplete.test.js +2 -2
- package/esm2015/src/app/shared/services/startable-service.class.js +74 -0
- package/esm2015/src/environments/environment.class.js +1 -1
- package/esm2015/src/environments/environment.js +5 -1
- package/fesm2015/sumaris-net.ngx-components.js +578 -614
- package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +1 -0
- package/src/app/admin/users/list/users.d.ts +1 -0
- package/src/app/core/graphql/graphql.service.d.ts +5 -13
- package/src/app/core/services/account.service.d.ts +11 -10
- package/src/app/core/services/config.service.d.ts +6 -5
- package/src/app/core/services/local-settings.service.d.ts +4 -9
- package/src/app/core/services/network.service.d.ts +27 -38
- package/src/app/core/services/platform.service.d.ts +1 -1
- package/src/app/core/services/storage/entities-storage.service.d.ts +13 -13
- package/src/app/shared/audio/audio.d.ts +4 -8
- package/src/app/shared/services/startable-service.class.d.ts +25 -0
- package/src/environments/environment.class.d.ts +1 -0
- package/sumaris-net.ngx-components.metadata.json +1 -1
|
@@ -7732,39 +7732,127 @@
|
|
|
7732
7732
|
matInput: [{ type: i0.ViewChild, args: ['matInput',] }]
|
|
7733
7733
|
};
|
|
7734
7734
|
|
|
7735
|
-
var
|
|
7736
|
-
|
|
7737
|
-
{ id: 'beep-error', assetPath: 'assets/audio/beep-error.mp3', vibration: 1000 },
|
|
7738
|
-
{ id: 'startup', assetPath: 'assets/audio/unfa-ping.mp3', vibration: [1, 500, 250, 750] },
|
|
7739
|
-
];
|
|
7740
|
-
var AudioProvider = /** @class */ (function () {
|
|
7741
|
-
function AudioProvider(platform, nativeAudio, vibration, audioManagement) {
|
|
7742
|
-
this.platform = platform;
|
|
7743
|
-
this.nativeAudio = nativeAudio;
|
|
7744
|
-
this.vibration = vibration;
|
|
7745
|
-
this.audioManagement = audioManagement;
|
|
7746
|
-
this._started = false;
|
|
7747
|
-
this._audioMode = ngx$1.AudioManagement.AudioMode.NORMAL;
|
|
7748
|
-
this._preloadedSounds = {};
|
|
7749
|
-
this._htmlAudioCache = {};
|
|
7735
|
+
var StartableService = /** @class */ (function () {
|
|
7736
|
+
function StartableService(platform) {
|
|
7750
7737
|
this.onStart = new rxjs.Subject();
|
|
7751
|
-
this.
|
|
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(); };
|
|
7752
7744
|
}
|
|
7753
|
-
|
|
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 () {
|
|
7754
7769
|
return __awaiter(this, void 0, void 0, function () {
|
|
7770
|
+
var err_1;
|
|
7755
7771
|
return __generator(this, function (_a) {
|
|
7756
7772
|
switch (_a.label) {
|
|
7757
7773
|
case 0:
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
return [4 /*yield*/, this.start()];
|
|
7774
|
+
_a.trys.push([0, 2, , 3]);
|
|
7775
|
+
return [4 /*yield*/, this.ngOnStop()];
|
|
7761
7776
|
case 1:
|
|
7762
7777
|
_a.sent();
|
|
7763
|
-
|
|
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
|
|
7764
7808
|
}
|
|
7765
7809
|
});
|
|
7766
7810
|
});
|
|
7767
7811
|
};
|
|
7812
|
+
Object.defineProperty(StartableService.prototype, "started", {
|
|
7813
|
+
get: function () {
|
|
7814
|
+
return this._started;
|
|
7815
|
+
},
|
|
7816
|
+
enumerable: false,
|
|
7817
|
+
configurable: true
|
|
7818
|
+
});
|
|
7819
|
+
StartableService.prototype.ready = function () {
|
|
7820
|
+
if (this._started)
|
|
7821
|
+
return Promise.resolve(this._data);
|
|
7822
|
+
return this.start();
|
|
7823
|
+
};
|
|
7824
|
+
StartableService.prototype.ngOnStop = function () {
|
|
7825
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
7826
|
+
return __generator(this, function (_a) {
|
|
7827
|
+
return [2 /*return*/];
|
|
7828
|
+
});
|
|
7829
|
+
});
|
|
7830
|
+
};
|
|
7831
|
+
return StartableService;
|
|
7832
|
+
}());
|
|
7833
|
+
StartableService.ctorParameters = function () { return [
|
|
7834
|
+
{ type: undefined, decorators: [{ type: i0.Optional }] }
|
|
7835
|
+
]; };
|
|
7836
|
+
|
|
7837
|
+
var SYSTEM_SOUNDS = [
|
|
7838
|
+
{ id: 'beep-confirm', assetPath: 'assets/audio/beep-confirm.mp3', vibration: 250 },
|
|
7839
|
+
{ id: 'beep-error', assetPath: 'assets/audio/beep-error.mp3', vibration: 1000 },
|
|
7840
|
+
{ id: 'startup', assetPath: 'assets/audio/unfa-ping.mp3', vibration: [1, 500, 250, 750] },
|
|
7841
|
+
];
|
|
7842
|
+
var AudioProvider = /** @class */ (function (_super) {
|
|
7843
|
+
__extends(AudioProvider, _super);
|
|
7844
|
+
function AudioProvider(platform, nativeAudio, vibration, audioManagement) {
|
|
7845
|
+
var _this = _super.call(this, platform) || this;
|
|
7846
|
+
_this.platform = platform;
|
|
7847
|
+
_this.nativeAudio = nativeAudio;
|
|
7848
|
+
_this.vibration = vibration;
|
|
7849
|
+
_this.audioManagement = audioManagement;
|
|
7850
|
+
_this._audioMode = ngx$1.AudioManagement.AudioMode.NORMAL;
|
|
7851
|
+
_this._preloadedSounds = {};
|
|
7852
|
+
_this._htmlAudioCache = {};
|
|
7853
|
+
_this.start();
|
|
7854
|
+
return _this;
|
|
7855
|
+
}
|
|
7768
7856
|
AudioProvider.prototype.playBeepConfirm = function () {
|
|
7769
7857
|
return this.play('beep-confirm', {
|
|
7770
7858
|
// Vibrate only if in vibration mode
|
|
@@ -7828,7 +7916,7 @@
|
|
|
7828
7916
|
return __generator(this, function (_a) {
|
|
7829
7917
|
switch (_a.label) {
|
|
7830
7918
|
case 0:
|
|
7831
|
-
if (!!this.
|
|
7919
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
7832
7920
|
return [4 /*yield*/, this.ready()];
|
|
7833
7921
|
case 1:
|
|
7834
7922
|
_a.sent();
|
|
@@ -7912,7 +8000,7 @@
|
|
|
7912
8000
|
return __generator(this, function (_a) {
|
|
7913
8001
|
switch (_a.label) {
|
|
7914
8002
|
case 0:
|
|
7915
|
-
if (!!this.
|
|
8003
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
7916
8004
|
return [4 /*yield*/, this.ready()];
|
|
7917
8005
|
case 1:
|
|
7918
8006
|
_a.sent();
|
|
@@ -7927,15 +8015,10 @@
|
|
|
7927
8015
|
});
|
|
7928
8016
|
};
|
|
7929
8017
|
/* -- protected methods -- */
|
|
7930
|
-
AudioProvider.prototype.
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
if (this._started)
|
|
7935
|
-
return Promise.resolve();
|
|
7936
|
-
var cordova;
|
|
7937
|
-
this._startPromise = this.platform.ready()
|
|
7938
|
-
.then(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
8018
|
+
AudioProvider.prototype.ngOnStart = function () {
|
|
8019
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
8020
|
+
var cordova;
|
|
8021
|
+
var _this = this;
|
|
7939
8022
|
return __generator(this, function (_a) {
|
|
7940
8023
|
switch (_a.label) {
|
|
7941
8024
|
case 0:
|
|
@@ -7947,33 +8030,21 @@
|
|
|
7947
8030
|
case 1:
|
|
7948
8031
|
_a.sent();
|
|
7949
8032
|
_a.label = 2;
|
|
7950
|
-
case 2:
|
|
8033
|
+
case 2:
|
|
8034
|
+
// Pre-loading system sounds
|
|
8035
|
+
console.debug('[audio] Preloading audio sounds...');
|
|
8036
|
+
return [4 /*yield*/, Promise.all(SYSTEM_SOUNDS.map(function (s) {
|
|
8037
|
+
// Disable vibration is cordova not enabled
|
|
8038
|
+
if (!cordova)
|
|
8039
|
+
s.vibration = undefined;
|
|
8040
|
+
return _this.preload(s);
|
|
8041
|
+
}))];
|
|
8042
|
+
case 3:
|
|
8043
|
+
_a.sent();
|
|
8044
|
+
return [2 /*return*/];
|
|
7951
8045
|
}
|
|
7952
8046
|
});
|
|
7953
|
-
}); })
|
|
7954
|
-
// Pre-loading system sounds
|
|
7955
|
-
.then(function () {
|
|
7956
|
-
console.debug('[audio] Preloading audio sounds...');
|
|
7957
|
-
return Promise.all(SYSTEM_SOUNDS.map(function (s) {
|
|
7958
|
-
// Disable vibration is cordova not enabled
|
|
7959
|
-
if (!cordova)
|
|
7960
|
-
s.vibration = undefined;
|
|
7961
|
-
return _this.preload(s);
|
|
7962
|
-
}));
|
|
7963
|
-
})
|
|
7964
|
-
.then(function () {
|
|
7965
|
-
_this._started = true;
|
|
7966
|
-
_this._startPromise = null;
|
|
7967
|
-
console.info('[audio] Audio provider started');
|
|
7968
|
-
// Emit event
|
|
7969
|
-
_this.onStart.next();
|
|
7970
|
-
})
|
|
7971
|
-
.catch(function (err) {
|
|
7972
|
-
console.error('[audio] Unable to start audio provider: ' + (err && err.message || err), err);
|
|
7973
|
-
_this._started = false;
|
|
7974
|
-
_this._startPromise = null;
|
|
7975
8047
|
});
|
|
7976
|
-
return this._startPromise;
|
|
7977
8048
|
};
|
|
7978
8049
|
AudioProvider.prototype.readAudioMode = function () {
|
|
7979
8050
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -7991,7 +8062,7 @@
|
|
|
7991
8062
|
});
|
|
7992
8063
|
};
|
|
7993
8064
|
return AudioProvider;
|
|
7994
|
-
}());
|
|
8065
|
+
}(StartableService));
|
|
7995
8066
|
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" });
|
|
7996
8067
|
AudioProvider.decorators = [
|
|
7997
8068
|
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
|
|
@@ -8977,6 +9048,10 @@
|
|
|
8977
9048
|
{
|
|
8978
9049
|
host: 'sih.sfa.sc',
|
|
8979
9050
|
port: 80
|
|
9051
|
+
},
|
|
9052
|
+
{
|
|
9053
|
+
host: 'test.sumaris.net',
|
|
9054
|
+
port: 443
|
|
8980
9055
|
}
|
|
8981
9056
|
],
|
|
8982
9057
|
defaultAppName: 'SUMARiS',
|
|
@@ -9589,110 +9664,87 @@
|
|
|
9589
9664
|
};
|
|
9590
9665
|
var APP_LOCAL_SETTINGS = new i0.InjectionToken('DefaultLocalSettings');
|
|
9591
9666
|
var APP_LOCAL_SETTINGS_OPTIONS = new i0.InjectionToken('LocalSettingsOptions');
|
|
9592
|
-
var LocalSettingsService = /** @class */ (function () {
|
|
9667
|
+
var LocalSettingsService = /** @class */ (function (_super) {
|
|
9668
|
+
__extends(LocalSettingsService, _super);
|
|
9593
9669
|
function LocalSettingsService(translate, platform, storage, environment, defaultSettings, defaultOptionsMap) {
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
if (
|
|
9670
|
+
var _this = _super.call(this, platform) || this;
|
|
9671
|
+
_this.translate = translate;
|
|
9672
|
+
_this.platform = platform;
|
|
9673
|
+
_this.storage = storage;
|
|
9674
|
+
_this.environment = environment;
|
|
9675
|
+
_this.defaultSettings = defaultSettings;
|
|
9676
|
+
_this.onChange = new rxjs.Subject();
|
|
9677
|
+
_this.defaultSettings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), _this.defaultSettings);
|
|
9678
|
+
_this._optionDefs = Object.values(defaultOptionsMap);
|
|
9679
|
+
_this.resetData();
|
|
9680
|
+
_this._debug = !environment.production;
|
|
9681
|
+
if (_this._debug)
|
|
9606
9682
|
console.debug('[settings] Creating service');
|
|
9683
|
+
return _this;
|
|
9607
9684
|
}
|
|
9608
9685
|
Object.defineProperty(LocalSettingsService.prototype, "settings", {
|
|
9609
9686
|
get: function () {
|
|
9610
|
-
return this.
|
|
9687
|
+
return this._data || this.defaultSettings;
|
|
9611
9688
|
},
|
|
9612
9689
|
enumerable: false,
|
|
9613
9690
|
configurable: true
|
|
9614
9691
|
});
|
|
9615
9692
|
Object.defineProperty(LocalSettingsService.prototype, "locale", {
|
|
9616
9693
|
get: function () {
|
|
9617
|
-
return this.
|
|
9694
|
+
return this._data && this._data.locale || this.translate.currentLang || this.translate.defaultLang;
|
|
9618
9695
|
},
|
|
9619
9696
|
enumerable: false,
|
|
9620
9697
|
configurable: true
|
|
9621
9698
|
});
|
|
9622
9699
|
Object.defineProperty(LocalSettingsService.prototype, "latLongFormat", {
|
|
9623
9700
|
get: function () {
|
|
9624
|
-
return this.
|
|
9701
|
+
return this._data && this._data.latLongFormat || 'DDMM';
|
|
9625
9702
|
},
|
|
9626
9703
|
enumerable: false,
|
|
9627
9704
|
configurable: true
|
|
9628
9705
|
});
|
|
9629
9706
|
Object.defineProperty(LocalSettingsService.prototype, "usageMode", {
|
|
9630
9707
|
get: function () {
|
|
9631
|
-
return (this.
|
|
9708
|
+
return (this._data && this._data.usageMode || (this.mobile ? 'FIELD' : 'DESK'));
|
|
9632
9709
|
},
|
|
9633
9710
|
enumerable: false,
|
|
9634
9711
|
configurable: true
|
|
9635
9712
|
});
|
|
9636
9713
|
Object.defineProperty(LocalSettingsService.prototype, "mobile", {
|
|
9637
9714
|
get: function () {
|
|
9638
|
-
return this.
|
|
9715
|
+
return this._data && toBoolean(this._data.mobile, this.platform.is('mobile'));
|
|
9639
9716
|
},
|
|
9640
9717
|
set: function (value) {
|
|
9641
|
-
this.
|
|
9718
|
+
this._data.mobile = value;
|
|
9642
9719
|
},
|
|
9643
9720
|
enumerable: false,
|
|
9644
9721
|
configurable: true
|
|
9645
9722
|
});
|
|
9646
9723
|
Object.defineProperty(LocalSettingsService.prototype, "touchUi", {
|
|
9647
9724
|
get: function () {
|
|
9648
|
-
return this.
|
|
9725
|
+
return this._data.touchUi;
|
|
9649
9726
|
},
|
|
9650
9727
|
set: function (value) {
|
|
9651
|
-
this.
|
|
9728
|
+
this._data.touchUi = value;
|
|
9652
9729
|
},
|
|
9653
9730
|
enumerable: false,
|
|
9654
9731
|
configurable: true
|
|
9655
9732
|
});
|
|
9656
9733
|
Object.defineProperty(LocalSettingsService.prototype, "pageHistory", {
|
|
9657
9734
|
get: function () {
|
|
9658
|
-
return (this.
|
|
9735
|
+
return (this._data && this._data.pageHistory || []);
|
|
9659
9736
|
},
|
|
9660
9737
|
enumerable: false,
|
|
9661
9738
|
configurable: true
|
|
9662
9739
|
});
|
|
9663
|
-
LocalSettingsService.prototype.
|
|
9664
|
-
|
|
9665
|
-
if (this._startPromise)
|
|
9666
|
-
return this._startPromise;
|
|
9667
|
-
if (this._started)
|
|
9668
|
-
return Promise.resolve(this.data);
|
|
9669
|
-
console.info('[settings] Starting settings...');
|
|
9740
|
+
LocalSettingsService.prototype.ngOnStart = function () {
|
|
9741
|
+
console.info('[settings] Starting service...');
|
|
9670
9742
|
// Restoring local settings
|
|
9671
|
-
this.
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
})
|
|
9677
|
-
.then(function () { return _this.restoreLocally(); })
|
|
9678
|
-
.then(function (data) {
|
|
9679
|
-
_this._started = true;
|
|
9680
|
-
_this._startPromise = undefined;
|
|
9681
|
-
return data;
|
|
9682
|
-
});
|
|
9683
|
-
return this._startPromise;
|
|
9684
|
-
};
|
|
9685
|
-
Object.defineProperty(LocalSettingsService.prototype, "started", {
|
|
9686
|
-
get: function () {
|
|
9687
|
-
return this._started;
|
|
9688
|
-
},
|
|
9689
|
-
enumerable: false,
|
|
9690
|
-
configurable: true
|
|
9691
|
-
});
|
|
9692
|
-
LocalSettingsService.prototype.ready = function () {
|
|
9693
|
-
if (this._started)
|
|
9694
|
-
return Promise.resolve(this.data);
|
|
9695
|
-
return this.start();
|
|
9743
|
+
this._data.mobile = isNotNil(this._data.mobile) ? this._data.mobile : this.platform.is('mobile');
|
|
9744
|
+
this._data.touchUi = this._data.mobile || this.platform.is('phablet') || this.platform.is('tablet');
|
|
9745
|
+
this._data.usageMode = this.platform.is('android') ? 'FIELD' : 'DESK'; // FIELD by default if Android
|
|
9746
|
+
// Restoring local settings
|
|
9747
|
+
return this.restoreLocally();
|
|
9696
9748
|
};
|
|
9697
9749
|
LocalSettingsService.prototype.isUsageMode = function (mode) {
|
|
9698
9750
|
return this.usageMode === mode;
|
|
@@ -9702,10 +9754,12 @@
|
|
|
9702
9754
|
};
|
|
9703
9755
|
LocalSettingsService.prototype.restoreLocally = function () {
|
|
9704
9756
|
return __awaiter(this, void 0, void 0, function () {
|
|
9705
|
-
var settingsStr, restoredData_1;
|
|
9757
|
+
var data, settingsStr, restoredData_1;
|
|
9706
9758
|
return __generator(this, function (_a) {
|
|
9707
9759
|
switch (_a.label) {
|
|
9708
|
-
case 0:
|
|
9760
|
+
case 0:
|
|
9761
|
+
data = this._data || {};
|
|
9762
|
+
return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
|
|
9709
9763
|
case 1:
|
|
9710
9764
|
settingsStr = _a.sent();
|
|
9711
9765
|
// Restore local settings (or keep old settings)
|
|
@@ -9716,30 +9770,31 @@
|
|
|
9716
9770
|
SETTINGS_TRANSIENT_PROPERTIES.forEach(function (transientKey) {
|
|
9717
9771
|
delete restoredData_1[transientKey];
|
|
9718
9772
|
});
|
|
9719
|
-
|
|
9773
|
+
// Merge into existing data
|
|
9774
|
+
data = Object.assign(data, restoredData_1);
|
|
9720
9775
|
}
|
|
9721
9776
|
// Emit event
|
|
9722
|
-
this.onChange.next(
|
|
9723
|
-
return [2 /*return*/,
|
|
9777
|
+
this.onChange.next(data);
|
|
9778
|
+
return [2 /*return*/, data];
|
|
9724
9779
|
}
|
|
9725
9780
|
});
|
|
9726
9781
|
});
|
|
9727
9782
|
};
|
|
9728
9783
|
LocalSettingsService.prototype.setProperty = function (keyOrDef, value) {
|
|
9729
|
-
if (!this.
|
|
9784
|
+
if (!this._data)
|
|
9730
9785
|
return;
|
|
9731
9786
|
if (typeof keyOrDef === 'object') {
|
|
9732
9787
|
this.setProperty(keyOrDef.key, value);
|
|
9733
9788
|
return;
|
|
9734
9789
|
}
|
|
9735
|
-
this.
|
|
9736
|
-
this.
|
|
9790
|
+
this._data.properties = this._data.properties || {};
|
|
9791
|
+
this._data.properties[keyOrDef] = isNil(value) ? undefined : value.toString();
|
|
9737
9792
|
};
|
|
9738
9793
|
LocalSettingsService.prototype.getProperty = function (keyOrDef, defaultValue) {
|
|
9739
9794
|
if (typeof keyOrDef === 'object') {
|
|
9740
9795
|
return this.getProperty(keyOrDef.key, isNil(defaultValue) ? keyOrDef.defaultValue : defaultValue);
|
|
9741
9796
|
}
|
|
9742
|
-
var value = this.
|
|
9797
|
+
var value = this._data && this._data.properties && this._data.properties[keyOrDef];
|
|
9743
9798
|
return isNotNil(value) ? value : defaultValue;
|
|
9744
9799
|
};
|
|
9745
9800
|
LocalSettingsService.prototype.getPropertyAsBoolean = function (definition, defaultValue) {
|
|
@@ -9765,19 +9820,25 @@
|
|
|
9765
9820
|
return __generator(this, function (_a) {
|
|
9766
9821
|
switch (_a.label) {
|
|
9767
9822
|
case 0:
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
return [4 /*yield*/, this.persistLocally(true)];
|
|
9823
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
9824
|
+
return [4 /*yield*/, this.ready()];
|
|
9771
9825
|
case 1:
|
|
9772
9826
|
_a.sent();
|
|
9773
|
-
|
|
9827
|
+
_a.label = 2;
|
|
9774
9828
|
case 2:
|
|
9775
|
-
this.
|
|
9776
|
-
|
|
9829
|
+
this._data = Object.assign(Object.assign({}, this._data), settings);
|
|
9830
|
+
if (!(opts && opts.persistImmediate)) return [3 /*break*/, 4];
|
|
9831
|
+
return [4 /*yield*/, this.persistLocally(true)];
|
|
9777
9832
|
case 3:
|
|
9833
|
+
_a.sent();
|
|
9834
|
+
return [3 /*break*/, 5];
|
|
9835
|
+
case 4:
|
|
9836
|
+
this.persistLocally(); // No AWAIT
|
|
9837
|
+
_a.label = 5;
|
|
9838
|
+
case 5:
|
|
9778
9839
|
// Emit event
|
|
9779
9840
|
if (!opts || opts.emitEvent !== false) {
|
|
9780
|
-
this.onChange.next(this.
|
|
9841
|
+
this.onChange.next(this._data);
|
|
9781
9842
|
}
|
|
9782
9843
|
return [2 /*return*/];
|
|
9783
9844
|
}
|
|
@@ -9801,27 +9862,27 @@
|
|
|
9801
9862
|
});
|
|
9802
9863
|
};
|
|
9803
9864
|
LocalSettingsService.prototype.getPageSettings = function (pageId, propertyName) {
|
|
9804
|
-
if (!this.
|
|
9865
|
+
if (!this._data || !this._data.pages)
|
|
9805
9866
|
return undefined;
|
|
9806
9867
|
var key = pageId.replace(/[/]/g, '__');
|
|
9807
9868
|
if (isNotNilOrBlank(propertyName)) {
|
|
9808
|
-
return getPropertyByPath(this.
|
|
9869
|
+
return getPropertyByPath(this._data.pages, key + '.' + propertyName);
|
|
9809
9870
|
}
|
|
9810
|
-
return this.
|
|
9871
|
+
return this._data.pages[key];
|
|
9811
9872
|
};
|
|
9812
9873
|
LocalSettingsService.prototype.savePageSetting = function (pageId, value, propertyName) {
|
|
9813
9874
|
return __awaiter(this, void 0, void 0, function () {
|
|
9814
9875
|
var key;
|
|
9815
9876
|
return __generator(this, function (_a) {
|
|
9816
|
-
this.
|
|
9817
|
-
this.
|
|
9877
|
+
this._data = this._data || this.defaultSettings;
|
|
9878
|
+
this._data.pages = this._data.pages || {};
|
|
9818
9879
|
key = pageId.replace(/[/]/g, '__');
|
|
9819
9880
|
if (propertyName) {
|
|
9820
|
-
this.
|
|
9821
|
-
this.
|
|
9881
|
+
this._data.pages[key] = this._data.pages[key] || {};
|
|
9882
|
+
this._data.pages[key][propertyName] = value;
|
|
9822
9883
|
}
|
|
9823
9884
|
else {
|
|
9824
|
-
this.
|
|
9885
|
+
this._data.pages[key] = value;
|
|
9825
9886
|
}
|
|
9826
9887
|
// Update local settings
|
|
9827
9888
|
this.persistLocally();
|
|
@@ -9830,13 +9891,13 @@
|
|
|
9830
9891
|
});
|
|
9831
9892
|
};
|
|
9832
9893
|
LocalSettingsService.prototype.getOfflineFeature = function (featureName) {
|
|
9833
|
-
if (!this.
|
|
9894
|
+
if (!this._data || !this._data.offlineFeatures || isEmptyArray(this._data.offlineFeatures))
|
|
9834
9895
|
return undefined;
|
|
9835
9896
|
if (!featureName)
|
|
9836
9897
|
throw Error('Missing \'featureName\' argument');
|
|
9837
9898
|
featureName = featureName.toLowerCase();
|
|
9838
9899
|
var featurePrefix = featureName + '#';
|
|
9839
|
-
var feature = this.
|
|
9900
|
+
var feature = this._data.offlineFeatures.find(function (f) {
|
|
9840
9901
|
if (typeof f === 'string')
|
|
9841
9902
|
return f.toLowerCase().startsWith(featurePrefix);
|
|
9842
9903
|
if (typeof f === 'object' && f.name)
|
|
@@ -9859,24 +9920,24 @@
|
|
|
9859
9920
|
LocalSettingsService.prototype.hasOfflineFeature = function (featureName) {
|
|
9860
9921
|
if (featureName)
|
|
9861
9922
|
return isNotNil(this.getOfflineFeature(featureName));
|
|
9862
|
-
return this.
|
|
9923
|
+
return this._data && isNotEmptyArray(this._data.offlineFeatures);
|
|
9863
9924
|
};
|
|
9864
9925
|
LocalSettingsService.prototype.saveOfflineFeature = function (feature) {
|
|
9865
|
-
this.
|
|
9866
|
-
this.
|
|
9926
|
+
this._data = this._data || this.defaultSettings;
|
|
9927
|
+
this._data.offlineFeatures = this._data.offlineFeatures || [];
|
|
9867
9928
|
feature.name = feature.name.toLowerCase();
|
|
9868
9929
|
var featurePrefix = feature.name + '#';
|
|
9869
|
-
var existingIndex = this.
|
|
9930
|
+
var existingIndex = this._data.offlineFeatures.findIndex(function (f) {
|
|
9870
9931
|
if (typeof f === 'string')
|
|
9871
9932
|
return f.toLowerCase().startsWith(featurePrefix);
|
|
9872
9933
|
if (typeof f === 'object' && f.name)
|
|
9873
9934
|
return f.name === feature.name;
|
|
9874
9935
|
});
|
|
9875
9936
|
if (existingIndex !== -1) {
|
|
9876
|
-
this.
|
|
9937
|
+
this._data.offlineFeatures[existingIndex] = feature;
|
|
9877
9938
|
}
|
|
9878
9939
|
else {
|
|
9879
|
-
this.
|
|
9940
|
+
this._data.offlineFeatures.push(feature);
|
|
9880
9941
|
}
|
|
9881
9942
|
// Update local settings
|
|
9882
9943
|
this.persistLocally();
|
|
@@ -9895,14 +9956,14 @@
|
|
|
9895
9956
|
this.saveOfflineFeature(feature);
|
|
9896
9957
|
};
|
|
9897
9958
|
LocalSettingsService.prototype.removeOfflineFeatures = function () {
|
|
9898
|
-
if (this.
|
|
9899
|
-
this.
|
|
9959
|
+
if (this._data && this._data.offlineFeatures) {
|
|
9960
|
+
this._data.offlineFeatures = [];
|
|
9900
9961
|
// Update local settings
|
|
9901
9962
|
this.persistLocally();
|
|
9902
9963
|
}
|
|
9903
9964
|
};
|
|
9904
9965
|
LocalSettingsService.prototype.getFieldDisplayAttributes = function (fieldName, defaultAttributes) {
|
|
9905
|
-
var value = this.
|
|
9966
|
+
var value = this._data && this._data.properties && this._data.properties["sumaris.field." + fieldName + ".attributes"];
|
|
9906
9967
|
// Nothing found in settings: return defaults
|
|
9907
9968
|
if (!value)
|
|
9908
9969
|
return defaultAttributes || ['label', 'name'];
|
|
@@ -9940,7 +10001,7 @@
|
|
|
9940
10001
|
// If not inside recursive call: fill page history defaults
|
|
9941
10002
|
if (!pageHistory)
|
|
9942
10003
|
this.fillPageHistoryDefaults(page, opts);
|
|
9943
|
-
pageHistory = pageHistory || this.
|
|
10004
|
+
pageHistory = pageHistory || this._data.pageHistory;
|
|
9944
10005
|
index = pageHistory.findIndex(function (p) { return (
|
|
9945
10006
|
// same path
|
|
9946
10007
|
p.path === page.path
|
|
@@ -9975,10 +10036,10 @@
|
|
|
9975
10036
|
_a.sent();
|
|
9976
10037
|
_a.label = 4;
|
|
9977
10038
|
case 4:
|
|
9978
|
-
if (!(pageHistory === this.
|
|
10039
|
+
if (!(pageHistory === this._data.pageHistory)) return [3 /*break*/, 6];
|
|
9979
10040
|
// If max has been reached, remove old pages
|
|
9980
|
-
if (this.
|
|
9981
|
-
removedPages = pageHistory.splice(this.
|
|
10041
|
+
if (this._data.pageHistory.length > this._data.pageHistoryMaxSize) {
|
|
10042
|
+
removedPages = pageHistory.splice(this._data.pageHistoryMaxSize, pageHistory.length - this._data.pageHistoryMaxSize);
|
|
9982
10043
|
console.debug('[settings] Pages removed from history: ', removedPages);
|
|
9983
10044
|
}
|
|
9984
10045
|
// Apply new value
|
|
@@ -10000,7 +10061,7 @@
|
|
|
10000
10061
|
return __generator(this, function (_a) {
|
|
10001
10062
|
switch (_a.label) {
|
|
10002
10063
|
case 0:
|
|
10003
|
-
pageHistory = pageHistory || this.
|
|
10064
|
+
pageHistory = pageHistory || this._data.pageHistory;
|
|
10004
10065
|
index = pageHistory.findIndex(function (p) { return p.path === path; });
|
|
10005
10066
|
found = index !== -1;
|
|
10006
10067
|
if (found) {
|
|
@@ -10015,9 +10076,9 @@
|
|
|
10015
10076
|
.filter(isNotEmptyArray)
|
|
10016
10077
|
.findIndex(function (children) { return _this.removePageHistory(path, opts, children); }) !== -1;
|
|
10017
10078
|
}
|
|
10018
|
-
if (!(found && pageHistory === this.
|
|
10079
|
+
if (!(found && pageHistory === this._data.pageHistory)) return [3 /*break*/, 2];
|
|
10019
10080
|
// Apply changes
|
|
10020
|
-
return [4 /*yield*/, this.applyProperty('pageHistory', this.
|
|
10081
|
+
return [4 /*yield*/, this.applyProperty('pageHistory', this._data.pageHistory)];
|
|
10021
10082
|
case 1:
|
|
10022
10083
|
// Apply changes
|
|
10023
10084
|
_a.sent();
|
|
@@ -10044,27 +10105,27 @@
|
|
|
10044
10105
|
};
|
|
10045
10106
|
/* -- Protected methods -- */
|
|
10046
10107
|
LocalSettingsService.prototype.resetData = function () {
|
|
10047
|
-
this.
|
|
10048
|
-
this.
|
|
10049
|
-
this.
|
|
10050
|
-
this.
|
|
10051
|
-
this.
|
|
10108
|
+
this._data = Object.assign(Object.assign({}, this._data), this.defaultSettings);
|
|
10109
|
+
this._data.locale = this.translate.currentLang || this.translate.defaultLang;
|
|
10110
|
+
this._data.mobile = undefined;
|
|
10111
|
+
this._data.usageMode = undefined;
|
|
10112
|
+
this._data.pageHistory = [];
|
|
10052
10113
|
var defaultPeer = this.environment.defaultPeer && exports.Peer.fromObject(this.environment.defaultPeer);
|
|
10053
|
-
this.
|
|
10054
|
-
if (this.
|
|
10055
|
-
this.onChange.next(this.
|
|
10114
|
+
this._data.peerUrl = defaultPeer && defaultPeer.url || undefined;
|
|
10115
|
+
if (this.started)
|
|
10116
|
+
this.onChange.next(this._data);
|
|
10056
10117
|
};
|
|
10057
10118
|
LocalSettingsService.prototype.persistLocally = function (immediate) {
|
|
10058
10119
|
var _this = this;
|
|
10059
10120
|
// Execute immediate
|
|
10060
10121
|
if (immediate) {
|
|
10061
|
-
if (!this.
|
|
10122
|
+
if (!this._data) {
|
|
10062
10123
|
console.debug('[settings] Removing local settings from storage');
|
|
10063
10124
|
return this.storage.remove(SETTINGS_STORAGE_KEY);
|
|
10064
10125
|
}
|
|
10065
10126
|
else {
|
|
10066
|
-
console.debug('[settings] Store local settings', this.
|
|
10067
|
-
return this.storage.set(SETTINGS_STORAGE_KEY, JSON.stringify(this.
|
|
10127
|
+
console.debug('[settings] Store local settings', this._data);
|
|
10128
|
+
return this.storage.set(SETTINGS_STORAGE_KEY, JSON.stringify(this._data));
|
|
10068
10129
|
}
|
|
10069
10130
|
}
|
|
10070
10131
|
// Execute with delay
|
|
@@ -10074,7 +10135,7 @@
|
|
|
10074
10135
|
this._$persist = new i0.EventEmitter(true);
|
|
10075
10136
|
this._$persist
|
|
10076
10137
|
.pipe(operators.debounceTime(2000), // add a delay of 2s
|
|
10077
|
-
operators.filter(function () { return _this.
|
|
10138
|
+
operators.filter(function () { return _this.started; }))
|
|
10078
10139
|
.subscribe(function () { return _this.persistLocally(true); });
|
|
10079
10140
|
}
|
|
10080
10141
|
this._$persist.emit();
|
|
@@ -10100,7 +10161,7 @@
|
|
|
10100
10161
|
return page;
|
|
10101
10162
|
};
|
|
10102
10163
|
return LocalSettingsService;
|
|
10103
|
-
}());
|
|
10164
|
+
}(StartableService));
|
|
10104
10165
|
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" });
|
|
10105
10166
|
LocalSettingsService.decorators = [
|
|
10106
10167
|
{ type: i0.Injectable, args: [{
|
|
@@ -10271,41 +10332,42 @@
|
|
|
10271
10332
|
MOBILE: 1000,
|
|
10272
10333
|
DESKTOP: 1000
|
|
10273
10334
|
}*/
|
|
10274
|
-
var NetworkService = /** @class */ (function () {
|
|
10335
|
+
var NetworkService = /** @class */ (function (_super) {
|
|
10336
|
+
__extends(NetworkService, _super);
|
|
10275
10337
|
function NetworkService(_document, platform, modalCtrl, cryptoService, storage, settings, cache, http, environment, network, splashScreen, translate, toastController) {
|
|
10276
|
-
var _this = this;
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
this._timerRefreshPeriod = NetworkRefreshTimerPeriod.MOBILE;
|
|
10300
|
-
this._timerRefreshCondition = function () { return _this.online; }; // Check only when online, and stop when offline
|
|
10338
|
+
var _this = _super.call(this, platform) || this;
|
|
10339
|
+
_this._document = _document;
|
|
10340
|
+
_this.platform = platform;
|
|
10341
|
+
_this.modalCtrl = modalCtrl;
|
|
10342
|
+
_this.cryptoService = cryptoService;
|
|
10343
|
+
_this.storage = storage;
|
|
10344
|
+
_this.settings = settings;
|
|
10345
|
+
_this.cache = cache;
|
|
10346
|
+
_this.http = http;
|
|
10347
|
+
_this.environment = environment;
|
|
10348
|
+
_this.network = network;
|
|
10349
|
+
_this.splashScreen = splashScreen;
|
|
10350
|
+
_this.translate = translate;
|
|
10351
|
+
_this.toastController = toastController;
|
|
10352
|
+
_this.onPeerChanges = _this.onStart.pipe(operators.map(function (peer) { return peer && peer.url; }), operators.filter(isNotNilOrBlank), operators.distinctUntilChanged());
|
|
10353
|
+
_this.onNetworkStatusChanges = new rxjs.BehaviorSubject(null);
|
|
10354
|
+
_this.onResetNetworkCache = new i0.EventEmitter(true);
|
|
10355
|
+
_this._subscription = new rxjs.Subscription();
|
|
10356
|
+
_this._listeners = {};
|
|
10357
|
+
_this._mobile = _this.platform.is('mobile');
|
|
10358
|
+
if (_this._mobile) {
|
|
10359
|
+
_this._timerRefreshPeriod = NetworkRefreshTimerPeriod.MOBILE;
|
|
10360
|
+
_this._timerRefreshCondition = function () { return _this.online; }; // Check only when online, and stop when offline
|
|
10301
10361
|
}
|
|
10302
10362
|
else {
|
|
10303
|
-
|
|
10304
|
-
|
|
10363
|
+
_this._timerRefreshPeriod = NetworkRefreshTimerPeriod.DESKTOP;
|
|
10364
|
+
_this._timerRefreshCondition = function () { return true; }; // Always check
|
|
10305
10365
|
}
|
|
10306
|
-
|
|
10366
|
+
_this.resetData();
|
|
10367
|
+
_this.onStart.subscribe(function () { return _this.ngOnAfterStart(); });
|
|
10307
10368
|
// For DEV only
|
|
10308
|
-
|
|
10369
|
+
_this._debug = !environment.production;
|
|
10370
|
+
return _this;
|
|
10309
10371
|
}
|
|
10310
10372
|
Object.defineProperty(NetworkService.prototype, "online", {
|
|
10311
10373
|
get: function () {
|
|
@@ -10326,24 +10388,18 @@
|
|
|
10326
10388
|
// If force offline: return 'none'
|
|
10327
10389
|
return this._forceOffline && 'none'
|
|
10328
10390
|
// Else, return device connection type (or unknown)
|
|
10329
|
-
|| (this.
|
|
10391
|
+
|| (this.started && this._deviceConnectionType || 'unknown');
|
|
10330
10392
|
},
|
|
10331
10393
|
enumerable: false,
|
|
10332
10394
|
configurable: true
|
|
10333
10395
|
});
|
|
10334
10396
|
Object.defineProperty(NetworkService.prototype, "peer", {
|
|
10335
10397
|
get: function () {
|
|
10336
|
-
return this.
|
|
10398
|
+
return this._data && this._data.clone();
|
|
10337
10399
|
},
|
|
10338
10400
|
set: function (peer) {
|
|
10339
|
-
this.
|
|
10340
|
-
|
|
10341
|
-
enumerable: false,
|
|
10342
|
-
configurable: true
|
|
10343
|
-
});
|
|
10344
|
-
Object.defineProperty(NetworkService.prototype, "started", {
|
|
10345
|
-
get: function () {
|
|
10346
|
-
return this._started;
|
|
10401
|
+
this._startingPeer = peer;
|
|
10402
|
+
this.restart();
|
|
10347
10403
|
},
|
|
10348
10404
|
enumerable: false,
|
|
10349
10405
|
configurable: true
|
|
@@ -10368,109 +10424,11 @@
|
|
|
10368
10424
|
return this.addListener(eventType, callback);
|
|
10369
10425
|
}
|
|
10370
10426
|
};
|
|
10371
|
-
NetworkService.prototype.start = function (peer) {
|
|
10372
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
10373
|
-
var _this = this;
|
|
10374
|
-
return __generator(this, function (_a) {
|
|
10375
|
-
if (this._startPromise)
|
|
10376
|
-
return [2 /*return*/, this._startPromise];
|
|
10377
|
-
if (this._started)
|
|
10378
|
-
return [2 /*return*/];
|
|
10379
|
-
console.info('[network] Starting network...');
|
|
10380
|
-
// Restoring local settings
|
|
10381
|
-
this._startPromise = (!peer && this.restoreLocally() || Promise.resolve(peer))
|
|
10382
|
-
.then(function (peer) { return __awaiter(_this, void 0, void 0, function () {
|
|
10383
|
-
return __generator(this, function (_a) {
|
|
10384
|
-
switch (_a.label) {
|
|
10385
|
-
case 0:
|
|
10386
|
-
// Make sure to hide the splashscreen, before open the modal
|
|
10387
|
-
if (!peer && this.splashScreen)
|
|
10388
|
-
this.splashScreen.hide();
|
|
10389
|
-
_a.label = 1;
|
|
10390
|
-
case 1:
|
|
10391
|
-
if (!!peer) return [3 /*break*/, 3];
|
|
10392
|
-
console.debug('[network] No peer defined. Asking user to choose a peer.');
|
|
10393
|
-
return [4 /*yield*/, this.showSelectPeerModal({ allowSelectDownPeer: false })];
|
|
10394
|
-
case 2:
|
|
10395
|
-
peer = _a.sent();
|
|
10396
|
-
return [3 /*break*/, 1];
|
|
10397
|
-
case 3:
|
|
10398
|
-
this._peer = peer;
|
|
10399
|
-
this._started = true;
|
|
10400
|
-
this._startPromise = undefined;
|
|
10401
|
-
this.onStart.next(peer);
|
|
10402
|
-
console.info("[platform] Starting network [OK] {online: " + this.online + "}");
|
|
10403
|
-
return [2 /*return*/];
|
|
10404
|
-
}
|
|
10405
|
-
});
|
|
10406
|
-
}); })
|
|
10407
|
-
.catch(function (err) {
|
|
10408
|
-
console.error(err && err.message || err, err);
|
|
10409
|
-
_this._started = false;
|
|
10410
|
-
_this._startPromise = undefined;
|
|
10411
|
-
})
|
|
10412
|
-
// Wait settings starts, then save peer in settings
|
|
10413
|
-
.then(function () { return _this.settings.ready(); })
|
|
10414
|
-
.then(function () { return _this.settings.apply({ peerUrl: _this._peer.url }); })
|
|
10415
|
-
.then(function () { return _this.onDeviceConnectionChanged(_this.network && _this.network.type || 'unknown'); })
|
|
10416
|
-
// Start the refresh timer
|
|
10417
|
-
.then(function () { return _this.startRefreshTimer(); });
|
|
10418
|
-
// Listen for device network changes
|
|
10419
|
-
if (this.network) {
|
|
10420
|
-
this._subscription.add(this.network.onDisconnect().subscribe(function () { return _this.onDeviceConnectionChanged('none'); }));
|
|
10421
|
-
this._subscription.add(this.network.onConnect().subscribe(function () { return _this.onDeviceConnectionChanged(_this.network.type); }));
|
|
10422
|
-
}
|
|
10423
|
-
return [2 /*return*/, this._startPromise];
|
|
10424
|
-
});
|
|
10425
|
-
});
|
|
10426
|
-
};
|
|
10427
|
-
NetworkService.prototype.ready = function () {
|
|
10428
|
-
if (this._started)
|
|
10429
|
-
return Promise.resolve();
|
|
10430
|
-
return this.start();
|
|
10431
|
-
};
|
|
10432
|
-
NetworkService.prototype.stop = function () {
|
|
10433
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
10434
|
-
return __generator(this, function (_a) {
|
|
10435
|
-
this.resetData();
|
|
10436
|
-
this._started = false;
|
|
10437
|
-
this._startPromise = undefined;
|
|
10438
|
-
// Stop timer if cannot refresh anymore
|
|
10439
|
-
if (this._timerRefreshCondition() === false) {
|
|
10440
|
-
this.stopRefreshTimer();
|
|
10441
|
-
}
|
|
10442
|
-
this._subscription.unsubscribe();
|
|
10443
|
-
this._subscription = new rxjs.Subscription();
|
|
10444
|
-
return [2 /*return*/];
|
|
10445
|
-
});
|
|
10446
|
-
});
|
|
10447
|
-
};
|
|
10448
|
-
NetworkService.prototype.restart = function (peer) {
|
|
10449
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
10450
|
-
var _this = this;
|
|
10451
|
-
return __generator(this, function (_a) {
|
|
10452
|
-
switch (_a.label) {
|
|
10453
|
-
case 0:
|
|
10454
|
-
if (!this._started) return [3 /*break*/, 2];
|
|
10455
|
-
return [4 /*yield*/, this.stop()
|
|
10456
|
-
.then(function () { return _this.start(peer); })];
|
|
10457
|
-
case 1:
|
|
10458
|
-
_a.sent();
|
|
10459
|
-
return [3 /*break*/, 4];
|
|
10460
|
-
case 2: return [4 /*yield*/, this.start(peer)];
|
|
10461
|
-
case 3:
|
|
10462
|
-
_a.sent();
|
|
10463
|
-
_a.label = 4;
|
|
10464
|
-
case 4: return [2 /*return*/];
|
|
10465
|
-
}
|
|
10466
|
-
});
|
|
10467
|
-
});
|
|
10468
|
-
};
|
|
10469
10427
|
NetworkService.prototype.tryOnline = function (opts) {
|
|
10470
10428
|
return __awaiter(this, void 0, void 0, function () {
|
|
10471
|
-
var now, showLoadingToast, loadingToast, settings, peer, peerInfo, peerAliveAndCompatible,
|
|
10472
|
-
return __generator(this, function (
|
|
10473
|
-
switch (
|
|
10429
|
+
var now, showLoadingToast, loadingToast, settings, peer, peerInfo, peerAliveAndCompatible, _b, err_1, online;
|
|
10430
|
+
return __generator(this, function (_c) {
|
|
10431
|
+
switch (_c.label) {
|
|
10474
10432
|
case 0:
|
|
10475
10433
|
// If offline mode not forced, and device says there is no connection: skip
|
|
10476
10434
|
if (!this._forceOffline || this._deviceConnectionType === 'none')
|
|
@@ -10481,57 +10439,57 @@
|
|
|
10481
10439
|
return [4 /*yield*/, this.showToast({ message: 'NETWORK.INFO.RETRY_TO_CONNECT',
|
|
10482
10440
|
duration: 10000, onWillPresent: function (t) { return loadingToast = t; } })];
|
|
10483
10441
|
case 1:
|
|
10484
|
-
|
|
10485
|
-
|
|
10442
|
+
_c.sent();
|
|
10443
|
+
_c.label = 2;
|
|
10486
10444
|
case 2:
|
|
10487
|
-
|
|
10445
|
+
_c.trys.push([2, 10, , 11]);
|
|
10488
10446
|
console.info('[network] Checking connection to pod...');
|
|
10489
10447
|
return [4 /*yield*/, this.settings.ready()];
|
|
10490
10448
|
case 3:
|
|
10491
|
-
settings =
|
|
10449
|
+
settings = _c.sent();
|
|
10492
10450
|
if (!settings.peerUrl)
|
|
10493
10451
|
return [2 /*return*/, false]; // No peer define. Skip
|
|
10494
10452
|
peer = exports.Peer.parseUrl(settings.peerUrl);
|
|
10495
10453
|
return [4 /*yield*/, this.checkPeerAlive(peer)];
|
|
10496
10454
|
case 4:
|
|
10497
|
-
peerInfo =
|
|
10498
|
-
|
|
10499
|
-
if (!
|
|
10455
|
+
peerInfo = _c.sent();
|
|
10456
|
+
_b = peerInfo;
|
|
10457
|
+
if (!_b) return [3 /*break*/, 6];
|
|
10500
10458
|
return [4 /*yield*/, this.checkPeerCompatible(peerInfo)];
|
|
10501
10459
|
case 5:
|
|
10502
|
-
|
|
10503
|
-
|
|
10460
|
+
_b = (_c.sent());
|
|
10461
|
+
_c.label = 6;
|
|
10504
10462
|
case 6:
|
|
10505
|
-
peerAliveAndCompatible =
|
|
10463
|
+
peerAliveAndCompatible = _b;
|
|
10506
10464
|
if (!peerAliveAndCompatible) return [3 /*break*/, 9];
|
|
10507
10465
|
// Disable the offline mode
|
|
10508
10466
|
this.setForceOffline(false);
|
|
10509
10467
|
// Restart
|
|
10510
|
-
|
|
10468
|
+
this._startingPeer = peer;
|
|
10469
|
+
return [4 /*yield*/, this.restart()];
|
|
10511
10470
|
case 7:
|
|
10512
|
-
|
|
10513
|
-
_b.sent();
|
|
10471
|
+
_c.sent();
|
|
10514
10472
|
// Wait a promise, before recheck
|
|
10515
10473
|
return [4 /*yield*/, this.emit('beforeTryOnlineFinish', this.online)];
|
|
10516
10474
|
case 8:
|
|
10517
10475
|
// Wait a promise, before recheck
|
|
10518
|
-
|
|
10519
|
-
|
|
10476
|
+
_c.sent();
|
|
10477
|
+
_c.label = 9;
|
|
10520
10478
|
case 9: return [3 /*break*/, 11];
|
|
10521
10479
|
case 10:
|
|
10522
|
-
err_1 =
|
|
10480
|
+
err_1 = _c.sent();
|
|
10523
10481
|
console.error(err_1 && err_1.message || err_1);
|
|
10524
10482
|
return [3 /*break*/, 11];
|
|
10525
10483
|
case 11:
|
|
10526
10484
|
if (!showLoadingToast) return [3 /*break*/, 14];
|
|
10527
10485
|
return [4 /*yield*/, sleep(2000 - (Date.now() - now))];
|
|
10528
10486
|
case 12:
|
|
10529
|
-
|
|
10487
|
+
_c.sent();
|
|
10530
10488
|
if (!loadingToast) return [3 /*break*/, 14];
|
|
10531
10489
|
return [4 /*yield*/, loadingToast.dismiss()];
|
|
10532
10490
|
case 13:
|
|
10533
|
-
|
|
10534
|
-
|
|
10491
|
+
_c.sent();
|
|
10492
|
+
_c.label = 14;
|
|
10535
10493
|
case 14:
|
|
10536
10494
|
online = this.online;
|
|
10537
10495
|
// Display a toast to user
|
|
@@ -10545,7 +10503,7 @@
|
|
|
10545
10503
|
// Display toast (without await, because not need to wait toast close event)
|
|
10546
10504
|
return [2 /*return*/, this.showOfflineToast({ showRetryButton: false })];
|
|
10547
10505
|
}
|
|
10548
|
-
return [2 /*return*/, this.
|
|
10506
|
+
return [2 /*return*/, this.started && online];
|
|
10549
10507
|
}
|
|
10550
10508
|
});
|
|
10551
10509
|
});
|
|
@@ -10553,8 +10511,8 @@
|
|
|
10553
10511
|
NetworkService.prototype.showOfflineToast = function (opts) {
|
|
10554
10512
|
return __awaiter(this, void 0, void 0, function () {
|
|
10555
10513
|
var toastResult, online;
|
|
10556
|
-
return __generator(this, function (
|
|
10557
|
-
switch (
|
|
10514
|
+
return __generator(this, function (_b) {
|
|
10515
|
+
switch (_b.label) {
|
|
10558
10516
|
case 0:
|
|
10559
10517
|
if (this.online)
|
|
10560
10518
|
return [2 /*return*/]; // Skip if online
|
|
@@ -10573,7 +10531,7 @@
|
|
|
10573
10531
|
]
|
|
10574
10532
|
})];
|
|
10575
10533
|
case 1:
|
|
10576
|
-
toastResult =
|
|
10534
|
+
toastResult = _b.sent();
|
|
10577
10535
|
// User don't click reconnect: return
|
|
10578
10536
|
if (!toastResult || toastResult.role !== 'refresh')
|
|
10579
10537
|
return [2 /*return*/, false];
|
|
@@ -10586,7 +10544,7 @@
|
|
|
10586
10544
|
showLoadingToast: toBoolean(opts && opts.showRetryLoadingToast, true)
|
|
10587
10545
|
})];
|
|
10588
10546
|
case 2:
|
|
10589
|
-
online =
|
|
10547
|
+
online = _b.sent();
|
|
10590
10548
|
if (online) {
|
|
10591
10549
|
// Call success callback (async)
|
|
10592
10550
|
if (opts && opts.onRetrySuccess) {
|
|
@@ -10595,7 +10553,7 @@
|
|
|
10595
10553
|
return [2 /*return*/, true];
|
|
10596
10554
|
}
|
|
10597
10555
|
opts = Object.assign(Object.assign({}, opts), { showRetryButton: false, showCloseButton: true });
|
|
10598
|
-
|
|
10556
|
+
_b.label = 3;
|
|
10599
10557
|
case 3:
|
|
10600
10558
|
// Simple toast, without 'await', because not need to wait toast's dismiss
|
|
10601
10559
|
this.showToast(Object.assign({ message: 'ERROR.NETWORK_REQUIRED', type: 'error' }, opts));
|
|
@@ -10604,97 +10562,6 @@
|
|
|
10604
10562
|
});
|
|
10605
10563
|
});
|
|
10606
10564
|
};
|
|
10607
|
-
/**
|
|
10608
|
-
* Try to restore peer from the local storage
|
|
10609
|
-
*/
|
|
10610
|
-
NetworkService.prototype.restoreLocally = function () {
|
|
10611
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
10612
|
-
var settingsStr, settings, location, hostname, detectedPeer;
|
|
10613
|
-
return __generator(this, function (_a) {
|
|
10614
|
-
switch (_a.label) {
|
|
10615
|
-
case 0: return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
|
|
10616
|
-
case 1:
|
|
10617
|
-
settingsStr = _a.sent();
|
|
10618
|
-
settings = settingsStr && JSON.parse(settingsStr) || undefined;
|
|
10619
|
-
if (settings && settings.peerUrl) {
|
|
10620
|
-
console.debug("[network] Use peer {" + settings.peerUrl + "} (found in the local storage)");
|
|
10621
|
-
return [2 /*return*/, exports.Peer.parseUrl(settings.peerUrl)];
|
|
10622
|
-
}
|
|
10623
|
-
// Else, use default peer in env, if exists
|
|
10624
|
-
if (this.environment.defaultPeer) {
|
|
10625
|
-
return [2 /*return*/, exports.Peer.fromObject(this.environment.defaultPeer)];
|
|
10626
|
-
}
|
|
10627
|
-
location = this._document && this._document.location;
|
|
10628
|
-
if (!(location && location.protocol && location.protocol.startsWith('http'))) return [3 /*break*/, 3];
|
|
10629
|
-
hostname = this._document.location.host;
|
|
10630
|
-
detectedPeer = exports.Peer.parseUrl("" + this._document.location.protocol + hostname + this.environment.baseUrl);
|
|
10631
|
-
return [4 /*yield*/, this.checkPeerAlive(detectedPeer)];
|
|
10632
|
-
case 2:
|
|
10633
|
-
if (_a.sent()) {
|
|
10634
|
-
return [2 /*return*/, detectedPeer];
|
|
10635
|
-
}
|
|
10636
|
-
_a.label = 3;
|
|
10637
|
-
case 3: return [2 /*return*/, undefined];
|
|
10638
|
-
}
|
|
10639
|
-
});
|
|
10640
|
-
});
|
|
10641
|
-
};
|
|
10642
|
-
/**
|
|
10643
|
-
* Refresh network state, using a ping to pod
|
|
10644
|
-
*/
|
|
10645
|
-
NetworkService.prototype.refreshPeerState = function (opts) {
|
|
10646
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
10647
|
-
return __generator(this, function (_a) {
|
|
10648
|
-
return [2 /*return*/];
|
|
10649
|
-
});
|
|
10650
|
-
});
|
|
10651
|
-
};
|
|
10652
|
-
/**
|
|
10653
|
-
* Stop to network state
|
|
10654
|
-
*
|
|
10655
|
-
* @protected
|
|
10656
|
-
*/
|
|
10657
|
-
NetworkService.prototype.stopRefreshTimer = function () {
|
|
10658
|
-
if (this._timerSubscription) {
|
|
10659
|
-
this._timerSubscription.unsubscribe();
|
|
10660
|
-
this._timerSubscription = undefined;
|
|
10661
|
-
}
|
|
10662
|
-
};
|
|
10663
|
-
/**
|
|
10664
|
-
* Refresh the network state
|
|
10665
|
-
*
|
|
10666
|
-
* @protected
|
|
10667
|
-
*/
|
|
10668
|
-
NetworkService.prototype.startRefreshTimer = function () {
|
|
10669
|
-
var _this = this;
|
|
10670
|
-
if (this._timerSubscription)
|
|
10671
|
-
return; // Already running: skip
|
|
10672
|
-
console.info("[network] Starting refresh timer, every " + this._timerRefreshPeriod + "ms...");
|
|
10673
|
-
var lastInfo;
|
|
10674
|
-
this._timerSubscription = rxjs.timer(this._timerRefreshPeriod, this._timerRefreshPeriod)
|
|
10675
|
-
.pipe(
|
|
10676
|
-
// Skip some timer event (see constructor)
|
|
10677
|
-
operators.filter(this._timerRefreshCondition),
|
|
10678
|
-
// Checkin if peer alive
|
|
10679
|
-
operators.tap(function () { return console.debug('[network] Checking connection to pod...'); }), operators.mergeMap(function () { return _this.checkPeerAlive(_this.peer); }),
|
|
10680
|
-
// Filter to keep only changes
|
|
10681
|
-
operators.filter(function (info) { return !!info !== !!lastInfo; }), operators.tap(function (info) { return lastInfo = info; }),
|
|
10682
|
-
// Check compatibility
|
|
10683
|
-
operators.mergeMap(function (info) { return _this.checkPeerCompatible(info, { showToast: true }); }))
|
|
10684
|
-
.subscribe(function (alive) {
|
|
10685
|
-
if (alive && _this.offline) {
|
|
10686
|
-
_this.setForceOffline(false);
|
|
10687
|
-
// Restart the service (to force re auth)
|
|
10688
|
-
_this.restart();
|
|
10689
|
-
}
|
|
10690
|
-
else if (!alive && _this.online) {
|
|
10691
|
-
_this.setForceOffline(true);
|
|
10692
|
-
// Stop the service
|
|
10693
|
-
_this.stop();
|
|
10694
|
-
}
|
|
10695
|
-
});
|
|
10696
|
-
this._timerSubscription.add(function () { return console.debug('[network] Refresh timer stopped'); });
|
|
10697
|
-
};
|
|
10698
10565
|
/**
|
|
10699
10566
|
* Check if the peer is alive
|
|
10700
10567
|
*
|
|
@@ -10703,24 +10570,24 @@
|
|
|
10703
10570
|
NetworkService.prototype.checkPeerAlive = function (peer, opts) {
|
|
10704
10571
|
return __awaiter(this, void 0, void 0, function () {
|
|
10705
10572
|
var settings, err_2;
|
|
10706
|
-
return __generator(this, function (
|
|
10707
|
-
switch (
|
|
10573
|
+
return __generator(this, function (_b) {
|
|
10574
|
+
switch (_b.label) {
|
|
10708
10575
|
case 0:
|
|
10709
10576
|
peer = peer || this.peer;
|
|
10710
10577
|
if (!!peer) return [3 /*break*/, 2];
|
|
10711
10578
|
return [4 /*yield*/, this.settings.ready()];
|
|
10712
10579
|
case 1:
|
|
10713
|
-
settings =
|
|
10580
|
+
settings = _b.sent();
|
|
10714
10581
|
if (!settings.peerUrl)
|
|
10715
10582
|
return [2 /*return*/, undefined]; // No peer define. Skip
|
|
10716
10583
|
peer = exports.Peer.parseUrl(settings.peerUrl);
|
|
10717
|
-
|
|
10584
|
+
_b.label = 2;
|
|
10718
10585
|
case 2:
|
|
10719
|
-
|
|
10586
|
+
_b.trys.push([2, 4, , 5]);
|
|
10720
10587
|
return [4 /*yield*/, this.getNodeInfo(peer)];
|
|
10721
|
-
case 3: return [2 /*return*/,
|
|
10588
|
+
case 3: return [2 /*return*/, _b.sent()];
|
|
10722
10589
|
case 4:
|
|
10723
|
-
err_2 =
|
|
10590
|
+
err_2 = _b.sent();
|
|
10724
10591
|
console.debug('[network] Cannot get /api/node/info from peer: ' + (err_2 && err_2.message || err_2), err_2);
|
|
10725
10592
|
return [2 /*return*/, undefined];
|
|
10726
10593
|
case 5: return [2 /*return*/];
|
|
@@ -10731,8 +10598,8 @@
|
|
|
10731
10598
|
NetworkService.prototype.checkPeerCompatible = function (peerInfo, opts) {
|
|
10732
10599
|
return __awaiter(this, void 0, void 0, function () {
|
|
10733
10600
|
var isCompatible;
|
|
10734
|
-
return __generator(this, function (
|
|
10735
|
-
switch (
|
|
10601
|
+
return __generator(this, function (_b) {
|
|
10602
|
+
switch (_b.label) {
|
|
10736
10603
|
case 0:
|
|
10737
10604
|
if (!this.environment.peerMinVersion)
|
|
10738
10605
|
return [2 /*return*/, true]; // Skip compatibility check
|
|
@@ -10747,8 +10614,8 @@
|
|
|
10747
10614
|
showCloseButton: true
|
|
10748
10615
|
})];
|
|
10749
10616
|
case 1:
|
|
10750
|
-
|
|
10751
|
-
|
|
10617
|
+
_b.sent();
|
|
10618
|
+
_b.label = 2;
|
|
10752
10619
|
case 2: return [2 /*return*/, isCompatible];
|
|
10753
10620
|
}
|
|
10754
10621
|
});
|
|
@@ -10788,8 +10655,8 @@
|
|
|
10788
10655
|
return __awaiter(this, void 0, void 0, function () {
|
|
10789
10656
|
var $onRefresh, peers$, modal, data;
|
|
10790
10657
|
var _this = this;
|
|
10791
|
-
return __generator(this, function (
|
|
10792
|
-
switch (
|
|
10658
|
+
return __generator(this, function (_b) {
|
|
10659
|
+
switch (_b.label) {
|
|
10793
10660
|
case 0:
|
|
10794
10661
|
opts = opts || {};
|
|
10795
10662
|
$onRefresh = new i0.EventEmitter();
|
|
@@ -10806,14 +10673,14 @@
|
|
|
10806
10673
|
showBackdrop: true
|
|
10807
10674
|
})];
|
|
10808
10675
|
case 1:
|
|
10809
|
-
modal =
|
|
10676
|
+
modal = _b.sent();
|
|
10810
10677
|
return [4 /*yield*/, modal.present()];
|
|
10811
10678
|
case 2:
|
|
10812
|
-
|
|
10679
|
+
_b.sent();
|
|
10813
10680
|
$onRefresh.emit();
|
|
10814
10681
|
return [4 /*yield*/, modal.onWillDismiss()];
|
|
10815
10682
|
case 3:
|
|
10816
|
-
data = (
|
|
10683
|
+
data = (_b.sent()).data;
|
|
10817
10684
|
$onRefresh.complete();
|
|
10818
10685
|
return [2 /*return*/, data && data || undefined];
|
|
10819
10686
|
}
|
|
@@ -10824,7 +10691,7 @@
|
|
|
10824
10691
|
return __awaiter(this, void 0, void 0, function () {
|
|
10825
10692
|
var now;
|
|
10826
10693
|
var _this = this;
|
|
10827
|
-
return __generator(this, function (
|
|
10694
|
+
return __generator(this, function (_b) {
|
|
10828
10695
|
now = this._debug && Date.now();
|
|
10829
10696
|
console.info('[network] Clearing all caches...');
|
|
10830
10697
|
return [2 /*return*/, this.cache.clearAll()
|
|
@@ -10843,10 +10710,164 @@
|
|
|
10843
10710
|
});
|
|
10844
10711
|
});
|
|
10845
10712
|
};
|
|
10713
|
+
/* -- protected functions -- */
|
|
10714
|
+
NetworkService.prototype.ngOnStart = function () {
|
|
10715
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
10716
|
+
var peer, _b;
|
|
10717
|
+
return __generator(this, function (_c) {
|
|
10718
|
+
switch (_c.label) {
|
|
10719
|
+
case 0:
|
|
10720
|
+
console.info('[network] Starting network...', this._startingPeer);
|
|
10721
|
+
_b = this._startingPeer;
|
|
10722
|
+
if (_b) return [3 /*break*/, 2];
|
|
10723
|
+
return [4 /*yield*/, this.restoreLocally()];
|
|
10724
|
+
case 1:
|
|
10725
|
+
_b = (_c.sent());
|
|
10726
|
+
_c.label = 2;
|
|
10727
|
+
case 2:
|
|
10728
|
+
peer = _b;
|
|
10729
|
+
// Make sure to hide the splashscreen, before open the modal
|
|
10730
|
+
if (!peer && this.splashScreen)
|
|
10731
|
+
this.splashScreen.hide();
|
|
10732
|
+
_c.label = 3;
|
|
10733
|
+
case 3:
|
|
10734
|
+
if (!!peer) return [3 /*break*/, 5];
|
|
10735
|
+
console.debug('[network] No peer defined. Asking user to choose a peer.');
|
|
10736
|
+
return [4 /*yield*/, this.showSelectPeerModal({ allowSelectDownPeer: false })];
|
|
10737
|
+
case 4:
|
|
10738
|
+
peer = _c.sent();
|
|
10739
|
+
return [3 /*break*/, 3];
|
|
10740
|
+
case 5:
|
|
10741
|
+
console.info("[network] Starting service [OK] {peer: '" + peer.url + "', online: " + this.online + "}");
|
|
10742
|
+
return [2 /*return*/, peer];
|
|
10743
|
+
}
|
|
10744
|
+
});
|
|
10745
|
+
});
|
|
10746
|
+
};
|
|
10747
|
+
NetworkService.prototype.ngOnAfterStart = function () {
|
|
10748
|
+
var _a;
|
|
10749
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
10750
|
+
var _this = this;
|
|
10751
|
+
return __generator(this, function (_b) {
|
|
10752
|
+
switch (_b.label) {
|
|
10753
|
+
case 0:
|
|
10754
|
+
// Wait settings starts, then save peer in settings
|
|
10755
|
+
return [4 /*yield*/, this.settings.apply({ peerUrl: this._data.url })];
|
|
10756
|
+
case 1:
|
|
10757
|
+
// Wait settings starts, then save peer in settings
|
|
10758
|
+
_b.sent();
|
|
10759
|
+
this.onDeviceConnectionChanged(((_a = this.network) === null || _a === void 0 ? void 0 : _a.type) || 'unknown');
|
|
10760
|
+
// Start the refresh timer
|
|
10761
|
+
this.startRefreshTimer();
|
|
10762
|
+
// Listen for device network changes
|
|
10763
|
+
if (this.network) {
|
|
10764
|
+
this._subscription.add(this.network.onDisconnect().subscribe(function () { return _this.onDeviceConnectionChanged('none'); }));
|
|
10765
|
+
this._subscription.add(this.network.onConnect().subscribe(function () { return _this.onDeviceConnectionChanged(_this.network.type); }));
|
|
10766
|
+
}
|
|
10767
|
+
return [2 /*return*/];
|
|
10768
|
+
}
|
|
10769
|
+
});
|
|
10770
|
+
});
|
|
10771
|
+
};
|
|
10772
|
+
NetworkService.prototype.ngOnStop = function () {
|
|
10773
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
10774
|
+
return __generator(this, function (_b) {
|
|
10775
|
+
this.resetData();
|
|
10776
|
+
// Stop timer if cannot refresh anymore
|
|
10777
|
+
if (this._timerRefreshCondition() === false) {
|
|
10778
|
+
this.stopRefreshTimer();
|
|
10779
|
+
}
|
|
10780
|
+
this._subscription.unsubscribe();
|
|
10781
|
+
this._subscription = new rxjs.Subscription();
|
|
10782
|
+
return [2 /*return*/];
|
|
10783
|
+
});
|
|
10784
|
+
});
|
|
10785
|
+
};
|
|
10786
|
+
/**
|
|
10787
|
+
* Try to restore peer from the local storage
|
|
10788
|
+
*/
|
|
10789
|
+
NetworkService.prototype.restoreLocally = function () {
|
|
10790
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
10791
|
+
var settingsStr, settings, location, hostname, detectedPeer;
|
|
10792
|
+
return __generator(this, function (_b) {
|
|
10793
|
+
switch (_b.label) {
|
|
10794
|
+
case 0: return [4 /*yield*/, this.storage.get(SETTINGS_STORAGE_KEY)];
|
|
10795
|
+
case 1:
|
|
10796
|
+
settingsStr = _b.sent();
|
|
10797
|
+
settings = settingsStr && JSON.parse(settingsStr) || undefined;
|
|
10798
|
+
if (settings && settings.peerUrl) {
|
|
10799
|
+
console.debug("[network] Use peer {" + settings.peerUrl + "} (found in the local storage)");
|
|
10800
|
+
return [2 /*return*/, exports.Peer.parseUrl(settings.peerUrl)];
|
|
10801
|
+
}
|
|
10802
|
+
// Else, use default peer in env, if exists
|
|
10803
|
+
if (this.environment.defaultPeer) {
|
|
10804
|
+
return [2 /*return*/, exports.Peer.fromObject(this.environment.defaultPeer)];
|
|
10805
|
+
}
|
|
10806
|
+
location = this._document && this._document.location;
|
|
10807
|
+
if (!(location && location.protocol && location.protocol.startsWith('http'))) return [3 /*break*/, 3];
|
|
10808
|
+
hostname = this._document.location.host;
|
|
10809
|
+
detectedPeer = exports.Peer.parseUrl("" + this._document.location.protocol + hostname + this.environment.baseUrl);
|
|
10810
|
+
return [4 /*yield*/, this.checkPeerAlive(detectedPeer)];
|
|
10811
|
+
case 2:
|
|
10812
|
+
if (_b.sent()) {
|
|
10813
|
+
return [2 /*return*/, detectedPeer];
|
|
10814
|
+
}
|
|
10815
|
+
_b.label = 3;
|
|
10816
|
+
case 3: return [2 /*return*/, undefined];
|
|
10817
|
+
}
|
|
10818
|
+
});
|
|
10819
|
+
});
|
|
10820
|
+
};
|
|
10821
|
+
/**
|
|
10822
|
+
* Stop to network state
|
|
10823
|
+
*
|
|
10824
|
+
* @protected
|
|
10825
|
+
*/
|
|
10826
|
+
NetworkService.prototype.stopRefreshTimer = function () {
|
|
10827
|
+
if (this._timerSubscription) {
|
|
10828
|
+
this._timerSubscription.unsubscribe();
|
|
10829
|
+
this._timerSubscription = undefined;
|
|
10830
|
+
}
|
|
10831
|
+
};
|
|
10832
|
+
/**
|
|
10833
|
+
* Refresh the network state
|
|
10834
|
+
*
|
|
10835
|
+
* @protected
|
|
10836
|
+
*/
|
|
10837
|
+
NetworkService.prototype.startRefreshTimer = function () {
|
|
10838
|
+
var _this = this;
|
|
10839
|
+
if (this._timerSubscription)
|
|
10840
|
+
return; // Already running: skip
|
|
10841
|
+
console.info("[network] Starting refresh timer, every " + this._timerRefreshPeriod + "ms...");
|
|
10842
|
+
var lastInfo;
|
|
10843
|
+
this._timerSubscription = rxjs.timer(this._timerRefreshPeriod, this._timerRefreshPeriod)
|
|
10844
|
+
.pipe(
|
|
10845
|
+
// Skip some timer event (see constructor)
|
|
10846
|
+
operators.filter(this._timerRefreshCondition),
|
|
10847
|
+
// Checkin if peer alive
|
|
10848
|
+
operators.tap(function () { return console.debug('[network] Checking connection to pod...'); }), operators.mergeMap(function () { return _this.checkPeerAlive(_this.peer); }),
|
|
10849
|
+
// Filter to keep only changes
|
|
10850
|
+
operators.filter(function (info) { return !!info !== !!lastInfo; }), operators.tap(function (info) { return lastInfo = info; }),
|
|
10851
|
+
// Check compatibility
|
|
10852
|
+
operators.mergeMap(function (info) { return _this.checkPeerCompatible(info, { showToast: true }); }))
|
|
10853
|
+
.subscribe(function (alive) {
|
|
10854
|
+
if (alive && _this.offline) {
|
|
10855
|
+
_this.setForceOffline(false);
|
|
10856
|
+
// Restart the service (to force re auth)
|
|
10857
|
+
_this.restart();
|
|
10858
|
+
}
|
|
10859
|
+
else if (!alive && _this.online) {
|
|
10860
|
+
_this.setForceOffline(true);
|
|
10861
|
+
// Stop the service
|
|
10862
|
+
_this.stop();
|
|
10863
|
+
}
|
|
10864
|
+
});
|
|
10865
|
+
this._timerSubscription.add(function () { return console.debug('[network] Refresh timer stopped'); });
|
|
10866
|
+
};
|
|
10846
10867
|
NetworkService.prototype.get = function (path, opts) {
|
|
10847
10868
|
return __awaiter(this, void 0, void 0, function () {
|
|
10848
10869
|
var uri, peerUrl;
|
|
10849
|
-
return __generator(this, function (
|
|
10870
|
+
return __generator(this, function (_b) {
|
|
10850
10871
|
uri = path;
|
|
10851
10872
|
// If path is not an URI: prepend with peer URL
|
|
10852
10873
|
if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
|
|
@@ -10897,7 +10918,7 @@
|
|
|
10897
10918
|
}
|
|
10898
10919
|
};
|
|
10899
10920
|
NetworkService.prototype.resetData = function () {
|
|
10900
|
-
this.
|
|
10921
|
+
this._data = null;
|
|
10901
10922
|
};
|
|
10902
10923
|
/**
|
|
10903
10924
|
* Get default peers, from environment
|
|
@@ -10905,7 +10926,7 @@
|
|
|
10905
10926
|
NetworkService.prototype.getDefaultPeers = function () {
|
|
10906
10927
|
return __awaiter(this, void 0, void 0, function () {
|
|
10907
10928
|
var peers;
|
|
10908
|
-
return __generator(this, function (
|
|
10929
|
+
return __generator(this, function (_b) {
|
|
10909
10930
|
peers = (this.environment.defaultPeers || []).map(exports.Peer.fromObject);
|
|
10910
10931
|
return [2 /*return*/, Promise.resolve(peers)];
|
|
10911
10932
|
});
|
|
@@ -10929,7 +10950,7 @@
|
|
|
10929
10950
|
NetworkService.prototype.emit = function (name, data) {
|
|
10930
10951
|
return __awaiter(this, void 0, void 0, function () {
|
|
10931
10952
|
var hooks;
|
|
10932
|
-
return __generator(this, function (
|
|
10953
|
+
return __generator(this, function (_b) {
|
|
10933
10954
|
hooks = this._listeners[name];
|
|
10934
10955
|
if (isNotEmptyArray(hooks)) {
|
|
10935
10956
|
console.info("[network-service] Trigger " + name + " hook: Executing " + hooks.length + " callbacks...");
|
|
@@ -10945,7 +10966,7 @@
|
|
|
10945
10966
|
});
|
|
10946
10967
|
};
|
|
10947
10968
|
return NetworkService;
|
|
10948
|
-
}());
|
|
10969
|
+
}(StartableService));
|
|
10949
10970
|
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" });
|
|
10950
10971
|
NetworkService.decorators = [
|
|
10951
10972
|
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
|
|
@@ -11548,31 +11569,31 @@
|
|
|
11548
11569
|
}());
|
|
11549
11570
|
|
|
11550
11571
|
var APP_LOCAL_STORAGE_TYPE_POLICIES = new i0.InjectionToken('localStorageTypePolicies');
|
|
11551
|
-
|
|
11572
|
+
;
|
|
11573
|
+
var EntitiesStorage = /** @class */ (function (_super) {
|
|
11574
|
+
__extends(EntitiesStorage, _super);
|
|
11552
11575
|
function EntitiesStorage(platform, progressBarService, storage, environment, typePolicies) {
|
|
11553
|
-
this
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11576
|
+
var _this = _super.call(this, platform) || this;
|
|
11577
|
+
_this.platform = platform;
|
|
11578
|
+
_this.progressBarService = progressBarService;
|
|
11579
|
+
_this.storage = storage;
|
|
11580
|
+
_this.environment = environment;
|
|
11581
|
+
_this._subscription = new rxjs.Subscription();
|
|
11582
|
+
_this._$save = new i0.EventEmitter(true);
|
|
11583
|
+
_this._dirty = false;
|
|
11584
|
+
_this._saving = false;
|
|
11585
|
+
_this._typePolicies = typePolicies || {};
|
|
11586
|
+
_this._saveTimerPeriod = environment.storageSavePeriodMs || 10000 /* = 10s */;
|
|
11587
|
+
_this._data = {};
|
|
11565
11588
|
// For DEV only
|
|
11566
|
-
|
|
11567
|
-
if (
|
|
11589
|
+
_this._debug = !environment.production;
|
|
11590
|
+
if (_this._debug)
|
|
11568
11591
|
console.debug('[entities-storage] Creating service');
|
|
11592
|
+
return _this;
|
|
11569
11593
|
}
|
|
11570
11594
|
Object.defineProperty(EntitiesStorage.prototype, "dirty", {
|
|
11571
11595
|
get: function () {
|
|
11572
|
-
return this._dirty || Object.
|
|
11573
|
-
var _b = __read(_a, 2), _ = _b[0], store = _b[1];
|
|
11574
|
-
return store.dirty;
|
|
11575
|
-
}) !== undefined;
|
|
11596
|
+
return this._dirty || Object.values(this._data).some(function (store) { return store.dirty; });
|
|
11576
11597
|
},
|
|
11577
11598
|
enumerable: false,
|
|
11578
11599
|
configurable: true
|
|
@@ -11580,7 +11601,7 @@
|
|
|
11580
11601
|
EntitiesStorage.prototype.watchAll = function (entityName, variables, opts) {
|
|
11581
11602
|
var _this = this;
|
|
11582
11603
|
// Make sure store is ready
|
|
11583
|
-
if (!this.
|
|
11604
|
+
if (!this.started) {
|
|
11584
11605
|
return rxjs.defer(function () { return _this.ready(); })
|
|
11585
11606
|
.pipe(operators.switchMap(function () { return _this.watchAll(entityName, variables, opts); })); // Loop
|
|
11586
11607
|
}
|
|
@@ -11597,7 +11618,7 @@
|
|
|
11597
11618
|
return __generator(this, function (_a) {
|
|
11598
11619
|
switch (_a.label) {
|
|
11599
11620
|
case 0:
|
|
11600
|
-
if (!!this.
|
|
11621
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11601
11622
|
return [4 /*yield*/, this.ready()];
|
|
11602
11623
|
case 1:
|
|
11603
11624
|
_a.sent();
|
|
@@ -11700,9 +11721,12 @@
|
|
|
11700
11721
|
case 0:
|
|
11701
11722
|
if (!entity)
|
|
11702
11723
|
return [2 /*return*/]; // skip
|
|
11724
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11703
11725
|
return [4 /*yield*/, this.ready()];
|
|
11704
11726
|
case 1:
|
|
11705
11727
|
_a.sent();
|
|
11728
|
+
_a.label = 2;
|
|
11729
|
+
case 2:
|
|
11706
11730
|
try {
|
|
11707
11731
|
this.progressBarService.increase();
|
|
11708
11732
|
this._dirty = true;
|
|
@@ -11729,9 +11753,12 @@
|
|
|
11729
11753
|
case 0:
|
|
11730
11754
|
if (isEmptyArray(entities) && (!opts || opts.reset !== true))
|
|
11731
11755
|
return [2 /*return*/, entities]; // Skip (nothing to save)
|
|
11756
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11732
11757
|
return [4 /*yield*/, this.ready()];
|
|
11733
11758
|
case 1:
|
|
11734
11759
|
_a.sent();
|
|
11760
|
+
_a.label = 2;
|
|
11761
|
+
case 2:
|
|
11735
11762
|
try {
|
|
11736
11763
|
this.progressBarService.increase();
|
|
11737
11764
|
this._dirty = true;
|
|
@@ -11753,10 +11780,12 @@
|
|
|
11753
11780
|
case 0:
|
|
11754
11781
|
if (!entity)
|
|
11755
11782
|
return [2 /*return*/, undefined]; // skip
|
|
11783
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11756
11784
|
return [4 /*yield*/, this.ready()];
|
|
11757
11785
|
case 1:
|
|
11758
11786
|
_a.sent();
|
|
11759
|
-
|
|
11787
|
+
_a.label = 2;
|
|
11788
|
+
case 2: return [2 /*return*/, this.deleteById(entity.id, Object.assign(Object.assign({}, opts), { entityName: opts && opts.entityName || this.detectEntityName(entity) }))];
|
|
11760
11789
|
}
|
|
11761
11790
|
});
|
|
11762
11791
|
});
|
|
@@ -11766,9 +11795,13 @@
|
|
|
11766
11795
|
var entityStore, deletedEntity;
|
|
11767
11796
|
return __generator(this, function (_a) {
|
|
11768
11797
|
switch (_a.label) {
|
|
11769
|
-
case 0:
|
|
11798
|
+
case 0:
|
|
11799
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11800
|
+
return [4 /*yield*/, this.ready()];
|
|
11770
11801
|
case 1:
|
|
11771
11802
|
_a.sent();
|
|
11803
|
+
_a.label = 2;
|
|
11804
|
+
case 2:
|
|
11772
11805
|
if (!opts || isNilOrBlank(opts.entityName))
|
|
11773
11806
|
throw new Error('Missing argument \'opts\' or \'entityName\'');
|
|
11774
11807
|
//if (id >= 0) throw new Error('Invalid id a local entity (not a negative number): ' + id);
|
|
@@ -11800,9 +11833,13 @@
|
|
|
11800
11833
|
var entityStore, deletedEntities;
|
|
11801
11834
|
return __generator(this, function (_a) {
|
|
11802
11835
|
switch (_a.label) {
|
|
11803
|
-
case 0:
|
|
11836
|
+
case 0:
|
|
11837
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11838
|
+
return [4 /*yield*/, this.ready()];
|
|
11804
11839
|
case 1:
|
|
11805
11840
|
_a.sent();
|
|
11841
|
+
_a.label = 2;
|
|
11842
|
+
case 2:
|
|
11806
11843
|
if (!opts || isNilOrBlank(opts.entityName))
|
|
11807
11844
|
throw new Error('Missing argument \'opts\' or \'opts.entityName\'');
|
|
11808
11845
|
try {
|
|
@@ -11835,10 +11872,12 @@
|
|
|
11835
11872
|
case 0:
|
|
11836
11873
|
if (!entity)
|
|
11837
11874
|
return [2 /*return*/, undefined]; // skip
|
|
11875
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11838
11876
|
return [4 /*yield*/, this.ready()];
|
|
11839
11877
|
case 1:
|
|
11840
11878
|
_a.sent();
|
|
11841
|
-
|
|
11879
|
+
_a.label = 2;
|
|
11880
|
+
case 2: return [2 /*return*/, this.deleteFromTrashById(entity.id, Object.assign(Object.assign({}, opts), { entityName: opts && opts.entityName || this.detectEntityName(entity) }))];
|
|
11842
11881
|
}
|
|
11843
11882
|
});
|
|
11844
11883
|
});
|
|
@@ -11865,9 +11904,12 @@
|
|
|
11865
11904
|
case 0:
|
|
11866
11905
|
if (!entity)
|
|
11867
11906
|
return [2 /*return*/, undefined]; // skip
|
|
11907
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11868
11908
|
return [4 /*yield*/, this.ready()];
|
|
11869
11909
|
case 1:
|
|
11870
11910
|
_a.sent();
|
|
11911
|
+
_a.label = 2;
|
|
11912
|
+
case 2:
|
|
11871
11913
|
entityName = opts && opts.entityName || this.detectEntityName(entity);
|
|
11872
11914
|
entityStore = this.getEntityStore(entityName);
|
|
11873
11915
|
if (entityStore)
|
|
@@ -11887,9 +11929,13 @@
|
|
|
11887
11929
|
var entityStore, deletedEntities, trashName;
|
|
11888
11930
|
return __generator(this, function (_a) {
|
|
11889
11931
|
switch (_a.label) {
|
|
11890
|
-
case 0:
|
|
11932
|
+
case 0:
|
|
11933
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11934
|
+
return [4 /*yield*/, this.ready()];
|
|
11891
11935
|
case 1:
|
|
11892
11936
|
_a.sent();
|
|
11937
|
+
_a.label = 2;
|
|
11938
|
+
case 2:
|
|
11893
11939
|
if (!opts || isNilOrBlank(opts.entityName))
|
|
11894
11940
|
throw new Error('Missing argument \'opts.entityName\'');
|
|
11895
11941
|
entityStore = this.getEntityStore(opts.entityName, { create: false });
|
|
@@ -11921,9 +11967,12 @@
|
|
|
11921
11967
|
case 0:
|
|
11922
11968
|
if (!entity)
|
|
11923
11969
|
return [2 /*return*/, undefined]; // skip
|
|
11970
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11924
11971
|
return [4 /*yield*/, this.ready()];
|
|
11925
11972
|
case 1:
|
|
11926
11973
|
_a.sent();
|
|
11974
|
+
_a.label = 2;
|
|
11975
|
+
case 2:
|
|
11927
11976
|
entityName = opts && opts.entityName || this.detectEntityName(entity);
|
|
11928
11977
|
trashName = EntitiesStorage.TRASH_PREFIX + entityName;
|
|
11929
11978
|
this.getEntityStore(trashName).save(entity, opts);
|
|
@@ -11938,9 +11987,13 @@
|
|
|
11938
11987
|
var trashName, entityStore;
|
|
11939
11988
|
return __generator(this, function (_a) {
|
|
11940
11989
|
switch (_a.label) {
|
|
11941
|
-
case 0:
|
|
11990
|
+
case 0:
|
|
11991
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
11992
|
+
return [4 /*yield*/, this.ready()];
|
|
11942
11993
|
case 1:
|
|
11943
11994
|
_a.sent();
|
|
11995
|
+
_a.label = 2;
|
|
11996
|
+
case 2:
|
|
11944
11997
|
trashName = EntitiesStorage.TRASH_PREFIX + entityName;
|
|
11945
11998
|
entityStore = this.getEntityStore(trashName, { create: false });
|
|
11946
11999
|
if (!entityStore)
|
|
@@ -11959,79 +12012,58 @@
|
|
|
11959
12012
|
}
|
|
11960
12013
|
return Promise.resolve();
|
|
11961
12014
|
};
|
|
11962
|
-
EntitiesStorage.prototype.
|
|
11963
|
-
if (this._started)
|
|
11964
|
-
return Promise.resolve();
|
|
11965
|
-
return this.start();
|
|
11966
|
-
};
|
|
11967
|
-
EntitiesStorage.prototype.start = function () {
|
|
11968
|
-
var _this = this;
|
|
11969
|
-
if (this._startPromise)
|
|
11970
|
-
return this._startPromise;
|
|
11971
|
-
if (this._started)
|
|
11972
|
-
return Promise.resolve();
|
|
11973
|
-
var now = Date.now();
|
|
11974
|
-
console.info("[entities-storage] Starting entity storage...");
|
|
11975
|
-
// Restore sequences
|
|
11976
|
-
this._startPromise = this.restoreLocally()
|
|
11977
|
-
.then(function () {
|
|
11978
|
-
// Start a save timer
|
|
11979
|
-
_this._subscription.add(rxjs.merge(_this._$save, rxjs.timer(2000, 10000))
|
|
11980
|
-
.pipe(operators.throttleTime(10000))
|
|
11981
|
-
.subscribe(function () { return _this.storeLocally(); }));
|
|
11982
|
-
_this._started = true;
|
|
11983
|
-
_this._startPromise = undefined;
|
|
11984
|
-
console.info("[entities-storage] Starting [OK] in " + (Date.now() - now) + "ms");
|
|
11985
|
-
// Emit event
|
|
11986
|
-
_this.onStart.next();
|
|
11987
|
-
});
|
|
11988
|
-
return this._startPromise;
|
|
11989
|
-
};
|
|
11990
|
-
EntitiesStorage.prototype.stop = function () {
|
|
12015
|
+
EntitiesStorage.prototype.ngOnStart = function () {
|
|
11991
12016
|
return __awaiter(this, void 0, void 0, function () {
|
|
12017
|
+
var now;
|
|
12018
|
+
var _this = this;
|
|
11992
12019
|
return __generator(this, function (_a) {
|
|
11993
12020
|
switch (_a.label) {
|
|
11994
12021
|
case 0:
|
|
11995
|
-
|
|
11996
|
-
|
|
11997
|
-
|
|
11998
|
-
|
|
11999
|
-
return [4 /*yield*/, this.storeLocally()];
|
|
12022
|
+
now = Date.now();
|
|
12023
|
+
console.info("[entities-storage] Starting entity storage...");
|
|
12024
|
+
// Restore sequences
|
|
12025
|
+
return [4 /*yield*/, this.restoreLocally()];
|
|
12000
12026
|
case 1:
|
|
12027
|
+
// Restore sequences
|
|
12001
12028
|
_a.sent();
|
|
12002
|
-
|
|
12003
|
-
|
|
12029
|
+
// Start a save timer
|
|
12030
|
+
this._subscription.add(rxjs.merge(this._$save, rxjs.timer(this._saveTimerPeriod, this._saveTimerPeriod))
|
|
12031
|
+
.pipe(
|
|
12032
|
+
// Avoid to many call (e.g. when $save AND timer are triggered
|
|
12033
|
+
operators.throttleTime(this._saveTimerPeriod))
|
|
12034
|
+
.subscribe(function () { return _this.storeLocally(); }));
|
|
12035
|
+
console.info("[entities-storage] Starting [OK] in " + (Date.now() - now) + "ms");
|
|
12036
|
+
return [2 /*return*/, this._data];
|
|
12004
12037
|
}
|
|
12005
12038
|
});
|
|
12006
12039
|
});
|
|
12007
12040
|
};
|
|
12008
|
-
EntitiesStorage.prototype.
|
|
12041
|
+
EntitiesStorage.prototype.ngOnStop = function () {
|
|
12009
12042
|
return __awaiter(this, void 0, void 0, function () {
|
|
12010
12043
|
return __generator(this, function (_a) {
|
|
12011
12044
|
switch (_a.label) {
|
|
12012
12045
|
case 0:
|
|
12013
|
-
|
|
12014
|
-
|
|
12046
|
+
this._subscription.unsubscribe();
|
|
12047
|
+
this._subscription = new rxjs.Subscription();
|
|
12048
|
+
if (!this.dirty) return [3 /*break*/, 2];
|
|
12049
|
+
return [4 /*yield*/, this.storeLocally()];
|
|
12015
12050
|
case 1:
|
|
12016
12051
|
_a.sent();
|
|
12017
12052
|
_a.label = 2;
|
|
12018
|
-
case 2: return [
|
|
12019
|
-
case 3:
|
|
12020
|
-
_a.sent();
|
|
12021
|
-
return [2 /*return*/];
|
|
12053
|
+
case 2: return [2 /*return*/];
|
|
12022
12054
|
}
|
|
12023
12055
|
});
|
|
12024
12056
|
});
|
|
12025
12057
|
};
|
|
12026
12058
|
/* -- protected methods -- */
|
|
12027
12059
|
EntitiesStorage.prototype.getEntityStore = function (name, opts) {
|
|
12028
|
-
var store = this.
|
|
12060
|
+
var store = this._data[name];
|
|
12029
12061
|
if (!store && (!opts || opts.create !== false)) {
|
|
12030
12062
|
if (this._debug)
|
|
12031
12063
|
console.debug("[entities-storage] Creating store " + name);
|
|
12032
12064
|
var typePolicy = this._typePolicies[name];
|
|
12033
12065
|
store = new EntityStore(name, this.storage, typePolicy);
|
|
12034
|
-
this.
|
|
12066
|
+
this._data[name] = store;
|
|
12035
12067
|
}
|
|
12036
12068
|
return store;
|
|
12037
12069
|
};
|
|
@@ -12088,11 +12120,11 @@
|
|
|
12088
12120
|
this._saving = true;
|
|
12089
12121
|
this._dirty = false;
|
|
12090
12122
|
this.progressBarService.increase();
|
|
12091
|
-
entityNames = this.
|
|
12123
|
+
entityNames = this._data && Object.keys(this._data) || [];
|
|
12092
12124
|
now = Date.now();
|
|
12093
12125
|
if (this._debug)
|
|
12094
12126
|
console.debug('[entities-storage] Persisting...');
|
|
12095
|
-
return [2 /*return*/,
|
|
12127
|
+
return [2 /*return*/, chainPromises(entityNames.map(function (entityName) { return function () {
|
|
12096
12128
|
currentEntityName = entityName;
|
|
12097
12129
|
var entityStore = _this.getEntityStore(entityName, { create: false });
|
|
12098
12130
|
if (!entityStore) {
|
|
@@ -12106,17 +12138,20 @@
|
|
|
12106
12138
|
entityNames.splice(entityNames.findIndex(function (e) { return e === entityName; }), 1);
|
|
12107
12139
|
}
|
|
12108
12140
|
});
|
|
12109
|
-
}
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12141
|
+
}; }))
|
|
12142
|
+
.then(function () {
|
|
12143
|
+
currentEntityName = undefined;
|
|
12144
|
+
return isEmptyArray(entityNames) ?
|
|
12145
|
+
_this.storage.remove(ENTITIES_STORAGE_KEY_PREFIX) :
|
|
12146
|
+
_this.storage.set(ENTITIES_STORAGE_KEY_PREFIX, entityNames);
|
|
12147
|
+
})
|
|
12148
|
+
.then(function () {
|
|
12149
|
+
if (_this._debug)
|
|
12150
|
+
console.debug("[entities-storage] Persisting [OK] " + entityNames.length + " stores saved in " + (Date.now() - now) + "ms...");
|
|
12151
|
+
_this._saving = false;
|
|
12152
|
+
_this.progressBarService.decrease();
|
|
12153
|
+
})
|
|
12154
|
+
.catch(function (err) {
|
|
12120
12155
|
_this._saving = false;
|
|
12121
12156
|
_this.progressBarService.decrease();
|
|
12122
12157
|
if (currentEntityName) {
|
|
@@ -12125,13 +12160,13 @@
|
|
|
12125
12160
|
else {
|
|
12126
12161
|
console.error("[entities-storage] Error while persisting: " + (err && err.message || err), err);
|
|
12127
12162
|
}
|
|
12128
|
-
|
|
12129
|
-
})
|
|
12163
|
+
throw err;
|
|
12164
|
+
})];
|
|
12130
12165
|
});
|
|
12131
12166
|
});
|
|
12132
12167
|
};
|
|
12133
12168
|
return EntitiesStorage;
|
|
12134
|
-
}());
|
|
12169
|
+
}(StartableService));
|
|
12135
12170
|
EntitiesStorage.TRASH_PREFIX = 'Trash#';
|
|
12136
12171
|
EntitiesStorage.REMOTE_PREFIX = 'Remote#';
|
|
12137
12172
|
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" });
|
|
@@ -12142,7 +12177,7 @@
|
|
|
12142
12177
|
{ type: i1$5.Platform },
|
|
12143
12178
|
{ type: ProgressBarService },
|
|
12144
12179
|
{ type: i3$2.Storage },
|
|
12145
|
-
{ type:
|
|
12180
|
+
{ type: Environment, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] },
|
|
12146
12181
|
{ type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [APP_LOCAL_STORAGE_TYPE_POLICIES,] }] }
|
|
12147
12182
|
]; };
|
|
12148
12183
|
|
|
@@ -12667,29 +12702,28 @@
|
|
|
12667
12702
|
}
|
|
12668
12703
|
|
|
12669
12704
|
var APP_GRAPHQL_TYPE_POLICIES = new i0.InjectionToken('graphqlTypePolicies');
|
|
12670
|
-
var GraphqlService = /** @class */ (function () {
|
|
12705
|
+
var GraphqlService = /** @class */ (function (_super) {
|
|
12706
|
+
__extends(GraphqlService, _super);
|
|
12671
12707
|
function GraphqlService(platform, apollo, httpLink, network, storage, cryptoService, environment, typePolicies) {
|
|
12672
|
-
var _this = this;
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
this._debug = !environment.production;
|
|
12688
|
-
this._defaultFetchPolicy = environment.apolloFetchPolicy;
|
|
12708
|
+
var _this = _super.call(this, network) || this;
|
|
12709
|
+
_this.platform = platform;
|
|
12710
|
+
_this.apollo = apollo;
|
|
12711
|
+
_this.httpLink = httpLink;
|
|
12712
|
+
_this.network = network;
|
|
12713
|
+
_this.storage = storage;
|
|
12714
|
+
_this.cryptoService = cryptoService;
|
|
12715
|
+
_this.environment = environment;
|
|
12716
|
+
_this.typePolicies = typePolicies;
|
|
12717
|
+
_this._subscription = new rxjs.Subscription();
|
|
12718
|
+
_this.connectionParams = {};
|
|
12719
|
+
_this.onNetworkError = new rxjs.Subject();
|
|
12720
|
+
_this.customErrors = {};
|
|
12721
|
+
_this._debug = !environment.production;
|
|
12722
|
+
_this._defaultFetchPolicy = environment.apolloFetchPolicy;
|
|
12689
12723
|
// Restart if network restart
|
|
12690
|
-
|
|
12724
|
+
_this.network.on('start', function () { return _this.restart(); });
|
|
12691
12725
|
// Clear cache
|
|
12692
|
-
|
|
12726
|
+
_this.network.on('resetCache', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
12693
12727
|
return __generator(this, function (_a) {
|
|
12694
12728
|
switch (_a.label) {
|
|
12695
12729
|
case 0: return [4 /*yield*/, this.ready()];
|
|
@@ -12703,23 +12737,17 @@
|
|
|
12703
12737
|
});
|
|
12704
12738
|
}); });
|
|
12705
12739
|
// Listen network status
|
|
12706
|
-
|
|
12740
|
+
_this._networkStatusChanged$ = network.onNetworkStatusChanges
|
|
12707
12741
|
.pipe(operators.filter(isNotNil), operators.distinctUntilChanged());
|
|
12708
12742
|
// When getting network error: try to ping peer, and toggle to offline
|
|
12709
|
-
|
|
12743
|
+
_this.onNetworkError
|
|
12710
12744
|
.pipe(operators.throttleTime(300), operators.filter(function () { return _this.network.online; }), operators.mergeMap(function () { return _this.network.checkPeerAlive(); }), operators.filter(function (alive) { return !alive; }))
|
|
12711
12745
|
.subscribe(function () { return _this.network.setForceOffline(true, { showToast: true }); });
|
|
12746
|
+
return _this;
|
|
12712
12747
|
}
|
|
12713
|
-
Object.defineProperty(GraphqlService.prototype, "started", {
|
|
12714
|
-
get: function () {
|
|
12715
|
-
return this._started;
|
|
12716
|
-
},
|
|
12717
|
-
enumerable: false,
|
|
12718
|
-
configurable: true
|
|
12719
|
-
});
|
|
12720
12748
|
Object.defineProperty(GraphqlService.prototype, "client", {
|
|
12721
12749
|
get: function () {
|
|
12722
|
-
return this.
|
|
12750
|
+
return this._data;
|
|
12723
12751
|
},
|
|
12724
12752
|
enumerable: false,
|
|
12725
12753
|
configurable: true
|
|
@@ -12738,34 +12766,6 @@
|
|
|
12738
12766
|
enumerable: false,
|
|
12739
12767
|
configurable: true
|
|
12740
12768
|
});
|
|
12741
|
-
GraphqlService.prototype.ready = function () {
|
|
12742
|
-
if (this._started)
|
|
12743
|
-
return Promise.resolve();
|
|
12744
|
-
return this.start();
|
|
12745
|
-
};
|
|
12746
|
-
GraphqlService.prototype.start = function () {
|
|
12747
|
-
var _this = this;
|
|
12748
|
-
if (this._startPromise)
|
|
12749
|
-
return this._startPromise;
|
|
12750
|
-
if (this._started)
|
|
12751
|
-
return Promise.resolve();
|
|
12752
|
-
console.info('[graphql] Starting graphql...');
|
|
12753
|
-
// Waiting for network service
|
|
12754
|
-
this._startPromise = this.network.ready()
|
|
12755
|
-
.then(function () { return _this.initApollo(); })
|
|
12756
|
-
.then(function () {
|
|
12757
|
-
_this._started = true;
|
|
12758
|
-
_this._startPromise = undefined;
|
|
12759
|
-
// Emit event
|
|
12760
|
-
_this.onStart.next();
|
|
12761
|
-
console.info('[graphql] Starting graphql [OK]');
|
|
12762
|
-
})
|
|
12763
|
-
.catch(function (err) {
|
|
12764
|
-
console.error(err && err.message || err, err);
|
|
12765
|
-
_this._startPromise = undefined;
|
|
12766
|
-
});
|
|
12767
|
-
return this._startPromise;
|
|
12768
|
-
};
|
|
12769
12769
|
GraphqlService.prototype.setAuthToken = function (token) {
|
|
12770
12770
|
if (token) {
|
|
12771
12771
|
console.debug('[graphql] Apply token authentication to headers');
|
|
@@ -12798,15 +12798,18 @@
|
|
|
12798
12798
|
*/
|
|
12799
12799
|
GraphqlService.prototype.addResolver = function (resolvers) {
|
|
12800
12800
|
return __awaiter(this, void 0, void 0, function () {
|
|
12801
|
-
var client;
|
|
12802
|
-
var _this = this;
|
|
12803
12801
|
return __generator(this, function (_a) {
|
|
12804
|
-
|
|
12805
|
-
|
|
12802
|
+
switch (_a.label) {
|
|
12803
|
+
case 0:
|
|
12804
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
12805
|
+
return [4 /*yield*/, this.ready()];
|
|
12806
|
+
case 1:
|
|
12807
|
+
_a.sent();
|
|
12808
|
+
_a.label = 2;
|
|
12809
|
+
case 2:
|
|
12810
|
+
this.apollo.client.addResolvers(resolvers);
|
|
12811
|
+
return [2 /*return*/];
|
|
12806
12812
|
}
|
|
12807
|
-
client = this.apollo.getClient();
|
|
12808
|
-
client.addResolvers(resolvers);
|
|
12809
|
-
return [2 /*return*/];
|
|
12810
12813
|
});
|
|
12811
12814
|
});
|
|
12812
12815
|
};
|
|
@@ -12816,21 +12819,26 @@
|
|
|
12816
12819
|
return __generator(this, function (_a) {
|
|
12817
12820
|
switch (_a.label) {
|
|
12818
12821
|
case 0:
|
|
12819
|
-
|
|
12820
|
-
return [4 /*yield*/, this.
|
|
12821
|
-
case 1:
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
fetchPolicy: opts.fetchPolicy || this._defaultFetchPolicy || undefined
|
|
12825
|
-
}).toPromise()];
|
|
12822
|
+
if (!!this.started) return [3 /*break*/, 2];
|
|
12823
|
+
return [4 /*yield*/, this.ready()];
|
|
12824
|
+
case 1:
|
|
12825
|
+
_a.sent();
|
|
12826
|
+
_a.label = 2;
|
|
12826
12827
|
case 2:
|
|
12827
|
-
|
|
12828
|
-
return [
|
|
12828
|
+
_a.trys.push([2, 4, , 5]);
|
|
12829
|
+
return [4 /*yield*/, this.client.query({
|
|
12830
|
+
query: opts.query,
|
|
12831
|
+
variables: opts.variables,
|
|
12832
|
+
fetchPolicy: opts.fetchPolicy || this._defaultFetchPolicy || undefined
|
|
12833
|
+
})];
|
|
12829
12834
|
case 3:
|
|
12835
|
+
res = _a.sent();
|
|
12836
|
+
return [3 /*break*/, 5];
|
|
12837
|
+
case 4:
|
|
12830
12838
|
err_1 = _a.sent();
|
|
12831
12839
|
res = this.toApolloError(err_1, opts.error);
|
|
12832
|
-
return [3 /*break*/,
|
|
12833
|
-
case
|
|
12840
|
+
return [3 /*break*/, 5];
|
|
12841
|
+
case 5:
|
|
12834
12842
|
if (res.errors) {
|
|
12835
12843
|
throw res.errors[0];
|
|
12836
12844
|
}
|
|
@@ -13207,13 +13215,14 @@
|
|
|
13207
13215
|
this.customErrors = Object.assign(Object.assign({}, this.customErrors), error);
|
|
13208
13216
|
};
|
|
13209
13217
|
/* -- protected methods -- */
|
|
13210
|
-
GraphqlService.prototype.
|
|
13218
|
+
GraphqlService.prototype.ngOnStart = function () {
|
|
13211
13219
|
return __awaiter(this, void 0, void 0, function () {
|
|
13212
13220
|
var mobile, enableTrackMutationQueries, peer, uri, wsUri, storage, client, wsLink, retryLink, authLink, httpLink, cache, mutationLinks, serializingLink, trackerLink, queueLink_1, err_2;
|
|
13213
13221
|
var _this = this;
|
|
13214
13222
|
return __generator(this, function (_a) {
|
|
13215
13223
|
switch (_a.label) {
|
|
13216
13224
|
case 0:
|
|
13225
|
+
console.info('[graphql] Starting graphql...');
|
|
13217
13226
|
mobile = this.platform.is('mobile') || this.platform.is('mobileweb');
|
|
13218
13227
|
enableTrackMutationQueries = !mobile;
|
|
13219
13228
|
peer = this.network.peer;
|
|
@@ -13284,9 +13293,8 @@
|
|
|
13284
13293
|
queueLink_1 = new QueueLink__default["default"]();
|
|
13285
13294
|
this._subscription.add(this._networkStatusChanged$
|
|
13286
13295
|
.subscribe(function (type) {
|
|
13287
|
-
var offline = type === 'none';
|
|
13288
13296
|
// Network is offline: start buffering into queue
|
|
13289
|
-
if (
|
|
13297
|
+
if (type === 'none') {
|
|
13290
13298
|
console.info('[graphql] offline mode: enable mutations buffer');
|
|
13291
13299
|
queueLink_1.close();
|
|
13292
13300
|
}
|
|
@@ -13349,12 +13357,14 @@
|
|
|
13349
13357
|
err_2 = _a.sent();
|
|
13350
13358
|
console.error('[graphql] Failed to restore tracked queries from storage: ' + (err_2 && err_2.message || err_2), err_2);
|
|
13351
13359
|
return [3 /*break*/, 7];
|
|
13352
|
-
case 7:
|
|
13360
|
+
case 7:
|
|
13361
|
+
console.info('[graphql] Starting graphql [OK]');
|
|
13362
|
+
return [2 /*return*/, client];
|
|
13353
13363
|
}
|
|
13354
13364
|
});
|
|
13355
13365
|
});
|
|
13356
13366
|
};
|
|
13357
|
-
GraphqlService.prototype.
|
|
13367
|
+
GraphqlService.prototype.ngOnStop = function () {
|
|
13358
13368
|
return __awaiter(this, void 0, void 0, function () {
|
|
13359
13369
|
return __generator(this, function (_a) {
|
|
13360
13370
|
switch (_a.label) {
|
|
@@ -13365,24 +13375,11 @@
|
|
|
13365
13375
|
return [4 /*yield*/, this.resetClient()];
|
|
13366
13376
|
case 1:
|
|
13367
13377
|
_a.sent();
|
|
13368
|
-
this._started = false;
|
|
13369
|
-
this._startPromise = undefined;
|
|
13370
13378
|
return [2 /*return*/];
|
|
13371
13379
|
}
|
|
13372
13380
|
});
|
|
13373
13381
|
});
|
|
13374
13382
|
};
|
|
13375
|
-
GraphqlService.prototype.restart = function () {
|
|
13376
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
13377
|
-
var _this = this;
|
|
13378
|
-
return __generator(this, function (_a) {
|
|
13379
|
-
if (this.started) {
|
|
13380
|
-
return [2 /*return*/, this.stop().then(function () { return _this.start(); })];
|
|
13381
|
-
}
|
|
13382
|
-
return [2 /*return*/, this.start()];
|
|
13383
|
-
});
|
|
13384
|
-
});
|
|
13385
|
-
};
|
|
13386
13383
|
GraphqlService.prototype.resetClient = function (client) {
|
|
13387
13384
|
return __awaiter(this, void 0, void 0, function () {
|
|
13388
13385
|
return __generator(this, function (_a) {
|
|
@@ -13484,24 +13481,8 @@
|
|
|
13484
13481
|
}
|
|
13485
13482
|
return undefined;
|
|
13486
13483
|
};
|
|
13487
|
-
GraphqlService.prototype.getApollo = function () {
|
|
13488
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
13489
|
-
return __generator(this, function (_a) {
|
|
13490
|
-
switch (_a.label) {
|
|
13491
|
-
case 0:
|
|
13492
|
-
if (!!this._started) return [3 /*break*/, 2];
|
|
13493
|
-
console.debug('[graphql] Waiting apollo client... ');
|
|
13494
|
-
return [4 /*yield*/, this.onStart.toPromise()];
|
|
13495
|
-
case 1:
|
|
13496
|
-
_a.sent();
|
|
13497
|
-
_a.label = 2;
|
|
13498
|
-
case 2: return [2 /*return*/, this.apollo];
|
|
13499
|
-
}
|
|
13500
|
-
});
|
|
13501
|
-
});
|
|
13502
|
-
};
|
|
13503
13484
|
return GraphqlService;
|
|
13504
|
-
}());
|
|
13485
|
+
}(StartableService));
|
|
13505
13486
|
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" });
|
|
13506
13487
|
GraphqlService.decorators = [
|
|
13507
13488
|
{ type: i0.Injectable, args: [{
|
|
@@ -13784,7 +13765,12 @@
|
|
|
13784
13765
|
_this.storage = storage;
|
|
13785
13766
|
_this.file = file;
|
|
13786
13767
|
_this.environment = environment;
|
|
13787
|
-
_this.
|
|
13768
|
+
_this.onLogin = new rxjs.Subject();
|
|
13769
|
+
_this.onLogout = new rxjs.Subject();
|
|
13770
|
+
_this.onChange = new rxjs.Subject();
|
|
13771
|
+
_this.onAuthTokenChange = new rxjs.Subject();
|
|
13772
|
+
_this.onAuthBasicChange = new rxjs.Subject();
|
|
13773
|
+
_this._data = {
|
|
13788
13774
|
loaded: false,
|
|
13789
13775
|
keypair: null,
|
|
13790
13776
|
authToken: null,
|
|
@@ -13798,11 +13784,6 @@
|
|
|
13798
13784
|
_this._started = false;
|
|
13799
13785
|
_this._$additionalFields = new rxjs.BehaviorSubject([]);
|
|
13800
13786
|
_this._tokenType$ = new rxjs.BehaviorSubject(undefined);
|
|
13801
|
-
_this.onLogin = new rxjs.Subject();
|
|
13802
|
-
_this.onLogout = new rxjs.Subject();
|
|
13803
|
-
_this.onChange = new rxjs.Subject();
|
|
13804
|
-
_this.onAuthTokenChange = new rxjs.Subject();
|
|
13805
|
-
_this.onAuthBasicChange = new rxjs.Subject();
|
|
13806
13787
|
_this._debug = !environment.production;
|
|
13807
13788
|
if (_this._debug)
|
|
13808
13789
|
console.debug('[account-service] Creating service');
|
|
@@ -13810,7 +13791,7 @@
|
|
|
13810
13791
|
// Send auth token to the graphql layer, when changed
|
|
13811
13792
|
_this.onAuthTokenChange.subscribe(function (token) { return _this.graphql.setAuthToken(token); });
|
|
13812
13793
|
_this.onAuthBasicChange.subscribe(function (basic) { return _this.graphql.setAuthBasic(basic); });
|
|
13813
|
-
// Listen
|
|
13794
|
+
// Listen graphql start (or restart)
|
|
13814
13795
|
_this.graphql.onStart.subscribe(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
13815
13796
|
return __generator(this, function (_b) {
|
|
13816
13797
|
if (!this._started) {
|
|
@@ -13844,27 +13825,27 @@
|
|
|
13844
13825
|
}
|
|
13845
13826
|
Object.defineProperty(AccountService.prototype, "account", {
|
|
13846
13827
|
get: function () {
|
|
13847
|
-
return this.
|
|
13828
|
+
return this._data.loaded ? this._data.account : undefined;
|
|
13848
13829
|
},
|
|
13849
13830
|
enumerable: false,
|
|
13850
13831
|
configurable: true
|
|
13851
13832
|
});
|
|
13852
13833
|
Object.defineProperty(AccountService.prototype, "person", {
|
|
13853
13834
|
get: function () {
|
|
13854
|
-
if (this.
|
|
13855
|
-
this.
|
|
13835
|
+
if (this._data.loaded && !this._data.person) {
|
|
13836
|
+
this._data.person = this._data.loaded ? this._data.account.asPerson() : undefined;
|
|
13856
13837
|
}
|
|
13857
|
-
return this.
|
|
13838
|
+
return this._data.person;
|
|
13858
13839
|
},
|
|
13859
13840
|
enumerable: false,
|
|
13860
13841
|
configurable: true
|
|
13861
13842
|
});
|
|
13862
13843
|
Object.defineProperty(AccountService.prototype, "department", {
|
|
13863
13844
|
get: function () {
|
|
13864
|
-
if (this.
|
|
13865
|
-
this.
|
|
13845
|
+
if (this._data.loaded && !this._data.department) {
|
|
13846
|
+
this._data.department = this._data.loaded ? this._data.account.asPerson().department : undefined;
|
|
13866
13847
|
}
|
|
13867
|
-
return this.
|
|
13848
|
+
return this._data.department;
|
|
13868
13849
|
},
|
|
13869
13850
|
enumerable: false,
|
|
13870
13851
|
configurable: true
|
|
@@ -13878,32 +13859,21 @@
|
|
|
13878
13859
|
console.info('[account] Using authentication token type: ' + value);
|
|
13879
13860
|
this._tokenType$.next(value);
|
|
13880
13861
|
// Reset values
|
|
13881
|
-
this.
|
|
13862
|
+
this._data.authToken = undefined;
|
|
13882
13863
|
this.onAuthTokenChange.next(undefined);
|
|
13883
|
-
this.
|
|
13864
|
+
this._data.authBasic = undefined;
|
|
13884
13865
|
this.onAuthBasicChange.next(undefined);
|
|
13885
13866
|
}
|
|
13886
13867
|
},
|
|
13887
13868
|
enumerable: false,
|
|
13888
13869
|
configurable: true
|
|
13889
13870
|
});
|
|
13890
|
-
AccountService.prototype.resetData = function () {
|
|
13891
|
-
this.data.loaded = false;
|
|
13892
|
-
this.data.keypair = null;
|
|
13893
|
-
this.data.authToken = null;
|
|
13894
|
-
this.data.authBasic = null;
|
|
13895
|
-
this.data.pubkey = null;
|
|
13896
|
-
this.data.mainProfile = null;
|
|
13897
|
-
this.data.account = new exports.Account();
|
|
13898
|
-
this.data.person = null;
|
|
13899
|
-
this.data.department = null;
|
|
13900
|
-
};
|
|
13901
13871
|
AccountService.prototype.start = function () {
|
|
13902
13872
|
var _this = this;
|
|
13903
13873
|
if (this._startPromise)
|
|
13904
13874
|
return this._startPromise;
|
|
13905
13875
|
if (this._started)
|
|
13906
|
-
return Promise.resolve();
|
|
13876
|
+
return Promise.resolve(this.account);
|
|
13907
13877
|
// Restoring local settings
|
|
13908
13878
|
this._startPromise = Promise.all([
|
|
13909
13879
|
this.settings.ready(),
|
|
@@ -13914,6 +13884,7 @@
|
|
|
13914
13884
|
.then(function () {
|
|
13915
13885
|
_this._started = true;
|
|
13916
13886
|
_this._startPromise = undefined;
|
|
13887
|
+
return _this.account;
|
|
13917
13888
|
});
|
|
13918
13889
|
return this._startPromise;
|
|
13919
13890
|
};
|
|
@@ -13931,8 +13902,8 @@
|
|
|
13931
13902
|
if (this._started || this._startPromise) {
|
|
13932
13903
|
this._started = false;
|
|
13933
13904
|
this._startPromise = undefined;
|
|
13934
|
-
hadAuthToken = this.
|
|
13935
|
-
hadAuthBasic = this.
|
|
13905
|
+
hadAuthToken = this._data.authToken && true;
|
|
13906
|
+
hadAuthBasic = this._data.authBasic && true;
|
|
13936
13907
|
hadAuth = hadAuthToken || hadAuthBasic;
|
|
13937
13908
|
this.resetData();
|
|
13938
13909
|
if (hadAuth) {
|
|
@@ -13962,35 +13933,35 @@
|
|
|
13962
13933
|
};
|
|
13963
13934
|
AccountService.prototype.ready = function () {
|
|
13964
13935
|
if (this._started)
|
|
13965
|
-
return Promise.resolve();
|
|
13936
|
+
return Promise.resolve(this.account);
|
|
13966
13937
|
return this.start();
|
|
13967
13938
|
};
|
|
13968
13939
|
AccountService.prototype.isLogin = function () {
|
|
13969
|
-
return !!(this.
|
|
13940
|
+
return !!(this._data.pubkey && this._data.loaded);
|
|
13970
13941
|
};
|
|
13971
13942
|
AccountService.prototype.isAuth = function () {
|
|
13972
|
-
return !!(this.
|
|
13943
|
+
return !!(this._data.pubkey && this._data.keypair && this._data.keypair.secretKey);
|
|
13973
13944
|
};
|
|
13974
13945
|
AccountService.prototype.hasMinProfile = function (userProfile) {
|
|
13975
13946
|
// should be login, and status ENABLE or TEMPORARY
|
|
13976
|
-
if (!this.
|
|
13977
|
-
(this.
|
|
13947
|
+
if (!this._data.account || !this._data.account.pubkey ||
|
|
13948
|
+
(this._data.account.statusId !== StatusIds.ENABLE && this._data.account.statusId !== StatusIds.TEMPORARY)) {
|
|
13978
13949
|
return false;
|
|
13979
13950
|
}
|
|
13980
|
-
return PersonUtils.hasUpperOrEqualsProfile(this.
|
|
13951
|
+
return PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, userProfile);
|
|
13981
13952
|
};
|
|
13982
13953
|
AccountService.prototype.hasExactProfile = function (label) {
|
|
13983
13954
|
// should be login, and status ENABLE or TEMPORARY
|
|
13984
|
-
if (!this.
|
|
13985
|
-
(this.
|
|
13955
|
+
if (!this._data.account || !this._data.account.pubkey ||
|
|
13956
|
+
(this._data.account.statusId !== StatusIds.ENABLE && this._data.account.statusId !== StatusIds.TEMPORARY))
|
|
13986
13957
|
return false;
|
|
13987
|
-
return this.
|
|
13958
|
+
return this._data.account.profiles.some(function (profile) { return profile === label; });
|
|
13988
13959
|
};
|
|
13989
13960
|
AccountService.prototype.hasProfileAndIsEnable = function (userProfile) {
|
|
13990
13961
|
// should be login, and status ENABLE
|
|
13991
|
-
if (!this.
|
|
13962
|
+
if (!this._data.account || !this._data.account.pubkey || this._data.account.statusId !== StatusIds.ENABLE)
|
|
13992
13963
|
return false;
|
|
13993
|
-
return PersonUtils.hasUpperOrEqualsProfile(this.
|
|
13964
|
+
return PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, userProfile);
|
|
13994
13965
|
};
|
|
13995
13966
|
AccountService.prototype.isAdmin = function () {
|
|
13996
13967
|
return this.hasProfileAndIsEnable('ADMIN');
|
|
@@ -14010,11 +13981,11 @@
|
|
|
14010
13981
|
};
|
|
14011
13982
|
AccountService.prototype.isOnlyGuest = function () {
|
|
14012
13983
|
// Should be login, and status ENABLE or TEMPORARY
|
|
14013
|
-
if (!this.
|
|
14014
|
-
(this.
|
|
13984
|
+
if (!this._data.account || !this._data.account.pubkey ||
|
|
13985
|
+
(this._data.account.statusId !== StatusIds.ENABLE && this._data.account.statusId !== StatusIds.TEMPORARY))
|
|
14015
13986
|
return false;
|
|
14016
13987
|
// Profile less then user
|
|
14017
|
-
return !PersonUtils.hasUpperOrEqualsProfile(this.
|
|
13988
|
+
return !PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, 'USER');
|
|
14018
13989
|
};
|
|
14019
13990
|
AccountService.prototype.canUserWriteDataForDepartment = function (recorderDepartment) {
|
|
14020
13991
|
if (ReferentialUtils.isEmpty(recorderDepartment)) {
|
|
@@ -14023,17 +13994,17 @@
|
|
|
14023
13994
|
return this.isAdmin();
|
|
14024
13995
|
}
|
|
14025
13996
|
// Should be login, and status ENABLE
|
|
14026
|
-
if (!this.
|
|
13997
|
+
if (!this._data.account || !this._data.account.pubkey || this._data.account.statusId !== StatusIds.ENABLE)
|
|
14027
13998
|
return false;
|
|
14028
|
-
if (!this.
|
|
13999
|
+
if (!this._data.account.department || !this._data.account.department.id) {
|
|
14029
14000
|
console.warn('User account has no department ! Unable to check write right against recorderDepartment');
|
|
14030
14001
|
return false;
|
|
14031
14002
|
}
|
|
14032
14003
|
// Same recorder department: OK, user can write
|
|
14033
|
-
if (this.
|
|
14004
|
+
if (this._data.account.department.id === recorderDepartment.id)
|
|
14034
14005
|
return true;
|
|
14035
14006
|
// Else, check if supervisor (or more)
|
|
14036
|
-
return PersonUtils.hasUpperOrEqualsProfile(this.
|
|
14007
|
+
return PersonUtils.hasUpperOrEqualsProfile(this._data.account.profiles, 'SUPERVISOR');
|
|
14037
14008
|
};
|
|
14038
14009
|
AccountService.prototype.register = function (data) {
|
|
14039
14010
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -14048,7 +14019,7 @@
|
|
|
14048
14019
|
throw new Error('Missing required username or password');
|
|
14049
14020
|
if (this._debug)
|
|
14050
14021
|
console.debug('[account] Register new user account...', data.account);
|
|
14051
|
-
this.
|
|
14022
|
+
this._data.loaded = false;
|
|
14052
14023
|
now = Date.now();
|
|
14053
14024
|
_b.label = 1;
|
|
14054
14025
|
case 1:
|
|
@@ -14062,29 +14033,29 @@
|
|
|
14062
14033
|
data.account.settings.locale = this.settings.locale;
|
|
14063
14034
|
data.account.settings.latLongFormat = this.settings.latLongFormat;
|
|
14064
14035
|
data.account.department.id = data.account.department.id || this.environment.defaultDepartmentId;
|
|
14065
|
-
this.
|
|
14036
|
+
this._data.keypair = keypair;
|
|
14066
14037
|
return [4 /*yield*/, this.saveRemotely(data.account, keypair)];
|
|
14067
14038
|
case 3:
|
|
14068
14039
|
account = _b.sent();
|
|
14069
14040
|
// Default values
|
|
14070
14041
|
account.avatar = account.avatar || (this.environment.baseUrl + DEFAULT_AVATAR_IMAGE);
|
|
14071
|
-
this.
|
|
14072
|
-
this.
|
|
14073
|
-
this.
|
|
14042
|
+
this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
|
|
14043
|
+
this._data.account = account;
|
|
14044
|
+
this._data.pubkey = account.pubkey;
|
|
14074
14045
|
// Try to auth on pod
|
|
14075
14046
|
return [4 /*yield*/, this.authenticate(data)];
|
|
14076
14047
|
case 4:
|
|
14077
14048
|
// Try to auth on pod
|
|
14078
14049
|
_b.sent();
|
|
14079
|
-
this.
|
|
14050
|
+
this._data.loaded = true;
|
|
14080
14051
|
return [4 /*yield*/, this.saveLocally()];
|
|
14081
14052
|
case 5:
|
|
14082
14053
|
_b.sent();
|
|
14083
14054
|
console.debug("[account] Account successfully registered in " + (Date.now() - now) + "ms");
|
|
14084
14055
|
// Emit events
|
|
14085
|
-
this.onLogin.next(this.
|
|
14086
|
-
this.onChange.next(this.
|
|
14087
|
-
return [2 /*return*/, this.
|
|
14056
|
+
this.onLogin.next(this._data.account);
|
|
14057
|
+
this.onChange.next(this._data.account);
|
|
14058
|
+
return [2 /*return*/, this._data.account];
|
|
14088
14059
|
case 6:
|
|
14089
14060
|
error_1 = _b.sent();
|
|
14090
14061
|
console.error(error_1 && error_1.message || error_1);
|
|
@@ -14106,22 +14077,22 @@
|
|
|
14106
14077
|
// Basic auth
|
|
14107
14078
|
if (tokenType === 'basic' || tokenType === 'basic-and-token') {
|
|
14108
14079
|
// Generate the authBasic, if used
|
|
14109
|
-
if (!this.
|
|
14080
|
+
if (!this._data.authBasic) {
|
|
14110
14081
|
// Skip if token already provided
|
|
14111
|
-
if (!(this.
|
|
14082
|
+
if (!(this._data.authToken && tokenType === 'basic-and-token')) {
|
|
14112
14083
|
if (!data || !data.username || !data.password)
|
|
14113
14084
|
throw new Error('Missing username and password');
|
|
14114
|
-
this.
|
|
14085
|
+
this._data.authBasic = this.cryptoService.encodeBase64(data.username + ":" + data.password);
|
|
14115
14086
|
}
|
|
14116
14087
|
}
|
|
14117
|
-
this.onAuthBasicChange.next(this.
|
|
14088
|
+
this.onAuthBasicChange.next(this._data.authBasic);
|
|
14118
14089
|
}
|
|
14119
14090
|
if (!(tokenType === 'token' || tokenType === 'basic-and-token')) return [3 /*break*/, 5];
|
|
14120
14091
|
_c.label = 2;
|
|
14121
14092
|
case 2:
|
|
14122
14093
|
_c.trys.push([2, 4, , 5]);
|
|
14123
|
-
_b = this.
|
|
14124
|
-
return [4 /*yield*/, this.authenticateAndGetToken(this.
|
|
14094
|
+
_b = this._data;
|
|
14095
|
+
return [4 /*yield*/, this.authenticateAndGetToken(this._data.authToken)];
|
|
14125
14096
|
case 3:
|
|
14126
14097
|
_b.authToken = _c.sent();
|
|
14127
14098
|
return [3 /*break*/, 5];
|
|
@@ -14134,7 +14105,7 @@
|
|
|
14134
14105
|
case 5:
|
|
14135
14106
|
// Forget authBasic, to switch to authToken
|
|
14136
14107
|
if (tokenType === 'basic-and-token') {
|
|
14137
|
-
this.
|
|
14108
|
+
this._data.authBasic = undefined;
|
|
14138
14109
|
this.onAuthBasicChange.next(undefined);
|
|
14139
14110
|
}
|
|
14140
14111
|
return [2 /*return*/];
|
|
@@ -14165,18 +14136,18 @@
|
|
|
14165
14136
|
throw { code: ErrorCodes$2.UNKNOWN_ERROR, message: 'ERROR.SCRYPT_ERROR' };
|
|
14166
14137
|
case 4:
|
|
14167
14138
|
// Store pubkey+keypair
|
|
14168
|
-
this.
|
|
14169
|
-
this.
|
|
14139
|
+
this._data.pubkey = Base58.encode(keypair.publicKey);
|
|
14140
|
+
this._data.keypair = keypair;
|
|
14170
14141
|
return [4 /*yield*/, this.storage.get(TOKEN_STORAGE_KEY)];
|
|
14171
14142
|
case 5:
|
|
14172
14143
|
previousToken = _b.sent();
|
|
14173
|
-
previousToken = previousToken && previousToken.startsWith(this.
|
|
14144
|
+
previousToken = previousToken && previousToken.startsWith(this._data.pubkey) && previousToken || null;
|
|
14174
14145
|
offline = this.settings.hasOfflineFeature() && (this.network.offline || data.offline === true);
|
|
14175
14146
|
if (!offline) return [3 /*break*/, 6];
|
|
14176
|
-
this.
|
|
14147
|
+
this._data.authToken = previousToken;
|
|
14177
14148
|
// Make sure network if set as offline
|
|
14178
14149
|
this.network.setForceOffline(true, { showToast: false });
|
|
14179
|
-
console.info("[account] Login [OK] {pubkey: " + this.
|
|
14150
|
+
console.info("[account] Login [OK] {pubkey: " + this._data.pubkey.substr(0, 8) + "}, {offline: true}");
|
|
14180
14151
|
return [3 /*break*/, 9];
|
|
14181
14152
|
case 6:
|
|
14182
14153
|
_b.trys.push([6, 8, , 9]);
|
|
@@ -14236,9 +14207,9 @@
|
|
|
14236
14207
|
throw error_5;
|
|
14237
14208
|
case 21:
|
|
14238
14209
|
// Emit event to observers
|
|
14239
|
-
this.onLogin.next(this.
|
|
14240
|
-
this.onChange.next(this.
|
|
14241
|
-
return [2 /*return*/, this.
|
|
14210
|
+
this.onLogin.next(this._data.account);
|
|
14211
|
+
this.onChange.next(this._data.account);
|
|
14212
|
+
return [2 /*return*/, this._data.account];
|
|
14242
14213
|
}
|
|
14243
14214
|
});
|
|
14244
14215
|
});
|
|
@@ -14248,7 +14219,7 @@
|
|
|
14248
14219
|
return __generator(this, function (_b) {
|
|
14249
14220
|
switch (_b.label) {
|
|
14250
14221
|
case 0:
|
|
14251
|
-
if (!this.
|
|
14222
|
+
if (!this._data.pubkey)
|
|
14252
14223
|
throw new Error('User not logged');
|
|
14253
14224
|
if (this.network.offline)
|
|
14254
14225
|
throw new Error('Cannot check account in offline mode');
|
|
@@ -14260,9 +14231,9 @@
|
|
|
14260
14231
|
_b.sent();
|
|
14261
14232
|
console.debug('[account] Successfully reload account');
|
|
14262
14233
|
// Emit login event to subscribers
|
|
14263
|
-
this.onLogin.next(this.
|
|
14264
|
-
this.onChange.next(this.
|
|
14265
|
-
return [2 /*return*/, this.
|
|
14234
|
+
this.onLogin.next(this._data.account);
|
|
14235
|
+
this.onChange.next(this._data.account);
|
|
14236
|
+
return [2 /*return*/, this._data.account];
|
|
14266
14237
|
}
|
|
14267
14238
|
});
|
|
14268
14239
|
});
|
|
@@ -14277,27 +14248,27 @@
|
|
|
14277
14248
|
return __generator(this, function (_b) {
|
|
14278
14249
|
switch (_b.label) {
|
|
14279
14250
|
case 0:
|
|
14280
|
-
if (!this.
|
|
14251
|
+
if (!this._data.pubkey)
|
|
14281
14252
|
return [2 /*return*/, Promise.reject('User not logged')];
|
|
14282
|
-
if (this.
|
|
14253
|
+
if (this._data.pubkey !== account.pubkey)
|
|
14283
14254
|
return [2 /*return*/, Promise.reject('Not user account')];
|
|
14284
|
-
return [4 /*yield*/, this.saveRemotely(account, this.
|
|
14255
|
+
return [4 /*yield*/, this.saveRemotely(account, this._data.keypair)];
|
|
14285
14256
|
case 1:
|
|
14286
14257
|
account = _b.sent();
|
|
14287
14258
|
// Set defaults
|
|
14288
14259
|
account.avatar = account.avatar || (this.environment.baseUrl + DEFAULT_AVATAR_IMAGE);
|
|
14289
|
-
this.
|
|
14290
|
-
this.
|
|
14291
|
-
this.
|
|
14260
|
+
this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
|
|
14261
|
+
this._data.account = account;
|
|
14262
|
+
this._data.loaded = true;
|
|
14292
14263
|
// Save locally (in storage)
|
|
14293
14264
|
return [4 /*yield*/, this.saveLocally()];
|
|
14294
14265
|
case 2:
|
|
14295
14266
|
// Save locally (in storage)
|
|
14296
14267
|
_b.sent();
|
|
14297
14268
|
// Send event
|
|
14298
|
-
this.onLogin.next(this.
|
|
14299
|
-
this.onChange.next(this.
|
|
14300
|
-
return [2 /*return*/, this.
|
|
14269
|
+
this.onLogin.next(this._data.account);
|
|
14270
|
+
this.onChange.next(this._data.account);
|
|
14271
|
+
return [2 /*return*/, this._data.account];
|
|
14301
14272
|
}
|
|
14302
14273
|
});
|
|
14303
14274
|
});
|
|
@@ -14308,9 +14279,9 @@
|
|
|
14308
14279
|
return __generator(this, function (_b) {
|
|
14309
14280
|
switch (_b.label) {
|
|
14310
14281
|
case 0:
|
|
14311
|
-
hadAuthToken = this.
|
|
14312
|
-
hadAuthBasic = this.
|
|
14313
|
-
pubkey = this.
|
|
14282
|
+
hadAuthToken = this._data.authToken && true;
|
|
14283
|
+
hadAuthBasic = this._data.authBasic && true;
|
|
14284
|
+
pubkey = this._data && this._data.pubkey;
|
|
14314
14285
|
this.resetData();
|
|
14315
14286
|
if (!!this.settings.hasOfflineFeature()) return [3 /*break*/, 2];
|
|
14316
14287
|
// Remove all data from the local storage
|
|
@@ -14382,9 +14353,9 @@
|
|
|
14382
14353
|
case 1:
|
|
14383
14354
|
json = _b.sent();
|
|
14384
14355
|
json = json && (typeof json === 'string') && JSON.parse(json) || json;
|
|
14385
|
-
json = json && this.
|
|
14386
|
-
if (!(!json && this.
|
|
14387
|
-
return [4 /*yield*/, this.storage.get(ACCOUNT_STORAGE_KEY + '#' + this.
|
|
14356
|
+
json = json && this._data.pubkey && (json.pubkey === this._data.pubkey) && json || null;
|
|
14357
|
+
if (!(!json && this._data.pubkey)) return [3 /*break*/, 3];
|
|
14358
|
+
return [4 /*yield*/, this.storage.get(ACCOUNT_STORAGE_KEY + '#' + this._data.pubkey)];
|
|
14388
14359
|
case 2:
|
|
14389
14360
|
json = _b.sent();
|
|
14390
14361
|
json = json && (typeof json === 'string') && JSON.parse(json) || json;
|
|
@@ -14515,7 +14486,8 @@
|
|
|
14515
14486
|
});
|
|
14516
14487
|
};
|
|
14517
14488
|
AccountService.prototype.listenChanges = function () {
|
|
14518
|
-
|
|
14489
|
+
var _this = this;
|
|
14490
|
+
if (!this._data.pubkey)
|
|
14519
14491
|
return rxjs.Subscription.EMPTY;
|
|
14520
14492
|
var self = this;
|
|
14521
14493
|
console.debug('[account] [WS] Listening account changes');
|
|
@@ -14531,15 +14503,14 @@
|
|
|
14531
14503
|
}).subscribe({
|
|
14532
14504
|
next: function (_b) {
|
|
14533
14505
|
var data = _b.data;
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
var existingUpdateDate;
|
|
14506
|
+
return __awaiter(_this, void 0, void 0, function () {
|
|
14507
|
+
var _a, existingUpdateDate;
|
|
14537
14508
|
return __generator(this, function (_b) {
|
|
14538
14509
|
switch (_b.label) {
|
|
14539
14510
|
case 0:
|
|
14540
14511
|
if (!data)
|
|
14541
14512
|
return [2 /*return*/];
|
|
14542
|
-
existingUpdateDate = toDateISOString((_a = self.
|
|
14513
|
+
existingUpdateDate = toDateISOString((_a = self._data.account) === null || _a === void 0 ? void 0 : _a.updateDate);
|
|
14543
14514
|
if (!(existingUpdateDate !== data.updateDate)) return [3 /*break*/, 2];
|
|
14544
14515
|
console.debug("[account] [WS] Detected update on {" + data.updateDate + "}");
|
|
14545
14516
|
return [4 /*yield*/, self.refresh()];
|
|
@@ -14551,32 +14522,30 @@
|
|
|
14551
14522
|
});
|
|
14552
14523
|
});
|
|
14553
14524
|
},
|
|
14554
|
-
error: function (err) {
|
|
14555
|
-
return
|
|
14556
|
-
|
|
14557
|
-
|
|
14558
|
-
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
|
|
14562
|
-
|
|
14563
|
-
|
|
14564
|
-
|
|
14565
|
-
|
|
14566
|
-
|
|
14567
|
-
|
|
14568
|
-
|
|
14569
|
-
|
|
14570
|
-
|
|
14571
|
-
|
|
14572
|
-
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
}
|
|
14577
|
-
});
|
|
14525
|
+
error: function (err) { return __awaiter(_this, void 0, void 0, function () {
|
|
14526
|
+
return __generator(this, function (_b) {
|
|
14527
|
+
switch (_b.label) {
|
|
14528
|
+
case 0:
|
|
14529
|
+
if (!(err && +err.code === ServerErrorCodes.NOT_FOUND)) return [3 /*break*/, 2];
|
|
14530
|
+
console.info('[account] Account not exists anymore: force user to logout...', err);
|
|
14531
|
+
return [4 /*yield*/, self.logout()];
|
|
14532
|
+
case 1:
|
|
14533
|
+
_b.sent();
|
|
14534
|
+
return [3 /*break*/, 5];
|
|
14535
|
+
case 2:
|
|
14536
|
+
if (!(err && +err.code === ServerErrorCodes.UNAUTHORIZED)) return [3 /*break*/, 4];
|
|
14537
|
+
console.info('[account] Account not authorized: force user to logout...', err);
|
|
14538
|
+
return [4 /*yield*/, self.logout()];
|
|
14539
|
+
case 3:
|
|
14540
|
+
_b.sent();
|
|
14541
|
+
return [3 /*break*/, 5];
|
|
14542
|
+
case 4:
|
|
14543
|
+
console.warn('[account] [WS] Received error:', err);
|
|
14544
|
+
_b.label = 5;
|
|
14545
|
+
case 5: return [2 /*return*/];
|
|
14546
|
+
}
|
|
14578
14547
|
});
|
|
14579
|
-
},
|
|
14548
|
+
}); },
|
|
14580
14549
|
complete: function () {
|
|
14581
14550
|
console.debug('[account] [WS] Completed');
|
|
14582
14551
|
}
|
|
@@ -14633,15 +14602,26 @@
|
|
|
14633
14602
|
this._$additionalFields.next(values.concat(field));
|
|
14634
14603
|
};
|
|
14635
14604
|
/* -- protected method -- */
|
|
14605
|
+
AccountService.prototype.resetData = function () {
|
|
14606
|
+
this._data.loaded = false;
|
|
14607
|
+
this._data.keypair = null;
|
|
14608
|
+
this._data.authToken = null;
|
|
14609
|
+
this._data.authBasic = null;
|
|
14610
|
+
this._data.pubkey = null;
|
|
14611
|
+
this._data.mainProfile = null;
|
|
14612
|
+
this._data.account = new exports.Account();
|
|
14613
|
+
this._data.person = null;
|
|
14614
|
+
this._data.department = null;
|
|
14615
|
+
};
|
|
14636
14616
|
AccountService.prototype.loadData = function (opts) {
|
|
14637
14617
|
return __awaiter(this, void 0, void 0, function () {
|
|
14638
14618
|
var account, error_6;
|
|
14639
14619
|
return __generator(this, function (_b) {
|
|
14640
14620
|
switch (_b.label) {
|
|
14641
14621
|
case 0:
|
|
14642
|
-
if (!this.
|
|
14622
|
+
if (!this._data.pubkey)
|
|
14643
14623
|
throw new Error('User not logged');
|
|
14644
|
-
this.
|
|
14624
|
+
this._data.loaded = false;
|
|
14645
14625
|
_b.label = 1;
|
|
14646
14626
|
case 1:
|
|
14647
14627
|
_b.trys.push([1, 3, , 4]);
|
|
@@ -14654,16 +14634,16 @@
|
|
|
14654
14634
|
account.settings.locale = account.settings.locale || this.settings.locale;
|
|
14655
14635
|
account.settings.latLongFormat = account.settings.latLongFormat || this.settings.latLongFormat || 'DDMM';
|
|
14656
14636
|
// Read main profile
|
|
14657
|
-
this.
|
|
14637
|
+
this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
|
|
14658
14638
|
// Update, instead of replace it
|
|
14659
|
-
if (this.
|
|
14660
|
-
this.
|
|
14639
|
+
if (this._data.account) {
|
|
14640
|
+
this._data.account.fromObject(account);
|
|
14661
14641
|
}
|
|
14662
14642
|
else {
|
|
14663
|
-
this.
|
|
14643
|
+
this._data.account = account;
|
|
14664
14644
|
}
|
|
14665
|
-
this.
|
|
14666
|
-
return [2 /*return*/, this.
|
|
14645
|
+
this._data.loaded = true;
|
|
14646
|
+
return [2 /*return*/, this._data.account];
|
|
14667
14647
|
case 3:
|
|
14668
14648
|
error_6 = _b.sent();
|
|
14669
14649
|
this.resetData();
|
|
@@ -14702,9 +14682,9 @@
|
|
|
14702
14682
|
return [2 /*return*/];
|
|
14703
14683
|
if (this._debug)
|
|
14704
14684
|
console.debug("[account] Account restoration...");
|
|
14705
|
-
this.
|
|
14706
|
-
this.
|
|
14707
|
-
this.
|
|
14685
|
+
this._data.authToken = token;
|
|
14686
|
+
this._data.pubkey = pubkey;
|
|
14687
|
+
this._data.keypair = seckey && {
|
|
14708
14688
|
publicKey: Base58.decode(pubkey),
|
|
14709
14689
|
secretKey: Base58.decode(seckey)
|
|
14710
14690
|
} || null;
|
|
@@ -14715,7 +14695,7 @@
|
|
|
14715
14695
|
return [4 /*yield*/, this.authenticate()];
|
|
14716
14696
|
case 3:
|
|
14717
14697
|
_b.sent();
|
|
14718
|
-
if (!this.
|
|
14698
|
+
if (!this._data.authToken && !this._data.authBasic)
|
|
14719
14699
|
throw new Error('Authentication failed');
|
|
14720
14700
|
return [3 /*break*/, 5];
|
|
14721
14701
|
case 4:
|
|
@@ -14748,14 +14728,14 @@
|
|
|
14748
14728
|
return [2 /*return*/];
|
|
14749
14729
|
account = exports.Account.fromObject(jsonAccount);
|
|
14750
14730
|
// Update data
|
|
14751
|
-
this.
|
|
14752
|
-
this.
|
|
14753
|
-
this.
|
|
14731
|
+
this._data.account = account;
|
|
14732
|
+
this._data.mainProfile = PersonUtils.getMainProfile(account.profiles);
|
|
14733
|
+
this._data.loaded = true;
|
|
14754
14734
|
// Emit event
|
|
14755
|
-
this.onLogin.next(this.
|
|
14756
|
-
this.onChange.next(this.
|
|
14735
|
+
this.onLogin.next(this._data.account);
|
|
14736
|
+
this.onChange.next(this._data.account);
|
|
14757
14737
|
if (this._debug)
|
|
14758
|
-
console.debug("[account] Account restoration [OK] {pubkey: " + pubkey.substr(0, 8) + "}, {profile: " + this.
|
|
14738
|
+
console.debug("[account] Account restoration [OK] {pubkey: " + pubkey.substr(0, 8) + "}, {profile: " + this._data.mainProfile + "}");
|
|
14759
14739
|
return [2 /*return*/, account];
|
|
14760
14740
|
}
|
|
14761
14741
|
});
|
|
@@ -14771,12 +14751,12 @@
|
|
|
14771
14751
|
return __generator(this, function (_b) {
|
|
14772
14752
|
switch (_b.label) {
|
|
14773
14753
|
case 0:
|
|
14774
|
-
if (!this.
|
|
14754
|
+
if (!this._data.pubkey)
|
|
14775
14755
|
throw new Error('User not logged');
|
|
14776
14756
|
if (this._debug)
|
|
14777
|
-
console.debug("[account] Saving account {" + this.
|
|
14778
|
-
json = this.
|
|
14779
|
-
seckey = this.
|
|
14757
|
+
console.debug("[account] Saving account {" + this._data.pubkey.substring(0, 6) + "} in local storage...");
|
|
14758
|
+
json = this._data.account.asObject({ keepTypename: true });
|
|
14759
|
+
seckey = this._data.keypair && this._data.keypair.secretKey && Base58.encode(this._data.keypair.secretKey) || null;
|
|
14780
14760
|
hasAvatarUrl = json.avatar && !json.avatar.endsWith(DEFAULT_AVATAR_IMAGE) &&
|
|
14781
14761
|
(json.avatar.startsWith('http://') || (json.avatar.startsWith('https://')));
|
|
14782
14762
|
if (!(hasAvatarUrl && this.network.online)) return [3 /*break*/, 2];
|
|
@@ -14799,9 +14779,9 @@
|
|
|
14799
14779
|
case 2:
|
|
14800
14780
|
_b.trys.push([2, 4, , 5]);
|
|
14801
14781
|
return [4 /*yield*/, Promise.all([
|
|
14802
|
-
this.storage.set(PUBKEY_STORAGE_KEY, this.
|
|
14803
|
-
this.storage.set(TOKEN_STORAGE_KEY, this.
|
|
14804
|
-
this.storage.set(ACCOUNT_STORAGE_KEY + "#" + this.
|
|
14782
|
+
this.storage.set(PUBKEY_STORAGE_KEY, this._data.pubkey),
|
|
14783
|
+
this.storage.set(TOKEN_STORAGE_KEY, this._data.authToken),
|
|
14784
|
+
this.storage.set(ACCOUNT_STORAGE_KEY + "#" + this._data.pubkey, json),
|
|
14805
14785
|
// Secret key (optional)
|
|
14806
14786
|
seckey && this.storage.set(SECKEY_STORAGE_KEY, seckey) || this.storage.remove(SECKEY_STORAGE_KEY),
|
|
14807
14787
|
// Remove old storage key
|
|
@@ -14878,7 +14858,7 @@
|
|
|
14878
14858
|
return __generator(this, function (_b) {
|
|
14879
14859
|
switch (_b.label) {
|
|
14880
14860
|
case 0:
|
|
14881
|
-
if (!this.
|
|
14861
|
+
if (!this._data.pubkey)
|
|
14882
14862
|
throw new Error('User not logged');
|
|
14883
14863
|
if (!counter)
|
|
14884
14864
|
console.info('[account] Authentication on pod...');
|
|
@@ -14905,7 +14885,7 @@
|
|
|
14905
14885
|
if (data_1 && data_1.authenticate) {
|
|
14906
14886
|
// Store the token
|
|
14907
14887
|
this.onAuthTokenChange.next(token);
|
|
14908
|
-
console.info("[account] Authentication on pod [OK] {pubkey: '" + this.
|
|
14888
|
+
console.info("[account] Authentication on pod [OK] {pubkey: '" + this._data.pubkey.substr(0, 8) + "'}");
|
|
14909
14889
|
return [2 /*return*/, token]; // return the token
|
|
14910
14890
|
}
|
|
14911
14891
|
_b.label = 2;
|
|
@@ -14931,10 +14911,10 @@
|
|
|
14931
14911
|
if (!signatureOK) {
|
|
14932
14912
|
console.warn('FIXME: Bad peer signature on auth challenge !', data.authChallenge);
|
|
14933
14913
|
}
|
|
14934
|
-
return [4 /*yield*/, this.cryptoService.sign(data.authChallenge.challenge, this.
|
|
14914
|
+
return [4 /*yield*/, this.cryptoService.sign(data.authChallenge.challenge, this._data.keypair)];
|
|
14935
14915
|
case 5:
|
|
14936
14916
|
signature = _b.sent();
|
|
14937
|
-
newToken = this.
|
|
14917
|
+
newToken = this._data.pubkey + ":" + data.authChallenge.challenge + "|" + signature;
|
|
14938
14918
|
return [4 /*yield*/, this.authenticateAndGetToken(newToken, (counter || 1) + 1 /* increment */)];
|
|
14939
14919
|
case 6:
|
|
14940
14920
|
// iterate with the new token
|
|
@@ -15264,9 +15244,8 @@
|
|
|
15264
15244
|
Object.defineProperty(ConfigService.prototype, "config", {
|
|
15265
15245
|
get: function () {
|
|
15266
15246
|
// If first call: start loading
|
|
15267
|
-
if (!this._started)
|
|
15247
|
+
if (!this._started)
|
|
15268
15248
|
this.start();
|
|
15269
|
-
}
|
|
15270
15249
|
return this.$data.pipe(operators.filter(isNotNil));
|
|
15271
15250
|
},
|
|
15272
15251
|
enumerable: false,
|
|
@@ -15281,30 +15260,49 @@
|
|
|
15281
15260
|
console.info('[config] Starting configuration...');
|
|
15282
15261
|
this._startPromise = this.graphql.ready()
|
|
15283
15262
|
.then(function () { return _this.loadOrRestoreLocally(); })
|
|
15284
|
-
.then(function () {
|
|
15263
|
+
.then(function (data) {
|
|
15285
15264
|
_this._started = true;
|
|
15286
15265
|
_this._startPromise = undefined;
|
|
15266
|
+
_this.$data.next(data);
|
|
15267
|
+
return data;
|
|
15287
15268
|
})
|
|
15288
15269
|
.catch(function (err) {
|
|
15289
15270
|
console.error(err && err.message || err, err);
|
|
15271
|
+
_this._started = false;
|
|
15290
15272
|
_this._startPromise = undefined;
|
|
15273
|
+
return null;
|
|
15291
15274
|
});
|
|
15292
15275
|
return this._startPromise;
|
|
15293
15276
|
};
|
|
15294
15277
|
ConfigService.prototype.stop = function () {
|
|
15295
|
-
this
|
|
15296
|
-
|
|
15297
|
-
|
|
15298
|
-
|
|
15278
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
15279
|
+
return __generator(this, function (_a) {
|
|
15280
|
+
this._subscription.unsubscribe();
|
|
15281
|
+
this._subscription = new rxjs.Subscription();
|
|
15282
|
+
this._started = false;
|
|
15283
|
+
this._startPromise = undefined;
|
|
15284
|
+
return [2 /*return*/];
|
|
15285
|
+
});
|
|
15286
|
+
});
|
|
15299
15287
|
};
|
|
15300
15288
|
ConfigService.prototype.restart = function () {
|
|
15301
|
-
|
|
15302
|
-
this
|
|
15303
|
-
|
|
15289
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
15290
|
+
return __generator(this, function (_a) {
|
|
15291
|
+
switch (_a.label) {
|
|
15292
|
+
case 0:
|
|
15293
|
+
if (!this.started) return [3 /*break*/, 2];
|
|
15294
|
+
return [4 /*yield*/, this.stop()];
|
|
15295
|
+
case 1:
|
|
15296
|
+
_a.sent();
|
|
15297
|
+
_a.label = 2;
|
|
15298
|
+
case 2: return [2 /*return*/, this.start()];
|
|
15299
|
+
}
|
|
15300
|
+
});
|
|
15301
|
+
});
|
|
15304
15302
|
};
|
|
15305
15303
|
ConfigService.prototype.ready = function () {
|
|
15306
15304
|
if (this._started)
|
|
15307
|
-
return Promise.resolve();
|
|
15305
|
+
return Promise.resolve(this.$data.value);
|
|
15308
15306
|
if (this._startPromise)
|
|
15309
15307
|
return this._startPromise;
|
|
15310
15308
|
return this.start();
|
|
@@ -15375,7 +15373,7 @@
|
|
|
15375
15373
|
return [4 /*yield*/, this.loadDefault({ fetchPolicy: 'network-only' })];
|
|
15376
15374
|
case 2:
|
|
15377
15375
|
reloadedConfig = _a.sent();
|
|
15378
|
-
defaultConfig = this.$data.
|
|
15376
|
+
defaultConfig = this.$data.value;
|
|
15379
15377
|
if (isNotNil(defaultConfig) && reloadedConfig.label === defaultConfig.label) {
|
|
15380
15378
|
// Emit update event when is default config
|
|
15381
15379
|
this.$data.next(reloadedConfig);
|
|
@@ -15484,8 +15482,7 @@
|
|
|
15484
15482
|
if (wasJustLoaded) {
|
|
15485
15483
|
// TODO
|
|
15486
15484
|
}
|
|
15487
|
-
|
|
15488
|
-
return [2 /*return*/];
|
|
15485
|
+
return [2 /*return*/, data];
|
|
15489
15486
|
}
|
|
15490
15487
|
});
|
|
15491
15488
|
});
|
|
@@ -15738,7 +15735,7 @@
|
|
|
15738
15735
|
.then(function () {
|
|
15739
15736
|
_this._started = true;
|
|
15740
15737
|
_this._startPromise = undefined;
|
|
15741
|
-
console.info("[platform] Starting platform [OK] {mobile: " + _this._mobile + ", touchUi: " + _this.touchUi + "
|
|
15738
|
+
console.info("[platform] Starting platform [OK] {mobile: " + _this._mobile + ", touchUi: " + _this.touchUi + ", downloader: " + !!_this.downloader + " in " + (Date.now() - now) + "ms");
|
|
15742
15739
|
// Update cache configuration when network changed
|
|
15743
15740
|
_this.networkService.onNetworkStatusChanges.subscribe(function (type) { return _this.configureCache(type !== 'none'); });
|
|
15744
15741
|
// Update authentication type
|
|
@@ -15787,18 +15784,37 @@
|
|
|
15787
15784
|
}
|
|
15788
15785
|
};
|
|
15789
15786
|
PlatformService.prototype.download = function (request) {
|
|
15790
|
-
|
|
15791
|
-
|
|
15792
|
-
|
|
15793
|
-
|
|
15794
|
-
|
|
15795
|
-
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
|
|
15801
|
-
|
|
15787
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
15788
|
+
var downloader, location, err_1;
|
|
15789
|
+
return __generator(this, function (_a) {
|
|
15790
|
+
switch (_a.label) {
|
|
15791
|
+
case 0:
|
|
15792
|
+
if (!request || !request.uri)
|
|
15793
|
+
throw new Error('Missing argument \'request\' or \'request.uri\'');
|
|
15794
|
+
downloader = this.downloader || window.plugins.Downloader;
|
|
15795
|
+
if (!(downloader && this._android && this._cordova)) return [3 /*break*/, 5];
|
|
15796
|
+
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) });
|
|
15797
|
+
_a.label = 1;
|
|
15798
|
+
case 1:
|
|
15799
|
+
_a.trys.push([1, 3, , 4]);
|
|
15800
|
+
return [4 /*yield*/, downloader.download(request)];
|
|
15801
|
+
case 2:
|
|
15802
|
+
location = _a.sent();
|
|
15803
|
+
console.info('[platform] File successfully downloaded at:' + location);
|
|
15804
|
+
return [2 /*return*/, location];
|
|
15805
|
+
case 3:
|
|
15806
|
+
err_1 = _a.sent();
|
|
15807
|
+
console.error('[platform] Error while downloading: ' + (err_1 && err_1.message || err_1), err_1);
|
|
15808
|
+
throw err_1;
|
|
15809
|
+
case 4: return [3 /*break*/, 6];
|
|
15810
|
+
case 5:
|
|
15811
|
+
console.warn('[platform] Cannot use Cordova downloader: using browser open()');
|
|
15812
|
+
this.open(request.uri, '_system', 'location=no', true);
|
|
15813
|
+
return [2 /*return*/, undefined];
|
|
15814
|
+
case 6: return [2 /*return*/];
|
|
15815
|
+
}
|
|
15816
|
+
});
|
|
15817
|
+
});
|
|
15802
15818
|
};
|
|
15803
15819
|
/* -- protected methods -- */
|
|
15804
15820
|
PlatformService.prototype.configureCordovaPlugins = function (mobile) {
|
|
@@ -15894,7 +15910,7 @@
|
|
|
15894
15910
|
};
|
|
15895
15911
|
PlatformService.prototype.migrateStorage = function (forage) {
|
|
15896
15912
|
return __awaiter(this, void 0, void 0, function () {
|
|
15897
|
-
var canMigrate, oldForage, keys, now, toast_1, duration,
|
|
15913
|
+
var canMigrate, oldForage, keys, now, toast_1, duration, err_2;
|
|
15898
15914
|
return __generator(this, function (_a) {
|
|
15899
15915
|
switch (_a.label) {
|
|
15900
15916
|
case 0:
|
|
@@ -15947,8 +15963,8 @@
|
|
|
15947
15963
|
_a.sent();
|
|
15948
15964
|
return [3 /*break*/, 12];
|
|
15949
15965
|
case 9:
|
|
15950
|
-
|
|
15951
|
-
console.error(
|
|
15966
|
+
err_2 = _a.sent();
|
|
15967
|
+
console.error(err_2 && err_2.message || err_2, err_2);
|
|
15952
15968
|
return [4 /*yield*/, toast_1.dismiss()];
|
|
15953
15969
|
case 10:
|
|
15954
15970
|
_a.sent();
|
|
@@ -17594,7 +17610,7 @@
|
|
|
17594
17610
|
AutocompleteTestPage.decorators = [
|
|
17595
17611
|
{ type: i0.Component, args: [{
|
|
17596
17612
|
selector: 'app-autocomplete-test',
|
|
17597
|
-
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Autocomplete field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <!-- Tab nav - mobile/desktop mode -->\n <nav mat-tab-nav-bar>\n <a mat-tab-link\n [active]=\"mode==='mobile'\"\n (click)=\"toggleMode('mobile')\">\n <mat-label>Mobile</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='desktop'\"\n (click)=\"toggleMode('desktop')\">\n <mat-label>Desktop</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='memory'\"\n (click)=\"toggleMode('memory')\">\n <mat-label>Memory leak debug</mat-label>\n </a>\n <a mat-tab-link\n [active]=\"mode==='temp'\"\n (click)=\"toggleMode('temp')\">\n <mat-label>Temporary</mat-label>\n </a>\n </nav>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <!--<ion-grid *ngIf=\"mode === 'temp'\">\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n </ion-grid>-->\n\n\n <ion-grid *ngIf=\"mode === 'memory'\">\n\n <!-- debugging memory leak -->\n <ion-row><ion-col><ion-text><h4>Debug memory leak</h4></ion-text></ion-col></ion-row>\n <ion-row>\n <ion-col size=\"2\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Items type\">\n <mat-select (selectionChange)=\"memoryAutocompleteFieldName=$event.value\" [value]=\"memoryAutocompleteFieldName\">\n <mat-option value=\"entity-$items\">Observable</mat-option>\n <mat-option value=\"entity-suggestFn\">Suggest function</mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n <ion-col size=\"1\" class=\"ion-no-padding\">\n <mat-form-field floatLabel=\"always\" >\n <input matInput type=\"text\" hidden placeholder=\"Mobile ?\">\n <mat-checkbox (change)=\"memoryMobile=$event.checked\" [checked]=\"memoryMobile\">\n </mat-checkbox>\n </mat-form-field>\n </ion-col>\n\n <ion-col size=\"2\">\n <ion-button *ngIf=\"!memoryTimer\" (click)=\"startMemoryTimer()\" color=\"tertiary\">Start</ion-button>\n <ion-button *ngIf=\"memoryTimer\" (click)=\"stopMemoryTimer()\" color=\"tertiary\">Stop</ion-button>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n *ngIf=\"!memoryHide && memoryAutocompleteFieldName\"\n [config]=\"autocompleteFields.get(memoryAutocompleteFieldName)\"\n [mobile]=\"memoryMobile\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-memory-leak]'\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <!-- Mobile mode -->\n <ion-grid *ngIf=\"mode === 'mobile'\">\n\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-1]'\"\n [required]=\"true\"\n placeholder=\"Suggest field\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Items is an Observable\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>mobile: true, items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-observable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>mobile: true, items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Change filter\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <ion-button (click)=\"updateFilter('entity-items-filter')\">Filter on: {{autocompleteFields.get('entity-items-filter').filter?.searchAttribute }}</ion-button>\n </ion-col>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-filter]'\"\n ></mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>class=\"min-width-large\"</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"true\"\n class=\"min-width-large\"\n panelWidth=\"400px\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Desktop mode -->\n <ion-grid *ngIf=\"mode === 'desktop'\">\n <ion-row>\n <ion-col><ion-text><h4>Desktop mode</h4></ion-text></ion-col>\n </ion-row>\n <ion-row>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n items from suggest function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult<any>\nsuggestLengthThreshold: '3'</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggest]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an array\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [logPrefix]=\"'[combo-desktop-array-1]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-missing]'\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size panel\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>class: 'mat-autocomplete-panel-full-size'</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [compareWith]=\"compareWithFn\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-disable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\" >\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>class=\"mat-autocomplete-panel-full-size\"</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n class=\"mat-autocomplete-panel-full-size\"\n panelWidth=\"100vw\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\" >\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>panelWidth: string</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n panelWidth=\"400px\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n </mat-checkbox>\n\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\">\n </mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
|
|
17613
|
+
template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Autocomplete field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n\n <!-- Tab nav - mobile/desktop mode -->\n <nav mat-tab-nav-bar>\n <a mat-tab-link\n [active]=\"mode==='mobile'\"\n (click)=\"toggleMode('mobile')\">\n <mat-label>Mobile</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='desktop'\"\n (click)=\"toggleMode('desktop')\">\n <mat-label>Desktop</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='memory'\"\n (click)=\"toggleMode('memory')\">\n <mat-label>Memory leak debug</mat-label>\n </a>\n <a mat-tab-link\n [active]=\"mode==='temp'\"\n (click)=\"toggleMode('temp')\">\n <mat-label>Temporary</mat-label>\n </a>\n </nav>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <!--<ion-grid *ngIf=\"mode === 'temp'\">\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n </ion-grid>-->\n\n\n <ion-grid *ngIf=\"mode === 'memory'\">\n\n <!-- debugging memory leak -->\n <ion-row><ion-col><ion-text><h4>Debug memory leak</h4></ion-text></ion-col></ion-row>\n <ion-row>\n <ion-col size=\"2\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Items type\">\n <mat-select (selectionChange)=\"memoryAutocompleteFieldName=$event.value\" [value]=\"memoryAutocompleteFieldName\">\n <mat-option value=\"entity-$items\">Observable</mat-option>\n <mat-option value=\"entity-suggestFn\">Suggest function</mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n <ion-col size=\"1\" class=\"ion-no-padding\">\n <mat-form-field floatLabel=\"always\" >\n <input matInput type=\"text\" hidden placeholder=\"Mobile ?\">\n <mat-checkbox (change)=\"memoryMobile=$event.checked\" [checked]=\"memoryMobile\">\n </mat-checkbox>\n </mat-form-field>\n </ion-col>\n\n <ion-col size=\"2\">\n <ion-button *ngIf=\"!memoryTimer\" (click)=\"startMemoryTimer()\" color=\"tertiary\">Start</ion-button>\n <ion-button *ngIf=\"memoryTimer\" (click)=\"stopMemoryTimer()\" color=\"tertiary\">Stop</ion-button>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n *ngIf=\"!memoryHide && memoryAutocompleteFieldName\"\n [config]=\"autocompleteFields.get(memoryAutocompleteFieldName)\"\n [mobile]=\"memoryMobile\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-memory-leak]'\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <!-- Mobile mode -->\n <ion-grid *ngIf=\"mode === 'mobile'\">\n\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-1]'\"\n [required]=\"true\"\n placeholder=\"Suggest field\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Items is an Observable\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>mobile: true, items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-observable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>mobile: true, items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Change filter\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <ion-button (click)=\"updateFilter('entity-items-filter')\">Filter on: {{autocompleteFields.get('entity-items-filter').filter?.searchAttribute }}</ion-button>\n </ion-col>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-filter]'\"\n ></mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>class=\"min-width-large\"</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"true\"\n class=\"min-width-large\"\n panelWidth=\"400px\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Desktop mode -->\n <ion-grid *ngIf=\"mode === 'desktop'\">\n <ion-row>\n <ion-col><ion-text><h4>Desktop mode</h4></ion-text></ion-col>\n </ion-row>\n <ion-row>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n items from suggest function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult<any>\nsuggestLengthThreshold: '3'</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggest]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an array\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [logPrefix]=\"'[combo-desktop-array-1]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable<any[]></pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-missing]'\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size panel\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>class: 'mat-autocomplete-panel-full-size'</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [compareWith]=\"compareWithFn\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-disable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\" >\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>class=\"mat-autocomplete-panel-full-size\"</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n class=\"mat-autocomplete-panel-full-size\"\n panelWidth=\"100vw\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\" >\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>panelWidth: string</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n panelWidth=\"400px\"\n [compareWith]=\"compareWithFn\"\n [logPrefix]=\"'[combo-desktop-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
|
|
17598
17614
|
},] }
|
|
17599
17615
|
];
|
|
17600
17616
|
AutocompleteTestPage.ctorParameters = function () { return [
|
|
@@ -21331,6 +21347,7 @@
|
|
|
21331
21347
|
AppInstallUpgradeCard.prototype.downloadLink = function (event, link) {
|
|
21332
21348
|
if (!link || !link.url)
|
|
21333
21349
|
return; // Skip
|
|
21350
|
+
console.info("[install-upgrade-card] Downloading '" + link.url + "' ...");
|
|
21334
21351
|
this.platform.download({
|
|
21335
21352
|
uri: link.url,
|
|
21336
21353
|
filename: link.downloadFilename,
|
|
@@ -21377,15 +21394,20 @@
|
|
|
21377
21394
|
};
|
|
21378
21395
|
AppInstallUpgradeCard.prototype.getCompatibleUpgradeLinks = function (installLinks, config) {
|
|
21379
21396
|
var _this = this;
|
|
21380
|
-
var
|
|
21381
|
-
var
|
|
21397
|
+
var appVersion = this.environment.version;
|
|
21398
|
+
var appMinVersionFromPod = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
|
|
21399
|
+
if (!appVersion) {
|
|
21400
|
+
console.error('Missing value for \'environment.version\': cannot check app compatibility!');
|
|
21401
|
+
return undefined;
|
|
21402
|
+
}
|
|
21403
|
+
var needUpgrade = appMinVersionFromPod && !VersionUtils.isCompatible(appMinVersionFromPod, appVersion);
|
|
21382
21404
|
if (!needUpgrade)
|
|
21383
21405
|
return undefined;
|
|
21384
21406
|
var upgradeLinks = installLinks
|
|
21385
21407
|
.filter(function (link) { return _this.platform.is('mobileweb') || (link.platform && _this.platform.is(link.platform)); });
|
|
21386
21408
|
// Use min version as default version
|
|
21387
21409
|
upgradeLinks.forEach(function (link) {
|
|
21388
|
-
link.version = link.version ||
|
|
21410
|
+
link.version = link.version || appMinVersionFromPod;
|
|
21389
21411
|
});
|
|
21390
21412
|
return isNotEmptyArray(upgradeLinks) ? upgradeLinks : undefined;
|
|
21391
21413
|
};
|
|
@@ -21397,6 +21419,7 @@
|
|
|
21397
21419
|
var url = config.getProperty(CORE_CONFIG_OPTIONS.ANDROID_INSTALL_URL);
|
|
21398
21420
|
if (isNilOrBlank(url))
|
|
21399
21421
|
url = this.environment.defaultAndroidInstallUrl || null;
|
|
21422
|
+
var minVersion = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
|
|
21400
21423
|
// Compute App name
|
|
21401
21424
|
var name = isNotNilOrBlank(url) && config.label || this.environment.defaultAppName || 'SUMARiS';
|
|
21402
21425
|
if (url) {
|
|
@@ -21405,7 +21428,7 @@
|
|
|
21405
21428
|
var mimeType = void 0;
|
|
21406
21429
|
// Get file name
|
|
21407
21430
|
var filename = this.getFilename(url);
|
|
21408
|
-
version =
|
|
21431
|
+
version = minVersion || 'latest';
|
|
21409
21432
|
// OK, this is a downloadable APK file (e.g. NOT a link to a playstore)
|
|
21410
21433
|
if (filename === null || filename === void 0 ? void 0 : filename.endsWith('.apk')) {
|
|
21411
21434
|
// Define mime type
|
|
@@ -21415,13 +21438,12 @@
|
|
|
21415
21438
|
version = versionMatches && versionMatches[1] || version;
|
|
21416
21439
|
// Compute a new file name, with the version
|
|
21417
21440
|
if (isNotNilOrBlank(name)) {
|
|
21418
|
-
downloadFilename = name + "-" + version + ".apk";
|
|
21441
|
+
downloadFilename = (name + "-v" + version + ".apk").toLowerCase();
|
|
21419
21442
|
}
|
|
21420
21443
|
else {
|
|
21421
21444
|
downloadFilename = filename;
|
|
21422
|
-
// Replace 'latest' with the app
|
|
21445
|
+
// Replace 'latest' with the app version, if present
|
|
21423
21446
|
if (downloadFilename.indexOf('latest')) {
|
|
21424
|
-
version = config.getProperty(CORE_CONFIG_OPTIONS.APP_MIN_VERSION);
|
|
21425
21447
|
downloadFilename = downloadFilename.replace('latest', version);
|
|
21426
21448
|
}
|
|
21427
21449
|
}
|
|
@@ -27155,6 +27177,7 @@
|
|
|
27155
27177
|
_this.filterCriteriaCount = 0;
|
|
27156
27178
|
_this.statusList = StatusList;
|
|
27157
27179
|
_this.statusById = StatusById;
|
|
27180
|
+
_this.useSticky = false;
|
|
27158
27181
|
_this.referentialToString = referentialToString;
|
|
27159
27182
|
_this.inlineEdition = accountService.isAdmin(); // Allow inline edition only if admin
|
|
27160
27183
|
_this.canEdit = accountService.isAdmin();
|
|
@@ -27273,13 +27296,13 @@
|
|
|
27273
27296
|
UsersPage.decorators = [
|
|
27274
27297
|
{ type: i0.Component, args: [{
|
|
27275
27298
|
selector: 'app-users-table',
|
|
27276
|
-
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 >=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 >=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",
|
|
27299
|
+
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 >=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 >=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",
|
|
27277
27300
|
providers: [
|
|
27278
27301
|
{ provide: ngxMaterialTable.ValidatorService, useExisting: PersonValidatorService }
|
|
27279
27302
|
],
|
|
27280
27303
|
animations: [slideUpDownAnimation],
|
|
27281
27304
|
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
27282
|
-
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-avatar{min-width:
|
|
27305
|
+
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}"]
|
|
27283
27306
|
},] }
|
|
27284
27307
|
];
|
|
27285
27308
|
UsersPage.ctorParameters = function () { return [
|
|
@@ -27299,6 +27322,7 @@
|
|
|
27299
27322
|
{ type: undefined, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] }
|
|
27300
27323
|
]; };
|
|
27301
27324
|
UsersPage.propDecorators = {
|
|
27325
|
+
useSticky: [{ type: i0.Input }],
|
|
27302
27326
|
filterExpansionPanel: [{ type: i0.ViewChild, args: [expansion.MatExpansionPanel, { static: true },] }]
|
|
27303
27327
|
};
|
|
27304
27328
|
|
|
@@ -27572,6 +27596,7 @@
|
|
|
27572
27596
|
exports.SharedTestingModule = SharedTestingModule;
|
|
27573
27597
|
exports.SharedValidators = SharedValidators;
|
|
27574
27598
|
exports.SocialModule = SocialModule;
|
|
27599
|
+
exports.StartableService = StartableService;
|
|
27575
27600
|
exports.StatusById = StatusById;
|
|
27576
27601
|
exports.StatusIds = StatusIds;
|
|
27577
27602
|
exports.StatusList = StatusList;
|