@acorex/platform 21.0.0-next.7 → 21.0.0-next.71
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/fesm2022/acorex-platform-auth.mjs +281 -23
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs +163 -0
- package/fesm2022/acorex-platform-common-common-settings.provider-Bi1RYif5.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +1381 -276
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +1538 -611
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain.mjs +557 -826
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +1372 -210
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs +121 -0
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-components.mjs +6298 -1929
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +456 -204
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs +371 -0
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity-file-list-popup.component-_yrP5SQe.mjs +100 -0
- package/fesm2022/acorex-platform-layout-entity-file-list-popup.component-_yrP5SQe.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity.mjs +22537 -9975
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +865 -218
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +2138 -487
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs → acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs} +10 -10
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs → acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs} +6 -7
- package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs → acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs} +12 -12
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs +116 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-BcpRkpJp.mjs} +6 -6
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-BcpRkpJp.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-DQtK4lxl.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-DQtK4lxl.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs → acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs} +6 -6
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets.mjs +10434 -7982
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-native.mjs +8 -7
- package/fesm2022/acorex-platform-native.mjs.map +1 -1
- package/fesm2022/acorex-platform-runtime.mjs +391 -166
- package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs +160 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs +120 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs → acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs} +21 -28
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-error-401.component-cfREo88K.mjs → acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs} +4 -4
- package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs → acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs} +4 -4
- package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +19 -0
- package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +2289 -90
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs → acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs} +6 -6
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs} +6 -6
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs → acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs} +52 -33
- package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs +94 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs +86 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +790 -612
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +978 -238
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/fesm2022/acorex-platform.mjs.map +1 -1
- package/package.json +40 -38
- package/{auth/index.d.ts → types/acorex-platform-auth.d.ts} +241 -4
- package/{common/index.d.ts → types/acorex-platform-common.d.ts} +833 -89
- package/{core/index.d.ts → types/acorex-platform-core.d.ts} +779 -164
- package/{domain/index.d.ts → types/acorex-platform-domain.d.ts} +744 -412
- package/{layout/builder/index.d.ts → types/acorex-platform-layout-builder.d.ts} +277 -55
- package/types/acorex-platform-layout-components.d.ts +3257 -0
- package/{layout/designer/index.d.ts → types/acorex-platform-layout-designer.d.ts} +96 -18
- package/types/acorex-platform-layout-entity.d.ts +4492 -0
- package/{layout/views/index.d.ts → types/acorex-platform-layout-views.d.ts} +247 -62
- package/{layout/widget-core/index.d.ts → types/acorex-platform-layout-widget-core.d.ts} +437 -131
- package/{layout/widgets/index.d.ts → types/acorex-platform-layout-widgets.d.ts} +1140 -506
- package/{native/index.d.ts → types/acorex-platform-native.d.ts} +0 -7
- package/types/acorex-platform-runtime.d.ts +571 -0
- package/{themes/default/index.d.ts → types/acorex-platform-themes-default.d.ts} +254 -7
- package/{themes/shared/index.d.ts → types/acorex-platform-themes-shared.d.ts} +30 -2
- package/{workflow/index.d.ts → types/acorex-platform-workflow.d.ts} +620 -617
- package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs +0 -71
- package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs +0 -135
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs +0 -157
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DfJEx_bs.mjs +0 -1542
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DfJEx_bs.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +0 -101
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-401.component-cfREo88K.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs +0 -19
- package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-DTnfRy5f.mjs +0 -65
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-DTnfRy5f.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs +0 -64
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs.map +0 -1
- package/layout/components/index.d.ts +0 -1669
- package/layout/entity/index.d.ts +0 -2287
- package/runtime/index.d.ts +0 -307
- /package/{index.d.ts → types/acorex-platform.d.ts} +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, Injectable,
|
|
2
|
+
import { InjectionToken, inject, Injectable, Directive, computed, Injector, ChangeDetectionStrategy, Component, input, ElementRef, ViewContainerRef, signal, effect, runInInjectionContext, Optional, Inject, NgModule, EventEmitter, HostListener, Output, provideAppInitializer, Pipe } from '@angular/core';
|
|
3
|
+
import { AXTranslationService, resolveMultiLanguageString } from '@acorex/core/translation';
|
|
4
|
+
import { AXDataSource } from '@acorex/cdk/common';
|
|
5
|
+
import { get, isPlainObject, set, isNil, isEmpty, isArray, merge, isObjectLike, transform, isEqual, differenceWith, union, cloneDeep, isObject, has, sortBy, isUndefined, endsWith, startsWith, includes, lte, gte, lt, gt, orderBy } from 'lodash-es';
|
|
3
6
|
import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
|
|
4
|
-
import
|
|
7
|
+
import * as i1 from '@acorex/components/skeleton';
|
|
8
|
+
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
5
9
|
import { Subject, interval, fromEvent } from 'rxjs';
|
|
6
10
|
import { AXCalendarService } from '@acorex/core/date-time';
|
|
7
11
|
import { startWith, map, debounceTime } from 'rxjs/operators';
|
|
@@ -17,10 +21,10 @@ class AXPActivityLogService {
|
|
|
17
21
|
async getHistoryByIds(refId, refType, ids) {
|
|
18
22
|
return (await Promise.all(this.providers?.map((p) => p.getHistoryByIds(refId, refType, ids)) ?? [])).flat();
|
|
19
23
|
}
|
|
20
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
21
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
24
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
25
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, providedIn: 'root' }); }
|
|
22
26
|
}
|
|
23
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
27
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityLogService, decorators: [{
|
|
24
28
|
type: Injectable,
|
|
25
29
|
args: [{ providedIn: 'root' }]
|
|
26
30
|
}] });
|
|
@@ -28,6 +32,184 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
28
32
|
class AXPActivityLogProvider {
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
//#region ---- Catalog scope definition ----
|
|
36
|
+
//#endregion
|
|
37
|
+
|
|
38
|
+
//#region ---- Provider contract ----
|
|
39
|
+
const AXP_CATALOG_SCOPE_DEFINITION_PROVIDER = new InjectionToken('AXP_CATALOG_SCOPE_DEFINITION_PROVIDER');
|
|
40
|
+
//#endregion
|
|
41
|
+
|
|
42
|
+
//#region ---- Imports ----
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region ---- Aggregator service ----
|
|
45
|
+
/**
|
|
46
|
+
* Collects {@link AXPCatalogScopeDefinition} entries from all registered providers.
|
|
47
|
+
*/
|
|
48
|
+
class AXPCatalogScopeDefinitionProviderService {
|
|
49
|
+
constructor() {
|
|
50
|
+
//#region ---- Services & Dependencies ----
|
|
51
|
+
this.providers = inject(AXP_CATALOG_SCOPE_DEFINITION_PROVIDER, { optional: true });
|
|
52
|
+
this.translation = inject(AXTranslationService);
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region ---- Public API ----
|
|
56
|
+
async items() {
|
|
57
|
+
const merged = [];
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
if (!Array.isArray(this.providers)) {
|
|
60
|
+
return merged;
|
|
61
|
+
}
|
|
62
|
+
for (const raw of this.providers) {
|
|
63
|
+
const provider = await Promise.resolve(raw);
|
|
64
|
+
if (!provider || typeof provider.items !== 'function') {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
for (const item of await provider.items()) {
|
|
68
|
+
const name = item.name?.trim();
|
|
69
|
+
if (!name) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (seen.has(name)) {
|
|
73
|
+
throw new Error(`Duplicate catalog scope definition: "${name}"`);
|
|
74
|
+
}
|
|
75
|
+
seen.add(name);
|
|
76
|
+
merged.push(item);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return merged.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
80
|
+
}
|
|
81
|
+
async get(name) {
|
|
82
|
+
const key = name?.trim();
|
|
83
|
+
if (!key) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return (await this.items()).find((d) => d.name === key);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Scopes applicable to the given entity ref (`Module.Entity`).
|
|
90
|
+
*/
|
|
91
|
+
async byTarget(entityRef) {
|
|
92
|
+
const target = entityRef?.trim();
|
|
93
|
+
if (!target) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
return (await this.items()).filter((d) => d.targets?.some((t) => t === target));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Resolves display title for a scope key (active locale).
|
|
100
|
+
*/
|
|
101
|
+
resolveTitle(definition) {
|
|
102
|
+
const locale = this.translation.getActiveLang() ?? 'en-US';
|
|
103
|
+
if (typeof definition.title === 'string') {
|
|
104
|
+
const title = definition.title.trim();
|
|
105
|
+
if (title.startsWith('@')) {
|
|
106
|
+
return this.translation.translateSync(title) || title;
|
|
107
|
+
}
|
|
108
|
+
return title;
|
|
109
|
+
}
|
|
110
|
+
return resolveMultiLanguageString(definition.title, locale) || definition.name;
|
|
111
|
+
}
|
|
112
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCatalogScopeDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
113
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCatalogScopeDefinitionProviderService, providedIn: 'root' }); }
|
|
114
|
+
}
|
|
115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCatalogScopeDefinitionProviderService, decorators: [{
|
|
116
|
+
type: Injectable,
|
|
117
|
+
args: [{ providedIn: 'root' }]
|
|
118
|
+
}] });
|
|
119
|
+
|
|
120
|
+
//#region ---- Imports ----
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region ---- Constants ----
|
|
123
|
+
/** Data source name for select widgets listing registered catalog scopes. */
|
|
124
|
+
const PLATFORM_CATALOG_SCOPES_DATASOURCE_NAME = 'platform-catalog-scopes';
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region ---- Data source definition ----
|
|
127
|
+
/**
|
|
128
|
+
* Registered catalog scopes for select / selection-list widgets via {@link PLATFORM_CATALOG_SCOPES_DATASOURCE_NAME}.
|
|
129
|
+
*/
|
|
130
|
+
class AXPCatalogScopeDefinitionsDataSourceDefinition {
|
|
131
|
+
constructor() {
|
|
132
|
+
//#region ---- Services & Dependencies ----
|
|
133
|
+
this.catalogScopeRegistry = inject(AXPCatalogScopeDefinitionProviderService);
|
|
134
|
+
//#endregion
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region ---- Public API ----
|
|
138
|
+
async items() {
|
|
139
|
+
return [
|
|
140
|
+
{
|
|
141
|
+
name: PLATFORM_CATALOG_SCOPES_DATASOURCE_NAME,
|
|
142
|
+
title: 'Catalog scopes',
|
|
143
|
+
source: () => new AXDataSource({
|
|
144
|
+
key: 'name',
|
|
145
|
+
pageSize: 500,
|
|
146
|
+
load: async (e) => {
|
|
147
|
+
const all = await this.catalogScopeRegistry.items();
|
|
148
|
+
const localeFilter = this.readTargetFilter(e?.filter);
|
|
149
|
+
const items = all
|
|
150
|
+
.filter((scope) => !localeFilter || scope.targets?.includes(localeFilter))
|
|
151
|
+
.map((scope) => ({
|
|
152
|
+
name: scope.name,
|
|
153
|
+
title: this.catalogScopeRegistry.resolveTitle(scope),
|
|
154
|
+
description: scope.description,
|
|
155
|
+
targets: scope.targets,
|
|
156
|
+
icon: scope.icon,
|
|
157
|
+
cssClass: scope.cssClass,
|
|
158
|
+
}));
|
|
159
|
+
return { items, total: items.length };
|
|
160
|
+
},
|
|
161
|
+
byKey: async (key) => {
|
|
162
|
+
const name = String(key ?? '').trim();
|
|
163
|
+
if (!name) {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
const scope = await this.catalogScopeRegistry.get(name);
|
|
167
|
+
if (!scope) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
name: scope.name,
|
|
172
|
+
title: this.catalogScopeRegistry.resolveTitle(scope),
|
|
173
|
+
description: scope.description,
|
|
174
|
+
targets: scope.targets,
|
|
175
|
+
icon: scope.icon,
|
|
176
|
+
cssClass: scope.cssClass,
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
}),
|
|
180
|
+
columns: [
|
|
181
|
+
{ name: 'name', title: 'Name', datatype: 'string', type: 'text-editor' },
|
|
182
|
+
{ name: 'title', title: 'Title', datatype: 'string', type: 'text-editor' },
|
|
183
|
+
],
|
|
184
|
+
filters: [
|
|
185
|
+
{
|
|
186
|
+
field: 'targets',
|
|
187
|
+
title: 'Target entity',
|
|
188
|
+
operator: { type: 'contains' },
|
|
189
|
+
widget: { type: 'text-editor' },
|
|
190
|
+
filterType: { advance: false, inline: false },
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
textField: { name: 'title', title: 'Title' },
|
|
194
|
+
valueField: { name: 'name', title: 'Name' },
|
|
195
|
+
},
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region ---- Helpers ----
|
|
200
|
+
readTargetFilter(filter) {
|
|
201
|
+
if (!filter || typeof filter !== 'object') {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
const f = filter;
|
|
205
|
+
if (f.field === 'targets' && typeof f.value === 'string' && f.value.trim()) {
|
|
206
|
+
return f.value.trim();
|
|
207
|
+
}
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//#endregion
|
|
212
|
+
|
|
31
213
|
//#region ---- Color Palette Provider ----
|
|
32
214
|
/**
|
|
33
215
|
* Abstract class for color palette providers
|
|
@@ -170,10 +352,10 @@ class AXPColorPaletteService {
|
|
|
170
352
|
const uniquePalettes = allPalettes.filter((palette, index, self) => index === self.findIndex((p) => p.name === palette.name));
|
|
171
353
|
this.cache = uniquePalettes;
|
|
172
354
|
}
|
|
173
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
174
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
355
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
356
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, providedIn: 'root' }); }
|
|
175
357
|
}
|
|
176
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
358
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColorPaletteService, decorators: [{
|
|
177
359
|
type: Injectable,
|
|
178
360
|
args: [{
|
|
179
361
|
providedIn: 'root',
|
|
@@ -288,13 +470,241 @@ class AXPDefaultColorPalettesProvider extends AXPColorPaletteProvider {
|
|
|
288
470
|
},
|
|
289
471
|
];
|
|
290
472
|
}
|
|
291
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
292
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
473
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
474
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider }); }
|
|
293
475
|
}
|
|
294
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
476
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultColorPalettesProvider, decorators: [{
|
|
295
477
|
type: Injectable
|
|
296
478
|
}] });
|
|
297
479
|
|
|
480
|
+
//#region ---- Column Width Provider ----
|
|
481
|
+
/**
|
|
482
|
+
* Injection token for column width providers
|
|
483
|
+
* Use this to register multiple column width providers with multi: true
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* ```typescript
|
|
487
|
+
* providers: [
|
|
488
|
+
* {
|
|
489
|
+
* provide: AXP_COLUMN_WIDTH_PROVIDER,
|
|
490
|
+
* useValue: {
|
|
491
|
+
* matchers: [
|
|
492
|
+
* { name: 'title', width: '300px', priority: 10 },
|
|
493
|
+
* { widgetType: /text-box/i, width: '200px' }
|
|
494
|
+
* ],
|
|
495
|
+
* priority: 150
|
|
496
|
+
* },
|
|
497
|
+
* multi: true
|
|
498
|
+
* }
|
|
499
|
+
* ]
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
const AXP_COLUMN_WIDTH_PROVIDER = new InjectionToken('AXP_COLUMN_WIDTH_PROVIDER');
|
|
503
|
+
//#endregion
|
|
504
|
+
|
|
505
|
+
//#region ---- Column Width Service ----
|
|
506
|
+
/**
|
|
507
|
+
* Service for resolving column widths based on registered providers
|
|
508
|
+
* Supports matching by column name (priority) and widget type (fallback)
|
|
509
|
+
* Uses multi-provider pattern for extensibility
|
|
510
|
+
*/
|
|
511
|
+
class AXPColumnWidthService {
|
|
512
|
+
constructor() {
|
|
513
|
+
//#region ---- Services & Dependencies ----
|
|
514
|
+
this.providers = inject(AXP_COLUMN_WIDTH_PROVIDER, {
|
|
515
|
+
optional: true,
|
|
516
|
+
}) ?? [];
|
|
517
|
+
}
|
|
518
|
+
//#region ---- Public Methods ----
|
|
519
|
+
/**
|
|
520
|
+
* Resolve width for a column based on registered providers
|
|
521
|
+
* Only returns a width if column doesn't already have one set
|
|
522
|
+
*
|
|
523
|
+
* @param column Column to resolve width for
|
|
524
|
+
* @returns Resolved width string (normalized) or undefined if no match or column already has width
|
|
525
|
+
*/
|
|
526
|
+
resolveWidth(column) {
|
|
527
|
+
// If column already has a width set, don't override
|
|
528
|
+
const existingWidth = column.width || column.options?.width;
|
|
529
|
+
if (existingWidth) {
|
|
530
|
+
return undefined;
|
|
531
|
+
}
|
|
532
|
+
// Get widget type from column (support both widget.type and showAs.type)
|
|
533
|
+
const widgetType = column.widget?.type || column.showAs?.type;
|
|
534
|
+
// Collect all matchers from all providers
|
|
535
|
+
const allMatchers = this.collectMatchers();
|
|
536
|
+
// Try name-based matches first (higher priority)
|
|
537
|
+
const nameMatch = this.findNameMatch(column.name, allMatchers);
|
|
538
|
+
if (nameMatch) {
|
|
539
|
+
return this.normalizeWidth(nameMatch.width);
|
|
540
|
+
}
|
|
541
|
+
// Fallback to widget-type matches (case-insensitive)
|
|
542
|
+
if (widgetType) {
|
|
543
|
+
const widgetMatch = this.findWidgetTypeMatch(widgetType, allMatchers);
|
|
544
|
+
if (widgetMatch) {
|
|
545
|
+
return this.normalizeWidth(widgetMatch.width);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return undefined;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Apply resolved width to a column (mutates the column)
|
|
552
|
+
* Only applies if column doesn't already have a width
|
|
553
|
+
*
|
|
554
|
+
* @param column Column to apply width to
|
|
555
|
+
* @returns true if width was applied, false if column already had width or no match found
|
|
556
|
+
*/
|
|
557
|
+
applyWidth(column) {
|
|
558
|
+
const width = this.resolveWidth(column);
|
|
559
|
+
if (!width) {
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
// Apply to the appropriate property
|
|
563
|
+
if (column.options) {
|
|
564
|
+
column.options.width = width;
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
column.width = width;
|
|
568
|
+
}
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region ---- Private Methods ----
|
|
573
|
+
/**
|
|
574
|
+
* Collect all matchers from all providers, sorted by provider priority and matcher priority
|
|
575
|
+
*/
|
|
576
|
+
collectMatchers() {
|
|
577
|
+
const allMatchers = [];
|
|
578
|
+
for (const provider of this.providers) {
|
|
579
|
+
const providerPriority = provider.priority ?? 100;
|
|
580
|
+
for (const matcher of provider.matchers) {
|
|
581
|
+
allMatchers.push({
|
|
582
|
+
matcher,
|
|
583
|
+
providerPriority,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// Sort by provider priority (descending), then by matcher priority (descending)
|
|
588
|
+
allMatchers.sort((a, b) => {
|
|
589
|
+
if (a.providerPriority !== b.providerPriority) {
|
|
590
|
+
return b.providerPriority - a.providerPriority; // Higher priority first
|
|
591
|
+
}
|
|
592
|
+
const priorityA = a.matcher.priority ?? 0;
|
|
593
|
+
const priorityB = b.matcher.priority ?? 0;
|
|
594
|
+
return priorityB - priorityA; // Higher priority first
|
|
595
|
+
});
|
|
596
|
+
return allMatchers;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Find first matching matcher by column name
|
|
600
|
+
* Name matches take precedence over widget type matches
|
|
601
|
+
*/
|
|
602
|
+
findNameMatch(columnName, allMatchers) {
|
|
603
|
+
for (const { matcher } of allMatchers) {
|
|
604
|
+
if (!matcher.name) {
|
|
605
|
+
continue; // Skip if no name matcher
|
|
606
|
+
}
|
|
607
|
+
if (typeof matcher.name === 'string') {
|
|
608
|
+
// Exact string match (case-sensitive for names)
|
|
609
|
+
if (matcher.name === columnName) {
|
|
610
|
+
return matcher;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
else if (matcher.name instanceof RegExp) {
|
|
614
|
+
// RegExp match
|
|
615
|
+
if (matcher.name.test(columnName)) {
|
|
616
|
+
return matcher;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return undefined;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Find first matching matcher by widget type (case-insensitive)
|
|
624
|
+
*/
|
|
625
|
+
findWidgetTypeMatch(widgetType, allMatchers) {
|
|
626
|
+
const widgetTypeLower = widgetType.toLowerCase();
|
|
627
|
+
for (const { matcher } of allMatchers) {
|
|
628
|
+
if (!matcher.widgetType) {
|
|
629
|
+
continue; // Skip if no widget type matcher
|
|
630
|
+
}
|
|
631
|
+
if (typeof matcher.widgetType === 'string') {
|
|
632
|
+
// Case-insensitive string match
|
|
633
|
+
if (matcher.widgetType.toLowerCase() === widgetTypeLower) {
|
|
634
|
+
return matcher;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
else if (matcher.widgetType instanceof RegExp) {
|
|
638
|
+
// RegExp match (should already be case-insensitive if needed, but we'll test case-insensitively)
|
|
639
|
+
// Create a new regex with case-insensitive flag if not already present
|
|
640
|
+
let regex = matcher.widgetType;
|
|
641
|
+
if (!regex.flags.includes('i')) {
|
|
642
|
+
regex = new RegExp(regex.source, regex.flags + 'i');
|
|
643
|
+
}
|
|
644
|
+
if (regex.test(widgetType)) {
|
|
645
|
+
return matcher;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return undefined;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Normalize width value to string format
|
|
653
|
+
* Numbers are converted to pixels (e.g., 150 -> '150px')
|
|
654
|
+
* Strings are preserved as-is (supports any CSS unit)
|
|
655
|
+
*/
|
|
656
|
+
normalizeWidth(width) {
|
|
657
|
+
if (typeof width === 'number') {
|
|
658
|
+
return `${width}px`;
|
|
659
|
+
}
|
|
660
|
+
return width;
|
|
661
|
+
}
|
|
662
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColumnWidthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
663
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColumnWidthService, providedIn: 'root' }); }
|
|
664
|
+
}
|
|
665
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPColumnWidthService, decorators: [{
|
|
666
|
+
type: Injectable,
|
|
667
|
+
args: [{
|
|
668
|
+
providedIn: 'root',
|
|
669
|
+
}]
|
|
670
|
+
}] });
|
|
671
|
+
|
|
672
|
+
//#region ---- Column Width Types ----
|
|
673
|
+
//#endregion
|
|
674
|
+
|
|
675
|
+
//#region ---- Default Column Width Provider ----
|
|
676
|
+
/**
|
|
677
|
+
* Default column width configuration
|
|
678
|
+
* Migrated from DEFAULT_COLUMN_WIDTHS in column-width.middleware.ts
|
|
679
|
+
* Provides sensible defaults for common column names
|
|
680
|
+
*/
|
|
681
|
+
const defaultColumnWidthProvider = {
|
|
682
|
+
priority: 100,
|
|
683
|
+
matchers: [
|
|
684
|
+
// Priority: name-based matches (higher priority = more specific)
|
|
685
|
+
{ name: 'code', width: '150px', priority: 10 },
|
|
686
|
+
{ name: 'name', width: '250px', priority: 10 },
|
|
687
|
+
{ name: 'title', width: '250px', priority: 10 },
|
|
688
|
+
{ name: 'description', width: '350px', priority: 10 },
|
|
689
|
+
{ name: 'note', width: '350px', priority: 10 },
|
|
690
|
+
{ name: 'notes', width: '350px', priority: 10 },
|
|
691
|
+
{ name: 'content', width: '500px', priority: 10 },
|
|
692
|
+
{ name: 'level', width: '100px', priority: 10 },
|
|
693
|
+
{ name: 'order', width: '100px', priority: 10 },
|
|
694
|
+
{ name: 'phones', width: '300px', priority: 10 },
|
|
695
|
+
{ name: 'emails', width: '300px', priority: 10 },
|
|
696
|
+
],
|
|
697
|
+
};
|
|
698
|
+
//#endregion
|
|
699
|
+
|
|
700
|
+
class AXPComponentSlot {
|
|
701
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
702
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPComponentSlot, isStandalone: true, ngImport: i0 }); }
|
|
703
|
+
}
|
|
704
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlot, decorators: [{
|
|
705
|
+
type: Directive
|
|
706
|
+
}] });
|
|
707
|
+
|
|
298
708
|
function extractNestedFieldsWildcard(obj, basePath, fields) {
|
|
299
709
|
const result = {};
|
|
300
710
|
if (fields.length === 1 && fields[0] === '*') {
|
|
@@ -313,7 +723,41 @@ function setSmart(obj, smartPath, value) {
|
|
|
313
723
|
const lastPart = pathParts[pathParts.length - 1];
|
|
314
724
|
const fieldMatch = lastPart.match(/^\{(.+)\}$/);
|
|
315
725
|
if (!fieldMatch) {
|
|
726
|
+
// Fix: If value is undefined and we're setting a nested property,
|
|
727
|
+
// check if the parent object exists and if setting this would result in
|
|
728
|
+
// all properties being undefined. If so, set the parent to null instead.
|
|
729
|
+
if (isNil(value) && pathParts.length > 1) {
|
|
730
|
+
const parentPath = pathParts.slice(0, -1).join('.');
|
|
731
|
+
const parentObj = get(obj, parentPath);
|
|
732
|
+
// If parent is already null/undefined, don't recreate the object structure
|
|
733
|
+
if (isNil(parentObj)) {
|
|
734
|
+
return obj;
|
|
735
|
+
}
|
|
736
|
+
// Check if parent is a plain object (not array, not null)
|
|
737
|
+
if (isPlainObject(parentObj)) {
|
|
738
|
+
const existingKeys = Object.keys(parentObj);
|
|
739
|
+
// Check if all existing properties are null/undefined using lodash
|
|
740
|
+
const allNil = isEmpty(existingKeys) || existingKeys.every((key) => isNil(parentObj[key]));
|
|
741
|
+
if (allNil) {
|
|
742
|
+
// Set parent to null instead of creating/keeping an object with all undefined properties
|
|
743
|
+
set(obj, parentPath, null);
|
|
744
|
+
return obj;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
316
748
|
set(obj, smartPath, value);
|
|
749
|
+
// After setting, check again if parent should be null using lodash
|
|
750
|
+
if (isNil(value) && pathParts.length > 1) {
|
|
751
|
+
const parentPath = pathParts.slice(0, -1).join('.');
|
|
752
|
+
const parentObj = get(obj, parentPath);
|
|
753
|
+
if (isPlainObject(parentObj)) {
|
|
754
|
+
// Use lodash to check if all properties are null/undefined
|
|
755
|
+
const allNil = Object.keys(parentObj).every((key) => isNil(parentObj[key]));
|
|
756
|
+
if (allNil) {
|
|
757
|
+
set(obj, parentPath, null);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
317
761
|
return obj;
|
|
318
762
|
}
|
|
319
763
|
const fields = fieldMatch[1].split(',').map((f) => f.trim());
|
|
@@ -523,44 +967,82 @@ function getEnumValues(enumType) {
|
|
|
523
967
|
return Object.entries(enumType).map(([key, value]) => ({ id: value, title: key }));
|
|
524
968
|
}
|
|
525
969
|
|
|
970
|
+
/**
|
|
971
|
+
* Returns whether `current` differs from the saved/clean `baseline` snapshot.
|
|
972
|
+
* Used by entity details pages, layout-builder dialogs, and {@link AXPContextStore}.
|
|
973
|
+
*/
|
|
974
|
+
function isFormContextDirty(current, baseline) {
|
|
975
|
+
return !isEqual(current, baseline);
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Clones a context object for use as a dirty-tracking baseline.
|
|
979
|
+
*/
|
|
980
|
+
function captureFormContextBaseline(context) {
|
|
981
|
+
return cloneDeep(context);
|
|
982
|
+
}
|
|
983
|
+
|
|
526
984
|
class AXPContextChangeEvent {
|
|
527
985
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
986
|
+
//#endregion
|
|
987
|
+
//#region ---- Context signal store ----
|
|
988
|
+
// Shared reactive context: root injector has a default instance; widget/layout trees
|
|
989
|
+
const AXPContextStore = signalStore(
|
|
531
990
|
// Initial State
|
|
532
991
|
withState(() => ({
|
|
533
992
|
data: {}, // Shared context data
|
|
534
993
|
state: 'initiated', // Current state
|
|
535
994
|
initialSnapshot: {}, // Snapshot of the first initialized state
|
|
536
995
|
previousSnapshot: {}, // Snapshot of the previous state
|
|
996
|
+
userDirtyPaths: [], // Paths changed by user interaction
|
|
537
997
|
lastChange: {
|
|
538
998
|
state: 'initiated',
|
|
539
999
|
}, // Last change event
|
|
540
1000
|
})),
|
|
541
1001
|
// Computed Signals
|
|
542
|
-
withComputed(({ data, state, lastChange, initialSnapshot, previousSnapshot }) => ({
|
|
1002
|
+
withComputed(({ data, state, lastChange, initialSnapshot, previousSnapshot, userDirtyPaths }) => ({
|
|
543
1003
|
isChanged: computed(() => state() === 'changed'),
|
|
544
1004
|
isReset: computed(() => state() === 'restored'),
|
|
545
1005
|
isInitiated: computed(() => state() === 'initiated'),
|
|
546
1006
|
isEmpty: computed(() => Object.keys(data()).length === 0),
|
|
547
|
-
isDirty: computed(() =>
|
|
1007
|
+
isDirty: computed(() => isFormContextDirty(data(), initialSnapshot())),
|
|
1008
|
+
isUserDirty: computed(() => userDirtyPaths().length > 0),
|
|
548
1009
|
snapshot: computed(() => cloneDeep(data())), // Current data snapshot
|
|
549
1010
|
initial: computed(() => cloneDeep(initialSnapshot())), // Initial snapshot
|
|
550
1011
|
previous: computed(() => cloneDeep(previousSnapshot())), // Previous snapshot
|
|
551
1012
|
changeEvent: computed(() => lastChange()), // Reactive last change event
|
|
552
1013
|
})),
|
|
553
1014
|
// Methods for State Management
|
|
554
|
-
withMethods((store) =>
|
|
555
|
-
|
|
556
|
-
|
|
1015
|
+
withMethods((store) => {
|
|
1016
|
+
const markUserDirtyPath = (path) => {
|
|
1017
|
+
const normalized = path?.trim();
|
|
1018
|
+
if (!normalized) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
const current = store.userDirtyPaths();
|
|
1022
|
+
if (current.includes(normalized)) {
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
patchState(store, { userDirtyPaths: [...current, normalized] });
|
|
1026
|
+
};
|
|
1027
|
+
const clearUserDirtyPaths = () => {
|
|
1028
|
+
if (store.userDirtyPaths().length === 0) {
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
1031
|
+
patchState(store, { userDirtyPaths: [] });
|
|
1032
|
+
};
|
|
1033
|
+
const resolvePatchOptions = (second) => {
|
|
1034
|
+
if (typeof second === 'boolean') {
|
|
1035
|
+
return { skipDirtyTracking: second };
|
|
1036
|
+
}
|
|
1037
|
+
return second ?? {};
|
|
1038
|
+
};
|
|
1039
|
+
const updateValue = (path, value, options) => {
|
|
557
1040
|
const currentData = cloneDeep(store.data());
|
|
558
1041
|
const oldValue = getSmart(currentData, path);
|
|
559
|
-
// Skip if the value hasn't changed
|
|
560
1042
|
if (isEqual(oldValue, value)) {
|
|
561
1043
|
return;
|
|
562
1044
|
}
|
|
563
|
-
|
|
1045
|
+
const origin = options?.origin ?? 'system';
|
|
564
1046
|
const updatedData = setSmart(currentData, path, value);
|
|
565
1047
|
const changeEvent = {
|
|
566
1048
|
oldValue,
|
|
@@ -568,107 +1050,614 @@ withMethods((store) => ({
|
|
|
568
1050
|
path,
|
|
569
1051
|
state: 'changed',
|
|
570
1052
|
data: updatedData,
|
|
1053
|
+
origin,
|
|
571
1054
|
};
|
|
572
|
-
// Patch the state
|
|
573
|
-
patchState(store, {
|
|
574
|
-
previousSnapshot: store.snapshot(), // Save the previous state
|
|
575
|
-
data: updatedData,
|
|
576
|
-
state: 'changed',
|
|
577
|
-
lastChange: changeEvent,
|
|
578
|
-
});
|
|
579
|
-
},
|
|
580
|
-
patch(context) {
|
|
581
|
-
const currentData = cloneDeep(store.data());
|
|
582
|
-
// Update the value and prepare the change event
|
|
583
|
-
const updatedData = { ...currentData, ...context };
|
|
584
|
-
const changeEvent = {
|
|
585
|
-
state: 'patch',
|
|
586
|
-
data: updatedData,
|
|
587
|
-
};
|
|
588
|
-
// Patch the state
|
|
589
1055
|
patchState(store, {
|
|
590
|
-
previousSnapshot: store.snapshot(),
|
|
1056
|
+
previousSnapshot: store.snapshot(),
|
|
591
1057
|
data: updatedData,
|
|
592
1058
|
state: 'changed',
|
|
593
1059
|
lastChange: changeEvent,
|
|
594
1060
|
});
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
reset() {
|
|
598
|
-
const initialData = store.initial();
|
|
599
|
-
const changeEvent = {
|
|
600
|
-
oldValue: cloneDeep(store.data()), // Current data becomes old value
|
|
601
|
-
newValue: cloneDeep(initialData), // Reset to the initial state
|
|
602
|
-
path: '',
|
|
603
|
-
state: 'restored',
|
|
604
|
-
data: initialData,
|
|
605
|
-
};
|
|
606
|
-
patchState(store, {
|
|
607
|
-
previousSnapshot: store.snapshot(), // Save the previous state
|
|
608
|
-
data: initialData,
|
|
609
|
-
state: 'restored',
|
|
610
|
-
lastChange: changeEvent,
|
|
611
|
-
});
|
|
612
|
-
},
|
|
613
|
-
// Initialize the state
|
|
614
|
-
set(initialData) {
|
|
615
|
-
const currentData = store.data();
|
|
616
|
-
if (isEqual(currentData, initialData)) {
|
|
617
|
-
return; // Skip if the current state matches the initial state
|
|
1061
|
+
if (origin === 'user') {
|
|
1062
|
+
markUserDirtyPath(path);
|
|
618
1063
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
path:
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
data: initialData,
|
|
630
|
-
state: 'initiated',
|
|
631
|
-
lastChange: changeEvent,
|
|
632
|
-
});
|
|
633
|
-
},
|
|
634
|
-
// Get a specific value
|
|
635
|
-
getValue(path) {
|
|
636
|
-
return getSmart(store.data(), path);
|
|
637
|
-
},
|
|
638
|
-
})));
|
|
639
|
-
|
|
640
|
-
class AXPDataGenerator {
|
|
641
|
-
static uuid() {
|
|
642
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
|
|
643
|
-
const random = (Math.random() * 16) | 0;
|
|
644
|
-
const value = char === 'x' ? random : (random & 0x3) | 0x8;
|
|
645
|
-
return value.toString(16);
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
static number(...args) {
|
|
649
|
-
let min = 0;
|
|
650
|
-
let max = 100;
|
|
651
|
-
if (args.length == 1)
|
|
652
|
-
max = args[0];
|
|
653
|
-
if (args.length == 2) {
|
|
654
|
-
min = args[0];
|
|
655
|
-
max = args[1];
|
|
1064
|
+
};
|
|
1065
|
+
const applyObjectPaths = (obj, options, prefix = '') => {
|
|
1066
|
+
for (const [key, value] of Object.entries(obj ?? {})) {
|
|
1067
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
1068
|
+
if (value !== null && isObject(value) && !Array.isArray(value)) {
|
|
1069
|
+
applyObjectPaths(value, options, path);
|
|
1070
|
+
}
|
|
1071
|
+
else {
|
|
1072
|
+
updateValue(path, value, options);
|
|
1073
|
+
}
|
|
656
1074
|
}
|
|
657
|
-
|
|
1075
|
+
};
|
|
1076
|
+
return {
|
|
1077
|
+
// Update a specific value
|
|
1078
|
+
update(path, value, options) {
|
|
1079
|
+
updateValue(path, value, options);
|
|
1080
|
+
},
|
|
1081
|
+
applyObjectPaths,
|
|
1082
|
+
patch(context, second) {
|
|
1083
|
+
const options = resolvePatchOptions(second);
|
|
1084
|
+
const currentData = cloneDeep(store.data());
|
|
1085
|
+
const updatedData = { ...currentData, ...context };
|
|
1086
|
+
const origin = options.origin ?? 'system';
|
|
1087
|
+
const changeEvent = {
|
|
1088
|
+
state: 'patch',
|
|
1089
|
+
data: updatedData,
|
|
1090
|
+
origin,
|
|
1091
|
+
};
|
|
1092
|
+
const syncedSnapshot = cloneDeep(updatedData);
|
|
1093
|
+
patchState(store, {
|
|
1094
|
+
...(options.skipDirtyTracking
|
|
1095
|
+
? { initialSnapshot: syncedSnapshot, previousSnapshot: syncedSnapshot }
|
|
1096
|
+
: { previousSnapshot: store.snapshot() }),
|
|
1097
|
+
data: updatedData,
|
|
1098
|
+
state: 'changed',
|
|
1099
|
+
lastChange: changeEvent,
|
|
1100
|
+
});
|
|
1101
|
+
if (!options.skipDirtyTracking && origin === 'user') {
|
|
1102
|
+
Object.keys(context).forEach((key) => markUserDirtyPath(key));
|
|
1103
|
+
}
|
|
1104
|
+
},
|
|
1105
|
+
// Reset to the initial state
|
|
1106
|
+
reset() {
|
|
1107
|
+
const initialData = store.initial();
|
|
1108
|
+
const changeEvent = {
|
|
1109
|
+
oldValue: cloneDeep(store.data()), // Current data becomes old value
|
|
1110
|
+
newValue: cloneDeep(initialData), // Reset to the initial state
|
|
1111
|
+
path: '',
|
|
1112
|
+
state: 'restored',
|
|
1113
|
+
data: initialData,
|
|
1114
|
+
};
|
|
1115
|
+
patchState(store, {
|
|
1116
|
+
previousSnapshot: store.snapshot(), // Save the previous state
|
|
1117
|
+
data: initialData,
|
|
1118
|
+
state: 'restored',
|
|
1119
|
+
lastChange: changeEvent,
|
|
1120
|
+
userDirtyPaths: [],
|
|
1121
|
+
});
|
|
1122
|
+
},
|
|
1123
|
+
// Initialize the state
|
|
1124
|
+
set(initialData) {
|
|
1125
|
+
const currentData = store.data();
|
|
1126
|
+
if (isEqual(currentData, initialData)) {
|
|
1127
|
+
return; // Skip if the current state matches the initial state
|
|
1128
|
+
}
|
|
1129
|
+
const changeEvent = {
|
|
1130
|
+
oldValue: null,
|
|
1131
|
+
newValue: cloneDeep(initialData),
|
|
1132
|
+
path: '',
|
|
1133
|
+
state: 'initiated',
|
|
1134
|
+
data: initialData,
|
|
1135
|
+
};
|
|
1136
|
+
patchState(store, {
|
|
1137
|
+
initialSnapshot: cloneDeep(initialData), // Save the initial state
|
|
1138
|
+
previousSnapshot: store.snapshot(), // Save the current state as the previous
|
|
1139
|
+
data: initialData,
|
|
1140
|
+
state: 'initiated',
|
|
1141
|
+
lastChange: changeEvent,
|
|
1142
|
+
userDirtyPaths: [],
|
|
1143
|
+
});
|
|
1144
|
+
},
|
|
1145
|
+
// Get a specific value
|
|
1146
|
+
getValue(path) {
|
|
1147
|
+
return getSmart(store.data(), path);
|
|
1148
|
+
},
|
|
1149
|
+
// Check if a path exists in the context
|
|
1150
|
+
hasValue(path) {
|
|
1151
|
+
return has(store.data(), path);
|
|
1152
|
+
},
|
|
1153
|
+
/** Marks the current data as the clean baseline (after init/normalization settles). */
|
|
1154
|
+
commitBaseline() {
|
|
1155
|
+
const snapshot = cloneDeep(store.data());
|
|
1156
|
+
patchState(store, {
|
|
1157
|
+
initialSnapshot: snapshot,
|
|
1158
|
+
previousSnapshot: snapshot,
|
|
1159
|
+
state: 'initiated',
|
|
1160
|
+
userDirtyPaths: [],
|
|
1161
|
+
});
|
|
1162
|
+
},
|
|
1163
|
+
clearUserDirtyPaths,
|
|
1164
|
+
};
|
|
1165
|
+
}));
|
|
1166
|
+
//#endregion
|
|
1167
|
+
|
|
1168
|
+
class AXPExpressionEvaluatorScopeProviderContext {
|
|
1169
|
+
constructor() {
|
|
1170
|
+
this.scopes = {};
|
|
658
1171
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
1172
|
+
addScope(namespace, functions) {
|
|
1173
|
+
this.scopes[namespace] = { ...this.scopes[namespace], ...functions };
|
|
1174
|
+
}
|
|
1175
|
+
getScopes() {
|
|
1176
|
+
return this.scopes;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
const AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER = new InjectionToken('AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER');
|
|
1180
|
+
class AXPExpressionEvaluatorScopeProviderService {
|
|
1181
|
+
constructor() {
|
|
1182
|
+
this.injector = inject(Injector);
|
|
1183
|
+
this.cache = null;
|
|
1184
|
+
}
|
|
1185
|
+
async load() {
|
|
1186
|
+
if (this.cache)
|
|
1187
|
+
return;
|
|
1188
|
+
const raw = this.injector.get(AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, [], { optional: true });
|
|
1189
|
+
const providers = Array.isArray(raw)
|
|
1190
|
+
? raw
|
|
1191
|
+
: typeof raw === 'function'
|
|
1192
|
+
? raw()
|
|
1193
|
+
: [];
|
|
1194
|
+
const context = new AXPExpressionEvaluatorScopeProviderContext();
|
|
1195
|
+
for (const provider of providers) {
|
|
1196
|
+
// Resolve lazy-loaded providers (provideLazyProvider useFactory returns Promise<Provider>)
|
|
1197
|
+
const resolved = await Promise.resolve(provider);
|
|
1198
|
+
if (!resolved || typeof resolved.provide !== 'function') {
|
|
1199
|
+
continue;
|
|
1200
|
+
}
|
|
1201
|
+
await resolved.provide(context);
|
|
1202
|
+
}
|
|
1203
|
+
this.cache = context.getScopes();
|
|
1204
|
+
}
|
|
1205
|
+
async getScopesAsync() {
|
|
1206
|
+
await this.load();
|
|
1207
|
+
return this.cache || {};
|
|
1208
|
+
}
|
|
1209
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1210
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, providedIn: 'root' }); }
|
|
1211
|
+
}
|
|
1212
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, decorators: [{
|
|
1213
|
+
type: Injectable,
|
|
1214
|
+
args: [{ providedIn: 'root' }]
|
|
1215
|
+
}] });
|
|
1216
|
+
|
|
1217
|
+
class AXPExpressionEvaluatorService {
|
|
1218
|
+
constructor() {
|
|
1219
|
+
// Memoization cache for compiled expressions
|
|
1220
|
+
this.expressionCache = new Map();
|
|
1221
|
+
this.providerService = inject(AXPExpressionEvaluatorScopeProviderService);
|
|
1222
|
+
}
|
|
1223
|
+
getOrCompileFunction(expression) {
|
|
1224
|
+
if (!this.expressionCache.has(expression)) {
|
|
1225
|
+
// Check if expression contains multiple statements (has semicolons or newlines)
|
|
1226
|
+
const hasMultipleStatements = expression.includes(';') || expression.includes('\n');
|
|
1227
|
+
let fn;
|
|
1228
|
+
if (hasMultipleStatements) {
|
|
1229
|
+
// For multiple statements, execute them in sequence and return the last expression
|
|
1230
|
+
fn = new Function('scope', `with (scope) { return (async function() { ${expression} })(); }`);
|
|
1231
|
+
}
|
|
1232
|
+
else {
|
|
1233
|
+
// For single expressions, use return
|
|
1234
|
+
fn = new Function('scope', `with (scope) { return (async function() { return ${expression}; })(); }`);
|
|
1235
|
+
}
|
|
1236
|
+
this.expressionCache.set(expression, fn);
|
|
1237
|
+
}
|
|
1238
|
+
return this.expressionCache.get(expression);
|
|
1239
|
+
}
|
|
1240
|
+
async getMergedScope(userScope) {
|
|
1241
|
+
const pluginScopes = await this.providerService.getScopesAsync();
|
|
1242
|
+
// Merge pluginScopes and userScope (userScope takes precedence)
|
|
1243
|
+
return { ...pluginScopes, ...userScope };
|
|
1244
|
+
}
|
|
1245
|
+
async evaluate(source, scope = {}) {
|
|
1246
|
+
try {
|
|
1247
|
+
const mergedScope = await this.getMergedScope(scope);
|
|
1248
|
+
if (typeof source === 'string' && source.includes('{{')) {
|
|
1249
|
+
return await this.evaluateStringExpression(source, mergedScope);
|
|
1250
|
+
}
|
|
1251
|
+
else if (Array.isArray(source)) {
|
|
1252
|
+
const evaluatedArray = [];
|
|
1253
|
+
for (const item of source) {
|
|
1254
|
+
evaluatedArray.push(await this.evaluate(item, mergedScope));
|
|
1255
|
+
}
|
|
1256
|
+
return evaluatedArray;
|
|
1257
|
+
}
|
|
1258
|
+
else if (typeof source === 'object' && source !== null) {
|
|
1259
|
+
const evaluatedObject = {};
|
|
1260
|
+
for (const key in source) {
|
|
1261
|
+
if (source.hasOwnProperty(key)) {
|
|
1262
|
+
evaluatedObject[key] = await this.evaluate(source[key], mergedScope);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
return evaluatedObject;
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
return source;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
catch (error) {
|
|
1272
|
+
console.error('Expression evaluator - Error evaluating expression:', source, error);
|
|
1273
|
+
return false;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
async evaluateStringExpression(templateExpression, scope) {
|
|
1277
|
+
// Check if the input is exactly a single {{ ... }} expression (handle multiline)
|
|
1278
|
+
const exactMatch = templateExpression.match(/^\s*\{\{\s*([\s\S]*?)\s*\}\}\s*$/);
|
|
1279
|
+
if (exactMatch) {
|
|
1280
|
+
const expression = exactMatch[1];
|
|
1281
|
+
const sandbox = this.getOrCompileFunction(expression);
|
|
1282
|
+
const result = await sandbox(scope);
|
|
1283
|
+
return result;
|
|
1284
|
+
}
|
|
1285
|
+
// Otherwise, interpolate all {{ ... }} expressions in the string
|
|
1286
|
+
const regex = /\{\{\s*([\s\S]*?)\s*\}\}/g;
|
|
1287
|
+
// Collect all matches and their positions
|
|
1288
|
+
const matches = [];
|
|
1289
|
+
let match;
|
|
1290
|
+
while ((match = regex.exec(templateExpression)) !== null) {
|
|
1291
|
+
matches.push({
|
|
1292
|
+
expression: match[1],
|
|
1293
|
+
start: match.index,
|
|
1294
|
+
end: regex.lastIndex,
|
|
1295
|
+
raw: match[0],
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
// Evaluate all expressions in parallel
|
|
1299
|
+
const values = await Promise.all(matches.map((m) => {
|
|
1300
|
+
const sandbox = this.getOrCompileFunction(m.expression);
|
|
1301
|
+
return sandbox(scope);
|
|
1302
|
+
}));
|
|
1303
|
+
// Reconstruct the string with evaluated values
|
|
1304
|
+
let result = '';
|
|
1305
|
+
let lastIndex = 0;
|
|
1306
|
+
matches.forEach((m, i) => {
|
|
1307
|
+
result += templateExpression.slice(lastIndex, m.start);
|
|
1308
|
+
const value = values[i];
|
|
1309
|
+
result += value !== undefined && value !== null ? value : '';
|
|
1310
|
+
lastIndex = m.end;
|
|
1311
|
+
});
|
|
1312
|
+
result += templateExpression.slice(lastIndex);
|
|
1313
|
+
return result;
|
|
1314
|
+
}
|
|
1315
|
+
isExpression(expression) {
|
|
1316
|
+
if (typeof expression === 'string') {
|
|
1317
|
+
return expression.trim().startsWith('{{') && expression.trim().endsWith('}}');
|
|
1318
|
+
}
|
|
1319
|
+
return false;
|
|
1320
|
+
}
|
|
1321
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1322
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorService, providedIn: 'root' }); }
|
|
1323
|
+
}
|
|
1324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExpressionEvaluatorService, decorators: [{
|
|
1325
|
+
type: Injectable,
|
|
1326
|
+
args: [{ providedIn: 'root' }]
|
|
1327
|
+
}] });
|
|
1328
|
+
|
|
1329
|
+
class AXPComponentSlotPlaceholderComponent {
|
|
1330
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotPlaceholderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1331
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AXPComponentSlotPlaceholderComponent, isStandalone: true, selector: "axp-component-slot-placeholder", ngImport: i0, template: `<div>
|
|
1332
|
+
<ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
|
|
1333
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i1.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1334
|
+
}
|
|
1335
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotPlaceholderComponent, decorators: [{
|
|
1336
|
+
type: Component,
|
|
1337
|
+
args: [{
|
|
1338
|
+
selector: 'axp-component-slot-placeholder',
|
|
1339
|
+
template: `<div>
|
|
1340
|
+
<ax-skeleton class="ax-w-full ax-h-10 ax-rounded-md"></ax-skeleton>
|
|
1341
|
+
</div>`,
|
|
1342
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1343
|
+
imports: [AXSkeletonModule],
|
|
1344
|
+
standalone: true,
|
|
1345
|
+
}]
|
|
1346
|
+
}] });
|
|
1347
|
+
|
|
1348
|
+
class AXPComponentSlotRegistryService {
|
|
1349
|
+
constructor() {
|
|
1350
|
+
this.registry = new Map();
|
|
1351
|
+
}
|
|
1352
|
+
register(slotName, config) {
|
|
1353
|
+
let configs = this.registry.get(slotName) || [];
|
|
1354
|
+
// Check if the component is already registered in this slot
|
|
1355
|
+
const isDuplicate = configs.some(existingConfig => existingConfig.name === config.name);
|
|
1356
|
+
if (!isDuplicate) {
|
|
1357
|
+
configs = [...configs, config]; // Add the new configuration
|
|
1358
|
+
this.registry.set(slotName, configs);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
get(slotName) {
|
|
1362
|
+
return this.registry.get(slotName) || [];
|
|
1363
|
+
}
|
|
1364
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1365
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotRegistryService, providedIn: 'root' }); }
|
|
1366
|
+
}
|
|
1367
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotRegistryService, decorators: [{
|
|
1368
|
+
type: Injectable,
|
|
1369
|
+
args: [{
|
|
1370
|
+
providedIn: 'root'
|
|
1371
|
+
}]
|
|
1372
|
+
}] });
|
|
1373
|
+
|
|
1374
|
+
class AXPComponentSlotDirective {
|
|
1375
|
+
constructor() {
|
|
1376
|
+
this.name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
1377
|
+
this.host = input(...(ngDevMode ? [undefined, { debugName: "host" }] : /* istanbul ignore next */ []));
|
|
1378
|
+
this.context = input(...(ngDevMode ? [undefined, { debugName: "context" }] : /* istanbul ignore next */ []));
|
|
1379
|
+
this.elementRef = inject(ElementRef);
|
|
1380
|
+
this.registryService = inject(AXPComponentSlotRegistryService);
|
|
1381
|
+
this.injector = inject(Injector);
|
|
1382
|
+
this.evaluator = inject(AXPExpressionEvaluatorService);
|
|
1383
|
+
this.viewContainerRef = inject(ViewContainerRef);
|
|
1384
|
+
this.contextStore = inject(AXPContextStore);
|
|
1385
|
+
this.isEmpty = computed(() => this._viewCount() === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
|
|
1386
|
+
// Create a signal to store the count of children
|
|
1387
|
+
this._viewCount = signal(0, ...(ngDevMode ? [{ debugName: "_viewCount" }] : /* istanbul ignore next */ []));
|
|
1388
|
+
// Track component references for updates
|
|
1389
|
+
this.componentRefs = [];
|
|
1390
|
+
// Track placeholder references for replacement
|
|
1391
|
+
this.placeholderRefs = new Map();
|
|
1392
|
+
// Watch for context changes and update component instances
|
|
1393
|
+
effect(() => {
|
|
1394
|
+
const currentContext = this.context();
|
|
1395
|
+
const currentHost = this.host();
|
|
1396
|
+
// Update all component references with new context and host
|
|
1397
|
+
this.componentRefs.forEach((componentRef) => {
|
|
1398
|
+
if (componentRef.instance) {
|
|
1399
|
+
Object.assign(componentRef.instance, {
|
|
1400
|
+
host: currentHost,
|
|
1401
|
+
context: currentContext,
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
async ngOnInit() {
|
|
1408
|
+
await this.loadComponents();
|
|
1409
|
+
// Update the signal after loading
|
|
1410
|
+
this._viewCount.set(this.viewContainerRef.length);
|
|
1411
|
+
}
|
|
1412
|
+
async loadComponents() {
|
|
1413
|
+
this.viewContainerRef.clear();
|
|
1414
|
+
// Clear previous component references
|
|
1415
|
+
this.componentRefs = [];
|
|
1416
|
+
this.placeholderRefs.clear();
|
|
1417
|
+
const configs = sortBy(this.registryService.get(this.name()), (c) => c.priority ?? 0);
|
|
1418
|
+
if (!configs) {
|
|
1419
|
+
console.error(`No component found for slot ${this.name()}`);
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
// Evaluate conditions and check features in parallel for performance
|
|
1423
|
+
const results = await Promise.all(configs.map(async (c) => {
|
|
1424
|
+
// Check condition if provided
|
|
1425
|
+
const conditionPassed = c.condition ? await this.evaluateCondition(c.condition) : true;
|
|
1426
|
+
// Check features if provided
|
|
1427
|
+
// const featuresPassed =
|
|
1428
|
+
// c.features && c.features.length > 0 ? this.sessionService.isFeatureEnabled(...c.features) : true;
|
|
1429
|
+
return {
|
|
1430
|
+
config: c,
|
|
1431
|
+
// visible: conditionPassed && featuresPassed,
|
|
1432
|
+
visible: conditionPassed,
|
|
1433
|
+
};
|
|
1434
|
+
}));
|
|
1435
|
+
// Filter visible components while preserving priority order
|
|
1436
|
+
const slots = results.filter((r) => r.visible).map((r) => r.config);
|
|
1437
|
+
// Create skeleton placeholders immediately in priority order
|
|
1438
|
+
slots.forEach((config, index) => {
|
|
1439
|
+
const placeholderRef = this.viewContainerRef.createComponent(AXPComponentSlotPlaceholderComponent);
|
|
1440
|
+
this.placeholderRefs.set(index, placeholderRef);
|
|
1441
|
+
});
|
|
1442
|
+
// Load all components in parallel and replace placeholders as they become ready
|
|
1443
|
+
const loadPromises = slots.map(async (config, index) => {
|
|
1444
|
+
let component;
|
|
1445
|
+
let options = {};
|
|
1446
|
+
// load component
|
|
1447
|
+
if (typeof config.loadComponent === 'function') {
|
|
1448
|
+
await runInInjectionContext(this.injector, async () => {
|
|
1449
|
+
component = await config.loadComponent?.();
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
else if (config.component) {
|
|
1453
|
+
component = config.component;
|
|
1454
|
+
}
|
|
1455
|
+
// load options
|
|
1456
|
+
if (typeof config.options === 'function') {
|
|
1457
|
+
await runInInjectionContext(this.injector, async () => {
|
|
1458
|
+
const fun = config.options;
|
|
1459
|
+
options = await fun();
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
else if (config.options) {
|
|
1463
|
+
options = await this.evaluator.evaluate(config.options, {});
|
|
1464
|
+
}
|
|
1465
|
+
// Replace placeholder with actual component as soon as it's ready
|
|
1466
|
+
if (!component) {
|
|
1467
|
+
console.warn(`Component failed to load for slot ${this.name()} at index ${index}`);
|
|
1468
|
+
// Remove placeholder if component failed to load
|
|
1469
|
+
const placeholderRef = this.placeholderRefs.get(index);
|
|
1470
|
+
if (placeholderRef) {
|
|
1471
|
+
placeholderRef.destroy();
|
|
1472
|
+
this.placeholderRefs.delete(index);
|
|
1473
|
+
}
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
// Get the placeholder reference at this index
|
|
1477
|
+
const placeholderRef = this.placeholderRefs.get(index);
|
|
1478
|
+
if (!placeholderRef) {
|
|
1479
|
+
console.warn(`Placeholder not found for index ${index}`);
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
// Get the index of the placeholder in the view container
|
|
1483
|
+
const placeholderIndex = this.viewContainerRef.indexOf(placeholderRef.hostView);
|
|
1484
|
+
// Remove the placeholder
|
|
1485
|
+
placeholderRef.destroy();
|
|
1486
|
+
this.placeholderRefs.delete(index);
|
|
1487
|
+
// Create the actual component at the same position
|
|
1488
|
+
const componentRef = this.viewContainerRef.createComponent(component, { index: placeholderIndex });
|
|
1489
|
+
// Store the component reference for future updates
|
|
1490
|
+
this.componentRefs.push(componentRef);
|
|
1491
|
+
Object.assign(componentRef.instance, {
|
|
1492
|
+
host: this.host(),
|
|
1493
|
+
context: this.context(),
|
|
1494
|
+
...options,
|
|
1495
|
+
});
|
|
1496
|
+
});
|
|
1497
|
+
// Wait for all components to finish loading (they render as they become ready)
|
|
1498
|
+
await Promise.all(loadPromises);
|
|
1499
|
+
}
|
|
1500
|
+
async evaluateCondition(condition) {
|
|
1501
|
+
if (typeof condition === 'string') {
|
|
1502
|
+
const result = await this.evaluator.evaluate(condition, {});
|
|
1503
|
+
return result;
|
|
1504
|
+
}
|
|
1505
|
+
return condition(this.contextStore.data());
|
|
1506
|
+
//return condition(this.context());
|
|
1507
|
+
}
|
|
1508
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1509
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPComponentSlotDirective, isStandalone: false, selector: "axp-component-slot", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, host: { classPropertyName: "host", publicName: "host", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["slot"], ngImport: i0 }); }
|
|
1510
|
+
}
|
|
1511
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotDirective, decorators: [{
|
|
1512
|
+
type: Directive,
|
|
1513
|
+
args: [{
|
|
1514
|
+
selector: 'axp-component-slot',
|
|
1515
|
+
standalone: false,
|
|
1516
|
+
exportAs: 'slot',
|
|
1517
|
+
}]
|
|
1518
|
+
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], host: [{ type: i0.Input, args: [{ isSignal: true, alias: "host", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
|
|
1519
|
+
|
|
1520
|
+
class AXPComponentSlotModule {
|
|
1521
|
+
static forRoot(configs) {
|
|
1522
|
+
return {
|
|
1523
|
+
ngModule: AXPComponentSlotModule,
|
|
1524
|
+
providers: [
|
|
1525
|
+
{
|
|
1526
|
+
provide: 'AXPComponentSlotModuleFactory',
|
|
1527
|
+
useFactory: (registry) => () => {
|
|
1528
|
+
if (configs) {
|
|
1529
|
+
for (const [key, value] of Object.entries(configs)) {
|
|
1530
|
+
value.forEach(v => {
|
|
1531
|
+
registry.register(key, v);
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
},
|
|
1536
|
+
deps: [AXPComponentSlotRegistryService],
|
|
1537
|
+
multi: true
|
|
1538
|
+
}
|
|
1539
|
+
]
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
static forChild(configs) {
|
|
1543
|
+
return {
|
|
1544
|
+
ngModule: AXPComponentSlotModule,
|
|
1545
|
+
providers: [
|
|
1546
|
+
{
|
|
1547
|
+
provide: 'AXPComponentSlotModuleFactory',
|
|
1548
|
+
useFactory: (registry) => () => {
|
|
1549
|
+
if (configs) {
|
|
1550
|
+
for (const [key, value] of Object.entries(configs)) {
|
|
1551
|
+
value.forEach(v => {
|
|
1552
|
+
registry.register(key, v);
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
deps: [AXPComponentSlotRegistryService],
|
|
1558
|
+
multi: true
|
|
1559
|
+
}
|
|
1560
|
+
]
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
/**
|
|
1564
|
+
* @ignore
|
|
1565
|
+
*/
|
|
1566
|
+
constructor(instances) {
|
|
1567
|
+
instances?.forEach(f => {
|
|
1568
|
+
f();
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule, deps: [{ token: 'AXPComponentSlotModuleFactory', optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1572
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule, declarations: [AXPComponentSlotDirective], exports: [AXPComponentSlotDirective] }); }
|
|
1573
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule }); }
|
|
1574
|
+
}
|
|
1575
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPComponentSlotModule, decorators: [{
|
|
1576
|
+
type: NgModule,
|
|
1577
|
+
args: [{
|
|
1578
|
+
declarations: [AXPComponentSlotDirective],
|
|
1579
|
+
exports: [AXPComponentSlotDirective]
|
|
1580
|
+
}]
|
|
1581
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
1582
|
+
type: Optional
|
|
1583
|
+
}, {
|
|
1584
|
+
type: Inject,
|
|
1585
|
+
args: ['AXPComponentSlotModuleFactory']
|
|
1586
|
+
}] }] });
|
|
1587
|
+
|
|
1588
|
+
//#region ---- AI metadata ----
|
|
1589
|
+
//#endregion
|
|
1590
|
+
|
|
1591
|
+
const AXP_CONTEXT_DEFINITION_PROVIDER = new InjectionToken('AXP_CONTEXT_DEFINITION_PROVIDER');
|
|
1592
|
+
//#endregion
|
|
1593
|
+
|
|
1594
|
+
//#region ---- Aggregator service ----
|
|
1595
|
+
/**
|
|
1596
|
+
* Collects {@link AXPContextDefinition} entries from all registered {@link AXPContextDefinitionProvider} instances.
|
|
1597
|
+
*/
|
|
1598
|
+
class AXPContextDefinitionProviderService {
|
|
1599
|
+
constructor() {
|
|
1600
|
+
//#region ---- Services & Dependencies ----
|
|
1601
|
+
this.providers = inject(AXP_CONTEXT_DEFINITION_PROVIDER, { optional: true });
|
|
1602
|
+
}
|
|
1603
|
+
//#endregion
|
|
1604
|
+
//#region ---- Public API ----
|
|
1605
|
+
async items() {
|
|
1606
|
+
const items = [];
|
|
1607
|
+
if (!Array.isArray(this.providers)) {
|
|
1608
|
+
return items;
|
|
1609
|
+
}
|
|
1610
|
+
for (const raw of this.providers) {
|
|
1611
|
+
const provider = await Promise.resolve(raw);
|
|
1612
|
+
if (provider && typeof provider.items === 'function') {
|
|
1613
|
+
items.push(...(await provider.items()));
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
return items;
|
|
1617
|
+
}
|
|
1618
|
+
async get(name) {
|
|
1619
|
+
return (await this.items()).find((d) => d.name === name);
|
|
1620
|
+
}
|
|
1621
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContextDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1622
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContextDefinitionProviderService, providedIn: 'root' }); }
|
|
1623
|
+
}
|
|
1624
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContextDefinitionProviderService, decorators: [{
|
|
1625
|
+
type: Injectable,
|
|
1626
|
+
args: [{ providedIn: 'root' }]
|
|
1627
|
+
}] });
|
|
1628
|
+
|
|
1629
|
+
class AXPDataGenerator {
|
|
1630
|
+
static uuid() {
|
|
1631
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
|
|
1632
|
+
const random = (Math.random() * 16) | 0;
|
|
1633
|
+
const value = char === 'x' ? random : (random & 0x3) | 0x8;
|
|
1634
|
+
return value.toString(16);
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
static number(...args) {
|
|
1638
|
+
let min = 0;
|
|
1639
|
+
let max = 100;
|
|
1640
|
+
if (args.length == 1)
|
|
1641
|
+
max = args[0];
|
|
1642
|
+
if (args.length == 2) {
|
|
1643
|
+
min = args[0];
|
|
1644
|
+
max = args[1];
|
|
1645
|
+
}
|
|
1646
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
1647
|
+
}
|
|
1648
|
+
static date(...args) {
|
|
1649
|
+
let start = new Date(2000, 0, 1);
|
|
1650
|
+
let end = new Date();
|
|
1651
|
+
if (args.length === 1) {
|
|
1652
|
+
start = args[0];
|
|
1653
|
+
}
|
|
1654
|
+
else if (args.length === 2) {
|
|
1655
|
+
start = args[0];
|
|
1656
|
+
end = args[1];
|
|
1657
|
+
}
|
|
1658
|
+
const startTime = start.getTime();
|
|
1659
|
+
const endTime = end.getTime();
|
|
1660
|
+
return new Date(startTime + Math.random() * (endTime - startTime));
|
|
672
1661
|
}
|
|
673
1662
|
static array(length = 5, generator) {
|
|
674
1663
|
return Array.from({ length }, generator);
|
|
@@ -829,11 +1818,14 @@ class AXPDataSourceDefinitionProviderService {
|
|
|
829
1818
|
}
|
|
830
1819
|
async items() {
|
|
831
1820
|
const items = [];
|
|
832
|
-
// Load from DI tokens
|
|
1821
|
+
// Load from DI tokens; resolve lazy providers (provideLazyProvider uses useFactory that returns Promise<T>)
|
|
833
1822
|
if (Array.isArray(this.providers)) {
|
|
834
|
-
for (const
|
|
835
|
-
|
|
836
|
-
|
|
1823
|
+
for (const raw of this.providers) {
|
|
1824
|
+
const provider = await Promise.resolve(raw);
|
|
1825
|
+
if (provider && typeof provider.items === 'function') {
|
|
1826
|
+
set(provider, '__parent__', this);
|
|
1827
|
+
items.push(...(await provider.items()));
|
|
1828
|
+
}
|
|
837
1829
|
}
|
|
838
1830
|
}
|
|
839
1831
|
return items;
|
|
@@ -841,52 +1833,32 @@ class AXPDataSourceDefinitionProviderService {
|
|
|
841
1833
|
async get(name) {
|
|
842
1834
|
return (await this.items()).find((c) => c.name == name);
|
|
843
1835
|
}
|
|
844
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
845
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1836
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1837
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, providedIn: 'root' }); }
|
|
846
1838
|
}
|
|
847
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1839
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSourceDefinitionProviderService, decorators: [{
|
|
848
1840
|
type: Injectable,
|
|
849
1841
|
args: [{ providedIn: 'root' }]
|
|
850
1842
|
}] });
|
|
851
1843
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
this.
|
|
856
|
-
this.
|
|
857
|
-
|
|
858
|
-
this.updateEffect = effect(() => {
|
|
859
|
-
const currentData = this.data();
|
|
860
|
-
const currentPath = this.path();
|
|
861
|
-
set(this.elementRef.nativeElement, currentPath, currentData);
|
|
862
|
-
}, ...(ngDevMode ? [{ debugName: "updateEffect" }] : []));
|
|
863
|
-
}
|
|
864
|
-
ngOnInit() {
|
|
865
|
-
// Initial data setup
|
|
866
|
-
set(this.elementRef.nativeElement, this.path(), this.data());
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* Get data from the element
|
|
870
|
-
*/
|
|
871
|
-
getData() {
|
|
872
|
-
return get(this.elementRef.nativeElement, this.path());
|
|
873
|
-
}
|
|
874
|
-
/**
|
|
875
|
-
* Update data at runtime
|
|
876
|
-
*/
|
|
877
|
-
setData(data) {
|
|
878
|
-
set(this.elementRef.nativeElement, this.path(), data);
|
|
1844
|
+
// src/app/directives/grid-layout.directive.ts
|
|
1845
|
+
class AXPContentCheckerDirective {
|
|
1846
|
+
constructor() {
|
|
1847
|
+
this.viewContainerRef = inject(ViewContainerRef);
|
|
1848
|
+
this.elementRef = inject((ElementRef));
|
|
1849
|
+
this.isEmpty = computed(() => this.viewContainerRef.length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
|
|
879
1850
|
}
|
|
880
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
881
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
1851
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContentCheckerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1852
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPContentCheckerDirective, isStandalone: true, selector: "[axp-content-checker]", exportAs: ["checker"], ngImport: i0 }); }
|
|
882
1853
|
}
|
|
883
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPContentCheckerDirective, decorators: [{
|
|
884
1855
|
type: Directive,
|
|
885
1856
|
args: [{
|
|
886
|
-
selector: '[axp-
|
|
887
|
-
standalone: true
|
|
1857
|
+
selector: '[axp-content-checker]',
|
|
1858
|
+
standalone: true,
|
|
1859
|
+
exportAs: 'checker'
|
|
888
1860
|
}]
|
|
889
|
-
}]
|
|
1861
|
+
}] });
|
|
890
1862
|
|
|
891
1863
|
class AXPDblClickDirective {
|
|
892
1864
|
constructor() {
|
|
@@ -909,10 +1881,10 @@ class AXPDblClickDirective {
|
|
|
909
1881
|
}
|
|
910
1882
|
this.lastTap = currentTime;
|
|
911
1883
|
}
|
|
912
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
913
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
1884
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDblClickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1885
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPDblClickDirective, isStandalone: true, selector: "[onDblClick]", outputs: { onDblClick: "onDblClick" }, host: { listeners: { "dblclick": "handleOnDblClick($event)", "touchend": "onTouchEnd($event)" } }, ngImport: i0 }); }
|
|
914
1886
|
}
|
|
915
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1887
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDblClickDirective, decorators: [{
|
|
916
1888
|
type: Directive,
|
|
917
1889
|
args: [{
|
|
918
1890
|
selector: '[onDblClick]'
|
|
@@ -927,12 +1899,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
927
1899
|
args: ['touchend', ['$event']]
|
|
928
1900
|
}] } });
|
|
929
1901
|
|
|
1902
|
+
class AXPElementDataDirective {
|
|
1903
|
+
constructor(elementRef) {
|
|
1904
|
+
this.elementRef = elementRef;
|
|
1905
|
+
this.data = input(null, { ...(ngDevMode ? { debugName: "data" } : /* istanbul ignore next */ {}), alias: 'axp-data' });
|
|
1906
|
+
this.path = input('__data__', { ...(ngDevMode ? { debugName: "path" } : /* istanbul ignore next */ {}), alias: 'axp-data-path' });
|
|
1907
|
+
// Effect to update element data when inputs change
|
|
1908
|
+
this.updateEffect = effect(() => {
|
|
1909
|
+
const currentData = this.data();
|
|
1910
|
+
const currentPath = this.path();
|
|
1911
|
+
set(this.elementRef.nativeElement, currentPath, currentData);
|
|
1912
|
+
}, ...(ngDevMode ? [{ debugName: "updateEffect" }] : /* istanbul ignore next */ []));
|
|
1913
|
+
}
|
|
1914
|
+
ngOnInit() {
|
|
1915
|
+
// Initial data setup
|
|
1916
|
+
set(this.elementRef.nativeElement, this.path(), this.data());
|
|
1917
|
+
}
|
|
1918
|
+
/**
|
|
1919
|
+
* Get data from the element
|
|
1920
|
+
*/
|
|
1921
|
+
getData() {
|
|
1922
|
+
return get(this.elementRef.nativeElement, this.path());
|
|
1923
|
+
}
|
|
1924
|
+
/**
|
|
1925
|
+
* Update data at runtime
|
|
1926
|
+
*/
|
|
1927
|
+
setData(data) {
|
|
1928
|
+
set(this.elementRef.nativeElement, this.path(), data);
|
|
1929
|
+
}
|
|
1930
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPElementDataDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1931
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPElementDataDirective, isStandalone: true, selector: "[axp-data]", inputs: { data: { classPropertyName: "data", publicName: "axp-data", isSignal: true, isRequired: false, transformFunction: null }, path: { classPropertyName: "path", publicName: "axp-data-path", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
1932
|
+
}
|
|
1933
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPElementDataDirective, decorators: [{
|
|
1934
|
+
type: Directive,
|
|
1935
|
+
args: [{
|
|
1936
|
+
selector: '[axp-data]',
|
|
1937
|
+
standalone: true
|
|
1938
|
+
}]
|
|
1939
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-data", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-data-path", required: false }] }] } });
|
|
1940
|
+
|
|
930
1941
|
// src/app/directives/grid-layout.directive.ts
|
|
931
1942
|
class AXPGridLayoutDirective {
|
|
932
1943
|
constructor(el, renderer) {
|
|
933
1944
|
this.el = el;
|
|
934
1945
|
this.renderer = renderer;
|
|
935
|
-
this.options = input.required(...(ngDevMode ?
|
|
1946
|
+
this.options = input.required({ ...(ngDevMode ? { debugName: "options" } : /* istanbul ignore next */ {}), alias: 'axp-grid-layout' });
|
|
936
1947
|
}
|
|
937
1948
|
ngOnChanges(changes) {
|
|
938
1949
|
if (changes['options']) {
|
|
@@ -976,232 +1987,16 @@ class AXPGridLayoutDirective {
|
|
|
976
1987
|
}
|
|
977
1988
|
});
|
|
978
1989
|
}
|
|
979
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
980
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
1990
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGridLayoutDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1991
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: AXPGridLayoutDirective, isStandalone: true, selector: "[axp-grid-layout]", inputs: { options: { classPropertyName: "options", publicName: "axp-grid-layout", isSignal: true, isRequired: true, transformFunction: null } }, usesOnChanges: true, ngImport: i0 }); }
|
|
981
1992
|
}
|
|
982
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1993
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGridLayoutDirective, decorators: [{
|
|
983
1994
|
type: Directive,
|
|
984
1995
|
args: [{
|
|
985
1996
|
selector: '[axp-grid-layout]',
|
|
986
1997
|
standalone: true,
|
|
987
1998
|
}]
|
|
988
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-grid-layout", required: true }] }] } });
|
|
989
|
-
|
|
990
|
-
// src/app/directives/grid-layout.directive.ts
|
|
991
|
-
class AXPContentCheckerDirective {
|
|
992
|
-
constructor() {
|
|
993
|
-
this.viewContainerRef = inject(ViewContainerRef);
|
|
994
|
-
this.elementRef = inject((ElementRef));
|
|
995
|
-
this.isEmpty = computed(() => this.viewContainerRef.length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : []));
|
|
996
|
-
}
|
|
997
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPContentCheckerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
998
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: AXPContentCheckerDirective, isStandalone: true, selector: "[axp-content-checker]", exportAs: ["checker"], ngImport: i0 }); }
|
|
999
|
-
}
|
|
1000
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPContentCheckerDirective, decorators: [{
|
|
1001
|
-
type: Directive,
|
|
1002
|
-
args: [{
|
|
1003
|
-
selector: '[axp-content-checker]',
|
|
1004
|
-
standalone: true,
|
|
1005
|
-
exportAs: 'checker'
|
|
1006
|
-
}]
|
|
1007
|
-
}] });
|
|
1008
|
-
|
|
1009
|
-
//#region ---- Imports ----
|
|
1010
|
-
//#endregion
|
|
1011
|
-
//#region ---- Directive ----
|
|
1012
|
-
/**
|
|
1013
|
-
* Fullscreen directive that provides CSS-based fullscreen functionality
|
|
1014
|
-
* Usage: <element axFullscreen #fullscreen="axFullscreen"></element>
|
|
1015
|
-
* Then: fullscreen.toggle() or fullscreen.enter() or fullscreen.exit()
|
|
1016
|
-
*/
|
|
1017
|
-
class AXFullscreenDirective {
|
|
1018
|
-
constructor(elementRef) {
|
|
1019
|
-
this.elementRef = elementRef;
|
|
1020
|
-
//#region ---- Properties ----
|
|
1021
|
-
/**
|
|
1022
|
-
* Current fullscreen state
|
|
1023
|
-
*/
|
|
1024
|
-
this.isFullscreenState = signal(false, ...(ngDevMode ? [{ debugName: "isFullscreenState" }] : []));
|
|
1025
|
-
/**
|
|
1026
|
-
* Original element styles to restore
|
|
1027
|
-
*/
|
|
1028
|
-
this.originalStyles = {};
|
|
1029
|
-
/**
|
|
1030
|
-
* Original parent element reference
|
|
1031
|
-
*/
|
|
1032
|
-
this.originalParent = null;
|
|
1033
|
-
/**
|
|
1034
|
-
* Fullscreen container element
|
|
1035
|
-
*/
|
|
1036
|
-
this.fullscreenContainer = null;
|
|
1037
|
-
/**
|
|
1038
|
-
* Fullscreen change event
|
|
1039
|
-
*/
|
|
1040
|
-
this.fullscreenChange = output();
|
|
1041
|
-
//#endregion
|
|
1042
|
-
//#region ---- Constructor ----
|
|
1043
|
-
this.destroyRef = inject(DestroyRef);
|
|
1044
|
-
this.renderer = inject(Renderer2);
|
|
1045
|
-
// Sync state changes to output
|
|
1046
|
-
effect(() => {
|
|
1047
|
-
const isFullscreen = this.isFullscreenState();
|
|
1048
|
-
untracked(() => {
|
|
1049
|
-
this.fullscreenChange.emit(isFullscreen);
|
|
1050
|
-
});
|
|
1051
|
-
});
|
|
1052
|
-
}
|
|
1053
|
-
//#endregion
|
|
1054
|
-
//#region ---- Public API ----
|
|
1055
|
-
/**
|
|
1056
|
-
* Toggle fullscreen state
|
|
1057
|
-
*/
|
|
1058
|
-
async toggle() {
|
|
1059
|
-
if (this.isFullscreenState()) {
|
|
1060
|
-
await this.exit();
|
|
1061
|
-
}
|
|
1062
|
-
else {
|
|
1063
|
-
await this.enter();
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
/**
|
|
1067
|
-
* Enter fullscreen mode using CSS
|
|
1068
|
-
*/
|
|
1069
|
-
async enter() {
|
|
1070
|
-
if (this.isFullscreenState()) {
|
|
1071
|
-
return;
|
|
1072
|
-
}
|
|
1073
|
-
const element = this.elementRef.nativeElement;
|
|
1074
|
-
try {
|
|
1075
|
-
// Store original styles and parent
|
|
1076
|
-
this.storeOriginalStyles(element);
|
|
1077
|
-
this.originalParent = element.parentElement;
|
|
1078
|
-
// Create fullscreen container
|
|
1079
|
-
this.fullscreenContainer = this.renderer.createElement('div');
|
|
1080
|
-
this.renderer.setStyle(this.fullscreenContainer, 'position', 'fixed');
|
|
1081
|
-
this.renderer.setStyle(this.fullscreenContainer, 'top', '0');
|
|
1082
|
-
this.renderer.setStyle(this.fullscreenContainer, 'left', '0');
|
|
1083
|
-
this.renderer.setStyle(this.fullscreenContainer, 'width', '100vw');
|
|
1084
|
-
this.renderer.setStyle(this.fullscreenContainer, 'height', '100vh');
|
|
1085
|
-
this.renderer.setStyle(this.fullscreenContainer, 'z-index', '9999');
|
|
1086
|
-
this.renderer.setStyle(this.fullscreenContainer, 'background-color', '#ffffff');
|
|
1087
|
-
this.renderer.setStyle(this.fullscreenContainer, 'overflow', 'auto');
|
|
1088
|
-
// Move element to container
|
|
1089
|
-
this.renderer.appendChild(this.fullscreenContainer, element);
|
|
1090
|
-
// Apply fullscreen styles to element
|
|
1091
|
-
this.renderer.setStyle(element, 'position', 'relative');
|
|
1092
|
-
this.renderer.setStyle(element, 'width', '100%');
|
|
1093
|
-
this.renderer.setStyle(element, 'height', '100%');
|
|
1094
|
-
this.renderer.setStyle(element, 'margin', '0');
|
|
1095
|
-
this.renderer.setStyle(element, 'padding', '0');
|
|
1096
|
-
// Append container to body
|
|
1097
|
-
this.renderer.appendChild(document.body, this.fullscreenContainer);
|
|
1098
|
-
// Prevent body scroll
|
|
1099
|
-
this.renderer.setStyle(document.body, 'overflow', 'hidden');
|
|
1100
|
-
this.isFullscreenState.set(true);
|
|
1101
|
-
}
|
|
1102
|
-
catch (error) {
|
|
1103
|
-
console.error('Error entering fullscreen:', error);
|
|
1104
|
-
this.restoreOriginalStyles(element);
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
/**
|
|
1108
|
-
* Exit fullscreen mode
|
|
1109
|
-
*/
|
|
1110
|
-
async exit() {
|
|
1111
|
-
if (!this.isFullscreenState()) {
|
|
1112
|
-
return;
|
|
1113
|
-
}
|
|
1114
|
-
const element = this.elementRef.nativeElement;
|
|
1115
|
-
try {
|
|
1116
|
-
// Restore body scroll
|
|
1117
|
-
this.renderer.removeStyle(document.body, 'overflow');
|
|
1118
|
-
// Move element back to original parent
|
|
1119
|
-
if (this.fullscreenContainer && this.originalParent) {
|
|
1120
|
-
this.renderer.removeChild(this.fullscreenContainer, element);
|
|
1121
|
-
this.renderer.appendChild(this.originalParent, element);
|
|
1122
|
-
// Remove container
|
|
1123
|
-
this.renderer.removeChild(document.body, this.fullscreenContainer);
|
|
1124
|
-
this.fullscreenContainer = null;
|
|
1125
|
-
}
|
|
1126
|
-
// Restore original styles
|
|
1127
|
-
this.restoreOriginalStyles(element);
|
|
1128
|
-
this.isFullscreenState.set(false);
|
|
1129
|
-
}
|
|
1130
|
-
catch (error) {
|
|
1131
|
-
console.error('Error exiting fullscreen:', error);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* Check if currently in fullscreen mode
|
|
1136
|
-
*/
|
|
1137
|
-
isFullscreen() {
|
|
1138
|
-
return this.isFullscreenState();
|
|
1139
|
-
}
|
|
1140
|
-
//#endregion
|
|
1141
|
-
//#region ---- Private Methods ----
|
|
1142
|
-
/**
|
|
1143
|
-
* Store original element styles
|
|
1144
|
-
*/
|
|
1145
|
-
storeOriginalStyles(element) {
|
|
1146
|
-
const computedStyle = window.getComputedStyle(element);
|
|
1147
|
-
this.originalStyles = {
|
|
1148
|
-
position: computedStyle.position,
|
|
1149
|
-
top: computedStyle.top,
|
|
1150
|
-
left: computedStyle.left,
|
|
1151
|
-
width: computedStyle.width,
|
|
1152
|
-
height: computedStyle.height,
|
|
1153
|
-
zIndex: computedStyle.zIndex,
|
|
1154
|
-
backgroundColor: computedStyle.backgroundColor,
|
|
1155
|
-
margin: computedStyle.margin,
|
|
1156
|
-
padding: computedStyle.padding,
|
|
1157
|
-
};
|
|
1158
|
-
}
|
|
1159
|
-
/**
|
|
1160
|
-
* Restore original element styles
|
|
1161
|
-
*/
|
|
1162
|
-
restoreOriginalStyles(element) {
|
|
1163
|
-
if (!this.originalStyles) {
|
|
1164
|
-
return;
|
|
1165
|
-
}
|
|
1166
|
-
// Restore each style property
|
|
1167
|
-
Object.entries(this.originalStyles).forEach(([key, value]) => {
|
|
1168
|
-
const styleKey = this.camelToKebabCase(key);
|
|
1169
|
-
if (value) {
|
|
1170
|
-
this.renderer.setStyle(element, styleKey, value);
|
|
1171
|
-
}
|
|
1172
|
-
else {
|
|
1173
|
-
this.renderer.removeStyle(element, styleKey);
|
|
1174
|
-
}
|
|
1175
|
-
});
|
|
1176
|
-
this.originalStyles = {};
|
|
1177
|
-
}
|
|
1178
|
-
/**
|
|
1179
|
-
* Convert camelCase to kebab-case for CSS properties
|
|
1180
|
-
*/
|
|
1181
|
-
camelToKebabCase(str) {
|
|
1182
|
-
return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
|
|
1183
|
-
}
|
|
1184
|
-
//#endregion
|
|
1185
|
-
//#region ---- Lifecycle ----
|
|
1186
|
-
ngOnDestroy() {
|
|
1187
|
-
// Exit fullscreen if still active
|
|
1188
|
-
if (this.isFullscreenState()) {
|
|
1189
|
-
this.exit().catch(() => {
|
|
1190
|
-
// Ignore errors during cleanup
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXFullscreenDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1195
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.12", type: AXFullscreenDirective, isStandalone: true, selector: "[axFullscreen]", outputs: { fullscreenChange: "fullscreenChange" }, exportAs: ["axFullscreen"], ngImport: i0 }); }
|
|
1196
|
-
}
|
|
1197
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXFullscreenDirective, decorators: [{
|
|
1198
|
-
type: Directive,
|
|
1199
|
-
args: [{
|
|
1200
|
-
selector: '[axFullscreen]',
|
|
1201
|
-
standalone: true,
|
|
1202
|
-
exportAs: 'axFullscreen',
|
|
1203
|
-
}]
|
|
1204
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { fullscreenChange: [{ type: i0.Output, args: ["fullscreenChange"] }] } });
|
|
1999
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "axp-grid-layout", required: true }] }] } });
|
|
1205
2000
|
|
|
1206
2001
|
const AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER = new InjectionToken('AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER');
|
|
1207
2002
|
|
|
@@ -1339,10 +2134,10 @@ class AXPDistributedEventListenerService {
|
|
|
1339
2134
|
this.listenersByKey.clear();
|
|
1340
2135
|
this.providersLoaded = false;
|
|
1341
2136
|
}
|
|
1342
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1343
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2137
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2138
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, providedIn: 'root' }); }
|
|
1344
2139
|
}
|
|
1345
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2140
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDistributedEventListenerService, decorators: [{
|
|
1346
2141
|
type: Injectable,
|
|
1347
2142
|
args: [{
|
|
1348
2143
|
providedIn: 'root',
|
|
@@ -1466,168 +2261,16 @@ class AXPBroadcastEventService {
|
|
|
1466
2261
|
// Cleanup multi-tab event history
|
|
1467
2262
|
this.multiTabEventHistory.clear();
|
|
1468
2263
|
}
|
|
1469
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1470
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2264
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2265
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, providedIn: 'root' }); }
|
|
1471
2266
|
}
|
|
1472
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2267
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBroadcastEventService, decorators: [{
|
|
1473
2268
|
type: Injectable,
|
|
1474
2269
|
args: [{
|
|
1475
2270
|
providedIn: 'root',
|
|
1476
2271
|
}]
|
|
1477
2272
|
}], ctorParameters: () => [] });
|
|
1478
2273
|
|
|
1479
|
-
class AXPExpressionEvaluatorScopeProviderContext {
|
|
1480
|
-
constructor() {
|
|
1481
|
-
this.scopes = {};
|
|
1482
|
-
}
|
|
1483
|
-
addScope(namespace, functions) {
|
|
1484
|
-
this.scopes[namespace] = { ...this.scopes[namespace], ...functions };
|
|
1485
|
-
}
|
|
1486
|
-
getScopes() {
|
|
1487
|
-
return this.scopes;
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
const AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER = new InjectionToken('AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER');
|
|
1491
|
-
class AXPExpressionEvaluatorScopeProviderService {
|
|
1492
|
-
constructor() {
|
|
1493
|
-
this.providers = inject(AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, { optional: true });
|
|
1494
|
-
this.cache = null;
|
|
1495
|
-
}
|
|
1496
|
-
async load() {
|
|
1497
|
-
if (this.cache)
|
|
1498
|
-
return;
|
|
1499
|
-
const context = new AXPExpressionEvaluatorScopeProviderContext();
|
|
1500
|
-
if (Array.isArray(this.providers)) {
|
|
1501
|
-
for (const provider of this.providers) {
|
|
1502
|
-
await provider.provide(context);
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
this.cache = context.getScopes();
|
|
1506
|
-
}
|
|
1507
|
-
async getScopesAsync() {
|
|
1508
|
-
await this.load();
|
|
1509
|
-
return this.cache || {};
|
|
1510
|
-
}
|
|
1511
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1512
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, providedIn: 'root' }); }
|
|
1513
|
-
}
|
|
1514
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorScopeProviderService, decorators: [{
|
|
1515
|
-
type: Injectable,
|
|
1516
|
-
args: [{ providedIn: 'root' }]
|
|
1517
|
-
}] });
|
|
1518
|
-
|
|
1519
|
-
class AXPExpressionEvaluatorService {
|
|
1520
|
-
constructor() {
|
|
1521
|
-
// Memoization cache for compiled expressions
|
|
1522
|
-
this.expressionCache = new Map();
|
|
1523
|
-
this.providerService = inject(AXPExpressionEvaluatorScopeProviderService);
|
|
1524
|
-
}
|
|
1525
|
-
getOrCompileFunction(expression) {
|
|
1526
|
-
if (!this.expressionCache.has(expression)) {
|
|
1527
|
-
// Check if expression contains multiple statements (has semicolons or newlines)
|
|
1528
|
-
const hasMultipleStatements = expression.includes(';') || expression.includes('\n');
|
|
1529
|
-
let fn;
|
|
1530
|
-
if (hasMultipleStatements) {
|
|
1531
|
-
// For multiple statements, execute them in sequence and return the last expression
|
|
1532
|
-
fn = new Function('scope', `with (scope) { return (async function() { ${expression} })(); }`);
|
|
1533
|
-
}
|
|
1534
|
-
else {
|
|
1535
|
-
// For single expressions, use return
|
|
1536
|
-
fn = new Function('scope', `with (scope) { return (async function() { return ${expression}; })(); }`);
|
|
1537
|
-
}
|
|
1538
|
-
this.expressionCache.set(expression, fn);
|
|
1539
|
-
}
|
|
1540
|
-
return this.expressionCache.get(expression);
|
|
1541
|
-
}
|
|
1542
|
-
async getMergedScope(userScope) {
|
|
1543
|
-
const pluginScopes = await this.providerService.getScopesAsync();
|
|
1544
|
-
// Merge pluginScopes and userScope (userScope takes precedence)
|
|
1545
|
-
return { ...pluginScopes, ...userScope };
|
|
1546
|
-
}
|
|
1547
|
-
async evaluate(source, scope = {}) {
|
|
1548
|
-
try {
|
|
1549
|
-
const mergedScope = await this.getMergedScope(scope);
|
|
1550
|
-
if (typeof source === 'string' && source.includes('{{')) {
|
|
1551
|
-
return await this.evaluateStringExpression(source, mergedScope);
|
|
1552
|
-
}
|
|
1553
|
-
else if (Array.isArray(source)) {
|
|
1554
|
-
const evaluatedArray = [];
|
|
1555
|
-
for (const item of source) {
|
|
1556
|
-
evaluatedArray.push(await this.evaluate(item, mergedScope));
|
|
1557
|
-
}
|
|
1558
|
-
return evaluatedArray;
|
|
1559
|
-
}
|
|
1560
|
-
else if (typeof source === 'object' && source !== null) {
|
|
1561
|
-
const evaluatedObject = {};
|
|
1562
|
-
for (const key in source) {
|
|
1563
|
-
if (source.hasOwnProperty(key)) {
|
|
1564
|
-
evaluatedObject[key] = await this.evaluate(source[key], mergedScope);
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
return evaluatedObject;
|
|
1568
|
-
}
|
|
1569
|
-
else {
|
|
1570
|
-
return source;
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
catch (error) {
|
|
1574
|
-
console.error('Expression evaluator - Error evaluating expression:', source, error);
|
|
1575
|
-
return false;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
async evaluateStringExpression(templateExpression, scope) {
|
|
1579
|
-
// Check if the input is exactly a single {{ ... }} expression (handle multiline)
|
|
1580
|
-
const exactMatch = templateExpression.match(/^\s*\{\{\s*([\s\S]*?)\s*\}\}\s*$/);
|
|
1581
|
-
if (exactMatch) {
|
|
1582
|
-
const expression = exactMatch[1];
|
|
1583
|
-
const sandbox = this.getOrCompileFunction(expression);
|
|
1584
|
-
const result = await sandbox(scope);
|
|
1585
|
-
return result;
|
|
1586
|
-
}
|
|
1587
|
-
// Otherwise, interpolate all {{ ... }} expressions in the string
|
|
1588
|
-
const regex = /\{\{\s*([\s\S]*?)\s*\}\}/g;
|
|
1589
|
-
// Collect all matches and their positions
|
|
1590
|
-
const matches = [];
|
|
1591
|
-
let match;
|
|
1592
|
-
while ((match = regex.exec(templateExpression)) !== null) {
|
|
1593
|
-
matches.push({
|
|
1594
|
-
expression: match[1],
|
|
1595
|
-
start: match.index,
|
|
1596
|
-
end: regex.lastIndex,
|
|
1597
|
-
raw: match[0],
|
|
1598
|
-
});
|
|
1599
|
-
}
|
|
1600
|
-
// Evaluate all expressions in parallel
|
|
1601
|
-
const values = await Promise.all(matches.map((m) => {
|
|
1602
|
-
const sandbox = this.getOrCompileFunction(m.expression);
|
|
1603
|
-
return sandbox(scope);
|
|
1604
|
-
}));
|
|
1605
|
-
// Reconstruct the string with evaluated values
|
|
1606
|
-
let result = '';
|
|
1607
|
-
let lastIndex = 0;
|
|
1608
|
-
matches.forEach((m, i) => {
|
|
1609
|
-
result += templateExpression.slice(lastIndex, m.start);
|
|
1610
|
-
const value = values[i];
|
|
1611
|
-
result += value !== undefined && value !== null ? value : '';
|
|
1612
|
-
lastIndex = m.end;
|
|
1613
|
-
});
|
|
1614
|
-
result += templateExpression.slice(lastIndex);
|
|
1615
|
-
return result;
|
|
1616
|
-
}
|
|
1617
|
-
isExpression(expression) {
|
|
1618
|
-
if (typeof expression === 'string') {
|
|
1619
|
-
return expression.includes('{{');
|
|
1620
|
-
}
|
|
1621
|
-
return false;
|
|
1622
|
-
}
|
|
1623
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1624
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorService, providedIn: 'root' }); }
|
|
1625
|
-
}
|
|
1626
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPExpressionEvaluatorService, decorators: [{
|
|
1627
|
-
type: Injectable,
|
|
1628
|
-
args: [{ providedIn: 'root' }]
|
|
1629
|
-
}] });
|
|
1630
|
-
|
|
1631
2274
|
class AXPHookService {
|
|
1632
2275
|
constructor() {
|
|
1633
2276
|
this.listenerProviders = inject(AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, { optional: true }) || [];
|
|
@@ -1674,10 +2317,10 @@ class AXPHookService {
|
|
|
1674
2317
|
}
|
|
1675
2318
|
return data;
|
|
1676
2319
|
}
|
|
1677
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1678
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2320
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2321
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, providedIn: 'root' }); }
|
|
1679
2322
|
}
|
|
1680
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2323
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHookService, decorators: [{
|
|
1681
2324
|
type: Injectable,
|
|
1682
2325
|
args: [{ providedIn: 'root' }]
|
|
1683
2326
|
}] });
|
|
@@ -1957,16 +2600,88 @@ class AXPModuleManifestRegistry {
|
|
|
1957
2600
|
}
|
|
1958
2601
|
return { missingModules, missingFeatures };
|
|
1959
2602
|
}
|
|
1960
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1961
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2603
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2604
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, providedIn: 'root' }); }
|
|
1962
2605
|
}
|
|
1963
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2606
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestRegistry, decorators: [{
|
|
1964
2607
|
type: Injectable,
|
|
1965
2608
|
args: [{ providedIn: 'root' }]
|
|
1966
2609
|
}] });
|
|
1967
2610
|
|
|
2611
|
+
//#region ---- Imports ----
|
|
2612
|
+
//#endregion
|
|
2613
|
+
//#region ---- Module manifests data source ----
|
|
2614
|
+
/**
|
|
2615
|
+
* Registered module manifests for select widgets via dataSource name {@link MODULE_MANIFESTS_DATASOURCE_NAME}.
|
|
2616
|
+
*/
|
|
2617
|
+
const MODULE_MANIFESTS_DATASOURCE_NAME = 'platform-module-manifests';
|
|
2618
|
+
/**
|
|
2619
|
+
* Data source definition for module names/titles from {@link AXPModuleManifestRegistry}.
|
|
2620
|
+
*/
|
|
2621
|
+
class AXPModuleManifestsDataSourceDefinition {
|
|
2622
|
+
constructor() {
|
|
2623
|
+
//#region ---- Services & Dependencies ----
|
|
2624
|
+
this.manifestRegistry = inject(AXPModuleManifestRegistry);
|
|
2625
|
+
//#endregion
|
|
2626
|
+
}
|
|
2627
|
+
//#endregion
|
|
2628
|
+
//#region ---- Public API ----
|
|
2629
|
+
async items() {
|
|
2630
|
+
return [
|
|
2631
|
+
{
|
|
2632
|
+
name: MODULE_MANIFESTS_DATASOURCE_NAME,
|
|
2633
|
+
title: 'Module manifests',
|
|
2634
|
+
source: () => new AXDataSource({
|
|
2635
|
+
key: 'id',
|
|
2636
|
+
load: async () => {
|
|
2637
|
+
await this.manifestRegistry.initialize();
|
|
2638
|
+
const list = this.manifestRegistry.getAll().map((m) => ({
|
|
2639
|
+
id: m.name,
|
|
2640
|
+
title: m.title || m.name,
|
|
2641
|
+
}));
|
|
2642
|
+
return { items: list, total: list.length };
|
|
2643
|
+
},
|
|
2644
|
+
byKey: async (key) => {
|
|
2645
|
+
await this.manifestRegistry.initialize();
|
|
2646
|
+
const m = this.manifestRegistry.getAll().find((x) => x.name === key);
|
|
2647
|
+
return m ? { id: m.name, title: m.title || m.name } : undefined;
|
|
2648
|
+
},
|
|
2649
|
+
pageSize: 1000,
|
|
2650
|
+
}),
|
|
2651
|
+
columns: [
|
|
2652
|
+
{
|
|
2653
|
+
name: 'id',
|
|
2654
|
+
title: 'ID',
|
|
2655
|
+
datatype: 'string',
|
|
2656
|
+
type: 'text-editor',
|
|
2657
|
+
},
|
|
2658
|
+
{
|
|
2659
|
+
name: 'title',
|
|
2660
|
+
title: 'Title',
|
|
2661
|
+
datatype: 'string',
|
|
2662
|
+
type: 'text-editor',
|
|
2663
|
+
},
|
|
2664
|
+
],
|
|
2665
|
+
filters: [
|
|
2666
|
+
{
|
|
2667
|
+
field: 'title',
|
|
2668
|
+
title: 'Title',
|
|
2669
|
+
operator: { type: 'equal' },
|
|
2670
|
+
widget: { type: 'text-editor' },
|
|
2671
|
+
filterType: { advance: true, inline: true },
|
|
2672
|
+
},
|
|
2673
|
+
],
|
|
2674
|
+
textField: { name: 'title', title: 'Title' },
|
|
2675
|
+
valueField: { name: 'id', title: 'ID' },
|
|
2676
|
+
},
|
|
2677
|
+
];
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
//#endregion
|
|
2681
|
+
|
|
1968
2682
|
class AXPAppStartUpService {
|
|
1969
2683
|
constructor() {
|
|
2684
|
+
this.translationService = inject(AXTranslationService);
|
|
1970
2685
|
this.tasks = [];
|
|
1971
2686
|
}
|
|
1972
2687
|
registerTask(task) {
|
|
@@ -1974,20 +2689,21 @@ class AXPAppStartUpService {
|
|
|
1974
2689
|
}
|
|
1975
2690
|
async runAllTasks() {
|
|
1976
2691
|
for (const task of this.tasks.sort((a, b) => a.priority - b.priority)) {
|
|
1977
|
-
this.updateStatus(task.statusText);
|
|
2692
|
+
await this.updateStatus(task.statusText);
|
|
1978
2693
|
await task.run();
|
|
1979
2694
|
}
|
|
1980
2695
|
}
|
|
1981
|
-
updateStatus(status) {
|
|
2696
|
+
async updateStatus(status) {
|
|
1982
2697
|
const loadingText = document.querySelector('#loadingText');
|
|
1983
2698
|
if (loadingText) {
|
|
1984
|
-
|
|
2699
|
+
const translatedStatus = this.translationService.resolve(status);
|
|
2700
|
+
loadingText.innerHTML = await this.translationService.translateAsync(translatedStatus);
|
|
1985
2701
|
}
|
|
1986
2702
|
}
|
|
1987
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1988
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2703
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2704
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, providedIn: 'root' }); }
|
|
1989
2705
|
}
|
|
1990
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppStartUpService, decorators: [{
|
|
1991
2707
|
type: Injectable,
|
|
1992
2708
|
args: [{
|
|
1993
2709
|
providedIn: 'root',
|
|
@@ -2018,24 +2734,57 @@ class AXPModuleManifestModule {
|
|
|
2018
2734
|
// Register manifest initialization task
|
|
2019
2735
|
appInitService.registerTask({
|
|
2020
2736
|
name: 'ModuleManifests',
|
|
2021
|
-
statusText: '
|
|
2737
|
+
statusText: '@general:app-startup.loading-module-manifests',
|
|
2022
2738
|
priority: 1, // Load early, before features/permissions
|
|
2023
2739
|
run: async () => {
|
|
2024
2740
|
await manifestRegistry.initialize();
|
|
2025
2741
|
},
|
|
2026
2742
|
});
|
|
2027
2743
|
}
|
|
2028
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2029
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
2030
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
2744
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule, deps: [{ token: AXPAppStartUpService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2745
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule }); }
|
|
2746
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule }); }
|
|
2031
2747
|
}
|
|
2032
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2748
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPModuleManifestModule, decorators: [{
|
|
2033
2749
|
type: NgModule,
|
|
2034
2750
|
args: [{
|
|
2035
2751
|
providers: [],
|
|
2036
2752
|
}]
|
|
2037
2753
|
}], ctorParameters: () => [{ type: AXPAppStartUpService }, { type: i0.Injector }] });
|
|
2038
2754
|
|
|
2755
|
+
//#region ---- Imports ----
|
|
2756
|
+
//#endregion
|
|
2757
|
+
//#region ---- Compare & sort ----
|
|
2758
|
+
const DEFAULT_COLLATOR_OPTIONS = { sensitivity: 'base' };
|
|
2759
|
+
/**
|
|
2760
|
+
* Locale-aware comparison of {@link AXPMultiLanguageString} values (plain string, `@scope:key`, or locale map).
|
|
2761
|
+
* Resolves each side with {@link resolveMultiLanguageString} for `locale`, then compares with `String#localeCompare`.
|
|
2762
|
+
*/
|
|
2763
|
+
function compareMultiLanguageStrings(a, b, locale, collatorOptions = DEFAULT_COLLATOR_OPTIONS) {
|
|
2764
|
+
const sa = resolveMultiLanguageString(a ?? '', locale);
|
|
2765
|
+
const sb = resolveMultiLanguageString(b ?? '', locale);
|
|
2766
|
+
return sa.localeCompare(sb, locale, collatorOptions);
|
|
2767
|
+
}
|
|
2768
|
+
/**
|
|
2769
|
+
* Stable sort copy: orders items by resolved string for `getValue(item)` using the active `locale`.
|
|
2770
|
+
*/
|
|
2771
|
+
function sortByMultiLanguageString(items, getValue, locale, collatorOptions) {
|
|
2772
|
+
return [...items].sort((x, y) => compareMultiLanguageStrings(getValue(x), getValue(y), locale, collatorOptions));
|
|
2773
|
+
}
|
|
2774
|
+
/**
|
|
2775
|
+
* True when the resolved value contains `query` (case-insensitive) for `locale`.
|
|
2776
|
+
* Useful for search/filter flows over {@link AXPMultiLanguageString}.
|
|
2777
|
+
*/
|
|
2778
|
+
function searchInMultiLanguageString(value, query, locale) {
|
|
2779
|
+
const q = query.trim().toLocaleLowerCase(locale);
|
|
2780
|
+
if (!q) {
|
|
2781
|
+
return true;
|
|
2782
|
+
}
|
|
2783
|
+
const text = resolveMultiLanguageString(value ?? '', locale).toLocaleLowerCase(locale);
|
|
2784
|
+
return text.includes(q);
|
|
2785
|
+
}
|
|
2786
|
+
//#endregion
|
|
2787
|
+
|
|
2039
2788
|
//#region ---- Tag Types ----
|
|
2040
2789
|
//#endregion
|
|
2041
2790
|
|
|
@@ -2187,10 +2936,10 @@ class AXPTagService {
|
|
|
2187
2936
|
const uniqueTags = allTags.filter((tag, index, self) => index === self.findIndex((t) => t.title.toLowerCase() === tag.title.toLowerCase()));
|
|
2188
2937
|
this.cache = uniqueTags;
|
|
2189
2938
|
}
|
|
2190
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2191
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2939
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2940
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, providedIn: 'root' }); }
|
|
2192
2941
|
}
|
|
2193
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2942
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTagService, decorators: [{
|
|
2194
2943
|
type: Injectable,
|
|
2195
2944
|
args: [{
|
|
2196
2945
|
providedIn: 'root',
|
|
@@ -3121,14 +3870,25 @@ function getNestedKeys(obj, prefix = '') {
|
|
|
3121
3870
|
}
|
|
3122
3871
|
return keys;
|
|
3123
3872
|
}
|
|
3873
|
+
/** Normalizes definition categories to an array for iteration and serialization. */
|
|
3874
|
+
function normalizeDefinitionCategories(categories) {
|
|
3875
|
+
if (categories == null) {
|
|
3876
|
+
return [];
|
|
3877
|
+
}
|
|
3878
|
+
return Array.isArray(categories) ? categories : [categories];
|
|
3879
|
+
}
|
|
3880
|
+
|
|
3881
|
+
//#region ---- Imports ----
|
|
3882
|
+
//#endregion
|
|
3124
3883
|
|
|
3125
3884
|
function applySystemActionDefault(action, type) {
|
|
3126
3885
|
const systemAction = getSystemActions(type);
|
|
3127
3886
|
return {
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3887
|
+
...action,
|
|
3888
|
+
name: action.name ?? systemAction.key,
|
|
3889
|
+
title: action.title ?? systemAction.title,
|
|
3890
|
+
icon: action.icon ?? systemAction.icon,
|
|
3891
|
+
color: action.color ?? systemAction.color,
|
|
3132
3892
|
};
|
|
3133
3893
|
}
|
|
3134
3894
|
|
|
@@ -3153,8 +3913,6 @@ class AXPIconLogoConfig {
|
|
|
3153
3913
|
|
|
3154
3914
|
var AXPPlatformScope;
|
|
3155
3915
|
(function (AXPPlatformScope) {
|
|
3156
|
-
AXPPlatformScope["Environment"] = "C";
|
|
3157
|
-
AXPPlatformScope["Global"] = "G";
|
|
3158
3916
|
AXPPlatformScope["Platform"] = "P";
|
|
3159
3917
|
AXPPlatformScope["Tenant"] = "T";
|
|
3160
3918
|
AXPPlatformScope["User"] = "U";
|
|
@@ -3162,8 +3920,6 @@ var AXPPlatformScope;
|
|
|
3162
3920
|
;
|
|
3163
3921
|
function resolvePlatformScopeKey(name) {
|
|
3164
3922
|
const scopeMap = {
|
|
3165
|
-
environment: AXPPlatformScope.Environment,
|
|
3166
|
-
global: AXPPlatformScope.Global,
|
|
3167
3923
|
platform: AXPPlatformScope.Platform,
|
|
3168
3924
|
tenant: AXPPlatformScope.Tenant,
|
|
3169
3925
|
user: AXPPlatformScope.User,
|
|
@@ -3172,8 +3928,6 @@ function resolvePlatformScopeKey(name) {
|
|
|
3172
3928
|
}
|
|
3173
3929
|
function resolvePlatformScopeName(scope) {
|
|
3174
3930
|
const scopeMap = {
|
|
3175
|
-
C: 'environment',
|
|
3176
|
-
G: 'global',
|
|
3177
3931
|
P: 'platform',
|
|
3178
3932
|
T: 'tenant',
|
|
3179
3933
|
U: 'user',
|
|
@@ -3193,7 +3947,7 @@ var AXPExportTemplateToken;
|
|
|
3193
3947
|
class AXPCountdownPipe {
|
|
3194
3948
|
constructor() {
|
|
3195
3949
|
this.calendarService = inject(AXCalendarService);
|
|
3196
|
-
this.countdownSignal = signal(this.setupTimer(), ...(ngDevMode ? [{ debugName: "countdownSignal" }] : []));
|
|
3950
|
+
this.countdownSignal = signal(this.setupTimer(), ...(ngDevMode ? [{ debugName: "countdownSignal" }] : /* istanbul ignore next */ []));
|
|
3197
3951
|
this.targetDate = 0;
|
|
3198
3952
|
this.prevValue = 0;
|
|
3199
3953
|
}
|
|
@@ -3222,10 +3976,10 @@ class AXPCountdownPipe {
|
|
|
3222
3976
|
updateTargetDate(value) {
|
|
3223
3977
|
this.targetDate = new Date(value).getTime();
|
|
3224
3978
|
}
|
|
3225
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3226
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "
|
|
3979
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
3980
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, isStandalone: true, name: "countdown", pure: false }); }
|
|
3227
3981
|
}
|
|
3228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3982
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCountdownPipe, decorators: [{
|
|
3229
3983
|
type: Pipe,
|
|
3230
3984
|
args: [{
|
|
3231
3985
|
name: 'countdown',
|
|
@@ -3235,6 +3989,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
3235
3989
|
}] });
|
|
3236
3990
|
|
|
3237
3991
|
const loggingEnabled = false; // Set to true to enable logging, false to disable
|
|
3992
|
+
//#region ---- Multilingual string helpers ----
|
|
3993
|
+
/**
|
|
3994
|
+
* Per-locale string map as produced by multilingual editors (e.g. `{ "en-US": "...", "fa-IR": "..." }`).
|
|
3995
|
+
*/
|
|
3996
|
+
function isLocaleStringMap(value) {
|
|
3997
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value) || value instanceof Date) {
|
|
3998
|
+
return false;
|
|
3999
|
+
}
|
|
4000
|
+
const values = Object.values(value);
|
|
4001
|
+
return values.length > 0 && values.every((v) => typeof v === 'string');
|
|
4002
|
+
}
|
|
4003
|
+
/**
|
|
4004
|
+
* Lowercased text for client-side filtering: plain string or all locale values joined.
|
|
4005
|
+
*/
|
|
4006
|
+
function toFilterSearchText(value) {
|
|
4007
|
+
if (typeof value === 'string') {
|
|
4008
|
+
return value.toLowerCase();
|
|
4009
|
+
}
|
|
4010
|
+
if (isLocaleStringMap(value)) {
|
|
4011
|
+
return Object.values(value).join(' ').toLowerCase();
|
|
4012
|
+
}
|
|
4013
|
+
return undefined;
|
|
4014
|
+
}
|
|
4015
|
+
function filterValuesAreEqual(itemRaw, condRaw) {
|
|
4016
|
+
if (typeof condRaw === 'string' && isLocaleStringMap(itemRaw)) {
|
|
4017
|
+
return Object.values(itemRaw).some((v) => v.toLowerCase() === condRaw.toLowerCase());
|
|
4018
|
+
}
|
|
4019
|
+
if (typeof itemRaw === 'string' && isLocaleStringMap(condRaw)) {
|
|
4020
|
+
return Object.values(condRaw).some((v) => v.toLowerCase() === itemRaw.toLowerCase());
|
|
4021
|
+
}
|
|
4022
|
+
const itemScalar = typeof itemRaw === 'string' ? itemRaw.toLowerCase() : itemRaw;
|
|
4023
|
+
const condScalar = typeof condRaw === 'string' ? condRaw.toLowerCase() : condRaw;
|
|
4024
|
+
return isEqual(itemScalar, condScalar);
|
|
4025
|
+
}
|
|
4026
|
+
//#endregion
|
|
3238
4027
|
function applyCondition(item, condition) {
|
|
3239
4028
|
const rawValue = condition.field ? get(item, condition.field) : null;
|
|
3240
4029
|
const itemValue = typeof rawValue === 'string' ? rawValue.toLowerCase() : rawValue;
|
|
@@ -3255,7 +4044,12 @@ function applyCondition(item, condition) {
|
|
|
3255
4044
|
switch (op) {
|
|
3256
4045
|
case 'equal':
|
|
3257
4046
|
case 'eq':
|
|
3258
|
-
|
|
4047
|
+
if (!isNil(condition.field) && condition.field !== '') {
|
|
4048
|
+
result = filterValuesAreEqual(rawValue, condition.value);
|
|
4049
|
+
}
|
|
4050
|
+
else {
|
|
4051
|
+
result = isEqual(valueToCompare, conditionValue);
|
|
4052
|
+
}
|
|
3259
4053
|
if (loggingEnabled) {
|
|
3260
4054
|
console.log('Equal check result:', result);
|
|
3261
4055
|
}
|
|
@@ -3263,7 +4057,12 @@ function applyCondition(item, condition) {
|
|
|
3263
4057
|
case 'notEqual':
|
|
3264
4058
|
case 'ne':
|
|
3265
4059
|
case 'neq':
|
|
3266
|
-
|
|
4060
|
+
if (!isNil(condition.field) && condition.field !== '') {
|
|
4061
|
+
result = !filterValuesAreEqual(rawValue, condition.value);
|
|
4062
|
+
}
|
|
4063
|
+
else {
|
|
4064
|
+
result = !isEqual(valueToCompare, conditionValue);
|
|
4065
|
+
}
|
|
3267
4066
|
if (loggingEnabled) {
|
|
3268
4067
|
console.log('Not equal check result:', result);
|
|
3269
4068
|
}
|
|
@@ -3296,12 +4095,15 @@ function applyCondition(item, condition) {
|
|
|
3296
4095
|
console.log('Less than or equal check result:', result);
|
|
3297
4096
|
}
|
|
3298
4097
|
break;
|
|
3299
|
-
case 'contains':
|
|
3300
|
-
|
|
3301
|
-
|
|
4098
|
+
case 'contains': {
|
|
4099
|
+
const needle = toFilterSearchText(condition.value) ??
|
|
4100
|
+
(condition.value == null ? '' : String(condition.value).toLowerCase());
|
|
4101
|
+
const haystack = toFilterSearchText(rawValue);
|
|
4102
|
+
if (haystack !== undefined) {
|
|
4103
|
+
result = includes(haystack, needle);
|
|
3302
4104
|
}
|
|
3303
|
-
else if (Array.isArray(
|
|
3304
|
-
result = includes(
|
|
4105
|
+
else if (Array.isArray(rawValue)) {
|
|
4106
|
+
result = includes(rawValue.map((val) => toFilterSearchText(val) ?? val.toString().toLowerCase()), needle);
|
|
3305
4107
|
}
|
|
3306
4108
|
else {
|
|
3307
4109
|
result = false;
|
|
@@ -3310,13 +4112,18 @@ function applyCondition(item, condition) {
|
|
|
3310
4112
|
console.log('Contains check result:', result);
|
|
3311
4113
|
}
|
|
3312
4114
|
break;
|
|
4115
|
+
}
|
|
3313
4116
|
case 'in':
|
|
3314
4117
|
if (Array.isArray(conditionValue)) {
|
|
3315
4118
|
if (typeof valueToCompare === 'string') {
|
|
3316
|
-
result = conditionValue.some(val => typeof val === 'string' ? val.toLowerCase() === valueToCompare : val === valueToCompare);
|
|
4119
|
+
result = conditionValue.some((val) => typeof val === 'string' ? val.toLowerCase() === valueToCompare : val === valueToCompare);
|
|
4120
|
+
}
|
|
4121
|
+
else if (isLocaleStringMap(rawValue)) {
|
|
4122
|
+
const localeValues = Object.values(rawValue).map((v) => v.toLowerCase());
|
|
4123
|
+
result = localeValues.some((localeVal) => conditionValue.some((val) => typeof val === 'string' ? val.toLowerCase() === localeVal : val === localeVal));
|
|
3317
4124
|
}
|
|
3318
4125
|
else if (Array.isArray(valueToCompare)) {
|
|
3319
|
-
result = valueToCompare.some(val => conditionValue.some(condVal => typeof val === 'string' && typeof condVal === 'string'
|
|
4126
|
+
result = valueToCompare.some((val) => conditionValue.some((condVal) => typeof val === 'string' && typeof condVal === 'string'
|
|
3320
4127
|
? val.toLowerCase() === condVal.toLowerCase()
|
|
3321
4128
|
: val === condVal));
|
|
3322
4129
|
}
|
|
@@ -3331,12 +4138,15 @@ function applyCondition(item, condition) {
|
|
|
3331
4138
|
console.log('In check result:', result);
|
|
3332
4139
|
}
|
|
3333
4140
|
break;
|
|
3334
|
-
case 'notContains':
|
|
3335
|
-
|
|
3336
|
-
|
|
4141
|
+
case 'notContains': {
|
|
4142
|
+
const needleNc = toFilterSearchText(condition.value) ??
|
|
4143
|
+
(condition.value == null ? '' : String(condition.value).toLowerCase());
|
|
4144
|
+
const haystackNc = toFilterSearchText(rawValue);
|
|
4145
|
+
if (haystackNc !== undefined) {
|
|
4146
|
+
result = !includes(haystackNc, needleNc);
|
|
3337
4147
|
}
|
|
3338
|
-
else if (Array.isArray(
|
|
3339
|
-
result = !includes(
|
|
4148
|
+
else if (Array.isArray(rawValue)) {
|
|
4149
|
+
result = !includes(rawValue.map((val) => toFilterSearchText(val) ?? val.toString().toLowerCase()), needleNc);
|
|
3340
4150
|
}
|
|
3341
4151
|
else {
|
|
3342
4152
|
result = false;
|
|
@@ -3345,18 +4155,27 @@ function applyCondition(item, condition) {
|
|
|
3345
4155
|
console.log('Not contains check result:', result);
|
|
3346
4156
|
}
|
|
3347
4157
|
break;
|
|
3348
|
-
|
|
3349
|
-
|
|
4158
|
+
}
|
|
4159
|
+
case 'startsWith': {
|
|
4160
|
+
const prefix = toFilterSearchText(condition.value) ??
|
|
4161
|
+
(condition.value == null ? '' : String(condition.value).toLowerCase());
|
|
4162
|
+
const haystackSw = toFilterSearchText(rawValue);
|
|
4163
|
+
result = haystackSw !== undefined && startsWith(haystackSw, prefix);
|
|
3350
4164
|
if (loggingEnabled) {
|
|
3351
4165
|
console.log('Starts with check result:', result);
|
|
3352
4166
|
}
|
|
3353
4167
|
break;
|
|
3354
|
-
|
|
3355
|
-
|
|
4168
|
+
}
|
|
4169
|
+
case 'endsWith': {
|
|
4170
|
+
const suffix = toFilterSearchText(condition.value) ??
|
|
4171
|
+
(condition.value == null ? '' : String(condition.value).toLowerCase());
|
|
4172
|
+
const haystackEw = toFilterSearchText(rawValue);
|
|
4173
|
+
result = haystackEw !== undefined && endsWith(haystackEw, suffix);
|
|
3356
4174
|
if (loggingEnabled) {
|
|
3357
4175
|
console.log('Ends with check result:', result);
|
|
3358
4176
|
}
|
|
3359
4177
|
break;
|
|
4178
|
+
}
|
|
3360
4179
|
case 'isEmpty':
|
|
3361
4180
|
result = isEmpty(valueToCompare);
|
|
3362
4181
|
if (loggingEnabled) {
|
|
@@ -3508,45 +4327,45 @@ class AXPDeviceService {
|
|
|
3508
4327
|
/**
|
|
3509
4328
|
* Current screen size (Small, Medium, Large)
|
|
3510
4329
|
*/
|
|
3511
|
-
this.screenSize = signal(getScreenSize(), ...(ngDevMode ? [{ debugName: "screenSize" }] : []));
|
|
4330
|
+
this.screenSize = signal(getScreenSize(), ...(ngDevMode ? [{ debugName: "screenSize" }] : /* istanbul ignore next */ []));
|
|
3512
4331
|
/**
|
|
3513
4332
|
* Current device type (Mobile, Tablet, Desktop)
|
|
3514
4333
|
*/
|
|
3515
|
-
this.deviceType = signal(getDeviceType(), ...(ngDevMode ? [{ debugName: "deviceType" }] : []));
|
|
4334
|
+
this.deviceType = signal(getDeviceType(), ...(ngDevMode ? [{ debugName: "deviceType" }] : /* istanbul ignore next */ []));
|
|
3516
4335
|
/**
|
|
3517
4336
|
* Whether the device supports touch input
|
|
3518
4337
|
*/
|
|
3519
|
-
this.isTouchDevice = signal(isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchDevice" }] : []));
|
|
4338
|
+
this.isTouchDevice = signal(isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchDevice" }] : /* istanbul ignore next */ []));
|
|
3520
4339
|
//#endregion
|
|
3521
4340
|
//#region ---- Computed Signals ----
|
|
3522
4341
|
/**
|
|
3523
4342
|
* Whether the screen size is Small
|
|
3524
4343
|
*/
|
|
3525
|
-
this.isSmall = computed(() => this.screenSize() === AXPScreenSize.Small, ...(ngDevMode ? [{ debugName: "isSmall" }] : []));
|
|
4344
|
+
this.isSmall = computed(() => this.screenSize() === AXPScreenSize.Small, ...(ngDevMode ? [{ debugName: "isSmall" }] : /* istanbul ignore next */ []));
|
|
3526
4345
|
/**
|
|
3527
4346
|
* Whether the screen size is Medium
|
|
3528
4347
|
*/
|
|
3529
|
-
this.isMedium = computed(() => this.screenSize() === AXPScreenSize.Medium, ...(ngDevMode ? [{ debugName: "isMedium" }] : []));
|
|
4348
|
+
this.isMedium = computed(() => this.screenSize() === AXPScreenSize.Medium, ...(ngDevMode ? [{ debugName: "isMedium" }] : /* istanbul ignore next */ []));
|
|
3530
4349
|
/**
|
|
3531
4350
|
* Whether the screen size is Large
|
|
3532
4351
|
*/
|
|
3533
|
-
this.isLarge = computed(() => this.screenSize() === AXPScreenSize.Large, ...(ngDevMode ? [{ debugName: "isLarge" }] : []));
|
|
4352
|
+
this.isLarge = computed(() => this.screenSize() === AXPScreenSize.Large, ...(ngDevMode ? [{ debugName: "isLarge" }] : /* istanbul ignore next */ []));
|
|
3534
4353
|
/**
|
|
3535
4354
|
* Whether the device is Mobile
|
|
3536
4355
|
*/
|
|
3537
|
-
this.isMobileDevice = computed(() => this.deviceType() === AXPDeviceType.Mobile, ...(ngDevMode ? [{ debugName: "isMobileDevice" }] : []));
|
|
4356
|
+
this.isMobileDevice = computed(() => this.deviceType() === AXPDeviceType.Mobile, ...(ngDevMode ? [{ debugName: "isMobileDevice" }] : /* istanbul ignore next */ []));
|
|
3538
4357
|
/**
|
|
3539
4358
|
* Whether the device is Tablet
|
|
3540
4359
|
*/
|
|
3541
|
-
this.isTabletDevice = computed(() => this.deviceType() === AXPDeviceType.Tablet, ...(ngDevMode ? [{ debugName: "isTabletDevice" }] : []));
|
|
4360
|
+
this.isTabletDevice = computed(() => this.deviceType() === AXPDeviceType.Tablet, ...(ngDevMode ? [{ debugName: "isTabletDevice" }] : /* istanbul ignore next */ []));
|
|
3542
4361
|
/**
|
|
3543
4362
|
* Whether the device is Desktop
|
|
3544
4363
|
*/
|
|
3545
|
-
this.isDesktopDevice = computed(() => this.deviceType() === AXPDeviceType.Desktop, ...(ngDevMode ? [{ debugName: "isDesktopDevice" }] : []));
|
|
4364
|
+
this.isDesktopDevice = computed(() => this.deviceType() === AXPDeviceType.Desktop, ...(ngDevMode ? [{ debugName: "isDesktopDevice" }] : /* istanbul ignore next */ []));
|
|
3546
4365
|
/**
|
|
3547
4366
|
* Whether the device supports touch (alias for isTouchDevice)
|
|
3548
4367
|
*/
|
|
3549
|
-
this.isTouchScreen = computed(() => this.isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchScreen" }] : []));
|
|
4368
|
+
this.isTouchScreen = computed(() => this.isTouchDevice(), ...(ngDevMode ? [{ debugName: "isTouchScreen" }] : /* istanbul ignore next */ []));
|
|
3550
4369
|
//#endregion
|
|
3551
4370
|
//#region ---- Private Properties ----
|
|
3552
4371
|
this._resizeListener = null;
|
|
@@ -3612,10 +4431,10 @@ class AXPDeviceService {
|
|
|
3612
4431
|
destroy() {
|
|
3613
4432
|
this._removeResizeListener();
|
|
3614
4433
|
}
|
|
3615
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3616
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
4434
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4435
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, providedIn: 'root' }); }
|
|
3617
4436
|
}
|
|
3618
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4437
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDeviceService, decorators: [{
|
|
3619
4438
|
type: Injectable,
|
|
3620
4439
|
args: [{
|
|
3621
4440
|
providedIn: 'root',
|
|
@@ -3719,10 +4538,10 @@ class AXHighlightService {
|
|
|
3719
4538
|
resultHTML += '</span>';
|
|
3720
4539
|
return resultHTML;
|
|
3721
4540
|
}
|
|
3722
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3723
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
4541
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4542
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, providedIn: 'root' }); }
|
|
3724
4543
|
}
|
|
3725
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4544
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXHighlightService, decorators: [{
|
|
3726
4545
|
type: Injectable,
|
|
3727
4546
|
args: [{
|
|
3728
4547
|
providedIn: 'root',
|
|
@@ -3754,17 +4573,23 @@ async function createProviderWithInjectionContext(loader) {
|
|
|
3754
4573
|
*
|
|
3755
4574
|
* @param token - The injection token to provide
|
|
3756
4575
|
* @param loader - Function that returns a promise resolving to the provider class
|
|
3757
|
-
* @param multi - Whether the provider is multi-provider (
|
|
4576
|
+
* @param multi - Optional. Whether the provider is a multi-provider (array of values). Defaults to `true`. Pass `false` for a single provider.
|
|
3758
4577
|
* @returns Provider configuration object
|
|
3759
4578
|
*
|
|
3760
4579
|
* @example
|
|
3761
4580
|
* ```typescript
|
|
3762
|
-
*
|
|
3763
|
-
*
|
|
3764
|
-
*
|
|
3765
|
-
*
|
|
3766
|
-
*
|
|
3767
|
-
*
|
|
4581
|
+
* // Multi-provider (default)
|
|
4582
|
+
* provideLazyProvider(
|
|
4583
|
+
* AXP_DATASOURCE_DEFINITION_PROVIDER,
|
|
4584
|
+
* () => import('./datasource.provider').then(m => m.AXMDataSourceProvider)
|
|
4585
|
+
* )
|
|
4586
|
+
*
|
|
4587
|
+
* // Single provider
|
|
4588
|
+
* provideLazyProvider(
|
|
4589
|
+
* SOME_TOKEN,
|
|
4590
|
+
* () => import('./my.provider').then(m => m.MyProvider),
|
|
4591
|
+
* false
|
|
4592
|
+
* )
|
|
3768
4593
|
* ```
|
|
3769
4594
|
*/
|
|
3770
4595
|
function provideLazyProvider(token, loader, multi = true) {
|
|
@@ -3775,11 +4600,113 @@ function provideLazyProvider(token, loader, multi = true) {
|
|
|
3775
4600
|
};
|
|
3776
4601
|
}
|
|
3777
4602
|
|
|
4603
|
+
//#region ---- Unwrapping ----
|
|
4604
|
+
/**
|
|
4605
|
+
* If `raw` is a plain non-array object with a `value` property, returns `value`; otherwise returns `raw`.
|
|
4606
|
+
*/
|
|
4607
|
+
function unwrapValueProperty(raw) {
|
|
4608
|
+
if (raw && typeof raw === 'object' && !Array.isArray(raw) && !(raw instanceof Date) && 'value' in raw) {
|
|
4609
|
+
return raw.value;
|
|
4610
|
+
}
|
|
4611
|
+
return raw;
|
|
4612
|
+
}
|
|
4613
|
+
//#endregion
|
|
4614
|
+
//#region ---- Scalar coercion ----
|
|
4615
|
+
/**
|
|
4616
|
+
* Coerces to a trimmed string. Plain objects may carry `{ value }` from setting widgets or `{ id }` from select payloads using `valueField: 'id'`.
|
|
4617
|
+
*/
|
|
4618
|
+
function coerceUnknownToTrimmedString(raw) {
|
|
4619
|
+
if (typeof raw === 'string') {
|
|
4620
|
+
return raw.trim();
|
|
4621
|
+
}
|
|
4622
|
+
if (raw && typeof raw === 'object' && !Array.isArray(raw) && !(raw instanceof Date)) {
|
|
4623
|
+
const r = raw;
|
|
4624
|
+
if ('value' in r && r['value'] != null) {
|
|
4625
|
+
return String(r['value']).trim();
|
|
4626
|
+
}
|
|
4627
|
+
if ('id' in r && r['id'] != null) {
|
|
4628
|
+
return String(r['id']).trim();
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
return '';
|
|
4632
|
+
}
|
|
4633
|
+
/**
|
|
4634
|
+
* Coerces to boolean: direct booleans pass through; wrapped `{ value: true | 'true' }` is respected; otherwise false.
|
|
4635
|
+
*/
|
|
4636
|
+
function coerceUnknownToBoolean(raw) {
|
|
4637
|
+
if (typeof raw === 'boolean') {
|
|
4638
|
+
return raw;
|
|
4639
|
+
}
|
|
4640
|
+
if (raw && typeof raw === 'object' && 'value' in raw) {
|
|
4641
|
+
const v = raw.value;
|
|
4642
|
+
return v === true || v === 'true';
|
|
4643
|
+
}
|
|
4644
|
+
return false;
|
|
4645
|
+
}
|
|
4646
|
+
/** Parses a finite number after optional `{ value }` unwrap; non-finite or empty string yields NaN. */
|
|
4647
|
+
function coerceUnknownToFiniteNumber(raw) {
|
|
4648
|
+
const v = unwrapValueProperty(raw);
|
|
4649
|
+
if (v === null || v === undefined) {
|
|
4650
|
+
return NaN;
|
|
4651
|
+
}
|
|
4652
|
+
if (typeof v === 'number') {
|
|
4653
|
+
return Number.isFinite(v) ? v : NaN;
|
|
4654
|
+
}
|
|
4655
|
+
if (typeof v === 'boolean') {
|
|
4656
|
+
return v ? 1 : 0;
|
|
4657
|
+
}
|
|
4658
|
+
if (typeof v === 'string') {
|
|
4659
|
+
const t = v.trim();
|
|
4660
|
+
if (t === '') {
|
|
4661
|
+
return NaN;
|
|
4662
|
+
}
|
|
4663
|
+
const n = Number(t);
|
|
4664
|
+
return Number.isFinite(n) ? n : NaN;
|
|
4665
|
+
}
|
|
4666
|
+
return NaN;
|
|
4667
|
+
}
|
|
4668
|
+
/** Parses a Date after optional `{ value }` unwrap; invalid input yields Invalid Date. */
|
|
4669
|
+
function coerceUnknownToDate(raw) {
|
|
4670
|
+
const v = unwrapValueProperty(raw);
|
|
4671
|
+
if (v === null || v === undefined) {
|
|
4672
|
+
return new Date(NaN);
|
|
4673
|
+
}
|
|
4674
|
+
if (v instanceof Date) {
|
|
4675
|
+
return new Date(v.getTime());
|
|
4676
|
+
}
|
|
4677
|
+
if (typeof v === 'number' && Number.isFinite(v)) {
|
|
4678
|
+
return new Date(v);
|
|
4679
|
+
}
|
|
4680
|
+
if (typeof v === 'string') {
|
|
4681
|
+
const t = v.trim();
|
|
4682
|
+
if (t === '') {
|
|
4683
|
+
return new Date(NaN);
|
|
4684
|
+
}
|
|
4685
|
+
return new Date(t);
|
|
4686
|
+
}
|
|
4687
|
+
return new Date(NaN);
|
|
4688
|
+
}
|
|
4689
|
+
//#endregion
|
|
4690
|
+
|
|
3778
4691
|
function extractTextFromHtml(value) {
|
|
3779
4692
|
const div = document.createElement('div');
|
|
3780
4693
|
div.innerHTML = value;
|
|
3781
4694
|
return div.textContent || div.innerText || '';
|
|
3782
4695
|
}
|
|
4696
|
+
/**
|
|
4697
|
+
* True when the string likely contains HTML markup (e.g. `<p>`, `<ul>`), as opposed to plain text.
|
|
4698
|
+
* Used to choose innerHTML vs text interpolation for multilingual fields.
|
|
4699
|
+
*/
|
|
4700
|
+
function containsHtmlMarkup(value) {
|
|
4701
|
+
if (value == null) {
|
|
4702
|
+
return false;
|
|
4703
|
+
}
|
|
4704
|
+
const t = value.trim();
|
|
4705
|
+
if (!t) {
|
|
4706
|
+
return false;
|
|
4707
|
+
}
|
|
4708
|
+
return /<\/?[a-z][\s\S]*?>/i.test(t);
|
|
4709
|
+
}
|
|
3783
4710
|
/**
|
|
3784
4711
|
* Generate kebab-case group name from title
|
|
3785
4712
|
*/
|
|
@@ -3797,5 +4724,5 @@ function generateKebabCase(title) {
|
|
|
3797
4724
|
* Generated bundle index. Do not edit.
|
|
3798
4725
|
*/
|
|
3799
4726
|
|
|
3800
|
-
export {
|
|
4727
|
+
export { AXHighlightService, AXPActivityLogProvider, AXPActivityLogService, AXPAppStartUpProvider, AXPAppStartUpService, AXPBroadcastEventService, AXPCatalogScopeDefinitionProviderService, AXPCatalogScopeDefinitionsDataSourceDefinition, AXPColorPaletteProvider, AXPColorPaletteService, AXPColumnWidthService, AXPComponentLogoConfig, AXPComponentSlot, AXPComponentSlotDirective, AXPComponentSlotModule, AXPComponentSlotRegistryService, AXPContentCheckerDirective, AXPContextChangeEvent, AXPContextDefinitionProviderService, AXPContextStore, AXPCountdownPipe, AXPDataGenerator, AXPDataSourceDefinitionProviderService, AXPDblClickDirective, AXPDefaultColorPalettesProvider, AXPDeviceService, AXPDeviceType, AXPDistributedEventListenerService, AXPElementDataDirective, AXPExportTemplateToken, AXPExpressionEvaluatorScopeProviderContext, AXPExpressionEvaluatorScopeProviderService, AXPExpressionEvaluatorService, AXPFeatureDefinitionProviderContext, AXPGridLayoutDirective, AXPHookService, AXPIconLogoConfig, AXPImageUrlLogoConfig, AXPModuleManifestModule, AXPModuleManifestRegistry, AXPModuleManifestsDataSourceDefinition, AXPPlatformScope, AXPScreenSize, AXPSystemActionType, AXPSystemActions, AXPTagProvider, AXPTagService, AXP_ACTIVITY_LOG_PROVIDER, AXP_CATALOG_SCOPE_DEFINITION_PROVIDER, AXP_COLOR_PALETTE_PROVIDER, AXP_COLUMN_WIDTH_PROVIDER, AXP_CONTEXT_DEFINITION_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, AXP_SESSION_SERVICE, AXP_TAG_PROVIDER, MODULE_MANIFESTS_DATASOURCE_NAME, PLATFORM_CATALOG_SCOPES_DATASOURCE_NAME, applyFilterArray, applyPagination, applyQueryArray, applySortArray, applySystemActionDefault, captureFormContextBaseline, cleanDeep, coerceUnknownToBoolean, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToTrimmedString, compareMultiLanguageStrings, containsHtmlMarkup, createProviderWithInjectionContext, defaultColumnWidthProvider, extractNestedFieldsWildcard, extractTextFromHtml, extractValue, generateKebabCase, getActionButton, getChangedPaths, getDetailedChanges, getEnumValues, getNestedKeys, getSmart, getSystemActions, isFormContextDirty, normalizeDefinitionCategories, objectKeyValueTransforms, provideLazyProvider, resolveActionLook, resolvePlatformScopeKey, resolvePlatformScopeName, searchInMultiLanguageString, setSmart, sortByMultiLanguageString, unwrapValueProperty };
|
|
3801
4728
|
//# sourceMappingURL=acorex-platform-core.mjs.map
|