@sumaris-net/ngx-components 1.19.3 → 1.19.5-rc2
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 +331 -285
- 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/esm2015/src/app/core/core.module.js +4 -1
- package/esm2015/src/app/core/install/install-upgrade-card.component.js +10 -40
- package/esm2015/src/app/core/offline/update-offline-mode-card.component.js +26 -0
- package/esm2015/src/app/core/services/platform.service.js +30 -15
- package/esm2015/src/app/core/table/entities-table-datasource.class.js +5 -3
- package/esm2015/src/app/shared/files.js +26 -1
- package/esm2015/src/app/shared/material/autocomplete/testing/autocomplete.test.js +11 -2
- package/esm2015/sumaris-net.ngx-components.js +8 -7
- package/fesm2015/sumaris-net.ngx-components.js +266 -221
- package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
- package/package.json +1 -1
- package/src/app/core/install/install-upgrade-card.component.d.ts +1 -6
- package/src/app/core/offline/update-offline-mode-card.component.d.ts +8 -0
- package/src/app/shared/files.d.ts +10 -0
- package/sumaris-net.ngx-components.d.ts +7 -6
- package/sumaris-net.ngx-components.metadata.json +1 -1
|
@@ -17888,6 +17888,252 @@
|
|
|
17888
17888
|
]; };
|
|
17889
17889
|
var templateObject_1$1, templateObject_2$1, templateObject_3$1, templateObject_4$1, templateObject_5$1;
|
|
17890
17890
|
|
|
17891
|
+
var UploadFile = /** @class */ (function (_super) {
|
|
17892
|
+
__extends(UploadFile, _super);
|
|
17893
|
+
function UploadFile() {
|
|
17894
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
17895
|
+
}
|
|
17896
|
+
return UploadFile;
|
|
17897
|
+
}(File));
|
|
17898
|
+
var FileResponse = /** @class */ (function () {
|
|
17899
|
+
function FileResponse(init) {
|
|
17900
|
+
this.type = i2$1.HttpEventType.Response;
|
|
17901
|
+
this.body = isNotNil(init === null || init === void 0 ? void 0 : init.body) ? init.body : null;
|
|
17902
|
+
this.status = (init === null || init === void 0 ? void 0 : init.status) || 0;
|
|
17903
|
+
this.statusText = (init === null || init === void 0 ? void 0 : init.statusText) || 'OK';
|
|
17904
|
+
}
|
|
17905
|
+
return FileResponse;
|
|
17906
|
+
}());
|
|
17907
|
+
function isProgressEvent(event) {
|
|
17908
|
+
return event && (event.type === i2$1.HttpEventType.UploadProgress
|
|
17909
|
+
|| event.type === i2$1.HttpEventType.DownloadProgress);
|
|
17910
|
+
}
|
|
17911
|
+
function isResponseEvent(event) {
|
|
17912
|
+
return event && event.type === i2$1.HttpEventType.Response;
|
|
17913
|
+
}
|
|
17914
|
+
|
|
17915
|
+
var UploadFilePopover = /** @class */ (function () {
|
|
17916
|
+
function UploadFilePopover(popoverController, translate, cd) {
|
|
17917
|
+
this.popoverController = popoverController;
|
|
17918
|
+
this.translate = translate;
|
|
17919
|
+
this.cd = cd;
|
|
17920
|
+
this.uniqueFile = false;
|
|
17921
|
+
this.instantUpload = false;
|
|
17922
|
+
this.importing = false;
|
|
17923
|
+
}
|
|
17924
|
+
Object.defineProperty(UploadFilePopover.prototype, "files", {
|
|
17925
|
+
get: function () {
|
|
17926
|
+
return this.uploader.files;
|
|
17927
|
+
},
|
|
17928
|
+
enumerable: false,
|
|
17929
|
+
configurable: true
|
|
17930
|
+
});
|
|
17931
|
+
Object.defineProperty(UploadFilePopover.prototype, "disabled", {
|
|
17932
|
+
get: function () {
|
|
17933
|
+
return this.importing || isEmptyArray(this.files);
|
|
17934
|
+
},
|
|
17935
|
+
enumerable: false,
|
|
17936
|
+
configurable: true
|
|
17937
|
+
});
|
|
17938
|
+
Object.defineProperty(UploadFilePopover.prototype, "valid", {
|
|
17939
|
+
get: function () {
|
|
17940
|
+
return isNotEmptyArray(this.files);
|
|
17941
|
+
},
|
|
17942
|
+
enumerable: false,
|
|
17943
|
+
configurable: true
|
|
17944
|
+
});
|
|
17945
|
+
UploadFilePopover.prototype.onValidate = function (event) {
|
|
17946
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
17947
|
+
var files, errors, err_1;
|
|
17948
|
+
return __generator(this, function (_a) {
|
|
17949
|
+
switch (_a.label) {
|
|
17950
|
+
case 0:
|
|
17951
|
+
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
17952
|
+
// Avoid multiple call
|
|
17953
|
+
if (this.importing)
|
|
17954
|
+
return [2 /*return*/];
|
|
17955
|
+
console.debug('[upload-file-popover] Validate form: will upload all files...');
|
|
17956
|
+
_a.label = 1;
|
|
17957
|
+
case 1:
|
|
17958
|
+
_a.trys.push([1, , 8, 9]);
|
|
17959
|
+
this.importing = true;
|
|
17960
|
+
this.resetError();
|
|
17961
|
+
_a.label = 2;
|
|
17962
|
+
case 2:
|
|
17963
|
+
_a.trys.push([2, 6, , 7]);
|
|
17964
|
+
// Wait processing files finished
|
|
17965
|
+
return [4 /*yield*/, this.uploader.waitIdle()];
|
|
17966
|
+
case 3:
|
|
17967
|
+
// Wait processing files finished
|
|
17968
|
+
_a.sent();
|
|
17969
|
+
// upload all files
|
|
17970
|
+
return [4 /*yield*/, this.uploader.uploadFiles()];
|
|
17971
|
+
case 4:
|
|
17972
|
+
// upload all files
|
|
17973
|
+
_a.sent();
|
|
17974
|
+
files = (this.uploader.processedFiles || [])
|
|
17975
|
+
.filter(function (file) { return !file.deleting; });
|
|
17976
|
+
// Nothing to upload: close popover
|
|
17977
|
+
if (isEmptyArray(files))
|
|
17978
|
+
return [2 /*return*/, this.cancel()];
|
|
17979
|
+
errors = files.map(function (file) { return file.error; }).filter(isNotNilOrBlank);
|
|
17980
|
+
// If error: stop
|
|
17981
|
+
if (errors.length) {
|
|
17982
|
+
errors.forEach(function (error) { return console.error(error); });
|
|
17983
|
+
throw { message: 'FILE.UPLOAD.ERROR' };
|
|
17984
|
+
}
|
|
17985
|
+
// return files
|
|
17986
|
+
return [4 /*yield*/, this.popoverController.dismiss(files)];
|
|
17987
|
+
case 5:
|
|
17988
|
+
// return files
|
|
17989
|
+
_a.sent();
|
|
17990
|
+
return [3 /*break*/, 7];
|
|
17991
|
+
case 6:
|
|
17992
|
+
err_1 = _a.sent();
|
|
17993
|
+
this.error = (err_1 && err_1.message) || err_1;
|
|
17994
|
+
return [3 /*break*/, 7];
|
|
17995
|
+
case 7: return [3 /*break*/, 9];
|
|
17996
|
+
case 8:
|
|
17997
|
+
this.importing = false;
|
|
17998
|
+
this.cd.markForCheck();
|
|
17999
|
+
return [7 /*endfinally*/];
|
|
18000
|
+
case 9: return [2 /*return*/];
|
|
18001
|
+
}
|
|
18002
|
+
});
|
|
18003
|
+
});
|
|
18004
|
+
};
|
|
18005
|
+
UploadFilePopover.prototype.cancel = function () {
|
|
18006
|
+
return this.popoverController.dismiss();
|
|
18007
|
+
};
|
|
18008
|
+
UploadFilePopover.prototype.resetError = function () {
|
|
18009
|
+
if (this.error) {
|
|
18010
|
+
this.error = null;
|
|
18011
|
+
this.cd.markForCheck();
|
|
18012
|
+
}
|
|
18013
|
+
};
|
|
18014
|
+
return UploadFilePopover;
|
|
18015
|
+
}());
|
|
18016
|
+
UploadFilePopover.decorators = [
|
|
18017
|
+
{ type: i0.Component, args: [{
|
|
18018
|
+
selector: 'app-upload-file-popover',
|
|
18019
|
+
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 <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",
|
|
18020
|
+
encapsulation: i0.ViewEncapsulation.None,
|
|
18021
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
18022
|
+
styles: [".importing-info{-webkit-padding-start:var(--ion-padding);padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}"]
|
|
18023
|
+
},] }
|
|
18024
|
+
];
|
|
18025
|
+
UploadFilePopover.ctorParameters = function () { return [
|
|
18026
|
+
{ type: i1$5.PopoverController },
|
|
18027
|
+
{ type: i1$2.TranslateService },
|
|
18028
|
+
{ type: i0.ChangeDetectorRef }
|
|
18029
|
+
]; };
|
|
18030
|
+
UploadFilePopover.propDecorators = {
|
|
18031
|
+
uploader: [{ type: i0.ViewChild, args: ['uploader', { static: true },] }],
|
|
18032
|
+
fileExtension: [{ type: i0.Input }],
|
|
18033
|
+
title: [{ type: i0.Input }],
|
|
18034
|
+
uniqueFile: [{ type: i0.Input }],
|
|
18035
|
+
instantUpload: [{ type: i0.Input }],
|
|
18036
|
+
uploadFn: [{ type: i0.Input }],
|
|
18037
|
+
deleteFn: [{ type: i0.Input }],
|
|
18038
|
+
maxParallelUpload: [{ type: i0.Input }]
|
|
18039
|
+
};
|
|
18040
|
+
|
|
18041
|
+
var MimeTypes = Object.freeze({
|
|
18042
|
+
ANDROID_APK: 'application/vnd.android.package-archive'
|
|
18043
|
+
});
|
|
18044
|
+
var FilesUtils = /** @class */ (function () {
|
|
18045
|
+
function FilesUtils() {
|
|
18046
|
+
}
|
|
18047
|
+
FilesUtils.showUploadPopover = function (popoverController, event, opts) {
|
|
18048
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
18049
|
+
var modal, _a, data, role;
|
|
18050
|
+
return __generator(this, function (_b) {
|
|
18051
|
+
switch (_b.label) {
|
|
18052
|
+
case 0: return [4 /*yield*/, popoverController.create({
|
|
18053
|
+
component: UploadFilePopover,
|
|
18054
|
+
componentProps: opts,
|
|
18055
|
+
backdropDismiss: false,
|
|
18056
|
+
keyboardClose: false,
|
|
18057
|
+
event: event,
|
|
18058
|
+
translucent: true,
|
|
18059
|
+
cssClass: 'popover-large',
|
|
18060
|
+
})];
|
|
18061
|
+
case 1:
|
|
18062
|
+
modal = _b.sent();
|
|
18063
|
+
return [4 /*yield*/, modal.present()];
|
|
18064
|
+
case 2:
|
|
18065
|
+
_b.sent();
|
|
18066
|
+
return [4 /*yield*/, modal.onDidDismiss()];
|
|
18067
|
+
case 3:
|
|
18068
|
+
_a = _b.sent(), data = _a.data, role = _a.role;
|
|
18069
|
+
return [2 /*return*/, {
|
|
18070
|
+
role: role,
|
|
18071
|
+
data: data ? data : undefined
|
|
18072
|
+
}];
|
|
18073
|
+
}
|
|
18074
|
+
});
|
|
18075
|
+
});
|
|
18076
|
+
};
|
|
18077
|
+
FilesUtils.readAsText = function (file, encoding) {
|
|
18078
|
+
var $progress = new rxjs.Subject();
|
|
18079
|
+
var reader = new FileReader();
|
|
18080
|
+
encoding = (encoding || 'UTF-8').toLowerCase();
|
|
18081
|
+
// Listen progress
|
|
18082
|
+
reader.onprogress = function (e) {
|
|
18083
|
+
var total = e.total || 1;
|
|
18084
|
+
var loaded = e.total || 0;
|
|
18085
|
+
if (loaded < total)
|
|
18086
|
+
$progress.next({ type: i2$1.HttpEventType.UploadProgress, loaded: loaded, total: total });
|
|
18087
|
+
};
|
|
18088
|
+
// Listen end
|
|
18089
|
+
reader.onloadend = function (e) {
|
|
18090
|
+
var body = reader.result;
|
|
18091
|
+
if (typeof body === 'string') {
|
|
18092
|
+
$progress.next(new FileResponse({ body: body }));
|
|
18093
|
+
$progress.complete();
|
|
18094
|
+
}
|
|
18095
|
+
else {
|
|
18096
|
+
console.error("Cannot read file '" + file.name + "' as text");
|
|
18097
|
+
$progress.error("Cannot read file as text");
|
|
18098
|
+
}
|
|
18099
|
+
};
|
|
18100
|
+
// Listen error
|
|
18101
|
+
reader.onerror = function (event) {
|
|
18102
|
+
console.error('[files] Error while reading file:', event);
|
|
18103
|
+
$progress.error(event);
|
|
18104
|
+
};
|
|
18105
|
+
// Start reading the file
|
|
18106
|
+
reader.readAsText(file, encoding);
|
|
18107
|
+
return $progress.asObservable();
|
|
18108
|
+
};
|
|
18109
|
+
return FilesUtils;
|
|
18110
|
+
}());
|
|
18111
|
+
var UriUtils = /** @class */ (function () {
|
|
18112
|
+
function UriUtils() {
|
|
18113
|
+
}
|
|
18114
|
+
/**
|
|
18115
|
+
* Extract the filename, from an uri (using the last slash)
|
|
18116
|
+
* @param uri
|
|
18117
|
+
*/
|
|
18118
|
+
UriUtils.getFilename = function (uri) {
|
|
18119
|
+
if (!uri)
|
|
18120
|
+
return uri;
|
|
18121
|
+
var filename = uri.trim();
|
|
18122
|
+
// Get last part (or all string, if no '/')
|
|
18123
|
+
var lastSlashIndex = filename.lastIndexOf('/');
|
|
18124
|
+
if (lastSlashIndex !== -1 && lastSlashIndex !== uri.length - 1) {
|
|
18125
|
+
filename = filename.substring(lastSlashIndex + 1);
|
|
18126
|
+
}
|
|
18127
|
+
// Remove query params
|
|
18128
|
+
var queryParamIndex = filename.indexOf('?');
|
|
18129
|
+
if (queryParamIndex !== -1) {
|
|
18130
|
+
filename = filename.substring(0, queryParamIndex);
|
|
18131
|
+
}
|
|
18132
|
+
return filename;
|
|
18133
|
+
};
|
|
18134
|
+
return UriUtils;
|
|
18135
|
+
}());
|
|
18136
|
+
|
|
17891
18137
|
var moment$4 = momentImported__namespace;
|
|
17892
18138
|
var AndroidOsEnvironment = Object.freeze({
|
|
17893
18139
|
DIRECTORY_DOWNLOADS: 'Download',
|
|
@@ -18083,34 +18329,48 @@
|
|
|
18083
18329
|
};
|
|
18084
18330
|
PlatformService.prototype.download = function (request) {
|
|
18085
18331
|
var _this = this;
|
|
18332
|
+
var _a, _b;
|
|
18086
18333
|
if (!request || !request.uri)
|
|
18087
18334
|
throw new Error('Missing argument \'request\' or \'request.uri\'');
|
|
18088
18335
|
if (this._android && this.downloader) {
|
|
18089
18336
|
// Check if not already downloading file
|
|
18090
|
-
var
|
|
18091
|
-
if (
|
|
18092
|
-
return
|
|
18093
|
-
|
|
18094
|
-
|
|
18337
|
+
var job$ = this._downloadingJobs.get(request.uri);
|
|
18338
|
+
if (job$)
|
|
18339
|
+
return job$;
|
|
18340
|
+
// Compute subPath (final filename)
|
|
18341
|
+
var subPath = ((_a = request.destinationInExternalPublicDir) === null || _a === void 0 ? void 0 : _a.subPath) || ((_b = request.destinationInExternalFilesDir) === null || _b === void 0 ? void 0 : _b.subPath)
|
|
18342
|
+
|| request.filename || UriUtils.getFilename(request.uri)
|
|
18343
|
+
|| request.title || 'download';
|
|
18344
|
+
subPath = subPath.toLowerCase()
|
|
18345
|
+
// Remove spaces
|
|
18346
|
+
.replace(/\s+/g, '-');
|
|
18347
|
+
// Force APK to finish with '.apk'
|
|
18348
|
+
if (request.mimeType === MimeTypes.ANDROID_APK && !subPath.toLowerCase().endsWith('.apk')) {
|
|
18349
|
+
subPath += '.apk';
|
|
18350
|
+
}
|
|
18351
|
+
var downloadRequest_1 = Object.assign(Object.assign({ visibleInDownloadsUi: true, notificationVisibility: ngx$6.NotificationVisibility.VisibleNotifyCompleted }, request), { filename: undefined, destinationInExternalPublicDir: !request.destinationInExternalFilesDir
|
|
18352
|
+
? Object.assign(Object.assign({ dirType: AndroidOsEnvironment.DIRECTORY_DOWNLOADS }, request.destinationInExternalPublicDir), { subPath: subPath }) : undefined, destinationInExternalFilesDir: request.destinationInExternalFilesDir
|
|
18353
|
+
? Object.assign(Object.assign({ dirType: AndroidOsEnvironment.DIRECTORY_DOWNLOADS }, request.destinationInExternalFilesDir), { subPath: subPath }) : undefined });
|
|
18095
18354
|
// Start download
|
|
18096
|
-
|
|
18355
|
+
console.debug('[platform] Downloading, using request: ' + JSON.stringify(downloadRequest_1));
|
|
18356
|
+
job$ = rxjs.from(this.downloader.download(downloadRequest_1));
|
|
18097
18357
|
// Remember this request uri
|
|
18098
|
-
this._downloadingJobs.set(
|
|
18099
|
-
return
|
|
18358
|
+
this._downloadingJobs.set(downloadRequest_1.uri, job$);
|
|
18359
|
+
return job$
|
|
18100
18360
|
.pipe(operators.tap(function (location) {
|
|
18101
18361
|
console.info('[platform] File successfully downloaded at:' + location);
|
|
18102
|
-
// Forget
|
|
18103
|
-
_this._downloadingJobs.delete(
|
|
18362
|
+
// Forget job
|
|
18363
|
+
_this._downloadingJobs.delete(downloadRequest_1.uri);
|
|
18104
18364
|
return location;
|
|
18105
18365
|
}), operators.catchError(function (err) {
|
|
18106
18366
|
var _a;
|
|
18107
18367
|
console.error('[platform] Unable to download: ' + (err && err.message || err));
|
|
18108
18368
|
// Forget the request
|
|
18109
|
-
_this._downloadingJobs.delete(
|
|
18369
|
+
_this._downloadingJobs.delete(downloadRequest_1.uri);
|
|
18110
18370
|
// Retry with another location - issue in older Android version
|
|
18111
|
-
if (((_a =
|
|
18112
|
-
|
|
18113
|
-
return _this.download(
|
|
18371
|
+
if (((_a = downloadRequest_1.destinationInExternalPublicDir) === null || _a === void 0 ? void 0 : _a.dirType) === AndroidOsEnvironment.DIRECTORY_DOWNLOADS) {
|
|
18372
|
+
downloadRequest_1.destinationInExternalPublicDir.dirType = AndroidOsEnvironment.DIRECTORY_DOWNLOADS_OLD;
|
|
18373
|
+
return _this.download(downloadRequest_1);
|
|
18114
18374
|
}
|
|
18115
18375
|
throw err;
|
|
18116
18376
|
}));
|
|
@@ -18526,30 +18786,6 @@
|
|
|
18526
18786
|
{ type: i1$2.TranslateService }
|
|
18527
18787
|
]; };
|
|
18528
18788
|
|
|
18529
|
-
var UploadFile = /** @class */ (function (_super) {
|
|
18530
|
-
__extends(UploadFile, _super);
|
|
18531
|
-
function UploadFile() {
|
|
18532
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
18533
|
-
}
|
|
18534
|
-
return UploadFile;
|
|
18535
|
-
}(File));
|
|
18536
|
-
var FileResponse = /** @class */ (function () {
|
|
18537
|
-
function FileResponse(init) {
|
|
18538
|
-
this.type = i2$1.HttpEventType.Response;
|
|
18539
|
-
this.body = isNotNil(init === null || init === void 0 ? void 0 : init.body) ? init.body : null;
|
|
18540
|
-
this.status = (init === null || init === void 0 ? void 0 : init.status) || 0;
|
|
18541
|
-
this.statusText = (init === null || init === void 0 ? void 0 : init.statusText) || 'OK';
|
|
18542
|
-
}
|
|
18543
|
-
return FileResponse;
|
|
18544
|
-
}());
|
|
18545
|
-
function isProgressEvent(event) {
|
|
18546
|
-
return event && (event.type === i2$1.HttpEventType.UploadProgress
|
|
18547
|
-
|| event.type === i2$1.HttpEventType.DownloadProgress);
|
|
18548
|
-
}
|
|
18549
|
-
function isResponseEvent(event) {
|
|
18550
|
-
return event && event.type === i2$1.HttpEventType.Response;
|
|
18551
|
-
}
|
|
18552
|
-
|
|
18553
18789
|
var UploadFileComponent = /** @class */ (function () {
|
|
18554
18790
|
function UploadFileComponent(cd, translate) {
|
|
18555
18791
|
this.cd = cd;
|
|
@@ -18778,132 +19014,6 @@
|
|
|
18778
19014
|
maxParallelUpload: [{ type: i0.Input }]
|
|
18779
19015
|
};
|
|
18780
19016
|
|
|
18781
|
-
var UploadFilePopover = /** @class */ (function () {
|
|
18782
|
-
function UploadFilePopover(popoverController, translate, cd) {
|
|
18783
|
-
this.popoverController = popoverController;
|
|
18784
|
-
this.translate = translate;
|
|
18785
|
-
this.cd = cd;
|
|
18786
|
-
this.uniqueFile = false;
|
|
18787
|
-
this.instantUpload = false;
|
|
18788
|
-
this.importing = false;
|
|
18789
|
-
}
|
|
18790
|
-
Object.defineProperty(UploadFilePopover.prototype, "files", {
|
|
18791
|
-
get: function () {
|
|
18792
|
-
return this.uploader.files;
|
|
18793
|
-
},
|
|
18794
|
-
enumerable: false,
|
|
18795
|
-
configurable: true
|
|
18796
|
-
});
|
|
18797
|
-
Object.defineProperty(UploadFilePopover.prototype, "disabled", {
|
|
18798
|
-
get: function () {
|
|
18799
|
-
return this.importing || isEmptyArray(this.files);
|
|
18800
|
-
},
|
|
18801
|
-
enumerable: false,
|
|
18802
|
-
configurable: true
|
|
18803
|
-
});
|
|
18804
|
-
Object.defineProperty(UploadFilePopover.prototype, "valid", {
|
|
18805
|
-
get: function () {
|
|
18806
|
-
return isNotEmptyArray(this.files);
|
|
18807
|
-
},
|
|
18808
|
-
enumerable: false,
|
|
18809
|
-
configurable: true
|
|
18810
|
-
});
|
|
18811
|
-
UploadFilePopover.prototype.onValidate = function (event) {
|
|
18812
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
18813
|
-
var files, errors, err_1;
|
|
18814
|
-
return __generator(this, function (_a) {
|
|
18815
|
-
switch (_a.label) {
|
|
18816
|
-
case 0:
|
|
18817
|
-
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
18818
|
-
// Avoid multiple call
|
|
18819
|
-
if (this.importing)
|
|
18820
|
-
return [2 /*return*/];
|
|
18821
|
-
console.debug('[upload-file-popover] Validate form: will upload all files...');
|
|
18822
|
-
_a.label = 1;
|
|
18823
|
-
case 1:
|
|
18824
|
-
_a.trys.push([1, , 8, 9]);
|
|
18825
|
-
this.importing = true;
|
|
18826
|
-
this.resetError();
|
|
18827
|
-
_a.label = 2;
|
|
18828
|
-
case 2:
|
|
18829
|
-
_a.trys.push([2, 6, , 7]);
|
|
18830
|
-
// Wait processing files finished
|
|
18831
|
-
return [4 /*yield*/, this.uploader.waitIdle()];
|
|
18832
|
-
case 3:
|
|
18833
|
-
// Wait processing files finished
|
|
18834
|
-
_a.sent();
|
|
18835
|
-
// upload all files
|
|
18836
|
-
return [4 /*yield*/, this.uploader.uploadFiles()];
|
|
18837
|
-
case 4:
|
|
18838
|
-
// upload all files
|
|
18839
|
-
_a.sent();
|
|
18840
|
-
files = (this.uploader.processedFiles || [])
|
|
18841
|
-
.filter(function (file) { return !file.deleting; });
|
|
18842
|
-
// Nothing to upload: close popover
|
|
18843
|
-
if (isEmptyArray(files))
|
|
18844
|
-
return [2 /*return*/, this.cancel()];
|
|
18845
|
-
errors = files.map(function (file) { return file.error; }).filter(isNotNilOrBlank);
|
|
18846
|
-
// If error: stop
|
|
18847
|
-
if (errors.length) {
|
|
18848
|
-
errors.forEach(function (error) { return console.error(error); });
|
|
18849
|
-
throw { message: 'FILE.UPLOAD.ERROR' };
|
|
18850
|
-
}
|
|
18851
|
-
// return files
|
|
18852
|
-
return [4 /*yield*/, this.popoverController.dismiss(files)];
|
|
18853
|
-
case 5:
|
|
18854
|
-
// return files
|
|
18855
|
-
_a.sent();
|
|
18856
|
-
return [3 /*break*/, 7];
|
|
18857
|
-
case 6:
|
|
18858
|
-
err_1 = _a.sent();
|
|
18859
|
-
this.error = (err_1 && err_1.message) || err_1;
|
|
18860
|
-
return [3 /*break*/, 7];
|
|
18861
|
-
case 7: return [3 /*break*/, 9];
|
|
18862
|
-
case 8:
|
|
18863
|
-
this.importing = false;
|
|
18864
|
-
this.cd.markForCheck();
|
|
18865
|
-
return [7 /*endfinally*/];
|
|
18866
|
-
case 9: return [2 /*return*/];
|
|
18867
|
-
}
|
|
18868
|
-
});
|
|
18869
|
-
});
|
|
18870
|
-
};
|
|
18871
|
-
UploadFilePopover.prototype.cancel = function () {
|
|
18872
|
-
return this.popoverController.dismiss();
|
|
18873
|
-
};
|
|
18874
|
-
UploadFilePopover.prototype.resetError = function () {
|
|
18875
|
-
if (this.error) {
|
|
18876
|
-
this.error = null;
|
|
18877
|
-
this.cd.markForCheck();
|
|
18878
|
-
}
|
|
18879
|
-
};
|
|
18880
|
-
return UploadFilePopover;
|
|
18881
|
-
}());
|
|
18882
|
-
UploadFilePopover.decorators = [
|
|
18883
|
-
{ type: i0.Component, args: [{
|
|
18884
|
-
selector: 'app-upload-file-popover',
|
|
18885
|
-
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 <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",
|
|
18886
|
-
encapsulation: i0.ViewEncapsulation.None,
|
|
18887
|
-
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
18888
|
-
styles: [".importing-info{-webkit-padding-start:var(--ion-padding);padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}"]
|
|
18889
|
-
},] }
|
|
18890
|
-
];
|
|
18891
|
-
UploadFilePopover.ctorParameters = function () { return [
|
|
18892
|
-
{ type: i1$5.PopoverController },
|
|
18893
|
-
{ type: i1$2.TranslateService },
|
|
18894
|
-
{ type: i0.ChangeDetectorRef }
|
|
18895
|
-
]; };
|
|
18896
|
-
UploadFilePopover.propDecorators = {
|
|
18897
|
-
uploader: [{ type: i0.ViewChild, args: ['uploader', { static: true },] }],
|
|
18898
|
-
fileExtension: [{ type: i0.Input }],
|
|
18899
|
-
title: [{ type: i0.Input }],
|
|
18900
|
-
uniqueFile: [{ type: i0.Input }],
|
|
18901
|
-
instantUpload: [{ type: i0.Input }],
|
|
18902
|
-
uploadFn: [{ type: i0.Input }],
|
|
18903
|
-
deleteFn: [{ type: i0.Input }],
|
|
18904
|
-
maxParallelUpload: [{ type: i0.Input }]
|
|
18905
|
-
};
|
|
18906
|
-
|
|
18907
19017
|
var APP_TESTING_PAGES = new i0.InjectionToken('testingPages');
|
|
18908
19018
|
var SharedTestsPage = /** @class */ (function () {
|
|
18909
19019
|
function SharedTestsPage(route, router, translate, pages) {
|
|
@@ -20498,74 +20608,6 @@
|
|
|
20498
20608
|
return JobUtils;
|
|
20499
20609
|
}());
|
|
20500
20610
|
|
|
20501
|
-
var FilesUtils = /** @class */ (function () {
|
|
20502
|
-
function FilesUtils() {
|
|
20503
|
-
}
|
|
20504
|
-
FilesUtils.showUploadPopover = function (popoverController, event, opts) {
|
|
20505
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
20506
|
-
var modal, _a, data, role;
|
|
20507
|
-
return __generator(this, function (_b) {
|
|
20508
|
-
switch (_b.label) {
|
|
20509
|
-
case 0: return [4 /*yield*/, popoverController.create({
|
|
20510
|
-
component: UploadFilePopover,
|
|
20511
|
-
componentProps: opts,
|
|
20512
|
-
backdropDismiss: false,
|
|
20513
|
-
keyboardClose: false,
|
|
20514
|
-
event: event,
|
|
20515
|
-
translucent: true,
|
|
20516
|
-
cssClass: 'popover-large',
|
|
20517
|
-
})];
|
|
20518
|
-
case 1:
|
|
20519
|
-
modal = _b.sent();
|
|
20520
|
-
return [4 /*yield*/, modal.present()];
|
|
20521
|
-
case 2:
|
|
20522
|
-
_b.sent();
|
|
20523
|
-
return [4 /*yield*/, modal.onDidDismiss()];
|
|
20524
|
-
case 3:
|
|
20525
|
-
_a = _b.sent(), data = _a.data, role = _a.role;
|
|
20526
|
-
return [2 /*return*/, {
|
|
20527
|
-
role: role,
|
|
20528
|
-
data: data ? data : undefined
|
|
20529
|
-
}];
|
|
20530
|
-
}
|
|
20531
|
-
});
|
|
20532
|
-
});
|
|
20533
|
-
};
|
|
20534
|
-
FilesUtils.readAsText = function (file, encoding) {
|
|
20535
|
-
var $progress = new rxjs.Subject();
|
|
20536
|
-
var reader = new FileReader();
|
|
20537
|
-
encoding = (encoding || 'UTF-8').toLowerCase();
|
|
20538
|
-
// Listen progress
|
|
20539
|
-
reader.onprogress = function (e) {
|
|
20540
|
-
var total = e.total || 1;
|
|
20541
|
-
var loaded = e.total || 0;
|
|
20542
|
-
if (loaded < total)
|
|
20543
|
-
$progress.next({ type: i2$1.HttpEventType.UploadProgress, loaded: loaded, total: total });
|
|
20544
|
-
};
|
|
20545
|
-
// Listen end
|
|
20546
|
-
reader.onloadend = function (e) {
|
|
20547
|
-
var body = reader.result;
|
|
20548
|
-
if (typeof body === 'string') {
|
|
20549
|
-
$progress.next(new FileResponse({ body: body }));
|
|
20550
|
-
$progress.complete();
|
|
20551
|
-
}
|
|
20552
|
-
else {
|
|
20553
|
-
console.error("Cannot read file '" + file.name + "' as text");
|
|
20554
|
-
$progress.error("Cannot read file as text");
|
|
20555
|
-
}
|
|
20556
|
-
};
|
|
20557
|
-
// Listen error
|
|
20558
|
-
reader.onerror = function (event) {
|
|
20559
|
-
console.error('[files] Error while reading file:', event);
|
|
20560
|
-
$progress.error(event);
|
|
20561
|
-
};
|
|
20562
|
-
// Start reading the file
|
|
20563
|
-
reader.readAsText(file, encoding);
|
|
20564
|
-
return $progress.asObservable();
|
|
20565
|
-
};
|
|
20566
|
-
return FilesUtils;
|
|
20567
|
-
}());
|
|
20568
|
-
|
|
20569
20611
|
/**
|
|
20570
20612
|
* Define here theme colors
|
|
20571
20613
|
*/
|
|
@@ -23215,9 +23257,6 @@
|
|
|
23215
23257
|
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
|
|
23216
23258
|
];
|
|
23217
23259
|
|
|
23218
|
-
var MimeTypes = Object.freeze({
|
|
23219
|
-
ANDROID_APK: 'application/vnd.android.package-archive'
|
|
23220
|
-
});
|
|
23221
23260
|
var AppInstallUpgradeCard = /** @class */ (function () {
|
|
23222
23261
|
function AppInstallUpgradeCard(modalCtrl, configService, toastController, alertController, translate, cd, platform, network, environment) {
|
|
23223
23262
|
this.modalCtrl = modalCtrl;
|
|
@@ -23230,7 +23269,6 @@
|
|
|
23230
23269
|
this.network = network;
|
|
23231
23270
|
this.environment = environment;
|
|
23232
23271
|
this._subscription = new rxjs.Subscription();
|
|
23233
|
-
this._showUpdateOfflineFeature = false;
|
|
23234
23272
|
this.loading = true;
|
|
23235
23273
|
this.hasDownloader = false;
|
|
23236
23274
|
this.downloading = false;
|
|
@@ -23238,21 +23276,7 @@
|
|
|
23238
23276
|
this.showUpgradeWarning = true;
|
|
23239
23277
|
this.showOfflineWarning = true;
|
|
23240
23278
|
this.showInstallButton = false;
|
|
23241
|
-
this.onUpdateOfflineModeClick = new i0.EventEmitter();
|
|
23242
23279
|
}
|
|
23243
|
-
Object.defineProperty(AppInstallUpgradeCard.prototype, "showUpdateOfflineFeature", {
|
|
23244
|
-
get: function () {
|
|
23245
|
-
return this._showUpdateOfflineFeature;
|
|
23246
|
-
},
|
|
23247
|
-
set: function (value) {
|
|
23248
|
-
if (value === this._showUpdateOfflineFeature)
|
|
23249
|
-
return; // Skip
|
|
23250
|
-
this._showUpdateOfflineFeature = value;
|
|
23251
|
-
this.markForCheck();
|
|
23252
|
-
},
|
|
23253
|
-
enumerable: false,
|
|
23254
|
-
configurable: true
|
|
23255
|
-
});
|
|
23256
23280
|
AppInstallUpgradeCard.prototype.ngOnInit = function () {
|
|
23257
23281
|
var _this = this;
|
|
23258
23282
|
this.offline = this.network.offline;
|
|
@@ -23276,7 +23300,6 @@
|
|
|
23276
23300
|
AppInstallUpgradeCard.prototype.ngOnDestroy = function () {
|
|
23277
23301
|
this._subscription.unsubscribe();
|
|
23278
23302
|
this._subscription = null;
|
|
23279
|
-
this.onUpdateOfflineModeClick.complete();
|
|
23280
23303
|
this.installLinks = null;
|
|
23281
23304
|
this.upgradeLinks = null;
|
|
23282
23305
|
};
|
|
@@ -23464,10 +23487,10 @@
|
|
|
23464
23487
|
var title = void 0;
|
|
23465
23488
|
var mimeType = void 0;
|
|
23466
23489
|
// Get file name
|
|
23467
|
-
var filename =
|
|
23490
|
+
var filename = UriUtils.getFilename(url);
|
|
23468
23491
|
var version = minVersion || 'latest';
|
|
23469
23492
|
// OK, this is a downloadable APK file (e.g. NOT a link to a playstore)
|
|
23470
|
-
if (filename === null || filename === void 0 ? void 0 : filename.endsWith('.apk')) {
|
|
23493
|
+
if (filename === null || filename === void 0 ? void 0 : filename.toLowerCase().endsWith('.apk')) {
|
|
23471
23494
|
// Define mime type
|
|
23472
23495
|
mimeType = MimeTypes.ANDROID_APK;
|
|
23473
23496
|
// Get the file version (if any)
|
|
@@ -23478,11 +23501,9 @@
|
|
|
23478
23501
|
filename = (name + "-v" + version + ".apk").toLowerCase();
|
|
23479
23502
|
title = name + " v" + version;
|
|
23480
23503
|
}
|
|
23481
|
-
|
|
23482
|
-
|
|
23483
|
-
|
|
23484
|
-
filename = filename.replace('latest', version);
|
|
23485
|
-
}
|
|
23504
|
+
// Replace 'latest' with the app version, if present in the filename
|
|
23505
|
+
else if (filename.indexOf('latest') && version !== 'latest') {
|
|
23506
|
+
filename = filename.replace('latest', version);
|
|
23486
23507
|
}
|
|
23487
23508
|
}
|
|
23488
23509
|
result.push({ name: name, url: url, platform: 'android', version: version, filename: filename, title: title, mimeType: mimeType });
|
|
@@ -23494,18 +23515,6 @@
|
|
|
23494
23515
|
//}
|
|
23495
23516
|
return result;
|
|
23496
23517
|
};
|
|
23497
|
-
AppInstallUpgradeCard.prototype.getFilename = function (url) {
|
|
23498
|
-
if (!url)
|
|
23499
|
-
return;
|
|
23500
|
-
// Get last part (or all string, if no '/')
|
|
23501
|
-
var filename = url.substring(url.lastIndexOf('/') + 1);
|
|
23502
|
-
var queryParamIndex = filename.indexOf('?');
|
|
23503
|
-
if (queryParamIndex !== -1) {
|
|
23504
|
-
// Remove query params
|
|
23505
|
-
return filename.substring(0, queryParamIndex);
|
|
23506
|
-
}
|
|
23507
|
-
return filename;
|
|
23508
|
-
};
|
|
23509
23518
|
AppInstallUpgradeCard.prototype.listenDownloadJobs = function () {
|
|
23510
23519
|
var _this = this;
|
|
23511
23520
|
// Listening downloading promise, if exists
|
|
@@ -23637,7 +23646,7 @@
|
|
|
23637
23646
|
AppInstallUpgradeCard.decorators = [
|
|
23638
23647
|
{ type: i0.Component, args: [{
|
|
23639
23648
|
selector: 'app-install-upgrade-card',
|
|
23640
|
-
template: "\n\n<!-- Offline mode card-->\n<ion-card *ngIf=\"showOfflineWarning && (!loading && offline || waitingNetwork)\"\n color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\" *ngIf=\"!waitingNetwork; else waitingNetworkText\">\n <h4>\n <b *ngIf=\"isLogin; else notLogin\" [innerHTML]=\"'NETWORK.INFO.OFFLINE_OR_UNAUTHORIZED'| translate\"></b>\n <ng-template #notLogin>\n <b [innerHTML]=\"'NETWORK.INFO.OFFLINE'| translate\"></b>\n </ng-template>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.OFFLINE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n <ng-template #waitingNetworkText>\n <ion-text class=\"ion-text-wrap\" [innerHTML]=\"'NETWORK.INFO.RETRY_TO_CONNECT'| translate\"></ion-text>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\">\n\n <!-- Retry button -->\n <ion-button *ngIf=\"!waitingNetwork; else waitingSpinner\" color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"tryOnline()\">\n <span translate>NETWORK.BTN_CHECK_ALIVE</span>\n </ion-button>\n\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Upgrade links -->\n<ion-card *ngIf=\"showUpgradeWarning && !loading && !offline && upgradeLinks\"\n color=\"accent\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of upgradeLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3>\n <span *ngIf=\"link.version\" [innerHTML]=\"'INFO.UPDATE_APP_TO_VERSION'| translate: link\"></span>\n <span *ngIf=\"!link.version\" [innerHTML]=\"'INFO.UPDATE_APP'| translate: link\"></span>\n </h3>\n <h4>\n <small *ngIf=\"last\" [innerHTML]=\"'INFO.UPDATE_APP_HELP'|translate\"></small>\n </h4>\n </ion-text>\n </ion-col>\n\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Install links -->\n<ion-card *ngIf=\"showInstallButton && !loading && !offline && installLinks\"\n color=\"secondary\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of installLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3 [innerHTML]=\"'INFO.DOWNLOAD_APP_TITLE'| translate: {name: link.name, platform: getPlatformName(link.platform) }\"></h3>\n <h4><small *ngIf=\"last\" [innerHTML]=\"'INFO.DOWNLOAD_APP_HELP'|translate\"></small></h4>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!--
|
|
23649
|
+
template: "\n\n<!-- Offline mode card-->\n<ion-card *ngIf=\"showOfflineWarning && (!loading && offline || waitingNetwork)\"\n color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\" *ngIf=\"!waitingNetwork; else waitingNetworkText\">\n <h4>\n <b *ngIf=\"isLogin; else notLogin\" [innerHTML]=\"'NETWORK.INFO.OFFLINE_OR_UNAUTHORIZED'| translate\"></b>\n <ng-template #notLogin>\n <b [innerHTML]=\"'NETWORK.INFO.OFFLINE'| translate\"></b>\n </ng-template>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.OFFLINE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n <ng-template #waitingNetworkText>\n <ion-text class=\"ion-text-wrap\" [innerHTML]=\"'NETWORK.INFO.RETRY_TO_CONNECT'| translate\"></ion-text>\n </ng-template>\n </ion-col>\n <ion-col size=\"auto\">\n\n <!-- Retry button -->\n <ion-button *ngIf=\"!waitingNetwork; else waitingSpinner\" color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"tryOnline()\">\n <span translate>NETWORK.BTN_CHECK_ALIVE</span>\n </ion-button>\n\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Upgrade links -->\n<ion-card *ngIf=\"showUpgradeWarning && !loading && !offline && upgradeLinks\"\n color=\"accent\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of upgradeLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3>\n <span *ngIf=\"link.version\" [innerHTML]=\"'INFO.UPDATE_APP_TO_VERSION'| translate: link\"></span>\n <span *ngIf=\"!link.version\" [innerHTML]=\"'INFO.UPDATE_APP'| translate: link\"></span>\n </h3>\n <h4>\n <small *ngIf=\"last\" [innerHTML]=\"'INFO.UPDATE_APP_HELP'|translate\"></small>\n </h4>\n </ion-text>\n </ion-col>\n\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Install links -->\n<ion-card *ngIf=\"showInstallButton && !loading && !offline && installLinks\"\n color=\"secondary\"\n class=\"ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngFor=\"let link of installLinks; last as last\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\">\n <h3 [innerHTML]=\"'INFO.DOWNLOAD_APP_TITLE'| translate: {name: link.name, platform: getPlatformName(link.platform) }\"></h3>\n <h4><small *ngIf=\"last\" [innerHTML]=\"'INFO.DOWNLOAD_APP_HELP'|translate\"></small></h4>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"downloadButton; context: { $implicit: link }\"></ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </ion-card-content>\n</ion-card>\n\n<!-- Display a download button, depending on the link URL, and the device platform -->\n<ng-template #downloadButton let-link>\n\n <ng-container *ngIf=\"link.filename; else redirectButton\">\n\n <ng-container *ngIf=\"hasDownloader; else webDownloadButton\">\n <!-- Download using platform -->\n <ion-button (click)=\"download($event, asLink(link))\"\n *ngIf=\"!link.location; else openButton\"\n [disabled]=\"link.downloading\"\n color=\"tertiary\" class=\"ion-float-end\">\n <ion-icon slot=\"start\" *ngIf=\"!link.downloading\" name=\"download\"></ion-icon>\n <ion-spinner slot=\"start\" class=\"ion-no-padding\" *ngIf=\"link.downloading\"></ion-spinner>\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n\n <!-- Open APK button -->\n <ng-template #openButton>\n <ion-button *ngIf=\"link.location\"\n (click)=\"openFile($event, link)\"\n color=\"tertiary\" class=\"ion-float-end\" >\n <ion-label translate>COMMON.BTN_INSTALL</ion-label>\n </ion-button>\n </ng-template>\n </ng-container>\n\n <!-- Web download button -->\n <ng-template #webDownloadButton>\n <ion-button [download]=\"link.downloadFilename\"\n [href]=\"link.url\"\n color=\"tertiary\" class=\"ion-float-end\" >\n <ion-label translate>COMMON.BTN_DOWNLOAD</ion-label>\n </ion-button>\n </ng-template>\n </ng-container>\n\n <!-- Web redirect button -->\n <ng-template #redirectButton>\n <ion-button [href]=\"link.url\" rel=\"external\" color=\"tertiary\" class=\"ion-float-end\" target=\"_blank\">\n <ion-label translate>COMMON.BTN_SHOW_MORE</ion-label>\n </ion-button>\n </ng-template>\n</ng-template>\n\n\n<!-- Waiting spinner -->\n<ng-template #waitingSpinner>\n <ion-spinner color=\"light\"></ion-spinner>\n</ng-template>\n",
|
|
23641
23650
|
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
23642
23651
|
animations: [slideUpDownAnimation],
|
|
23643
23652
|
styles: ["ion-text small{font-size:85%}"]
|
|
@@ -23658,9 +23667,7 @@
|
|
|
23658
23667
|
isLogin: [{ type: i0.Input }],
|
|
23659
23668
|
showUpgradeWarning: [{ type: i0.Input }],
|
|
23660
23669
|
showOfflineWarning: [{ type: i0.Input }],
|
|
23661
|
-
showInstallButton: [{ type: i0.Input }]
|
|
23662
|
-
showUpdateOfflineFeature: [{ type: i0.Input }],
|
|
23663
|
-
onUpdateOfflineModeClick: [{ type: i0.Output }]
|
|
23670
|
+
showInstallButton: [{ type: i0.Input }]
|
|
23664
23671
|
};
|
|
23665
23672
|
|
|
23666
23673
|
var IsLoginAccountPipe = /** @class */ (function () {
|
|
@@ -24198,6 +24205,31 @@
|
|
|
24198
24205
|
ref: [{ type: i0.Input }]
|
|
24199
24206
|
};
|
|
24200
24207
|
|
|
24208
|
+
var AppUpdateOfflineModeCard = /** @class */ (function () {
|
|
24209
|
+
function AppUpdateOfflineModeCard() {
|
|
24210
|
+
this.onUpdateClick = new i0.EventEmitter();
|
|
24211
|
+
}
|
|
24212
|
+
AppUpdateOfflineModeCard.prototype.ngOnDestroy = function () {
|
|
24213
|
+
this.onUpdateClick.complete();
|
|
24214
|
+
};
|
|
24215
|
+
return AppUpdateOfflineModeCard;
|
|
24216
|
+
}());
|
|
24217
|
+
AppUpdateOfflineModeCard.decorators = [
|
|
24218
|
+
{ type: i0.Component, args: [{
|
|
24219
|
+
selector: 'app-update-offline-mode-card',
|
|
24220
|
+
template: "\n<!-- Update offline feature card-->\n<ion-card color=\"accent\"\n class=\"main ion-no-margin\"\n @slideUpDownAnimation>\n <ion-card-content class=\"ion-no-padding\">\n <ion-grid>\n <ion-row *ngIf=\"!progressionValue; else progression\">\n <ion-col>\n <ion-text class=\"ion-text-wrap\" >\n <h4>\n <b [innerHTML]=\"'NETWORK.INFO.UPDATE_OFFLINE_MODE'| translate\"></b>\n </h4>\n <h3>\n <small [innerHTML]=\"'NETWORK.INFO.UPDATE_OFFLINE_MODE_HELP'|translate\"></small>\n </h3>\n </ion-text>\n </ion-col>\n\n <!-- Update button -->\n <ion-col size=\"auto\">\n <ion-button color=\"tertiary\" class=\"ion-float-end\"\n (click)=\"onUpdateClick.emit($event)\">\n <span translate>NETWORK.BTN_UPDATE</span>\n </ion-button>\n </ion-col>\n </ion-row>\n\n <ng-template #progression>\n <ion-row>\n <ion-col>\n <ion-text class=\"ion-text-wrap\" [innerHTML]=\"progressionMessage\"></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-progress-bar [value]=\"progressionValue / 100\"></ion-progress-bar>\n </ion-col>\n </ion-row>\n </ng-template>\n </ion-grid>\n\n\n </ion-card-content>\n</ion-card>\n",
|
|
24221
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
24222
|
+
animations: [slideUpDownAnimation],
|
|
24223
|
+
styles: ["ion-text small{font-size:85%}"]
|
|
24224
|
+
},] }
|
|
24225
|
+
];
|
|
24226
|
+
AppUpdateOfflineModeCard.ctorParameters = function () { return []; };
|
|
24227
|
+
AppUpdateOfflineModeCard.propDecorators = {
|
|
24228
|
+
progressionMessage: [{ type: i0.Input }],
|
|
24229
|
+
progressionValue: [{ type: i0.Input }],
|
|
24230
|
+
onUpdateClick: [{ type: i0.Output }]
|
|
24231
|
+
};
|
|
24232
|
+
|
|
24201
24233
|
var CoreModule = /** @class */ (function () {
|
|
24202
24234
|
function CoreModule() {
|
|
24203
24235
|
}
|
|
@@ -24247,6 +24279,7 @@
|
|
|
24247
24279
|
// Network
|
|
24248
24280
|
SelectPeerModal,
|
|
24249
24281
|
AppInstallUpgradeCard,
|
|
24282
|
+
AppUpdateOfflineModeCard,
|
|
24250
24283
|
// Other components
|
|
24251
24284
|
TableSelectColumnsComponent,
|
|
24252
24285
|
ActionsColumnComponent,
|
|
@@ -24282,6 +24315,7 @@
|
|
|
24282
24315
|
AppPropertiesForm,
|
|
24283
24316
|
AppListForm,
|
|
24284
24317
|
AppInstallUpgradeCard,
|
|
24318
|
+
AppUpdateOfflineModeCard,
|
|
24285
24319
|
DepartmentToStringPipe,
|
|
24286
24320
|
AppIconComponent,
|
|
24287
24321
|
TextPopover,
|
|
@@ -25266,7 +25300,7 @@
|
|
|
25266
25300
|
updateDatasource: { get: function () { return _super_1.prototype.updateDatasource; } }
|
|
25267
25301
|
});
|
|
25268
25302
|
return __awaiter(this, void 0, void 0, function () {
|
|
25269
|
-
var res, existingData;
|
|
25303
|
+
var fetchMoreFn, res, existingData;
|
|
25270
25304
|
return __generator(this, function (_a) {
|
|
25271
25305
|
switch (_a.label) {
|
|
25272
25306
|
case 0:
|
|
@@ -25276,9 +25310,9 @@
|
|
|
25276
25310
|
console.warn('Cannot fetch more because still editing row');
|
|
25277
25311
|
return [2 /*return*/];
|
|
25278
25312
|
}
|
|
25279
|
-
|
|
25280
|
-
this._fetchMoreFn = null;
|
|
25281
|
-
return [4 /*yield*/,
|
|
25313
|
+
fetchMoreFn = this._fetchMoreFn;
|
|
25314
|
+
this._fetchMoreFn = null;
|
|
25315
|
+
return [4 /*yield*/, fetchMoreFn()];
|
|
25282
25316
|
case 1:
|
|
25283
25317
|
res = _a.sent();
|
|
25284
25318
|
// Skip if empty (no more data)
|
|
@@ -30321,6 +30355,7 @@
|
|
|
30321
30355
|
missingEntity: [null, SharedValidators.entity],
|
|
30322
30356
|
disableEntity: [null, SharedValidators.entity],
|
|
30323
30357
|
entities: [null, SharedFormArrayValidators.requiredArrayMinLength(1)],
|
|
30358
|
+
farEntity: [null, SharedValidators.entity]
|
|
30324
30359
|
});
|
|
30325
30360
|
this.form.get('disableEntity').disable();
|
|
30326
30361
|
}
|
|
@@ -30359,6 +30394,13 @@
|
|
|
30359
30394
|
attributes: ['label', 'name', 'description', 'comments'],
|
|
30360
30395
|
displayWith: this.entityToString
|
|
30361
30396
|
});
|
|
30397
|
+
// Far entity, in the list
|
|
30398
|
+
this.autocompleteFields.add('entity-far', {
|
|
30399
|
+
suggestFn: function (value, filter) { return _this.suggest(value, filter); },
|
|
30400
|
+
attributes: ['label', 'name'],
|
|
30401
|
+
displayWith: this.entityToString,
|
|
30402
|
+
showAllOnFocus: true
|
|
30403
|
+
});
|
|
30362
30404
|
// For mutliple value
|
|
30363
30405
|
this.autocompleteFields.add('entities-items-filter', {
|
|
30364
30406
|
service: {
|
|
@@ -30378,6 +30420,7 @@
|
|
|
30378
30420
|
return __generator(this, function (_a) {
|
|
30379
30421
|
data = {
|
|
30380
30422
|
entity: deepCopy(FAKE_ENTITIES)[0],
|
|
30423
|
+
farEntity: deepCopy(FAKE_ENTITIES)[2],
|
|
30381
30424
|
// This item is NOT in the items list => i should be displayed anyway
|
|
30382
30425
|
missingEntity: {
|
|
30383
30426
|
id: -1, label: '??', name: 'Missing item'
|
|
@@ -30473,7 +30516,7 @@
|
|
|
30473
30516
|
AutocompleteTestPage.decorators = [
|
|
30474
30517
|
{ type: i0.Component, args: [{
|
|
30475
30518
|
selector: 'app-autocomplete-test',
|
|
30476
|
-
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>\n <ion-col>\n <ion-text><h4>Debug memory leak</h4></ion-text>\n </ion-col>\n </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 [equals]=\"equals\"\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>\n <pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre>\n </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 [equals]=\"equals\"\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>\n <pre>mobile: true, items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\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>\n <pre>mobile: true, items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\n [clearable]=\"true\"\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-text color=\"primary\">\n search with a suggestLengthThreshold\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>\n </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]=\"true\"\n [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-mobile-suggestLengthThreshold]'\"\n required\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 Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"true\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-multiple]'\"\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 [equals]=\"equals\"\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>\n <pre></pre>\n </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(filterChangeField, '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\" #filterChangeField\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\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>\n <pre>class=\"min-width-large\"</pre>\n </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 [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n <ion-row>\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 <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\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 Fullscreen\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </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 [class]=\"'mat-autocomplete-panel-full-size'\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-mobile-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\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>\n <ion-text><h4>Desktop mode</h4></ion-text>\n </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></pre>\n </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 [equals]=\"equals\"\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 search with a suggestLengthThreshold\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>\n </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 [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggestLengthThreshold]'\"\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>\n <pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre>\n </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 [equals]=\"equals\"\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>\n <pre>items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\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-text color=\"primary\">\n Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"false\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-multiple]'\"\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>\n <pre>items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\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>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </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 [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\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 [equals]=\"equals\"\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 [equals]=\"equals\"\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>\n <pre>class=\"mat-autocomplete-panel-full-size\"</pre>\n </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 [equals]=\"equals\"\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>\n <pre>panelWidth: string</pre>\n </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 [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-large]'\"\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 Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n <ion-col size=\"3\">\n <mat-checkbox #showIcons [checked]=\"false\">\n Icons ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n <mat-icon matPrefix *ngIf=\"showIcons.checked\">keyboard_arrow_right</mat-icon>\n <mat-icon matSuffix *ngIf=\"showIcons.checked\">keyboard_arrow_left</mat-icon>\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\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"
|
|
30519
|
+
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>\n <ion-col>\n <ion-text><h4>Debug memory leak</h4></ion-text>\n </ion-col>\n </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 [equals]=\"equals\"\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>\n <pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"farEntity\"\n [config]=\"autocompleteFields.get('entity-far')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-far]'\"\n [required]=\"true\"\n placeholder=\"Far entity (in the list)\"\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 Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, suggestFn: (searchText, filter) => any[]</pre>\n </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 [equals]=\"equals\"\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>\n <pre>mobile: true, items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\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>\n <pre>mobile: true, items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\n [clearable]=\"true\"\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-text color=\"primary\">\n search with a suggestLengthThreshold\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>\n </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]=\"true\"\n [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-mobile-suggestLengthThreshold]'\"\n required\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 Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"true\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-multiple]'\"\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 [equals]=\"equals\"\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>\n <pre></pre>\n </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(filterChangeField, '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\" #filterChangeField\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\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>\n <pre>class=\"min-width-large\"</pre>\n </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 [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n <ion-row>\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 <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\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 Fullscreen\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </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 [class]=\"'mat-autocomplete-panel-full-size'\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-mobile-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\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>\n <ion-text><h4>Desktop mode</h4></ion-text>\n </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></pre>\n </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 [equals]=\"equals\"\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 search with a suggestLengthThreshold\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>\n </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 [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggestLengthThreshold]'\"\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>\n <pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre>\n </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 [equals]=\"equals\"\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>\n <pre>items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\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-text color=\"primary\">\n Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"false\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-multiple]'\"\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>\n <pre>items: Observable<any[]></pre>\n </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 [equals]=\"equals\"\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>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </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 [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\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 [equals]=\"equals\"\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 [equals]=\"equals\"\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>\n <pre>class=\"mat-autocomplete-panel-full-size\"</pre>\n </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 [equals]=\"equals\"\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>\n <pre>panelWidth: string</pre>\n </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 [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-large]'\"\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 Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n <ion-col size=\"3\">\n <mat-checkbox #showIcons [checked]=\"false\">\n Icons ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n <mat-icon matPrefix *ngIf=\"showIcons.checked\">keyboard_arrow_right</mat-icon>\n <mat-icon matSuffix *ngIf=\"showIcons.checked\">keyboard_arrow_left</mat-icon>\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\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"
|
|
30477
30520
|
},] }
|
|
30478
30521
|
];
|
|
30479
30522
|
AutocompleteTestPage.ctorParameters = function () { return [
|
|
@@ -31965,6 +32008,7 @@
|
|
|
31965
32008
|
exports.MessageService = MessageService;
|
|
31966
32009
|
exports.MessageTypeList = MessageTypeList;
|
|
31967
32010
|
exports.MessageTypes = MessageTypes;
|
|
32011
|
+
exports.MimeTypes = MimeTypes;
|
|
31968
32012
|
exports.ModalToolbarComponent = ModalToolbarComponent;
|
|
31969
32013
|
exports.NetworkService = NetworkService;
|
|
31970
32014
|
exports.NgInitDirective = NgInitDirective;
|
|
@@ -32049,6 +32093,7 @@
|
|
|
32049
32093
|
exports.UploadFilePopover = UploadFilePopover;
|
|
32050
32094
|
exports.UploadFileTestingModule = UploadFileTestingModule;
|
|
32051
32095
|
exports.UploadFileTestingPage = UploadFileTestingPage;
|
|
32096
|
+
exports.UriUtils = UriUtils;
|
|
32052
32097
|
exports.UserEventFragments = UserEventFragments;
|
|
32053
32098
|
exports.UserEventService = UserEventService;
|
|
32054
32099
|
exports.UserEventTypes = UserEventTypes;
|
|
@@ -32210,12 +32255,13 @@
|
|
|
32210
32255
|
exports.ɵf = RegisterModal;
|
|
32211
32256
|
exports.ɵg = UserSettingsValidatorService;
|
|
32212
32257
|
exports.ɵh = LocalSettingsValidatorService;
|
|
32213
|
-
exports.ɵi =
|
|
32214
|
-
exports.ɵj =
|
|
32215
|
-
exports.ɵk =
|
|
32216
|
-
exports.ɵl =
|
|
32217
|
-
exports.ɵm =
|
|
32218
|
-
exports.ɵn =
|
|
32258
|
+
exports.ɵi = AppUpdateOfflineModeCard;
|
|
32259
|
+
exports.ɵj = AppIconComponent;
|
|
32260
|
+
exports.ɵk = DateTestPage;
|
|
32261
|
+
exports.ɵl = NumpadTestPage;
|
|
32262
|
+
exports.ɵm = MatBadgeIconTestPage;
|
|
32263
|
+
exports.ɵn = ToastTestingModule;
|
|
32264
|
+
exports.ɵo = ToastTestingPage;
|
|
32219
32265
|
|
|
32220
32266
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
32221
32267
|
|