@acorex/platform 0.0.0-ACOREX

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.
Files changed (116) hide show
  1. package/README.md +7 -0
  2. package/auth/README.md +3 -0
  3. package/common/README.md +3 -0
  4. package/core/README.md +4 -0
  5. package/fesm2022/acorex-platform-auth.mjs +1362 -0
  6. package/fesm2022/acorex-platform-auth.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-common-common-settings.provider-G9XcXXOG.mjs +127 -0
  8. package/fesm2022/acorex-platform-common-common-settings.provider-G9XcXXOG.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-common.mjs +4601 -0
  10. package/fesm2022/acorex-platform-common.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-core.mjs +4374 -0
  12. package/fesm2022/acorex-platform-core.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-domain.mjs +3234 -0
  14. package/fesm2022/acorex-platform-domain.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-layout-builder.mjs +2847 -0
  16. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs +121 -0
  18. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-layout-components.mjs +8583 -0
  20. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-layout-designer.mjs +2474 -0
  22. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-layout-entity.mjs +19150 -0
  24. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-layout-views.mjs +1468 -0
  26. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-layout-widget-core.mjs +2950 -0
  28. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs +72 -0
  30. package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs +158 -0
  32. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-9uCkMxcc.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs +29 -0
  34. package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs +172 -0
  36. package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs +111 -0
  38. package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-BGQqY5Mw.mjs.map +1 -0
  39. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs +274 -0
  40. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DmzNTYiS.mjs.map +1 -0
  41. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs +64 -0
  42. package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-BNG_588B.mjs.map +1 -0
  43. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs +34 -0
  44. package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-layout-widgets.mjs +29791 -0
  46. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -0
  47. package/fesm2022/acorex-platform-native.mjs +155 -0
  48. package/fesm2022/acorex-platform-native.mjs.map +1 -0
  49. package/fesm2022/acorex-platform-runtime-catalog-command-definition.mjs +20 -0
  50. package/fesm2022/acorex-platform-runtime-catalog-command-definition.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-runtime-catalog-query-definition.mjs +20 -0
  52. package/fesm2022/acorex-platform-runtime-catalog-query-definition.mjs.map +1 -0
  53. package/fesm2022/acorex-platform-runtime.mjs +899 -0
  54. package/fesm2022/acorex-platform-runtime.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs +160 -0
  56. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-Cvvr4HnL.mjs.map +1 -0
  57. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs +120 -0
  58. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-TYoLN1Jq.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.mjs +237 -0
  60. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-C2z5Lq9y.mjs.map +1 -0
  61. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs +31 -0
  62. package/fesm2022/acorex-platform-themes-default-error-401.component-C7EYJzSr.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs +25 -0
  64. package/fesm2022/acorex-platform-themes-default-error-404.component-7MVLMwIa.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +19 -0
  66. package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +1 -0
  67. package/fesm2022/acorex-platform-themes-default.mjs +2589 -0
  68. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -0
  69. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs +55 -0
  70. package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +1 -0
  71. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs +57 -0
  72. package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +1 -0
  73. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs +168 -0
  74. package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +1 -0
  75. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs +65 -0
  76. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-CHfrTtol.mjs.map +1 -0
  77. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs +64 -0
  78. package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-BSmvnUVq.mjs.map +1 -0
  79. package/fesm2022/acorex-platform-themes-shared.mjs +2125 -0
  80. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -0
  81. package/fesm2022/acorex-platform-workflow.mjs +2501 -0
  82. package/fesm2022/acorex-platform-workflow.mjs.map +1 -0
  83. package/fesm2022/acorex-platform.mjs +6 -0
  84. package/fesm2022/acorex-platform.mjs.map +1 -0
  85. package/layout/builder/README.md +1578 -0
  86. package/layout/components/README.md +3 -0
  87. package/layout/designer/README.md +4 -0
  88. package/layout/entity/README.md +4 -0
  89. package/layout/views/README.md +3 -0
  90. package/layout/widget-core/README.md +4 -0
  91. package/layout/widgets/README.md +3 -0
  92. package/native/README.md +4 -0
  93. package/package.json +103 -0
  94. package/runtime/README.md +3 -0
  95. package/themes/default/README.md +3 -0
  96. package/themes/shared/README.md +3 -0
  97. package/types/acorex-platform-auth.d.ts +680 -0
  98. package/types/acorex-platform-common.d.ts +2926 -0
  99. package/types/acorex-platform-core.d.ts +2896 -0
  100. package/types/acorex-platform-domain.d.ts +2353 -0
  101. package/types/acorex-platform-layout-builder.d.ts +926 -0
  102. package/types/acorex-platform-layout-components.d.ts +2903 -0
  103. package/types/acorex-platform-layout-designer.d.ts +422 -0
  104. package/types/acorex-platform-layout-entity.d.ts +3189 -0
  105. package/types/acorex-platform-layout-views.d.ts +667 -0
  106. package/types/acorex-platform-layout-widget-core.d.ts +1086 -0
  107. package/types/acorex-platform-layout-widgets.d.ts +5478 -0
  108. package/types/acorex-platform-native.d.ts +28 -0
  109. package/types/acorex-platform-runtime-catalog-command-definition.d.ts +137 -0
  110. package/types/acorex-platform-runtime-catalog-query-definition.d.ts +125 -0
  111. package/types/acorex-platform-runtime.d.ts +470 -0
  112. package/types/acorex-platform-themes-default.d.ts +573 -0
  113. package/types/acorex-platform-themes-shared.d.ts +170 -0
  114. package/types/acorex-platform-workflow.d.ts +1806 -0
  115. package/types/acorex-platform.d.ts +2 -0
  116. package/workflow/README.md +4 -0
@@ -0,0 +1,4601 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, Injectable, Injector, signal, makeEnvironmentProviders, NgModule, ErrorHandler, EventEmitter, Input, Output, Directive, ChangeDetectionStrategy, Component, ViewEncapsulation, Inject, runInInjectionContext, model, linkedSignal, afterNextRender } from '@angular/core';
3
+ import { kebabCase, merge, sortBy, cloneDeep, get, omit } from 'lodash-es';
4
+ import { Router, ROUTES, RouterModule } from '@angular/router';
5
+ import { AXPSessionService, AXPSessionStatus } from '@acorex/platform/auth';
6
+ import { Subject, distinctUntilChanged, merge as merge$1 } from 'rxjs';
7
+ import { AXPPlatformScope, AXPBroadcastEventService, objectKeyValueTransforms, AXPSystemActionType, AXPModuleManifestModule, AXPAppStartUpProvider, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPHookService, AXPDataGenerator, AXPModuleManifestRegistry } from '@acorex/platform/core';
8
+ import { AXTranslationService } from '@acorex/core/translation';
9
+ import { AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
10
+ import { AXPopupModule, AXPopupService } from '@acorex/components/popup';
11
+ import { AXToastService, AXToastModule } from '@acorex/components/toast';
12
+ import { AXDateTimeModule } from '@acorex/core/date-time';
13
+ import * as i1 from '@acorex/platform/workflow';
14
+ import { AXPWorkflowService, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowError, AXPWorkflowModule } from '@acorex/platform/workflow';
15
+ import { AXDataSource } from '@acorex/cdk/common';
16
+ import { AXPCommandExecutor, AXPCommandService } from '@acorex/platform/runtime';
17
+ import { signalStore, withState, withMethods, patchState, withHooks } from '@ngrx/signals';
18
+ import { AXFormatService } from '@acorex/core/format';
19
+ import { AXDialogService } from '@acorex/components/dialog';
20
+ import { AXFileService } from '@acorex/core/file';
21
+ import * as i5 from '@acorex/components/button';
22
+ import { AXButtonModule } from '@acorex/components/button';
23
+ import { AXCheckBoxModule } from '@acorex/components/check-box';
24
+ import * as i6 from '@acorex/components/color-box';
25
+ import { AXColorBoxModule } from '@acorex/components/color-box';
26
+ import * as i4 from '@acorex/components/decorators';
27
+ import { AXDecoratorModule } from '@acorex/components/decorators';
28
+ import * as i3 from '@acorex/components/label';
29
+ import { AXLabelModule } from '@acorex/components/label';
30
+ import * as i2 from '@acorex/components/number-box';
31
+ import { AXNumberBoxModule } from '@acorex/components/number-box';
32
+ import { AXBasePageComponent } from '@acorex/components/page';
33
+ import { AXTextBoxModule } from '@acorex/components/text-box';
34
+ import * as i1$1 from '@angular/forms';
35
+ import { FormsModule } from '@angular/forms';
36
+
37
+ const AXP_APP_VERSION_PROVIDER = new InjectionToken('AXP_APP_VERSION_PROVIDER', {
38
+ providedIn: 'root',
39
+ factory: () => {
40
+ return new AXPAppVersionDefaultProvider();
41
+ },
42
+ });
43
+ class AXPAppVersionDefaultProvider {
44
+ async provider() {
45
+ return {
46
+ version: '1.0.0',
47
+ build: 1,
48
+ date: new Date(),
49
+ };
50
+ }
51
+ }
52
+ class AXPAppVersionService {
53
+ constructor() {
54
+ this.provider = inject(AXP_APP_VERSION_PROVIDER);
55
+ }
56
+ async getAppVersion() {
57
+ return this.provider.provider();
58
+ }
59
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppVersionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
60
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppVersionService, providedIn: 'root' }); }
61
+ }
62
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAppVersionService, decorators: [{
63
+ type: Injectable,
64
+ args: [{
65
+ providedIn: 'root',
66
+ }]
67
+ }] });
68
+
69
+ var AXPRelationshipKind;
70
+ (function (AXPRelationshipKind) {
71
+ AXPRelationshipKind[AXPRelationshipKind["Association"] = 0] = "Association";
72
+ AXPRelationshipKind[AXPRelationshipKind["Composition"] = 1] = "Composition";
73
+ AXPRelationshipKind[AXPRelationshipKind["Aggregation"] = 2] = "Aggregation";
74
+ })(AXPRelationshipKind || (AXPRelationshipKind = {}));
75
+ var AXPRelationshipCardinality;
76
+ (function (AXPRelationshipCardinality) {
77
+ AXPRelationshipCardinality[AXPRelationshipCardinality["OneToOne"] = 0] = "OneToOne";
78
+ AXPRelationshipCardinality[AXPRelationshipCardinality["OneToMany"] = 1] = "OneToMany";
79
+ AXPRelationshipCardinality[AXPRelationshipCardinality["ManyToMany"] = 2] = "ManyToMany";
80
+ })(AXPRelationshipCardinality || (AXPRelationshipCardinality = {}));
81
+ var AXPEntityCommandScope;
82
+ (function (AXPEntityCommandScope) {
83
+ AXPEntityCommandScope["TypeLevel"] = "typeLevel";
84
+ AXPEntityCommandScope["Selected"] = "selected";
85
+ AXPEntityCommandScope["Individual"] = "individual";
86
+ AXPEntityCommandScope["Section"] = "section";
87
+ })(AXPEntityCommandScope || (AXPEntityCommandScope = {}));
88
+ var AXPEntityQueryType;
89
+ (function (AXPEntityQueryType) {
90
+ AXPEntityQueryType["Single"] = "single";
91
+ AXPEntityQueryType["List"] = "list";
92
+ })(AXPEntityQueryType || (AXPEntityQueryType = {}));
93
+ function getEntityInfo(entity) {
94
+ return {
95
+ source: `${entity.module}.${entity.name}`,
96
+ module: {
97
+ route: kebabCase(entity.module),
98
+ },
99
+ entity: {
100
+ route: kebabCase(entity.name),
101
+ },
102
+ };
103
+ }
104
+ function createQueryView(name, title, fixed, params = {
105
+ columns: [],
106
+ conditions: [],
107
+ sorts: [],
108
+ }) {
109
+ params = Object.assign({ columns: [], sorts: [], conditions: [] }, params);
110
+ return {
111
+ name,
112
+ title,
113
+ fixed,
114
+ columns: params.columns ?? [],
115
+ conditions: params.conditions ?? [],
116
+ sorts: params.sorts ?? [],
117
+ };
118
+ }
119
+ function createAllQueryView(params = {
120
+ columns: [],
121
+ sorts: [],
122
+ conditions: [],
123
+ }) {
124
+ params = Object.assign({ columns: [], sorts: [], conditions: [] }, params);
125
+ return createQueryView('all', '@general:terms.interface.selection.all-items', true, {
126
+ columns: params.columns ?? [],
127
+ conditions: params.conditions ?? [],
128
+ sorts: params.sorts ?? [],
129
+ });
130
+ }
131
+ // new version
132
+ var AXPEntityType;
133
+ (function (AXPEntityType) {
134
+ AXPEntityType[AXPEntityType["Entity"] = 0] = "Entity";
135
+ AXPEntityType[AXPEntityType["AggregateRoot"] = 1] = "AggregateRoot";
136
+ AXPEntityType[AXPEntityType["ValueObject"] = 2] = "ValueObject";
137
+ })(AXPEntityType || (AXPEntityType = {}));
138
+
139
+ const EQ_OPER = { name: 'equal', title: '@general:terms.operators.equal', hasValue: true };
140
+ const NOT_EQ_OPER = { name: 'notEqual', title: '@general:terms.operators.not-equal', hasValue: true };
141
+ const GT_OPER = { name: 'greaterThan', title: '@general:terms.operators.greater-than', hasValue: true };
142
+ const LT_OPER = { name: 'lessThan', title: '@general:terms.operators.less-than', hasValue: true };
143
+ const GTE_OPER = {
144
+ name: 'greaterThanOrEqual',
145
+ title: '@general:terms.operators.greater-than-or-equal',
146
+ hasValue: true,
147
+ };
148
+ const LTE_OPER = { name: 'lessThanOrEqual', title: '@general:terms.operators.less-than-or-equal', hasValue: true };
149
+ const CONTAINS_OPER = { name: 'contains', title: '@general:terms.operators.contains', hasValue: true };
150
+ const NOT_CONTAINS_OPER = { name: 'notContains', title: '@general:terms.operators.not-contains', hasValue: true };
151
+ const IN_OPER = { name: 'in', title: '@general:terms.operators.in', hasValue: true };
152
+ const STARTS_WITH_OPER = { name: 'startsWith', title: '@general:terms.operators.starts-with', hasValue: true };
153
+ const ENDS_WITH_OPER = { name: 'endsWith', title: '@general:terms.operators.ends-with', hasValue: true };
154
+ const IS_EMPTY_OPER = { name: 'isEmpty', title: '@general:terms.operators.is-empty', hasValue: false };
155
+ const IS_NOT_EMPTY_OPER = { name: 'isNotEmpty', title: '@general:terms.operators.is-not-empty', hasValue: false };
156
+ const BETWEEN_OPER = { name: 'between', title: '@general:terms.operators.between', hasValue: true };
157
+ const STRING_OPERATORS = [
158
+ EQ_OPER,
159
+ NOT_EQ_OPER,
160
+ CONTAINS_OPER,
161
+ NOT_CONTAINS_OPER,
162
+ STARTS_WITH_OPER,
163
+ ENDS_WITH_OPER,
164
+ IS_EMPTY_OPER,
165
+ IS_NOT_EMPTY_OPER,
166
+ IN_OPER
167
+ ];
168
+ const NUMBER_OPERATORS = [
169
+ EQ_OPER,
170
+ NOT_EQ_OPER,
171
+ BETWEEN_OPER,
172
+ GT_OPER,
173
+ GTE_OPER,
174
+ LT_OPER,
175
+ LTE_OPER,
176
+ IS_EMPTY_OPER,
177
+ IS_NOT_EMPTY_OPER,
178
+ ];
179
+ const BOOLEAN_OPERATORS = [EQ_OPER];
180
+ const DATE_OPERATORS = [
181
+ EQ_OPER,
182
+ NOT_EQ_OPER,
183
+ GT_OPER,
184
+ GTE_OPER,
185
+ LT_OPER,
186
+ LTE_OPER,
187
+ IS_EMPTY_OPER,
188
+ IS_NOT_EMPTY_OPER,
189
+ ];
190
+ const ALL_DEFAULT_OPERATORS = [
191
+ EQ_OPER,
192
+ NOT_EQ_OPER,
193
+ GT_OPER,
194
+ LT_OPER,
195
+ GTE_OPER,
196
+ LTE_OPER,
197
+ CONTAINS_OPER,
198
+ IN_OPER,
199
+ NOT_CONTAINS_OPER,
200
+ STARTS_WITH_OPER,
201
+ ENDS_WITH_OPER,
202
+ IS_EMPTY_OPER,
203
+ IS_NOT_EMPTY_OPER,
204
+ BETWEEN_OPER,
205
+ ];
206
+
207
+ const AXP_HOME_PAGES = new InjectionToken('AXP_HOME_PAGES');
208
+ const AXP_HOME_PAGE_DEFAULT_KEY = new InjectionToken('AXP_HOME_PAGE_DEFAULT_KEY', {
209
+ factory: () => 'home'
210
+ });
211
+
212
+ /**
213
+ * Regional and locale-related setting keys used by platform widgets and components.
214
+ * Most values use the `LocaleManagement:Setting:Regional.*` prefix; definitions live in the locale-management module where applicable.
215
+ */
216
+ var AXPRegionalSetting;
217
+ (function (AXPRegionalSetting) {
218
+ AXPRegionalSetting["LocaleProfile"] = "LocaleManagement:Setting:Regional.LocaleProfile";
219
+ AXPRegionalSetting["TimeZone"] = "LocaleManagement:Setting:Regional.TimeZone";
220
+ AXPRegionalSetting["Language"] = "LocaleManagement:Setting:Regional.Language";
221
+ AXPRegionalSetting["Country"] = "LocaleManagement:Setting:Regional.Country";
222
+ AXPRegionalSetting["Calendar"] = "LocaleManagement:Setting:Regional.Calendar";
223
+ AXPRegionalSetting["FirstDayOfWeek"] = "LocaleManagement:Setting:Regional.FirstDayOfWeek";
224
+ AXPRegionalSetting["WeekendDays"] = "LocaleManagement:Setting:Regional.WeekendDays";
225
+ AXPRegionalSetting["ShortDate"] = "LocaleManagement:Setting:Regional.ShortDate";
226
+ AXPRegionalSetting["MediumDate"] = "LocaleManagement:Setting:Regional.MediumDate";
227
+ AXPRegionalSetting["LongDate"] = "LocaleManagement:Setting:Regional.LongDate";
228
+ AXPRegionalSetting["ShortTime"] = "LocaleManagement:Setting:Regional.ShortTime";
229
+ AXPRegionalSetting["MediumTime"] = "LocaleManagement:Setting:Regional.MediumTime";
230
+ AXPRegionalSetting["LongTime"] = "LocaleManagement:Setting:Regional.LongTime";
231
+ AXPRegionalSetting["MeasurementUnits"] = "LocaleManagement:Setting:Regional.MeasurementUnits";
232
+ AXPRegionalSetting["TemperatureUnits"] = "LocaleManagement:Setting:Regional.TemperatureUnits";
233
+ AXPRegionalSetting["DistanceUnits"] = "LocaleManagement:Setting:Regional.DistanceUnits";
234
+ AXPRegionalSetting["WeightUnits"] = "LocaleManagement:Setting:Regional.WeightUnits";
235
+ AXPRegionalSetting["VolumeUnits"] = "LocaleManagement:Setting:Regional.VolumeUnits";
236
+ AXPRegionalSetting["SpeedUnits"] = "LocaleManagement:Setting:Regional.SpeedUnits";
237
+ AXPRegionalSetting["AreaUnits"] = "LocaleManagement:Setting:Regional.AreaUnits";
238
+ /** Default multi-language behavior for standard text field names; defined in locale-management `AXMRegionalSettingProvider`. */
239
+ AXPRegionalSetting["MultiLanguageSupport"] = "LocaleManagement:Setting:Regional.MultiLanguageSupport";
240
+ })(AXPRegionalSetting || (AXPRegionalSetting = {}));
241
+
242
+ const AXP_SETTING_VALUE_PROVIDER = new InjectionToken('AXP_SETTING_VALUE_PROVIDER', {
243
+ providedIn: 'root',
244
+ factory: () => {
245
+ const injector = inject(Injector);
246
+ return [
247
+ new AXPSettingValueProviderDefault(AXPPlatformScope.Platform, injector),
248
+ new AXPSettingValueProviderDefault(AXPPlatformScope.Tenant, injector),
249
+ new AXPSettingValueProviderDefault(AXPPlatformScope.User, injector)
250
+ ];
251
+ }
252
+ });
253
+ class AXPSettingValueProviderDefault {
254
+ constructor(_scope, injector) {
255
+ this._scope = _scope;
256
+ this.injector = injector;
257
+ this.cache = new Map();
258
+ this.localStorageKey = null;
259
+ this.sessionService = this.injector.get(AXPSessionService);
260
+ // Platform scope doesn't depend on session, initialize immediately
261
+ if (this.scope === AXPPlatformScope.Platform) {
262
+ this.localStorageKey = `AXP_SETTINGS_SCOPE(P)`;
263
+ }
264
+ else {
265
+ this.sessionService.status$.subscribe((status) => {
266
+ if (status === AXPSessionStatus.Authorized || status === AXPSessionStatus.Authenticated) {
267
+ if (this.scope === AXPPlatformScope.User) {
268
+ this.localStorageKey = `AXP_SETTINGS_SCOPE(${this.sessionService.user?.id ?? 'U'})`;
269
+ }
270
+ else if (this.scope === AXPPlatformScope.Tenant) {
271
+ this.localStorageKey = `AXP_SETTINGS_SCOPE(${this.sessionService.tenant?.id ?? 'T'})`;
272
+ }
273
+ }
274
+ });
275
+ }
276
+ }
277
+ get scope() {
278
+ return this._scope;
279
+ }
280
+ async load() {
281
+ if (!this.localStorageKey) {
282
+ return Promise.resolve([]);
283
+ }
284
+ // Load settings from localStorage as a single key
285
+ const storedSettings = localStorage.getItem(this.localStorageKey);
286
+ if (storedSettings) {
287
+ const parsedSettings = JSON.parse(storedSettings);
288
+ Object.entries(parsedSettings).forEach(([key, value]) => {
289
+ this.cache.set(key, value);
290
+ });
291
+ return Promise.resolve(Array.from(this.cache.entries()).map(c => ({ key: c[0], value: c[1] })));
292
+ }
293
+ return Promise.resolve([]);
294
+ }
295
+ async set(keyOrValues, value) {
296
+ if (typeof keyOrValues === 'string') {
297
+ // Single value update
298
+ this.cache.set(keyOrValues, value);
299
+ }
300
+ else {
301
+ // Bulk update
302
+ for (const [key, val] of Object.entries(keyOrValues)) {
303
+ this.cache.set(key, val);
304
+ }
305
+ }
306
+ await this.saveToLocalStorage();
307
+ }
308
+ async saveToLocalStorage() {
309
+ if (!this.localStorageKey) {
310
+ return;
311
+ }
312
+ const settingsObject = {};
313
+ this.cache.forEach((value, key) => {
314
+ settingsObject[key] = value;
315
+ });
316
+ localStorage.setItem(this.localStorageKey, JSON.stringify(settingsObject));
317
+ }
318
+ async clear() {
319
+ if (!this.localStorageKey) {
320
+ return;
321
+ }
322
+ localStorage.removeItem(this.localStorageKey);
323
+ }
324
+ }
325
+
326
+ class AXPSettingDefinitionProviderContext {
327
+ constructor() {
328
+ this.rootGroups = [];
329
+ this.groupMap = new Map();
330
+ }
331
+ addGroup(name, title, description, icon) {
332
+ const newGroup = {
333
+ name,
334
+ title,
335
+ description,
336
+ icon,
337
+ groups: [],
338
+ sections: [],
339
+ };
340
+ this.rootGroups.push(newGroup);
341
+ this.groupMap.set(name, newGroup); // Index by name
342
+ return new AXPSettingDefinitionGroupBuilder(this, newGroup);
343
+ }
344
+ group(name) {
345
+ const foundGroup = this.groupMap.get(name);
346
+ if (!foundGroup) {
347
+ console.error(`Group with name "${name}" not found.`);
348
+ return null;
349
+ }
350
+ return new AXPSettingDefinitionGroupBuilder(this, foundGroup);
351
+ }
352
+ getGroups() {
353
+ return this.rootGroups;
354
+ }
355
+ // Expose groupMap for controlled access
356
+ hasGroup(name) {
357
+ return this.groupMap.has(name);
358
+ }
359
+ getGroup(name) {
360
+ return this.groupMap.get(name);
361
+ }
362
+ }
363
+ class AXPSettingDefinitionGroupBuilder {
364
+ constructor(context, group) {
365
+ this.context = context;
366
+ this.group = group;
367
+ }
368
+ addSection(name, title, description) {
369
+ const newSection = {
370
+ name,
371
+ title,
372
+ description: description,
373
+ settings: [],
374
+ };
375
+ this.group.sections.push(newSection);
376
+ return new AXPSettingDefinitionSectionBuilder(this, newSection);
377
+ }
378
+ section(name) {
379
+ const foundSection = this.group.sections.find((section) => section.name === name);
380
+ if (!foundSection) {
381
+ throw new Error(`Section with name "${name}" not found in group "${this.group.name}".`);
382
+ }
383
+ return new AXPSettingDefinitionSectionBuilder(this, foundSection);
384
+ }
385
+ addGroup(name, title, description, icon) {
386
+ const newGroup = {
387
+ name,
388
+ title,
389
+ description: description,
390
+ icon,
391
+ groups: [],
392
+ sections: [],
393
+ };
394
+ this.group.groups.push(newGroup);
395
+ if (this.context.hasGroup(name)) {
396
+ throw new Error(`Group with name "${name}" already exists.`);
397
+ }
398
+ this.context['groupMap'].set(name, newGroup);
399
+ return new AXPSettingDefinitionGroupBuilder(this.context, newGroup);
400
+ }
401
+ endGroup() {
402
+ return this.context;
403
+ }
404
+ }
405
+ class AXPSettingDefinitionSectionBuilder {
406
+ constructor(groupBuilder, section) {
407
+ this.groupBuilder = groupBuilder;
408
+ this.section = section;
409
+ }
410
+ addSetting(setting) {
411
+ const newSetting = {
412
+ name: setting.key,
413
+ title: setting.title,
414
+ description: setting.description,
415
+ isRequired: setting.isRequired ?? false,
416
+ isInherited: setting.isInherited ?? false,
417
+ isEncrypted: setting.isEncrypted ?? false,
418
+ defaultValue: setting.defaultValue,
419
+ scope: setting.scope ?? 'P',
420
+ layout: setting.widget.layout,
421
+ widget: {
422
+ type: setting.widget.type,
423
+ name: setting.key,
424
+ path: setting.key,
425
+ defaultValue: setting.defaultValue,
426
+ options: merge(setting.widget.options ?? {}, {
427
+ label: Object.keys(setting.widget.options ?? {}).includes('label') ? setting.widget.options?.['label'] : setting.title,
428
+ validationRules: setting.validationRules ?? [],
429
+ }),
430
+ valueTransforms: setting.valueTransforms,
431
+ triggers: setting.widget.triggers,
432
+ },
433
+ };
434
+ this.section.settings.push(newSetting);
435
+ return this;
436
+ }
437
+ endSection() {
438
+ return this.groupBuilder;
439
+ }
440
+ }
441
+
442
+ // Injection token for setting providers
443
+ const AXP_SETTING_DEFINITION_PROVIDER = new InjectionToken('AXP_SETTING_DEFINITION_PROVIDER');
444
+ class AXPSettingDefinitionProviderService {
445
+ constructor() {
446
+ this.providers = inject(AXP_SETTING_DEFINITION_PROVIDER, { optional: true });
447
+ this.cache = null;
448
+ }
449
+ async load() {
450
+ if (this.cache) {
451
+ return;
452
+ }
453
+ const context = new AXPSettingDefinitionProviderContext();
454
+ // Load providers from DI tokens
455
+ if (Array.isArray(this.providers)) {
456
+ for (const provider of this.providers) {
457
+ if (provider instanceof Promise) {
458
+ // If provider is a promise, resolve it
459
+ const resolvedProvider = await provider;
460
+ await resolvedProvider.provide(context);
461
+ }
462
+ else {
463
+ // If provider is a direct instance, use it directly
464
+ await provider.provide(context);
465
+ }
466
+ }
467
+ }
468
+ this.cache = context.getGroups();
469
+ }
470
+ async reload() {
471
+ this.cache = null;
472
+ await this.load();
473
+ }
474
+ async getListAsync(scope) {
475
+ await this.load();
476
+ return this.getList(scope);
477
+ }
478
+ getList(scope) {
479
+ if (!this.cache) {
480
+ return [];
481
+ }
482
+ const scopeOrder = ['P', 'T', 'U']; // Scopes hierarchy in ascending order
483
+ const filterByScope = (groups, currentScope) => {
484
+ const currentScopeIndex = scopeOrder.indexOf(currentScope);
485
+ return groups
486
+ .map((group) => ({
487
+ ...group,
488
+ sections: group.sections.map((section) => ({
489
+ ...section,
490
+ settings: section.settings.filter((setting) => {
491
+ const settingScopeIndex = scopeOrder.indexOf(setting.scope);
492
+ // Include settings where:
493
+ // 1. The scope matches the requested scope.
494
+ if (setting.scope === currentScope)
495
+ return true;
496
+ // 2. The setting scope is higher (closer to 'U') and is inherited.
497
+ if (setting.isInherited &&
498
+ settingScopeIndex > currentScopeIndex // Higher scope
499
+ ) {
500
+ return true;
501
+ }
502
+ // 3. Exclude settings with a lower or irrelevant scope.
503
+ return false;
504
+ }),
505
+ })).filter((section) => section.settings.length > 0), // Keep only sections with settings
506
+ groups: filterByScope(group.groups, currentScope), // Recursively filter nested groups
507
+ }))
508
+ .filter((group) => group.sections.length > 0 || group.groups.length > 0); // Keep groups with valid sections or nested groups
509
+ };
510
+ return sortBy(filterByScope(this.cache, scope), 'title');
511
+ }
512
+ async defaultValues() {
513
+ const defaults = {};
514
+ const collectDefaults = (groups) => {
515
+ groups.forEach((group) => {
516
+ group.sections.forEach((section) => {
517
+ section.settings.forEach((setting) => {
518
+ if (setting.defaultValue !== undefined) {
519
+ defaults[setting.name] = setting.defaultValue;
520
+ }
521
+ });
522
+ });
523
+ collectDefaults(group.groups);
524
+ });
525
+ };
526
+ if (!this.cache) {
527
+ await this.load();
528
+ }
529
+ collectDefaults(this.cache);
530
+ return defaults;
531
+ }
532
+ findGroup(scope, groupName) {
533
+ return this.searchRecursive(this.getList(scope), groupName, []); // Initialize with an empty breadcrumb
534
+ }
535
+ searchRecursive(groups, groupName, breadcrumb) {
536
+ for (const group of groups) {
537
+ const currentBreadcrumb = [...breadcrumb, { name: group.name, title: group.title, description: group.description }];
538
+ // If the group name matches, return its details
539
+ if (group.name === groupName) {
540
+ return {
541
+ breadcrumb: currentBreadcrumb,
542
+ sections: group.sections.length > 0 ? group.sections : null,
543
+ groups: group.groups.length > 0 ? group.groups : null,
544
+ };
545
+ }
546
+ // Recursively search in nested groups
547
+ const nestedResult = this.searchRecursive(group.groups, groupName, currentBreadcrumb);
548
+ if (nestedResult.breadcrumb.length > 0) {
549
+ return nestedResult;
550
+ }
551
+ }
552
+ // If no matching group is found
553
+ return {
554
+ breadcrumb: [],
555
+ groups: [],
556
+ sections: []
557
+ };
558
+ }
559
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
560
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingDefinitionProviderService, providedIn: 'root' }); }
561
+ }
562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingDefinitionProviderService, decorators: [{
563
+ type: Injectable,
564
+ args: [{ providedIn: 'root' }]
565
+ }] });
566
+ // Multi-provider token for higher-layer default values
567
+ const AXP_SETTING_DEFAULT_VALUES_PROVIDERS = new InjectionToken('AXP_SETTING_DEFAULT_VALUES_PROVIDERS', {
568
+ providedIn: 'root',
569
+ factory: () => [],
570
+ });
571
+ // Aggregator service that merges definition defaults with higher-layer providers (by priority)
572
+ class AXPSettingDefaultValuesAggregatorService {
573
+ constructor() {
574
+ this.definitionService = inject(AXPSettingDefinitionProviderService);
575
+ this.providers = inject(AXP_SETTING_DEFAULT_VALUES_PROVIDERS, { optional: true }) ?? [];
576
+ }
577
+ async getDefaults() {
578
+ const baseDefaults = await this.definitionService.defaultValues();
579
+ const ordered = [...this.providers].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
580
+ const merged = { ...baseDefaults };
581
+ for (const provider of ordered) {
582
+ try {
583
+ const overrideMap = await provider.provide();
584
+ Object.assign(merged, overrideMap);
585
+ }
586
+ catch (err) {
587
+ console.error('AXPSettingDefaultValuesProvider failed:', err);
588
+ }
589
+ }
590
+ return merged;
591
+ }
592
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingDefaultValuesAggregatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
593
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingDefaultValuesAggregatorService, providedIn: 'root' }); }
594
+ }
595
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingDefaultValuesAggregatorService, decorators: [{
596
+ type: Injectable,
597
+ args: [{ providedIn: 'root' }]
598
+ }] });
599
+
600
+ class AXPSettingsService {
601
+ constructor() {
602
+ this.providers = inject(AXP_SETTING_VALUE_PROVIDER);
603
+ this.injector = inject(Injector);
604
+ this.eventService = inject(AXPBroadcastEventService);
605
+ this.sessionService = inject(AXPSessionService);
606
+ this.scopedSettingsCache = new Map();
607
+ this.onChanged = new Subject();
608
+ this.onLoaded = new Subject();
609
+ // Initialize scoped caches for dynamic scopes
610
+ const staticScopes = [
611
+ AXPPlatformScope.Platform,
612
+ AXPPlatformScope.Tenant,
613
+ AXPPlatformScope.User,
614
+ ];
615
+ staticScopes.forEach((scope) => {
616
+ if (!this.scopedSettingsCache.has(scope)) {
617
+ this.scopedSettingsCache.set(scope, new Map());
618
+ }
619
+ });
620
+ // Listen for setting changes from other tabs
621
+ this.eventService.listen('AXPSettingChangedEvent').subscribe((event) => {
622
+ const data = event.data;
623
+ data.keys.forEach((key) => {
624
+ this.scopedSettingsCache.get(data.scope)?.set(key, data.values[key]);
625
+ });
626
+ this.onChanged.next(data); // Notify subscribers in the current tab
627
+ });
628
+ // reload settings when user is authenticated
629
+ this.sessionService.isAuthenticated$.pipe(distinctUntilChanged()).subscribe(async (isAuthenticated) => {
630
+ if (isAuthenticated) {
631
+ await this.reload();
632
+ }
633
+ });
634
+ }
635
+ async reload() {
636
+ await this.load();
637
+ }
638
+ async load() {
639
+ try {
640
+ const settingsList = [];
641
+ for (const provider of this.providers) {
642
+ const scopeCache = this.scopedSettingsCache.get(provider.scope) ?? new Map();
643
+ const providerSettings = await provider.load();
644
+ providerSettings.forEach((setting) => {
645
+ scopeCache.set(setting.key, setting.value);
646
+ });
647
+ settingsList.push(...providerSettings);
648
+ }
649
+ this.onLoaded.next();
650
+ return settingsList;
651
+ }
652
+ catch (error) {
653
+ console.error('Error loading settings', error);
654
+ throw error;
655
+ }
656
+ }
657
+ async get(key) {
658
+ if (this.scopedSettingsCache.size === 0) {
659
+ await this.load();
660
+ }
661
+ const scopeOrder = [
662
+ AXPPlatformScope.User,
663
+ AXPPlatformScope.Tenant,
664
+ AXPPlatformScope.Platform,
665
+ ];
666
+ for (const scope of scopeOrder) {
667
+ const scopeCache = this.scopedSettingsCache.get(scope);
668
+ if (scopeCache && scopeCache.has(key)) {
669
+ const value = scopeCache.get(key);
670
+ if (value !== undefined && value !== null) {
671
+ return cloneDeep(value);
672
+ }
673
+ }
674
+ }
675
+ const defaults = await this.injector.get(AXPSettingDefaultValuesAggregatorService).getDefaults();
676
+ return get(defaults, key); // Fallback if no value is found
677
+ }
678
+ async defaultValues(scope) {
679
+ let scopeOrder = [
680
+ AXPPlatformScope.Platform,
681
+ AXPPlatformScope.Tenant,
682
+ AXPPlatformScope.User,
683
+ ].reverse();
684
+ const scopeIndex = scopeOrder.indexOf(scope);
685
+ if (scopeIndex === -1) {
686
+ throw new Error(`Invalid scope: ${scope}`);
687
+ }
688
+ scopeOrder = scopeOrder.slice(scopeIndex + 1);
689
+ // Accumulate defaults from the current scope and higher scopes
690
+ const accumulatedDefaults = {};
691
+ for (let i = scopeIndex; i < scopeOrder.length; i++) {
692
+ const currentScope = scopeOrder[i];
693
+ const scopeCache = this.scopedSettingsCache.get(currentScope);
694
+ if (scopeCache) {
695
+ scopeCache.forEach((value, key) => {
696
+ if (!(key in accumulatedDefaults)) {
697
+ accumulatedDefaults[key] = value;
698
+ }
699
+ });
700
+ }
701
+ }
702
+ // Merge with aggregated default values (definition + higher-layer providers)
703
+ const globalDefaults = await this.injector.get(AXPSettingDefaultValuesAggregatorService).getDefaults();
704
+ return { ...globalDefaults, ...accumulatedDefaults };
705
+ }
706
+ scope(scope) {
707
+ const provider = this.providers.find((p) => p.scope === scope);
708
+ if (!provider) {
709
+ throw new Error(`No provider found for scope: ${scope}`);
710
+ }
711
+ return new ScopedSettingService(this, provider, this.scopedSettingsCache.get(scope));
712
+ }
713
+ invokeChangeEvent(event) {
714
+ this.onChanged.next(event);
715
+ this.eventService.publish('AXPSettingChangedEvent', event);
716
+ }
717
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
718
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingsService, providedIn: 'root' }); }
719
+ }
720
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSettingsService, decorators: [{
721
+ type: Injectable,
722
+ args: [{
723
+ providedIn: 'root',
724
+ }]
725
+ }], ctorParameters: () => [] });
726
+ class ScopedSettingService {
727
+ constructor(parent, provider, scopeCache) {
728
+ this.parent = parent;
729
+ this.provider = provider;
730
+ this.scopeCache = scopeCache;
731
+ }
732
+ async get(key) {
733
+ const settings = await this.provider.load();
734
+ const setting = settings.find((s) => s.key === key);
735
+ return setting ? cloneDeep(setting.value) : undefined;
736
+ }
737
+ async all() {
738
+ const settings = await this.provider.load();
739
+ return Object.fromEntries(settings.map((s) => [s.key, cloneDeep(s.value)]));
740
+ }
741
+ async defaultValues() {
742
+ return this.parent.defaultValues(this.provider.scope);
743
+ }
744
+ async set(keyOrValues, value) {
745
+ if (typeof keyOrValues === 'string') {
746
+ // Single key-value pair
747
+ await this.provider.set(keyOrValues, value);
748
+ this.scopeCache.set(keyOrValues, value); // Sync the cache
749
+ this.parent.invokeChangeEvent({
750
+ scope: this.provider.scope,
751
+ keys: [keyOrValues],
752
+ values: { [keyOrValues]: value },
753
+ entries: [{ key: keyOrValues, value }],
754
+ });
755
+ }
756
+ else {
757
+ // Multiple key-value pairs
758
+ await this.provider.set(keyOrValues);
759
+ Object.entries(keyOrValues).forEach(([key, val]) => this.scopeCache.set(key, val)); // Sync the cache
760
+ const entries = Object.entries(keyOrValues).map(([key, val]) => ({ key, value: val }));
761
+ this.parent.invokeChangeEvent({
762
+ scope: this.provider.scope,
763
+ keys: Object.keys(keyOrValues),
764
+ values: keyOrValues,
765
+ entries,
766
+ });
767
+ }
768
+ }
769
+ async update(key, updateFn) {
770
+ const currentValue = await this.get(key);
771
+ const newValue = updateFn(currentValue);
772
+ await this.set(key, newValue);
773
+ }
774
+ }
775
+
776
+ const DEFAULT_APPLY_DEFAULT_MULTILANGUAGE = true;
777
+ /**
778
+ * Synchronous access to default multi-language behavior for named entity fields and widget
779
+ * property bindings. Mirrors {@link AXPLayoutOrderingConfigService}: avoids async in entity
780
+ * modifiers and startup deadlocks.
781
+ */
782
+ class AXPDefaultMultiLanguageConfigService {
783
+ constructor() {
784
+ this.settingsService = inject(AXPSettingsService);
785
+ this._applyDefault = signal(DEFAULT_APPLY_DEFAULT_MULTILANGUAGE, ...(ngDevMode ? [{ debugName: "_applyDefault" }] : /* istanbul ignore next */ []));
786
+ this.syncScheduled = false;
787
+ this.settingsService.onLoaded.subscribe(() => this.syncFromSettings());
788
+ this.settingsService.onChanged.subscribe(() => this.syncFromSettings());
789
+ }
790
+ getApplyDefaultMultiLanguage() {
791
+ if (!this.syncScheduled) {
792
+ this.syncScheduled = true;
793
+ this.settingsService
794
+ .get(AXPRegionalSetting.MultiLanguageSupport)
795
+ .then((value) => this._applyDefault.set(value ?? DEFAULT_APPLY_DEFAULT_MULTILANGUAGE))
796
+ .catch(() => this._applyDefault.set(DEFAULT_APPLY_DEFAULT_MULTILANGUAGE));
797
+ }
798
+ return this._applyDefault();
799
+ }
800
+ async syncFromSettings() {
801
+ try {
802
+ const value = await this.settingsService.get(AXPRegionalSetting.MultiLanguageSupport);
803
+ this._applyDefault.set(value ?? DEFAULT_APPLY_DEFAULT_MULTILANGUAGE);
804
+ }
805
+ catch {
806
+ this._applyDefault.set(DEFAULT_APPLY_DEFAULT_MULTILANGUAGE);
807
+ }
808
+ }
809
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultMultiLanguageConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
810
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultMultiLanguageConfigService, providedIn: 'root' }); }
811
+ }
812
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultMultiLanguageConfigService, decorators: [{
813
+ type: Injectable,
814
+ args: [{ providedIn: 'root' }]
815
+ }], ctorParameters: () => [] });
816
+
817
+ //#region ---- Constants ----
818
+ /**
819
+ * Widget types that support the multiLanguage option (text / rich text editors).
820
+ */
821
+ const MULTILANGUAGE_CAPABLE_WIDGET_TYPES = new Set([
822
+ 'text-editor',
823
+ 'large-text-editor',
824
+ 'rich-text-editor',
825
+ 'template-content-editor',
826
+ ]);
827
+ /**
828
+ * Common property names / binding path segments that are usually translatable when the feature is
829
+ * enabled in settings. Explicit `multiLanguage` on the property still wins.
830
+ */
831
+ const DEFAULT_MULTILANGUAGE_FIELD_NAMES = new Set([
832
+ 'title',
833
+ 'description',
834
+ 'note',
835
+ 'content',
836
+ /** e.g. `post.summaryContent` — last path segment */
837
+ 'summaryContent',
838
+ 'question',
839
+ 'summary',
840
+ 'body',
841
+ 'caption',
842
+ 'remarks',
843
+ 'subtitle',
844
+ 'label',
845
+ 'placeholder',
846
+ 'message',
847
+ 'subject',
848
+ ]);
849
+ //#endregion
850
+ //#region ---- Helpers ----
851
+ function interfacePathLastSegment(path) {
852
+ if (path == null || typeof path !== 'string' || !path.length) {
853
+ return null;
854
+ }
855
+ const seg = path.includes('.') ? path.split('.').pop() : path;
856
+ return seg && seg.length ? seg : null;
857
+ }
858
+ function shouldApplyDefaultMultiLanguageToEntityProperty(prop) {
859
+ if (prop.schema.dataType !== 'string') {
860
+ return false;
861
+ }
862
+ if (!DEFAULT_MULTILANGUAGE_FIELD_NAMES.has(prop.name)) {
863
+ return false;
864
+ }
865
+ const widgetType = prop.schema.interface?.type;
866
+ if (typeof widgetType !== 'string' || !MULTILANGUAGE_CAPABLE_WIDGET_TYPES.has(widgetType)) {
867
+ return false;
868
+ }
869
+ const opts = prop.schema.interface?.options;
870
+ if (opts && 'multiLanguage' in opts) {
871
+ return false;
872
+ }
873
+ return true;
874
+ }
875
+ function shouldApplyDefaultMultiLanguageToWidgetProperty(prop) {
876
+ if (prop.schema.dataType !== 'string') {
877
+ return false;
878
+ }
879
+ const key = interfacePathLastSegment(prop.schema.interface.path);
880
+ if (!key || !DEFAULT_MULTILANGUAGE_FIELD_NAMES.has(key)) {
881
+ return false;
882
+ }
883
+ const widgetType = prop.schema.interface.type;
884
+ if (typeof widgetType !== 'string' || !MULTILANGUAGE_CAPABLE_WIDGET_TYPES.has(widgetType)) {
885
+ return false;
886
+ }
887
+ const opts = prop.schema.interface.options;
888
+ if (opts && 'multiLanguage' in opts) {
889
+ return false;
890
+ }
891
+ return true;
892
+ }
893
+ /**
894
+ * Leaf widget nodes in entity `schema.interface` trees (e.g. GridLayout → RichText under `pre` /
895
+ * `post`) — same path/type rules as {@link shouldApplyDefaultMultiLanguageToWidgetProperty}, without
896
+ * `schema.dataType` (nodes do not carry entity schema).
897
+ */
898
+ function shouldApplyDefaultMultiLanguageToWidgetNode(node) {
899
+ const widgetType = node.type;
900
+ if (typeof widgetType !== 'string' || !MULTILANGUAGE_CAPABLE_WIDGET_TYPES.has(widgetType)) {
901
+ return false;
902
+ }
903
+ const key = interfacePathLastSegment(node.path);
904
+ if (!key || !DEFAULT_MULTILANGUAGE_FIELD_NAMES.has(key)) {
905
+ return false;
906
+ }
907
+ const opts = node.options;
908
+ if (opts && 'multiLanguage' in opts) {
909
+ return false;
910
+ }
911
+ return true;
912
+ }
913
+ /**
914
+ * When {@link AXPDefaultMultiLanguageConfigService#getApplyDefaultMultiLanguage} is true, sets
915
+ * `options.multiLanguage` on eligible editor leaves inside an entity property's widget tree
916
+ * (including nested layouts). Used by entity middleware so object fields (e.g. `pre`, `post`) are
917
+ * covered, not only top-level string properties.
918
+ */
919
+ function withDefaultMultiLanguageOnWidgetNodeTree(root, applyDefault) {
920
+ if (root == null || !applyDefault) {
921
+ return root ?? undefined;
922
+ }
923
+ return visitWidgetNodeForDefaultMultiLanguage(root);
924
+ }
925
+ function visitWidgetNodeForDefaultMultiLanguage(node) {
926
+ let next = node;
927
+ if (node.children?.length) {
928
+ const newChildren = node.children.map((child) => visitWidgetNodeForDefaultMultiLanguage(child));
929
+ if (newChildren.some((c, i) => c !== node.children[i])) {
930
+ next = { ...node, children: newChildren };
931
+ }
932
+ }
933
+ if (shouldApplyDefaultMultiLanguageToWidgetNode(next)) {
934
+ return {
935
+ ...next,
936
+ options: {
937
+ ...(next.options ?? {}),
938
+ multiLanguage: true,
939
+ },
940
+ };
941
+ }
942
+ return next;
943
+ }
944
+ /**
945
+ * When {@link AXPDefaultMultiLanguageConfigService#getApplyDefaultMultiLanguage} is true, sets
946
+ * `schema.interface.options.multiLanguage` for eligible string widget properties (same rules as
947
+ * entity middleware), unless the property already specifies `multiLanguage`.
948
+ */
949
+ function withDefaultMultiLanguageOnWidgetProperty(prop, applyDefault) {
950
+ if (!applyDefault || !shouldApplyDefaultMultiLanguageToWidgetProperty(prop)) {
951
+ return prop;
952
+ }
953
+ const iface = prop.schema.interface;
954
+ const existingOpts = (iface.options ?? {});
955
+ return {
956
+ ...prop,
957
+ schema: {
958
+ ...prop.schema,
959
+ interface: {
960
+ ...iface,
961
+ options: {
962
+ ...existingOpts,
963
+ multiLanguage: true,
964
+ },
965
+ },
966
+ },
967
+ };
968
+ }
969
+ //#endregion
970
+
971
+ //#region ---- Settings expression scope ----
972
+ /**
973
+ * Exposes platform settings in expression strings, e.g.
974
+ * `{{ settings.get('Common:Setting:Entity.ShowPageBadge') }}`.
975
+ */
976
+ class AXPSettingsEvaluatorScopeProvider {
977
+ constructor() {
978
+ this.settingsService = inject(AXPSettingsService);
979
+ }
980
+ async provide(context) {
981
+ context.addScope('settings', {
982
+ get: async (key) => {
983
+ return await this.settingsService.get(key);
984
+ },
985
+ });
986
+ }
987
+ }
988
+ //#endregion
989
+
990
+ var AXPHomePageSettings;
991
+ (function (AXPHomePageSettings) {
992
+ AXPHomePageSettings["UserHomePath"] = "Common:Setting:Startup.HomePage";
993
+ })(AXPHomePageSettings || (AXPHomePageSettings = {}));
994
+
995
+ class AXPHomePageService {
996
+ get flatCandidates() {
997
+ return this.candidates.flatMap((c) => c);
998
+ }
999
+ constructor() {
1000
+ this.defaultHomePageKey = inject(AXP_HOME_PAGE_DEFAULT_KEY, { optional: true }) ?? 'home';
1001
+ this.userHomePageKey = null;
1002
+ this.candidates = inject(AXP_HOME_PAGES, { optional: true }) ?? [];
1003
+ this.settingsService = inject(AXPSettingsService);
1004
+ this.sessionService = inject(AXPSessionService);
1005
+ this.injector = inject(Injector);
1006
+ this.originalConfig = null;
1007
+ this.loginPath = 'auth/login';
1008
+ // remove circular dependency
1009
+ setTimeout(async () => {
1010
+ await this.init();
1011
+ });
1012
+ }
1013
+ async init() {
1014
+ await this.load();
1015
+ //
1016
+ const keys = [AXPHomePageSettings.UserHomePath];
1017
+ this.settingsService.onChanged.subscribe(async (c) => {
1018
+ if (keys.some((k) => c.keys.includes(k))) {
1019
+ await this.load();
1020
+ this.refreshRoutes();
1021
+ }
1022
+ });
1023
+ //
1024
+ merge$1(this.sessionService.status$, this.sessionService.application$, this.sessionService.tenant$).subscribe(async (data) => {
1025
+ await this.load();
1026
+ this.refreshRoutes();
1027
+ });
1028
+ }
1029
+ async load() {
1030
+ this.userHomePageKey = await this.settingsService.get(AXPHomePageSettings.UserHomePath);
1031
+ }
1032
+ getRegisteredList() {
1033
+ return this.flatCandidates.filter((c) => c.route);
1034
+ }
1035
+ getRegisteredRoutes() {
1036
+ const defaultHomePage = this.flatCandidates.find((c) => c.key === this.defaultHomePageKey);
1037
+ const home = this.flatCandidates.find((c) => this.userHomePageKey && c.key === this.userHomePageKey) ?? defaultHomePage;
1038
+ if (home && home.route && this.sessionService.application?.name) {
1039
+ const fullPath = this.findPath(home.route);
1040
+ return [
1041
+ { path: '', redirectTo: fullPath, pathMatch: 'full' },
1042
+ { path: ':app', redirectTo: fullPath, pathMatch: 'full' },
1043
+ { ...home?.route, ...{ data: { key: home?.key, title: home?.title, path: fullPath } } },
1044
+ ];
1045
+ }
1046
+ return [{ path: '', redirectTo: this.loginPath, pathMatch: 'full' }];
1047
+ }
1048
+ getCurrent() {
1049
+ const key = this.userHomePageKey ?? this.defaultHomePageKey;
1050
+ const homePage = this.getRegisteredRoutes().find((c) => c.data?.['key'] === key);
1051
+ if (homePage) {
1052
+ return {
1053
+ path: homePage.data?.['path'],
1054
+ title: homePage.data?.['title'],
1055
+ };
1056
+ }
1057
+ return {
1058
+ path: this.loginPath,
1059
+ title: '',
1060
+ };
1061
+ }
1062
+ findPath(target) {
1063
+ const rawPath = this.buildFullPaths(target).join('/');
1064
+ const appName = this.sessionService.application?.name;
1065
+ if (appName) {
1066
+ return rawPath.replace(':app', appName);
1067
+ }
1068
+ return rawPath;
1069
+ }
1070
+ buildFullPaths(route, parentPath = []) {
1071
+ const segments = [...parentPath];
1072
+ if (route.path) {
1073
+ segments.push(route.path);
1074
+ }
1075
+ // Recursively search the first matched child (deepest first match)
1076
+ if (route.children?.length) {
1077
+ return this.buildFullPaths(route.children[0], segments);
1078
+ }
1079
+ return segments;
1080
+ }
1081
+ refreshRoutes() {
1082
+ const router = this.injector.get(Router);
1083
+ // 👇 On first call, remember what was there before:
1084
+ if (!this.originalConfig) {
1085
+ this.originalConfig = router.config;
1086
+ }
1087
+ this.applyMergedConfig(router);
1088
+ }
1089
+ applyMergedConfig(router) {
1090
+ const newHomeRoutes = this.getRegisteredRoutes(); // your 3 home entries
1091
+ // Filter the original routes to drop the old home placeholders.
1092
+ // We know your dynamic routes always have path === '' or ':app'
1093
+ // or carry a `data.key` matching one of your home-page keys.
1094
+ const otherRoutes = (this.originalConfig ?? []).filter((r) => r.path !== '' && r.path !== ':app' && !(r.data && typeof r.data['key'] === 'string'));
1095
+ // Build the new merged tree
1096
+ const merged = [...newHomeRoutes, ...otherRoutes];
1097
+ // TODO: check this for custom menu like :app/terms
1098
+ router.resetConfig(merged);
1099
+ }
1100
+ async navigateTo() {
1101
+ // wait for the router to be initialized
1102
+ setTimeout(() => {
1103
+ const router = this.injector.get(Router);
1104
+ const current = this.getCurrent();
1105
+ router.navigate([current.path], { onSameUrlNavigation: 'reload' });
1106
+ }, 100);
1107
+ }
1108
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1109
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageService, providedIn: 'root' }); }
1110
+ }
1111
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageService, decorators: [{
1112
+ type: Injectable,
1113
+ args: [{
1114
+ providedIn: 'root',
1115
+ }]
1116
+ }], ctorParameters: () => [] });
1117
+
1118
+ function dynamicRoutesFactory() {
1119
+ const service = inject(AXPHomePageService);
1120
+ return service.getRegisteredRoutes();
1121
+ }
1122
+ function provideDynamicHomePage() {
1123
+ return makeEnvironmentProviders([
1124
+ {
1125
+ provide: ROUTES,
1126
+ useFactory: dynamicRoutesFactory,
1127
+ multi: true
1128
+ }
1129
+ ]);
1130
+ }
1131
+
1132
+ class AXPHomePageSettingProvider {
1133
+ constructor(injector) {
1134
+ this.injector = injector;
1135
+ this.translateService = this.injector.get(AXTranslationService);
1136
+ this.homePageService = this.injector.get(AXPHomePageService);
1137
+ this.defaultHomePageKey = inject(AXP_HOME_PAGE_DEFAULT_KEY, { optional: true }) ?? 'home';
1138
+ }
1139
+ async provide(context) {
1140
+ const trans = async (key) => await this.translateService.translateAsync(`@general:settings.${key}`);
1141
+ const list = await this.homePageService.getRegisteredList().map((c) => ({ id: c.key, title: c.title }));
1142
+ if (list.length === 0) {
1143
+ return;
1144
+ }
1145
+ // Define the 'General Settings' group
1146
+ context
1147
+ .addGroup('general', await trans('general.title'), await trans('general.description'), 'fa-light fa-palette')
1148
+ // Add the 'Startup' section
1149
+ .addSection('startup', await trans('general.startup.title'), await trans('general.startup.description'))
1150
+ // Add the 'Home Page' setting
1151
+ .addSetting({
1152
+ key: AXPHomePageSettings.UserHomePath,
1153
+ title: await trans('general.startup.home-page.title'),
1154
+ scope: AXPPlatformScope.User,
1155
+ isInherited: true,
1156
+ defaultValue: this.defaultHomePageKey || list[0].id,
1157
+ valueTransforms: objectKeyValueTransforms('id'),
1158
+ widget: {
1159
+ type: AXPWidgetsCatalog.select,
1160
+ options: {
1161
+ valueField: 'id',
1162
+ textField: 'title',
1163
+ dataSource: list,
1164
+ },
1165
+ },
1166
+ description: await trans('general.startup.home-page.description'),
1167
+ })
1168
+ // End the 'Startup' section
1169
+ .endSection()
1170
+ // End the 'General Settings' group
1171
+ .endGroup();
1172
+ }
1173
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageSettingProvider, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
1174
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageSettingProvider }); }
1175
+ }
1176
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageSettingProvider, decorators: [{
1177
+ type: Injectable
1178
+ }], ctorParameters: () => [{ type: i0.Injector }] });
1179
+
1180
+ class AXPHomePageModule {
1181
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1182
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageModule }); }
1183
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageModule, providers: [
1184
+ {
1185
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
1186
+ useClass: AXPHomePageSettingProvider,
1187
+ multi: true,
1188
+ },
1189
+ ] }); }
1190
+ }
1191
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageModule, decorators: [{
1192
+ type: NgModule,
1193
+ args: [{
1194
+ imports: [],
1195
+ providers: [
1196
+ {
1197
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
1198
+ useClass: AXPHomePageSettingProvider,
1199
+ multi: true,
1200
+ },
1201
+ ],
1202
+ }]
1203
+ }] });
1204
+
1205
+ class AXPDataProvider {
1206
+ }
1207
+
1208
+ class AXPCustomOperatorService {
1209
+ }
1210
+ class AXPCustomOperatorServiceImpl extends AXPCustomOperatorService {
1211
+ getCustomOperators() {
1212
+ return {};
1213
+ }
1214
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCustomOperatorServiceImpl, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1215
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCustomOperatorServiceImpl }); }
1216
+ }
1217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCustomOperatorServiceImpl, decorators: [{
1218
+ type: Injectable
1219
+ }] });
1220
+
1221
+ class AXPFilterOperatorMiddlewareService {
1222
+ }
1223
+ class AXPFilterOperatorMiddlewareServiceImpl extends AXPFilterOperatorMiddlewareService {
1224
+ constructor() {
1225
+ super(...arguments);
1226
+ this.customOperatorService = inject(AXPCustomOperatorService);
1227
+ this.operators = {
1228
+ ...this.getDefaultOperators(),
1229
+ ...this.customOperatorService.getCustomOperators(),
1230
+ };
1231
+ }
1232
+ transformFilters(filters) {
1233
+ return filters.map((filter) => this.transformFilter(filter));
1234
+ }
1235
+ transformFilter(filter) {
1236
+ const { operator, value, filters, field } = filter;
1237
+ // Find the operator (either default or custom)
1238
+ const filterOperator = this.operators[operator?.type ?? ''] || null;
1239
+ // Start by transforming the filter itself
1240
+ const transformedFilter = {
1241
+ ...filter, // Keep the original filter structure
1242
+ operator: filterOperator ? filterOperator : operator, // Add operator name
1243
+ };
1244
+ // If the filter contains nested filters, recursively transform them
1245
+ if (filters && filters.length > 0) {
1246
+ transformedFilter.filters = this.transformFilters(filters); // Recursively transform nested filters
1247
+ }
1248
+ return transformedFilter;
1249
+ }
1250
+ getOperator(key) {
1251
+ return this.operators[key];
1252
+ }
1253
+ // Helper function to return the default operators
1254
+ getDefaultOperators() {
1255
+ return ALL_DEFAULT_OPERATORS.reduce((acc, operator) => {
1256
+ acc[operator.name] = {
1257
+ type: operator.name,
1258
+ };
1259
+ return acc;
1260
+ }, {});
1261
+ }
1262
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFilterOperatorMiddlewareServiceImpl, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
1263
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFilterOperatorMiddlewareServiceImpl }); }
1264
+ }
1265
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFilterOperatorMiddlewareServiceImpl, decorators: [{
1266
+ type: Injectable
1267
+ }] });
1268
+
1269
+ class AXPErrorHandlerRegistryService {
1270
+ constructor(injector) {
1271
+ this.injector = injector;
1272
+ this.errorHandlers = [];
1273
+ }
1274
+ register(...plugins) {
1275
+ plugins.forEach(t => {
1276
+ const childInjector = Injector.create({ providers: [{ provide: t, useClass: t, deps: [] }], parent: this.injector });
1277
+ const handler = childInjector.get(t);
1278
+ if (handler) {
1279
+ this.errorHandlers.push(handler);
1280
+ }
1281
+ });
1282
+ }
1283
+ get handlers() {
1284
+ return this.errorHandlers;
1285
+ }
1286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPErrorHandlerRegistryService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
1287
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPErrorHandlerRegistryService, providedIn: 'root' }); }
1288
+ }
1289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPErrorHandlerRegistryService, decorators: [{
1290
+ type: Injectable,
1291
+ args: [{
1292
+ providedIn: 'root'
1293
+ }]
1294
+ }], ctorParameters: () => [{ type: i0.Injector }] });
1295
+
1296
+ class AXPGlobalErrorHandler extends ErrorHandler {
1297
+ constructor(injector, registry) {
1298
+ super();
1299
+ this.injector = injector;
1300
+ this.registry = registry;
1301
+ }
1302
+ handleError(error) {
1303
+ const handleErrorRecursively = (index, error) => {
1304
+ const errorHandlers = this.registry.handlers;
1305
+ if (index < errorHandlers.length) {
1306
+ errorHandlers[index].handleError(error, (err) => {
1307
+ handleErrorRecursively(index + 1, err);
1308
+ });
1309
+ }
1310
+ else {
1311
+ super.handleError(error); // Fallback to default handler
1312
+ }
1313
+ };
1314
+ if (error.message?.startsWith('NG0100')) {
1315
+ //ignore it
1316
+ return;
1317
+ }
1318
+ handleErrorRecursively(0, error);
1319
+ }
1320
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, deps: [{ token: i0.Injector }, { token: AXPErrorHandlerRegistryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1321
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, providedIn: 'root' }); }
1322
+ }
1323
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, decorators: [{
1324
+ type: Injectable,
1325
+ args: [{ providedIn: 'root' }]
1326
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: AXPErrorHandlerRegistryService }] });
1327
+
1328
+ const AXP_TOKEN_DEFINITION_PROVIDER = new InjectionToken('AXP_TOKEN_DEFINITION_PROVIDER', {
1329
+ factory: () => [],
1330
+ });
1331
+
1332
+ //#region ---- Imports ----
1333
+ //#endregion
1334
+ class AXPTokenDefinitionService {
1335
+ constructor() {
1336
+ //#region ---- Providers & Caches ----
1337
+ this.definitionProviders = inject(AXP_TOKEN_DEFINITION_PROVIDER, { optional: true }) || [];
1338
+ /** Cache for definitions by name. */
1339
+ this.definitionsByName = new Map();
1340
+ }
1341
+ //#endregion
1342
+ //#region ---- Public API ----
1343
+ /**
1344
+ * Returns a token definition by its name.
1345
+ * First checks the cache, then queries all providers if not found.
1346
+ * @param name The token name.
1347
+ * @returns The token definition if found, undefined otherwise.
1348
+ */
1349
+ async getDefinition(name) {
1350
+ // Check cache first
1351
+ if (this.definitionsByName.has(name)) {
1352
+ return this.definitionsByName.get(name);
1353
+ }
1354
+ // Not in cache, query providers
1355
+ // Resolve all providers (some may be promises, some may be arrays)
1356
+ const resolvedProviders = await Promise.all(this.definitionProviders);
1357
+ // Flatten the array - some providers may be arrays of providers (e.g., dynamic token providers)
1358
+ const flattenedProviders = [];
1359
+ for (const provider of resolvedProviders) {
1360
+ if (Array.isArray(provider)) {
1361
+ // If provider is an array, add all items
1362
+ flattenedProviders.push(...provider);
1363
+ }
1364
+ else if (provider) {
1365
+ // If provider is a single provider, add it
1366
+ flattenedProviders.push(provider);
1367
+ }
1368
+ }
1369
+ const match = flattenedProviders.find(def => def?.name === name);
1370
+ if (match) {
1371
+ this.definitionsByName.set(name, match);
1372
+ return match;
1373
+ }
1374
+ return undefined;
1375
+ }
1376
+ /**
1377
+ * Gets the resolved value of a token by its name.
1378
+ * @param name The token name.
1379
+ * @returns The resolved token value, or undefined if the token is not found.
1380
+ */
1381
+ async getValue(name) {
1382
+ const definition = await this.getDefinition(name);
1383
+ if (definition) {
1384
+ return await definition.execute();
1385
+ }
1386
+ return undefined;
1387
+ }
1388
+ //#endregion
1389
+ //#region ---- Cache Management ----
1390
+ /** Clears the definitions by name cache. */
1391
+ clearDefinitionsCache() {
1392
+ this.definitionsByName.clear();
1393
+ }
1394
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTokenDefinitionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1395
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTokenDefinitionService, providedIn: 'root' }); }
1396
+ }
1397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPTokenDefinitionService, decorators: [{
1398
+ type: Injectable,
1399
+ args: [{
1400
+ providedIn: 'root',
1401
+ }]
1402
+ }] });
1403
+
1404
+ class AXPTokenEvaluatorScopeProvider {
1405
+ constructor() {
1406
+ this.tokenService = inject(AXPTokenDefinitionService);
1407
+ }
1408
+ async provide(context) {
1409
+ context.addScope('tokens', {
1410
+ get: async (name) => {
1411
+ return await this.tokenService.getValue(name);
1412
+ }
1413
+ });
1414
+ }
1415
+ }
1416
+
1417
+ class AXPStickyDirective {
1418
+ get isSticky() {
1419
+ return this._isSticky;
1420
+ }
1421
+ set isSticky(value) {
1422
+ if (this._isSticky !== value) {
1423
+ this._isSticky = value;
1424
+ this.isStickyChange.emit(value);
1425
+ }
1426
+ }
1427
+ constructor(element, renderer, zone, cdr) {
1428
+ this.element = element;
1429
+ this.renderer = renderer;
1430
+ this.zone = zone;
1431
+ this.cdr = cdr;
1432
+ this.stickyOffset = 100;
1433
+ this.isStickyChange = new EventEmitter();
1434
+ this._isSticky = false;
1435
+ this.onWindowResize = () => {
1436
+ this.applyStickyStateFromScrollPosition();
1437
+ };
1438
+ this.onParentScroll = () => {
1439
+ this.applyStickyStateFromScrollPosition();
1440
+ };
1441
+ }
1442
+ ngAfterViewInit() {
1443
+ this.initSticky();
1444
+ // Add mutation observer for dynamic content
1445
+ this.mutationObserver = new MutationObserver(() => {
1446
+ this.applyStickyStateFromScrollPosition();
1447
+ });
1448
+ this.mutationObserver.observe(this.element.nativeElement, {
1449
+ childList: true,
1450
+ subtree: true,
1451
+ });
1452
+ window.addEventListener('resize', this.onWindowResize);
1453
+ }
1454
+ initSticky() {
1455
+ if (this.stickyParent instanceof HTMLElement) {
1456
+ this.parentElement = this.stickyParent;
1457
+ }
1458
+ else {
1459
+ this.parentElement = document.querySelector(this.stickyParent) || window;
1460
+ }
1461
+ this.targetElement = document.querySelector(this.stickyTarget) || this.element.nativeElement;
1462
+ this.parentElement.addEventListener('scroll', this.onParentScroll);
1463
+ this.applyStickyStateFromScrollPosition();
1464
+ }
1465
+ getScrollTop() {
1466
+ return this.parentElement === window ? window.scrollY : this.parentElement.scrollTop;
1467
+ }
1468
+ /**
1469
+ * Toggle stuck styling only while this element is visually pinned (matches `position: sticky; top: 0`).
1470
+ * Scroll-offset thresholds would stay true for every section already passed, so multiple stacked stickies
1471
+ * would all keep `--stuck`; geometry fixes that.
1472
+ */
1473
+ computeShouldStick() {
1474
+ if (this.getScrollTop() <= 0) {
1475
+ return false;
1476
+ }
1477
+ const tRect = this.targetElement.getBoundingClientRect();
1478
+ const epsilon = 3;
1479
+ let limitY;
1480
+ if (this.parentElement === window) {
1481
+ limitY = this.stickyOffset;
1482
+ }
1483
+ else {
1484
+ limitY = this.parentElement.getBoundingClientRect().top;
1485
+ }
1486
+ return tRect.top <= limitY + epsilon && tRect.top >= limitY - epsilon;
1487
+ }
1488
+ applyStickyStateFromScrollPosition() {
1489
+ this.zone.runOutsideAngular(() => {
1490
+ const shouldStick = this.computeShouldStick();
1491
+ if (shouldStick !== this.isSticky) {
1492
+ this.zone.run(() => {
1493
+ this.isSticky = shouldStick;
1494
+ this.toggleStickyClasses(shouldStick);
1495
+ this.cdr.markForCheck();
1496
+ });
1497
+ }
1498
+ });
1499
+ }
1500
+ toggleStickyClasses(isSticky) {
1501
+ const classes = this.stickyClass.split(' ').filter(Boolean);
1502
+ classes.forEach((className) => {
1503
+ if (isSticky) {
1504
+ this.renderer.addClass(this.targetElement, className);
1505
+ }
1506
+ else {
1507
+ this.renderer.removeClass(this.targetElement, className);
1508
+ }
1509
+ });
1510
+ }
1511
+ ngOnDestroy() {
1512
+ this.parentElement.removeEventListener('scroll', this.onParentScroll);
1513
+ window.removeEventListener('resize', this.onWindowResize);
1514
+ if (this.mutationObserver) {
1515
+ this.mutationObserver.disconnect();
1516
+ }
1517
+ }
1518
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStickyDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1519
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: AXPStickyDirective, isStandalone: true, selector: "[axpSticky]", inputs: { stickyClass: ["axpSticky", "stickyClass"], stickyOffset: "stickyOffset", stickyParent: "stickyParent", stickyTarget: "stickyTarget" }, outputs: { isStickyChange: "isStickyChange" }, exportAs: ["axpSticky"], ngImport: i0 }); }
1520
+ }
1521
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStickyDirective, decorators: [{
1522
+ type: Directive,
1523
+ args: [{
1524
+ selector: '[axpSticky]',
1525
+ exportAs: 'axpSticky',
1526
+ standalone: true,
1527
+ }]
1528
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }], propDecorators: { stickyClass: [{
1529
+ type: Input,
1530
+ args: ['axpSticky']
1531
+ }], stickyOffset: [{
1532
+ type: Input,
1533
+ args: ['stickyOffset']
1534
+ }], isStickyChange: [{
1535
+ type: Output
1536
+ }], stickyParent: [{
1537
+ type: Input
1538
+ }], stickyTarget: [{
1539
+ type: Input
1540
+ }] } });
1541
+
1542
+ //#region ---- Menu Context Builder ----
1543
+ /**
1544
+ * Creates a rich context for menu manipulation
1545
+ * Similar to entity modifier context pattern
1546
+ */
1547
+ function createMenuContext(items) {
1548
+ const context = {
1549
+ get items() {
1550
+ return items;
1551
+ },
1552
+ find(nameOrPattern) {
1553
+ if (typeof nameOrPattern === 'string') {
1554
+ return context.findByName(nameOrPattern);
1555
+ }
1556
+ const found = context.findByPattern(nameOrPattern);
1557
+ return found.length > 0 ? found[0] : createEmptyFinder();
1558
+ },
1559
+ findByName(name) {
1560
+ return createMenuItemFinder(items, name);
1561
+ },
1562
+ findByPattern(pattern) {
1563
+ const regex = typeof pattern === 'string' ? wildcardToRegex(pattern) : pattern;
1564
+ const results = [];
1565
+ const searchRecursive = (itemList) => {
1566
+ for (const item of itemList) {
1567
+ if (item.name && regex.test(item.name)) {
1568
+ results.push(createMenuItemFinder(items, item.name));
1569
+ }
1570
+ if (item.children) {
1571
+ searchRecursive(item.children);
1572
+ }
1573
+ }
1574
+ };
1575
+ searchRecursive(items);
1576
+ return results;
1577
+ },
1578
+ add(...newItems) {
1579
+ items.push(...newItems);
1580
+ return context;
1581
+ },
1582
+ remove(predicate) {
1583
+ removeRecursive(items, predicate);
1584
+ return context;
1585
+ },
1586
+ sort() {
1587
+ sortItemsRecursively(items);
1588
+ return context;
1589
+ },
1590
+ toArray() {
1591
+ return items;
1592
+ },
1593
+ };
1594
+ return context;
1595
+ }
1596
+ //#endregion
1597
+ //#region ---- Menu Item Finder Implementation ----
1598
+ /**
1599
+ * Creates a finder for a specific menu item
1600
+ */
1601
+ function createMenuItemFinder(rootItems, targetName) {
1602
+ const findItemWithParent = (items, name, parent = { items: rootItems }) => {
1603
+ for (const item of items) {
1604
+ if (item.name === name) {
1605
+ return { item, parent };
1606
+ }
1607
+ if (item.children) {
1608
+ const result = findItemWithParent(item.children, name, { items: item.children });
1609
+ if (result.item) {
1610
+ return result;
1611
+ }
1612
+ }
1613
+ }
1614
+ return { item: undefined, parent };
1615
+ };
1616
+ const finder = {
1617
+ get() {
1618
+ return findItemWithParent(rootItems, targetName).item;
1619
+ },
1620
+ exists() {
1621
+ return finder.get() !== undefined;
1622
+ },
1623
+ update(updater) {
1624
+ const { item } = findItemWithParent(rootItems, targetName);
1625
+ if (item) {
1626
+ const updates = typeof updater === 'function' ? updater(item) : updater;
1627
+ Object.assign(item, updates);
1628
+ }
1629
+ return finder;
1630
+ },
1631
+ remove() {
1632
+ const { item, parent } = findItemWithParent(rootItems, targetName);
1633
+ if (item) {
1634
+ const index = parent.items.indexOf(item);
1635
+ if (index !== -1) {
1636
+ parent.items.splice(index, 1);
1637
+ }
1638
+ }
1639
+ return finder;
1640
+ },
1641
+ hide() {
1642
+ // Hide by removing the item from menu
1643
+ return finder.remove();
1644
+ },
1645
+ show() {
1646
+ // Show is a no-op since items are visible by default
1647
+ // To truly implement show, we'd need to track removed items and re-add them
1648
+ console.warn('show() is not fully implemented - items are visible by default');
1649
+ return finder;
1650
+ },
1651
+ setPriority(priority) {
1652
+ return finder.update({ priority });
1653
+ },
1654
+ addChildren(...children) {
1655
+ const { item } = findItemWithParent(rootItems, targetName);
1656
+ if (item) {
1657
+ item.children = item.children || [];
1658
+ item.children.push(...children);
1659
+ }
1660
+ return finder;
1661
+ },
1662
+ removeChildren(predicate) {
1663
+ const { item } = findItemWithParent(rootItems, targetName);
1664
+ if (item && item.children) {
1665
+ item.children = item.children.filter((c) => !predicate(c));
1666
+ }
1667
+ return finder;
1668
+ },
1669
+ moveTo(parentName) {
1670
+ const { item, parent: oldParent } = findItemWithParent(rootItems, targetName);
1671
+ if (!item) {
1672
+ return finder;
1673
+ }
1674
+ // Remove from old parent
1675
+ const oldIndex = oldParent.items.indexOf(item);
1676
+ if (oldIndex !== -1) {
1677
+ oldParent.items.splice(oldIndex, 1);
1678
+ }
1679
+ // Add to new parent
1680
+ if (!parentName || parentName === '') {
1681
+ // Move to root (handles null, undefined, and empty string)
1682
+ rootItems.push(item);
1683
+ }
1684
+ else {
1685
+ const { item: newParentItem } = findItemWithParent(rootItems, parentName);
1686
+ if (newParentItem) {
1687
+ newParentItem.children = newParentItem.children || [];
1688
+ newParentItem.children.push(item);
1689
+ }
1690
+ }
1691
+ return finder;
1692
+ },
1693
+ insertBefore(...items) {
1694
+ const { item, parent } = findItemWithParent(rootItems, targetName);
1695
+ if (item) {
1696
+ const index = parent.items.indexOf(item);
1697
+ if (index !== -1) {
1698
+ parent.items.splice(index, 0, ...items);
1699
+ }
1700
+ }
1701
+ return finder;
1702
+ },
1703
+ insertAfter(...items) {
1704
+ const { item, parent } = findItemWithParent(rootItems, targetName);
1705
+ if (item) {
1706
+ const index = parent.items.indexOf(item);
1707
+ if (index !== -1) {
1708
+ parent.items.splice(index + 1, 0, ...items);
1709
+ }
1710
+ }
1711
+ return finder;
1712
+ },
1713
+ };
1714
+ return finder;
1715
+ }
1716
+ /**
1717
+ * Creates an empty finder for items not found
1718
+ */
1719
+ function createEmptyFinder() {
1720
+ return {
1721
+ get: () => undefined,
1722
+ exists: () => false,
1723
+ update: () => createEmptyFinder(),
1724
+ remove: () => createEmptyFinder(),
1725
+ hide: () => createEmptyFinder(),
1726
+ show: () => createEmptyFinder(),
1727
+ setPriority: () => createEmptyFinder(),
1728
+ addChildren: () => createEmptyFinder(),
1729
+ removeChildren: () => createEmptyFinder(),
1730
+ moveTo: () => createEmptyFinder(),
1731
+ insertBefore: () => createEmptyFinder(),
1732
+ insertAfter: () => createEmptyFinder(),
1733
+ };
1734
+ }
1735
+ //#endregion
1736
+ //#region ---- Helper Functions ----
1737
+ /**
1738
+ * Converts wildcard pattern to regex
1739
+ */
1740
+ function wildcardToRegex(pattern) {
1741
+ const escaped = pattern.replace(/[.+?^${}()|\[\]\\]/g, '\\$&');
1742
+ const regexStr = `^${escaped.replace(/\*/g, '.*')}$`;
1743
+ return new RegExp(regexStr);
1744
+ }
1745
+ /**
1746
+ * Recursively removes items matching predicate
1747
+ */
1748
+ function removeRecursive(items, predicate) {
1749
+ for (let i = items.length - 1; i >= 0; i--) {
1750
+ const item = items[i];
1751
+ if (predicate(item)) {
1752
+ items.splice(i, 1);
1753
+ }
1754
+ else if (item.children) {
1755
+ removeRecursive(item.children, predicate);
1756
+ }
1757
+ }
1758
+ }
1759
+ /**
1760
+ * Recursively sorts items by priority
1761
+ */
1762
+ function sortItemsRecursively(items) {
1763
+ items.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
1764
+ items.forEach((item) => {
1765
+ if (item.children && item.children.length > 0) {
1766
+ sortItemsRecursively(item.children);
1767
+ }
1768
+ });
1769
+ }
1770
+ //#endregion
1771
+
1772
+ /**
1773
+ * Injection token for menu middlewares (multi-provider)
1774
+ */
1775
+ const AXP_MENU_MIDDLEWARE = new InjectionToken('AXP_MENU_MIDDLEWARE');
1776
+ //#endregion
1777
+
1778
+ //#region ---- Menu Middleware Registry ----
1779
+ /**
1780
+ * Central service for managing menu middlewares with priority-based ordering
1781
+ * Similar to token registry pattern used in identifier-management
1782
+ */
1783
+ class AXPMenuMiddlewareRegistry {
1784
+ constructor() {
1785
+ //#region ---- Fields ----
1786
+ /**
1787
+ * Manually registered middlewares
1788
+ */
1789
+ this.manualMiddlewares = new Map();
1790
+ /**
1791
+ * Provider-based middlewares (multi-provider injection)
1792
+ */
1793
+ this.providerMiddlewares = inject(AXP_MENU_MIDDLEWARE, { optional: true }) ?? [];
1794
+ }
1795
+ //#endregion
1796
+ //#region ---- Registration Methods ----
1797
+ /**
1798
+ * Manually register a middleware
1799
+ * @param middleware - The middleware to register
1800
+ */
1801
+ register(middleware) {
1802
+ const name = middleware.name || `middleware_${Date.now()}_${Math.random()}`;
1803
+ const existing = this.manualMiddlewares.get(name);
1804
+ if (!existing || (middleware.priority ?? 0) > (existing.priority ?? 0)) {
1805
+ this.manualMiddlewares.set(name, middleware);
1806
+ }
1807
+ }
1808
+ /**
1809
+ * Unregister a middleware by name
1810
+ * @param name - The name of the middleware to remove
1811
+ */
1812
+ unregister(name) {
1813
+ this.manualMiddlewares.delete(name);
1814
+ }
1815
+ /**
1816
+ * Get a specific middleware by name
1817
+ * @param name - The middleware name
1818
+ */
1819
+ get(name) {
1820
+ // Provider-provided middlewares take precedence
1821
+ const fromProvider = this.providerMiddlewares
1822
+ .filter((m) => m.name === name)
1823
+ .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0))[0];
1824
+ if (fromProvider) {
1825
+ return fromProvider;
1826
+ }
1827
+ return this.manualMiddlewares.get(name);
1828
+ }
1829
+ /**
1830
+ * Get all middlewares sorted by priority (highest first)
1831
+ * Combines provider-based and manually registered middlewares
1832
+ */
1833
+ list() {
1834
+ const map = new Map();
1835
+ // Helper to add middleware, respecting priority
1836
+ const addMiddleware = (m) => {
1837
+ const name = m.name || `anonymous_${Date.now()}`;
1838
+ const existing = map.get(name);
1839
+ if (!existing || (m.priority ?? 0) > (existing.priority ?? 0)) {
1840
+ map.set(name, m);
1841
+ }
1842
+ };
1843
+ // Add provider middlewares first (higher precedence)
1844
+ this.providerMiddlewares.forEach(addMiddleware);
1845
+ // Add manual middlewares
1846
+ Array.from(this.manualMiddlewares.values()).forEach(addMiddleware);
1847
+ // Return sorted by priority (highest first)
1848
+ return Array.from(map.values()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
1849
+ }
1850
+ /**
1851
+ * Check if a middleware exists
1852
+ * @param name - The middleware name
1853
+ */
1854
+ exists(name) {
1855
+ return this.get(name) !== undefined;
1856
+ }
1857
+ /**
1858
+ * Clear all manually registered middlewares
1859
+ * Provider-based middlewares are not affected
1860
+ */
1861
+ clear() {
1862
+ this.manualMiddlewares.clear();
1863
+ }
1864
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuMiddlewareRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1865
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuMiddlewareRegistry, providedIn: 'root' }); }
1866
+ }
1867
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuMiddlewareRegistry, decorators: [{
1868
+ type: Injectable,
1869
+ args: [{ providedIn: 'root' }]
1870
+ }] });
1871
+
1872
+ const AXP_MENU_PROVIDER = new InjectionToken('AXP_MENU_PROVIDER');
1873
+ //TODO: check performance of this service
1874
+ class AXPMenuProviderService {
1875
+ constructor() {
1876
+ //#region ---- Dependencies ----
1877
+ this.providers = inject(AXP_MENU_PROVIDER, { optional: true });
1878
+ this.middlewareRegistry = inject(AXPMenuMiddlewareRegistry);
1879
+ //#endregion
1880
+ //#region ---- State ----
1881
+ this.cache = null;
1882
+ this.pendingInserts = [];
1883
+ this.pendingRemovals = [];
1884
+ this.pendingUpdates = [];
1885
+ this.pendingAdditions = [];
1886
+ this.pendingMoves = [];
1887
+ /**
1888
+ * Observable for menu reload events
1889
+ * Emits when menu cache is cleared and consumers should reload
1890
+ */
1891
+ this.menuReloadSubject = new Subject();
1892
+ this.menuReload$ = this.menuReloadSubject.asObservable();
1893
+ }
1894
+ //#endregion
1895
+ //#region ---- Public API ----
1896
+ /**
1897
+ * Get menu items with middlewares applied (for end-user display)
1898
+ */
1899
+ async items() {
1900
+ // Return cached items if available
1901
+ if (this.cache) {
1902
+ return this.cache;
1903
+ }
1904
+ const items = [];
1905
+ const context = this.createMenuProviderContext(items);
1906
+ // Load providers from DI tokens
1907
+ if (Array.isArray(this.providers)) {
1908
+ for (const provider of this.providers) {
1909
+ if (provider instanceof Promise) {
1910
+ // If provider is a promise, resolve it
1911
+ const resolvedProvider = await provider;
1912
+ await resolvedProvider.provide(context);
1913
+ }
1914
+ else {
1915
+ // If provider is a direct instance, use it directly
1916
+ await provider.provide(context);
1917
+ }
1918
+ // Apply pending operations after each provider so subsequent providers
1919
+ // can find items added by earlier providers (e.g. Tokens under Data Definitions)
1920
+ this.applyPendingOperations(items);
1921
+ }
1922
+ }
1923
+ // Sort items by priority
1924
+ items.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
1925
+ // Apply middlewares using registry (sorted by priority)
1926
+ await this.applyMiddlewares(items);
1927
+ // ADD level property to items
1928
+ setMenuItemMeta(items);
1929
+ // Cache the computed items
1930
+ this.cache = items;
1931
+ return items;
1932
+ }
1933
+ /**
1934
+ * Get raw menu items WITHOUT middleware applied (for management/editing)
1935
+ * Used by menu management pages to show original items before customization
1936
+ */
1937
+ async rawItems() {
1938
+ const items = [];
1939
+ const context = this.createMenuProviderContext(items);
1940
+ // Load providers from DI tokens
1941
+ if (Array.isArray(this.providers)) {
1942
+ for (const provider of this.providers) {
1943
+ if (provider instanceof Promise) {
1944
+ // If provider is a promise, resolve it
1945
+ const resolvedProvider = await provider;
1946
+ await resolvedProvider.provide(context);
1947
+ }
1948
+ else {
1949
+ // If provider is a direct instance, use it directly
1950
+ await provider.provide(context);
1951
+ }
1952
+ // Apply pending operations after each provider
1953
+ this.applyPendingOperations(items);
1954
+ }
1955
+ }
1956
+ // Sort items by priority
1957
+ items.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
1958
+ // ADD level property to items (but NO middleware)
1959
+ setMenuItemMeta(items);
1960
+ return items;
1961
+ }
1962
+ /**
1963
+ * Clear the cache to force reload of menu items
1964
+ * Notifies all subscribers to reload their menu data
1965
+ */
1966
+ clearCache() {
1967
+ this.cache = null;
1968
+ this.pendingInserts = [];
1969
+ this.pendingRemovals = [];
1970
+ this.pendingUpdates = [];
1971
+ this.pendingAdditions = [];
1972
+ this.pendingMoves = [];
1973
+ // Notify subscribers that menu should be reloaded
1974
+ this.menuReloadSubject.next();
1975
+ }
1976
+ //#endregion
1977
+ //#region ---- Private Methods ----
1978
+ /**
1979
+ * Apply middlewares in priority order using the enhanced context API
1980
+ */
1981
+ async applyMiddlewares(items) {
1982
+ const middlewares = this.middlewareRegistry.list();
1983
+ for (const middleware of middlewares) {
1984
+ try {
1985
+ const context = createMenuContext(items);
1986
+ await middleware.process(context);
1987
+ // The context mutates the items array, so no need to reassign
1988
+ }
1989
+ catch (error) {
1990
+ console.error(`Error in menu middleware ${middleware.name || 'anonymous'}:`, error);
1991
+ }
1992
+ }
1993
+ }
1994
+ /**
1995
+ * Create provider context for menu providers
1996
+ */
1997
+ createMenuProviderContext(items) {
1998
+ return {
1999
+ addItems: (newItems) => {
2000
+ for (const newItem of newItems) {
2001
+ if (newItem.name) {
2002
+ const existingItem = this.findItemByName(items, newItem.name);
2003
+ if (existingItem) {
2004
+ // Update existing item, merging properties
2005
+ this.mergeMenuItem(existingItem, newItem);
2006
+ }
2007
+ else {
2008
+ // Add new item if it doesn't exist
2009
+ items.push(newItem);
2010
+ }
2011
+ }
2012
+ else {
2013
+ // Add item without name (no way to check for duplicates)
2014
+ items.push(newItem);
2015
+ }
2016
+ }
2017
+ },
2018
+ find: (target) => {
2019
+ const foundItemInfo = this.findItemWithParent(items, target);
2020
+ const exists = foundItemInfo.foundItem !== null;
2021
+ return {
2022
+ exists,
2023
+ insert: (newItems, position) => {
2024
+ this.pendingInserts.push({ target, newItems, position });
2025
+ },
2026
+ remove: () => {
2027
+ this.pendingRemovals.push(target);
2028
+ },
2029
+ update: (updatedItem) => {
2030
+ this.pendingUpdates.push({ target, updatedItem });
2031
+ },
2032
+ addItems: (newItems) => {
2033
+ this.pendingAdditions.push({ target, newItems });
2034
+ },
2035
+ moveTo: (destination, position = 'inside') => {
2036
+ this.pendingMoves.push({
2037
+ source: target,
2038
+ destination,
2039
+ position: position ?? 'inside',
2040
+ });
2041
+ },
2042
+ };
2043
+ }
2044
+ };
2045
+ }
2046
+ applyPendingOperations(items) {
2047
+ for (const { target, newItems, position } of this.pendingInserts) {
2048
+ const foundItemInfo = this.findItemWithParent(items, target);
2049
+ const { foundItem, parentItems } = foundItemInfo;
2050
+ if (!foundItem) {
2051
+ console.warn(`Target "${target}" not found, appending items.`);
2052
+ items.push(...newItems);
2053
+ }
2054
+ else {
2055
+ if (position === 'inside') {
2056
+ if (!foundItem.children) {
2057
+ foundItem.children = [];
2058
+ }
2059
+ // Check for duplicates by name and merge or add
2060
+ for (const newItem of newItems) {
2061
+ if (newItem.name) {
2062
+ const existingChild = this.findItemByName(foundItem.children, newItem.name);
2063
+ if (existingChild) {
2064
+ this.mergeMenuItem(existingChild, newItem);
2065
+ }
2066
+ else {
2067
+ foundItem.children.push(newItem);
2068
+ }
2069
+ }
2070
+ else {
2071
+ foundItem.children.push(newItem);
2072
+ }
2073
+ }
2074
+ }
2075
+ else {
2076
+ // For 'before' and 'after', check for duplicates in parent items
2077
+ const itemsToInsert = [];
2078
+ for (const newItem of newItems) {
2079
+ if (newItem.name) {
2080
+ const existingItem = this.findItemByName(parentItems, newItem.name);
2081
+ if (existingItem) {
2082
+ this.mergeMenuItem(existingItem, newItem);
2083
+ }
2084
+ else {
2085
+ itemsToInsert.push(newItem);
2086
+ }
2087
+ }
2088
+ else {
2089
+ itemsToInsert.push(newItem);
2090
+ }
2091
+ }
2092
+ if (itemsToInsert.length > 0) {
2093
+ const index = parentItems.indexOf(foundItem);
2094
+ const insertPosition = position === 'before' ? index : index + 1;
2095
+ parentItems.splice(insertPosition, 0, ...itemsToInsert);
2096
+ }
2097
+ }
2098
+ }
2099
+ }
2100
+ for (const target of this.pendingRemovals) {
2101
+ const foundItemInfo = this.findItemWithParent(items, target);
2102
+ const { foundItem, parentItems } = foundItemInfo;
2103
+ if (!foundItem) {
2104
+ console.warn(`Target "${target}" not found, nothing to remove.`);
2105
+ }
2106
+ else {
2107
+ const index = parentItems.indexOf(foundItem);
2108
+ parentItems.splice(index, 1);
2109
+ }
2110
+ }
2111
+ for (const { target, updatedItem } of this.pendingUpdates) {
2112
+ const foundItemInfo = this.findItemWithParent(items, target);
2113
+ const { foundItem } = foundItemInfo;
2114
+ if (!foundItem) {
2115
+ console.warn(`Target "${target}" not found, nothing to update.`);
2116
+ }
2117
+ else {
2118
+ Object.assign(foundItem, updatedItem);
2119
+ }
2120
+ }
2121
+ for (const { target, newItems } of this.pendingAdditions) {
2122
+ const foundItemInfo = this.findItemWithParent(items, target);
2123
+ const { foundItem } = foundItemInfo;
2124
+ if (!foundItem) {
2125
+ console.warn(`Target "${target}" not found, nothing to add items to.`);
2126
+ }
2127
+ else {
2128
+ if (!foundItem.children) {
2129
+ foundItem.children = [];
2130
+ }
2131
+ // Check for duplicates by name and merge or add
2132
+ for (const newItem of newItems) {
2133
+ if (newItem.name) {
2134
+ const existingChild = this.findItemByName(foundItem.children, newItem.name);
2135
+ if (existingChild) {
2136
+ this.mergeMenuItem(existingChild, newItem);
2137
+ }
2138
+ else {
2139
+ foundItem.children.push(newItem);
2140
+ }
2141
+ }
2142
+ else {
2143
+ foundItem.children.push(newItem);
2144
+ }
2145
+ }
2146
+ }
2147
+ }
2148
+ for (const move of this.pendingMoves) {
2149
+ this.applyPendingMove(items, move.source, move.destination, move.position);
2150
+ }
2151
+ // Clear pending operations after applying them
2152
+ this.pendingInserts = [];
2153
+ this.pendingRemovals = [];
2154
+ this.pendingUpdates = [];
2155
+ this.pendingAdditions = [];
2156
+ this.pendingMoves = [];
2157
+ }
2158
+ findItemWithParent(items, target, parentItems = items) {
2159
+ for (const item of items) {
2160
+ if (item.name === target) {
2161
+ return { foundItem: item, parentItems };
2162
+ }
2163
+ if (item.children) {
2164
+ const result = this.findItemWithParent(item.children, target, item.children);
2165
+ if (result.foundItem) {
2166
+ return result;
2167
+ }
2168
+ }
2169
+ }
2170
+ return { foundItem: null, parentItems: items };
2171
+ }
2172
+ /**
2173
+ * Find menu item by name in the items tree (recursive search)
2174
+ */
2175
+ findItemByName(items, name) {
2176
+ for (const item of items) {
2177
+ if (item.name === name) {
2178
+ return item;
2179
+ }
2180
+ if (item.children) {
2181
+ const found = this.findItemByName(item.children, name);
2182
+ if (found) {
2183
+ return found;
2184
+ }
2185
+ }
2186
+ }
2187
+ return null;
2188
+ }
2189
+ applyPendingMove(items, sourceName, destName, position) {
2190
+ if (sourceName === destName) {
2191
+ console.warn(`moveTo: source and destination are the same ("${sourceName}"), ignored.`);
2192
+ return;
2193
+ }
2194
+ const sourceInfo = this.findItemWithParent(items, sourceName);
2195
+ const { foundItem: sourceItem, parentItems: sourceParent } = sourceInfo;
2196
+ if (!sourceItem) {
2197
+ console.warn(`moveTo: source "${sourceName}" not found.`);
2198
+ return;
2199
+ }
2200
+ const destInfo = this.findItemWithParent(items, destName);
2201
+ const { foundItem: destItem, parentItems: destParent } = destInfo;
2202
+ if (!destItem) {
2203
+ console.warn(`moveTo: destination "${destName}" not found.`);
2204
+ return;
2205
+ }
2206
+ if (this.itemIsInSubtreeOf(sourceItem, destItem)) {
2207
+ console.warn(`moveTo: cannot move "${sourceName}" because "${destName}" is inside the source subtree.`);
2208
+ return;
2209
+ }
2210
+ const sourceIndex = sourceParent.indexOf(sourceItem);
2211
+ if (sourceIndex === -1) {
2212
+ console.warn(`moveTo: source "${sourceName}" not in parent list (inconsistent).`);
2213
+ return;
2214
+ }
2215
+ sourceParent.splice(sourceIndex, 1);
2216
+ if (position === 'inside') {
2217
+ if (!destItem.children) {
2218
+ destItem.children = [];
2219
+ }
2220
+ destItem.children.push(sourceItem);
2221
+ return;
2222
+ }
2223
+ const destIndexInParent = destParent.indexOf(destItem);
2224
+ if (destIndexInParent === -1) {
2225
+ console.warn(`moveTo: destination "${destName}" not in parent list, reverting source removal.`);
2226
+ sourceParent.splice(sourceIndex, 0, sourceItem);
2227
+ return;
2228
+ }
2229
+ const insertIndex = position === 'before' ? destIndexInParent : destIndexInParent + 1;
2230
+ destParent.splice(insertIndex, 0, sourceItem);
2231
+ }
2232
+ itemIsInSubtreeOf(root, candidate) {
2233
+ if (root === candidate) {
2234
+ return true;
2235
+ }
2236
+ if (!root.children?.length) {
2237
+ return false;
2238
+ }
2239
+ for (const child of root.children) {
2240
+ if (child === candidate) {
2241
+ return true;
2242
+ }
2243
+ if (this.itemIsInSubtreeOf(child, candidate)) {
2244
+ return true;
2245
+ }
2246
+ }
2247
+ return false;
2248
+ }
2249
+ /**
2250
+ * Merge new item properties into existing item, handling children merge
2251
+ */
2252
+ mergeMenuItem(existingItem, newItem) {
2253
+ // Merge top-level properties (newItem properties override existing only if defined)
2254
+ if (newItem.text !== undefined)
2255
+ existingItem.text = newItem.text;
2256
+ if (newItem.description !== undefined)
2257
+ existingItem.description = newItem.description;
2258
+ if (newItem.icon !== undefined)
2259
+ existingItem.icon = newItem.icon;
2260
+ if (newItem.path !== undefined)
2261
+ existingItem.path = newItem.path;
2262
+ if (newItem.priority !== undefined)
2263
+ existingItem.priority = newItem.priority;
2264
+ if (newItem.type !== undefined)
2265
+ existingItem.type = newItem.type;
2266
+ if (newItem.command !== undefined)
2267
+ existingItem.command = newItem.command;
2268
+ if (newItem.badgeKey !== undefined)
2269
+ existingItem.badgeKey = newItem.badgeKey;
2270
+ if (newItem.data !== undefined)
2271
+ existingItem.data = newItem.data;
2272
+ if (newItem.policy !== undefined)
2273
+ existingItem.policy = newItem.policy;
2274
+ // Merge children if both have children
2275
+ if (newItem.children && newItem.children.length > 0) {
2276
+ if (!existingItem.children) {
2277
+ existingItem.children = [];
2278
+ }
2279
+ // For each child in newItem, check if it exists by name and merge or add
2280
+ for (const newChild of newItem.children) {
2281
+ if (newChild.name) {
2282
+ const existingChild = this.findItemByName(existingItem.children, newChild.name);
2283
+ if (existingChild) {
2284
+ this.mergeMenuItem(existingChild, newChild);
2285
+ }
2286
+ else {
2287
+ existingItem.children.push(newChild);
2288
+ }
2289
+ }
2290
+ else {
2291
+ existingItem.children.push(newChild);
2292
+ }
2293
+ }
2294
+ }
2295
+ }
2296
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2297
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuProviderService, providedIn: 'root' }); }
2298
+ }
2299
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuProviderService, decorators: [{
2300
+ type: Injectable,
2301
+ args: [{ providedIn: 'root' }]
2302
+ }] });
2303
+ function setMenuItemMeta(items, parentIndex = '', depth = 0) {
2304
+ items.forEach((item, index) => {
2305
+ const currentIndex = parentIndex ? `${parentIndex}-${index}` : `${index}`;
2306
+ const hasChildren = !!(item.children && Array.isArray(item.children) && item.children.length > 0);
2307
+ item.meta = {
2308
+ index: currentIndex,
2309
+ isRoot: depth === 0,
2310
+ hasChildren,
2311
+ depth
2312
+ };
2313
+ if (hasChildren) {
2314
+ setMenuItemMeta(item.children, currentIndex, depth + 1);
2315
+ }
2316
+ });
2317
+ }
2318
+
2319
+ //#region ---- Imports ----
2320
+ //#endregion
2321
+ //#region ---- Helpers ----
2322
+ function flattenMenuItems(items, depth) {
2323
+ const rows = [];
2324
+ let index = 0;
2325
+ for (const it of items) {
2326
+ const fallback = `menu-${depth}-${index}`;
2327
+ index += 1;
2328
+ const id = it.name ?? it.path ?? fallback;
2329
+ rows.push({ id, title: it.text });
2330
+ if (it.children?.length) {
2331
+ rows.push(...flattenMenuItems(it.children, depth + 1));
2332
+ }
2333
+ }
2334
+ return rows;
2335
+ }
2336
+ //#endregion
2337
+ //#region ---- Menu items data source ----
2338
+ /**
2339
+ * Registered menu items (raw tree flattened) for select widgets via dataSource name {@link MENU_ITEMS_DATASOURCE_NAME}.
2340
+ */
2341
+ const MENU_ITEMS_DATASOURCE_NAME = 'platform-menu-items';
2342
+ /**
2343
+ * Data source definition for menu items from {@link AXPMenuProviderService#rawItems}.
2344
+ */
2345
+ class AXPMenuItemsDataSourceDefinition {
2346
+ constructor() {
2347
+ //#region ---- Services & Dependencies ----
2348
+ this.menuProviderService = inject(AXPMenuProviderService);
2349
+ //#endregion
2350
+ }
2351
+ //#endregion
2352
+ //#region ---- Public API ----
2353
+ async items() {
2354
+ return [
2355
+ {
2356
+ name: MENU_ITEMS_DATASOURCE_NAME,
2357
+ title: 'Menu items',
2358
+ source: () => new AXDataSource({
2359
+ key: 'id',
2360
+ load: async () => {
2361
+ const raw = await this.menuProviderService.rawItems();
2362
+ const list = flattenMenuItems(raw, 0);
2363
+ return { items: list, total: list.length };
2364
+ },
2365
+ byKey: async (key) => {
2366
+ const raw = await this.menuProviderService.rawItems();
2367
+ const list = flattenMenuItems(raw, 0);
2368
+ return list.find((item) => item.id === key);
2369
+ },
2370
+ pageSize: 1000,
2371
+ }),
2372
+ columns: [
2373
+ {
2374
+ name: 'id',
2375
+ title: 'ID',
2376
+ datatype: 'string',
2377
+ type: AXPWidgetsCatalog.text,
2378
+ },
2379
+ {
2380
+ name: 'title',
2381
+ title: 'Title',
2382
+ datatype: 'string',
2383
+ type: AXPWidgetsCatalog.text,
2384
+ },
2385
+ ],
2386
+ filters: [
2387
+ {
2388
+ field: 'title',
2389
+ title: 'Title',
2390
+ operator: { type: 'equal' },
2391
+ widget: { type: AXPWidgetsCatalog.text },
2392
+ filterType: { advance: true, inline: true },
2393
+ },
2394
+ ],
2395
+ textField: { name: 'title', title: 'Title' },
2396
+ valueField: { name: 'id', title: 'ID' },
2397
+ },
2398
+ ];
2399
+ }
2400
+ }
2401
+ //#endregion
2402
+
2403
+ //#region ---- Menu Middleware Provider Helper ----
2404
+ /**
2405
+ * Helper function to provide menu middlewares with proper DI setup
2406
+ * Similar to provideCommandMiddleware pattern
2407
+ *
2408
+ * @example
2409
+ * ```typescript
2410
+ * // In app.config.ts or module providers
2411
+ * export const appConfig: ApplicationConfig = {
2412
+ * providers: [
2413
+ * provideMenuMiddleware([
2414
+ * customizationMiddleware,
2415
+ * securityMiddleware,
2416
+ * loggingMiddleware
2417
+ * ])
2418
+ * ]
2419
+ * };
2420
+ * ```
2421
+ */
2422
+ function provideMenuMiddleware(middlewares) {
2423
+ return makeEnvironmentProviders([
2424
+ ...middlewares.map((middleware) => ({
2425
+ provide: AXP_MENU_MIDDLEWARE,
2426
+ useValue: middleware,
2427
+ multi: true,
2428
+ })),
2429
+ ]);
2430
+ }
2431
+ /**
2432
+ * Helper to create a class-based middleware with priority
2433
+ *
2434
+ * @example
2435
+ * ```typescript
2436
+ * const myMiddleware = createMenuMiddleware({
2437
+ * name: 'my-middleware',
2438
+ * priority: 100,
2439
+ * process: async (context) => {
2440
+ * context.find('dashboard').setPriority(1);
2441
+ * }
2442
+ * });
2443
+ * ```
2444
+ */
2445
+ function createMenuMiddleware(config) {
2446
+ return {
2447
+ name: config.name,
2448
+ priority: config.priority ?? 0,
2449
+ process: config.process,
2450
+ };
2451
+ }
2452
+ //#endregion
2453
+
2454
+ const AXPMenuService = signalStore({ providedIn: 'root' },
2455
+ // Initial State
2456
+ withState((router = inject(Router)) => {
2457
+ return {
2458
+ items: [],
2459
+ selectedMenuItem: {
2460
+ item: null,
2461
+ isFullMatch: false,
2462
+ },
2463
+ };
2464
+ }),
2465
+ // Methods for State Management
2466
+ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowService), commandExecutor = inject(AXPCommandExecutor)) => {
2467
+ return {
2468
+ setMenuItems(items) {
2469
+ patchState(store, { items: items });
2470
+ },
2471
+ selectMenuItemByRoute(path) {
2472
+ const currentRawPath = path;
2473
+ const findItem = (items) => {
2474
+ for (const item of items) {
2475
+ // Recursively search children first
2476
+ if (item.children) {
2477
+ const foundChild = findItem(item.children);
2478
+ if (foundChild.item) {
2479
+ return foundChild;
2480
+ }
2481
+ }
2482
+ if (item.path) {
2483
+ // Check if the item path matches the current path (including query param subset if provided on item)
2484
+ const matchResult = pathsMatch(item.path, currentRawPath, ['list', 'view', 'edit', 'create']);
2485
+ if (matchResult.isMatch) {
2486
+ return { item, isPartialMatch: matchResult.isPartial };
2487
+ }
2488
+ }
2489
+ }
2490
+ return { item: null, isPartialMatch: false };
2491
+ };
2492
+ const pathsMatch = (itemPath, currentPath, trailingSegmentsToIgnore = []) => {
2493
+ // Split base and query/hash
2494
+ const itemNoHash = itemPath.split('#')[0];
2495
+ const currentNoHash = currentPath.split('#')[0];
2496
+ const [itemBase, itemQueryString = ''] = itemNoHash.split('?');
2497
+ const [currentBase, currentQueryString = ''] = currentNoHash.split('?');
2498
+ const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
2499
+ const pathSegments = currentBase.split('/').filter((segment) => segment.length > 0);
2500
+ const menuLength = itemSegments.length;
2501
+ const pathLength = pathSegments.length;
2502
+ // Identify the effective base length for the menuPath
2503
+ let effectiveMenuLength = menuLength;
2504
+ if (menuLength > 0 && trailingSegmentsToIgnore.includes(itemSegments[menuLength - 1])) {
2505
+ effectiveMenuLength--; // Exclude trailing non-hierarchical segments
2506
+ }
2507
+ // Check if the menuPath (base segments) is a prefix of browserPath
2508
+ let isPrefix = true;
2509
+ if (pathLength < effectiveMenuLength) {
2510
+ return { isMatch: false, isPartial: false };
2511
+ }
2512
+ for (let i = 0; i < effectiveMenuLength; i++) {
2513
+ if (itemSegments[i] !== pathSegments[i]) {
2514
+ isPrefix = false;
2515
+ break;
2516
+ }
2517
+ }
2518
+ if (!isPrefix) {
2519
+ return { isMatch: false, isPartial: false };
2520
+ }
2521
+ // Partial match: menuPath base is a strict prefix of browserPath
2522
+ const isPartialMatch = effectiveMenuLength < pathLength;
2523
+ // Exact match: all segments match completely
2524
+ const isExactMatch = effectiveMenuLength === pathLength;
2525
+ // Query params subset match: if item defines any query params, require them to match
2526
+ const itemParams = new URLSearchParams(itemQueryString);
2527
+ const currentParams = new URLSearchParams(currentQueryString);
2528
+ let queryMatches = true;
2529
+ const itemParamPairs = [];
2530
+ itemParams.forEach((value, key) => {
2531
+ itemParamPairs.push([key, value]);
2532
+ });
2533
+ if (itemParamPairs.length > 0) {
2534
+ for (const [k, v] of itemParamPairs) {
2535
+ if (currentParams.get(k) !== v) {
2536
+ queryMatches = false;
2537
+ break;
2538
+ }
2539
+ }
2540
+ }
2541
+ return {
2542
+ isMatch: (isExactMatch || isPartialMatch) && queryMatches,
2543
+ isPartial: isPartialMatch && !isExactMatch,
2544
+ };
2545
+ };
2546
+ const items = store.items();
2547
+ const { item, isPartialMatch } = findItem(items);
2548
+ patchState(store, { selectedMenuItem: { item, isFullMatch: !isPartialMatch } });
2549
+ },
2550
+ executeCommand(item) {
2551
+ if (item.path) {
2552
+ workflow.execute('navigate', {
2553
+ type: 'router',
2554
+ options: { path: item.path },
2555
+ });
2556
+ patchState(store, { selectedMenuItem: { item, isFullMatch: true } });
2557
+ }
2558
+ if (item.command) {
2559
+ const command = item.command;
2560
+ if (workflow.exists(command?.name)) {
2561
+ workflow.execute(command.name, command.options);
2562
+ }
2563
+ else {
2564
+ commandExecutor.execute(command.name, command.options);
2565
+ }
2566
+ }
2567
+ },
2568
+ isItemOpen(item) {
2569
+ const selectedItem = store.selectedMenuItem();
2570
+ if (!selectedItem.item) {
2571
+ return false;
2572
+ }
2573
+ const findParent = (currentItem, targetItem) => {
2574
+ if (currentItem.children?.includes(targetItem)) {
2575
+ return true;
2576
+ }
2577
+ return currentItem.children?.some((child) => findParent(child, targetItem)) ?? false;
2578
+ };
2579
+ return item === selectedItem.item || findParent(item, selectedItem.item);
2580
+ },
2581
+ };
2582
+ }), withHooks((store, menuProviderService = inject(AXPMenuProviderService)) => {
2583
+ let reloadSubscription;
2584
+ return {
2585
+ onInit() {
2586
+ // Load initial menu items
2587
+ (async () => {
2588
+ const items = await menuProviderService.items();
2589
+ patchState(store, { items: items });
2590
+ })();
2591
+ // Subscribe to menu reload events
2592
+ reloadSubscription = menuProviderService.menuReload$.subscribe(async () => {
2593
+ const items = await menuProviderService.items();
2594
+ patchState(store, { items: items });
2595
+ });
2596
+ },
2597
+ onDestroy() {
2598
+ // Clean up subscription
2599
+ if (reloadSubscription) {
2600
+ reloadSubscription.unsubscribe();
2601
+ }
2602
+ },
2603
+ };
2604
+ }));
2605
+
2606
+ /**
2607
+ * Service for checking menu item visibility based on permissions, features, and children.
2608
+ * This service helps filter out empty menu items that have no visible children.
2609
+ */
2610
+ class AXPMenuVisibilityService {
2611
+ constructor() {
2612
+ this.sessionService = inject(AXPSessionService);
2613
+ }
2614
+ /**
2615
+ * Checks if a menu item should be visible based on permissions and features.
2616
+ */
2617
+ isItemVisible(item) {
2618
+ const policy = item.policy;
2619
+ if (!policy) {
2620
+ return true; // No policy means visible
2621
+ }
2622
+ // Check features
2623
+ if (policy.features && policy.features.length > 0) {
2624
+ const featureKeys = Array.isArray(policy.features) ? policy.features : [policy.features];
2625
+ if (!this.sessionService.isFeatureEnabled(...featureKeys)) {
2626
+ return false;
2627
+ }
2628
+ }
2629
+ // Check permissions
2630
+ if (policy.permissions && policy.permissions.length > 0) {
2631
+ const permissionKeys = Array.isArray(policy.permissions) ? policy.permissions : [policy.permissions];
2632
+ if (!this.sessionService.authorize(...permissionKeys)) {
2633
+ return false;
2634
+ }
2635
+ }
2636
+ return true;
2637
+ }
2638
+ /**
2639
+ * Recursively checks if a menu item has any visible children.
2640
+ * @param item The menu item to check
2641
+ * @param getRouterLink Optional function to check if an item has a router link
2642
+ */
2643
+ hasVisibleChildren(item, getRouterLink) {
2644
+ if (!item.children || item.children.length === 0) {
2645
+ return false;
2646
+ }
2647
+ return item.children.some((child) => {
2648
+ // Check if child itself is visible
2649
+ if (!this.isItemVisible(child)) {
2650
+ return false;
2651
+ }
2652
+ // If child has a routerLink, it's visible
2653
+ if (getRouterLink && getRouterLink(child)) {
2654
+ return true;
2655
+ }
2656
+ // If child has visible children, it's visible
2657
+ if (this.hasVisibleChildren(child, getRouterLink)) {
2658
+ return true;
2659
+ }
2660
+ // For items without routerLink, check if they have a command (non-empty menu items)
2661
+ if (child.command) {
2662
+ return true;
2663
+ }
2664
+ return false;
2665
+ });
2666
+ }
2667
+ /**
2668
+ * Determines if a menu item should be rendered.
2669
+ * A menu item should be rendered if:
2670
+ * 1. It has a routerLink, OR
2671
+ * 2. It has visible children, OR
2672
+ * 3. It has a command (for non-router navigation)
2673
+ *
2674
+ * @param item The menu item to check
2675
+ * @param getRouterLink Optional function to check if an item has a router link
2676
+ */
2677
+ shouldRenderMenuItem(item, getRouterLink) {
2678
+ // Check if item itself is visible (permissions/features)
2679
+ if (!this.isItemVisible(item)) {
2680
+ return false;
2681
+ }
2682
+ // If it has a routerLink, render it
2683
+ if (getRouterLink && getRouterLink(item)) {
2684
+ return true;
2685
+ }
2686
+ // If it has visible children, render it
2687
+ if (this.hasVisibleChildren(item, getRouterLink)) {
2688
+ return true;
2689
+ }
2690
+ // If it has a command (for non-router navigation), render it
2691
+ if (item.command) {
2692
+ return true;
2693
+ }
2694
+ // Otherwise, don't render empty menu items
2695
+ return false;
2696
+ }
2697
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuVisibilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2698
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuVisibilityService, providedIn: 'root' }); }
2699
+ }
2700
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPMenuVisibilityService, decorators: [{
2701
+ type: Injectable,
2702
+ args: [{ providedIn: 'root' }]
2703
+ }] });
2704
+
2705
+ class AXPMenuSearchDefinitionProvider {
2706
+ async provide(context) {
2707
+ context.addDefinition('menu', 'Menu', 'menu', 'fa-thin fa-bars', 2, {
2708
+ format: {
2709
+ id: '{{data.name}}',
2710
+ },
2711
+ actions: [
2712
+ {
2713
+ name: 'navigate',
2714
+ type: AXPSystemActionType.View,
2715
+ priority: 'primary',
2716
+ },
2717
+ ],
2718
+ });
2719
+ }
2720
+ }
2721
+
2722
+ class AXPMenuSearchProvider {
2723
+ constructor() {
2724
+ this.menuService = inject(AXPMenuProviderService);
2725
+ this.translateService = inject(AXTranslationService);
2726
+ }
2727
+ async search(text) {
2728
+ const menuItems = await this.searchMenuItems(await this.menuService.items(), text);
2729
+ return sortBy(menuItems.map((item) => ({
2730
+ group: 'menu', // Use `name` or empty string if undefined
2731
+ title: item.text, // Use `text` for the `title`
2732
+ icon: item.icon, // Include the `icon` if present
2733
+ data: omit(item, ['parent', 'children']), // Include all data except `parent` and `children`
2734
+ command: item.path ? {
2735
+ name: 'navigate',
2736
+ options: {
2737
+ type: 'router',
2738
+ options: {
2739
+ path: item.path,
2740
+ },
2741
+ }
2742
+ } : item.command,
2743
+ parent: item.parent
2744
+ ? {
2745
+ title: item.parent.text,
2746
+ }
2747
+ : undefined,
2748
+ })), [(o) => this.translateService.translateSync(o.title)]);
2749
+ }
2750
+ /**
2751
+ * Recursively searches AXPMenuItem and its children for a matching text.
2752
+ *
2753
+ * @param menuItems - The array of AXPMenuItem to search in.
2754
+ * @param searchText - The text to search for (case-insensitive).
2755
+ * @returns An array of AXPMenuItem that match the search text.
2756
+ */
2757
+ async searchMenuItems(menuItems, searchText) {
2758
+ const result = [];
2759
+ for (const item of menuItems) {
2760
+ // Check if the current item's text matches the search text
2761
+ if (item.type != 'group' &&
2762
+ (item.children?.length ?? 0) == 0 &&
2763
+ (await this.translateService.translateAsync(item.text)).toLowerCase().includes(searchText.toLowerCase())) {
2764
+ result.push(item);
2765
+ }
2766
+ // Recursively search in children if they exist
2767
+ if (item.children && item.children.length > 0) {
2768
+ const childResults = await this.searchMenuItems(item.children, searchText);
2769
+ result.push(...childResults.map((x) => ({ ...x, parent: item })));
2770
+ }
2771
+ }
2772
+ return result;
2773
+ }
2774
+ }
2775
+
2776
+ class AXPFooterTextSlotComponent {
2777
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFooterTextSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2778
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AXPFooterTextSlotComponent, isStandalone: true, selector: "ng-component", inputs: { text: "text" }, ngImport: i0, template: `
2779
+ <small class="ax-text-sm" [innerHTML]="text"></small>
2780
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2781
+ }
2782
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFooterTextSlotComponent, decorators: [{
2783
+ type: Component,
2784
+ args: [{
2785
+ template: `
2786
+ <small class="ax-text-sm" [innerHTML]="text"></small>
2787
+ `,
2788
+ standalone: true,
2789
+ changeDetection: ChangeDetectionStrategy.OnPush,
2790
+ }]
2791
+ }], propDecorators: { text: [{
2792
+ type: Input
2793
+ }] } });
2794
+
2795
+ class AXPNavBarSlotComponent {
2796
+ handleCommand(action) {
2797
+ // if (action)
2798
+ // this.store.dispatch(action)
2799
+ }
2800
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavBarSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2801
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPNavBarSlotComponent, isStandalone: true, selector: "ng-component", inputs: { items: "items" }, ngImport: i0, template: `
2802
+ <div class="ax-flex ax-items-center ax-justify-between ax-gap-5">
2803
+ @for (link of items; track link) {
2804
+ <a (click)="handleCommand(link.command)" >{{ link.text }}</a>
2805
+ }
2806
+ </div>
2807
+ `, isInline: true, encapsulation: i0.ViewEncapsulation.None }); }
2808
+ }
2809
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavBarSlotComponent, decorators: [{
2810
+ type: Component,
2811
+ args: [{
2812
+ template: `
2813
+ <div class="ax-flex ax-items-center ax-justify-between ax-gap-5">
2814
+ @for (link of items; track link) {
2815
+ <a (click)="handleCommand(link.command)" >{{ link.text }}</a>
2816
+ }
2817
+ </div>
2818
+ `,
2819
+ imports: [],
2820
+ encapsulation: ViewEncapsulation.None
2821
+ }]
2822
+ }], propDecorators: { items: [{
2823
+ type: Input
2824
+ }] } });
2825
+
2826
+ class AXPSearchDefinitionProviderContext {
2827
+ constructor() {
2828
+ this.definitions = [];
2829
+ this.definitionMap = new Map();
2830
+ }
2831
+ addDefinition(name, title, group, icon, order, options) {
2832
+ const definitionSearch = {
2833
+ name,
2834
+ title,
2835
+ group,
2836
+ icon,
2837
+ order,
2838
+ format: {
2839
+ title: options?.format?.title ?? '{{ title }}',
2840
+ description: options?.format?.description ?? undefined,
2841
+ icon: options?.format?.icon ?? undefined,
2842
+ id: options?.format?.id ?? '{{ id }}',
2843
+ },
2844
+ actions: options?.actions ?? [],
2845
+ };
2846
+ this.definitions.push(definitionSearch);
2847
+ this.definitionMap.set(name, definitionSearch); // Index by name
2848
+ return new AXPSearchDefinitionBuilder(this, definitionSearch);
2849
+ }
2850
+ getDefinitions() {
2851
+ return this.definitions;
2852
+ }
2853
+ // Expose groupMap for controlled access
2854
+ hasEntity(name) {
2855
+ return this.definitionMap.has(name);
2856
+ }
2857
+ getDefinition(name) {
2858
+ return this.definitionMap.get(name);
2859
+ }
2860
+ }
2861
+ class AXPSearchDefinitionBuilder {
2862
+ constructor(context, definition) {
2863
+ this.context = context;
2864
+ this.definition = definition;
2865
+ }
2866
+ addAction(name) {
2867
+ const newAction = {
2868
+ name,
2869
+ type: AXPSystemActionType.View,
2870
+ priority: 'primary',
2871
+ };
2872
+ this.definition.actions.push(newAction);
2873
+ return new AXPSearchDefinitionActionBuilder(this);
2874
+ }
2875
+ action(name) {
2876
+ const foundAction = this.definition.actions.find((action) => action.name === name);
2877
+ if (!foundAction) {
2878
+ throw new Error(`action with name "${name}" not found in entity "${this.definition.name}".`);
2879
+ }
2880
+ return new AXPSearchDefinitionActionBuilder(this);
2881
+ }
2882
+ endEntity() {
2883
+ return this.context;
2884
+ }
2885
+ }
2886
+ class AXPSearchDefinitionActionBuilder {
2887
+ constructor(entityBuilder) {
2888
+ this.entityBuilder = entityBuilder;
2889
+ }
2890
+ endAction() {
2891
+ return this.entityBuilder;
2892
+ }
2893
+ }
2894
+
2895
+ // Injection token for setting providers
2896
+ const AXP_SEARCH_DEFINITION_PROVIDER = new InjectionToken('AXP_SEARCH_DEFINITION_PROVIDER');
2897
+ class AXPSearchDefinitionProviderService {
2898
+ constructor() {
2899
+ this.providers = inject(AXP_SEARCH_DEFINITION_PROVIDER, { optional: true });
2900
+ this.cache = null;
2901
+ }
2902
+ async load() {
2903
+ if (this.cache) {
2904
+ return;
2905
+ }
2906
+ const context = new AXPSearchDefinitionProviderContext();
2907
+ // Load providers from DI tokens (backward compatibility)
2908
+ if (Array.isArray(this.providers)) {
2909
+ for (const provider of this.providers) {
2910
+ await provider.provide(context);
2911
+ }
2912
+ }
2913
+ // Note: Search definition providers are different from search command providers
2914
+ // Search command providers are handled separately in search.service.ts
2915
+ this.cache = context.getDefinitions();
2916
+ }
2917
+ async getListAsync() {
2918
+ await this.load();
2919
+ return this.getList();
2920
+ }
2921
+ getList() {
2922
+ if (!this.cache) {
2923
+ return [];
2924
+ }
2925
+ else {
2926
+ return this.cache;
2927
+ }
2928
+ }
2929
+ findDefinition(definitionName) {
2930
+ const definition = this.getList().find((definition) => definition.name === definitionName);
2931
+ if (!definition) {
2932
+ throw new Error(`Definition with name ${definitionName} not found`);
2933
+ }
2934
+ return definition;
2935
+ }
2936
+ findDefinitionByGroup(definitionGroup) {
2937
+ const definition = this.getList().find((definition) => definition.group === definitionGroup);
2938
+ if (!definition) {
2939
+ throw new Error(`Definition with group ${definitionGroup} not found`);
2940
+ }
2941
+ return definition;
2942
+ }
2943
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSearchDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2944
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSearchDefinitionProviderService, providedIn: 'root' }); }
2945
+ }
2946
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSearchDefinitionProviderService, decorators: [{
2947
+ type: Injectable,
2948
+ args: [{ providedIn: 'root' }]
2949
+ }] });
2950
+
2951
+ class AXPSearchCommandProvider {
2952
+ async search(text) {
2953
+ return this.commands.filter((command) => command.title.toLowerCase().includes(text.toLowerCase()));
2954
+ }
2955
+ }
2956
+
2957
+ // Injection token for setting providers
2958
+ const AXP_SEARCH_PROVIDER = new InjectionToken('AXP_SEARCH_PROVIDER');
2959
+ class AXPSearchService {
2960
+ constructor() {
2961
+ this.providers = inject(AXP_SEARCH_PROVIDER, { optional: true });
2962
+ this.definitionService = inject(AXPSearchDefinitionProviderService);
2963
+ this.formatService = inject(AXFormatService);
2964
+ this.translationService = inject(AXTranslationService);
2965
+ }
2966
+ async search(text) {
2967
+ //TODO better handle this
2968
+ if (this.definitionService.getList().length == 0) {
2969
+ await this.definitionService.getListAsync();
2970
+ }
2971
+ // Collect providers from DI tokens
2972
+ const allProviders = [];
2973
+ // Load from DI tokens
2974
+ if (Array.isArray(this.providers)) {
2975
+ allProviders.push(...this.providers);
2976
+ }
2977
+ else if (this.providers) {
2978
+ allProviders.push(this.providers);
2979
+ }
2980
+ if (allProviders.length === 0) {
2981
+ throw new Error('No search providers available');
2982
+ }
2983
+ const providersWithSearch = allProviders.filter((provider) => provider != null && typeof provider.search === 'function');
2984
+ if (providersWithSearch.length === 0) {
2985
+ throw new Error('No search providers with a valid search method available');
2986
+ }
2987
+ const mergeData = [];
2988
+ const promises = providersWithSearch.map((provider) => provider.search(text));
2989
+ const results = await Promise.all(promises);
2990
+ for (const resultArray of results) {
2991
+ for (const result of resultArray) {
2992
+ try {
2993
+ const definition = this.definitionService.findDefinition(result.group);
2994
+ mergeData.push({
2995
+ definitionName: definition.group,
2996
+ definitionTitle: definition.title,
2997
+ name: result.group,
2998
+ id: `${definition.name}:${this.formatService.format(definition.format.id, 'string', result)}`,
2999
+ title: result.title ??
3000
+ (definition.format.title
3001
+ ? this.formatService.format(definition.format.title, 'string', result.data)
3002
+ : 'Unknown'),
3003
+ description: result.description ??
3004
+ (definition.format.description
3005
+ ? this.formatService.format(definition.format.description, 'string', result.data)
3006
+ : undefined),
3007
+ icon: result.icon ?? definition.icon,
3008
+ data: result.data,
3009
+ command: result.command,
3010
+ actions: definition.actions,
3011
+ parent: result.parent,
3012
+ order: definition.order,
3013
+ });
3014
+ }
3015
+ catch (e) {
3016
+ console.error(e);
3017
+ }
3018
+ }
3019
+ }
3020
+ // Group data
3021
+ const groupedData = [];
3022
+ const groupMap = {};
3023
+ // Create groups
3024
+ for (const item of mergeData) {
3025
+ const groupName = item.definitionName; // Change this to the property you want to group by
3026
+ if (!groupMap[groupName]) {
3027
+ groupMap[groupName] = {
3028
+ name: groupName,
3029
+ title: item.definitionTitle, // You can adjust the title logic if needed
3030
+ order: item.order, // Add order to the group
3031
+ children: [],
3032
+ };
3033
+ groupedData.push(groupMap[groupName]);
3034
+ }
3035
+ groupMap[groupName].children.push(omit(item, ['definitionName', 'definitionTitle', 'order']));
3036
+ }
3037
+ // Sort groups by order
3038
+ groupedData.sort((a, b) => a.order - b.order);
3039
+ return groupedData;
3040
+ }
3041
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3042
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSearchService, providedIn: 'root' }); }
3043
+ }
3044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSearchService, decorators: [{
3045
+ type: Injectable,
3046
+ args: [{ providedIn: 'root' }]
3047
+ }] });
3048
+
3049
+ /**
3050
+ * Shared utility for creating Entity:Create command options used in search command providers.
3051
+ * Use with command: { name: 'Entity:Create', options: createEntityCommandOptions(...) }
3052
+ */
3053
+ function createEntityCommandOptions(entityKey, entityInfo) {
3054
+ return {
3055
+ __context__: {
3056
+ entity: entityKey,
3057
+ entityInfo: {
3058
+ name: entityInfo.name,
3059
+ module: entityInfo.module,
3060
+ title: entityInfo.title,
3061
+ parentKey: undefined,
3062
+ source: entityKey,
3063
+ },
3064
+ data: {},
3065
+ options: {},
3066
+ },
3067
+ };
3068
+ }
3069
+ /**
3070
+ * Creates a search command for "Create {Entity}" with consistent i18n pattern.
3071
+ * Use titleKey/descriptionKey from module (e.g. @module:entity.permissions.create.title).
3072
+ * Standard: "Create {Entity}" for title, "Create new {entities}" for description.
3073
+ */
3074
+ function createEntitySearchCommand(config) {
3075
+ return {
3076
+ id: config.id,
3077
+ group: 'command',
3078
+ title: config.titleKey,
3079
+ description: config.descriptionKey ?? config.titleKey,
3080
+ icon: config.icon,
3081
+ command: {
3082
+ name: 'Entity:Create',
3083
+ options: createEntityCommandOptions(config.entityKey, config.entityInfo),
3084
+ },
3085
+ };
3086
+ }
3087
+
3088
+ var AXPCommonSettings;
3089
+ (function (AXPCommonSettings) {
3090
+ AXPCommonSettings["EnableOperationToasts"] = "Common:Setting:Notifications.EnableOperationToasts";
3091
+ AXPCommonSettings["EntityFilterApplyMode"] = "Common:Setting:Entity.FilterApplyMode";
3092
+ AXPCommonSettings["ShowCategoryColumnsByDefault"] = "Common:Setting:Entity.ShowCategoryColumnsByDefault";
3093
+ AXPCommonSettings["ApplyLayoutOrdering"] = "Common:Setting:Entity.ApplyLayoutOrdering";
3094
+ AXPCommonSettings["RedirectToDetailsAfterCreate"] = "Common:Setting:Entity.RedirectToDetailsAfterCreate";
3095
+ AXPCommonSettings["ShowPageBadge"] = "Common:Setting:Entity.ShowPageBadge";
3096
+ AXPCommonSettings["DebugMode"] = "PlatformDevTools:Setting:Developer.DebugMode";
3097
+ })(AXPCommonSettings || (AXPCommonSettings = {}));
3098
+
3099
+ //TODO Loading, Redirect, Drawer, Show toast
3100
+ const AXPRedirectEvent = createWorkFlowEvent('Redirect Event Fired');
3101
+ const AXPRefreshEvent = createWorkFlowEvent('Refresh Event Fired');
3102
+ const AXPReloadEvent = createWorkFlowEvent('Reload Event Fired');
3103
+ class AXPWorkflowNavigateAction extends AXPWorkflowAction {
3104
+ constructor() {
3105
+ super(...arguments);
3106
+ this.router = inject(Router);
3107
+ }
3108
+ async execute(context) {
3109
+ const payload = context.getVariable('payload');
3110
+ if (Array.isArray(payload.commands)) {
3111
+ this.router.navigate(payload.commands, payload.extras);
3112
+ }
3113
+ else {
3114
+ if (payload.commands.toLowerCase().startsWith('http') || payload.target == 'blank') {
3115
+ window.open(payload.commands, '_blank');
3116
+ }
3117
+ else
3118
+ this.router.navigate([payload.commands], payload.extras);
3119
+ }
3120
+ }
3121
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3122
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction }); }
3123
+ }
3124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction, decorators: [{
3125
+ type: Injectable
3126
+ }] });
3127
+ class AXPDialogConfirmAction extends AXPWorkflowAction {
3128
+ constructor() {
3129
+ super(...arguments);
3130
+ this.dialogService = inject(AXDialogService);
3131
+ this.translationService = inject(AXTranslationService);
3132
+ this.defaultAction = 'cancel';
3133
+ }
3134
+ async execute(context) {
3135
+ console.log('AXPDialogConfirmAction', this.title, this.message, this.type);
3136
+ context.setOutput('result', false);
3137
+ const dialogResult = await this.dialogService.confirm(await this.translationService.translateAsync(this.title), await this.translationService.translateAsync(this.message), (await this.translationService.translateAsync(this.type)), 'horizontal', false, 'cancel');
3138
+ context.setOutput('result', dialogResult.result);
3139
+ }
3140
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3141
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction }); }
3142
+ }
3143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction, decorators: [{
3144
+ type: Injectable
3145
+ }] });
3146
+ class AXPToastAction extends AXPWorkflowAction {
3147
+ constructor() {
3148
+ super(...arguments);
3149
+ this.toastService = inject(AXToastService);
3150
+ this.translationService = inject(AXTranslationService);
3151
+ this.settingsService = inject(AXPSettingsService);
3152
+ }
3153
+ async execute(context) {
3154
+ const showResult = await this.settingsService.get(AXPCommonSettings.EnableOperationToasts);
3155
+ if (showResult) {
3156
+ this.toastService.show({
3157
+ color: this.color,
3158
+ title: await this.translationService.translateAsync(this.title),
3159
+ content: await this.translationService.translateAsync(this.content),
3160
+ closeButton: true,
3161
+ timeOut: 3000,
3162
+ timeOutProgress: true,
3163
+ });
3164
+ }
3165
+ }
3166
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPToastAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3167
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPToastAction }); }
3168
+ }
3169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPToastAction, decorators: [{
3170
+ type: Injectable
3171
+ }] });
3172
+ class AXPReloadAction extends AXPWorkflowAction {
3173
+ async execute(context) {
3174
+ this.dispatch(AXPReloadEvent({ entity: context.getVariable('entity'), meta: context.getVariable('meta') }));
3175
+ }
3176
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3177
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction }); }
3178
+ }
3179
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction, decorators: [{
3180
+ type: Injectable
3181
+ }] });
3182
+
3183
+ class AXPWorkflowRouterNavigateAction extends AXPWorkflowAction {
3184
+ constructor() {
3185
+ super(...arguments);
3186
+ this.router = inject(Router);
3187
+ }
3188
+ async execute(context) {
3189
+ const command = context.getVariable();
3190
+ const path = command.options.path;
3191
+ if (path?.toLowerCase()?.startsWith('http') || command.options?.extras?.target === 'blank') {
3192
+ window.open(path, '_blank');
3193
+ }
3194
+ else {
3195
+ const [basePathAndFragment, queryString] = path.split('?');
3196
+ const [basePath, fragment] = basePathAndFragment.split('#'); // Extract fragment if present
3197
+ const queryParams = this.parseQueryParams(queryString);
3198
+ this.router.navigate([basePath], {
3199
+ ...command.options.extras,
3200
+ queryParams, // Pass query parameters separately
3201
+ fragment, // Pass fragment explicitly
3202
+ });
3203
+ }
3204
+ }
3205
+ /**
3206
+ * Parses query parameters from a query string into an object.
3207
+ */
3208
+ parseQueryParams(queryString) {
3209
+ if (!queryString)
3210
+ return undefined;
3211
+ return queryString
3212
+ .split('&')
3213
+ .map((pair) => pair.split('='))
3214
+ .reduce((params, [key, value]) => {
3215
+ params[decodeURIComponent(key)] = decodeURIComponent(value);
3216
+ return params;
3217
+ }, {});
3218
+ }
3219
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3220
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction }); }
3221
+ }
3222
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction, decorators: [{
3223
+ type: Injectable
3224
+ }] });
3225
+ const AXPNavigateWorkflow = {
3226
+ startStepId: 'start',
3227
+ steps: {
3228
+ start: {
3229
+ action: 'navigate-router',
3230
+ },
3231
+ },
3232
+ };
3233
+
3234
+ class AXMWorkflowErrorHandler {
3235
+ constructor() {
3236
+ this.dialog = inject(AXDialogService);
3237
+ }
3238
+ handleError(error, next) {
3239
+ if (error instanceof AXPWorkflowError) {
3240
+ this.dialog.alert("Somthing is wrong!", error.inner ? error.inner.message : error.message, 'danger');
3241
+ next(error);
3242
+ }
3243
+ else {
3244
+ next(error);
3245
+ }
3246
+ }
3247
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3248
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler }); }
3249
+ }
3250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler, decorators: [{
3251
+ type: Injectable
3252
+ }] });
3253
+
3254
+ class AXPCommonModule {
3255
+ static forRoot(configs) {
3256
+ return {
3257
+ ngModule: AXPCommonModule,
3258
+ providers: [
3259
+ ...(configs?.errorHandlers || []),
3260
+ {
3261
+ provide: 'AXPCommonModuleFactory',
3262
+ useFactory: (registry) => () => {
3263
+ registry.register(...(configs?.errorHandlers || []));
3264
+ },
3265
+ deps: [AXPErrorHandlerRegistryService],
3266
+ multi: true,
3267
+ },
3268
+ ],
3269
+ };
3270
+ }
3271
+ static forChild(configs) {
3272
+ return {
3273
+ ngModule: AXPCommonModule,
3274
+ providers: [
3275
+ ...(configs?.errorHandlers || []),
3276
+ {
3277
+ provide: 'AXPCommonModuleFactory',
3278
+ useFactory: (registry) => () => {
3279
+ registry.register(...(configs?.errorHandlers || []));
3280
+ },
3281
+ deps: [AXPErrorHandlerRegistryService],
3282
+ multi: true,
3283
+ },
3284
+ ],
3285
+ };
3286
+ }
3287
+ /**
3288
+ * @ignore
3289
+ */
3290
+ constructor(instances) {
3291
+ instances.forEach((f) => {
3292
+ f();
3293
+ });
3294
+ }
3295
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, deps: [{ token: 'AXPCommonModuleFactory' }], target: i0.ɵɵFactoryTarget.NgModule }); }
3296
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, imports: [i1.AXPWorkflowModule, AXPopupModule,
3297
+ AXDateTimeModule,
3298
+ AXToastModule,
3299
+ AXPModuleManifestModule], exports: [RouterModule] }); }
3300
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, providers: [
3301
+ AXPAppStartUpProvider,
3302
+ {
3303
+ provide: ErrorHandler,
3304
+ useClass: AXPGlobalErrorHandler,
3305
+ },
3306
+ {
3307
+ provide: AXPCustomOperatorService,
3308
+ useClass: AXPCustomOperatorServiceImpl,
3309
+ },
3310
+ {
3311
+ provide: AXPFilterOperatorMiddlewareService,
3312
+ useClass: AXPFilterOperatorMiddlewareServiceImpl,
3313
+ },
3314
+ {
3315
+ provide: AXP_SEARCH_PROVIDER,
3316
+ useClass: AXPMenuSearchProvider,
3317
+ multi: true,
3318
+ },
3319
+ {
3320
+ provide: AXP_SEARCH_DEFINITION_PROVIDER,
3321
+ useClass: AXPMenuSearchDefinitionProvider,
3322
+ multi: true,
3323
+ },
3324
+ {
3325
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
3326
+ useClass: AXPTokenEvaluatorScopeProvider,
3327
+ multi: true,
3328
+ },
3329
+ {
3330
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
3331
+ useClass: AXPSettingsEvaluatorScopeProvider,
3332
+ multi: true,
3333
+ },
3334
+ {
3335
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
3336
+ useFactory: async () => {
3337
+ const injector = inject(Injector);
3338
+ const provider = (await import('./acorex-platform-common-common-settings.provider-G9XcXXOG.mjs')).AXPCommonSettingProvider;
3339
+ return new provider(injector);
3340
+ },
3341
+ multi: true,
3342
+ },
3343
+ ], imports: [AXPWorkflowModule.forChild({
3344
+ actions: {
3345
+ 'navigate-router': AXPWorkflowRouterNavigateAction,
3346
+ 'show-prompt-dialog': AXPDialogConfirmAction,
3347
+ 'show-toast': AXPToastAction,
3348
+ reload: AXPReloadAction,
3349
+ },
3350
+ workflows: {
3351
+ navigate: AXPNavigateWorkflow,
3352
+ },
3353
+ }),
3354
+ AXPopupModule,
3355
+ AXDateTimeModule,
3356
+ AXToastModule,
3357
+ AXPModuleManifestModule, RouterModule] }); }
3358
+ }
3359
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, decorators: [{
3360
+ type: NgModule,
3361
+ args: [{
3362
+ imports: [
3363
+ AXPWorkflowModule.forChild({
3364
+ actions: {
3365
+ 'navigate-router': AXPWorkflowRouterNavigateAction,
3366
+ 'show-prompt-dialog': AXPDialogConfirmAction,
3367
+ 'show-toast': AXPToastAction,
3368
+ reload: AXPReloadAction,
3369
+ },
3370
+ workflows: {
3371
+ navigate: AXPNavigateWorkflow,
3372
+ },
3373
+ }),
3374
+ AXPopupModule,
3375
+ AXDateTimeModule,
3376
+ AXToastModule,
3377
+ AXPModuleManifestModule,
3378
+ ],
3379
+ exports: [RouterModule],
3380
+ providers: [
3381
+ AXPAppStartUpProvider,
3382
+ {
3383
+ provide: ErrorHandler,
3384
+ useClass: AXPGlobalErrorHandler,
3385
+ },
3386
+ {
3387
+ provide: AXPCustomOperatorService,
3388
+ useClass: AXPCustomOperatorServiceImpl,
3389
+ },
3390
+ {
3391
+ provide: AXPFilterOperatorMiddlewareService,
3392
+ useClass: AXPFilterOperatorMiddlewareServiceImpl,
3393
+ },
3394
+ {
3395
+ provide: AXP_SEARCH_PROVIDER,
3396
+ useClass: AXPMenuSearchProvider,
3397
+ multi: true,
3398
+ },
3399
+ {
3400
+ provide: AXP_SEARCH_DEFINITION_PROVIDER,
3401
+ useClass: AXPMenuSearchDefinitionProvider,
3402
+ multi: true,
3403
+ },
3404
+ {
3405
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
3406
+ useClass: AXPTokenEvaluatorScopeProvider,
3407
+ multi: true,
3408
+ },
3409
+ {
3410
+ provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
3411
+ useClass: AXPSettingsEvaluatorScopeProvider,
3412
+ multi: true,
3413
+ },
3414
+ {
3415
+ provide: AXP_SETTING_DEFINITION_PROVIDER,
3416
+ useFactory: async () => {
3417
+ const injector = inject(Injector);
3418
+ const provider = (await import('./acorex-platform-common-common-settings.provider-G9XcXXOG.mjs')).AXPCommonSettingProvider;
3419
+ return new provider(injector);
3420
+ },
3421
+ multi: true,
3422
+ },
3423
+ ],
3424
+ }]
3425
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
3426
+ type: Inject,
3427
+ args: ['AXPCommonModuleFactory']
3428
+ }] }] });
3429
+
3430
+ const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
3431
+ const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
3432
+ providedIn: 'root',
3433
+ factory: () => {
3434
+ return AXPPlatformDefaultConfigs;
3435
+ },
3436
+ });
3437
+ const AXPPlatformDefaultConfigs = {
3438
+ copyright: 'ACoreX @ 2024',
3439
+ title: 'ACoreX Platform',
3440
+ network: {
3441
+ timeOut: 5000,
3442
+ },
3443
+ };
3444
+ function configPlatform(config = AXPPlatformDefaultConfigs) {
3445
+ return merge(AXPPlatformDefaultConfigs, config);
3446
+ }
3447
+
3448
+ const AXP_ROOT_CONFIG_TOKEN = new InjectionToken('AXP_ROOT_CONFIG_TOKEN');
3449
+
3450
+ class AXPFileStorageService {
3451
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3452
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileStorageService }); }
3453
+ }
3454
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileStorageService, decorators: [{
3455
+ type: Injectable
3456
+ }] });
3457
+
3458
+ var AXPFileStorageStatus;
3459
+ (function (AXPFileStorageStatus) {
3460
+ AXPFileStorageStatus["Temporary"] = "temporary";
3461
+ AXPFileStorageStatus["Committed"] = "committed";
3462
+ AXPFileStorageStatus["PendingDeletion"] = "pendingDeletion";
3463
+ AXPFileStorageStatus["Archived"] = "archived";
3464
+ AXPFileStorageStatus["Error"] = "error";
3465
+ })(AXPFileStorageStatus || (AXPFileStorageStatus = {}));
3466
+
3467
+ //#endregion
3468
+ //#region ---- Injection Token ----
3469
+ /**
3470
+ * Multi-provider injection token for file action providers.
3471
+ * Modules can provide multiple implementations using this token.
3472
+ */
3473
+ const AXP_FILE_ACTION_PROVIDER = new InjectionToken('AXP_FILE_ACTION_PROVIDER');
3474
+ //#endregion
3475
+
3476
+ //#region ---- Service ----
3477
+ /**
3478
+ * Service for managing file uploader actions.
3479
+ * Aggregates actions from multiple providers and filters them based on plugin configuration.
3480
+ * Wraps the hook system for backward compatibility.
3481
+ */
3482
+ class AXPFileActionsService {
3483
+ constructor() {
3484
+ //#region ---- Dependencies ----
3485
+ this.actionProviders = inject(AXP_FILE_ACTION_PROVIDER, { optional: true }) || [];
3486
+ this.hookService = inject(AXPHookService);
3487
+ this.injector = inject(Injector);
3488
+ }
3489
+ //#endregion
3490
+ //#region ---- Public API ----
3491
+ /**
3492
+ * Get all actions from providers, filtered based on plugin configuration.
3493
+ * Wraps the hook system for backward compatibility.
3494
+ * @param payload Initial payload with capabilities and plugin configuration.
3495
+ * @returns Filtered list of actions.
3496
+ */
3497
+ async getActions(payload) {
3498
+ // First, run hook system for backward compatibility
3499
+ // Note: Hook system may still use old format with 'host', but we pass capabilities
3500
+ // Hook providers that need host will need to be migrated to use capabilities
3501
+ let hookPayload;
3502
+ try {
3503
+ hookPayload = await this.hookService.runAsync('file-uploader.actions', {
3504
+ ...payload,
3505
+ // For backward compatibility, hooks might expect 'host' but we're using capabilities
3506
+ // Old hook providers will need to be migrated
3507
+ });
3508
+ }
3509
+ catch (err) {
3510
+ // If hook fails, continue with new system
3511
+ console.warn('[AXPFileActionsService] Hook system failed, continuing with providers only', err);
3512
+ }
3513
+ // Merge hook actions into payload (if any)
3514
+ const mergedPayload = {
3515
+ ...payload,
3516
+ actions: hookPayload?.actions ?? payload.actions ?? [],
3517
+ };
3518
+ // Resolve all providers (handle both direct and Promise<provider>)
3519
+ const providers = await this.resolveProviders();
3520
+ // Filter providers by key
3521
+ const matchingProviders = providers
3522
+ .filter((p) => p.key === 'file-uploader.actions')
3523
+ .sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
3524
+ // Execute providers sequentially (waterfall pattern)
3525
+ let currentPayload = { ...mergedPayload, actions: [...mergedPayload.actions] };
3526
+ for (const provider of matchingProviders) {
3527
+ try {
3528
+ currentPayload = await Promise.resolve(runInInjectionContext(this.injector, () => provider.execute(currentPayload)));
3529
+ }
3530
+ catch (err) {
3531
+ console.error(`[AXPFileActionsService] Provider '${provider.key}' failed`, err);
3532
+ }
3533
+ }
3534
+ // Filter actions based on plugin configuration
3535
+ return this.filterActions(currentPayload.actions, payload.plugins, payload.excludePlugins);
3536
+ }
3537
+ //#endregion
3538
+ //#region ---- Private Methods ----
3539
+ /**
3540
+ * Resolve all providers (handle both direct providers and Promise<provider>).
3541
+ */
3542
+ async resolveProviders() {
3543
+ return Promise.all(this.actionProviders.map((p) => (p instanceof Promise ? p : Promise.resolve(p))));
3544
+ }
3545
+ /**
3546
+ * Filter actions based on enabled plugins and exclude list.
3547
+ */
3548
+ filterActions(actions, enabledPlugins, excludePlugins) {
3549
+ const enabledPluginNames = enabledPlugins?.map((p) => p.name) ?? [];
3550
+ const excludedPluginNames = excludePlugins ?? [];
3551
+ return actions.filter((action) => {
3552
+ // Exclude if in exclude list
3553
+ if (excludedPluginNames.includes(action.plugin)) {
3554
+ return false;
3555
+ }
3556
+ // Include if global
3557
+ if (action.global === true) {
3558
+ return true;
3559
+ }
3560
+ // Include if plugin is explicitly enabled
3561
+ if (enabledPluginNames.length > 0 && enabledPluginNames.includes(action.plugin)) {
3562
+ return true;
3563
+ }
3564
+ // If no plugins are enabled, only show global actions
3565
+ if (enabledPluginNames.length === 0) {
3566
+ return !!action.global;
3567
+ }
3568
+ return false;
3569
+ });
3570
+ }
3571
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileActionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3572
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileActionsService, providedIn: 'root' }); }
3573
+ }
3574
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileActionsService, decorators: [{
3575
+ type: Injectable,
3576
+ args: [{
3577
+ providedIn: 'root',
3578
+ }]
3579
+ }] });
3580
+
3581
+ //#endregion
3582
+
3583
+ const UploadFromComputerActionProvider = {
3584
+ key: 'file-uploader.actions',
3585
+ priority: 1, // Higher priority than upload-from-drive to show first
3586
+ execute: (payload) => {
3587
+ const fileService = inject(AXFileService);
3588
+ // Capture widget options for use in the action
3589
+ const widgetOptions = payload.options;
3590
+ payload.actions = [
3591
+ ...payload.actions,
3592
+ {
3593
+ plugin: 'upload-from-computer',
3594
+ global: true,
3595
+ textKey: '@document-management:actions.upload-from-device',
3596
+ icon: 'fa-light fa-file-arrow-up',
3597
+ run: async (capabilities) => {
3598
+ // Open file picker with widget options
3599
+ const files = await fileService.choose({
3600
+ multiple: widgetOptions?.multiple ?? true,
3601
+ accept: widgetOptions?.accept,
3602
+ });
3603
+ // If no files are selected, return
3604
+ if (files.length === 0) {
3605
+ return;
3606
+ }
3607
+ // Create file list items from selected files
3608
+ const fileItems = files.map((file) => ({
3609
+ id: AXPDataGenerator.uuid(),
3610
+ name: file.name,
3611
+ size: file.size,
3612
+ status: 'attached',
3613
+ source: {
3614
+ kind: 'blob',
3615
+ value: file,
3616
+ },
3617
+ }));
3618
+ // Add files using capabilities
3619
+ capabilities.addFiles(fileItems);
3620
+ },
3621
+ },
3622
+ ];
3623
+ return payload;
3624
+ },
3625
+ };
3626
+
3627
+ const AXP_FILE_TYPE_INFO_PROVIDER = new InjectionToken('AXP_FILE_TYPE_INFO_PROVIDER');
3628
+ class AXPFileTypeProviderService {
3629
+ constructor() {
3630
+ this.providers = inject(AXP_FILE_TYPE_INFO_PROVIDER, { optional: true });
3631
+ }
3632
+ async items() {
3633
+ const items = [];
3634
+ if (Array.isArray(this.providers)) {
3635
+ for (const provider of this.providers) {
3636
+ items.push(...(await provider.items()));
3637
+ }
3638
+ }
3639
+ return items;
3640
+ }
3641
+ async get(name) {
3642
+ return (await this.items()).find((c) => c.name == name);
3643
+ }
3644
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3645
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, providedIn: 'root' }); }
3646
+ }
3647
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, decorators: [{
3648
+ type: Injectable,
3649
+ args: [{ providedIn: 'root' }]
3650
+ }] });
3651
+
3652
+ class AXPLockService {
3653
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLockService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3654
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLockService }); }
3655
+ }
3656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLockService, decorators: [{
3657
+ type: Injectable
3658
+ }] });
3659
+
3660
+ /**
3661
+ * Status Definition Types
3662
+ * Defines the structure for status definitions and their transitions
3663
+ */
3664
+ /**
3665
+ * Abstract class for status providers
3666
+ * Similar to AXPTaskBadgeProvider pattern
3667
+ */
3668
+ class AXPStatusProvider {
3669
+ }
3670
+ //#endregion
3671
+
3672
+ //#region ---- Injection Token ----
3673
+ /**
3674
+ * Injection token for status providers
3675
+ * Use with multi: true to register multiple providers
3676
+ */
3677
+ const AXP_STATUS_PROVIDERS = new InjectionToken('AXP_STATUS_PROVIDERS');
3678
+ //#endregion
3679
+ //#region ---- Provider Service ----
3680
+ /**
3681
+ * Service for managing status definitions from multiple providers
3682
+ * Similar to AXPTaskBadgeService pattern - no cache, direct access
3683
+ *
3684
+ * @example
3685
+ * ```typescript
3686
+ * // In a module providers array:
3687
+ * {
3688
+ * provide: AXP_STATUS_PROVIDERS,
3689
+ * useClass: TaskStatusProvider,
3690
+ * multi: true,
3691
+ * }
3692
+ *
3693
+ * // Example provider implementation:
3694
+ * export class TaskStatusProvider extends AXPStatusProvider {
3695
+ * readonly key = 'task-management.status';
3696
+ * readonly statuses = [
3697
+ * { name: 'todo', title: 'To Do', color: '#6b7280', icon: 'fa-light fa-circle', isInitial: true },
3698
+ * { name: 'in-progress', title: 'In Progress', color: '#3b82f6', icon: 'fa-light fa-play' },
3699
+ * { name: 'done', title: 'Done', color: '#10b981', icon: 'fa-light fa-check-circle', isFinal: true },
3700
+ * ];
3701
+ * readonly transitions = [
3702
+ * { from: 'todo', to: 'in-progress', title: 'Start', condition: '{{user.canEdit}}' },
3703
+ * { from: 'in-progress', to: 'done', title: 'Complete' },
3704
+ * ];
3705
+ * readonly defaultStatus = 'todo';
3706
+ * }
3707
+ *
3708
+ * // Later, get the status:
3709
+ * const status = await statusService.getStatus('task-management.status');
3710
+ * if (status) {
3711
+ * console.log('Statuses:', status.statuses);
3712
+ * console.log('Transitions:', status.transitions);
3713
+ * }
3714
+ * ```
3715
+ */
3716
+ class AXPStatusDefinitionProviderService {
3717
+ constructor() {
3718
+ //#region ---- Dependencies ----
3719
+ this.providers = inject(AXP_STATUS_PROVIDERS, { optional: true }) ?? [];
3720
+ this.commandService = inject(AXPCommandService);
3721
+ //#endregion
3722
+ //#region ---- State ----
3723
+ this.statusMap = new Map();
3724
+ this.initializationPromise = null;
3725
+ this.isInitialized = false;
3726
+ }
3727
+ //#endregion
3728
+ //#region ---- Initialization ----
3729
+ /**
3730
+ * Initialize providers (resolve promises if needed)
3731
+ * Called lazily on first access
3732
+ */
3733
+ async initialize() {
3734
+ if (this.isInitialized) {
3735
+ return;
3736
+ }
3737
+ if (this.initializationPromise) {
3738
+ return this.initializationPromise;
3739
+ }
3740
+ this.initializationPromise = this._doInitialize();
3741
+ await this.initializationPromise;
3742
+ }
3743
+ async _doInitialize() {
3744
+ // Register all providers, resolving promises if needed
3745
+ for (const provider of this.providers) {
3746
+ let resolvedProvider;
3747
+ if (provider instanceof Promise) {
3748
+ // If provider is a promise, resolve it
3749
+ resolvedProvider = await provider;
3750
+ }
3751
+ else {
3752
+ // If provider is a direct instance, use it directly
3753
+ resolvedProvider = provider;
3754
+ }
3755
+ if (this.statusMap.has(resolvedProvider.key)) {
3756
+ console.warn(`Status with key "${resolvedProvider.key}" already exists. Overwriting with new status.`);
3757
+ }
3758
+ this.statusMap.set(resolvedProvider.key, resolvedProvider);
3759
+ }
3760
+ this.isInitialized = true;
3761
+ }
3762
+ //#endregion
3763
+ //#region ---- Public API ----
3764
+ /**
3765
+ * Get a status provider by key
3766
+ * Ensures initialization is complete before accessing the status map.
3767
+ *
3768
+ * @param key - Status key (e.g., 'task-management.status')
3769
+ * @returns Promise that resolves to status provider with all statuses and transitions, or undefined if not found
3770
+ *
3771
+ * @example
3772
+ * ```typescript
3773
+ * const status = await statusService.getStatus('task-management.status');
3774
+ * if (status) {
3775
+ * console.log('Statuses:', status.statuses);
3776
+ * console.log('Transitions:', status.transitions);
3777
+ * }
3778
+ * ```
3779
+ */
3780
+ async getStatus(key) {
3781
+ await this.initialize();
3782
+ return this.statusMap.get(key);
3783
+ }
3784
+ /**
3785
+ * Execute a status transition workflow action
3786
+ * Uses transition.command if provided, otherwise defaults to Entity:UpdateStatus
3787
+ * Validates the transition is allowed before executing
3788
+ *
3789
+ * @param definitionKey - Status definition key
3790
+ * @param transition - The transition to execute
3791
+ * @param context - Context data for the command (must include entity name and id/ids)
3792
+ * @returns Promise that resolves when the command execution completes
3793
+ *
3794
+ * @example
3795
+ * ```typescript
3796
+ * await statusService.executeTransition(
3797
+ * 'task-management.status',
3798
+ * { from: 'todo', to: 'in-progress' },
3799
+ * { entity: 'TaskManagement.Task', id: '123', ...entityData }
3800
+ * );
3801
+ * ```
3802
+ */
3803
+ async executeTransition(definitionKey, transition, context) {
3804
+ await this.initialize();
3805
+ const provider = this.statusMap.get(definitionKey);
3806
+ if (!provider) {
3807
+ throw new Error(`Status provider with key "${definitionKey}" not found.`);
3808
+ }
3809
+ // Validate transition is allowed
3810
+ if (!this.isValidTransition(provider, transition.from, transition.to)) {
3811
+ throw new Error(`Invalid transition from "${transition.from}" to "${transition.to}"`);
3812
+ }
3813
+ // Determine which command to use
3814
+ let commandName;
3815
+ let commandOptions;
3816
+ if (transition.command) {
3817
+ // Use transition's explicit command
3818
+ commandName = transition.command.name;
3819
+ commandOptions = {
3820
+ ...(transition.command.options ?? {}),
3821
+ ...context,
3822
+ };
3823
+ }
3824
+ else {
3825
+ // Use default Entity:UpdateStatus command
3826
+ const entity = context['entityName'] ?? context['__meta__']?.config?.name;
3827
+ if (!entity) {
3828
+ throw new Error('Entity name is required in context when using default status update command');
3829
+ }
3830
+ const id = context['id'];
3831
+ const ids = context['ids'];
3832
+ if (!id && !ids) {
3833
+ throw new Error('Either id or ids must be provided in context');
3834
+ }
3835
+ commandName = 'Entity:UpdateStatus';
3836
+ commandOptions = {
3837
+ entity,
3838
+ status: transition.to,
3839
+ statusField: context['statusField'] ?? 'statusId',
3840
+ ...(id ? { id } : {}),
3841
+ ...(ids ? { ids } : {}),
3842
+ };
3843
+ }
3844
+ // Execute the command
3845
+ const result = await this.commandService.execute(commandName, commandOptions);
3846
+ if (!result?.success) {
3847
+ throw new Error(result?.message?.text || 'Failed to execute status transition command');
3848
+ }
3849
+ }
3850
+ /**
3851
+ * Validate if a transition is allowed
3852
+ * Checks if the transition exists in the provider's transitions list
3853
+ */
3854
+ isValidTransition(provider, from, to) {
3855
+ return provider.transitions.some((transition) => transition.from === from && transition.to === to);
3856
+ }
3857
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3858
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, providedIn: 'root' }); }
3859
+ }
3860
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, decorators: [{
3861
+ type: Injectable,
3862
+ args: [{ providedIn: 'root' }]
3863
+ }] });
3864
+
3865
+ /**
3866
+ * Standard system status types
3867
+ * These are the predefined status values used across the platform
3868
+ */
3869
+ var AXPSystemStatusType;
3870
+ (function (AXPSystemStatusType) {
3871
+ AXPSystemStatusType["Todo"] = "todo";
3872
+ AXPSystemStatusType["InProgress"] = "in-progress";
3873
+ AXPSystemStatusType["InReview"] = "in-review";
3874
+ AXPSystemStatusType["Open"] = "open";
3875
+ AXPSystemStatusType["Closed"] = "closed";
3876
+ AXPSystemStatusType["Blocked"] = "blocked";
3877
+ AXPSystemStatusType["Done"] = "done";
3878
+ AXPSystemStatusType["Cancelled"] = "cancelled";
3879
+ AXPSystemStatusType["Draft"] = "draft";
3880
+ AXPSystemStatusType["PendingReview"] = "pending-review";
3881
+ AXPSystemStatusType["Approved"] = "approved";
3882
+ AXPSystemStatusType["Published"] = "published";
3883
+ AXPSystemStatusType["Archived"] = "archived";
3884
+ AXPSystemStatusType["Rejected"] = "rejected";
3885
+ AXPSystemStatusType["Active"] = "active";
3886
+ AXPSystemStatusType["Inactive"] = "inactive";
3887
+ AXPSystemStatusType["Pending"] = "pending";
3888
+ AXPSystemStatusType["Completed"] = "completed";
3889
+ AXPSystemStatusType["Suspended"] = "suspended";
3890
+ AXPSystemStatusType["Failed"] = "failed";
3891
+ AXPSystemStatusType["Review"] = "review";
3892
+ AXPSystemStatusType["Expired"] = "expired";
3893
+ })(AXPSystemStatusType || (AXPSystemStatusType = {}));
3894
+ const i18n = (key) => `@general:statuses.${key}`;
3895
+ /**
3896
+ * Standard system status definitions
3897
+ * Provides consistent status definitions across the platform
3898
+ * Uses AXPStatusDefinition interface from status-definition.types.ts
3899
+ */
3900
+ const AXPSystemStatuses = Object.freeze({
3901
+ Open: {
3902
+ name: AXPSystemStatusType.Open,
3903
+ title: i18n('open.title'),
3904
+ icon: 'fa-light fa-circle',
3905
+ color: 'secondary',
3906
+ description: i18n('open.description'),
3907
+ order: 1,
3908
+ isInitial: true,
3909
+ isFinal: false,
3910
+ },
3911
+ Closed: {
3912
+ name: AXPSystemStatusType.Closed,
3913
+ title: i18n('closed.title'),
3914
+ icon: 'fa-light fa-circle',
3915
+ color: 'danger',
3916
+ description: i18n('closed.description'),
3917
+ order: 2,
3918
+ isInitial: false,
3919
+ isFinal: true,
3920
+ },
3921
+ Todo: {
3922
+ name: AXPSystemStatusType.Todo,
3923
+ title: i18n('todo.title'),
3924
+ icon: 'fa-light fa-circle',
3925
+ color: 'secondary',
3926
+ description: i18n('todo.description'),
3927
+ order: 1,
3928
+ isInitial: true,
3929
+ isFinal: false,
3930
+ },
3931
+ InProgress: {
3932
+ name: AXPSystemStatusType.InProgress,
3933
+ title: i18n('in-progress.title'),
3934
+ icon: 'fa-light fa-play',
3935
+ color: 'info',
3936
+ description: i18n('in-progress.description'),
3937
+ order: 2,
3938
+ isInitial: false,
3939
+ isFinal: false,
3940
+ },
3941
+ InReview: {
3942
+ name: AXPSystemStatusType.InReview,
3943
+ title: i18n('in-review.title'),
3944
+ icon: 'fa-light fa-eye',
3945
+ color: 'info',
3946
+ description: i18n('in-review.description'),
3947
+ order: 3,
3948
+ isInitial: false,
3949
+ isFinal: false,
3950
+ },
3951
+ Blocked: {
3952
+ name: AXPSystemStatusType.Blocked,
3953
+ title: i18n('blocked.title'),
3954
+ icon: 'fa-light fa-ban',
3955
+ color: 'danger',
3956
+ description: i18n('blocked.description'),
3957
+ order: 4,
3958
+ isInitial: false,
3959
+ isFinal: false,
3960
+ },
3961
+ Done: {
3962
+ name: AXPSystemStatusType.Done,
3963
+ title: i18n('done.title'),
3964
+ icon: 'fa-light fa-check-circle',
3965
+ color: 'success',
3966
+ description: i18n('done.description'),
3967
+ order: 5,
3968
+ isInitial: false,
3969
+ isFinal: true,
3970
+ },
3971
+ Cancelled: {
3972
+ name: AXPSystemStatusType.Cancelled,
3973
+ title: i18n('cancelled.title'),
3974
+ icon: 'fa-light fa-times-circle',
3975
+ color: 'neutral',
3976
+ description: i18n('cancelled.description'),
3977
+ order: 6,
3978
+ isInitial: false,
3979
+ isFinal: true,
3980
+ },
3981
+ Draft: {
3982
+ name: AXPSystemStatusType.Draft,
3983
+ title: i18n('draft.title'),
3984
+ icon: 'fa-light fa-file-pen',
3985
+ color: 'neutral',
3986
+ description: i18n('draft.description'),
3987
+ order: 1,
3988
+ isInitial: true,
3989
+ isFinal: false,
3990
+ },
3991
+ PendingReview: {
3992
+ name: AXPSystemStatusType.PendingReview,
3993
+ title: i18n('pending-review.title'),
3994
+ icon: 'fa-light fa-clock',
3995
+ color: 'warning',
3996
+ description: i18n('pending-review.description'),
3997
+ order: 2,
3998
+ isInitial: false,
3999
+ isFinal: false,
4000
+ },
4001
+ Approved: {
4002
+ name: AXPSystemStatusType.Approved,
4003
+ title: i18n('approved.title'),
4004
+ icon: 'fa-light fa-check-circle',
4005
+ color: 'success',
4006
+ description: i18n('approved.description'),
4007
+ order: 3,
4008
+ isInitial: false,
4009
+ isFinal: false,
4010
+ },
4011
+ Published: {
4012
+ name: AXPSystemStatusType.Published,
4013
+ title: i18n('published.title'),
4014
+ icon: 'fa-light fa-globe',
4015
+ color: 'primary',
4016
+ description: i18n('published.description'),
4017
+ order: 4,
4018
+ isInitial: false,
4019
+ isFinal: false,
4020
+ },
4021
+ Archived: {
4022
+ name: AXPSystemStatusType.Archived,
4023
+ title: i18n('archived.title'),
4024
+ icon: 'fa-light fa-archive',
4025
+ color: 'danger',
4026
+ description: i18n('archived.description'),
4027
+ order: 5,
4028
+ isInitial: false,
4029
+ isFinal: true,
4030
+ },
4031
+ Rejected: {
4032
+ name: AXPSystemStatusType.Rejected,
4033
+ title: i18n('rejected.title'),
4034
+ icon: 'fa-light fa-times-circle',
4035
+ color: 'danger',
4036
+ description: i18n('rejected.description'),
4037
+ order: 6,
4038
+ isInitial: false,
4039
+ isFinal: true,
4040
+ },
4041
+ Active: {
4042
+ name: AXPSystemStatusType.Active,
4043
+ title: i18n('active.title'),
4044
+ icon: 'fa-light fa-check-circle',
4045
+ color: 'success',
4046
+ description: i18n('active.description'),
4047
+ order: 1,
4048
+ isInitial: false,
4049
+ isFinal: false,
4050
+ },
4051
+ Inactive: {
4052
+ name: AXPSystemStatusType.Inactive,
4053
+ title: i18n('inactive.title'),
4054
+ icon: 'fa-light fa-circle',
4055
+ color: 'secondary',
4056
+ description: i18n('inactive.description'),
4057
+ order: 2,
4058
+ isInitial: false,
4059
+ isFinal: false,
4060
+ },
4061
+ Pending: {
4062
+ name: AXPSystemStatusType.Pending,
4063
+ title: i18n('pending.title'),
4064
+ icon: 'fa-light fa-clock',
4065
+ color: 'warning',
4066
+ description: i18n('pending.description'),
4067
+ order: 1,
4068
+ isInitial: true,
4069
+ isFinal: false,
4070
+ },
4071
+ Completed: {
4072
+ name: AXPSystemStatusType.Completed,
4073
+ title: i18n('completed.title'),
4074
+ icon: 'fa-light fa-check-circle',
4075
+ color: 'success',
4076
+ description: i18n('completed.description'),
4077
+ order: 10,
4078
+ isInitial: false,
4079
+ isFinal: true,
4080
+ },
4081
+ Suspended: {
4082
+ name: AXPSystemStatusType.Suspended,
4083
+ title: i18n('suspended.title'),
4084
+ icon: 'fa-light fa-pause-circle',
4085
+ color: 'neutral',
4086
+ description: i18n('suspended.description'),
4087
+ order: 5,
4088
+ isInitial: false,
4089
+ isFinal: false,
4090
+ },
4091
+ Failed: {
4092
+ name: AXPSystemStatusType.Failed,
4093
+ title: i18n('failed.title'),
4094
+ icon: 'fa-light fa-xmark-circle',
4095
+ color: 'danger',
4096
+ description: i18n('failed.description'),
4097
+ order: 10,
4098
+ isInitial: false,
4099
+ isFinal: true,
4100
+ },
4101
+ Review: {
4102
+ name: AXPSystemStatusType.Review,
4103
+ title: i18n('review.title'),
4104
+ icon: 'fa-light fa-eye',
4105
+ color: 'info',
4106
+ description: i18n('review.description'),
4107
+ order: 3,
4108
+ },
4109
+ Expired: {
4110
+ name: AXPSystemStatusType.Expired,
4111
+ title: i18n('expired.title'),
4112
+ icon: 'fa-light fa-clock',
4113
+ color: 'danger',
4114
+ description: i18n('expired.description'),
4115
+ order: 10,
4116
+ isInitial: false,
4117
+ isFinal: true,
4118
+ },
4119
+ });
4120
+ /**
4121
+ * Get system status definition by type
4122
+ * @param type - Status type
4123
+ * @returns System status definition or undefined
4124
+ */
4125
+ function getSystemStatus(type) {
4126
+ return Object.values(AXPSystemStatuses).find(status => status.name === type);
4127
+ }
4128
+ /**
4129
+ * Resolves the visual appearance (color and icon) for status
4130
+ * using the system statuses from the core module.
4131
+ * @param statusType - Status type string
4132
+ * @returns Color and icon for the status
4133
+ */
4134
+ function resolveStatusLook(statusType) {
4135
+ // Try to get system status first
4136
+ const systemStatusType = statusType;
4137
+ if (systemStatusType) {
4138
+ const systemStatus = getSystemStatus(systemStatusType);
4139
+ if (systemStatus) {
4140
+ // Convert hex color to semantic color type if needed
4141
+ // For now, return as-is and let the UI handle it
4142
+ return {
4143
+ color: systemStatus.color,
4144
+ icon: systemStatus.icon || ''
4145
+ };
4146
+ }
4147
+ }
4148
+ // Fallback for unknown statuses
4149
+ return {
4150
+ color: 'secondary',
4151
+ icon: ''
4152
+ };
4153
+ }
4154
+ /**
4155
+ * Resolves the complete status information (title, description, icon, color) for a status
4156
+ * using the system statuses from the core module.
4157
+ * @param statusType - Status type string
4158
+ * @returns Complete status information as AXPStatusDefinition
4159
+ */
4160
+ function getStatusInfo(statusType) {
4161
+ const systemStatusType = statusType;
4162
+ if (systemStatusType) {
4163
+ const systemStatus = getSystemStatus(systemStatusType);
4164
+ if (systemStatus) {
4165
+ return systemStatus;
4166
+ }
4167
+ }
4168
+ // Fallback for unknown statuses
4169
+ return {
4170
+ name: statusType,
4171
+ title: statusType,
4172
+ description: `Status: ${statusType}`,
4173
+ icon: '',
4174
+ color: 'secondary'
4175
+ };
4176
+ }
4177
+ /**
4178
+ * Get system status definition directly (no conversion needed since it's already AXPStatusDefinition)
4179
+ * @param statusType - Status type
4180
+ * @param overrides - Optional overrides for the status definition
4181
+ * @returns AXPStatusDefinition
4182
+ */
4183
+ function systemStatusToDefinition(statusType, overrides) {
4184
+ const systemStatus = getSystemStatus(statusType);
4185
+ if (!systemStatus) {
4186
+ throw new Error(`System status ${statusType} not found`);
4187
+ }
4188
+ return {
4189
+ ...systemStatus,
4190
+ ...overrides,
4191
+ };
4192
+ }
4193
+
4194
+ class AXPClipBoardService {
4195
+ constructor() {
4196
+ this.toast = inject(AXToastService);
4197
+ }
4198
+ copy(title, value) {
4199
+ const copyText = document.createElement('input');
4200
+ copyText.type = 'text';
4201
+ copyText.select();
4202
+ copyText.setSelectionRange(0, 99999); // For mobile devices
4203
+ copyText.remove();
4204
+ navigator.clipboard.writeText(value);
4205
+ this.toast.success(`${title} copied!`);
4206
+ }
4207
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPClipBoardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4208
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPClipBoardService, providedIn: 'root' }); }
4209
+ }
4210
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPClipBoardService, decorators: [{
4211
+ type: Injectable,
4212
+ args: [{
4213
+ providedIn: 'root',
4214
+ }]
4215
+ }] });
4216
+
4217
+ //#region ---- Imports ----
4218
+ //#endregion
4219
+ //#region ---- Debug Service ----
4220
+ /**
4221
+ * Service for debugging user access information.
4222
+ * Displays loaded modules, features, and permissions for the current user.
4223
+ */
4224
+ class AXPDebugService {
4225
+ constructor() {
4226
+ //#region ---- Services & Dependencies ----
4227
+ this.sessionService = inject(AXPSessionService);
4228
+ this.manifestRegistry = inject(AXPModuleManifestRegistry);
4229
+ }
4230
+ //#endregion
4231
+ //#region ---- Public Methods ----
4232
+ /**
4233
+ * Display all loaded modules, features, and permissions for the current user.
4234
+ */
4235
+ async displayUserAccessInfo() {
4236
+ try {
4237
+ // Ensure registry is initialized
4238
+ await this.manifestRegistry.initialize();
4239
+ // Get all registered modules
4240
+ const allManifests = this.manifestRegistry.getAll();
4241
+ // Get all feature definitions
4242
+ const allFeatures = this.manifestRegistry.getAllFeatureDefinitions();
4243
+ // Get current user permissions
4244
+ const userPermissions = this.sessionService.permissions;
4245
+ const user = this.sessionService.user;
4246
+ console.group('🔐 User Access Information');
4247
+ console.log(`User: ${user?.name || user?.title || 'Unknown'} (${user?.id || 'N/A'})`);
4248
+ console.log('');
4249
+ if (allManifests.length === 0) {
4250
+ console.log('No modules loaded');
4251
+ console.groupEnd();
4252
+ return;
4253
+ }
4254
+ // Group features by module
4255
+ const featuresByModule = new Map();
4256
+ allFeatures.forEach((feature) => {
4257
+ const moduleName = feature.module;
4258
+ if (!featuresByModule.has(moduleName)) {
4259
+ featuresByModule.set(moduleName, []);
4260
+ }
4261
+ featuresByModule.get(moduleName).push(feature);
4262
+ });
4263
+ // Group permissions by module (if they follow ModuleName:PermissionKey pattern)
4264
+ const permissionsByModule = new Map();
4265
+ const ungroupedPermissions = [];
4266
+ userPermissions.forEach((permission) => {
4267
+ const parts = permission.split(':');
4268
+ if (parts.length >= 2) {
4269
+ const moduleName = parts[0];
4270
+ if (!permissionsByModule.has(moduleName)) {
4271
+ permissionsByModule.set(moduleName, []);
4272
+ }
4273
+ permissionsByModule.get(moduleName).push(permission);
4274
+ }
4275
+ else {
4276
+ ungroupedPermissions.push(permission);
4277
+ }
4278
+ });
4279
+ // Display modules in tree format
4280
+ allManifests.forEach((manifest) => {
4281
+ const moduleName = manifest.name;
4282
+ const moduleFeatures = featuresByModule.get(moduleName) || [];
4283
+ const modulePermissions = permissionsByModule.get(moduleName) || [];
4284
+ console.group(`📦 ${moduleName}`);
4285
+ // Display Features
4286
+ if (moduleFeatures.length > 0) {
4287
+ console.log(' --- Features:');
4288
+ moduleFeatures.forEach((feature) => {
4289
+ console.log(` • ${feature.name}`);
4290
+ });
4291
+ }
4292
+ else {
4293
+ console.log(' --- Features: (none)');
4294
+ }
4295
+ // Display Permissions
4296
+ if (modulePermissions.length > 0) {
4297
+ console.log(' --- Permissions:');
4298
+ modulePermissions.forEach((permission) => {
4299
+ console.log(` • ${permission}`);
4300
+ });
4301
+ }
4302
+ else {
4303
+ console.log(' --- Permissions: (none)');
4304
+ }
4305
+ console.groupEnd();
4306
+ });
4307
+ // Display ungrouped permissions if any
4308
+ if (ungroupedPermissions.length > 0) {
4309
+ console.group('📁 Other Permissions');
4310
+ ungroupedPermissions.forEach((permission) => {
4311
+ console.log(` • ${permission}`);
4312
+ });
4313
+ console.groupEnd();
4314
+ }
4315
+ // Summary
4316
+ console.log('');
4317
+ console.log(`Summary: ${allManifests.length} modules, ${allFeatures.length} features, ${userPermissions.length} permissions`);
4318
+ console.groupEnd();
4319
+ }
4320
+ catch (error) {
4321
+ console.error('[AXPDebugService] Failed to display user access info:', error);
4322
+ }
4323
+ }
4324
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDebugService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4325
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDebugService, providedIn: 'root' }); }
4326
+ }
4327
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDebugService, decorators: [{
4328
+ type: Injectable,
4329
+ args: [{
4330
+ providedIn: 'root',
4331
+ }]
4332
+ }] });
4333
+
4334
+ class AXMOrgChartPrintPage extends AXBasePageComponent {
4335
+ constructor() {
4336
+ super(...arguments);
4337
+ this.ratio = signal(false, ...(ngDevMode ? [{ debugName: "ratio" }] : /* istanbul ignore next */ []));
4338
+ this.baseWidth = signal(undefined, ...(ngDevMode ? [{ debugName: "baseWidth" }] : /* istanbul ignore next */ []));
4339
+ this.baseHeight = signal(undefined, ...(ngDevMode ? [{ debugName: "baseHeight" }] : /* istanbul ignore next */ []));
4340
+ this.bgcolor = model(...(ngDevMode ? [undefined, { debugName: "bgcolor" }] : /* istanbul ignore next */ []));
4341
+ this.width = model(...(ngDevMode ? [undefined, { debugName: "width" }] : /* istanbul ignore next */ []));
4342
+ this.height = model(...(ngDevMode ? [undefined, { debugName: "height" }] : /* istanbul ignore next */ []));
4343
+ this.quality = model(...(ngDevMode ? [undefined, { debugName: "quality" }] : /* istanbul ignore next */ []));
4344
+ this.qualityComputed = linkedSignal(() => (this.data.quality ?? 1) * 100, ...(ngDevMode ? [{ debugName: "qualityComputed" }] : /* istanbul ignore next */ []));
4345
+ this.scale = model(...(ngDevMode ? [undefined, { debugName: "scale" }] : /* istanbul ignore next */ []));
4346
+ this.#init = afterNextRender(() => {
4347
+ this.bgcolor.set(this.data.bgcolor);
4348
+ this.width.set(this.data.width);
4349
+ this.baseWidth.set(this.data.width);
4350
+ this.height.set(this.data.height);
4351
+ this.baseHeight.set(this.data.height);
4352
+ this.quality.set(this.data.quality);
4353
+ this.scale.set(this.data.scale);
4354
+ });
4355
+ }
4356
+ #init;
4357
+ calculateRatio(event, type) {
4358
+ if (!this.ratio() || !event.isUserInteraction)
4359
+ return;
4360
+ const value = event.value;
4361
+ if (type === 'width') {
4362
+ const newHeight = Math.round((value / this.baseWidth()) * this.baseHeight() * 100) / 100;
4363
+ this.height.set(newHeight);
4364
+ this.width.set(value);
4365
+ }
4366
+ else {
4367
+ const newWidth = Math.round((value / this.baseHeight()) * this.baseWidth() * 100) / 100;
4368
+ this.width.set(newWidth);
4369
+ this.height.set(value);
4370
+ }
4371
+ }
4372
+ async handleClose(isCanceled = false) {
4373
+ this.close({
4374
+ bgcolor: this.bgcolor(),
4375
+ width: this.width(),
4376
+ height: this.height(),
4377
+ quality: this.qualityComputed() / 100,
4378
+ scale: this.scale(),
4379
+ isCanceled,
4380
+ });
4381
+ }
4382
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMOrgChartPrintPage, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4383
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AXMOrgChartPrintPage, isStandalone: true, selector: "ng-component", inputs: { bgcolor: { classPropertyName: "bgcolor", publicName: "bgcolor", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bgcolor: "bgcolorChange", width: "widthChange", height: "heightChange", quality: "qualityChange", scale: "scaleChange" }, usesInheritance: true, ngImport: i0, template: ` <div class="ax-grid ax-grid-cols-[auto_18rem] ax-gap-4 ax-justify-center ax-p-4 ax-items-center">
4384
+ <ax-label>Resolution (px)</ax-label>
4385
+ <div class="ax-flex ax-gap-2 ax-items-center">
4386
+ <ax-number-box
4387
+ [changeOnScroll]="true"
4388
+ [decimals]="4"
4389
+ [value]="width()"
4390
+ (onValueChanged)="calculateRatio($event, 'width')"
4391
+ name="Width"
4392
+ >
4393
+ </ax-number-box>
4394
+ <ax-button [toggleable]="true" [(selected)]="ratio"
4395
+ ><ax-icon><i class="fa-solid fa-vector-square"></i></ax-icon
4396
+ ></ax-button>
4397
+ <ax-number-box
4398
+ [changeOnScroll]="true"
4399
+ [decimals]="4"
4400
+ [value]="height()"
4401
+ (onValueChanged)="calculateRatio($event, 'height')"
4402
+ name="Height"
4403
+ >
4404
+ </ax-number-box>
4405
+ </div>
4406
+
4407
+ <ax-label>Background color</ax-label>
4408
+ <ax-color-box [(ngModel)]="bgcolor"></ax-color-box>
4409
+
4410
+ <ax-label>Quality of image (50-100%)</ax-label>
4411
+ <ax-number-box
4412
+ [changeOnScroll]="true"
4413
+ [minValue]="50"
4414
+ [maxValue]="100"
4415
+ [(ngModel)]="qualityComputed"
4416
+ name="Quality"
4417
+ >
4418
+ </ax-number-box>
4419
+
4420
+ <ax-label>Scale</ax-label>
4421
+ <ax-number-box [changeOnScroll]="true" [minValue]="1" [(ngModel)]="scale" name="scale"> </ax-number-box>
4422
+ </div>
4423
+
4424
+ <ax-footer>
4425
+ <ax-prefix> </ax-prefix>
4426
+ <ax-suffix>
4427
+ <ax-button text="Cancel" look="solid" (onClick)="handleClose(true)"> </ax-button>
4428
+ <ax-button text="Print" look="solid" color="primary" (onClick)="handleClose()">
4429
+ <ax-icon class="fa-solid fa-print"> </ax-icon>
4430
+ </ax-button>
4431
+ </ax-suffix>
4432
+ </ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXNumberBoxModule }, { kind: "component", type: i2.AXNumberBoxComponent, selector: "ax-number-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "minValue", "maxValue", "showSpinButtons", "thousandsSeparator", "decimals", "changeOnScroll", "step"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "thousandsSeparatorChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i4.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i5.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXColorBoxModule }, { kind: "component", type: i6.AXColorBoxComponent, selector: "ax-color-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "showBadge", "showValue", "showClearButton", "showIcon"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed"] }] }); }
4433
+ }
4434
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMOrgChartPrintPage, decorators: [{
4435
+ type: Component,
4436
+ args: [{
4437
+ template: ` <div class="ax-grid ax-grid-cols-[auto_18rem] ax-gap-4 ax-justify-center ax-p-4 ax-items-center">
4438
+ <ax-label>Resolution (px)</ax-label>
4439
+ <div class="ax-flex ax-gap-2 ax-items-center">
4440
+ <ax-number-box
4441
+ [changeOnScroll]="true"
4442
+ [decimals]="4"
4443
+ [value]="width()"
4444
+ (onValueChanged)="calculateRatio($event, 'width')"
4445
+ name="Width"
4446
+ >
4447
+ </ax-number-box>
4448
+ <ax-button [toggleable]="true" [(selected)]="ratio"
4449
+ ><ax-icon><i class="fa-solid fa-vector-square"></i></ax-icon
4450
+ ></ax-button>
4451
+ <ax-number-box
4452
+ [changeOnScroll]="true"
4453
+ [decimals]="4"
4454
+ [value]="height()"
4455
+ (onValueChanged)="calculateRatio($event, 'height')"
4456
+ name="Height"
4457
+ >
4458
+ </ax-number-box>
4459
+ </div>
4460
+
4461
+ <ax-label>Background color</ax-label>
4462
+ <ax-color-box [(ngModel)]="bgcolor"></ax-color-box>
4463
+
4464
+ <ax-label>Quality of image (50-100%)</ax-label>
4465
+ <ax-number-box
4466
+ [changeOnScroll]="true"
4467
+ [minValue]="50"
4468
+ [maxValue]="100"
4469
+ [(ngModel)]="qualityComputed"
4470
+ name="Quality"
4471
+ >
4472
+ </ax-number-box>
4473
+
4474
+ <ax-label>Scale</ax-label>
4475
+ <ax-number-box [changeOnScroll]="true" [minValue]="1" [(ngModel)]="scale" name="scale"> </ax-number-box>
4476
+ </div>
4477
+
4478
+ <ax-footer>
4479
+ <ax-prefix> </ax-prefix>
4480
+ <ax-suffix>
4481
+ <ax-button text="Cancel" look="solid" (onClick)="handleClose(true)"> </ax-button>
4482
+ <ax-button text="Print" look="solid" color="primary" (onClick)="handleClose()">
4483
+ <ax-icon class="fa-solid fa-print"> </ax-icon>
4484
+ </ax-button>
4485
+ </ax-suffix>
4486
+ </ax-footer>`,
4487
+ imports: [
4488
+ FormsModule,
4489
+ AXCheckBoxModule,
4490
+ AXNumberBoxModule,
4491
+ AXTextBoxModule,
4492
+ AXLabelModule,
4493
+ AXDecoratorModule,
4494
+ AXButtonModule,
4495
+ AXColorBoxModule,
4496
+ ],
4497
+ }]
4498
+ }], propDecorators: { bgcolor: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgcolor", required: false }] }, { type: i0.Output, args: ["bgcolorChange"] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }, { type: i0.Output, args: ["widthChange"] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }, { type: i0.Output, args: ["heightChange"] }], quality: [{ type: i0.Input, args: [{ isSignal: true, alias: "quality", required: false }] }, { type: i0.Output, args: ["qualityChange"] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }, { type: i0.Output, args: ["scaleChange"] }] } });
4499
+
4500
+ // AXPPdfService
4501
+ class AXPExportService {
4502
+ constructor() {
4503
+ this.popupService = inject(AXPopupService);
4504
+ }
4505
+ async generateBlobFromElement(element, blobOptions) {
4506
+ const domtoimage = (await import('dom-to-image')).default;
4507
+ const originalWidth = element.scrollWidth;
4508
+ const originalHeight = element.scrollHeight;
4509
+ let popup, options = {}, newOptions = {};
4510
+ if (blobOptions) {
4511
+ ({ popup, ...options } = blobOptions);
4512
+ }
4513
+ if (popup) {
4514
+ const result = await this.popupService.open(AXMOrgChartPrintPage, {
4515
+ header: true,
4516
+ size: 'fit',
4517
+ draggable: true,
4518
+ hasBackdrop: true,
4519
+ title: 'Export Options',
4520
+ data: { data: options },
4521
+ });
4522
+ if (result.data.isCanceled) {
4523
+ throw new Error('Process is Canceled by User!');
4524
+ }
4525
+ else {
4526
+ newOptions = { ...options, ...result.data };
4527
+ }
4528
+ }
4529
+ return domtoimage.toBlob(element, {
4530
+ ...newOptions,
4531
+ width: (newOptions.width ?? originalWidth) * (newOptions?.scale ?? 1),
4532
+ height: (newOptions.height ?? originalHeight) * (newOptions?.scale ?? 1),
4533
+ style: {
4534
+ transform: `scale(${newOptions?.scale ?? 1})`,
4535
+ transformOrigin: 'top left',
4536
+ },
4537
+ });
4538
+ }
4539
+ download(blob, filename) {
4540
+ const link = document.createElement('a');
4541
+ link.href = URL.createObjectURL(blob);
4542
+ link.download = filename;
4543
+ document.body.appendChild(link);
4544
+ link.click();
4545
+ document.body.removeChild(link);
4546
+ URL.revokeObjectURL(link.href);
4547
+ }
4548
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4549
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExportService, providedIn: 'root' }); }
4550
+ }
4551
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPExportService, decorators: [{
4552
+ type: Injectable,
4553
+ args: [{
4554
+ providedIn: 'root',
4555
+ }]
4556
+ }] });
4557
+
4558
+ function AXPCleanNestedFilters(filters) {
4559
+ return filters
4560
+ .map((filter) => {
4561
+ if (!filter)
4562
+ return undefined;
4563
+ if (filter.filters?.length) {
4564
+ const cleanedNestedFilters = AXPCleanNestedFilters(filter.filters);
4565
+ if (!filter.field && !filter.operator && cleanedNestedFilters.length === 0) {
4566
+ return undefined;
4567
+ }
4568
+ return {
4569
+ ...filter,
4570
+ filters: cleanedNestedFilters.filter(Boolean),
4571
+ };
4572
+ }
4573
+ if ((!filter.value && filter.value != false) || filter.value === 'unknown') {
4574
+ return undefined;
4575
+ }
4576
+ return filter;
4577
+ })
4578
+ .filter(Boolean);
4579
+ }
4580
+
4581
+ const AXP_LOCALE_MANAGEMENT_PORT = new InjectionToken('AXP_LOCALE_MANAGEMENT_PORT');
4582
+
4583
+ //#region ---- Versioning Types ----
4584
+ var AXVChangeType;
4585
+ (function (AXVChangeType) {
4586
+ AXVChangeType["Create"] = "Create";
4587
+ AXVChangeType["Update"] = "Update";
4588
+ AXVChangeType["Delete"] = "Delete";
4589
+ })(AXVChangeType || (AXVChangeType = {}));
4590
+ //#endregion
4591
+ //#region ---- Service Contract ----
4592
+ class AXPVersioningService {
4593
+ }
4594
+ //#endregion
4595
+
4596
+ /**
4597
+ * Generated bundle index. Do not edit.
4598
+ */
4599
+
4600
+ export { ALL_DEFAULT_OPERATORS, AXMWorkflowErrorHandler, AXPAppVersionService, AXPCleanNestedFilters, AXPClipBoardService, AXPCommonModule, AXPCommonSettings, AXPCustomOperatorService, AXPCustomOperatorServiceImpl, AXPDataProvider, AXPDebugService, AXPDefaultMultiLanguageConfigService, AXPDialogConfirmAction, AXPEntityCommandScope, AXPEntityQueryType, AXPEntityType, AXPErrorHandlerRegistryService, AXPExportService, AXPFileActionsService, AXPFileStorageService, AXPFileStorageStatus, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPLockService, AXPMenuItemsDataSourceDefinition, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateWorkflow, AXPPlatformDefaultConfigs, AXPRedirectEvent, AXPRefreshEvent, AXPRegionalSetting, AXPRelationshipCardinality, AXPRelationshipKind, AXPReloadAction, AXPReloadEvent, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsEvaluatorScopeProvider, AXPSettingsService, AXPStatusDefinitionProviderService, AXPStatusProvider, AXPStickyDirective, AXPSystemStatusType, AXPSystemStatuses, AXPToastAction, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPVersioningService, AXPWorkflowNavigateAction, AXPWorkflowRouterNavigateAction, AXP_APP_VERSION_PROVIDER, AXP_FILE_ACTION_PROVIDER, AXP_FILE_TYPE_INFO_PROVIDER, AXP_HOME_PAGES, AXP_HOME_PAGE_DEFAULT_KEY, AXP_LOCALE_MANAGEMENT_PORT, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_PLATFORM_CONFIG_TOKEN, AXP_ROOT_CONFIG_TOKEN, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFAULT_VALUES_PROVIDERS, AXP_SETTING_DEFINITION_PROVIDER, AXP_SETTING_VALUE_PROVIDER, AXP_STATUS_PROVIDERS, AXP_TOKEN_DEFINITION_PROVIDER, AXVChangeType, BETWEEN_OPER, BOOLEAN_OPERATORS, CONTAINS_OPER, DATE_OPERATORS, DEFAULT_MULTILANGUAGE_FIELD_NAMES, ENDS_WITH_OPER, ENVIRONMENT, EQ_OPER, GTE_OPER, GT_OPER, IN_OPER, IS_EMPTY_OPER, IS_NOT_EMPTY_OPER, LTE_OPER, LT_OPER, MENU_ITEMS_DATASOURCE_NAME, MULTILANGUAGE_CAPABLE_WIDGET_TYPES, NOT_CONTAINS_OPER, NOT_EQ_OPER, NUMBER_OPERATORS, STARTS_WITH_OPER, STRING_OPERATORS, UploadFromComputerActionProvider, configPlatform, createAllQueryView, createEntityCommandOptions, createEntitySearchCommand, createMenuContext, createMenuMiddleware, createQueryView, getEntityInfo, getStatusInfo, getSystemStatus, provideDynamicHomePage, provideMenuMiddleware, resolveStatusLook, shouldApplyDefaultMultiLanguageToEntityProperty, shouldApplyDefaultMultiLanguageToWidgetNode, shouldApplyDefaultMultiLanguageToWidgetProperty, systemStatusToDefinition, withDefaultMultiLanguageOnWidgetNodeTree, withDefaultMultiLanguageOnWidgetProperty };
4601
+ //# sourceMappingURL=acorex-platform-common.mjs.map