@sumaris-net/ngx-components 1.19.4 → 1.19.5-rc1

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.
@@ -15680,6 +15680,196 @@ ConfigService.ctorParameters = () => [
15680
15680
  { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [APP_CONFIG_OPTIONS,] }] }
15681
15681
  ];
15682
15682
 
15683
+ class UploadFile extends File {
15684
+ }
15685
+ class FileResponse {
15686
+ constructor(init) {
15687
+ this.type = HttpEventType.Response;
15688
+ this.body = isNotNil(init === null || init === void 0 ? void 0 : init.body) ? init.body : null;
15689
+ this.status = (init === null || init === void 0 ? void 0 : init.status) || 0;
15690
+ this.statusText = (init === null || init === void 0 ? void 0 : init.statusText) || 'OK';
15691
+ }
15692
+ }
15693
+ function isProgressEvent(event) {
15694
+ return event && (event.type === HttpEventType.UploadProgress
15695
+ || event.type === HttpEventType.DownloadProgress);
15696
+ }
15697
+ function isResponseEvent(event) {
15698
+ return event && event.type === HttpEventType.Response;
15699
+ }
15700
+
15701
+ class UploadFilePopover {
15702
+ constructor(popoverController, translate, cd) {
15703
+ this.popoverController = popoverController;
15704
+ this.translate = translate;
15705
+ this.cd = cd;
15706
+ this.uniqueFile = false;
15707
+ this.instantUpload = false;
15708
+ this.importing = false;
15709
+ }
15710
+ get files() {
15711
+ return this.uploader.files;
15712
+ }
15713
+ get disabled() {
15714
+ return this.importing || isEmptyArray(this.files);
15715
+ }
15716
+ get valid() {
15717
+ return isNotEmptyArray(this.files);
15718
+ }
15719
+ onValidate(event) {
15720
+ return __awaiter(this, void 0, void 0, function* () {
15721
+ event === null || event === void 0 ? void 0 : event.stopPropagation();
15722
+ // Avoid multiple call
15723
+ if (this.importing)
15724
+ return;
15725
+ console.debug('[upload-file-popover] Validate form: will upload all files...');
15726
+ try {
15727
+ this.importing = true;
15728
+ this.resetError();
15729
+ try {
15730
+ // Wait processing files finished
15731
+ yield this.uploader.waitIdle();
15732
+ // upload all files
15733
+ yield this.uploader.uploadFiles();
15734
+ const files = (this.uploader.processedFiles || [])
15735
+ .filter(file => !file.deleting); // Remove deleting file (deletion in progress)
15736
+ // Nothing to upload: close popover
15737
+ if (isEmptyArray(files))
15738
+ return this.cancel();
15739
+ // check errors
15740
+ const errors = files.map(file => file.error).filter(isNotNilOrBlank);
15741
+ // If error: stop
15742
+ if (errors.length) {
15743
+ errors.forEach((error) => console.error(error));
15744
+ throw { message: 'FILE.UPLOAD.ERROR' };
15745
+ }
15746
+ // return files
15747
+ yield this.popoverController.dismiss(files);
15748
+ }
15749
+ catch (err) {
15750
+ this.error = (err && err.message) || err;
15751
+ }
15752
+ }
15753
+ finally {
15754
+ this.importing = false;
15755
+ this.cd.markForCheck();
15756
+ }
15757
+ });
15758
+ }
15759
+ cancel() {
15760
+ return this.popoverController.dismiss();
15761
+ }
15762
+ resetError() {
15763
+ if (this.error) {
15764
+ this.error = null;
15765
+ this.cd.markForCheck();
15766
+ }
15767
+ }
15768
+ }
15769
+ UploadFilePopover.decorators = [
15770
+ { type: Component, args: [{
15771
+ selector: 'app-upload-file-popover',
15772
+ template: "\n<ion-content class=\"ion-no-padding\" scrollY=\"false\">\n <div class=\"modal-content\">\n <app-upload-file\n #uploader\n [uploadFn]=\"uploadFn\"\n [deleteFn]=\"deleteFn\"\n [fileExtension]=\"fileExtension\"\n [instantUpload]=\"instantUpload\"\n [uniqueFile]=\"uniqueFile\"\n [maxParallelUpload]=\"maxParallelUpload\"\n ></app-upload-file>\n </div>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n <div *ngIf=\"importing\" class=\"importing-info\">\n <ion-text color=\"medium\"><small translate>FILE.UPLOAD.IMPORTING</small></ion-text>\n &nbsp;<ion-spinner name=\"dots\" color=\"accent\"></ion-spinner>\n </div>\n <ion-item *ngIf=\"error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"ion-text-wrap\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel()\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"onValidate($event)\"\n (keyup.enter)=\"onValidate($event)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n >\n <ion-label translate>COMMON.BTN_IMPORT</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n",
15773
+ encapsulation: ViewEncapsulation.None,
15774
+ changeDetection: ChangeDetectionStrategy.OnPush,
15775
+ styles: [".importing-info{-webkit-padding-start:var(--ion-padding);padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}"]
15776
+ },] }
15777
+ ];
15778
+ UploadFilePopover.ctorParameters = () => [
15779
+ { type: PopoverController },
15780
+ { type: TranslateService },
15781
+ { type: ChangeDetectorRef }
15782
+ ];
15783
+ UploadFilePopover.propDecorators = {
15784
+ uploader: [{ type: ViewChild, args: ['uploader', { static: true },] }],
15785
+ fileExtension: [{ type: Input }],
15786
+ title: [{ type: Input }],
15787
+ uniqueFile: [{ type: Input }],
15788
+ instantUpload: [{ type: Input }],
15789
+ uploadFn: [{ type: Input }],
15790
+ deleteFn: [{ type: Input }],
15791
+ maxParallelUpload: [{ type: Input }]
15792
+ };
15793
+
15794
+ const MimeTypes = Object.freeze({
15795
+ ANDROID_APK: 'application/vnd.android.package-archive'
15796
+ });
15797
+ class FilesUtils {
15798
+ static showUploadPopover(popoverController, event, opts) {
15799
+ return __awaiter(this, void 0, void 0, function* () {
15800
+ const modal = yield popoverController.create({
15801
+ component: UploadFilePopover,
15802
+ componentProps: opts,
15803
+ backdropDismiss: false,
15804
+ keyboardClose: false,
15805
+ event,
15806
+ translucent: true,
15807
+ cssClass: 'popover-large',
15808
+ });
15809
+ yield modal.present();
15810
+ const { data, role } = yield modal.onDidDismiss();
15811
+ return {
15812
+ role,
15813
+ data: data ? data : undefined
15814
+ };
15815
+ });
15816
+ }
15817
+ static readAsText(file, encoding) {
15818
+ const $progress = new Subject();
15819
+ const reader = new FileReader();
15820
+ encoding = (encoding || 'UTF-8').toLowerCase();
15821
+ // Listen progress
15822
+ reader.onprogress = (e) => {
15823
+ const total = e.total || 1;
15824
+ const loaded = e.total || 0;
15825
+ if (loaded < total)
15826
+ $progress.next({ type: HttpEventType.UploadProgress, loaded, total });
15827
+ };
15828
+ // Listen end
15829
+ reader.onloadend = (e) => {
15830
+ const body = reader.result;
15831
+ if (typeof body === 'string') {
15832
+ $progress.next(new FileResponse({ body }));
15833
+ $progress.complete();
15834
+ }
15835
+ else {
15836
+ console.error(`Cannot read file '${file.name}' as text`);
15837
+ $progress.error(`Cannot read file as text`);
15838
+ }
15839
+ };
15840
+ // Listen error
15841
+ reader.onerror = (event) => {
15842
+ console.error('[files] Error while reading file:', event);
15843
+ $progress.error(event);
15844
+ };
15845
+ // Start reading the file
15846
+ reader.readAsText(file, encoding);
15847
+ return $progress.asObservable();
15848
+ }
15849
+ }
15850
+ class UriUtils {
15851
+ /**
15852
+ * Extract the filename, from an uri (using the last slash)
15853
+ * @param uri
15854
+ */
15855
+ static getFilename(uri) {
15856
+ if (!uri)
15857
+ return uri;
15858
+ let filename = uri.trim();
15859
+ // Get last part (or all string, if no '/')
15860
+ const lastSlashIndex = filename.lastIndexOf('/');
15861
+ if (lastSlashIndex !== -1 && lastSlashIndex !== uri.length - 1) {
15862
+ filename = filename.substring(lastSlashIndex + 1);
15863
+ }
15864
+ // Remove query params
15865
+ const queryParamIndex = filename.indexOf('?');
15866
+ if (queryParamIndex !== -1) {
15867
+ filename = filename.substring(0, queryParamIndex);
15868
+ }
15869
+ return filename;
15870
+ }
15871
+ }
15872
+
15683
15873
  const moment$4 = momentImported;
15684
15874
  const AndroidOsEnvironment = Object.freeze({
15685
15875
  DIRECTORY_DOWNLOADS: 'Download',
@@ -15840,34 +16030,48 @@ class PlatformService extends StartableService {
15840
16030
  return this._downloadingJobs.get(uri);
15841
16031
  }
15842
16032
  download(request) {
16033
+ var _a, _b;
15843
16034
  if (!request || !request.uri)
15844
16035
  throw new Error('Missing argument \'request\' or \'request.uri\'');
15845
16036
  if (this._android && this.downloader) {
15846
16037
  // Check if not already downloading file
15847
- let location$ = this._downloadingJobs.get(request.uri);
15848
- if (location$)
15849
- return location$;
15850
- request = Object.assign(Object.assign({ visibleInDownloadsUi: true, notificationVisibility: NotificationVisibility.VisibleNotifyCompleted, title: request.title || request.filename }, request), { destinationInExternalPublicDir: Object.assign({ dirType: AndroidOsEnvironment.DIRECTORY_DOWNLOADS, subPath: request.filename || request.title || '' }, request.destinationInExternalPublicDir) });
15851
- console.debug('[platform] Downloading, using request: ' + JSON.stringify(request));
16038
+ let job$ = this._downloadingJobs.get(request.uri);
16039
+ if (job$)
16040
+ return job$;
16041
+ // Compute subPath (final filename)
16042
+ let subPath = ((_a = request.destinationInExternalPublicDir) === null || _a === void 0 ? void 0 : _a.subPath) || ((_b = request.destinationInExternalFilesDir) === null || _b === void 0 ? void 0 : _b.subPath)
16043
+ || request.filename || UriUtils.getFilename(request.uri)
16044
+ || request.title || 'download';
16045
+ subPath = subPath.toLowerCase()
16046
+ // Remove spaces
16047
+ .replace(/\s+/g, '-');
16048
+ // Force APK to finish with '.apk'
16049
+ if (request.mimeType === MimeTypes.ANDROID_APK && !subPath.toLowerCase().endsWith('.apk')) {
16050
+ subPath += '.apk';
16051
+ }
16052
+ const downloadRequest = Object.assign(Object.assign({ visibleInDownloadsUi: true, notificationVisibility: NotificationVisibility.VisibleNotifyCompleted }, request), { filename: undefined, destinationInExternalPublicDir: !request.destinationInExternalFilesDir
16053
+ ? Object.assign(Object.assign({ dirType: AndroidOsEnvironment.DIRECTORY_DOWNLOADS }, request.destinationInExternalPublicDir), { subPath }) : undefined, destinationInExternalFilesDir: request.destinationInExternalFilesDir
16054
+ ? Object.assign(Object.assign({ dirType: AndroidOsEnvironment.DIRECTORY_DOWNLOADS }, request.destinationInExternalFilesDir), { subPath }) : undefined });
15852
16055
  // Start download
15853
- location$ = from(this.downloader.download(request));
16056
+ console.debug('[platform] Downloading, using request: ' + JSON.stringify(downloadRequest));
16057
+ job$ = from(this.downloader.download(downloadRequest));
15854
16058
  // Remember this request uri
15855
- this._downloadingJobs.set(request.uri, location$);
15856
- return location$
16059
+ this._downloadingJobs.set(downloadRequest.uri, job$);
16060
+ return job$
15857
16061
  .pipe(tap(location => {
15858
16062
  console.info('[platform] File successfully downloaded at:' + location);
15859
- // Forget the request
15860
- this._downloadingJobs.delete(request.uri);
16063
+ // Forget job
16064
+ this._downloadingJobs.delete(downloadRequest.uri);
15861
16065
  return location;
15862
16066
  }), catchError(err => {
15863
16067
  var _a;
15864
16068
  console.error('[platform] Unable to download: ' + (err && err.message || err));
15865
16069
  // Forget the request
15866
- this._downloadingJobs.delete(request.uri);
16070
+ this._downloadingJobs.delete(downloadRequest.uri);
15867
16071
  // Retry with another location - issue in older Android version
15868
- if (((_a = request.destinationInExternalPublicDir) === null || _a === void 0 ? void 0 : _a.dirType) === AndroidOsEnvironment.DIRECTORY_DOWNLOADS) {
15869
- request.destinationInExternalPublicDir.dirType = AndroidOsEnvironment.DIRECTORY_DOWNLOADS_OLD;
15870
- return this.download(request);
16072
+ if (((_a = downloadRequest.destinationInExternalPublicDir) === null || _a === void 0 ? void 0 : _a.dirType) === AndroidOsEnvironment.DIRECTORY_DOWNLOADS) {
16073
+ downloadRequest.destinationInExternalPublicDir.dirType = AndroidOsEnvironment.DIRECTORY_DOWNLOADS_OLD;
16074
+ return this.download(downloadRequest);
15871
16075
  }
15872
16076
  throw err;
15873
16077
  }));
@@ -16219,24 +16423,6 @@ MatStepperI18n.ctorParameters = () => [
16219
16423
  { type: TranslateService }
16220
16424
  ];
16221
16425
 
16222
- class UploadFile extends File {
16223
- }
16224
- class FileResponse {
16225
- constructor(init) {
16226
- this.type = HttpEventType.Response;
16227
- this.body = isNotNil(init === null || init === void 0 ? void 0 : init.body) ? init.body : null;
16228
- this.status = (init === null || init === void 0 ? void 0 : init.status) || 0;
16229
- this.statusText = (init === null || init === void 0 ? void 0 : init.statusText) || 'OK';
16230
- }
16231
- }
16232
- function isProgressEvent(event) {
16233
- return event && (event.type === HttpEventType.UploadProgress
16234
- || event.type === HttpEventType.DownloadProgress);
16235
- }
16236
- function isResponseEvent(event) {
16237
- return event && event.type === HttpEventType.Response;
16238
- }
16239
-
16240
16426
  class UploadFileComponent {
16241
16427
  constructor(cd, translate) {
16242
16428
  this.cd = cd;
@@ -16431,99 +16617,6 @@ UploadFileComponent.propDecorators = {
16431
16617
  maxParallelUpload: [{ type: Input }]
16432
16618
  };
16433
16619
 
16434
- class UploadFilePopover {
16435
- constructor(popoverController, translate, cd) {
16436
- this.popoverController = popoverController;
16437
- this.translate = translate;
16438
- this.cd = cd;
16439
- this.uniqueFile = false;
16440
- this.instantUpload = false;
16441
- this.importing = false;
16442
- }
16443
- get files() {
16444
- return this.uploader.files;
16445
- }
16446
- get disabled() {
16447
- return this.importing || isEmptyArray(this.files);
16448
- }
16449
- get valid() {
16450
- return isNotEmptyArray(this.files);
16451
- }
16452
- onValidate(event) {
16453
- return __awaiter(this, void 0, void 0, function* () {
16454
- event === null || event === void 0 ? void 0 : event.stopPropagation();
16455
- // Avoid multiple call
16456
- if (this.importing)
16457
- return;
16458
- console.debug('[upload-file-popover] Validate form: will upload all files...');
16459
- try {
16460
- this.importing = true;
16461
- this.resetError();
16462
- try {
16463
- // Wait processing files finished
16464
- yield this.uploader.waitIdle();
16465
- // upload all files
16466
- yield this.uploader.uploadFiles();
16467
- const files = (this.uploader.processedFiles || [])
16468
- .filter(file => !file.deleting); // Remove deleting file (deletion in progress)
16469
- // Nothing to upload: close popover
16470
- if (isEmptyArray(files))
16471
- return this.cancel();
16472
- // check errors
16473
- const errors = files.map(file => file.error).filter(isNotNilOrBlank);
16474
- // If error: stop
16475
- if (errors.length) {
16476
- errors.forEach((error) => console.error(error));
16477
- throw { message: 'FILE.UPLOAD.ERROR' };
16478
- }
16479
- // return files
16480
- yield this.popoverController.dismiss(files);
16481
- }
16482
- catch (err) {
16483
- this.error = (err && err.message) || err;
16484
- }
16485
- }
16486
- finally {
16487
- this.importing = false;
16488
- this.cd.markForCheck();
16489
- }
16490
- });
16491
- }
16492
- cancel() {
16493
- return this.popoverController.dismiss();
16494
- }
16495
- resetError() {
16496
- if (this.error) {
16497
- this.error = null;
16498
- this.cd.markForCheck();
16499
- }
16500
- }
16501
- }
16502
- UploadFilePopover.decorators = [
16503
- { type: Component, args: [{
16504
- selector: 'app-upload-file-popover',
16505
- template: "\n<ion-content class=\"ion-no-padding\" scrollY=\"false\">\n <div class=\"modal-content\">\n <app-upload-file\n #uploader\n [uploadFn]=\"uploadFn\"\n [deleteFn]=\"deleteFn\"\n [fileExtension]=\"fileExtension\"\n [instantUpload]=\"instantUpload\"\n [uniqueFile]=\"uniqueFile\"\n [maxParallelUpload]=\"maxParallelUpload\"\n ></app-upload-file>\n </div>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n <div *ngIf=\"importing\" class=\"importing-info\">\n <ion-text color=\"medium\"><small translate>FILE.UPLOAD.IMPORTING</small></ion-text>\n &nbsp;<ion-spinner name=\"dots\" color=\"accent\"></ion-spinner>\n </div>\n <ion-item *ngIf=\"error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"ion-text-wrap\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel()\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"onValidate($event)\"\n (keyup.enter)=\"onValidate($event)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n >\n <ion-label translate>COMMON.BTN_IMPORT</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n",
16506
- encapsulation: ViewEncapsulation.None,
16507
- changeDetection: ChangeDetectionStrategy.OnPush,
16508
- styles: [".importing-info{-webkit-padding-start:var(--ion-padding);padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}"]
16509
- },] }
16510
- ];
16511
- UploadFilePopover.ctorParameters = () => [
16512
- { type: PopoverController },
16513
- { type: TranslateService },
16514
- { type: ChangeDetectorRef }
16515
- ];
16516
- UploadFilePopover.propDecorators = {
16517
- uploader: [{ type: ViewChild, args: ['uploader', { static: true },] }],
16518
- fileExtension: [{ type: Input }],
16519
- title: [{ type: Input }],
16520
- uniqueFile: [{ type: Input }],
16521
- instantUpload: [{ type: Input }],
16522
- uploadFn: [{ type: Input }],
16523
- deleteFn: [{ type: Input }],
16524
- maxParallelUpload: [{ type: Input }]
16525
- };
16526
-
16527
16620
  const APP_TESTING_PAGES = new InjectionToken('testingPages');
16528
16621
  class SharedTestsPage {
16529
16622
  constructor(route, router, translate, pages) {
@@ -17859,60 +17952,6 @@ class JobUtils {
17859
17952
  }
17860
17953
  }
17861
17954
 
17862
- class FilesUtils {
17863
- static showUploadPopover(popoverController, event, opts) {
17864
- return __awaiter(this, void 0, void 0, function* () {
17865
- const modal = yield popoverController.create({
17866
- component: UploadFilePopover,
17867
- componentProps: opts,
17868
- backdropDismiss: false,
17869
- keyboardClose: false,
17870
- event,
17871
- translucent: true,
17872
- cssClass: 'popover-large',
17873
- });
17874
- yield modal.present();
17875
- const { data, role } = yield modal.onDidDismiss();
17876
- return {
17877
- role,
17878
- data: data ? data : undefined
17879
- };
17880
- });
17881
- }
17882
- static readAsText(file, encoding) {
17883
- const $progress = new Subject();
17884
- const reader = new FileReader();
17885
- encoding = (encoding || 'UTF-8').toLowerCase();
17886
- // Listen progress
17887
- reader.onprogress = (e) => {
17888
- const total = e.total || 1;
17889
- const loaded = e.total || 0;
17890
- if (loaded < total)
17891
- $progress.next({ type: HttpEventType.UploadProgress, loaded, total });
17892
- };
17893
- // Listen end
17894
- reader.onloadend = (e) => {
17895
- const body = reader.result;
17896
- if (typeof body === 'string') {
17897
- $progress.next(new FileResponse({ body }));
17898
- $progress.complete();
17899
- }
17900
- else {
17901
- console.error(`Cannot read file '${file.name}' as text`);
17902
- $progress.error(`Cannot read file as text`);
17903
- }
17904
- };
17905
- // Listen error
17906
- reader.onerror = (event) => {
17907
- console.error('[files] Error while reading file:', event);
17908
- $progress.error(event);
17909
- };
17910
- // Start reading the file
17911
- reader.readAsText(file, encoding);
17912
- return $progress.asObservable();
17913
- }
17914
- }
17915
-
17916
17955
  /**
17917
17956
  * Define here theme colors
17918
17957
  */
@@ -20141,9 +20180,6 @@ PersonToStringPipe.decorators = [
20141
20180
  { type: Injectable, args: [{ providedIn: 'root' },] }
20142
20181
  ];
20143
20182
 
20144
- const MimeTypes = Object.freeze({
20145
- ANDROID_APK: 'application/vnd.android.package-archive'
20146
- });
20147
20183
  class AppInstallUpgradeCard {
20148
20184
  constructor(modalCtrl, configService, toastController, alertController, translate, cd, platform, network, environment) {
20149
20185
  this.modalCtrl = modalCtrl;
@@ -20348,10 +20384,10 @@ class AppInstallUpgradeCard {
20348
20384
  let title;
20349
20385
  let mimeType;
20350
20386
  // Get file name
20351
- let filename = this.getFilename(url);
20387
+ let filename = UriUtils.getFilename(url);
20352
20388
  let version = minVersion || 'latest';
20353
20389
  // OK, this is a downloadable APK file (e.g. NOT a link to a playstore)
20354
- if (filename === null || filename === void 0 ? void 0 : filename.endsWith('.apk')) {
20390
+ if (filename === null || filename === void 0 ? void 0 : filename.toLowerCase().endsWith('.apk')) {
20355
20391
  // Define mime type
20356
20392
  mimeType = MimeTypes.ANDROID_APK;
20357
20393
  // Get the file version (if any)
@@ -20362,11 +20398,9 @@ class AppInstallUpgradeCard {
20362
20398
  filename = `${name}-v${version}.apk`.toLowerCase();
20363
20399
  title = `${name} v${version}`;
20364
20400
  }
20365
- else {
20366
- // Replace 'latest' with the app version, if present
20367
- if (filename.indexOf('latest')) {
20368
- filename = filename.replace('latest', version);
20369
- }
20401
+ // Replace 'latest' with the app version, if present in the filename
20402
+ else if (filename.indexOf('latest') && version !== 'latest') {
20403
+ filename = filename.replace('latest', version);
20370
20404
  }
20371
20405
  }
20372
20406
  result.push({ name, url, platform: 'android', version, filename, title, mimeType });
@@ -20378,18 +20412,6 @@ class AppInstallUpgradeCard {
20378
20412
  //}
20379
20413
  return result;
20380
20414
  }
20381
- getFilename(url) {
20382
- if (!url)
20383
- return;
20384
- // Get last part (or all string, if no '/')
20385
- let filename = url.substring(url.lastIndexOf('/') + 1);
20386
- const queryParamIndex = filename.indexOf('?');
20387
- if (queryParamIndex !== -1) {
20388
- // Remove query params
20389
- return filename.substring(0, queryParamIndex);
20390
- }
20391
- return filename;
20392
- }
20393
20415
  listenDownloadJobs() {
20394
20416
  // Listening downloading promise, if exists
20395
20417
  (this.upgradeLinks || []).forEach(link => {
@@ -21877,9 +21899,11 @@ class EntitiesTableDataSource extends TableDataSource {
21877
21899
  console.warn('Cannot fetch more because still editing row');
21878
21900
  return;
21879
21901
  }
21902
+ // Forget the fetchMore function, to avoid multiple call
21903
+ const fetchMoreFn = this._fetchMoreFn;
21904
+ this._fetchMoreFn = null;
21880
21905
  // Fetch next page
21881
- this._fetchMoreFn = null; // Avoid multiple call
21882
- const res = yield this._fetchMoreFn();
21906
+ const res = yield fetchMoreFn();
21883
21907
  // Skip if empty (no more data)
21884
21908
  if (isNotEmptyArray(res === null || res === void 0 ? void 0 : res.data))
21885
21909
  return false;
@@ -27502,5 +27526,5 @@ CoreTestingModule.decorators = [
27502
27526
  * Generated bundle index. Do not edit.
27503
27527
  */
27504
27528
 
27505
- export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_MENU_ITEMS, APP_TESTING_PAGES, AboutModal, Account, AccountPage, AccountService, AccountToStringPipe, ActionsColumnComponent, AdminModule, AdminRoutingModule, Alerts, AndroidOsEnvironment, AnimationState, AppEditor, AppEditorOptions, AppEntityEditor, AppForm, AppFormField, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppInMemoryTable, AppInstallUpgradeCard, AppListForm, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppTabEditor, AppTabEditorOptions, AppTable, AppTableDataSourceOptions, AppTableUtils, AppValidatorService, AppendToInputDirective, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayLengthPipe, ArrayPluckPipe, AudioProvider, AuthForm, AuthGuardService, AuthModal, AutocompleteTestPage, AutofocusDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, DATE_ISO_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFromNowPipe, DateTimeTestPage, DateUtils, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesService, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, Fragments$1 as Fragments, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, InMemoryEntitiesService, IsLoginAccountPipe, IsNilOrBlankPipe, IsNotNilOrBlankPipe, IsNotOnFieldModePipe, IsOnFieldModePipe, JobUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LongitudeFormatPipe, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MapGetPipe, MapKeysPipe, MapValuesPipe, MatAutocompleteConfigHolder, MatAutocompleteField, MatBadgeIconDirective, MatBooleanField, MatChipsField, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatNumpadComponent, MatNumpadContainerComponent, MatNumpadContent, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItems, MenuService, Message, MessageFilter, MessageForm, MessageModal, MessageService, MessageTypeList, MessageTypes, ModalToolbarComponent, NetworkService, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, NumpadDirective, OddPipe, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SelectPeerModal, SettingsPage, SharedAsyncValidators, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBadgeIconModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatNumpadModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedValidators, SocialErrorCodes, SocialModule, Software, StartableService, StatusById, StatusIds, StatusList, StrIncludesPipe, StrLengthPipe, SwipeTestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TextForm, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, Toasts, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UserEvent, UserEventFilter, UserEventFragments, UserEventService, UserEventTypes, UserEventsTable, UserSettings, UsersPage, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayGroupBy, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, fadeInAnimation, fadeInOutAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, hexToRgb, hexToRgbArray, isAndroid, isBlankString, isControlHasInput, isCordova, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, noTrailingSlash, notNilOrDefault, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputRange, setCalculatedValue, setTabIndex, sleep, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForTrue, waitIdle, waitWhilePending, ɵ0, CustomReuseStrategy as ɵa, MatNumpadDomService as ɵb, isFocusableElement as ɵc, RegisterForm as ɵd, AccountValidatorService as ɵe, RegisterModal as ɵf, UserSettingsValidatorService as ɵg, LocalSettingsValidatorService as ɵh, AppIconComponent as ɵi, DateTestPage as ɵj, NumpadTestPage as ɵk, MatBadgeIconTestPage as ɵl, ToastTestingModule as ɵm, ToastTestingPage as ɵn };
27529
+ export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_MENU_ITEMS, APP_TESTING_PAGES, AboutModal, Account, AccountPage, AccountService, AccountToStringPipe, ActionsColumnComponent, AdminModule, AdminRoutingModule, Alerts, AndroidOsEnvironment, AnimationState, AppEditor, AppEditorOptions, AppEntityEditor, AppForm, AppFormField, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppInMemoryTable, AppInstallUpgradeCard, AppListForm, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppTabEditor, AppTabEditorOptions, AppTable, AppTableDataSourceOptions, AppTableUtils, AppValidatorService, AppendToInputDirective, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayLengthPipe, ArrayPluckPipe, AudioProvider, AuthForm, AuthGuardService, AuthModal, AutocompleteTestPage, AutofocusDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, DATE_ISO_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFromNowPipe, DateTimeTestPage, DateUtils, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesService, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, Fragments$1 as Fragments, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, InMemoryEntitiesService, IsLoginAccountPipe, IsNilOrBlankPipe, IsNotNilOrBlankPipe, IsNotOnFieldModePipe, IsOnFieldModePipe, JobUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LongitudeFormatPipe, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MapGetPipe, MapKeysPipe, MapValuesPipe, MatAutocompleteConfigHolder, MatAutocompleteField, MatBadgeIconDirective, MatBooleanField, MatChipsField, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatNumpadComponent, MatNumpadContainerComponent, MatNumpadContent, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItems, MenuService, Message, MessageFilter, MessageForm, MessageModal, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NetworkService, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, NumpadDirective, OddPipe, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SelectPeerModal, SettingsPage, SharedAsyncValidators, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBadgeIconModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatNumpadModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedValidators, SocialErrorCodes, SocialModule, Software, StartableService, StatusById, StatusIds, StatusList, StrIncludesPipe, StrLengthPipe, SwipeTestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TextForm, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, Toasts, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEvent, UserEventFilter, UserEventFragments, UserEventService, UserEventTypes, UserEventsTable, UserSettings, UsersPage, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayGroupBy, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, fadeInAnimation, fadeInOutAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, hexToRgb, hexToRgbArray, isAndroid, isBlankString, isControlHasInput, isCordova, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, noTrailingSlash, notNilOrDefault, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputRange, setCalculatedValue, setTabIndex, sleep, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForTrue, waitIdle, waitWhilePending, ɵ0, CustomReuseStrategy as ɵa, MatNumpadDomService as ɵb, isFocusableElement as ɵc, RegisterForm as ɵd, AccountValidatorService as ɵe, RegisterModal as ɵf, UserSettingsValidatorService as ɵg, LocalSettingsValidatorService as ɵh, AppIconComponent as ɵi, DateTestPage as ɵj, NumpadTestPage as ɵk, MatBadgeIconTestPage as ɵl, ToastTestingModule as ɵm, ToastTestingPage as ɵn };
27506
27530
  //# sourceMappingURL=sumaris-net.ngx-components.js.map