@sumaris-net/ngx-components 1.21.0-beta8 → 1.21.1
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 +535 -1191
- package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
- package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
- package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
- package/doc/changelog.md +12 -0
- package/esm2015/public_api.js +3 -8
- package/esm2015/src/app/core/account/account.js +2 -2
- package/esm2015/src/app/core/auth/form/form-auth.js +4 -2
- package/esm2015/src/app/core/form/editor.class.js +52 -20
- package/esm2015/src/app/core/form/entity-editor-modal.class.js +17 -6
- package/esm2015/src/app/core/form/entity-editor.class.js +1 -1
- package/esm2015/src/app/core/form/form.class.js +66 -33
- package/esm2015/src/app/core/graphql/graphql.service.js +5 -3
- package/esm2015/src/app/core/icon/icon.component.js +2 -5
- package/esm2015/src/app/core/menu/menu.component.js +2 -2
- package/esm2015/src/app/core/services/local-settings.service.js +2 -2
- package/esm2015/src/app/core/table/table.class.js +18 -23
- package/esm2015/src/app/shared/functions.js +1 -60
- package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +5 -4
- package/esm2015/src/app/shared/material/autocomplete/testing/autocomplete.test.js +10 -7
- package/esm2015/src/app/shared/material/chips/material.chips.js +3 -2
- package/esm2015/src/app/shared/material/chips/testing/chips.test.js +3 -2
- package/esm2015/src/app/shared/material/datetime/material.date.js +3 -2
- package/esm2015/src/app/shared/material/datetime/material.datetime.js +3 -2
- package/esm2015/src/app/shared/observables.js +13 -7
- package/esm2015/src/app/shared/pipes/arrays.pipe.js +1 -1
- package/esm2015/src/app/shared/pipes/form.pipes.js +4 -6
- package/esm2015/src/app/shared/pipes/highlight.pipe.js +4 -4
- package/esm2015/src/app/shared/pipes/string.pipes.js +7 -18
- package/esm2015/src/app/shared/services/memory-entity-service.class.js +13 -1
- package/esm2015/src/app/shared/services.js +61 -0
- package/esm2015/src/app/shared/types.js +1 -1
- package/esm2015/src/app/social/social.errors.js +2 -5
- package/esm2015/src/app/social/social.module.js +15 -10
- package/esm2015/src/app/social/user-event/user-event.model.js +2 -58
- package/esm2015/src/app/social/user-event/user-event.service.js +167 -293
- package/esm2015/src/app/social/user-event/user-events.table.js +12 -17
- package/esm2015/sumaris-net.ngx-components.js +6 -8
- package/fesm2015/sumaris-net.ngx-components.js +437 -990
- package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
- package/package.json +3 -2
- package/public_api.d.ts +2 -7
- package/src/app/core/auth/form/form-auth.d.ts +1 -1
- package/src/app/core/form/editor.class.d.ts +38 -12
- package/src/app/core/form/entity-editor-modal.class.d.ts +1 -0
- package/src/app/core/form/entity-editor.class.d.ts +6 -2
- package/src/app/core/form/form.class.d.ts +32 -19
- package/src/app/core/icon/icon.component.d.ts +4 -4
- package/src/app/core/table/table.class.d.ts +15 -14
- package/src/app/shared/functions.d.ts +0 -9
- package/src/app/shared/material/autocomplete/testing/autocomplete.test.d.ts +1 -2
- package/src/app/shared/material/badge/badge-icon.test.d.ts +1 -1
- package/src/app/shared/observables.d.ts +1 -0
- package/src/app/shared/pipes/form.pipes.d.ts +1 -2
- package/src/app/shared/services/memory-entity-service.class.d.ts +6 -0
- package/src/app/shared/services.d.ts +9 -0
- package/src/app/shared/types.d.ts +0 -4
- package/src/app/social/social.errors.d.ts +0 -3
- package/src/app/social/social.module.d.ts +0 -8
- package/src/app/social/user-event/user-event.model.d.ts +6 -51
- package/src/app/social/user-event/user-event.service.d.ts +51 -79
- package/src/app/social/user-event/user-events.table.d.ts +6 -6
- package/src/assets/i18n/en-US.json +2 -15
- package/src/assets/i18n/en.json +2 -15
- package/src/assets/i18n/fr.json +1 -14
- package/src/theme/_ngx-components.scss +0 -7
- package/sumaris-net.ngx-components.d.ts +5 -7
- package/sumaris-net.ngx-components.metadata.json +1 -1
- package/esm2015/src/app/social/job/job.model.js +0 -24
- package/esm2015/src/app/social/job/job.module.js +0 -25
- package/esm2015/src/app/social/job/job.service.js +0 -53
- package/esm2015/src/app/social/job/progression/job-progression.component.js +0 -192
- package/esm2015/src/app/social/job/progression/job-progression.list.js +0 -20
- package/esm2015/src/app/social/message/message.module.js +0 -25
- package/esm2015/src/app/social/user-event/notification/user-event-notification.component.js +0 -92
- package/esm2015/src/app/social/user-event/notification/user-event-notification.list.js +0 -39
- package/esm2015/src/app/social/user-event/user-event.module.js +0 -28
- package/src/app/social/job/job.model.d.ts +0 -32
- package/src/app/social/job/job.module.d.ts +0 -2
- package/src/app/social/job/job.service.d.ts +0 -23
- package/src/app/social/job/progression/job-progression.component.d.ts +0 -43
- package/src/app/social/job/progression/job-progression.list.d.ts +0 -12
- package/src/app/social/message/message.module.d.ts +0 -2
- package/src/app/social/user-event/notification/user-event-notification.component.d.ts +0 -25
- package/src/app/social/user-event/notification/user-event-notification.list.d.ts +0 -20
- package/src/app/social/user-event/user-event.module.d.ts +0 -2
|
@@ -241,64 +241,6 @@ function changeCaseToUnderscore(value) {
|
|
|
241
241
|
function removeDiacritics(text) {
|
|
242
242
|
return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
243
243
|
}
|
|
244
|
-
function suggestFromArray(items, value, opts) {
|
|
245
|
-
if (isNotNil(value) && typeof value === 'object')
|
|
246
|
-
return { data: [value] };
|
|
247
|
-
value = (typeof value === 'string' && value !== '*') && value.toUpperCase() || undefined;
|
|
248
|
-
const keys = opts && (opts.searchAttribute && [opts.searchAttribute] || opts.searchAttributes) || ['label'];
|
|
249
|
-
if (!items) {
|
|
250
|
-
return { data: [], total: 0 };
|
|
251
|
-
}
|
|
252
|
-
// Filter items
|
|
253
|
-
let filteredItems = items;
|
|
254
|
-
if (isNotNilOrBlank(value)) {
|
|
255
|
-
// If wildcard, search using regexp
|
|
256
|
-
if (value.indexOf('*') !== -1) {
|
|
257
|
-
value = value.replace(/[*]+/g, '.*');
|
|
258
|
-
filteredItems = filteredItems.filter(v => keys.findIndex(key => matchUpperCase(getPropertyByPathAsString(v, key), value)) !== -1);
|
|
259
|
-
}
|
|
260
|
-
// Else (no wildcard), search using startsWith
|
|
261
|
-
else {
|
|
262
|
-
filteredItems = filteredItems.filter(v => keys.findIndex(key => startsWithUpperCase(getPropertyByPathAsString(v, key), value)) !== -1);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
// Exclude ids
|
|
266
|
-
if (isNotEmptyArray(opts === null || opts === void 0 ? void 0 : opts.excludedIds)) {
|
|
267
|
-
filteredItems = filteredItems.filter(v => !opts.excludedIds.includes(+v['id']));
|
|
268
|
-
}
|
|
269
|
-
// Sort
|
|
270
|
-
if (!opts || opts.skipSort !== true) {
|
|
271
|
-
// Make to copy input items, before sorting (if not yet already done)
|
|
272
|
-
if (filteredItems === items)
|
|
273
|
-
filteredItems = filteredItems.slice();
|
|
274
|
-
// Sort by keys
|
|
275
|
-
filteredItems.sort(propertiesPathComparator(keys));
|
|
276
|
-
}
|
|
277
|
-
const total = filteredItems.length || 0;
|
|
278
|
-
// Pagination (truncate if need)
|
|
279
|
-
let pageData = filteredItems;
|
|
280
|
-
if (opts) {
|
|
281
|
-
if ((opts.offset || 0) > 0) {
|
|
282
|
-
pageData = pageData.slice(opts.offset);
|
|
283
|
-
}
|
|
284
|
-
if (isNotNil(opts.size) && pageData.length > opts.size) {
|
|
285
|
-
pageData = pageData.slice(0, opts.size);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
const result = {
|
|
289
|
-
data: pageData,
|
|
290
|
-
total
|
|
291
|
-
};
|
|
292
|
-
// Add fetch more capability, if total was fetched
|
|
293
|
-
const nextOffset = (opts && opts.offset || 0) + pageData.length;
|
|
294
|
-
if (nextOffset < total) {
|
|
295
|
-
result.fetchMore = (_) => __awaiter(this, void 0, void 0, function* () {
|
|
296
|
-
return suggestFromArray(filteredItems, undefined /*OPTIMISATION: already applied*/, Object.assign(Object.assign({}, opts), { offset: nextOffset, skipSort: true, excludedIds: undefined // OPTIMISATION: already filtered
|
|
297
|
-
}));
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
return result;
|
|
301
|
-
}
|
|
302
244
|
function suggestFromStringArray(values, value, options) {
|
|
303
245
|
value = (typeof value === 'string' && value !== '*') && value.toUpperCase() || undefined;
|
|
304
246
|
if (isNilOrBlank(value))
|
|
@@ -843,11 +785,11 @@ function chainPromises(defers) {
|
|
|
843
785
|
}, null);
|
|
844
786
|
}
|
|
845
787
|
function firstTrue(obs) {
|
|
846
|
-
return obs.pipe(first(
|
|
788
|
+
return obs.pipe(first(value => value === true), map(_ => { }) // Convert to void
|
|
847
789
|
);
|
|
848
790
|
}
|
|
849
791
|
function firstFalse(obs) {
|
|
850
|
-
return obs.pipe(first(
|
|
792
|
+
return obs.pipe(first(value => value === false), map(_ => { }) // Convert to void
|
|
851
793
|
);
|
|
852
794
|
}
|
|
853
795
|
/**
|
|
@@ -879,12 +821,11 @@ function waitFor(predicate, opts) {
|
|
|
879
821
|
}
|
|
880
822
|
function waitForTrue(observable, opts) {
|
|
881
823
|
return __awaiter(this, void 0, void 0, function* () {
|
|
882
|
-
const firstTrueObservable = firstTrue(observable);
|
|
883
824
|
// Timeout (+ dueTime)
|
|
884
825
|
if (opts && opts.timeout > 0) {
|
|
885
826
|
const $timeout = timer(opts.timeout);
|
|
886
827
|
return merge(timer(opts.dueTime || 0)
|
|
887
|
-
.pipe(switchMap(() =>
|
|
828
|
+
.pipe(switchMap(() => firstTrue(observable)), takeUntil($timeout)), $timeout
|
|
888
829
|
.pipe(map(() => {
|
|
889
830
|
throw new Error(`Timeout ready() - after ${opts.timeout}ms`);
|
|
890
831
|
})))
|
|
@@ -893,10 +834,17 @@ function waitForTrue(observable, opts) {
|
|
|
893
834
|
// dueTime (without timeout)
|
|
894
835
|
if (opts && opts.dueTime > 0) {
|
|
895
836
|
return timer(opts.dueTime)
|
|
896
|
-
.pipe(switchMap(() =>
|
|
837
|
+
.pipe(switchMap(() => firstTrue(observable)))
|
|
897
838
|
.toPromise();
|
|
898
839
|
}
|
|
899
|
-
return
|
|
840
|
+
return firstTrue(observable).toPromise();
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
function waitForFalse(observable, opts) {
|
|
844
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
845
|
+
return waitForTrue(
|
|
846
|
+
// Inverse the logic
|
|
847
|
+
observable.pipe(map(v => v === false)), opts);
|
|
900
848
|
});
|
|
901
849
|
}
|
|
902
850
|
|
|
@@ -1100,6 +1048,65 @@ const isMobile = (win) => {
|
|
|
1100
1048
|
return _cache.mobile;
|
|
1101
1049
|
};
|
|
1102
1050
|
|
|
1051
|
+
function suggestFromArray(items, value, opts) {
|
|
1052
|
+
if (isNotNil(value) && typeof value === 'object')
|
|
1053
|
+
return { data: [value] };
|
|
1054
|
+
value = (typeof value === 'string' && value !== '*') && value.toUpperCase() || undefined;
|
|
1055
|
+
const keys = opts && (opts.searchAttribute && [opts.searchAttribute] || opts.searchAttributes) || ['label'];
|
|
1056
|
+
if (!items) {
|
|
1057
|
+
return { data: [], total: 0 };
|
|
1058
|
+
}
|
|
1059
|
+
// Filter items
|
|
1060
|
+
let filteredItems = items;
|
|
1061
|
+
if (isNotNilOrBlank(value)) {
|
|
1062
|
+
// If wildcard, search using regexp
|
|
1063
|
+
if (value.indexOf('*') !== -1) {
|
|
1064
|
+
value = value.replace(/[*]+/g, '.*');
|
|
1065
|
+
filteredItems = filteredItems.filter(v => keys.findIndex(key => matchUpperCase(getPropertyByPathAsString(v, key), value)) !== -1);
|
|
1066
|
+
}
|
|
1067
|
+
// Else (no wildcard), search using startsWith
|
|
1068
|
+
else {
|
|
1069
|
+
filteredItems = filteredItems.filter(v => keys.findIndex(key => startsWithUpperCase(getPropertyByPathAsString(v, key), value)) !== -1);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
// Exclude ids
|
|
1073
|
+
if (isNotEmptyArray(opts === null || opts === void 0 ? void 0 : opts.excludedIds)) {
|
|
1074
|
+
filteredItems = filteredItems.filter(v => !opts.excludedIds.includes(+v['id']));
|
|
1075
|
+
}
|
|
1076
|
+
// Sort
|
|
1077
|
+
if (!opts || opts.skipSort !== true) {
|
|
1078
|
+
// Make to copy input items, before sorting (if not yet already done)
|
|
1079
|
+
if (filteredItems === items)
|
|
1080
|
+
filteredItems = filteredItems.slice();
|
|
1081
|
+
// Sort by keys
|
|
1082
|
+
filteredItems.sort(propertiesPathComparator(keys));
|
|
1083
|
+
}
|
|
1084
|
+
const total = filteredItems.length || 0;
|
|
1085
|
+
// Pagination (truncate if need)
|
|
1086
|
+
let pageData = filteredItems;
|
|
1087
|
+
if (opts) {
|
|
1088
|
+
if ((opts.offset || 0) > 0) {
|
|
1089
|
+
pageData = pageData.slice(opts.offset);
|
|
1090
|
+
}
|
|
1091
|
+
if (isNotNil(opts.size) && pageData.length > opts.size) {
|
|
1092
|
+
pageData = pageData.slice(0, opts.size);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
const result = {
|
|
1096
|
+
data: pageData,
|
|
1097
|
+
total
|
|
1098
|
+
};
|
|
1099
|
+
// Add fetch more capability, if total was fetched
|
|
1100
|
+
const nextOffset = (opts && opts.offset || 0) + pageData.length;
|
|
1101
|
+
if (nextOffset < total) {
|
|
1102
|
+
result.fetchMore = (_) => __awaiter(this, void 0, void 0, function* () {
|
|
1103
|
+
return suggestFromArray(filteredItems, undefined /*OPTIMISATION: already applied*/, Object.assign(Object.assign({}, opts), { offset: nextOffset, skipSort: true, excludedIds: undefined // OPTIMISATION: already filtered
|
|
1104
|
+
}));
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
return result;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1103
1110
|
class MatAutocompleteConfigHolder {
|
|
1104
1111
|
constructor(options) {
|
|
1105
1112
|
this.options = options;
|
|
@@ -1360,11 +1367,11 @@ class MatAutocompleteField {
|
|
|
1360
1367
|
// Search text (no distinctUntilChanged() because of the debounceTime() pipe)
|
|
1361
1368
|
this.formControl.valueChanges
|
|
1362
1369
|
.pipe(filter(value => this.enabled && isNotNilString(value)),
|
|
1363
|
-
// Mark as loading (to show loading spinner) -
|
|
1370
|
+
// Mark as loading (to show loading spinner) - as soon as possible, and before debounceTime
|
|
1364
1371
|
tap(_ => this.showLoadingSpinner && this.markAsLoading()),
|
|
1365
1372
|
// Filter if not enough character
|
|
1366
1373
|
filter(value => {
|
|
1367
|
-
if (value.length
|
|
1374
|
+
if (((value === null || value === void 0 ? void 0 : value.length) || 0) < this.suggestLengthThreshold) {
|
|
1368
1375
|
// Update display value, to enable the message "not enough characters"
|
|
1369
1376
|
this.displayValue = value;
|
|
1370
1377
|
return false;
|
|
@@ -2328,9 +2335,9 @@ class HighlightPipe {
|
|
|
2328
2335
|
const cleanedSearchText = removeDiacritics(searchRegexp).toUpperCase();
|
|
2329
2336
|
const index = removeDiacritics(value.toUpperCase()).indexOf(cleanedSearchText);
|
|
2330
2337
|
if (index !== -1) {
|
|
2331
|
-
return value.
|
|
2332
|
-
'<b>' + value.
|
|
2333
|
-
value.
|
|
2338
|
+
return value.substring(0, index - 1) +
|
|
2339
|
+
'<b>' + value.substring(index, cleanedSearchText.length) + '</b>' +
|
|
2340
|
+
value.substring(index + cleanedSearchText.length);
|
|
2334
2341
|
}
|
|
2335
2342
|
return value;
|
|
2336
2343
|
}
|
|
@@ -2728,60 +2735,50 @@ class IsNotNilOrBlankPipe {
|
|
|
2728
2735
|
return isNotNilOrBlank(value);
|
|
2729
2736
|
}
|
|
2730
2737
|
}
|
|
2731
|
-
IsNotNilOrBlankPipe.ɵprov = ɵɵdefineInjectable({ factory: function IsNotNilOrBlankPipe_Factory() { return new IsNotNilOrBlankPipe(); }, token: IsNotNilOrBlankPipe, providedIn: "root" });
|
|
2732
2738
|
IsNotNilOrBlankPipe.decorators = [
|
|
2733
2739
|
{ type: Pipe, args: [{
|
|
2734
2740
|
name: 'isNotNilOrBlank'
|
|
2735
|
-
},] }
|
|
2736
|
-
{ type: Injectable, args: [{ providedIn: 'root' },] }
|
|
2741
|
+
},] }
|
|
2737
2742
|
];
|
|
2738
2743
|
class IsNilOrBlankPipe {
|
|
2739
2744
|
transform(value) {
|
|
2740
2745
|
return isNilOrBlank(value);
|
|
2741
2746
|
}
|
|
2742
2747
|
}
|
|
2743
|
-
IsNilOrBlankPipe.ɵprov = ɵɵdefineInjectable({ factory: function IsNilOrBlankPipe_Factory() { return new IsNilOrBlankPipe(); }, token: IsNilOrBlankPipe, providedIn: "root" });
|
|
2744
2748
|
IsNilOrBlankPipe.decorators = [
|
|
2745
2749
|
{ type: Pipe, args: [{
|
|
2746
2750
|
name: 'isNilOrBlank'
|
|
2747
|
-
},] }
|
|
2748
|
-
{ type: Injectable, args: [{ providedIn: 'root' },] }
|
|
2751
|
+
},] }
|
|
2749
2752
|
];
|
|
2750
2753
|
class ToStringPipe {
|
|
2751
2754
|
transform(value) {
|
|
2752
2755
|
return (value !== null && value !== undefined) ? value.toString() : '';
|
|
2753
2756
|
}
|
|
2754
2757
|
}
|
|
2755
|
-
ToStringPipe.ɵprov = ɵɵdefineInjectable({ factory: function ToStringPipe_Factory() { return new ToStringPipe(); }, token: ToStringPipe, providedIn: "root" });
|
|
2756
2758
|
ToStringPipe.decorators = [
|
|
2757
2759
|
{ type: Pipe, args: [{
|
|
2758
2760
|
name: 'toString'
|
|
2759
|
-
},] }
|
|
2760
|
-
{ type: Injectable, args: [{ providedIn: 'root' },] }
|
|
2761
|
+
},] }
|
|
2761
2762
|
];
|
|
2762
2763
|
class StrLengthPipe {
|
|
2763
2764
|
transform(value) {
|
|
2764
2765
|
return value && value.length || 0;
|
|
2765
2766
|
}
|
|
2766
2767
|
}
|
|
2767
|
-
StrLengthPipe.ɵprov = ɵɵdefineInjectable({ factory: function StrLengthPipe_Factory() { return new StrLengthPipe(); }, token: StrLengthPipe, providedIn: "root" });
|
|
2768
2768
|
StrLengthPipe.decorators = [
|
|
2769
2769
|
{ type: Pipe, args: [{
|
|
2770
2770
|
name: 'strLength'
|
|
2771
|
-
},] }
|
|
2772
|
-
{ type: Injectable, args: [{ providedIn: 'root' },] }
|
|
2771
|
+
},] }
|
|
2773
2772
|
];
|
|
2774
2773
|
class StrIncludesPipe {
|
|
2775
2774
|
transform(value, searchString, position) {
|
|
2776
2775
|
return (value === null || value === void 0 ? void 0 : value.includes(searchString, position)) || false;
|
|
2777
2776
|
}
|
|
2778
2777
|
}
|
|
2779
|
-
StrIncludesPipe.ɵprov = ɵɵdefineInjectable({ factory: function StrIncludesPipe_Factory() { return new StrIncludesPipe(); }, token: StrIncludesPipe, providedIn: "root" });
|
|
2780
2778
|
StrIncludesPipe.decorators = [
|
|
2781
2779
|
{ type: Pipe, args: [{
|
|
2782
2780
|
name: 'strIncludes'
|
|
2783
|
-
},] }
|
|
2784
|
-
{ type: Injectable, args: [{ providedIn: 'root' },] }
|
|
2781
|
+
},] }
|
|
2785
2782
|
];
|
|
2786
2783
|
|
|
2787
2784
|
class TranslateContextService {
|
|
@@ -4203,7 +4200,7 @@ FormGetPipe.decorators = [
|
|
|
4203
4200
|
];
|
|
4204
4201
|
class FormGetControlPipe {
|
|
4205
4202
|
transform(form, path) {
|
|
4206
|
-
return (form && path && form.get(path) || form);
|
|
4203
|
+
return (form && isNotNil(path) && form.get(path) || form);
|
|
4207
4204
|
}
|
|
4208
4205
|
}
|
|
4209
4206
|
FormGetControlPipe.decorators = [
|
|
@@ -4232,8 +4229,7 @@ FormGetGroupPipe.decorators = [
|
|
|
4232
4229
|
},] }
|
|
4233
4230
|
];
|
|
4234
4231
|
class FormGetValuePipe {
|
|
4235
|
-
constructor(
|
|
4236
|
-
this.adapter = adapter;
|
|
4232
|
+
constructor(_ref) {
|
|
4237
4233
|
this._ref = _ref;
|
|
4238
4234
|
this.value = undefined;
|
|
4239
4235
|
this._lastControl = null;
|
|
@@ -4298,7 +4294,6 @@ FormGetValuePipe.decorators = [
|
|
|
4298
4294
|
},] }
|
|
4299
4295
|
];
|
|
4300
4296
|
FormGetValuePipe.ctorParameters = () => [
|
|
4301
|
-
{ type: FormErrorTranslator },
|
|
4302
4297
|
{ type: ChangeDetectorRef }
|
|
4303
4298
|
];
|
|
4304
4299
|
|
|
@@ -5169,7 +5164,8 @@ class MatDate {
|
|
|
5169
5164
|
set tabindex(value) {
|
|
5170
5165
|
if (this._tabindex !== value) {
|
|
5171
5166
|
this._tabindex = value;
|
|
5172
|
-
|
|
5167
|
+
if (!this._writing)
|
|
5168
|
+
this.updateTabIndex();
|
|
5173
5169
|
}
|
|
5174
5170
|
}
|
|
5175
5171
|
get tabindex() {
|
|
@@ -5528,7 +5524,8 @@ class MatDateTime {
|
|
|
5528
5524
|
set tabindex(value) {
|
|
5529
5525
|
if (this._tabindex !== value) {
|
|
5530
5526
|
this._tabindex = value;
|
|
5531
|
-
|
|
5527
|
+
if (!this._writing)
|
|
5528
|
+
this.updateTabIndex();
|
|
5532
5529
|
}
|
|
5533
5530
|
}
|
|
5534
5531
|
get tabindex() {
|
|
@@ -10707,7 +10704,7 @@ class LocalSettingsService extends StartableService {
|
|
|
10707
10704
|
}
|
|
10708
10705
|
get usageMode() {
|
|
10709
10706
|
var _a;
|
|
10710
|
-
if (isNil((_a = this._data) === null || _a === void 0 ? void 0 : _a.
|
|
10707
|
+
if (isNil((_a = this._data) === null || _a === void 0 ? void 0 : _a.usageMode)) {
|
|
10711
10708
|
console.warn("[settings] Accessing to property 'usageMode' BEFORE service started! Please use ready()");
|
|
10712
10709
|
return isCordova(window) ? 'FIELD' : 'DESK';
|
|
10713
10710
|
}
|
|
@@ -13307,7 +13304,8 @@ class GraphqlService extends StartableService {
|
|
|
13307
13304
|
console.debug('[graphql] Apply token authentication to headers');
|
|
13308
13305
|
this.connectionParams.authToken = token;
|
|
13309
13306
|
}
|
|
13310
|
-
|
|
13307
|
+
// Clean auth token
|
|
13308
|
+
else if (this.connectionParams.authToken) {
|
|
13311
13309
|
console.debug('[graphql] Remove token authentication from headers');
|
|
13312
13310
|
delete this.connectionParams.authToken;
|
|
13313
13311
|
// Clear cache
|
|
@@ -13319,7 +13317,8 @@ class GraphqlService extends StartableService {
|
|
|
13319
13317
|
console.debug('[graphql] Apply basic authentication to headers');
|
|
13320
13318
|
this.connectionParams.authBasic = basic;
|
|
13321
13319
|
}
|
|
13322
|
-
|
|
13320
|
+
// Clean auth basic
|
|
13321
|
+
else if (this.connectionParams.authBasic) {
|
|
13323
13322
|
console.debug('[graphql] Remove basic authentication from headers');
|
|
13324
13323
|
delete this.connectionParams.authBasic;
|
|
13325
13324
|
// Clear cache
|
|
@@ -17425,12 +17424,12 @@ class FormFieldValuesHolder {
|
|
|
17425
17424
|
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
17426
17425
|
class AppForm {
|
|
17427
17426
|
constructor(injector, form) {
|
|
17428
|
-
this.
|
|
17427
|
+
this._subscription = new Subscription();
|
|
17429
17428
|
this._enable = false;
|
|
17430
|
-
this._$ready = new BehaviorSubject(false);
|
|
17431
|
-
this._$loading = new BehaviorSubject(true);
|
|
17432
17429
|
this.i18nFieldPrefix = null;
|
|
17433
|
-
this.
|
|
17430
|
+
this.readySubject = new BehaviorSubject(false);
|
|
17431
|
+
this.loadingSubject = new BehaviorSubject(true);
|
|
17432
|
+
this.errorSubject = new BehaviorSubject(undefined);
|
|
17434
17433
|
this.debug = false;
|
|
17435
17434
|
this.onCancel = new EventEmitter();
|
|
17436
17435
|
this.onSubmit = new EventEmitter();
|
|
@@ -17456,8 +17455,29 @@ class AppForm {
|
|
|
17456
17455
|
get _loading() {
|
|
17457
17456
|
return this._$loading.value;
|
|
17458
17457
|
}
|
|
17458
|
+
/**
|
|
17459
|
+
* @deprecated
|
|
17460
|
+
*/
|
|
17461
|
+
get _$ready() {
|
|
17462
|
+
return this.readySubject;
|
|
17463
|
+
}
|
|
17464
|
+
/**
|
|
17465
|
+
* @deprecated
|
|
17466
|
+
*/
|
|
17467
|
+
get _$loading() {
|
|
17468
|
+
return this.loadingSubject;
|
|
17469
|
+
}
|
|
17470
|
+
get error() {
|
|
17471
|
+
return this.errorSubject.value;
|
|
17472
|
+
}
|
|
17473
|
+
set error(error) {
|
|
17474
|
+
this.setError(error);
|
|
17475
|
+
}
|
|
17459
17476
|
get loading() {
|
|
17460
|
-
return this.
|
|
17477
|
+
return this.loadingSubject.value;
|
|
17478
|
+
}
|
|
17479
|
+
get loaded() {
|
|
17480
|
+
return !this.loadingSubject.value;
|
|
17461
17481
|
}
|
|
17462
17482
|
get value() {
|
|
17463
17483
|
return this.form.value;
|
|
@@ -17466,7 +17486,8 @@ class AppForm {
|
|
|
17466
17486
|
this.setValue(data);
|
|
17467
17487
|
}
|
|
17468
17488
|
get dirty() {
|
|
17469
|
-
|
|
17489
|
+
var _a;
|
|
17490
|
+
return ((_a = this.form) === null || _a === void 0 ? void 0 : _a.dirty) || false;
|
|
17470
17491
|
}
|
|
17471
17492
|
get invalid() {
|
|
17472
17493
|
return !this.form || this.form.invalid;
|
|
@@ -17475,7 +17496,8 @@ class AppForm {
|
|
|
17475
17496
|
return !this.form || (this.form.dirty && this.form.pending);
|
|
17476
17497
|
}
|
|
17477
17498
|
get valid() {
|
|
17478
|
-
|
|
17499
|
+
var _a;
|
|
17500
|
+
return ((_a = this.form) === null || _a === void 0 ? void 0 : _a.valid) || false;
|
|
17479
17501
|
}
|
|
17480
17502
|
get empty() {
|
|
17481
17503
|
return !this.form || (!this.form.dirty && !this.form.touched);
|
|
@@ -17521,17 +17543,16 @@ class AppForm {
|
|
|
17521
17543
|
}
|
|
17522
17544
|
ngOnDestroy() {
|
|
17523
17545
|
this._subscription.unsubscribe();
|
|
17524
|
-
this.
|
|
17546
|
+
this.readySubject.unsubscribe();
|
|
17547
|
+
this.loadingSubject.unsubscribe();
|
|
17548
|
+
this.errorSubject.unsubscribe();
|
|
17525
17549
|
this.onCancel.unsubscribe();
|
|
17526
|
-
this.onSubmit.complete();
|
|
17527
17550
|
this.onSubmit.unsubscribe();
|
|
17528
|
-
this._$ready.complete();
|
|
17529
|
-
this._$ready.unsubscribe();
|
|
17530
|
-
this._$loading.complete();
|
|
17531
|
-
this._$loading.unsubscribe();
|
|
17532
17551
|
}
|
|
17533
17552
|
cancel() {
|
|
17534
|
-
this
|
|
17553
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17554
|
+
this.onCancel.emit();
|
|
17555
|
+
});
|
|
17535
17556
|
}
|
|
17536
17557
|
/**
|
|
17537
17558
|
*
|
|
@@ -17626,22 +17647,14 @@ class AppForm {
|
|
|
17626
17647
|
this.markForCheck();
|
|
17627
17648
|
}
|
|
17628
17649
|
markAsLoading(opts) {
|
|
17629
|
-
|
|
17630
|
-
this._$loading.next(true);
|
|
17631
|
-
if (!opts || opts.emitEvent !== false)
|
|
17632
|
-
this.markForCheck();
|
|
17633
|
-
}
|
|
17650
|
+
this.setLoading(true, opts);
|
|
17634
17651
|
}
|
|
17635
17652
|
markAsLoaded(opts) {
|
|
17636
|
-
|
|
17637
|
-
this._$loading.next(false);
|
|
17638
|
-
if (!opts || opts.emitEvent !== false)
|
|
17639
|
-
this.markForCheck();
|
|
17640
|
-
}
|
|
17653
|
+
this.setLoading(false, opts);
|
|
17641
17654
|
}
|
|
17642
17655
|
markAsReady(opts) {
|
|
17643
|
-
if (this.
|
|
17644
|
-
this.
|
|
17656
|
+
if (this.readySubject.value !== true) {
|
|
17657
|
+
this.readySubject.next(true);
|
|
17645
17658
|
// If subclasses implements OnReady
|
|
17646
17659
|
if (typeof this['ngOnReady'] === 'function') {
|
|
17647
17660
|
this.ngOnReady();
|
|
@@ -17653,16 +17666,18 @@ class AppForm {
|
|
|
17653
17666
|
* @param opts
|
|
17654
17667
|
*/
|
|
17655
17668
|
ready(opts) {
|
|
17656
|
-
|
|
17669
|
+
if (this.readySubject.value)
|
|
17670
|
+
return Promise.resolve();
|
|
17671
|
+
return waitForTrue(this.readySubject, opts);
|
|
17657
17672
|
}
|
|
17658
17673
|
/**
|
|
17659
|
-
* Wait form is
|
|
17674
|
+
* Wait form is not busy (=loaded)
|
|
17660
17675
|
* @param opts
|
|
17661
17676
|
*/
|
|
17662
17677
|
waitIdle(opts) {
|
|
17663
|
-
|
|
17664
|
-
return
|
|
17665
|
-
|
|
17678
|
+
if (!this.loadingSubject.value)
|
|
17679
|
+
return Promise.resolve();
|
|
17680
|
+
return waitForFalse(this.loadingSubject, opts);
|
|
17666
17681
|
}
|
|
17667
17682
|
updateValueAndValidity(opts) {
|
|
17668
17683
|
AppFormUtils.updateValueAndValidity(this.form, opts);
|
|
@@ -17692,10 +17707,27 @@ class AppForm {
|
|
|
17692
17707
|
registerAutocompleteField(fieldName, opts) {
|
|
17693
17708
|
return this.autocompleteHelper.add(fieldName, opts);
|
|
17694
17709
|
}
|
|
17710
|
+
setError(value, opts) {
|
|
17711
|
+
if (this.errorSubject.value !== value) {
|
|
17712
|
+
this.errorSubject.next(value);
|
|
17713
|
+
if (!opts || opts.emitEvent !== false) {
|
|
17714
|
+
this.markForCheck();
|
|
17715
|
+
}
|
|
17716
|
+
}
|
|
17717
|
+
}
|
|
17695
17718
|
markForCheck() {
|
|
17696
17719
|
// Should be overwritten by subclasses
|
|
17697
17720
|
console.warn('markForCheck() has been called, but is not overwritten by component ' + this.constructor.name);
|
|
17698
17721
|
}
|
|
17722
|
+
/* -- private function -- */
|
|
17723
|
+
setLoading(value, opts) {
|
|
17724
|
+
if (this.loadingSubject.value !== value) {
|
|
17725
|
+
this.loadingSubject.next(value);
|
|
17726
|
+
if (!opts || opts.emitEvent !== false) {
|
|
17727
|
+
this.markForCheck();
|
|
17728
|
+
}
|
|
17729
|
+
}
|
|
17730
|
+
}
|
|
17699
17731
|
}
|
|
17700
17732
|
AppForm.decorators = [
|
|
17701
17733
|
{ type: Directive }
|
|
@@ -18213,6 +18245,18 @@ class InMemoryEntitiesService extends EntitiesService {
|
|
|
18213
18245
|
return this._equalsFn(d1, d2);
|
|
18214
18246
|
return d1 && d1.equals ? d1.equals(d2) : EntityUtils.equals(d1, d2, 'id');
|
|
18215
18247
|
}
|
|
18248
|
+
/**
|
|
18249
|
+
* Count data stored by the service (without hidden data).
|
|
18250
|
+
* @param opts
|
|
18251
|
+
*/
|
|
18252
|
+
get count() {
|
|
18253
|
+
var _a;
|
|
18254
|
+
return (((_a = this.data) === null || _a === void 0 ? void 0 : _a.length) || 0);
|
|
18255
|
+
}
|
|
18256
|
+
get hiddenCount() {
|
|
18257
|
+
var _a;
|
|
18258
|
+
return ((_a = this._hiddenData) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
18259
|
+
}
|
|
18216
18260
|
/* -- protected methods -- */
|
|
18217
18261
|
filter(data, _filter, hiddenData) {
|
|
18218
18262
|
// if filter is DataFilter instance, use its test function
|
|
@@ -18766,7 +18810,9 @@ class AuthForm extends AppForm {
|
|
|
18766
18810
|
}
|
|
18767
18811
|
}
|
|
18768
18812
|
cancel() {
|
|
18769
|
-
this
|
|
18813
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18814
|
+
this.onCancel.emit();
|
|
18815
|
+
});
|
|
18770
18816
|
}
|
|
18771
18817
|
doSubmit(event) {
|
|
18772
18818
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -19623,7 +19669,7 @@ class AccountPage extends AppForm {
|
|
|
19623
19669
|
cancel: { get: () => super.cancel }
|
|
19624
19670
|
});
|
|
19625
19671
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19626
|
-
_super.cancel.call(this);
|
|
19672
|
+
yield _super.cancel.call(this);
|
|
19627
19673
|
});
|
|
19628
19674
|
}
|
|
19629
19675
|
markForCheck() {
|
|
@@ -21431,7 +21477,7 @@ class MenuComponent {
|
|
|
21431
21477
|
MenuComponent.decorators = [
|
|
21432
21478
|
{ type: Component, args: [{
|
|
21433
21479
|
selector: 'app-menu',
|
|
21434
|
-
template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n
|
|
21480
|
+
template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n </ion-row>\n </ion-grid>\n\n </ion-toolbar>\n\n <!-- User not logged -->\n <ng-template #notLogin>\n <mat-toolbar class=\"ion-padding\" @fadeInAnimation\n style=\"height: unset; display: block; margin: auto; text-align: center;\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"150px;\">\n <span *ngIf=\"!logo\" style=\"width: 150px\">{{appName}}</span>\n </mat-toolbar>\n </ng-template>\n </ion-header>\n\n <ion-content [class.has-user-header]=\"isLogin\">\n\n <ion-list lines=\"none\">\n <ion-menu-toggle auto-hide=\"false\"\n [class.flex-spacer]=\"item.cssClass == 'flex-spacer'\"\n *ngFor=\"let item of $items | async\">\n\n <!-- link -->\n <ion-item *ngIf=\"!loading && item.path\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n routerLinkActive=\"selected\"\n [routerLinkActiveOptions]=\"{exact: (item.path === '/')}\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- action -->\n <ion-item *ngIf=\"!loading && item.action\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n (click)=\"doAction(item.action, $event)\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- divider -->\n <ion-item-divider @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}}\"\n *ngIf=\"!loading && !item.path && !item.action\">\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item-divider>\n\n </ion-menu-toggle>\n </ion-list>\n </ion-content>\n\n <ion-footer class=\"hidden-xs hidden-sm\">\n <ion-toolbar>\n\n <ion-buttons slot=\"start\">\n <ion-button mat-icon-button color=\"accent\" (click)=\"openAboutModal($event)\">\n <mat-icon slot=\"icon-only\">help_outline</mat-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title (click)=\"openAboutModal($event)\" color=\"medium\">\n {{'MENU.FOOTER_VERSION_ABOUT'| translate: {version: appVersion} }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <button mat-icon-button color=\"accent\" (click)=\"toggleSplitPaneShow($event)\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(splitPane.when ? 'COMMON.BTN_HIDE_MENU' : 'COMMON.BTN_SHOW_MENU') |translate\">\n <mat-icon><span>{{splitPane.when ? '«' : '»'}}</span></mat-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n\n </ion-menu>\n\n <ng-content></ng-content>\n\n</ion-split-pane>\n",
|
|
21435
21481
|
animations: [fadeInAnimation],
|
|
21436
21482
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
21437
21483
|
styles: ["ion-menu{--ion-item-background:transparent;--ion-item-divider-background:transparent;--ion-item-icon-color:var(--ion-color-primary-tint);--ion-item-text-color:var(--ion-color-primary-tint);--ion-item-background-selected:var(--ion-color-secondary100);--ion-item-text-color-selected:var(--ion-color-primary);--ion-item-icon-color-selected:var(--ion-color-primary);--ion-item-text-color-disable:var(--ion-color-medium);--ion-item-icon-color-disable:var(--ion-color-medium)}ion-menu ion-header ion-text{color:var(--ion-color-primary)}ion-menu ion-header .user-avatar{background-size:cover;background-repeat:no-repeat;background-position:50%;background-color:var(--ion-color-secondary);border:1px solid var(--ion-color-primary);overflow:hidden!important;font-size:var(--avatar-size,60px)!important;line-height:var(--avatar-size,60px);height:var(--avatar-size,60px)!important;width:var(--avatar-size,60px)!important;border-radius:50%;display:inline-block}ion-menu ion-header .user-logo{text-align:right}ion-menu ion-header .user-logo img{max-width:120px;max-height:var(--avatar-size,60px);width:auto}ion-menu ion-header .username{padding-top:0;margin-top:0;margin-bottom:0;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-menu ion-header button[mat-button]{padding:0;text-align:start!important;width:100%}ion-menu .scroll-content{margin-top:79px!important}ion-menu .has-user-header .scroll-content{margin-top:188px!important}ion-menu ion-content.has-profile-header{--offset-top:188px}ion-menu ion-content.no-profile-header{--offset-top:79px}ion-menu ion-content ion-list{min-height:100%;display:flex;flex-direction:column;justify-content:flex-start}ion-menu ion-content ion-list ion-menu-toggle.flex-spacer{flex:1 1 auto;display:flex;flex-direction:column;justify-content:flex-end}ion-menu ion-content ion-list ion-item.primary{--ion-item-icon-color:var(--ion-color-primary-tint);--ion-item-text-color:var(--ion-color-primary-tint)}ion-menu ion-content ion-list ion-item.secondary{--ion-item-icon-color:var(--ion-color-secondary-tint);--ion-item-text-color:var(--ion-color-secondary-tint)}ion-menu ion-content ion-list ion-item.tertiary{--ion-item-icon-color:var(--ion-color-tertiary-tint);--ion-item-text-color:var(--ion-color-tertiary-tint)}ion-menu ion-content ion-list ion-item.danger{--ion-item-icon-color:var(--ion-color-danger-tint);--ion-item-text-color:var(--ion-color-danger-tint)}ion-menu ion-content ion-list ion-item.medium{--ion-item-icon-color:var(--ion-color-medium-shade);--ion-item-text-color:var(--ion-color-medium-shade)}ion-menu ion-content ion-list ion-item.dark{--ion-item-icon-color:var(--ion-color-dark-tint);--ion-item-text-color:var(--ion-color-dark-tint)}ion-menu ion-content ion-list ion-item ion-icon,ion-menu ion-content ion-list ion-item mat-icon{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-menu ion-content ion-list ion-item ion-label,ion-menu ion-content ion-list ion-item ion-text{color:var(--ion-item-text-color)!important}ion-menu ion-content ion-list ion-item.selected{background-color:var(--ion-item-background-selected)!important;--color-hover:var(--ion-item-background-selected)!important}ion-menu ion-content ion-list ion-item.selected ion-icon,ion-menu ion-content ion-list ion-item.selected mat-icon{color:var(--ion-item-icon-color-selected)!important;fill:currentColor;stroke:currentColor}ion-menu ion-content ion-list ion-item.selected ion-label,ion-menu ion-content ion-list ion-item.selected ion-text{color:var(--ion-item-text-color-selected)!important}ion-menu ion-content ion-list ion-item.selected:hover{--color-hover:var(--ion-item-background-selected)!important;--ion-item-icon-color-selected:var(--ion-item-icon-color)!important;--ion-item-text-color-selected:var(--ion-item-text-color)!important}ion-menu ion-footer{display:block!important}ion-menu ion-footer ion-toolbar ion-title{cursor:pointer;font-size:12pt;font-weight:400;text-align:center;padding:0 8px}ion-menu ion-footer ion-toolbar ion-button{--width:40px}@media screen and (max-width:767px){ion-menu ion-footer{display:none!important;visibility:hidden!important}}@media screen and (min-width:768px){ion-menu ion-scroll{overflow-y:auto!important}ion-menu .user-avatar{font-size:var(--avatar-size,80px)!important;line-height:var(--avatar-size,80px);height:var(--avatar-size,80px)!important;width:var(--avatar-size,80px)!important}ion-menu .user-logo img{max-height:var(--avatar-size,80px)}}"]
|
|
@@ -21495,14 +21541,13 @@ class AppIconComponent {
|
|
|
21495
21541
|
this.icon = value.icon;
|
|
21496
21542
|
this.matIcon = value.matIcon;
|
|
21497
21543
|
this.matSvgIcon = value.matSvgIcon;
|
|
21498
|
-
this.color = value.color;
|
|
21499
21544
|
}
|
|
21500
21545
|
;
|
|
21501
21546
|
}
|
|
21502
21547
|
AppIconComponent.decorators = [
|
|
21503
21548
|
{ type: Component, args: [{
|
|
21504
21549
|
selector: 'app-icon',
|
|
21505
|
-
template: "<ion-icon *ngIf=\"icon; else matIconTemplate\" slot=\"icon-only\"\n [color]=\"color\"\n [name]=\"icon\"\n
|
|
21550
|
+
template: "<ion-icon *ngIf=\"icon; else matIconTemplate\" slot=\"icon-only\"\n [color]=\"color\"\n [name]=\"icon\"\n></ion-icon>\n<ng-template #matIconTemplate>\n <mat-icon [svgIcon]=\"matSvgIcon\"\n [style.color]=\"'var(--ion-color-'+color+')'\">{{matIcon}}</mat-icon>\n</ng-template>\n\n"
|
|
21506
21551
|
},] }
|
|
21507
21552
|
];
|
|
21508
21553
|
AppIconComponent.propDecorators = {
|
|
@@ -21510,8 +21555,6 @@ AppIconComponent.propDecorators = {
|
|
|
21510
21555
|
matIcon: [{ type: Input }],
|
|
21511
21556
|
matSvgIcon: [{ type: Input }],
|
|
21512
21557
|
color: [{ type: Input }],
|
|
21513
|
-
height: [{ type: Input }],
|
|
21514
|
-
width: [{ type: Input }],
|
|
21515
21558
|
ref: [{ type: Input }]
|
|
21516
21559
|
};
|
|
21517
21560
|
|
|
@@ -22583,13 +22626,12 @@ class AppTable {
|
|
|
22583
22626
|
get error() {
|
|
22584
22627
|
return this.errorSubject.value;
|
|
22585
22628
|
}
|
|
22586
|
-
get error$() {
|
|
22587
|
-
return this.errorSubject.asObservable();
|
|
22588
|
-
}
|
|
22589
22629
|
/**
|
|
22590
22630
|
* @deprecated
|
|
22591
|
-
* @param error
|
|
22592
22631
|
*/
|
|
22632
|
+
get error$() {
|
|
22633
|
+
return this.errorSubject.asObservable();
|
|
22634
|
+
}
|
|
22593
22635
|
set error(error) {
|
|
22594
22636
|
this.setError(error);
|
|
22595
22637
|
}
|
|
@@ -23013,7 +23055,7 @@ class AppTable {
|
|
|
23013
23055
|
.then(() => this.editRowById(event, row.id, { focusColumn: this.lastUserColumn }));
|
|
23014
23056
|
return true;
|
|
23015
23057
|
}
|
|
23016
|
-
// Edit
|
|
23058
|
+
// Edit previous row
|
|
23017
23059
|
this.editRow(event, row, { focusColumn: this.lastUserColumn });
|
|
23018
23060
|
return true;
|
|
23019
23061
|
}
|
|
@@ -23036,8 +23078,7 @@ class AppTable {
|
|
|
23036
23078
|
if (id < 0)
|
|
23037
23079
|
return;
|
|
23038
23080
|
if (id >= this.visibleRowCount) {
|
|
23039
|
-
this.
|
|
23040
|
-
this.addRow(event);
|
|
23081
|
+
this.addRow(event, undefined, opts);
|
|
23041
23082
|
}
|
|
23042
23083
|
else {
|
|
23043
23084
|
const row = yield this.dataSource.getRow(id);
|
|
@@ -23110,7 +23151,7 @@ class AppTable {
|
|
|
23110
23151
|
this.cancelExistingRow(event, row, opts);
|
|
23111
23152
|
}
|
|
23112
23153
|
}
|
|
23113
|
-
addRow(event, insertAt) {
|
|
23154
|
+
addRow(event, insertAt, opts) {
|
|
23114
23155
|
if (this.debug)
|
|
23115
23156
|
console.debug('[table] Asking for new row...');
|
|
23116
23157
|
if (!this._enabled)
|
|
@@ -23125,7 +23166,7 @@ class AppTable {
|
|
|
23125
23166
|
return false;
|
|
23126
23167
|
}
|
|
23127
23168
|
// Add new row
|
|
23128
|
-
this.addRowToTable(insertAt);
|
|
23169
|
+
this.addRowToTable(insertAt, opts);
|
|
23129
23170
|
return true;
|
|
23130
23171
|
}
|
|
23131
23172
|
save(opts) {
|
|
@@ -23240,7 +23281,7 @@ class AppTable {
|
|
|
23240
23281
|
* @param event
|
|
23241
23282
|
* @param row
|
|
23242
23283
|
* @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
|
|
23243
|
-
*
|
|
23284
|
+
* And to force deletion even if table is busy
|
|
23244
23285
|
*/
|
|
23245
23286
|
deleteRow(event, row, opts) {
|
|
23246
23287
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -23253,7 +23294,7 @@ class AppTable {
|
|
|
23253
23294
|
* @param event
|
|
23254
23295
|
* @param rows
|
|
23255
23296
|
* @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
|
|
23256
|
-
*
|
|
23297
|
+
* And to force deletion even if table is busy
|
|
23257
23298
|
*/
|
|
23258
23299
|
deleteRows(event, rows, opts) {
|
|
23259
23300
|
var _a;
|
|
@@ -23266,8 +23307,8 @@ class AppTable {
|
|
|
23266
23307
|
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
23267
23308
|
if (!this._enabled || isEmptyArray(rows))
|
|
23268
23309
|
return 0; // Skip is disabled, or no rows to delete
|
|
23269
|
-
if (this.loading && (!opts || opts.
|
|
23270
|
-
console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.
|
|
23310
|
+
if (this.loading && (!opts || opts.interactive !== false)) {
|
|
23311
|
+
console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.interactive = false to force deletion');
|
|
23271
23312
|
return 0; // Skip if loading
|
|
23272
23313
|
}
|
|
23273
23314
|
// Make sure to keep newly created row
|
|
@@ -23404,15 +23445,11 @@ class AppTable {
|
|
|
23404
23445
|
moveRow(id, direction) {
|
|
23405
23446
|
this.dataSource.move(id, direction);
|
|
23406
23447
|
}
|
|
23407
|
-
ready() {
|
|
23408
|
-
return
|
|
23409
|
-
yield firstTruePromise(this.readySubject);
|
|
23410
|
-
});
|
|
23448
|
+
ready(opts) {
|
|
23449
|
+
return waitForTrue(this.readySubject, opts);
|
|
23411
23450
|
}
|
|
23412
23451
|
waitIdle(opts) {
|
|
23413
|
-
return
|
|
23414
|
-
yield firstFalsePromise(this.loadingSubject);
|
|
23415
|
-
});
|
|
23452
|
+
return waitForFalse(this.loadingSubject, opts);
|
|
23416
23453
|
}
|
|
23417
23454
|
openSelectColumnsModal(event) {
|
|
23418
23455
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -23790,9 +23827,10 @@ class AppTable {
|
|
|
23790
23827
|
//if (this.debug) console.debug("[table] id = " + id);
|
|
23791
23828
|
return id;
|
|
23792
23829
|
}
|
|
23793
|
-
addRowToTable(insertAt) {
|
|
23830
|
+
addRowToTable(insertAt, opts) {
|
|
23794
23831
|
return __awaiter(this, void 0, void 0, function* () {
|
|
23795
23832
|
this.focusFirstColumn = true;
|
|
23833
|
+
this.focusColumn = (opts === null || opts === void 0 ? void 0 : opts.focusColumn) || this.firstUserColumn;
|
|
23796
23834
|
yield this._dataSource.asyncCreateNew(insertAt);
|
|
23797
23835
|
this.editedRow = this._dataSource.getRow(-1);
|
|
23798
23836
|
// Emit start editing event
|
|
@@ -24139,8 +24177,9 @@ class AppEditor {
|
|
|
24139
24177
|
this._subscription = new Subscription();
|
|
24140
24178
|
this._enabled = false;
|
|
24141
24179
|
this._dirty = false;
|
|
24142
|
-
this.
|
|
24143
|
-
this.
|
|
24180
|
+
this.readySubject = new BehaviorSubject(false);
|
|
24181
|
+
this.loadingSubject = new BehaviorSubject(true);
|
|
24182
|
+
this.errorSubject = new BehaviorSubject(undefined);
|
|
24144
24183
|
this.debug = false;
|
|
24145
24184
|
this.submitted = false;
|
|
24146
24185
|
this.toolbar = null;
|
|
@@ -24150,13 +24189,31 @@ class AppEditor {
|
|
|
24150
24189
|
* @deprecated
|
|
24151
24190
|
*/
|
|
24152
24191
|
set _loading(value) {
|
|
24153
|
-
this.
|
|
24192
|
+
this.readySubject.next(value);
|
|
24154
24193
|
}
|
|
24155
24194
|
/**
|
|
24156
24195
|
* @deprecated
|
|
24157
24196
|
*/
|
|
24158
24197
|
get _loading() {
|
|
24159
|
-
return this.
|
|
24198
|
+
return this.loadingSubject.value;
|
|
24199
|
+
}
|
|
24200
|
+
/**
|
|
24201
|
+
* @deprecated
|
|
24202
|
+
*/
|
|
24203
|
+
get _$ready() {
|
|
24204
|
+
return this.readySubject;
|
|
24205
|
+
}
|
|
24206
|
+
/**
|
|
24207
|
+
* @deprecated
|
|
24208
|
+
*/
|
|
24209
|
+
get _$loading() {
|
|
24210
|
+
return this.loadingSubject;
|
|
24211
|
+
}
|
|
24212
|
+
get error() {
|
|
24213
|
+
return this.errorSubject.value;
|
|
24214
|
+
}
|
|
24215
|
+
set error(error) {
|
|
24216
|
+
this.setError(error);
|
|
24160
24217
|
}
|
|
24161
24218
|
get tables() {
|
|
24162
24219
|
return this._children && this._children.filter(c => c instanceof AppTable);
|
|
@@ -24185,7 +24242,7 @@ class AppEditor {
|
|
|
24185
24242
|
}
|
|
24186
24243
|
get loading() {
|
|
24187
24244
|
var _a;
|
|
24188
|
-
return this.
|
|
24245
|
+
return this.loadingSubject.value || (((_a = this._children) === null || _a === void 0 ? void 0 : _a.findIndex(c => c.enabled && c.loading)) !== -1) || false;
|
|
24189
24246
|
}
|
|
24190
24247
|
get enabled() {
|
|
24191
24248
|
return this._enabled;
|
|
@@ -24209,12 +24266,11 @@ class AppEditor {
|
|
|
24209
24266
|
}
|
|
24210
24267
|
ngOnDestroy() {
|
|
24211
24268
|
this._subscription.unsubscribe();
|
|
24212
|
-
this.
|
|
24213
|
-
this.
|
|
24214
|
-
this.
|
|
24215
|
-
|
|
24216
|
-
|
|
24217
|
-
addChildForm(form) {
|
|
24269
|
+
this.readySubject.unsubscribe();
|
|
24270
|
+
this.loadingSubject.unsubscribe();
|
|
24271
|
+
this.errorSubject.unsubscribe();
|
|
24272
|
+
}
|
|
24273
|
+
addChildForm(form) {
|
|
24218
24274
|
if (!form)
|
|
24219
24275
|
throw new Error('Trying to register an undefined child form');
|
|
24220
24276
|
this._children = this._children || [];
|
|
@@ -24281,16 +24337,16 @@ class AppEditor {
|
|
|
24281
24337
|
this.markForCheck();
|
|
24282
24338
|
}
|
|
24283
24339
|
markAsLoading(opts) {
|
|
24284
|
-
if (!this.
|
|
24285
|
-
this.
|
|
24340
|
+
if (!this.loadingSubject.value) {
|
|
24341
|
+
this.loadingSubject.next(true);
|
|
24286
24342
|
if (!opts || opts.emitEvent !== false)
|
|
24287
24343
|
this.markForCheck();
|
|
24288
24344
|
}
|
|
24289
24345
|
}
|
|
24290
24346
|
markAsLoaded(opts) {
|
|
24291
24347
|
var _a;
|
|
24292
|
-
if (this.
|
|
24293
|
-
this.
|
|
24348
|
+
if (this.loadingSubject.value) {
|
|
24349
|
+
this.loadingSubject.next(false);
|
|
24294
24350
|
if (!opts || opts.onlySelf !== true) {
|
|
24295
24351
|
// Emit to children forms
|
|
24296
24352
|
// Tables should be changed by parent
|
|
@@ -24304,15 +24360,17 @@ class AppEditor {
|
|
|
24304
24360
|
markAsReady(opts) {
|
|
24305
24361
|
var _a;
|
|
24306
24362
|
(_a = this._children) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markAsReady(opts));
|
|
24307
|
-
this.
|
|
24363
|
+
this.readySubject.next(true);
|
|
24308
24364
|
}
|
|
24309
24365
|
ready(opts) {
|
|
24310
|
-
|
|
24311
|
-
return
|
|
24312
|
-
|
|
24366
|
+
if (this.readySubject.value)
|
|
24367
|
+
return Promise.resolve();
|
|
24368
|
+
return waitForTrue(this.readySubject, opts);
|
|
24313
24369
|
}
|
|
24314
24370
|
waitIdle(opts) {
|
|
24315
|
-
|
|
24371
|
+
if (!this.loadingSubject.value)
|
|
24372
|
+
return Promise.resolve();
|
|
24373
|
+
return waitForFalse(this.loadingSubject, opts);
|
|
24316
24374
|
}
|
|
24317
24375
|
cancel(event) {
|
|
24318
24376
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -24515,6 +24573,14 @@ class AppEditor {
|
|
|
24515
24573
|
console.warn(`${prefix} Unknown children sub-form: `, c);
|
|
24516
24574
|
}
|
|
24517
24575
|
}
|
|
24576
|
+
setError(value, opts) {
|
|
24577
|
+
if (this.errorSubject.value !== value) {
|
|
24578
|
+
this.errorSubject.next(value);
|
|
24579
|
+
if (!opts || opts.emitEvent !== false) {
|
|
24580
|
+
this.markForCheck();
|
|
24581
|
+
}
|
|
24582
|
+
}
|
|
24583
|
+
}
|
|
24518
24584
|
markForCheck() {
|
|
24519
24585
|
// Should be override by subclasses, if change detection is Push
|
|
24520
24586
|
}
|
|
@@ -24601,6 +24667,10 @@ class AppTabEditor extends AppEditor {
|
|
|
24601
24667
|
this.markForCheck();
|
|
24602
24668
|
}
|
|
24603
24669
|
}
|
|
24670
|
+
realignInkBar() {
|
|
24671
|
+
var _a;
|
|
24672
|
+
(_a = this.tabGroup) === null || _a === void 0 ? void 0 : _a.realignInkBar();
|
|
24673
|
+
}
|
|
24604
24674
|
onTabChange(event, queryTabIndexParamName) {
|
|
24605
24675
|
queryTabIndexParamName = queryTabIndexParamName || this.queryTabIndexParamName;
|
|
24606
24676
|
if (!queryTabIndexParamName || !this.route)
|
|
@@ -25580,13 +25650,14 @@ class AppEntityEditorModal extends AppTabEditor {
|
|
|
25580
25650
|
console.debug(this._logPrefix + 'Saving data...');
|
|
25581
25651
|
try {
|
|
25582
25652
|
// Save all dirty tables
|
|
25583
|
-
const saved =
|
|
25584
|
-
|
|
25585
|
-
|
|
25586
|
-
|
|
25653
|
+
const saved = yield this.saveDirtyTables();
|
|
25654
|
+
if (!saved)
|
|
25655
|
+
return false;
|
|
25656
|
+
// Fill data
|
|
25587
25657
|
this.data = yield this.getValue();
|
|
25658
|
+
// Mark as submitted
|
|
25588
25659
|
this.submitted = true;
|
|
25589
|
-
return
|
|
25660
|
+
return true;
|
|
25590
25661
|
}
|
|
25591
25662
|
catch (err) {
|
|
25592
25663
|
this.submitted = true;
|
|
@@ -25698,6 +25769,16 @@ class AppEntityEditorModal extends AppTabEditor {
|
|
|
25698
25769
|
this.markForCheck();
|
|
25699
25770
|
}
|
|
25700
25771
|
/* -- protected methods -- */
|
|
25772
|
+
saveDirtyTables() {
|
|
25773
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25774
|
+
// Save all dirty tables
|
|
25775
|
+
const results = yield Promise.all((this.tables || [])
|
|
25776
|
+
.filter(c => c.dirty)
|
|
25777
|
+
.map(c => c.save()));
|
|
25778
|
+
const saved = results.findIndex(result => result !== true) === -1;
|
|
25779
|
+
return saved;
|
|
25780
|
+
});
|
|
25781
|
+
}
|
|
25701
25782
|
waitWhilePending(opts) {
|
|
25702
25783
|
return AppFormUtils.waitWhilePending(this, opts);
|
|
25703
25784
|
}
|
|
@@ -25823,10 +25904,7 @@ AppInMemoryTable.propDecorators = {
|
|
|
25823
25904
|
const SocialErrorCodes = {
|
|
25824
25905
|
LOAD_USER_EVENTS_ERROR: 50000,
|
|
25825
25906
|
SAVE_USER_EVENT_ERROR: 50001,
|
|
25826
|
-
|
|
25827
|
-
SEND_MESSAGE_ERROR: 50003,
|
|
25828
|
-
SUBSCRIBE_USER_EVENTS_ERROR: 50005,
|
|
25829
|
-
SUBSCRIBE_JOB_PROGRESSION_ERROR: 50010
|
|
25907
|
+
SEND_MESSAGE_ERROR: 50003
|
|
25830
25908
|
};
|
|
25831
25909
|
|
|
25832
25910
|
var UserEvent_1;
|
|
@@ -25841,23 +25919,16 @@ let UserEvent = UserEvent_1 = class UserEvent extends Entity {
|
|
|
25841
25919
|
}
|
|
25842
25920
|
asObject(opts) {
|
|
25843
25921
|
const target = super.asObject(opts);
|
|
25844
|
-
target.creationDate = toDateISOString(this.creationDate);
|
|
25845
|
-
target.readDate = toDateISOString(this.readDate);
|
|
25846
25922
|
// Serialize content
|
|
25847
25923
|
if (typeof target.content === 'object') {
|
|
25848
25924
|
target.content = JSON.stringify(target.content);
|
|
25849
25925
|
}
|
|
25850
|
-
delete target.avatar;
|
|
25851
|
-
delete target.avatarIcon;
|
|
25852
|
-
delete target.icon;
|
|
25853
|
-
delete target.actions;
|
|
25854
25926
|
return target;
|
|
25855
25927
|
}
|
|
25856
25928
|
fromObject(source) {
|
|
25857
25929
|
Object.assign(this, source); // Copy all properties
|
|
25858
25930
|
super.fromObject(source);
|
|
25859
25931
|
this.creationDate = fromDateISOString(source.creationDate);
|
|
25860
|
-
this.readDate = fromDateISOString(source.readDate);
|
|
25861
25932
|
try {
|
|
25862
25933
|
// Deserialize content
|
|
25863
25934
|
if (typeof source.content === 'string' && source.content.startsWith('{')) {
|
|
@@ -25876,52 +25947,6 @@ let UserEvent = UserEvent_1 = class UserEvent extends Entity {
|
|
|
25876
25947
|
UserEvent = UserEvent_1 = __decorate([
|
|
25877
25948
|
EntityClass({ typename: 'UserEventVO' })
|
|
25878
25949
|
], UserEvent);
|
|
25879
|
-
// @dynamic
|
|
25880
|
-
let UserEventFilter = class UserEventFilter extends EntityFilter {
|
|
25881
|
-
constructor() {
|
|
25882
|
-
super(...arguments);
|
|
25883
|
-
this.types = [];
|
|
25884
|
-
this.levels = [];
|
|
25885
|
-
this.issuers = [];
|
|
25886
|
-
this.recipients = [];
|
|
25887
|
-
this.startDate = null;
|
|
25888
|
-
this.excludeRead = false;
|
|
25889
|
-
}
|
|
25890
|
-
fromObject(source, opts) {
|
|
25891
|
-
super.fromObject(source, opts);
|
|
25892
|
-
this.types = source.types || [];
|
|
25893
|
-
this.levels = source.levels || [];
|
|
25894
|
-
this.issuers = source.issuers || [];
|
|
25895
|
-
this.recipients = source.recipients || [];
|
|
25896
|
-
this.startDate = fromDateISOString(source.startDate);
|
|
25897
|
-
this.excludeRead = source.excludeRead || false;
|
|
25898
|
-
}
|
|
25899
|
-
buildFilter() {
|
|
25900
|
-
const filterFns = super.buildFilter();
|
|
25901
|
-
if (isNotEmptyArray(this.types)) {
|
|
25902
|
-
filterFns.push(t => this.types.includes(t.type));
|
|
25903
|
-
}
|
|
25904
|
-
if (isNotEmptyArray(this.levels)) {
|
|
25905
|
-
filterFns.push(t => this.levels.includes(t.level));
|
|
25906
|
-
}
|
|
25907
|
-
if (isNotEmptyArray(this.issuers)) {
|
|
25908
|
-
filterFns.push(t => this.issuers.includes(t.issuer));
|
|
25909
|
-
}
|
|
25910
|
-
if (isNotEmptyArray(this.recipients)) {
|
|
25911
|
-
filterFns.push(t => this.recipients.includes(t.recipient));
|
|
25912
|
-
}
|
|
25913
|
-
if (isNotNil(this.startDate)) {
|
|
25914
|
-
filterFns.push(t => this.startDate.isSameOrBefore(t.creationDate));
|
|
25915
|
-
}
|
|
25916
|
-
if (this.excludeRead === true) {
|
|
25917
|
-
filterFns.push(t => isNil(t.readSignature)); // todo or t.signature ?
|
|
25918
|
-
}
|
|
25919
|
-
return filterFns;
|
|
25920
|
-
}
|
|
25921
|
-
};
|
|
25922
|
-
UserEventFilter = __decorate([
|
|
25923
|
-
EntityClass({ typename: 'UserEventFilterVO' })
|
|
25924
|
-
], UserEventFilter);
|
|
25925
25950
|
|
|
25926
25951
|
const UserEventFragments = {
|
|
25927
25952
|
userEvent: gql `fragment UserEventFragment on UserEventVO {
|
|
@@ -25949,188 +25974,134 @@ const UserEventFragments = {
|
|
|
25949
25974
|
}`
|
|
25950
25975
|
};
|
|
25951
25976
|
|
|
25952
|
-
|
|
25953
|
-
|
|
25954
|
-
|
|
25955
|
-
|
|
25977
|
+
// @dynamic
|
|
25978
|
+
let UserEventFilter = class UserEventFilter extends EntityFilter {
|
|
25979
|
+
constructor() {
|
|
25980
|
+
super(...arguments);
|
|
25981
|
+
this.issuer = null;
|
|
25982
|
+
this.recipient = null;
|
|
25983
|
+
}
|
|
25984
|
+
fromObject(source, opts) {
|
|
25985
|
+
super.fromObject(source, opts);
|
|
25986
|
+
this.issuer = source.issuer;
|
|
25987
|
+
this.recipient = source.recipient;
|
|
25988
|
+
}
|
|
25989
|
+
buildFilter() {
|
|
25990
|
+
const filterFns = super.buildFilter();
|
|
25991
|
+
// issuer
|
|
25992
|
+
if (this.issuer) {
|
|
25993
|
+
filterFns.push(t => (t.issuer === this.issuer));
|
|
25994
|
+
}
|
|
25995
|
+
if (this.recipient) {
|
|
25996
|
+
filterFns.push(t => (t.recipient === this.recipient));
|
|
25997
|
+
}
|
|
25998
|
+
return filterFns;
|
|
25999
|
+
}
|
|
26000
|
+
};
|
|
26001
|
+
UserEventFilter = __decorate([
|
|
26002
|
+
EntityClass({ typename: 'UserEventFilterVO' })
|
|
26003
|
+
], UserEventFilter);
|
|
26004
|
+
const SaveQuery = gql `
|
|
26005
|
+
mutation SaveUserEvent($data: UserEventVOInput){
|
|
26006
|
+
data: saveUserEvent(userEvent: $data){
|
|
26007
|
+
...UserEventFragment
|
|
26008
|
+
}
|
|
26009
|
+
}
|
|
26010
|
+
${UserEventFragments.userEvent}
|
|
26011
|
+
`;
|
|
26012
|
+
const LoadAllQuery = gql `
|
|
26013
|
+
query UserEvents($filter: UserEventFilterVOInput, $page: PageInput){
|
|
26014
|
+
data: userEvents(filter: $filter, page: $page){
|
|
26015
|
+
...LightUserEventFragment
|
|
26016
|
+
}
|
|
26017
|
+
}
|
|
26018
|
+
${UserEventFragments.lightUserEvent}
|
|
26019
|
+
`;
|
|
26020
|
+
const DeleteByIdsMutation = gql `
|
|
26021
|
+
mutation DeleteUserEvents($ids:[Int]){
|
|
26022
|
+
deleteUserEvents(ids: $ids)
|
|
26023
|
+
}
|
|
26024
|
+
`;
|
|
26025
|
+
const LoadAllWithContentQuery = gql `
|
|
26026
|
+
query UserEventsWithContent($filter: UserEventFilterVOInput, $page: PageInput){
|
|
26027
|
+
data: userEvents(filter: $filter, page: $page){
|
|
26028
|
+
...UserEventFragment
|
|
26029
|
+
}
|
|
26030
|
+
}
|
|
26031
|
+
${UserEventFragments.userEvent}
|
|
26032
|
+
`;
|
|
26033
|
+
class UserEventService extends BaseGraphqlService {
|
|
26034
|
+
constructor(graphql, accountService, network, translate, toastController, environment) {
|
|
25956
26035
|
super(graphql, environment);
|
|
25957
26036
|
this.graphql = graphql;
|
|
25958
26037
|
this.accountService = accountService;
|
|
25959
26038
|
this.network = network;
|
|
25960
26039
|
this.translate = translate;
|
|
25961
|
-
this.
|
|
25962
|
-
this.mutations = mutations;
|
|
25963
|
-
this.subscriptions = subscriptions;
|
|
26040
|
+
this.toastController = toastController;
|
|
25964
26041
|
this.environment = environment;
|
|
25965
|
-
this.
|
|
25966
|
-
this._subscriptions = new Subscription();
|
|
25967
|
-
this.listeners = [];
|
|
25968
|
-
this._logPrefix = '[user-event-service] ';
|
|
26042
|
+
this._userEventActions = [];
|
|
25969
26043
|
// For DEV only
|
|
25970
|
-
this._debug =
|
|
25971
|
-
// listen login/logout
|
|
25972
|
-
this._subscriptions.add(accountService.onLogin.subscribe(() => __awaiter(this, void 0, void 0, function* () {
|
|
25973
|
-
const count = yield this.count(this.defaultFilter());
|
|
25974
|
-
if (count && this._debug) {
|
|
25975
|
-
console.debug(`${this._logPrefix}Received ${count} unread notifications`);
|
|
25976
|
-
}
|
|
25977
|
-
this._count$.next(count);
|
|
25978
|
-
})));
|
|
25979
|
-
}
|
|
25980
|
-
get userEventCount() {
|
|
25981
|
-
return this._count$.asObservable();
|
|
25982
|
-
}
|
|
25983
|
-
ngOnDestroy() {
|
|
25984
|
-
this._subscriptions.unsubscribe();
|
|
26044
|
+
this._debug = environment && !environment.production;
|
|
25985
26045
|
}
|
|
26046
|
+
/**
|
|
26047
|
+
*
|
|
26048
|
+
* @param offset
|
|
26049
|
+
* @param size
|
|
26050
|
+
* @param sortBy
|
|
26051
|
+
* @param sortDirection
|
|
26052
|
+
* @param filter
|
|
26053
|
+
* @param options
|
|
26054
|
+
* @deprecated use watchPage() instead
|
|
26055
|
+
*/
|
|
25986
26056
|
watchAll(offset, size, sortBy, sortDirection, filter, options) {
|
|
25987
26057
|
return this.watchPage({ offset, size, sortBy, sortDirection }, filter, options);
|
|
25988
26058
|
}
|
|
25989
26059
|
watchPage(page, filter, options) {
|
|
25990
|
-
var _a;
|
|
25991
26060
|
let now = this._debug && Date.now();
|
|
25992
26061
|
//if (this._debug)
|
|
25993
|
-
console.debug(
|
|
26062
|
+
console.debug('[user-event-service] Loading user events...', filter);
|
|
25994
26063
|
filter = this.asFilter(filter);
|
|
25995
26064
|
// Force recipient to current issuer, if not admin and not specified
|
|
25996
|
-
if (
|
|
25997
|
-
const recipient = this.
|
|
25998
|
-
if (
|
|
26065
|
+
if (isNilOrBlank(filter.recipient) || !this.accountService.isAdmin()) {
|
|
26066
|
+
const recipient = this.accountService.account.pubkey;
|
|
26067
|
+
if (recipient !== filter.recipient) {
|
|
25999
26068
|
console.warn('[user-events-service] Force user event filter.recipient=' + recipient);
|
|
26000
|
-
filter.
|
|
26069
|
+
filter.recipient = recipient;
|
|
26001
26070
|
}
|
|
26002
26071
|
}
|
|
26003
|
-
const withContent =
|
|
26072
|
+
const withContent = options && options.withContent === true;
|
|
26004
26073
|
return this.mutableWatchQuery({
|
|
26005
26074
|
queryName: withContent ? 'LoadAllWithContent' : 'LoadAll',
|
|
26006
|
-
query: withContent ?
|
|
26075
|
+
query: withContent ? LoadAllWithContentQuery : LoadAllQuery,
|
|
26007
26076
|
variables: {
|
|
26008
|
-
page: Object.assign({ sortBy: 'updateDate', sortDirection: '
|
|
26077
|
+
page: Object.assign(Object.assign({ sortBy: 'updateDate' }, page), { sortDirection: (page.sortDirection || 'DESC').toUpperCase() }),
|
|
26009
26078
|
filter: filter && filter.asPodObject()
|
|
26010
26079
|
},
|
|
26011
26080
|
arrayFieldName: 'data',
|
|
26012
26081
|
error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
|
|
26013
|
-
fetchPolicy:
|
|
26082
|
+
fetchPolicy: options && options.fetchPolicy || undefined
|
|
26014
26083
|
})
|
|
26015
26084
|
.pipe(map(res => {
|
|
26016
|
-
const data =
|
|
26085
|
+
const data = res && (res.data || []).map(UserEvent.fromObject);
|
|
26017
26086
|
if (now) {
|
|
26018
|
-
console.debug(
|
|
26087
|
+
console.debug(`[user-event-service] ${data.length} user events loaded in ${Date.now() - now}ms`);
|
|
26019
26088
|
now = null;
|
|
26020
26089
|
}
|
|
26021
|
-
const unreadCount = this.unreadEvents(data);
|
|
26022
26090
|
return {
|
|
26023
26091
|
data,
|
|
26024
|
-
total:
|
|
26092
|
+
total: res && toNumber(res.total, data.length)
|
|
26025
26093
|
};
|
|
26026
26094
|
}));
|
|
26027
26095
|
}
|
|
26028
|
-
|
|
26029
|
-
|
|
26030
|
-
|
|
26031
|
-
const withContent = !!entity.content;
|
|
26032
|
-
// Add user event locally
|
|
26033
|
-
this.insertIntoMutableCachedQueries(this.graphql.cache, {
|
|
26034
|
-
query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
|
|
26035
|
-
data: entity
|
|
26036
|
-
});
|
|
26037
|
-
// Update count
|
|
26038
|
-
this._count$.next(this._count$.value + 1);
|
|
26039
|
-
}
|
|
26040
|
-
count(filter, options) {
|
|
26041
|
-
var _a;
|
|
26042
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26043
|
-
if (!((_a = this.queries) === null || _a === void 0 ? void 0 : _a.count)) {
|
|
26044
|
-
console.warn(`${this._logPrefix}Query 'count' not provided, skip.`);
|
|
26045
|
-
return undefined;
|
|
26046
|
-
}
|
|
26047
|
-
if (!filter)
|
|
26048
|
-
throw new Error(`Missing argument 'filter'`);
|
|
26049
|
-
filter = this.asFilter(filter);
|
|
26050
|
-
if (this._debug)
|
|
26051
|
-
console.debug(`${this._logPrefix}Counting user events with filter:`, filter);
|
|
26052
|
-
const res = yield this.graphql.query({
|
|
26053
|
-
query: this.queries.count,
|
|
26054
|
-
variables: {
|
|
26055
|
-
filter: filter.asPodObject()
|
|
26056
|
-
},
|
|
26057
|
-
error: { code: SocialErrorCodes.COUNT_USER_EVENT_ERROR, message: 'SOCIAL.ERROR.COUNT_USER_EVENT_ERROR' },
|
|
26058
|
-
fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || 'network-only'
|
|
26059
|
-
});
|
|
26060
|
-
return res.total;
|
|
26061
|
-
});
|
|
26062
|
-
}
|
|
26063
|
-
listenChanges(filter, options) {
|
|
26064
|
-
var _a;
|
|
26065
|
-
if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenChanges)) {
|
|
26066
|
-
console.warn(`${this._logPrefix}Subscription query 'listenChanges' not provided, skip.`);
|
|
26067
|
-
return of();
|
|
26068
|
-
}
|
|
26069
|
-
if (!filter)
|
|
26070
|
-
throw new Error(`Missing argument 'filter'`);
|
|
26071
|
-
filter = this.asFilter(filter);
|
|
26072
|
-
const withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
|
|
26073
|
-
if (this._debug)
|
|
26074
|
-
console.debug(`${this._logPrefix}[WS] Listening changes for user events with filter:`, filter);
|
|
26075
|
-
return this.graphql.subscribe({
|
|
26076
|
-
query: this.subscriptions.listenChanges,
|
|
26077
|
-
fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
|
|
26078
|
-
variables: { filter: filter.asPodObject(), interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
|
|
26079
|
-
error: {
|
|
26080
|
-
code: SocialErrorCodes.SUBSCRIBE_USER_EVENTS_ERROR,
|
|
26081
|
-
message: 'SOCIAL.ERROR.SUBSCRIBE_USER_EVENTS_ERROR'
|
|
26082
|
-
}
|
|
26083
|
-
}).pipe(map(({ data }) => {
|
|
26084
|
-
if (data && this._debug)
|
|
26085
|
-
console.debug(`${this._logPrefix}Received new user events:`, data);
|
|
26086
|
-
const updatedData = data === null || data === void 0 ? void 0 : data.map(this.processUserEvent);
|
|
26087
|
-
// Update cache
|
|
26088
|
-
this.insertIntoMutableCachedQueries(this.graphql.cache, {
|
|
26089
|
-
query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
|
|
26090
|
-
data: updatedData
|
|
26091
|
-
});
|
|
26092
|
-
// update count
|
|
26093
|
-
this._count$.next(this.unreadEvents(updatedData));
|
|
26094
|
-
return updatedData;
|
|
26095
|
-
}));
|
|
26096
|
-
}
|
|
26097
|
-
delete(entity) {
|
|
26098
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26099
|
-
if (!entity)
|
|
26100
|
-
return; // skip
|
|
26101
|
-
yield this.deleteAll([entity]);
|
|
26102
|
-
});
|
|
26103
|
-
}
|
|
26104
|
-
deleteAll(entities, opts) {
|
|
26105
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26106
|
-
const ids = entities && entities
|
|
26107
|
-
.map(t => t.id);
|
|
26108
|
-
if (isEmptyArray(ids))
|
|
26109
|
-
return; // stop, if nothing else to do
|
|
26110
|
-
const now = Date.now();
|
|
26111
|
-
if (this._debug)
|
|
26112
|
-
console.debug(`${this._logPrefix}Deleting events... ids:`, ids);
|
|
26113
|
-
yield this.graphql.mutate({
|
|
26114
|
-
mutation: this.mutations.deleteByIds,
|
|
26115
|
-
variables: {
|
|
26116
|
-
ids
|
|
26117
|
-
},
|
|
26118
|
-
update: (proxy) => {
|
|
26119
|
-
// Remove from caches
|
|
26120
|
-
this.removeFromMutableCachedQueriesByIds(proxy, {
|
|
26121
|
-
query: this.queries.loadAll,
|
|
26122
|
-
ids
|
|
26123
|
-
});
|
|
26124
|
-
this.removeFromMutableCachedQueriesByIds(proxy, {
|
|
26125
|
-
query: this.queries.loadAllWithContent,
|
|
26126
|
-
ids
|
|
26127
|
-
});
|
|
26128
|
-
if (this._debug)
|
|
26129
|
-
console.debug(`${this._logPrefix}Events deleted in ${Date.now() - now}ms`);
|
|
26130
|
-
}
|
|
26131
|
-
});
|
|
26132
|
-
});
|
|
26096
|
+
saveAll(data, options) {
|
|
26097
|
+
return Promise.all(data
|
|
26098
|
+
.map(entity => this.save(entity, options)));
|
|
26133
26099
|
}
|
|
26100
|
+
/**
|
|
26101
|
+
* Save a userEvent entity
|
|
26102
|
+
*
|
|
26103
|
+
* @param entity
|
|
26104
|
+
*/
|
|
26134
26105
|
save(entity, options) {
|
|
26135
26106
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26136
26107
|
this.fillDefaultProperties(entity);
|
|
@@ -26139,9 +26110,9 @@ class AbstractUserEventService extends BaseGraphqlService {
|
|
|
26139
26110
|
const json = entity.asObject();
|
|
26140
26111
|
const now = Date.now();
|
|
26141
26112
|
if (this._debug)
|
|
26142
|
-
console.debug(
|
|
26113
|
+
console.debug(`[user-event-service] Saving user event...`, json);
|
|
26143
26114
|
yield this.graphql.mutate({
|
|
26144
|
-
mutation:
|
|
26115
|
+
mutation: SaveQuery,
|
|
26145
26116
|
variables: {
|
|
26146
26117
|
data: json
|
|
26147
26118
|
},
|
|
@@ -26151,16 +26122,16 @@ class AbstractUserEventService extends BaseGraphqlService {
|
|
|
26151
26122
|
const savedEntity = data && data.data;
|
|
26152
26123
|
if (savedEntity) {
|
|
26153
26124
|
if (this._debug)
|
|
26154
|
-
console.debug(
|
|
26125
|
+
console.debug(`[user-event-service] User event saved in ${Date.now() - now}ms`, entity);
|
|
26155
26126
|
this.copyIdAndUpdateDate(savedEntity, entity);
|
|
26156
26127
|
// Add to cache
|
|
26157
26128
|
if (isNew) {
|
|
26158
26129
|
this.insertIntoMutableCachedQueries(proxy, {
|
|
26159
|
-
query:
|
|
26130
|
+
query: LoadAllQuery,
|
|
26160
26131
|
data: Object.assign(Object.assign({}, savedEntity), { content: null })
|
|
26161
26132
|
});
|
|
26162
26133
|
this.insertIntoMutableCachedQueries(proxy, {
|
|
26163
|
-
query:
|
|
26134
|
+
query: LoadAllWithContentQuery,
|
|
26164
26135
|
data: savedEntity
|
|
26165
26136
|
});
|
|
26166
26137
|
}
|
|
@@ -26170,144 +26141,63 @@ class AbstractUserEventService extends BaseGraphqlService {
|
|
|
26170
26141
|
return entity;
|
|
26171
26142
|
});
|
|
26172
26143
|
}
|
|
26173
|
-
|
|
26174
|
-
|
|
26175
|
-
|
|
26176
|
-
|
|
26177
|
-
|
|
26144
|
+
/**
|
|
26145
|
+
* Save many trips
|
|
26146
|
+
*
|
|
26147
|
+
* @param entities
|
|
26148
|
+
* @param opts
|
|
26149
|
+
*/
|
|
26150
|
+
deleteAll(entities, opts) {
|
|
26178
26151
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26179
|
-
|
|
26180
|
-
|
|
26181
|
-
if (
|
|
26182
|
-
|
|
26183
|
-
|
|
26152
|
+
const ids = entities && entities
|
|
26153
|
+
.map(t => t.id);
|
|
26154
|
+
if (isEmptyArray(ids))
|
|
26155
|
+
return; // stop, if nothing else to do
|
|
26156
|
+
const now = Date.now();
|
|
26157
|
+
if (this._debug)
|
|
26158
|
+
console.debug('[user-event-service] Deleting events... ids:', ids);
|
|
26159
|
+
yield this.graphql.mutate({
|
|
26160
|
+
mutation: DeleteByIdsMutation,
|
|
26161
|
+
variables: {
|
|
26162
|
+
ids
|
|
26163
|
+
},
|
|
26164
|
+
update: (proxy) => {
|
|
26165
|
+
// Remove from caches
|
|
26166
|
+
this.removeFromMutableCachedQueriesByIds(proxy, {
|
|
26167
|
+
query: LoadAllQuery,
|
|
26168
|
+
ids
|
|
26169
|
+
});
|
|
26170
|
+
this.removeFromMutableCachedQueriesByIds(proxy, {
|
|
26171
|
+
query: LoadAllWithContentQuery,
|
|
26172
|
+
ids
|
|
26173
|
+
});
|
|
26174
|
+
if (this._debug)
|
|
26175
|
+
console.debug(`[user-event-service] Events deleted in ${Date.now() - now}ms`);
|
|
26184
26176
|
}
|
|
26185
|
-
}
|
|
26186
|
-
else {
|
|
26187
|
-
// Use default
|
|
26188
|
-
yield this.defaultMarkAsRead(entity);
|
|
26189
|
-
}
|
|
26177
|
+
});
|
|
26190
26178
|
});
|
|
26191
26179
|
}
|
|
26192
|
-
|
|
26193
|
-
|
|
26194
|
-
|
|
26195
|
-
|
|
26196
|
-
}
|
|
26197
|
-
/* -- protected methods -- */
|
|
26198
|
-
processUserEvent(source) {
|
|
26199
|
-
// Convert json source to IUserEvent
|
|
26200
|
-
let target = this.fromObject(source);
|
|
26201
|
-
// Get listeners
|
|
26202
|
-
const listeners = (this.listeners || []).filter(listener => listener.onReceived).filter(listener => listener.accept(target));
|
|
26203
|
-
for (const listener of listeners) {
|
|
26204
|
-
if (target) {
|
|
26205
|
-
target = listener.onReceived(target);
|
|
26206
|
-
}
|
|
26207
|
-
else {
|
|
26208
|
-
if (this._debug)
|
|
26209
|
-
console.debug(`${this._logPrefix}Event has been rejected by a listener`, source);
|
|
26210
|
-
break;
|
|
26211
|
-
}
|
|
26212
|
-
}
|
|
26213
|
-
return target;
|
|
26214
|
-
}
|
|
26215
|
-
defaultMarkAsRead(userEvent) {
|
|
26180
|
+
/**
|
|
26181
|
+
* Delete userEvent entities
|
|
26182
|
+
*/
|
|
26183
|
+
delete(data) {
|
|
26216
26184
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26217
|
-
if (!
|
|
26218
|
-
|
|
26219
|
-
|
|
26220
|
-
userEvent.readDate = moment$6();
|
|
26221
|
-
if (!userEvent.id || userEvent.id < 0) {
|
|
26222
|
-
if (this._debug)
|
|
26223
|
-
console.debug(`${this._logPrefix}Save local user event`);
|
|
26224
|
-
// TODO !!!!!!!!!!!!!
|
|
26225
|
-
}
|
|
26226
|
-
else {
|
|
26227
|
-
yield this.save(userEvent);
|
|
26228
|
-
}
|
|
26185
|
+
if (!data)
|
|
26186
|
+
return; // skip
|
|
26187
|
+
yield this.deleteAll([data]);
|
|
26229
26188
|
});
|
|
26230
26189
|
}
|
|
26231
|
-
|
|
26232
|
-
//
|
|
26233
|
-
|
|
26234
|
-
|
|
26235
|
-
};
|
|
26236
|
-
}
|
|
26237
|
-
defaultRecipient() {
|
|
26238
|
-
return this.accountService.person.pubkey;
|
|
26239
|
-
}
|
|
26240
|
-
fillDefaultProperties(entity) {
|
|
26241
|
-
}
|
|
26242
|
-
unreadEvents(events) {
|
|
26243
|
-
// default calculation on unread events from a list
|
|
26244
|
-
if (isEmptyArray(events))
|
|
26245
|
-
return undefined;
|
|
26246
|
-
const lastReadDate = events
|
|
26247
|
-
.filter(event => isNotNil(event.readDate))
|
|
26248
|
-
.reduce((lastDate, event) => DateUtils.max(lastDate, event.readDate), undefined);
|
|
26249
|
-
return events
|
|
26250
|
-
.filter(event => event.creationDate.isSameOrAfter(lastReadDate)).length;
|
|
26251
|
-
}
|
|
26252
|
-
copyIdAndUpdateDate(source, target) {
|
|
26253
|
-
EntityUtils.copyIdAndUpdateDate(source, target);
|
|
26254
|
-
}
|
|
26255
|
-
}
|
|
26256
|
-
AbstractUserEventService.decorators = [
|
|
26257
|
-
{ type: Directive }
|
|
26258
|
-
];
|
|
26259
|
-
AbstractUserEventService.ctorParameters = () => [
|
|
26260
|
-
{ type: GraphqlService },
|
|
26261
|
-
{ type: AccountService },
|
|
26262
|
-
{ type: NetworkService },
|
|
26263
|
-
{ type: TranslateService },
|
|
26264
|
-
{ type: undefined },
|
|
26265
|
-
{ type: undefined },
|
|
26266
|
-
{ type: undefined },
|
|
26267
|
-
{ type: Environment, decorators: [{ type: Optional }, { type: Inject, args: [ENVIRONMENT,] }] }
|
|
26268
|
-
];
|
|
26269
|
-
const userEventQueries = {
|
|
26270
|
-
loadAll: gql `
|
|
26271
|
-
query UserEvents($filter: UserEventFilterVOInput, $page: PageInput){
|
|
26272
|
-
data: userEvents(filter: $filter, page: $page){
|
|
26273
|
-
...LightUserEventFragment
|
|
26274
|
-
}
|
|
26275
|
-
}
|
|
26276
|
-
${UserEventFragments.lightUserEvent}
|
|
26277
|
-
`,
|
|
26278
|
-
loadAllWithContent: gql `
|
|
26279
|
-
query UserEventsWithContent($filter: UserEventFilterVOInput, $page: PageInput){
|
|
26280
|
-
data: userEvents(filter: $filter, page: $page){
|
|
26281
|
-
...UserEventFragment
|
|
26282
|
-
}
|
|
26190
|
+
listenChanges(id, options) {
|
|
26191
|
+
// TODO
|
|
26192
|
+
console.warn('TODO: implement listen changes on user events');
|
|
26193
|
+
return of();
|
|
26283
26194
|
}
|
|
26284
|
-
|
|
26285
|
-
|
|
26286
|
-
|
|
26287
|
-
const userEventMutations = {
|
|
26288
|
-
deleteByIds: gql `
|
|
26289
|
-
mutation DeleteUserEvents($ids:[Int]){
|
|
26290
|
-
deleteUserEvents(ids: $ids)
|
|
26291
|
-
}
|
|
26292
|
-
`,
|
|
26293
|
-
save: gql `
|
|
26294
|
-
mutation SaveUserEvent($data: UserEventVOInput){
|
|
26295
|
-
data: saveUserEvent(userEvent: $data){
|
|
26296
|
-
...UserEventFragment
|
|
26297
|
-
}
|
|
26195
|
+
registerAction(definition) {
|
|
26196
|
+
console.info(`[user-event-service] Registering action ${definition.name} for ${definition.__typename}`);
|
|
26197
|
+
this._userEventActions.push(definition);
|
|
26298
26198
|
}
|
|
26299
|
-
|
|
26300
|
-
|
|
26301
|
-
};
|
|
26302
|
-
class UserEventService extends AbstractUserEventService {
|
|
26303
|
-
constructor(graphql, accountService, network, translate, toastController, environment) {
|
|
26304
|
-
super(graphql, accountService, network, translate, userEventQueries, userEventMutations, undefined, environment);
|
|
26305
|
-
this.graphql = graphql;
|
|
26306
|
-
this.accountService = accountService;
|
|
26307
|
-
this.network = network;
|
|
26308
|
-
this.translate = translate;
|
|
26309
|
-
this.toastController = toastController;
|
|
26310
|
-
this.environment = environment;
|
|
26199
|
+
getActionsByTypename(typename) {
|
|
26200
|
+
return this._userEventActions.filter(def => def.__typename === typename);
|
|
26311
26201
|
}
|
|
26312
26202
|
showToastErrorWithContext(opts) {
|
|
26313
26203
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -26371,16 +26261,13 @@ class UserEventService extends AbstractUserEventService {
|
|
|
26371
26261
|
}
|
|
26372
26262
|
sendDataForDebug(data) {
|
|
26373
26263
|
const userEvent = new UserEvent();
|
|
26374
|
-
userEvent.
|
|
26264
|
+
userEvent.eventType = UserEventTypes.DEBUG_DATA;
|
|
26375
26265
|
userEvent.content = this.convertObjectToString(data);
|
|
26376
26266
|
return this.save(userEvent);
|
|
26377
26267
|
}
|
|
26378
26268
|
asFilter(filter) {
|
|
26379
26269
|
return UserEventFilter.fromObject(filter);
|
|
26380
26270
|
}
|
|
26381
|
-
fromObject(source) {
|
|
26382
|
-
return UserEvent.fromObject(source);
|
|
26383
|
-
}
|
|
26384
26271
|
/* -- protected methods -- */
|
|
26385
26272
|
convertObjectToString(data) {
|
|
26386
26273
|
if (typeof data === 'string') {
|
|
@@ -26409,9 +26296,13 @@ class UserEventService extends AbstractUserEventService {
|
|
|
26409
26296
|
// TODO: compute sign
|
|
26410
26297
|
console.warn('TODO: sign user event before sending');
|
|
26411
26298
|
}
|
|
26299
|
+
copyIdAndUpdateDate(source, target) {
|
|
26300
|
+
EntityUtils.copyIdAndUpdateDate(source, target);
|
|
26301
|
+
}
|
|
26412
26302
|
}
|
|
26303
|
+
UserEventService.ɵprov = ɵɵdefineInjectable({ factory: function UserEventService_Factory() { return new UserEventService(ɵɵinject(GraphqlService), ɵɵinject(AccountService), ɵɵinject(NetworkService), ɵɵinject(TranslateService), ɵɵinject(ToastController), ɵɵinject(ENVIRONMENT, 8)); }, token: UserEventService, providedIn: "root" });
|
|
26413
26304
|
UserEventService.decorators = [
|
|
26414
|
-
{ type: Injectable }
|
|
26305
|
+
{ type: Injectable, args: [{ providedIn: 'root' },] }
|
|
26415
26306
|
];
|
|
26416
26307
|
UserEventService.ctorParameters = () => [
|
|
26417
26308
|
{ type: GraphqlService },
|
|
@@ -26424,7 +26315,7 @@ UserEventService.ctorParameters = () => [
|
|
|
26424
26315
|
|
|
26425
26316
|
const ICONS_MAP = {
|
|
26426
26317
|
DEBUG_DATA: { matIcon: 'bug_report' },
|
|
26427
|
-
INBOX_MESSAGE: { matIcon: 'mail' }
|
|
26318
|
+
INBOX_MESSAGE: { matIcon: 'mail' },
|
|
26428
26319
|
};
|
|
26429
26320
|
// TODO: refactor with a registration done by data service:
|
|
26430
26321
|
// - userEventService.registerEventAction({__typename: 'TripVO', ...})
|
|
@@ -26490,7 +26381,7 @@ class UserEventsTable extends AppTable {
|
|
|
26490
26381
|
}
|
|
26491
26382
|
}));
|
|
26492
26383
|
const filter = this.filter || new UserEventFilter();
|
|
26493
|
-
filter.
|
|
26384
|
+
filter.recipient = this.recipient;
|
|
26494
26385
|
this.setFilter(filter, { emitEvent: true });
|
|
26495
26386
|
}
|
|
26496
26387
|
start() {
|
|
@@ -26503,17 +26394,17 @@ class UserEventsTable extends AppTable {
|
|
|
26503
26394
|
});
|
|
26504
26395
|
}
|
|
26505
26396
|
getIcon(source) {
|
|
26506
|
-
return ICONS_MAP[source.
|
|
26397
|
+
return ICONS_MAP[source.eventType];
|
|
26507
26398
|
}
|
|
26508
26399
|
getDetail(source) {
|
|
26509
26400
|
if (!source)
|
|
26510
26401
|
return undefined;
|
|
26511
|
-
if (source.content && source.
|
|
26402
|
+
if (source.content && source.eventType === UserEventTypes.DEBUG_DATA) {
|
|
26512
26403
|
const context = source.content.context;
|
|
26513
26404
|
if (context && context.__typename) {
|
|
26514
|
-
|
|
26405
|
+
const actions = this.service.getActionsByTypename(context.__typename);
|
|
26515
26406
|
return {
|
|
26516
|
-
|
|
26407
|
+
actions,
|
|
26517
26408
|
title: source.content.error && source.content.error.message || source.content.message,
|
|
26518
26409
|
description: source.content.error && source.content.error.details || undefined
|
|
26519
26410
|
};
|
|
@@ -26525,11 +26416,11 @@ class UserEventsTable extends AppTable {
|
|
|
26525
26416
|
doAction(action, row) {
|
|
26526
26417
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26527
26418
|
const event = row.currentData;
|
|
26528
|
-
|
|
26419
|
+
const context = event.content && event.content.context;
|
|
26529
26420
|
this.markAsLoading();
|
|
26530
26421
|
if (action && typeof action.executeAction === 'function') {
|
|
26531
26422
|
try {
|
|
26532
|
-
let res = action.executeAction(event
|
|
26423
|
+
let res = action.executeAction(event, context);
|
|
26533
26424
|
res = (res instanceof Promise) ? yield res : res;
|
|
26534
26425
|
}
|
|
26535
26426
|
catch (err) {
|
|
@@ -26548,18 +26439,13 @@ UserEventsTable.decorators = [
|
|
|
26548
26439
|
selector: 'app-user-events-table',
|
|
26549
26440
|
template: "\n<!-- Type = options menu -->\n<mat-menu #optionsMenu=\"matMenu\" xPosition=\"after\">\n\n <!-- display columns -->\n <button mat-menu-item\n (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n</mat-menu>\n\n<!-- top header -->\n<mat-toolbar>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n\n <button mat-icon-button [title]=\"'COMMON.BTN_REFRESH'|translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\n\n <!-- delete -->\n <button mat-icon-button class=\"hidden-xs hidden-sm\" *ngIf=\"canDelete\"\n [title]=\"'COMMON.BTN_DELETE'|translate\" (click)=\"deleteSelection($event)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" hidden-xs hidden-sm hidden-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS'|translate\"\n [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n</mat-toolbar>\n\n\n<mat-table [dataSource]=\"dataSource\" matSort\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear [trackBy]=\"trackByFn\">\n\n <!-- select -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\" [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <!-- id -->\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef mat-sort-header [class.cdk-visually-hidden]=\"!isAdmin\">\n <app-loading-spinner [loading]=\"loadingSubject|async\"><ion-label>#</ion-label></app-loading-spinner>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!isAdmin\">{{ row.currentData.id | mathAbs }}</mat-cell>\n </ng-container>\n\n <!-- creationDate -->\n <ng-container matColumnDef=\"creationDate\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.CREATION_DATE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ion-text>\n {{row.currentData.creationDate | dateFromNow }}<br/>\n <ion-text color=\"medium\"><small>{{row.currentData.creationDate | dateFormat: {time: true} }}</small></ion-text>\n </ion-text>\n </mat-cell>\n </ng-container>\n\n <!-- icon -->\n <ng-container matColumnDef=\"icon\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getIcon(row.currentData); let details\">\n <ion-icon slot=\"start\" *ngIf=\"details.icon\" [name]=\"details.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"details.matIcon\">{{details.matIcon}}</mat-icon>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- event type -->\n <ng-container matColumnDef=\"eventType\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.EVENT_TYPE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <span>{{'SOCIAL.USER_EVENT.TYPE_ENUM.' + row.currentData.eventType | translate}}</span>\n </mat-cell>\n </ng-container>\n\n <!-- message -->\n <ng-container matColumnDef=\"message\">\n <mat-header-cell *matHeaderCellDef>\n <ion-label translate>SOCIAL.USER_EVENT.MESSAGE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <ion-text [innerHTML]=\"details.title|translate\">\n </ion-text>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- Actions buttons column -->\n <ng-container matColumnDef=\"actions\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <button mat-icon-button color=\"light\"\n *ngFor=\"let action of details.actions\"\n [title]=\"action.title |translate\"\n [color]=\"action.color\"\n (click)=\"doAction(action, row)\">\n <ion-icon slot=\"start\" *ngIf=\"action.icon\" [name]=\"action.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"action.matIcon\">{{action.matIcon}}</mat-icon>\n </button>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n class=\"mat-row-disabled\"\n (click)=\"clickRow($event, row)\"></mat-row>\n\n</mat-table>\n\n<ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col class=\"ion-no-padding\" size=\"auto\">\n <mat-paginator [length]=\"totalRowCount\" [pageSize]=\"defaultPageSize\" [pageSizeOptions]=\"defaultPageSizeOptions\" showFirstLastButtons>\n </mat-paginator>\n </ion-col>\n</ion-row>\n",
|
|
26550
26441
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26551
|
-
providers: [
|
|
26552
|
-
{
|
|
26553
|
-
provide: UserEventServiceToken, useClass: UserEventService
|
|
26554
|
-
}
|
|
26555
|
-
],
|
|
26556
26442
|
styles: [".mat-header-row .mat-column-icon,.mat-row .mat-column-icon{max-width:40px;padding-left:0}.mat-header-row .mat-column-icon ion-icon,.mat-header-row .mat-column-icon mat-icon,.mat-row .mat-column-icon ion-icon,.mat-row .mat-column-icon mat-icon{font-size:1.2em;height:1.2em;width:1.2em}.mat-header-row .mat-column-creationDate,.mat-row .mat-column-creationDate{min-width:100px;max-width:120px}"]
|
|
26557
26443
|
},] }
|
|
26558
26444
|
];
|
|
26559
26445
|
UserEventsTable.ctorParameters = () => [
|
|
26560
26446
|
{ type: Injector },
|
|
26561
26447
|
{ type: AccountService },
|
|
26562
|
-
{ type:
|
|
26448
|
+
{ type: UserEventService },
|
|
26563
26449
|
{ type: EntitiesStorage },
|
|
26564
26450
|
{ type: ChangeDetectorRef },
|
|
26565
26451
|
{ type: undefined, decorators: [{ type: Inject, args: [ENVIRONMENT,] }] }
|
|
@@ -26571,147 +26457,6 @@ UserEventsTable.propDecorators = {
|
|
|
26571
26457
|
defaultSortDirection: [{ type: Input }]
|
|
26572
26458
|
};
|
|
26573
26459
|
|
|
26574
|
-
class UserEventNotificationList {
|
|
26575
|
-
constructor(popoverController) {
|
|
26576
|
-
this.popoverController = popoverController;
|
|
26577
|
-
}
|
|
26578
|
-
ngOnInit() {
|
|
26579
|
-
}
|
|
26580
|
-
read($event, userEvent) {
|
|
26581
|
-
var _a;
|
|
26582
|
-
if (userEvent === null || userEvent === void 0 ? void 0 : userEvent.readDate)
|
|
26583
|
-
return;
|
|
26584
|
-
(_a = this.readEvent) === null || _a === void 0 ? void 0 : _a.emit(userEvent);
|
|
26585
|
-
}
|
|
26586
|
-
executeAction(action, userEvent) {
|
|
26587
|
-
// Execute then close popover
|
|
26588
|
-
action.executeAction(userEvent);
|
|
26589
|
-
this.dismiss();
|
|
26590
|
-
}
|
|
26591
|
-
dismiss() {
|
|
26592
|
-
this.popoverController.dismiss();
|
|
26593
|
-
}
|
|
26594
|
-
}
|
|
26595
|
-
UserEventNotificationList.decorators = [
|
|
26596
|
-
{ type: Component, args: [{
|
|
26597
|
-
selector: 'app-user-event-notification-list',
|
|
26598
|
-
template: "\n<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!(userEvents | async)?.length\">\n {{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}\n </ion-item>\n <ion-item\n *ngFor=\"let userEvent of userEvents | async\"\n (click)=\"read($event, userEvent)\"\n >\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"userEvent.avatar; else avatarIcon\" src=\"{{ userEvent.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"userEvent.avatarIcon\"\n [ref]=\"userEvent.avatarIcon\"\n height=\"40\"\n width=\"40\"\n ></app-icon>\n </ng-template>\n\n </ion-avatar>\n\n <ion-grid class=\"ion-no-margin ion-no-padding\">\n <ion-row>\n <ion-col>\n <p [class.unread]=\"!userEvent.readDate\">\n {{userEvent.message}}\n </p>\n </ion-col>\n </ion-row>\n <ion-row *ngIf=\"userEvent.actions?.length\">\n <ion-col>\n <p>\n <span *ngFor=\"let action of userEvent.actions\">\n <a\n [style.margin-right.px]=\"8\"\n [style.cursor]=\"'pointer'\"\n (click)=\"executeAction(action, userEvent)\"\n >\n {{ '➞ ' + action.name}}\n </a>\n </span>\n </p>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <app-icon\n *ngIf=\"userEvent.icon\"\n [ref]=\"userEvent.icon\"\n height=\"16\"\n width=\"16\"\n [style.vertical-align]=\"'sub'\"\n ></app-icon>\n <small>\n <span>{{userEvent.creationDate|dateFromNow}}</span>\n <span [style.color]=\"'gray'\">{{ ' | ' + (userEvent.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
|
|
26599
|
-
styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}.unread{font-weight:700}"]
|
|
26600
|
-
},] }
|
|
26601
|
-
];
|
|
26602
|
-
UserEventNotificationList.ctorParameters = () => [
|
|
26603
|
-
{ type: PopoverController }
|
|
26604
|
-
];
|
|
26605
|
-
UserEventNotificationList.propDecorators = {
|
|
26606
|
-
titleI18n: [{ type: Input }],
|
|
26607
|
-
userEvents: [{ type: Input }],
|
|
26608
|
-
readEvent: [{ type: Output }]
|
|
26609
|
-
};
|
|
26610
|
-
|
|
26611
|
-
class UserEventNotificationComponent {
|
|
26612
|
-
constructor(userEventService, accountService, popoverController, cd) {
|
|
26613
|
-
this.userEventService = userEventService;
|
|
26614
|
-
this.accountService = accountService;
|
|
26615
|
-
this.popoverController = popoverController;
|
|
26616
|
-
this.cd = cd;
|
|
26617
|
-
this.debug = false;
|
|
26618
|
-
this.titleI18n = 'SOCIAL.USER_EVENT.NOTIFICATION.TITLE';
|
|
26619
|
-
this.disabled = false;
|
|
26620
|
-
this.userEventsSubject = new BehaviorSubject(undefined);
|
|
26621
|
-
this._subscriptions = new Subscription();
|
|
26622
|
-
this._logPrefix = '[user-event-notification] ';
|
|
26623
|
-
this._readEvent = new EventEmitter();
|
|
26624
|
-
}
|
|
26625
|
-
get count() {
|
|
26626
|
-
var _a;
|
|
26627
|
-
return (_a = this.userEventService) === null || _a === void 0 ? void 0 : _a.userEventCount.pipe(map(value => value === 0 ? undefined : value));
|
|
26628
|
-
}
|
|
26629
|
-
ngOnInit() {
|
|
26630
|
-
if (isNil(this.userEventService)) {
|
|
26631
|
-
console.warn(`${this._logPrefix}No service injected`);
|
|
26632
|
-
this.disabled = true;
|
|
26633
|
-
return;
|
|
26634
|
-
}
|
|
26635
|
-
this._subscriptions.add(this.userEventService.watchAll(0, 10, 'creationDate', "desc").subscribe(value => {
|
|
26636
|
-
const data = value.data;
|
|
26637
|
-
if (this.debug) {
|
|
26638
|
-
console.debug(`${this._logPrefix}Receiving user events`, data);
|
|
26639
|
-
}
|
|
26640
|
-
this.userEventsSubject.next(data);
|
|
26641
|
-
}));
|
|
26642
|
-
this._readEvent.subscribe(value => {
|
|
26643
|
-
this.userEventService.markAsRead(value);
|
|
26644
|
-
});
|
|
26645
|
-
}
|
|
26646
|
-
showList(event) {
|
|
26647
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26648
|
-
const popover = yield this.popoverController.create({
|
|
26649
|
-
component: UserEventNotificationList,
|
|
26650
|
-
componentProps: {
|
|
26651
|
-
titleI18n: this.titleI18n,
|
|
26652
|
-
userEvents: this.userEventsSubject,
|
|
26653
|
-
readEvent: this._readEvent
|
|
26654
|
-
},
|
|
26655
|
-
backdropDismiss: true,
|
|
26656
|
-
keyboardClose: true,
|
|
26657
|
-
event,
|
|
26658
|
-
translucent: true,
|
|
26659
|
-
cssClass: 'popover-large'
|
|
26660
|
-
});
|
|
26661
|
-
yield popover.present();
|
|
26662
|
-
});
|
|
26663
|
-
}
|
|
26664
|
-
markForCheck() {
|
|
26665
|
-
this.cd.markForCheck();
|
|
26666
|
-
}
|
|
26667
|
-
ngOnDestroy() {
|
|
26668
|
-
if (this.debug) {
|
|
26669
|
-
console.debug(`${this._logPrefix}Destroying`);
|
|
26670
|
-
}
|
|
26671
|
-
this._subscriptions.unsubscribe();
|
|
26672
|
-
}
|
|
26673
|
-
}
|
|
26674
|
-
UserEventNotificationComponent.decorators = [
|
|
26675
|
-
{ type: Component, args: [{
|
|
26676
|
-
selector: 'app-user-event-notification-component',
|
|
26677
|
-
template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n [matBadge]=\"count | async\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n >notifications\n </mat-icon>\n</button>\n\n",
|
|
26678
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26679
|
-
styles: [""]
|
|
26680
|
-
},] }
|
|
26681
|
-
];
|
|
26682
|
-
UserEventNotificationComponent.ctorParameters = () => [
|
|
26683
|
-
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [UserEventServiceToken,] }] },
|
|
26684
|
-
{ type: AccountService },
|
|
26685
|
-
{ type: PopoverController },
|
|
26686
|
-
{ type: ChangeDetectorRef }
|
|
26687
|
-
];
|
|
26688
|
-
UserEventNotificationComponent.propDecorators = {
|
|
26689
|
-
debug: [{ type: Input }],
|
|
26690
|
-
titleI18n: [{ type: Input }],
|
|
26691
|
-
disabled: [{ type: Input }]
|
|
26692
|
-
};
|
|
26693
|
-
|
|
26694
|
-
class UserEventModule {
|
|
26695
|
-
}
|
|
26696
|
-
UserEventModule.decorators = [
|
|
26697
|
-
{ type: NgModule, args: [{
|
|
26698
|
-
imports: [
|
|
26699
|
-
CommonModule,
|
|
26700
|
-
CoreModule,
|
|
26701
|
-
SharedModule
|
|
26702
|
-
],
|
|
26703
|
-
declarations: [
|
|
26704
|
-
UserEventsTable,
|
|
26705
|
-
UserEventNotificationComponent,
|
|
26706
|
-
UserEventNotificationList,
|
|
26707
|
-
],
|
|
26708
|
-
exports: [
|
|
26709
|
-
UserEventsTable,
|
|
26710
|
-
UserEventNotificationComponent
|
|
26711
|
-
]
|
|
26712
|
-
},] }
|
|
26713
|
-
];
|
|
26714
|
-
|
|
26715
26460
|
const MessageTypes = {
|
|
26716
26461
|
INBOX_MESSAGE: 'INBOX_MESSAGE',
|
|
26717
26462
|
EMAIL: 'EMAIL',
|
|
@@ -26923,9 +26668,9 @@ MessageForm.propDecorators = {
|
|
|
26923
26668
|
canSelectType: [{ type: Input }]
|
|
26924
26669
|
};
|
|
26925
26670
|
|
|
26926
|
-
class
|
|
26671
|
+
class SocialModule {
|
|
26927
26672
|
}
|
|
26928
|
-
|
|
26673
|
+
SocialModule.decorators = [
|
|
26929
26674
|
{ type: NgModule, args: [{
|
|
26930
26675
|
imports: [
|
|
26931
26676
|
CommonModule,
|
|
@@ -26933,317 +26678,17 @@ MessageModule.decorators = [
|
|
|
26933
26678
|
SharedModule
|
|
26934
26679
|
],
|
|
26935
26680
|
declarations: [
|
|
26681
|
+
UserEventsTable,
|
|
26936
26682
|
MessageModal,
|
|
26937
26683
|
MessageForm
|
|
26938
26684
|
],
|
|
26939
26685
|
exports: [
|
|
26686
|
+
UserEventsTable,
|
|
26940
26687
|
MessageModal
|
|
26941
26688
|
]
|
|
26942
26689
|
},] }
|
|
26943
26690
|
];
|
|
26944
26691
|
|
|
26945
|
-
var JobProgression_1;
|
|
26946
|
-
// todo use entity
|
|
26947
|
-
class Job {
|
|
26948
|
-
}
|
|
26949
|
-
// @dynamic
|
|
26950
|
-
let JobProgression = JobProgression_1 = class JobProgression extends Entity {
|
|
26951
|
-
constructor() {
|
|
26952
|
-
super(JobProgression_1.TYPENAME);
|
|
26953
|
-
}
|
|
26954
|
-
fromObject(source) {
|
|
26955
|
-
super.fromObject(source);
|
|
26956
|
-
this.message = source.message;
|
|
26957
|
-
this.current = source.current;
|
|
26958
|
-
this.total = source.total;
|
|
26959
|
-
}
|
|
26960
|
-
};
|
|
26961
|
-
JobProgression = JobProgression_1 = __decorate([
|
|
26962
|
-
EntityClass({ typename: 'JobProgressionVO' })
|
|
26963
|
-
], JobProgression);
|
|
26964
|
-
|
|
26965
|
-
const JobProgressionServiceToken = new InjectionToken('JobProgressionService');
|
|
26966
|
-
const jobProgressionSubscription = gql `subscription UpdateJobProgression($id: Int!, $interval: Int){
|
|
26967
|
-
data: updateJobProgression(id: $id, interval: $interval) {
|
|
26968
|
-
id
|
|
26969
|
-
message
|
|
26970
|
-
current
|
|
26971
|
-
total
|
|
26972
|
-
}
|
|
26973
|
-
}`;
|
|
26974
|
-
class JobProgressionService extends BaseGraphqlService {
|
|
26975
|
-
constructor(graphql, environment) {
|
|
26976
|
-
super(graphql, environment);
|
|
26977
|
-
this.graphql = graphql;
|
|
26978
|
-
this.environment = environment;
|
|
26979
|
-
this._logPrefix = '[job-progression-service] ';
|
|
26980
|
-
// For DEV only
|
|
26981
|
-
this._debug = !(environment === null || environment === void 0 ? void 0 : environment.production);
|
|
26982
|
-
}
|
|
26983
|
-
listenChanges(id, options) {
|
|
26984
|
-
if (isNil(id))
|
|
26985
|
-
throw new Error(`${this._logPrefix}Missing argument 'id'`);
|
|
26986
|
-
if (this._debug)
|
|
26987
|
-
console.debug(`${this._logPrefix}[WS] Listening changes for job progression {${id}}...`);
|
|
26988
|
-
return this.graphql.subscribe({
|
|
26989
|
-
query: jobProgressionSubscription,
|
|
26990
|
-
fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
|
|
26991
|
-
variables: { id, interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
|
|
26992
|
-
error: { code: SocialErrorCodes.SUBSCRIBE_JOB_PROGRESSION_ERROR, message: 'SOCIAL.ERROR.SUBSCRIBE_JOB_PROGRESSION_ERROR' }
|
|
26993
|
-
}).pipe(map(({ data }) => {
|
|
26994
|
-
const progression = data && JobProgression.fromObject(data);
|
|
26995
|
-
if (progression && this._debug)
|
|
26996
|
-
console.debug(`${this._logPrefix}Job progression ${id} updated on server`, progression);
|
|
26997
|
-
return progression;
|
|
26998
|
-
}));
|
|
26999
|
-
}
|
|
27000
|
-
}
|
|
27001
|
-
JobProgressionService.decorators = [
|
|
27002
|
-
{ type: Injectable }
|
|
27003
|
-
];
|
|
27004
|
-
JobProgressionService.ctorParameters = () => [
|
|
27005
|
-
{ type: GraphqlService },
|
|
27006
|
-
{ type: Environment, decorators: [{ type: Optional }, { type: Inject, args: [ENVIRONMENT,] }] }
|
|
27007
|
-
];
|
|
27008
|
-
|
|
27009
|
-
class JobProgressionList {
|
|
27010
|
-
constructor() {
|
|
27011
|
-
}
|
|
27012
|
-
ngOnInit() {
|
|
27013
|
-
}
|
|
27014
|
-
}
|
|
27015
|
-
JobProgressionList.decorators = [
|
|
27016
|
-
{ type: Component, args: [{
|
|
27017
|
-
selector: 'app-job-progression-list',
|
|
27018
|
-
template: "<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!jobProgressions?.length\">\n {{'SOCIAL.JOB.PROGRESSION.EMPTY' | translate}}\n </ion-item>\n <ion-item *ngFor=\"let jobProgression of jobProgressions\">\n <ion-grid class=\"ion-no-margin\">\n <ion-row>\n <ion-col>\n {{jobProgression.message}}\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-progress-bar\n [value]=\"jobProgression.total > 0 ? jobProgression.current / jobProgression.total : undefined\"\n [type]=\"jobProgression.total > 0 ? 'determinate' : 'indeterminate'\">\n </ion-progress-bar>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
|
|
27019
|
-
styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}"]
|
|
27020
|
-
},] }
|
|
27021
|
-
];
|
|
27022
|
-
JobProgressionList.ctorParameters = () => [];
|
|
27023
|
-
JobProgressionList.propDecorators = {
|
|
27024
|
-
titleI18n: [{ type: Input }],
|
|
27025
|
-
jobProgressions: [{ type: Input }]
|
|
27026
|
-
};
|
|
27027
|
-
|
|
27028
|
-
class JobProgressionComponent {
|
|
27029
|
-
constructor(jobProgressionService, popoverController, cd) {
|
|
27030
|
-
this.jobProgressionService = jobProgressionService;
|
|
27031
|
-
this.popoverController = popoverController;
|
|
27032
|
-
this.cd = cd;
|
|
27033
|
-
this.debug = false;
|
|
27034
|
-
this.titleI18n = 'SOCIAL.JOB.PROGRESSION.TITLE';
|
|
27035
|
-
this.jobFinished = new EventEmitter();
|
|
27036
|
-
this.disabled = true;
|
|
27037
|
-
this.color = 'accent';
|
|
27038
|
-
this.mode = 'determinate';
|
|
27039
|
-
this.value = 0;
|
|
27040
|
-
this.jobProgressions = [];
|
|
27041
|
-
this._subscriptions = new Subscription();
|
|
27042
|
-
this._subscriptionsById = {};
|
|
27043
|
-
this._logPrefix = '[job-progression] ';
|
|
27044
|
-
}
|
|
27045
|
-
ngOnInit() {
|
|
27046
|
-
var _a, _b, _c, _d;
|
|
27047
|
-
if (isNil(this.jobProgressionService)) {
|
|
27048
|
-
console.warn(`${this._logPrefix}No service injected`);
|
|
27049
|
-
}
|
|
27050
|
-
// parse options
|
|
27051
|
-
this.autoHide = toBoolean((_a = this.options) === null || _a === void 0 ? void 0 : _a.autoHide, false);
|
|
27052
|
-
this.visible = !this.autoHide;
|
|
27053
|
-
this.autoHideDelay = toNumber((_b = this.options) === null || _b === void 0 ? void 0 : _b.autoHideDelay, 1000);
|
|
27054
|
-
this.autoRemove = toBoolean((_c = this.options) === null || _c === void 0 ? void 0 : _c.autoRemove, true);
|
|
27055
|
-
this.autoRemoveDelay = toNumber((_d = this.options) === null || _d === void 0 ? void 0 : _d.autoRemoveDelay, 1000);
|
|
27056
|
-
}
|
|
27057
|
-
addJob(id) {
|
|
27058
|
-
if (isNil(this.jobProgressionService)) {
|
|
27059
|
-
console.warn(`${this._logPrefix}No service injected. Can't add a job`);
|
|
27060
|
-
return;
|
|
27061
|
-
}
|
|
27062
|
-
if (this.debug) {
|
|
27063
|
-
console.debug(`${this._logPrefix}Add job id=${id}`);
|
|
27064
|
-
}
|
|
27065
|
-
if (!!this.getProgression(id)) {
|
|
27066
|
-
console.warn(`${this._logPrefix}Job (id=${id}) already present`);
|
|
27067
|
-
return;
|
|
27068
|
-
}
|
|
27069
|
-
this.disabled = false;
|
|
27070
|
-
const sub = this.jobProgressionService.listenChanges(id)
|
|
27071
|
-
.pipe(filter(progression => {
|
|
27072
|
-
if (id !== progression.id) {
|
|
27073
|
-
console.error(`${this._logPrefix}Job progression (id=${progression.id}) doesn't match expected job (id=${id})`);
|
|
27074
|
-
return false;
|
|
27075
|
-
}
|
|
27076
|
-
return true;
|
|
27077
|
-
}), map(progression => {
|
|
27078
|
-
// Ensure visible
|
|
27079
|
-
this.visible = true;
|
|
27080
|
-
// Get current progression object
|
|
27081
|
-
const currentProgression = this.getProgression(id);
|
|
27082
|
-
if (!currentProgression) {
|
|
27083
|
-
// add it
|
|
27084
|
-
this.jobProgressions.push(progression);
|
|
27085
|
-
if (this.debug) {
|
|
27086
|
-
console.debug(`${this._logPrefix}Progression added id=${id}`, progression);
|
|
27087
|
-
}
|
|
27088
|
-
}
|
|
27089
|
-
else {
|
|
27090
|
-
// update current
|
|
27091
|
-
Object.assign(currentProgression, progression);
|
|
27092
|
-
if (this.debug) {
|
|
27093
|
-
console.debug(`${this._logPrefix}Progression updated id=${id}`, progression);
|
|
27094
|
-
}
|
|
27095
|
-
}
|
|
27096
|
-
return progression;
|
|
27097
|
-
}))
|
|
27098
|
-
.subscribe(progression => {
|
|
27099
|
-
// update value
|
|
27100
|
-
this.updateValue();
|
|
27101
|
-
// job finished
|
|
27102
|
-
if (progression.total > 0 && progression.current == progression.total) {
|
|
27103
|
-
if (this.debug) {
|
|
27104
|
-
console.debug(`${this._logPrefix}Finished job id=${progression.id}`);
|
|
27105
|
-
}
|
|
27106
|
-
// emit event
|
|
27107
|
-
this.jobFinished.emit(progression.id);
|
|
27108
|
-
if (this.autoRemove) {
|
|
27109
|
-
setTimeout(() => {
|
|
27110
|
-
var _a;
|
|
27111
|
-
this.removeJob(progression.id);
|
|
27112
|
-
// If last job
|
|
27113
|
-
if (this.autoHide && !((_a = this.jobProgressions) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
27114
|
-
setTimeout(() => {
|
|
27115
|
-
this.visible = false;
|
|
27116
|
-
this.markForCheck();
|
|
27117
|
-
}, this.autoHideDelay);
|
|
27118
|
-
}
|
|
27119
|
-
}, this.autoRemoveDelay);
|
|
27120
|
-
}
|
|
27121
|
-
}
|
|
27122
|
-
});
|
|
27123
|
-
this._subscriptionsById[id] = sub;
|
|
27124
|
-
this._subscriptions.add(sub);
|
|
27125
|
-
}
|
|
27126
|
-
removeJob(id) {
|
|
27127
|
-
if (this.debug) {
|
|
27128
|
-
console.debug(`${this._logPrefix}Remove job id=${id}`);
|
|
27129
|
-
}
|
|
27130
|
-
const sub = this._subscriptionsById[id];
|
|
27131
|
-
if (sub) {
|
|
27132
|
-
this._subscriptions.remove(sub);
|
|
27133
|
-
sub.unsubscribe();
|
|
27134
|
-
}
|
|
27135
|
-
const progression = this.getProgression(id);
|
|
27136
|
-
if (progression) {
|
|
27137
|
-
this.jobProgressions.splice(this.jobProgressions.indexOf(progression), 1);
|
|
27138
|
-
}
|
|
27139
|
-
this.updateValue();
|
|
27140
|
-
}
|
|
27141
|
-
getProgression(id) {
|
|
27142
|
-
return this.jobProgressions.find(progression => progression.id === id);
|
|
27143
|
-
}
|
|
27144
|
-
updateValue() {
|
|
27145
|
-
if (this.debug) {
|
|
27146
|
-
console.debug(`${this._logPrefix}Updating value`);
|
|
27147
|
-
}
|
|
27148
|
-
let value = 0;
|
|
27149
|
-
const nbProgression = arraySize(this.jobProgressions);
|
|
27150
|
-
let allIndeterminate = nbProgression > 0;
|
|
27151
|
-
this.jobProgressions.forEach(progression => {
|
|
27152
|
-
const indeterminate = progression.total === 0;
|
|
27153
|
-
allIndeterminate = allIndeterminate && indeterminate;
|
|
27154
|
-
if (!indeterminate) {
|
|
27155
|
-
value = value + progression.current * 100 / progression.total;
|
|
27156
|
-
}
|
|
27157
|
-
});
|
|
27158
|
-
this.value = nbProgression > 0 ? value / nbProgression : 0;
|
|
27159
|
-
this.mode = allIndeterminate ? 'indeterminate' : 'determinate';
|
|
27160
|
-
if (this.debug) {
|
|
27161
|
-
console.debug(`${this._logPrefix}Setting value=${this.value}, mode=${this.mode}`);
|
|
27162
|
-
}
|
|
27163
|
-
this.markForCheck();
|
|
27164
|
-
}
|
|
27165
|
-
showList(event) {
|
|
27166
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
27167
|
-
const popover = yield this.popoverController.create({
|
|
27168
|
-
component: JobProgressionList,
|
|
27169
|
-
componentProps: {
|
|
27170
|
-
titleI18n: this.titleI18n,
|
|
27171
|
-
jobProgressions: this.jobProgressions
|
|
27172
|
-
},
|
|
27173
|
-
backdropDismiss: true,
|
|
27174
|
-
keyboardClose: true,
|
|
27175
|
-
event,
|
|
27176
|
-
translucent: true,
|
|
27177
|
-
cssClass: 'popover-large'
|
|
27178
|
-
});
|
|
27179
|
-
yield popover.present();
|
|
27180
|
-
});
|
|
27181
|
-
}
|
|
27182
|
-
markForCheck() {
|
|
27183
|
-
this.cd.markForCheck();
|
|
27184
|
-
}
|
|
27185
|
-
ngOnDestroy() {
|
|
27186
|
-
if (this.debug) {
|
|
27187
|
-
console.debug(`${this._logPrefix}Destroying`);
|
|
27188
|
-
}
|
|
27189
|
-
this._subscriptions.unsubscribe();
|
|
27190
|
-
}
|
|
27191
|
-
}
|
|
27192
|
-
JobProgressionComponent.decorators = [
|
|
27193
|
-
{ type: Component, args: [{
|
|
27194
|
-
selector: 'app-job-progression',
|
|
27195
|
-
template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n *ngIf=\"visible\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n [matBadge]=\"jobProgressions?.length\"\n [matBadgeHidden]=\"!jobProgressions?.length\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n >{{ disabled || jobProgressions?.length ? 'schedule' : 'task_alt' }}\n </mat-icon>\n <mat-spinner\n #spinner\n *ngIf=\"jobProgressions?.length\"\n class=\"floating-spinner\"\n [color]=\"color\"\n [mode]=\"mode\"\n [value]=\"value\"\n diameter=\"30\"\n strokeWidth=\"3\"\n ></mat-spinner>\n</button>\n\n",
|
|
27196
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
27197
|
-
styles: [".floating-spinner{position:absolute;top:6px;left:5px}"]
|
|
27198
|
-
},] }
|
|
27199
|
-
];
|
|
27200
|
-
JobProgressionComponent.ctorParameters = () => [
|
|
27201
|
-
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [JobProgressionServiceToken,] }] },
|
|
27202
|
-
{ type: PopoverController },
|
|
27203
|
-
{ type: ChangeDetectorRef }
|
|
27204
|
-
];
|
|
27205
|
-
JobProgressionComponent.propDecorators = {
|
|
27206
|
-
debug: [{ type: Input }],
|
|
27207
|
-
titleI18n: [{ type: Input }],
|
|
27208
|
-
options: [{ type: Input }],
|
|
27209
|
-
jobFinished: [{ type: Output }]
|
|
27210
|
-
};
|
|
27211
|
-
|
|
27212
|
-
class JobModule {
|
|
27213
|
-
}
|
|
27214
|
-
JobModule.decorators = [
|
|
27215
|
-
{ type: NgModule, args: [{
|
|
27216
|
-
imports: [
|
|
27217
|
-
CommonModule,
|
|
27218
|
-
SharedModule,
|
|
27219
|
-
TranslateModule.forChild(),
|
|
27220
|
-
],
|
|
27221
|
-
declarations: [
|
|
27222
|
-
JobProgressionComponent,
|
|
27223
|
-
JobProgressionList
|
|
27224
|
-
],
|
|
27225
|
-
exports: [
|
|
27226
|
-
JobProgressionComponent
|
|
27227
|
-
]
|
|
27228
|
-
},] }
|
|
27229
|
-
];
|
|
27230
|
-
|
|
27231
|
-
const SocialModuleOptionsToken = new InjectionToken("SocialModuleOptions");
|
|
27232
|
-
class SocialModule {
|
|
27233
|
-
}
|
|
27234
|
-
SocialModule.decorators = [
|
|
27235
|
-
{ type: NgModule, args: [{
|
|
27236
|
-
imports: [
|
|
27237
|
-
CommonModule,
|
|
27238
|
-
CoreModule,
|
|
27239
|
-
SharedModule,
|
|
27240
|
-
UserEventModule,
|
|
27241
|
-
JobModule,
|
|
27242
|
-
MessageModule,
|
|
27243
|
-
],
|
|
27244
|
-
},] }
|
|
27245
|
-
];
|
|
27246
|
-
|
|
27247
26692
|
const Mutations = {
|
|
27248
26693
|
send: gql `mutation SendMessage($data: MessageVOInput){
|
|
27249
26694
|
done: sendMessage(message: $data)
|
|
@@ -27889,10 +27334,12 @@ class AutocompleteTestPage {
|
|
|
27889
27334
|
});
|
|
27890
27335
|
}
|
|
27891
27336
|
ngAfterViewInit() {
|
|
27892
|
-
|
|
27893
|
-
|
|
27894
|
-
|
|
27895
|
-
|
|
27337
|
+
if (this.farEntityField) {
|
|
27338
|
+
setTimeout(() => {
|
|
27339
|
+
this.farEntityField.suggestLengthThreshold = 2;
|
|
27340
|
+
this.farEntityField.reloadItems();
|
|
27341
|
+
}, 2000);
|
|
27342
|
+
}
|
|
27896
27343
|
setTimeout(() => this.loadData(), 1000);
|
|
27897
27344
|
}
|
|
27898
27345
|
// Load the form with data
|
|
@@ -27980,7 +27427,7 @@ class AutocompleteTestPage {
|
|
|
27980
27427
|
AutocompleteTestPage.decorators = [
|
|
27981
27428
|
{ type: Component, args: [{
|
|
27982
27429
|
selector: 'app-autocomplete-test',
|
|
27983
|
-
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 Entity far in the list (not in first page)\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre style=\"white-space: normal !important;\">value: {{stringify(form.controls.farEntity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"farEntity\" #farEntityField\n [config]=\"autocompleteFields.get('entity-far')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-far]'\"\n [debug]=\"true\"\n [required]=\"true\"\n [clearable]=\"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 [clearable]=\"true\"\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"
|
|
27430
|
+
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 Entity far in the list (not in first page)\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre style=\"white-space: normal !important;\">value: {{stringify(form.controls.farEntity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"farEntity\" #farEntityField\n [config]=\"autocompleteFields.get('entity-far')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-far]'\"\n [debug]=\"true\"\n [required]=\"true\"\n [clearable]=\"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 [clearable]=\"true\"\n [logPrefix]=\"'[combo-desktop-suggest]'\"\n [debug]=\"true\">\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"
|
|
27984
27431
|
},] }
|
|
27985
27432
|
];
|
|
27986
27433
|
AutocompleteTestPage.ctorParameters = () => [
|
|
@@ -28056,13 +27503,13 @@ LatLongTestPage.ctorParameters = () => [
|
|
|
28056
27503
|
{ type: FormBuilder }
|
|
28057
27504
|
];
|
|
28058
27505
|
|
|
28059
|
-
const moment$
|
|
27506
|
+
const moment$6 = momentImported;
|
|
28060
27507
|
class SwipeTestPage {
|
|
28061
27508
|
constructor(formBuilder, dateFormatPipe) {
|
|
28062
27509
|
this.formBuilder = formBuilder;
|
|
28063
27510
|
this.dateFormatPipe = dateFormatPipe;
|
|
28064
27511
|
this.$dates = new BehaviorSubject(undefined);
|
|
28065
|
-
this._today = moment$
|
|
27512
|
+
this._today = moment$6().startOf('day');
|
|
28066
27513
|
this.form = formBuilder.group({
|
|
28067
27514
|
empty: [null, Validators.required],
|
|
28068
27515
|
date: [null, Validators.compose([Validators.required, SharedValidators.validDate])],
|
|
@@ -28075,7 +27522,7 @@ class SwipeTestPage {
|
|
|
28075
27522
|
ngOnInit() {
|
|
28076
27523
|
const dates = [];
|
|
28077
27524
|
for (let d = 0; d < 7; d++) {
|
|
28078
|
-
dates[d] = moment$
|
|
27525
|
+
dates[d] = moment$6(this._today).add(d - 3, 'day');
|
|
28079
27526
|
}
|
|
28080
27527
|
this.$dates.next(dates);
|
|
28081
27528
|
this.loadData();
|
|
@@ -28116,7 +27563,7 @@ SwipeTestPage.ctorParameters = () => [
|
|
|
28116
27563
|
{ type: DateFormatPipe }
|
|
28117
27564
|
];
|
|
28118
27565
|
|
|
28119
|
-
const moment$
|
|
27566
|
+
const moment$7 = momentImported;
|
|
28120
27567
|
class DateTimeTestPage {
|
|
28121
27568
|
constructor(platform, formBuilder, cd) {
|
|
28122
27569
|
this.platform = platform;
|
|
@@ -28148,7 +27595,7 @@ class DateTimeTestPage {
|
|
|
28148
27595
|
// Load the form with data
|
|
28149
27596
|
loadData() {
|
|
28150
27597
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28151
|
-
const now = moment$
|
|
27598
|
+
const now = moment$7();
|
|
28152
27599
|
const data = {
|
|
28153
27600
|
empty: null,
|
|
28154
27601
|
emptyRequired: null,
|
|
@@ -28394,7 +27841,7 @@ NumpadTestPage.ctorParameters = () => [
|
|
|
28394
27841
|
{ type: FormBuilder }
|
|
28395
27842
|
];
|
|
28396
27843
|
|
|
28397
|
-
const moment$
|
|
27844
|
+
const moment$8 = momentImported;
|
|
28398
27845
|
class DateTestPage {
|
|
28399
27846
|
constructor(formBuilder, cd) {
|
|
28400
27847
|
this.formBuilder = formBuilder;
|
|
@@ -28427,7 +27874,7 @@ class DateTestPage {
|
|
|
28427
27874
|
// Load the form with data
|
|
28428
27875
|
loadData() {
|
|
28429
27876
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28430
|
-
const now = moment$
|
|
27877
|
+
const now = moment$8();
|
|
28431
27878
|
const nowAtMahe = now.clone().tz(this.timezone).startOf('day');
|
|
28432
27879
|
const data = {
|
|
28433
27880
|
empty: null,
|
|
@@ -29173,5 +28620,5 @@ CoreTestingModule.decorators = [
|
|
|
29173
28620
|
* Generated bundle index. Do not edit.
|
|
29174
28621
|
*/
|
|
29175
28622
|
|
|
29176
|
-
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,
|
|
28623
|
+
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, AppEntityEditorModal, AppEntityEditorModalOptions, 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, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_MENU_SHOW_WHEN, 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, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, 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, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, ResizableComponent, ResizableDirective, ResizableModule, 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, ServerErrorCodes, 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, escapeRegExp, 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, moment$5 as moment, 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, tz, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForFalse, 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, AppUpdateOfflineModeCard as ɵi, AppIconComponent as ɵj, DateTestPage as ɵk, NumpadTestPage as ɵl, MatBadgeIconTestPage as ɵm, ToastTestingModule as ɵn, ToastTestingPage as ɵo };
|
|
29177
28624
|
//# sourceMappingURL=sumaris-net.ngx-components.js.map
|