@acorex/modules 20.7.7 → 20.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth/index.d.ts +16 -2
- package/document-management/index.d.ts +33 -10
- package/fesm2022/acorex-modules-application-management.mjs +16 -1
- package/fesm2022/acorex-modules-application-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-auth-acorex-modules-auth-CyabqFR8.mjs → acorex-modules-auth-acorex-modules-auth-Dg9sg98-.mjs} +32 -13
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-Dg9sg98-.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-app-chooser.component-CizgE3Bb.mjs → acorex-modules-auth-app-chooser.component-Dr8EZ7ZX.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-app-chooser.component-CizgE3Bb.mjs.map → acorex-modules-auth-app-chooser.component-Dr8EZ7ZX.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-login.module-DRVqUojm.mjs → acorex-modules-auth-login.module-C7Rt6tLk.mjs} +6 -4
- package/fesm2022/acorex-modules-auth-login.module-C7Rt6tLk.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-master.layout-C1zCbrQh.mjs → acorex-modules-auth-master.layout-CgD5kk65.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-master.layout-C1zCbrQh.mjs.map → acorex-modules-auth-master.layout-CgD5kk65.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-DmNV6zL4.mjs → acorex-modules-auth-oauth-callback.component-CuGIGBVO.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-DmNV6zL4.mjs.map → acorex-modules-auth-oauth-callback.component-CuGIGBVO.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-BmTCzp3t.mjs → acorex-modules-auth-password.component-C6TCAUm4.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-password.component-BmTCzp3t.mjs.map → acorex-modules-auth-password.component-C6TCAUm4.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-DSysOOu9.mjs → acorex-modules-auth-password.component-DmohsIxt.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-password.component-DSysOOu9.mjs.map → acorex-modules-auth-password.component-DmohsIxt.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-routes-oYfOJjLO.mjs → acorex-modules-auth-routes-C3162bwa.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-routes-oYfOJjLO.mjs.map → acorex-modules-auth-routes-C3162bwa.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-DqrZiwp6.mjs → acorex-modules-auth-tenant-chooser.component-Ce-n3WC9.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-tenant-chooser.component-DqrZiwp6.mjs.map → acorex-modules-auth-tenant-chooser.component-Ce-n3WC9.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-two-factor.module-Cc3x-76V.mjs → acorex-modules-auth-two-factor.module-B2nPzX-3.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-two-factor.module-Cc3x-76V.mjs.map → acorex-modules-auth-two-factor.module-B2nPzX-3.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-user-sessions.component-CiGEYKgb.mjs → acorex-modules-auth-user-sessions.component-wVKJ2KIm.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-user-sessions.component-CiGEYKgb.mjs.map → acorex-modules-auth-user-sessions.component-wVKJ2KIm.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth.mjs +1 -1
- package/fesm2022/acorex-modules-content-management.mjs +3 -3
- package/fesm2022/acorex-modules-content-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-dashboard-management.mjs +24 -23
- package/fesm2022/acorex-modules-dashboard-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-data-management.mjs +68 -61
- package/fesm2022/acorex-modules-data-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-document-management-drive-choose.component-CJRrn2XH.mjs → acorex-modules-document-management-drive-choose.component-ovwhHP2n.mjs} +4 -4
- package/fesm2022/{acorex-modules-document-management-drive-choose.component-CJRrn2XH.mjs.map → acorex-modules-document-management-drive-choose.component-ovwhHP2n.mjs.map} +1 -1
- package/fesm2022/acorex-modules-document-management.mjs +363 -231
- package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-help-desk-acorex-modules-help-desk-DGgHWrL0.mjs → acorex-modules-help-desk-acorex-modules-help-desk-CydmGF5Q.mjs} +8 -4
- package/fesm2022/{acorex-modules-help-desk-acorex-modules-help-desk-DGgHWrL0.mjs.map → acorex-modules-help-desk-acorex-modules-help-desk-CydmGF5Q.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-help-desk-capture-screen.component-CAknGKEK.mjs → acorex-modules-help-desk-capture-screen.component-Bsq1FJId.mjs} +2 -2
- package/fesm2022/{acorex-modules-help-desk-capture-screen.component-CAknGKEK.mjs.map → acorex-modules-help-desk-capture-screen.component-Bsq1FJId.mjs.map} +1 -1
- package/fesm2022/acorex-modules-help-desk.mjs +1 -1
- package/fesm2022/acorex-modules-human-capital-management.mjs +41 -26
- package/fesm2022/acorex-modules-human-capital-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-organization-management-org-chart.page-C85uluWf.mjs → acorex-modules-organization-management-org-chart.page-Ca_aJDbu.mjs} +19 -13
- package/fesm2022/acorex-modules-organization-management-org-chart.page-Ca_aJDbu.mjs.map +1 -0
- package/fesm2022/acorex-modules-organization-management.mjs +2 -2
- package/fesm2022/{acorex-modules-person-management-person.entity-BtaGNj8n.mjs → acorex-modules-person-management-person.entity-CaEVw1mL.mjs} +2 -2
- package/fesm2022/acorex-modules-person-management-person.entity-CaEVw1mL.mjs.map +1 -0
- package/fesm2022/acorex-modules-person-management.mjs +1 -1
- package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-DEx13GSy.mjs → acorex-modules-platform-management-acorex-modules-platform-management-DVkP3JKC.mjs} +1188 -341
- package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-DVkP3JKC.mjs.map +1 -0
- package/fesm2022/acorex-modules-platform-management-menu-list.component-C_mdsuRc.mjs +519 -0
- package/fesm2022/acorex-modules-platform-management-menu-list.component-C_mdsuRc.mjs.map +1 -0
- package/fesm2022/acorex-modules-platform-management.mjs +1 -1
- package/fesm2022/acorex-modules-report-management.mjs +27 -6
- package/fesm2022/acorex-modules-report-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-workflow-management.mjs +15 -9
- package/fesm2022/acorex-modules-workflow-management.mjs.map +1 -1
- package/package.json +2 -2
- package/platform-management/index.d.ts +12 -1
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-CyabqFR8.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-login.module-DRVqUojm.mjs.map +0 -1
- package/fesm2022/acorex-modules-organization-management-org-chart.page-C85uluWf.mjs.map +0 -1
- package/fesm2022/acorex-modules-person-management-person.entity-BtaGNj8n.mjs.map +0 -1
- package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-DEx13GSy.mjs.map +0 -1
- package/fesm2022/acorex-modules-platform-management-menu-list.component-DLg61Nf8.mjs +0 -853
- package/fesm2022/acorex-modules-platform-management-menu-list.component-DLg61Nf8.mjs.map +0 -1
|
@@ -1,65 +1,1098 @@
|
|
|
1
|
-
import { AXPTokenDefinitionService, AXP_TOKEN_DEFINITION_PROVIDER, AXPSettingsService, createAllQueryView, AXPEntityCommandScope, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER } from '@acorex/platform/common';
|
|
2
|
-
import { AXPExpressionEvaluatorService, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXPPlatformScope, AXP_MODULE_MANIFEST_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER } from '@acorex/platform/core';
|
|
3
|
-
import { AXMEntityCrudServiceImpl, AXPEntityService, entityMasterCrudActions, entityMasterRecordActions, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
4
1
|
import { AXPAuthGuard, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex/platform/auth';
|
|
2
|
+
import { AXPSettingsService, AXPMenuProviderService, AXPTokenDefinitionService, AXP_TOKEN_DEFINITION_PROVIDER, createAllQueryView, AXPEntityCommandScope, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER } from '@acorex/platform/common';
|
|
3
|
+
import { AXPPlatformScope, AXPExpressionEvaluatorService, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER } from '@acorex/platform/core';
|
|
4
|
+
import { AXMEntityCrudServiceImpl, AXPEntityService, entityMasterCrudActions, entityMasterRecordActions, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
|
|
5
5
|
import { AXPRootLayoutComponent } from '@acorex/platform/themes/default';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
|
-
import { Injectable,
|
|
7
|
+
import { inject, Injector, Injectable, viewChild, signal, computed, ViewEncapsulation, Component, NgModule } from '@angular/core';
|
|
8
8
|
import { ROUTES } from '@angular/router';
|
|
9
|
+
import { AXPMenuCustomizerService, AXPMenuCustomizerComponent, AXPThemeLayoutBlockComponent, AXP_MENU_CUSTOMIZER_SERVICE } from '@acorex/platform/layout/components';
|
|
10
|
+
import * as i1 from '@acorex/platform/workflow';
|
|
11
|
+
import { AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
12
|
+
import { cloneDeep } from 'lodash-es';
|
|
13
|
+
import { AXPopupService } from '@acorex/components/popup';
|
|
14
|
+
import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
|
|
15
|
+
import { AXPPopupLayoutBaseComponent, AXPPopupLayoutComponent, AXPPopupLayoutBase } from '@acorex/platform/layout/views';
|
|
16
|
+
import { CommonModule } from '@angular/common';
|
|
9
17
|
import { provideCommandSetups } from '@acorex/platform/runtime';
|
|
10
18
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
11
|
-
import { AXTranslationService } from '@acorex/core/translation';
|
|
12
19
|
import { SwUpdate } from '@angular/service-worker';
|
|
13
20
|
import { AXPCommonMenuKeys, AXPWidgetsList } from '@acorex/modules/common';
|
|
14
21
|
import { AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
|
|
15
22
|
|
|
16
|
-
const config = {
|
|
17
|
-
i18n: 'platform-management',
|
|
18
|
-
};
|
|
19
|
-
const RootConfig = {
|
|
20
|
-
config,
|
|
21
|
-
module: {
|
|
22
|
-
route: 'platform-management',
|
|
23
|
-
name: 'PlatformManagement',
|
|
24
|
-
title: `@${config.i18n}:module.title`,
|
|
25
|
-
icon: 'fa-light fa-cogs',
|
|
26
|
-
},
|
|
27
|
-
entities: {
|
|
28
|
-
localizationManagement: {
|
|
29
|
-
name: 'Localization Management',
|
|
30
|
-
title: `@${config.i18n}:localization-management.entities.localization-management.title`,
|
|
31
|
-
icon: 'fa-light fa-globe',
|
|
23
|
+
const config = {
|
|
24
|
+
i18n: 'platform-management',
|
|
25
|
+
};
|
|
26
|
+
const RootConfig = {
|
|
27
|
+
config,
|
|
28
|
+
module: {
|
|
29
|
+
route: 'platform-management',
|
|
30
|
+
name: 'PlatformManagement',
|
|
31
|
+
title: `@${config.i18n}:module.title`,
|
|
32
|
+
icon: 'fa-light fa-cogs',
|
|
33
|
+
},
|
|
34
|
+
entities: {
|
|
35
|
+
localizationManagement: {
|
|
36
|
+
name: 'Localization Management',
|
|
37
|
+
title: `@${config.i18n}:localization-management.entities.localization-management.title`,
|
|
38
|
+
icon: 'fa-light fa-globe',
|
|
39
|
+
},
|
|
40
|
+
token: {
|
|
41
|
+
name: 'Tokens',
|
|
42
|
+
title: `@${config.i18n}:tokens.entities.token.title`,
|
|
43
|
+
icon: 'fa-light fa-object-exclude',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
class AXMEntityLoader {
|
|
49
|
+
constructor() {
|
|
50
|
+
this.injector = inject(Injector);
|
|
51
|
+
}
|
|
52
|
+
preload() {
|
|
53
|
+
const module = RootConfig.module.name;
|
|
54
|
+
return Array.from(Object.values(RootConfig.entities)).map((entity) => ({
|
|
55
|
+
module: module,
|
|
56
|
+
entity: entity.name,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
async get(moduleName, entityName) {
|
|
60
|
+
if (moduleName == RootConfig.module.name) {
|
|
61
|
+
return new Promise(async (resolve) => {
|
|
62
|
+
switch (entityName) {
|
|
63
|
+
case RootConfig.entities.token.name: {
|
|
64
|
+
const entity = (await Promise.resolve().then(function () { return index; })).tokenEntityFactory;
|
|
65
|
+
resolve(entity(this.injector));
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
default:
|
|
69
|
+
resolve(null);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
async list() {
|
|
76
|
+
const m = RootConfig.module.name;
|
|
77
|
+
return Promise.resolve(Object.values(RootConfig.entities).map((e) => ({ name: e.name, module: m })));
|
|
78
|
+
}
|
|
79
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMEntityLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
80
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMEntityLoader }); }
|
|
81
|
+
}
|
|
82
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMEntityLoader, decorators: [{
|
|
83
|
+
type: Injectable
|
|
84
|
+
}] });
|
|
85
|
+
|
|
86
|
+
const AXPPlatformManagementFeatureKeys = {
|
|
87
|
+
MenuCustomization: 'PlatformManagement:Feature:menu-customization',
|
|
88
|
+
AutoCheckUpdates: 'PlatformManagement:Feature:auto-check-updates',
|
|
89
|
+
MaxTokens: 'PlatformManagement:Feature:max-tokens',
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
//#region ---- Imports ----
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region ---- Feature Definition Provider ----
|
|
95
|
+
/**
|
|
96
|
+
* Platform Management Feature Definition Provider.
|
|
97
|
+
* Provides feature definitions for the Platform Management module.
|
|
98
|
+
*/
|
|
99
|
+
class AXPPlatformManagementFeatureDefinitionProvider {
|
|
100
|
+
async provide(context) {
|
|
101
|
+
context.addFeature(AXPPlatformManagementFeatureKeys.MenuCustomization, {
|
|
102
|
+
title: '@platform-management:features.menu-customization.title',
|
|
103
|
+
description: '@platform-management:features.menu-customization.description',
|
|
104
|
+
defaultValue: true,
|
|
105
|
+
type: 'boolean',
|
|
106
|
+
});
|
|
107
|
+
context.addFeature(AXPPlatformManagementFeatureKeys.AutoCheckUpdates, {
|
|
108
|
+
title: '@platform-management:features.auto-check-updates.title',
|
|
109
|
+
description: '@platform-management:features.auto-check-updates.description',
|
|
110
|
+
defaultValue: true,
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
});
|
|
113
|
+
context.addFeature(AXPPlatformManagementFeatureKeys.MaxTokens, {
|
|
114
|
+
title: '@platform-management:features.max-tokens.title',
|
|
115
|
+
description: '@platform-management:features.max-tokens.description',
|
|
116
|
+
defaultValue: 100,
|
|
117
|
+
type: 'number',
|
|
118
|
+
interface: {
|
|
119
|
+
type: 'number-editor',
|
|
120
|
+
options: {
|
|
121
|
+
min: 1,
|
|
122
|
+
max: 1000,
|
|
123
|
+
step: 1,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
|
|
131
|
+
//#region ---- Menu Customization Constants ----
|
|
132
|
+
/**
|
|
133
|
+
* Setting key for menu customizations
|
|
134
|
+
*/
|
|
135
|
+
const AXP_MENU_CUSTOMIZATION_KEY = 'axp.platform-management.menu-customization';
|
|
136
|
+
/**
|
|
137
|
+
* Current version of menu customization schema
|
|
138
|
+
*/
|
|
139
|
+
const AXP_MENU_CUSTOMIZATION_VERSION = '1.0.0';
|
|
140
|
+
/**
|
|
141
|
+
* Default menu customization
|
|
142
|
+
*/
|
|
143
|
+
const AXP_MENU_CUSTOMIZATION_DEFAULT = {
|
|
144
|
+
version: AXP_MENU_CUSTOMIZATION_VERSION,
|
|
145
|
+
overrides: {},
|
|
146
|
+
customItems: [],
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Menu management feature configuration
|
|
150
|
+
*/
|
|
151
|
+
const MenuManagementConfig = {
|
|
152
|
+
route: 'menus',
|
|
153
|
+
title: `@${RootConfig.config.i18n}:menu-management.components.menu-list.title`,
|
|
154
|
+
icon: 'fa-light fa-bars',
|
|
155
|
+
};
|
|
156
|
+
//#endregion
|
|
157
|
+
|
|
158
|
+
//#region ---- Custom Menu Middleware ----
|
|
159
|
+
/**
|
|
160
|
+
* Middleware that applies menu customizations using the enhanced context API
|
|
161
|
+
* Applies user/tenant customizations from settings with priority support
|
|
162
|
+
*/
|
|
163
|
+
class AXPCustomMenuMiddleware {
|
|
164
|
+
constructor() {
|
|
165
|
+
//#region ---- Middleware Properties ----
|
|
166
|
+
this.name = 'menu-customization';
|
|
167
|
+
this.priority = 100; // High priority to apply customizations early
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region ---- Dependencies ----
|
|
170
|
+
this.settingsService = inject(AXPSettingsService);
|
|
171
|
+
//#endregion
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region ---- Middleware Implementation ----
|
|
175
|
+
async process(context) {
|
|
176
|
+
try {
|
|
177
|
+
// Load menu customization from settings
|
|
178
|
+
const customization = await this.loadCustomization();
|
|
179
|
+
// Apply overrides to existing menu items using context API
|
|
180
|
+
this.applyOverrides(context, customization);
|
|
181
|
+
// Add custom menu items
|
|
182
|
+
this.addCustomItems(context, customization);
|
|
183
|
+
// Re-sort after applying priority overrides
|
|
184
|
+
context.sort();
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
console.error('Error applying menu customizations:', error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region ---- Private Methods ----
|
|
192
|
+
/**
|
|
193
|
+
* Load menu customization from settings
|
|
194
|
+
* Merges Tenant and User scope customizations (User overrides Tenant)
|
|
195
|
+
*/
|
|
196
|
+
async loadCustomization() {
|
|
197
|
+
try {
|
|
198
|
+
// Load both scopes
|
|
199
|
+
const tenantSettings = this.settingsService.scope(AXPPlatformScope.Tenant);
|
|
200
|
+
const userSettings = this.settingsService.scope(AXPPlatformScope.User);
|
|
201
|
+
const tenantCustomization = await tenantSettings.get(AXP_MENU_CUSTOMIZATION_KEY);
|
|
202
|
+
const userCustomization = await userSettings.get(AXP_MENU_CUSTOMIZATION_KEY);
|
|
203
|
+
// Merge customizations: Tenant as base, User overrides
|
|
204
|
+
const merged = {
|
|
205
|
+
version: userCustomization?.version || tenantCustomization?.version || AXP_MENU_CUSTOMIZATION_DEFAULT.version,
|
|
206
|
+
overrides: {
|
|
207
|
+
...(tenantCustomization?.overrides || {}),
|
|
208
|
+
...(userCustomization?.overrides || {}), // User overrides win
|
|
209
|
+
},
|
|
210
|
+
customItems: [...(tenantCustomization?.customItems || []), ...(userCustomization?.customItems || [])],
|
|
211
|
+
};
|
|
212
|
+
// Return merged result or default if both are empty
|
|
213
|
+
const hasCustomizations = Object.keys(merged.overrides).length > 0 || merged.customItems.length > 0;
|
|
214
|
+
return hasCustomizations ? merged : AXP_MENU_CUSTOMIZATION_DEFAULT;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error('Failed to load menu customization:', error);
|
|
218
|
+
return AXP_MENU_CUSTOMIZATION_DEFAULT;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Apply overrides to existing menu items using enhanced context API
|
|
223
|
+
*/
|
|
224
|
+
applyOverrides(context, customization) {
|
|
225
|
+
Object.entries(customization.overrides).forEach(([menuName, override]) => {
|
|
226
|
+
const finder = context.findByName(menuName);
|
|
227
|
+
if (!finder.exists()) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Hide menu item
|
|
231
|
+
if (override.hidden) {
|
|
232
|
+
finder.remove();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// Apply priority override
|
|
236
|
+
if (override.priority !== undefined) {
|
|
237
|
+
finder.setPriority(override.priority);
|
|
238
|
+
}
|
|
239
|
+
// Apply property overrides
|
|
240
|
+
if (override.properties) {
|
|
241
|
+
finder.update(override.properties);
|
|
242
|
+
}
|
|
243
|
+
// Move to different parent
|
|
244
|
+
if (override.parentName !== undefined) {
|
|
245
|
+
finder.moveTo(override.parentName);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Add custom menu items using context API
|
|
251
|
+
*/
|
|
252
|
+
addCustomItems(context, customization) {
|
|
253
|
+
if (customization.customItems && customization.customItems.length > 0) {
|
|
254
|
+
context.add(...customization.customItems);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Builds a customization key from a scope key
|
|
262
|
+
* @param scopeKey The scope key (e.g., 'edition:123', 'tenant:456')
|
|
263
|
+
* @returns The full customization storage key
|
|
264
|
+
*/
|
|
265
|
+
function buildCustomizationKey(scopeKey) {
|
|
266
|
+
return `${AXP_MENU_CUSTOMIZATION_KEY}.${scopeKey}`;
|
|
267
|
+
}
|
|
268
|
+
//#region ---- Menu Management Service ----
|
|
269
|
+
/**
|
|
270
|
+
* Constants for priority calculation
|
|
271
|
+
*/
|
|
272
|
+
const PRIORITY_BASE_ROOT = 0;
|
|
273
|
+
const PRIORITY_BASE_NESTED = 1000;
|
|
274
|
+
const PRIORITY_STEP = 10;
|
|
275
|
+
class AXPMenuManagementService extends AXPMenuCustomizerService {
|
|
276
|
+
constructor() {
|
|
277
|
+
super(...arguments);
|
|
278
|
+
//#region ---- Dependencies ----
|
|
279
|
+
this.settingsService = inject(AXPSettingsService);
|
|
280
|
+
this.menuProviderService = inject(AXPMenuProviderService);
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region ---- AXPMenuCustomizerService Interface Implementation ----
|
|
284
|
+
/**
|
|
285
|
+
* Interface implementation: Get menu tree for the given scope key
|
|
286
|
+
*/
|
|
287
|
+
async getMenuTree(scopeKey) {
|
|
288
|
+
return this.getMenuTreeByKey(scopeKey);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Interface implementation: Sync tree changes
|
|
292
|
+
*/
|
|
293
|
+
async syncTreeChanges(scopeKey, treeNodes) {
|
|
294
|
+
return this.syncTreeChangesByKey(scopeKey, treeNodes);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Interface implementation: Show menu item
|
|
298
|
+
*/
|
|
299
|
+
async showMenuItem(scopeKey, menuName) {
|
|
300
|
+
return this.showMenuItemByKey(scopeKey, menuName);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Interface implementation: Hide menu item
|
|
304
|
+
*/
|
|
305
|
+
async hideMenuItem(scopeKey, menuName) {
|
|
306
|
+
return this.hideMenuItemByKey(scopeKey, menuName);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Interface implementation: Add custom menu item
|
|
310
|
+
*/
|
|
311
|
+
async addCustomMenuItem(scopeKey, menuItem, parentName) {
|
|
312
|
+
return this.addCustomMenuItemByKey(scopeKey, menuItem, parentName);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Interface implementation: Update custom menu item
|
|
316
|
+
*/
|
|
317
|
+
async updateCustomMenuItem(scopeKey, menuName, menuItem) {
|
|
318
|
+
return this.updateCustomMenuItemByKey(scopeKey, menuName, menuItem);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Interface implementation: Update menu properties
|
|
322
|
+
*/
|
|
323
|
+
async updateMenuProperties(scopeKey, menuName, properties) {
|
|
324
|
+
return this.updateMenuPropertiesByKey(scopeKey, menuName, properties);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Interface implementation: Delete custom menu item
|
|
328
|
+
*/
|
|
329
|
+
async deleteCustomMenuItem(scopeKey, menuName) {
|
|
330
|
+
return this.deleteCustomMenuItemByKey(scopeKey, menuName);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Interface implementation: Reset customizations
|
|
334
|
+
*/
|
|
335
|
+
async resetCustomizations(scopeKey) {
|
|
336
|
+
return this.resetCustomizationsByKey(scopeKey);
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region ---- Scope-Based Public Methods ----
|
|
340
|
+
/**
|
|
341
|
+
* Get menu tree as AXTreeViewNode[] for ax-tree-view component (scope-based)
|
|
342
|
+
*/
|
|
343
|
+
async getMenuTreeByScope(scope) {
|
|
344
|
+
// Get RAW menu items WITHOUT middleware (for management purposes)
|
|
345
|
+
const baseItems = await this.menuProviderService.rawItems();
|
|
346
|
+
// Load customizations for the given scope
|
|
347
|
+
const customization = await this.loadCustomization(scope);
|
|
348
|
+
// Merge custom items with base items
|
|
349
|
+
const allItems = [...baseItems, ...customization.customItems];
|
|
350
|
+
// Apply parent overrides to restructure items BEFORE building tree
|
|
351
|
+
const restructuredItems = this.applyParentOverrides(allItems, customization);
|
|
352
|
+
// Convert to tree nodes with metadata
|
|
353
|
+
return this.convertToTreeNodes(restructuredItems, customization);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Sync tree changes back to customization (scope-based)
|
|
357
|
+
* Called automatically when tree structure changes via drag-drop
|
|
358
|
+
*/
|
|
359
|
+
async syncTreeChangesByScope(scope, treeNodes) {
|
|
360
|
+
const customization = await this.loadCustomization(scope);
|
|
361
|
+
// Extract and update priorities and parent relationships from tree structure
|
|
362
|
+
this.updateCustomizationFromTree(treeNodes, customization);
|
|
363
|
+
await this.saveCustomization(scope, customization);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Load menu customization for a specific scope
|
|
367
|
+
*/
|
|
368
|
+
async loadCustomization(scope) {
|
|
369
|
+
try {
|
|
370
|
+
const scopedSettings = this.settingsService.scope(scope);
|
|
371
|
+
const saved = await scopedSettings.get(AXP_MENU_CUSTOMIZATION_KEY);
|
|
372
|
+
if (saved && saved.version) {
|
|
373
|
+
return saved;
|
|
374
|
+
}
|
|
375
|
+
return cloneDeep(AXP_MENU_CUSTOMIZATION_DEFAULT);
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
return cloneDeep(AXP_MENU_CUSTOMIZATION_DEFAULT);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Save menu customization for a specific scope
|
|
383
|
+
*/
|
|
384
|
+
async saveCustomization(scope, customization) {
|
|
385
|
+
const scopedSettings = this.settingsService.scope(scope);
|
|
386
|
+
await scopedSettings.set(AXP_MENU_CUSTOMIZATION_KEY, customization);
|
|
387
|
+
// Clear menu cache to force reload
|
|
388
|
+
this.menuProviderService.clearCache();
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Hide a menu item (scope-based)
|
|
392
|
+
*/
|
|
393
|
+
async hideMenuItemByScope(scope, menuName) {
|
|
394
|
+
this.validateMenuName(menuName, 'hide');
|
|
395
|
+
const customization = await this.loadCustomization(scope);
|
|
396
|
+
this.ensureOverrideExists(customization, menuName);
|
|
397
|
+
customization.overrides[menuName].hidden = true;
|
|
398
|
+
await this.saveCustomization(scope, customization);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Show a menu item (scope-based)
|
|
402
|
+
*/
|
|
403
|
+
async showMenuItemByScope(scope, menuName) {
|
|
404
|
+
this.validateMenuName(menuName, 'show');
|
|
405
|
+
const customization = await this.loadCustomization(scope);
|
|
406
|
+
if (customization.overrides[menuName]) {
|
|
407
|
+
delete customization.overrides[menuName].hidden;
|
|
408
|
+
this.cleanupEmptyOverride(customization, menuName);
|
|
409
|
+
}
|
|
410
|
+
await this.saveCustomization(scope, customization);
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Update menu item priority (scope-based)
|
|
414
|
+
*/
|
|
415
|
+
async updateMenuPriorityByScope(scope, menuName, priority) {
|
|
416
|
+
this.validateMenuName(menuName, 'update priority for');
|
|
417
|
+
const customization = await this.loadCustomization(scope);
|
|
418
|
+
this.ensureOverrideExists(customization, menuName);
|
|
419
|
+
customization.overrides[menuName].priority = priority;
|
|
420
|
+
await this.saveCustomization(scope, customization);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Update menu item properties (scope-based)
|
|
424
|
+
*/
|
|
425
|
+
async updateMenuPropertiesByScope(scope, menuName, properties) {
|
|
426
|
+
this.validateMenuName(menuName, 'update properties for');
|
|
427
|
+
const customization = await this.loadCustomization(scope);
|
|
428
|
+
this.ensureOverrideExists(customization, menuName);
|
|
429
|
+
customization.overrides[menuName].properties = {
|
|
430
|
+
...customization.overrides[menuName].properties,
|
|
431
|
+
...properties,
|
|
432
|
+
};
|
|
433
|
+
await this.saveCustomization(scope, customization);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Add custom menu item (scope-based)
|
|
437
|
+
*/
|
|
438
|
+
async addCustomMenuItemByScope(scope, menuItem, parent) {
|
|
439
|
+
const customization = await this.loadCustomization(scope);
|
|
440
|
+
// Generate unique name if not provided
|
|
441
|
+
if (!menuItem.name) {
|
|
442
|
+
menuItem.name = `custom-menu-${Date.now()}`;
|
|
443
|
+
}
|
|
444
|
+
customization.customItems.push(menuItem);
|
|
445
|
+
await this.saveCustomization(scope, customization);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Update custom menu item (scope-based)
|
|
449
|
+
*/
|
|
450
|
+
async updateCustomMenuItemByScope(scope, menuName, menuItem) {
|
|
451
|
+
this.validateMenuName(menuName, 'update');
|
|
452
|
+
const customization = await this.loadCustomization(scope);
|
|
453
|
+
const index = customization.customItems.findIndex((item) => item.name === menuName);
|
|
454
|
+
if (index === -1) {
|
|
455
|
+
throw new Error(`Custom menu item '${menuName}' not found`);
|
|
456
|
+
}
|
|
457
|
+
customization.customItems[index] = menuItem;
|
|
458
|
+
await this.saveCustomization(scope, customization);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Delete custom menu item (scope-based)
|
|
462
|
+
*/
|
|
463
|
+
async deleteCustomMenuItemByScope(scope, menuName) {
|
|
464
|
+
this.validateMenuName(menuName, 'delete');
|
|
465
|
+
const customization = await this.loadCustomization(scope);
|
|
466
|
+
const initialLength = customization.customItems.length;
|
|
467
|
+
customization.customItems = customization.customItems.filter((item) => item.name !== menuName);
|
|
468
|
+
if (customization.customItems.length === initialLength) {
|
|
469
|
+
throw new Error(`Custom menu item '${menuName}' not found`);
|
|
470
|
+
}
|
|
471
|
+
await this.saveCustomization(scope, customization);
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Reset all customizations for a scope (scope-based)
|
|
475
|
+
*/
|
|
476
|
+
async resetCustomizationsByScope(scope) {
|
|
477
|
+
await this.saveCustomization(scope, cloneDeep(AXP_MENU_CUSTOMIZATION_DEFAULT));
|
|
478
|
+
}
|
|
479
|
+
//#endregion
|
|
480
|
+
//#region ---- Key-Based Public Methods ----
|
|
481
|
+
/**
|
|
482
|
+
* Get menu tree using a generic scope key (e.g., 'edition:123', 'tenant:456')
|
|
483
|
+
*/
|
|
484
|
+
async getMenuTreeByKey(scopeKey) {
|
|
485
|
+
// Get RAW menu items WITHOUT middleware (for management purposes)
|
|
486
|
+
const baseItems = await this.menuProviderService.rawItems();
|
|
487
|
+
// Load customizations for the given scope key
|
|
488
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
489
|
+
// Merge custom items with base items
|
|
490
|
+
const allItems = [...baseItems, ...customization.customItems];
|
|
491
|
+
// Apply parent overrides to restructure items BEFORE building tree
|
|
492
|
+
const restructuredItems = this.applyParentOverrides(allItems, customization);
|
|
493
|
+
// Convert to tree nodes with metadata
|
|
494
|
+
return this.convertToTreeNodes(restructuredItems, customization);
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Sync tree changes using a generic scope key
|
|
498
|
+
*/
|
|
499
|
+
async syncTreeChangesByKey(scopeKey, treeNodes) {
|
|
500
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
501
|
+
// Extract and update priorities and parent relationships from tree structure
|
|
502
|
+
this.updateCustomizationFromTree(treeNodes, customization);
|
|
503
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Load menu customization using a generic scope key
|
|
507
|
+
*/
|
|
508
|
+
async loadCustomizationByKey(scopeKey) {
|
|
509
|
+
try {
|
|
510
|
+
const storageKey = buildCustomizationKey(scopeKey);
|
|
511
|
+
const scopedSettings = this.settingsService.scope(AXPPlatformScope.Tenant);
|
|
512
|
+
const saved = await scopedSettings.get(storageKey);
|
|
513
|
+
if (saved && saved.version) {
|
|
514
|
+
return saved;
|
|
515
|
+
}
|
|
516
|
+
return cloneDeep(AXP_MENU_CUSTOMIZATION_DEFAULT);
|
|
517
|
+
}
|
|
518
|
+
catch {
|
|
519
|
+
return cloneDeep(AXP_MENU_CUSTOMIZATION_DEFAULT);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Save menu customization using a generic scope key
|
|
524
|
+
*/
|
|
525
|
+
async saveCustomizationByKey(scopeKey, customization) {
|
|
526
|
+
const storageKey = buildCustomizationKey(scopeKey);
|
|
527
|
+
const scopedSettings = this.settingsService.scope(AXPPlatformScope.Tenant);
|
|
528
|
+
await scopedSettings.set(storageKey, customization);
|
|
529
|
+
// Clear menu cache to force reload
|
|
530
|
+
this.menuProviderService.clearCache();
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Hide a menu item using a generic scope key
|
|
534
|
+
*/
|
|
535
|
+
async hideMenuItemByKey(scopeKey, menuName) {
|
|
536
|
+
this.validateMenuName(menuName, 'hide');
|
|
537
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
538
|
+
this.ensureOverrideExists(customization, menuName);
|
|
539
|
+
customization.overrides[menuName].hidden = true;
|
|
540
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Show a menu item using a generic scope key
|
|
544
|
+
*/
|
|
545
|
+
async showMenuItemByKey(scopeKey, menuName) {
|
|
546
|
+
this.validateMenuName(menuName, 'show');
|
|
547
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
548
|
+
if (customization.overrides[menuName]) {
|
|
549
|
+
delete customization.overrides[menuName].hidden;
|
|
550
|
+
this.cleanupEmptyOverride(customization, menuName);
|
|
551
|
+
}
|
|
552
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Update menu item properties using a generic scope key
|
|
556
|
+
*/
|
|
557
|
+
async updateMenuPropertiesByKey(scopeKey, menuName, properties) {
|
|
558
|
+
this.validateMenuName(menuName, 'update properties for');
|
|
559
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
560
|
+
this.ensureOverrideExists(customization, menuName);
|
|
561
|
+
customization.overrides[menuName].properties = {
|
|
562
|
+
...customization.overrides[menuName].properties,
|
|
563
|
+
...properties,
|
|
564
|
+
};
|
|
565
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Add custom menu item using a generic scope key
|
|
569
|
+
*/
|
|
570
|
+
async addCustomMenuItemByKey(scopeKey, menuItem, parent) {
|
|
571
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
572
|
+
// Generate unique name if not provided
|
|
573
|
+
if (!menuItem.name) {
|
|
574
|
+
menuItem.name = `custom-menu-${Date.now()}`;
|
|
575
|
+
}
|
|
576
|
+
customization.customItems.push(menuItem);
|
|
577
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Update custom menu item using a generic scope key
|
|
581
|
+
*/
|
|
582
|
+
async updateCustomMenuItemByKey(scopeKey, menuName, menuItem) {
|
|
583
|
+
this.validateMenuName(menuName, 'update');
|
|
584
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
585
|
+
const index = customization.customItems.findIndex((item) => item.name === menuName);
|
|
586
|
+
if (index === -1) {
|
|
587
|
+
throw new Error(`Custom menu item '${menuName}' not found`);
|
|
588
|
+
}
|
|
589
|
+
customization.customItems[index] = menuItem;
|
|
590
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Delete custom menu item using a generic scope key
|
|
594
|
+
*/
|
|
595
|
+
async deleteCustomMenuItemByKey(scopeKey, menuName) {
|
|
596
|
+
this.validateMenuName(menuName, 'delete');
|
|
597
|
+
const customization = await this.loadCustomizationByKey(scopeKey);
|
|
598
|
+
const initialLength = customization.customItems.length;
|
|
599
|
+
customization.customItems = customization.customItems.filter((item) => item.name !== menuName);
|
|
600
|
+
if (customization.customItems.length === initialLength) {
|
|
601
|
+
throw new Error(`Custom menu item '${menuName}' not found`);
|
|
602
|
+
}
|
|
603
|
+
await this.saveCustomizationByKey(scopeKey, customization);
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Reset all customizations using a generic scope key
|
|
607
|
+
*/
|
|
608
|
+
async resetCustomizationsByKey(scopeKey) {
|
|
609
|
+
await this.saveCustomizationByKey(scopeKey, cloneDeep(AXP_MENU_CUSTOMIZATION_DEFAULT));
|
|
610
|
+
}
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region ---- Private Methods ----
|
|
613
|
+
/**
|
|
614
|
+
* Apply parent overrides from customization to restructure menu items
|
|
615
|
+
* This ensures the tree reflects saved parent changes (moves)
|
|
616
|
+
*/
|
|
617
|
+
applyParentOverrides(items, customization) {
|
|
618
|
+
// First, flatten all items into a map for easy lookup
|
|
619
|
+
const itemMap = this.flattenMenuItems(items);
|
|
620
|
+
// Build new structure based on effective parent relationships
|
|
621
|
+
const rootItems = [];
|
|
622
|
+
const childrenMap = new Map();
|
|
623
|
+
for (const [itemName, item] of itemMap.entries()) {
|
|
624
|
+
const override = customization.overrides[itemName];
|
|
625
|
+
// Determine effective parent (override takes precedence)
|
|
626
|
+
let effectiveParent;
|
|
627
|
+
if (override?.parentName !== undefined) {
|
|
628
|
+
// parentName is explicitly set (could be null for root, or a parent name)
|
|
629
|
+
effectiveParent = override.parentName;
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
// No override - find original parent by searching original structure
|
|
633
|
+
effectiveParent = this.findOriginalParent(items, itemName);
|
|
634
|
+
}
|
|
635
|
+
if (effectiveParent === null || effectiveParent === undefined) {
|
|
636
|
+
// Root level item
|
|
637
|
+
rootItems.push(item);
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
// Child item - add to parent's children
|
|
641
|
+
if (!childrenMap.has(effectiveParent)) {
|
|
642
|
+
childrenMap.set(effectiveParent, []);
|
|
643
|
+
}
|
|
644
|
+
childrenMap.get(effectiveParent).push(item);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
// Attach children to their parents recursively
|
|
648
|
+
const attachChildren = (item) => {
|
|
649
|
+
if (item.name && childrenMap.has(item.name)) {
|
|
650
|
+
item.children = childrenMap.get(item.name);
|
|
651
|
+
item.children?.forEach(attachChildren);
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
rootItems.forEach(attachChildren);
|
|
655
|
+
return rootItems;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Find the original parent name of an item in the original structure
|
|
659
|
+
* Returns undefined for root items, string for items with parents, null for not found
|
|
660
|
+
*/
|
|
661
|
+
findOriginalParent(items, targetName, currentParent) {
|
|
662
|
+
for (const item of items) {
|
|
663
|
+
if (item.name === targetName) {
|
|
664
|
+
return currentParent; // undefined if root, string if has parent
|
|
665
|
+
}
|
|
666
|
+
if (item.children) {
|
|
667
|
+
const found = this.findOriginalParent(item.children, targetName, item.name);
|
|
668
|
+
if (found !== null) {
|
|
669
|
+
// Found in children (could be undefined for root of subtree, or string for nested item)
|
|
670
|
+
return found;
|
|
671
|
+
}
|
|
672
|
+
// found === null means not found in this subtree, continue searching
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return null; // Not found in this level or any children
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Convert menu items to AXTreeNode[] with metadata
|
|
679
|
+
*/
|
|
680
|
+
convertToTreeNodes(items, customization, parentName) {
|
|
681
|
+
const nodes = items.map((item) => {
|
|
682
|
+
const itemName = item.name;
|
|
683
|
+
const override = itemName ? customization.overrides[itemName] : undefined;
|
|
684
|
+
const isCustom = itemName ? customization.customItems.some((ci) => ci.name === itemName) : false;
|
|
685
|
+
// Create metadata
|
|
686
|
+
const metadata = {
|
|
687
|
+
isBuiltIn: !isCustom,
|
|
688
|
+
isCustom,
|
|
689
|
+
isHidden: override?.hidden || false,
|
|
690
|
+
originalPriority: item.priority,
|
|
691
|
+
originalParentName: parentName,
|
|
692
|
+
};
|
|
693
|
+
// Apply priority override
|
|
694
|
+
const effectivePriority = override?.priority !== undefined ? override.priority : item.priority;
|
|
695
|
+
const itemWithPriority = { ...item, priority: effectivePriority };
|
|
696
|
+
// Create tree node data
|
|
697
|
+
const nodeData = {
|
|
698
|
+
menuItem: itemWithPriority,
|
|
699
|
+
metadata,
|
|
700
|
+
};
|
|
701
|
+
// Create tree node
|
|
702
|
+
const treeNode = {
|
|
703
|
+
id: itemName || item.path || this.generateNodeId(),
|
|
704
|
+
title: item.text || item.path || 'Unnamed',
|
|
705
|
+
icon: item.icon,
|
|
706
|
+
expanded: false,
|
|
707
|
+
selected: false,
|
|
708
|
+
['children']: item.children ? this.convertToTreeNodes(item.children, customization, itemName) : undefined,
|
|
709
|
+
childrenCount: item.children?.length,
|
|
710
|
+
data: nodeData,
|
|
711
|
+
};
|
|
712
|
+
return treeNode;
|
|
713
|
+
});
|
|
714
|
+
// Sort by priority
|
|
715
|
+
nodes.sort((a, b) => {
|
|
716
|
+
const aPriority = a['data']?.menuItem.priority ?? 0;
|
|
717
|
+
const bPriority = b['data']?.menuItem.priority ?? 0;
|
|
718
|
+
return aPriority - bPriority;
|
|
719
|
+
});
|
|
720
|
+
return nodes;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Update customization from tree structure
|
|
724
|
+
* Extracts priorities and parent relationships from tree nodes
|
|
725
|
+
*/
|
|
726
|
+
updateCustomizationFromTree(treeNodes, customization, parentName) {
|
|
727
|
+
// Calculate base priority for this level to maintain relative ordering
|
|
728
|
+
const basePriority = parentName ? PRIORITY_BASE_NESTED : PRIORITY_BASE_ROOT;
|
|
729
|
+
const priorityStep = PRIORITY_STEP;
|
|
730
|
+
treeNodes.forEach((node, index) => {
|
|
731
|
+
const nodeData = node['data'] || null;
|
|
732
|
+
const menuItem = nodeData?.menuItem;
|
|
733
|
+
if (menuItem?.name) {
|
|
734
|
+
this.ensureOverrideExists(customization, menuItem.name);
|
|
735
|
+
// Calculate new priority based on current position
|
|
736
|
+
const newPriority = basePriority + index * priorityStep;
|
|
737
|
+
// Get current effective priority (considering existing overrides)
|
|
738
|
+
const currentEffectivePriority = customization.overrides[menuItem.name]?.priority ?? nodeData.metadata.originalPriority ?? 0;
|
|
739
|
+
// Always update priority to reflect current position in tree
|
|
740
|
+
// This ensures reordering works correctly even after multiple moves
|
|
741
|
+
if (newPriority !== currentEffectivePriority) {
|
|
742
|
+
customization.overrides[menuItem.name].priority = newPriority;
|
|
743
|
+
}
|
|
744
|
+
// Determine current effective parent (considering existing overrides)
|
|
745
|
+
const currentEffectiveParent = customization.overrides[menuItem.name]?.parentName ?? nodeData.metadata.originalParentName;
|
|
746
|
+
// Update parent relationship if it changed from current effective parent
|
|
747
|
+
if (parentName !== currentEffectiveParent) {
|
|
748
|
+
if (parentName) {
|
|
749
|
+
customization.overrides[menuItem.name].parentName = parentName;
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
// Moving to root - set to null (not undefined) so middleware will process it
|
|
753
|
+
// moveTo(null) moves the item to root level
|
|
754
|
+
customization.overrides[menuItem.name].parentName = null;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
// Clean up empty overrides
|
|
758
|
+
this.cleanupEmptyOverride(customization, menuItem.name);
|
|
759
|
+
// Recursively process children
|
|
760
|
+
const nodeChildren = node['children'];
|
|
761
|
+
if (nodeChildren && nodeChildren.length > 0) {
|
|
762
|
+
this.updateCustomizationFromTree(nodeChildren, customization, menuItem.name);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Validate menu name before operations
|
|
769
|
+
*/
|
|
770
|
+
validateMenuName(menuName, operation) {
|
|
771
|
+
if (!menuName) {
|
|
772
|
+
throw new Error(`Menu item must have a name to be ${operation}`);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Ensure override object exists for a menu item
|
|
777
|
+
*/
|
|
778
|
+
ensureOverrideExists(customization, menuName) {
|
|
779
|
+
if (!customization.overrides[menuName]) {
|
|
780
|
+
customization.overrides[menuName] = {};
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Clean up empty override objects
|
|
785
|
+
*/
|
|
786
|
+
cleanupEmptyOverride(customization, menuName) {
|
|
787
|
+
if (Object.keys(customization.overrides[menuName] || {}).length === 0) {
|
|
788
|
+
delete customization.overrides[menuName];
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Flatten menu items recursively into a map
|
|
793
|
+
*/
|
|
794
|
+
flattenMenuItems(items) {
|
|
795
|
+
const itemMap = new Map();
|
|
796
|
+
const flatten = (itemList) => {
|
|
797
|
+
for (const item of itemList) {
|
|
798
|
+
if (item.name) {
|
|
799
|
+
// Clone item without children to rebuild structure
|
|
800
|
+
itemMap.set(item.name, { ...item, children: undefined });
|
|
801
|
+
}
|
|
802
|
+
if (item.children) {
|
|
803
|
+
flatten(item.children);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
flatten(items);
|
|
808
|
+
return itemMap;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Generate unique ID for tree nodes
|
|
812
|
+
*/
|
|
813
|
+
generateNodeId() {
|
|
814
|
+
return `node-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
|
|
815
|
+
}
|
|
816
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPMenuManagementService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
817
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPMenuManagementService, providedIn: 'root' }); }
|
|
818
|
+
}
|
|
819
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPMenuManagementService, decorators: [{
|
|
820
|
+
type: Injectable,
|
|
821
|
+
args: [{ providedIn: 'root' }]
|
|
822
|
+
}] });
|
|
823
|
+
|
|
824
|
+
//#endregion
|
|
825
|
+
//#region ---- Menu Customizer Popup Component ----
|
|
826
|
+
/**
|
|
827
|
+
* Popup wrapper for the menu customizer component.
|
|
828
|
+
* Provides a popup layout with actions for managing menu customizations.
|
|
829
|
+
*
|
|
830
|
+
* Pass the following data when opening the popup:
|
|
831
|
+
* - scopeKey: string - The scope key for menu customizations
|
|
832
|
+
* - showToolbar?: boolean - Whether to show the toolbar (default: true)
|
|
833
|
+
* - allowAddItems?: boolean - Whether to allow adding items (default: true)
|
|
834
|
+
* - dragBehavior?: AXTreeViewDragBehavior - Drag behavior (default: 'move')
|
|
835
|
+
* - dragArea?: AXTreeViewDragArea - Drag area (default: 'handler')
|
|
836
|
+
*/
|
|
837
|
+
class AXPMenuCustomizerPopupComponent extends AXPPopupLayoutBaseComponent {
|
|
838
|
+
constructor() {
|
|
839
|
+
super(...arguments);
|
|
840
|
+
//#region ---- Component State ----
|
|
841
|
+
/** Reference to the menu customizer component */
|
|
842
|
+
this.menuCustomizer = viewChild(AXPMenuCustomizerComponent, ...(ngDevMode ? [{ debugName: "menuCustomizer" }] : []));
|
|
843
|
+
/** The scope key for menu customizations (set by popup service) */
|
|
844
|
+
this.scopeKey = signal('', ...(ngDevMode ? [{ debugName: "scopeKey" }] : []));
|
|
845
|
+
/** Whether to show the toolbar */
|
|
846
|
+
this.showToolbar = signal(true, ...(ngDevMode ? [{ debugName: "showToolbar" }] : []));
|
|
847
|
+
/** Whether to allow adding custom items */
|
|
848
|
+
this.allowAddItems = signal(true, ...(ngDevMode ? [{ debugName: "allowAddItems" }] : []));
|
|
849
|
+
/** Drag behavior for the tree view */
|
|
850
|
+
this.dragBehavior = signal('both', ...(ngDevMode ? [{ debugName: "dragBehavior" }] : []));
|
|
851
|
+
/** Drag area for the tree view */
|
|
852
|
+
this.dragArea = signal('handler', ...(ngDevMode ? [{ debugName: "dragArea" }] : []));
|
|
853
|
+
/** Whether the component is ready to render (scopeKey is set) */
|
|
854
|
+
this.isReady = computed(() => this.scopeKey() !== '', ...(ngDevMode ? [{ debugName: "isReady" }] : []));
|
|
855
|
+
}
|
|
856
|
+
//#endregion
|
|
857
|
+
//#region ---- Lifecycle Methods ----
|
|
858
|
+
async ngOnInit() {
|
|
859
|
+
await super.ngOnInit();
|
|
860
|
+
// Popup-specific initialization can go here
|
|
861
|
+
}
|
|
862
|
+
//#endregion
|
|
863
|
+
//#region ---- UI Handlers ----
|
|
864
|
+
/**
|
|
865
|
+
* Returns the primary menu items for the popup layout.
|
|
866
|
+
*/
|
|
867
|
+
getPrimaryMenuItems() {
|
|
868
|
+
return [
|
|
869
|
+
{
|
|
870
|
+
title: '@general:actions.close.title',
|
|
871
|
+
icon: 'fa-solid fa-xmark',
|
|
872
|
+
command: {
|
|
873
|
+
name: 'close',
|
|
874
|
+
},
|
|
875
|
+
},
|
|
876
|
+
];
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Handles when changes are saved
|
|
880
|
+
*/
|
|
881
|
+
onSaved() {
|
|
882
|
+
this.close(true);
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Handles when customization is cancelled
|
|
886
|
+
*/
|
|
887
|
+
onCancelled() {
|
|
888
|
+
this.close(false);
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Executes popup commands
|
|
892
|
+
*/
|
|
893
|
+
execute(command) {
|
|
894
|
+
if (command.name === 'close') {
|
|
895
|
+
this.close(false);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPMenuCustomizerPopupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
899
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXPMenuCustomizerPopupComponent, isStandalone: true, selector: "axp-menu-customizer-popup", host: { classAttribute: "axp-menu-customizer-popup" }, providers: [
|
|
900
|
+
{
|
|
901
|
+
provide: AXPPopupLayoutBase,
|
|
902
|
+
useExisting: AXPMenuCustomizerPopupComponent,
|
|
903
|
+
},
|
|
904
|
+
], viewQueries: [{ propertyName: "menuCustomizer", first: true, predicate: AXPMenuCustomizerComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
905
|
+
<axp-popup-layout>
|
|
906
|
+
<axp-page-content>
|
|
907
|
+
@if (isReady()) {
|
|
908
|
+
<axp-menu-customizer
|
|
909
|
+
[scopeKey]="scopeKey()"
|
|
910
|
+
[showToolbar]="showToolbar()"
|
|
911
|
+
[allowAddItems]="allowAddItems()"
|
|
912
|
+
[dragBehavior]="dragBehavior()"
|
|
913
|
+
[dragArea]="dragArea()"
|
|
914
|
+
(saved)="onSaved()"
|
|
915
|
+
(cancelled)="onCancelled()"
|
|
916
|
+
></axp-menu-customizer>
|
|
917
|
+
}
|
|
918
|
+
</axp-page-content>
|
|
919
|
+
</axp-popup-layout>
|
|
920
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPPopupLayoutComponent, selector: "axp-popup-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPMenuCustomizerComponent, selector: "axp-menu-customizer", inputs: ["scopeKey", "showToolbar", "allowAddItems", "dragBehavior", "dragArea"], outputs: ["saved", "cancelled"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
921
|
+
}
|
|
922
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPMenuCustomizerPopupComponent, decorators: [{
|
|
923
|
+
type: Component,
|
|
924
|
+
args: [{
|
|
925
|
+
selector: 'axp-menu-customizer-popup',
|
|
926
|
+
template: `
|
|
927
|
+
<axp-popup-layout>
|
|
928
|
+
<axp-page-content>
|
|
929
|
+
@if (isReady()) {
|
|
930
|
+
<axp-menu-customizer
|
|
931
|
+
[scopeKey]="scopeKey()"
|
|
932
|
+
[showToolbar]="showToolbar()"
|
|
933
|
+
[allowAddItems]="allowAddItems()"
|
|
934
|
+
[dragBehavior]="dragBehavior()"
|
|
935
|
+
[dragArea]="dragArea()"
|
|
936
|
+
(saved)="onSaved()"
|
|
937
|
+
(cancelled)="onCancelled()"
|
|
938
|
+
></axp-menu-customizer>
|
|
939
|
+
}
|
|
940
|
+
</axp-page-content>
|
|
941
|
+
</axp-popup-layout>
|
|
942
|
+
`,
|
|
943
|
+
imports: [
|
|
944
|
+
CommonModule,
|
|
945
|
+
AXTranslationModule,
|
|
946
|
+
AXPPopupLayoutComponent,
|
|
947
|
+
AXPThemeLayoutBlockComponent,
|
|
948
|
+
AXPMenuCustomizerComponent,
|
|
949
|
+
],
|
|
950
|
+
encapsulation: ViewEncapsulation.None,
|
|
951
|
+
providers: [
|
|
952
|
+
{
|
|
953
|
+
provide: AXPPopupLayoutBase,
|
|
954
|
+
useExisting: AXPMenuCustomizerPopupComponent,
|
|
955
|
+
},
|
|
956
|
+
],
|
|
957
|
+
host: { class: 'axp-menu-customizer-popup' },
|
|
958
|
+
}]
|
|
959
|
+
}], propDecorators: { menuCustomizer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPMenuCustomizerComponent), { isSignal: true }] }] } });
|
|
960
|
+
|
|
961
|
+
//#region ---- Imports ----
|
|
962
|
+
//#endregion
|
|
963
|
+
//#region ---- Open Menu Customizer Action ----
|
|
964
|
+
/**
|
|
965
|
+
* Workflow action that opens the menu customizer popup.
|
|
966
|
+
* Expects the context to contain:
|
|
967
|
+
* - data: The entity data (must have an 'id' property)
|
|
968
|
+
* - options.scopePrefix: The prefix for the scope key (e.g., 'edition', 'tenant')
|
|
969
|
+
* - options.title: Optional custom title for the popup
|
|
970
|
+
* - options.showToolbar: Whether to show toolbar (default: true)
|
|
971
|
+
* - options.allowAddItems: Whether to allow adding items (default: true)
|
|
972
|
+
* - options.dragBehavior: Drag behavior - 'none' | 'move' | 'copy' (default: 'move')
|
|
973
|
+
* - options.dragArea: Drag area - 'node' | 'handler' (default: 'handler')
|
|
974
|
+
*/
|
|
975
|
+
class AXMOpenMenuCustomizerAction extends AXPWorkflowAction {
|
|
976
|
+
constructor() {
|
|
977
|
+
super(...arguments);
|
|
978
|
+
//#region ---- Dependencies ----
|
|
979
|
+
this.popupService = inject(AXPopupService);
|
|
980
|
+
this.translateService = inject(AXTranslationService);
|
|
981
|
+
}
|
|
982
|
+
//#endregion
|
|
983
|
+
//#region ---- Execute ----
|
|
984
|
+
async execute(context) {
|
|
985
|
+
// Get entity data
|
|
986
|
+
const data = context.getVariable('data');
|
|
987
|
+
const entityId = data?.id;
|
|
988
|
+
if (!entityId) {
|
|
989
|
+
console.error('Menu customizer requires entity data with an id property');
|
|
990
|
+
context.setOutput('result', false);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
// Get scope configuration
|
|
994
|
+
const scopePrefix = context.getVariable('options.scopePrefix') || 'entity';
|
|
995
|
+
const scopeKey = `${scopePrefix}:${entityId}`;
|
|
996
|
+
// Get optional title
|
|
997
|
+
const customTitle = context.getVariable('options.title');
|
|
998
|
+
const defaultTitle = await this.translateService.translateAsync('@platform-management:menu-management.components.menu-customizer-popup.title');
|
|
999
|
+
const entityTitle = data?.title || data?.name || entityId;
|
|
1000
|
+
const title = customTitle || `${defaultTitle} - ${entityTitle}`;
|
|
1001
|
+
// Open popup using the component from platform/layout/components
|
|
1002
|
+
// Pass signals to properly bind to the popup component's signal properties
|
|
1003
|
+
const result = await this.popupService.open(AXPMenuCustomizerPopupComponent, {
|
|
1004
|
+
title,
|
|
1005
|
+
size: 'lg',
|
|
1006
|
+
data: {
|
|
1007
|
+
scopeKey: signal(scopeKey),
|
|
1008
|
+
showToolbar: signal(context.getVariable('options.showToolbar') ?? true),
|
|
1009
|
+
allowAddItems: signal(context.getVariable('options.allowAddItems') ?? true),
|
|
1010
|
+
dragBehavior: signal(context.getVariable('options.dragBehavior') ?? 'both'),
|
|
1011
|
+
dragArea: signal(context.getVariable('options.dragArea') ?? 'handler'),
|
|
1012
|
+
},
|
|
1013
|
+
});
|
|
1014
|
+
// Set result based on popup outcome
|
|
1015
|
+
context.setOutput('result', result?.data === true);
|
|
1016
|
+
}
|
|
1017
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMOpenMenuCustomizerAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1018
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMOpenMenuCustomizerAction }); }
|
|
1019
|
+
}
|
|
1020
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMOpenMenuCustomizerAction, decorators: [{
|
|
1021
|
+
type: Injectable
|
|
1022
|
+
}] });
|
|
1023
|
+
//#endregion
|
|
1024
|
+
//#region ---- Customize Menu Workflow ----
|
|
1025
|
+
/**
|
|
1026
|
+
* Workflow definition for customizing menus.
|
|
1027
|
+
* Opens the menu customizer popup and handles the result.
|
|
1028
|
+
*/
|
|
1029
|
+
const AXMCustomizeMenuWorkflow = {
|
|
1030
|
+
startStepId: 'open-customizer',
|
|
1031
|
+
steps: {
|
|
1032
|
+
'open-customizer': {
|
|
1033
|
+
action: 'open-menu-customizer',
|
|
1034
|
+
nextSteps: [
|
|
1035
|
+
{
|
|
1036
|
+
conditions: [{ type: 'SINGLE', expression: 'context.getOutput("result") == true' }],
|
|
1037
|
+
nextStepId: 'show-success-toast',
|
|
1038
|
+
},
|
|
1039
|
+
],
|
|
32
1040
|
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
1041
|
+
'show-success-toast': {
|
|
1042
|
+
action: 'AXPToastAction',
|
|
1043
|
+
input: {
|
|
1044
|
+
color: 'success',
|
|
1045
|
+
title: '@platform-management:menu-management.messages.success.customization-saved',
|
|
1046
|
+
},
|
|
37
1047
|
},
|
|
38
1048
|
},
|
|
39
1049
|
};
|
|
40
1050
|
|
|
41
1051
|
//#region ---- Imports ----
|
|
42
1052
|
//#endregion
|
|
43
|
-
//#region ----
|
|
1053
|
+
//#region ---- Module ----
|
|
44
1054
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
1055
|
+
* Module for menu management features including the menu customizer
|
|
1056
|
+
* and related workflows.
|
|
47
1057
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
1058
|
+
class AXMMenuManagementModule {
|
|
1059
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMMenuManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1060
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AXMMenuManagementModule, imports: [i1.AXPWorkflowModule] }); }
|
|
1061
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMMenuManagementModule, providers: [
|
|
1062
|
+
{
|
|
1063
|
+
provide: AXP_MENU_CUSTOMIZER_SERVICE,
|
|
1064
|
+
useExisting: AXPMenuManagementService,
|
|
1065
|
+
},
|
|
1066
|
+
], imports: [AXPWorkflowModule.forChild({
|
|
1067
|
+
workflows: {
|
|
1068
|
+
'customize-menu': AXMCustomizeMenuWorkflow,
|
|
1069
|
+
},
|
|
1070
|
+
actions: {
|
|
1071
|
+
'open-menu-customizer': AXMOpenMenuCustomizerAction,
|
|
1072
|
+
},
|
|
1073
|
+
})] }); }
|
|
1074
|
+
}
|
|
1075
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMMenuManagementModule, decorators: [{
|
|
1076
|
+
type: NgModule,
|
|
1077
|
+
args: [{
|
|
1078
|
+
imports: [
|
|
1079
|
+
AXPWorkflowModule.forChild({
|
|
1080
|
+
workflows: {
|
|
1081
|
+
'customize-menu': AXMCustomizeMenuWorkflow,
|
|
1082
|
+
},
|
|
1083
|
+
actions: {
|
|
1084
|
+
'open-menu-customizer': AXMOpenMenuCustomizerAction,
|
|
1085
|
+
},
|
|
1086
|
+
}),
|
|
1087
|
+
],
|
|
1088
|
+
providers: [
|
|
1089
|
+
{
|
|
1090
|
+
provide: AXP_MENU_CUSTOMIZER_SERVICE,
|
|
1091
|
+
useExisting: AXPMenuManagementService,
|
|
1092
|
+
},
|
|
1093
|
+
],
|
|
1094
|
+
}]
|
|
1095
|
+
}] });
|
|
63
1096
|
|
|
64
1097
|
/**
|
|
65
1098
|
* Token that returns current ISO date-time string.
|
|
@@ -394,192 +1427,95 @@ class AXPUpdaterService {
|
|
|
394
1427
|
icon: 'fa-regular fa-info',
|
|
395
1428
|
content: translateService.translateSync('updater.content', { scope: scope }),
|
|
396
1429
|
title: translateService.translateSync('updater.title', { scope: scope }),
|
|
397
|
-
type: 'primary',
|
|
398
|
-
orientation: 'horizontal',
|
|
399
|
-
buttons: [
|
|
400
|
-
{
|
|
401
|
-
text: translateService.translateSync('updater.update', { scope: scope }),
|
|
402
|
-
color: 'primary',
|
|
403
|
-
onClick: async (e) => {
|
|
404
|
-
try {
|
|
405
|
-
document.location.reload();
|
|
406
|
-
dialog.close();
|
|
407
|
-
}
|
|
408
|
-
catch (error) {
|
|
409
|
-
console.error(error);
|
|
410
|
-
}
|
|
411
|
-
},
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
text: translateService.translateSync('updater.cancel', { scope: scope }),
|
|
415
|
-
color: 'default',
|
|
416
|
-
autofocus: true,
|
|
417
|
-
onClick: (e) => {
|
|
418
|
-
dialog.close();
|
|
419
|
-
},
|
|
420
|
-
},
|
|
421
|
-
],
|
|
422
|
-
closeButton: false,
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPUpdaterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
429
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPUpdaterService, providedIn: 'root' }); }
|
|
430
|
-
}
|
|
431
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPUpdaterService, decorators: [{
|
|
432
|
-
type: Injectable,
|
|
433
|
-
args: [{ providedIn: 'root' }]
|
|
434
|
-
}], ctorParameters: () => [] });
|
|
435
|
-
|
|
436
|
-
class AXMUpdaterModule {
|
|
437
|
-
constructor(updaterService) {
|
|
438
|
-
this.updaterService = updaterService;
|
|
439
|
-
}
|
|
440
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule, deps: [{ token: AXPUpdaterService }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
441
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule }); }
|
|
442
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule, providers: [AXPUpdaterService] }); }
|
|
443
|
-
}
|
|
444
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule, decorators: [{
|
|
445
|
-
type: NgModule,
|
|
446
|
-
args: [{
|
|
447
|
-
imports: [],
|
|
448
|
-
exports: [],
|
|
449
|
-
declarations: [],
|
|
450
|
-
providers: [AXPUpdaterService],
|
|
451
|
-
}]
|
|
452
|
-
}], ctorParameters: () => [{ type: AXPUpdaterService }] });
|
|
453
|
-
|
|
454
|
-
//#region ---- Menu Customization Constants ----
|
|
455
|
-
/**
|
|
456
|
-
* Setting key for menu customizations
|
|
457
|
-
*/
|
|
458
|
-
const AXP_MENU_CUSTOMIZATION_KEY = 'axp.platform-management.menu-customization';
|
|
459
|
-
/**
|
|
460
|
-
* Current version of menu customization schema
|
|
461
|
-
*/
|
|
462
|
-
const AXP_MENU_CUSTOMIZATION_VERSION = '1.0.0';
|
|
463
|
-
/**
|
|
464
|
-
* Default menu customization
|
|
465
|
-
*/
|
|
466
|
-
const AXP_MENU_CUSTOMIZATION_DEFAULT = {
|
|
467
|
-
version: AXP_MENU_CUSTOMIZATION_VERSION,
|
|
468
|
-
overrides: {},
|
|
469
|
-
customItems: [],
|
|
470
|
-
};
|
|
471
|
-
/**
|
|
472
|
-
* Menu management feature configuration
|
|
473
|
-
*/
|
|
474
|
-
const MenuManagementConfig = {
|
|
475
|
-
route: 'menus',
|
|
476
|
-
title: `@${RootConfig.config.i18n}:menu-management.components.menu-list.title`,
|
|
477
|
-
icon: 'fa-light fa-bars',
|
|
478
|
-
};
|
|
479
|
-
//#endregion
|
|
480
|
-
|
|
481
|
-
//#region ---- Custom Menu Middleware ----
|
|
482
|
-
/**
|
|
483
|
-
* Middleware that applies menu customizations using the enhanced context API
|
|
484
|
-
* Applies user/tenant customizations from settings with priority support
|
|
485
|
-
*/
|
|
486
|
-
class AXPCustomMenuMiddleware {
|
|
487
|
-
constructor() {
|
|
488
|
-
//#region ---- Middleware Properties ----
|
|
489
|
-
this.name = 'menu-customization';
|
|
490
|
-
this.priority = 100; // High priority to apply customizations early
|
|
491
|
-
//#endregion
|
|
492
|
-
//#region ---- Dependencies ----
|
|
493
|
-
this.settingsService = inject(AXPSettingsService);
|
|
494
|
-
//#endregion
|
|
495
|
-
}
|
|
496
|
-
//#endregion
|
|
497
|
-
//#region ---- Middleware Implementation ----
|
|
498
|
-
async process(context) {
|
|
499
|
-
try {
|
|
500
|
-
// Load menu customization from settings
|
|
501
|
-
const customization = await this.loadCustomization();
|
|
502
|
-
// Apply overrides to existing menu items using context API
|
|
503
|
-
this.applyOverrides(context, customization);
|
|
504
|
-
// Add custom menu items
|
|
505
|
-
this.addCustomItems(context, customization);
|
|
506
|
-
// Re-sort after applying priority overrides
|
|
507
|
-
context.sort();
|
|
508
|
-
}
|
|
509
|
-
catch (error) {
|
|
510
|
-
console.error('Error applying menu customizations:', error);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
//#endregion
|
|
514
|
-
//#region ---- Private Methods ----
|
|
515
|
-
/**
|
|
516
|
-
* Load menu customization from settings
|
|
517
|
-
* Merges Tenant and User scope customizations (User overrides Tenant)
|
|
518
|
-
*/
|
|
519
|
-
async loadCustomization() {
|
|
520
|
-
try {
|
|
521
|
-
// Load both scopes
|
|
522
|
-
const tenantSettings = this.settingsService.scope(AXPPlatformScope.Tenant);
|
|
523
|
-
const userSettings = this.settingsService.scope(AXPPlatformScope.User);
|
|
524
|
-
const tenantCustomization = await tenantSettings.get(AXP_MENU_CUSTOMIZATION_KEY);
|
|
525
|
-
const userCustomization = await userSettings.get(AXP_MENU_CUSTOMIZATION_KEY);
|
|
526
|
-
// Merge customizations: Tenant as base, User overrides
|
|
527
|
-
const merged = {
|
|
528
|
-
version: userCustomization?.version || tenantCustomization?.version || AXP_MENU_CUSTOMIZATION_DEFAULT.version,
|
|
529
|
-
overrides: {
|
|
530
|
-
...(tenantCustomization?.overrides || {}),
|
|
531
|
-
...(userCustomization?.overrides || {}), // User overrides win
|
|
532
|
-
},
|
|
533
|
-
customItems: [...(tenantCustomization?.customItems || []), ...(userCustomization?.customItems || [])],
|
|
534
|
-
};
|
|
535
|
-
// Return merged result or default if both are empty
|
|
536
|
-
const hasCustomizations = Object.keys(merged.overrides).length > 0 || merged.customItems.length > 0;
|
|
537
|
-
return hasCustomizations ? merged : AXP_MENU_CUSTOMIZATION_DEFAULT;
|
|
538
|
-
}
|
|
539
|
-
catch (error) {
|
|
540
|
-
console.error('Failed to load menu customization:', error);
|
|
541
|
-
return AXP_MENU_CUSTOMIZATION_DEFAULT;
|
|
1430
|
+
type: 'primary',
|
|
1431
|
+
orientation: 'horizontal',
|
|
1432
|
+
buttons: [
|
|
1433
|
+
{
|
|
1434
|
+
text: translateService.translateSync('updater.update', { scope: scope }),
|
|
1435
|
+
color: 'primary',
|
|
1436
|
+
onClick: async (e) => {
|
|
1437
|
+
try {
|
|
1438
|
+
document.location.reload();
|
|
1439
|
+
dialog.close();
|
|
1440
|
+
}
|
|
1441
|
+
catch (error) {
|
|
1442
|
+
console.error(error);
|
|
1443
|
+
}
|
|
1444
|
+
},
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
text: translateService.translateSync('updater.cancel', { scope: scope }),
|
|
1448
|
+
color: 'default',
|
|
1449
|
+
autofocus: true,
|
|
1450
|
+
onClick: (e) => {
|
|
1451
|
+
dialog.close();
|
|
1452
|
+
},
|
|
1453
|
+
},
|
|
1454
|
+
],
|
|
1455
|
+
closeButton: false,
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
});
|
|
542
1459
|
}
|
|
543
1460
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
finder.remove();
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
// Apply priority override
|
|
559
|
-
if (override.priority !== undefined) {
|
|
560
|
-
finder.setPriority(override.priority);
|
|
561
|
-
}
|
|
562
|
-
// Apply property overrides
|
|
563
|
-
if (override.properties) {
|
|
564
|
-
finder.update(override.properties);
|
|
565
|
-
}
|
|
566
|
-
// Move to different parent
|
|
567
|
-
if (override.parentName !== undefined) {
|
|
568
|
-
finder.moveTo(override.parentName);
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
/**
|
|
573
|
-
* Add custom menu items using context API
|
|
574
|
-
*/
|
|
575
|
-
addCustomItems(context, customization) {
|
|
576
|
-
if (customization.customItems && customization.customItems.length > 0) {
|
|
577
|
-
context.add(...customization.customItems);
|
|
578
|
-
}
|
|
1461
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPUpdaterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1462
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPUpdaterService, providedIn: 'root' }); }
|
|
1463
|
+
}
|
|
1464
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXPUpdaterService, decorators: [{
|
|
1465
|
+
type: Injectable,
|
|
1466
|
+
args: [{ providedIn: 'root' }]
|
|
1467
|
+
}], ctorParameters: () => [] });
|
|
1468
|
+
|
|
1469
|
+
class AXMUpdaterModule {
|
|
1470
|
+
constructor(updaterService) {
|
|
1471
|
+
this.updaterService = updaterService;
|
|
579
1472
|
}
|
|
1473
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule, deps: [{ token: AXPUpdaterService }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1474
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule }); }
|
|
1475
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule, providers: [AXPUpdaterService] }); }
|
|
580
1476
|
}
|
|
1477
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMUpdaterModule, decorators: [{
|
|
1478
|
+
type: NgModule,
|
|
1479
|
+
args: [{
|
|
1480
|
+
imports: [],
|
|
1481
|
+
exports: [],
|
|
1482
|
+
declarations: [],
|
|
1483
|
+
providers: [AXPUpdaterService],
|
|
1484
|
+
}]
|
|
1485
|
+
}], ctorParameters: () => [{ type: AXPUpdaterService }] });
|
|
1486
|
+
|
|
1487
|
+
//#region ---- Imports ----
|
|
1488
|
+
//#endregion
|
|
1489
|
+
//#region ---- Manifest Definition ----
|
|
1490
|
+
/**
|
|
1491
|
+
* Platform Management Module Manifest.
|
|
1492
|
+
* Defines module metadata, features, and provider references.
|
|
1493
|
+
*/
|
|
1494
|
+
const PlatformManagementManifest = {
|
|
1495
|
+
name: RootConfig.module.name,
|
|
1496
|
+
version: '1.0.0',
|
|
1497
|
+
title: RootConfig.module.title,
|
|
1498
|
+
icon: RootConfig.module.icon,
|
|
1499
|
+
i18n: RootConfig.config.i18n,
|
|
1500
|
+
dependencies: [
|
|
1501
|
+
'SecurityManagement',
|
|
1502
|
+
'ApplicationManagement',
|
|
1503
|
+
'SystemInsight',
|
|
1504
|
+
'TenantManagement',
|
|
1505
|
+
'SubscriptionManagement',
|
|
1506
|
+
],
|
|
1507
|
+
};
|
|
581
1508
|
//#endregion
|
|
582
1509
|
|
|
1510
|
+
const AXPPlatformManagementMenuKeys = {
|
|
1511
|
+
AdministrationGroup: 'administration:group',
|
|
1512
|
+
Root: 'platform-management:menu',
|
|
1513
|
+
Tokens: 'platform-management:menu:tokens',
|
|
1514
|
+
Glossary: 'platform-management:menu:glossary',
|
|
1515
|
+
UserMenuManagement: 'platform-management:user:menus',
|
|
1516
|
+
MenuManagement: 'platform-management:menus',
|
|
1517
|
+
};
|
|
1518
|
+
|
|
583
1519
|
const AXPPlatformManagementPermissionKeys = {
|
|
584
1520
|
PlatformManagement: {
|
|
585
1521
|
Management: 'PlatformManagement:Permission:Management',
|
|
@@ -601,11 +1537,29 @@ const AXPPlatformManagementPermissionKeys = {
|
|
|
601
1537
|
},
|
|
602
1538
|
};
|
|
603
1539
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
1540
|
+
class AXMMenuProvider {
|
|
1541
|
+
constructor() {
|
|
1542
|
+
this.entityService = inject(AXPEntityService);
|
|
1543
|
+
}
|
|
1544
|
+
async provide(context) {
|
|
1545
|
+
const scope = RootConfig.config.i18n;
|
|
1546
|
+
//#region ---- Administration Menu (Authorized Users) ----
|
|
1547
|
+
context.find(AXPCommonMenuKeys.FoundationData).addItems([
|
|
1548
|
+
{
|
|
1549
|
+
name: AXPPlatformManagementMenuKeys.Tokens,
|
|
1550
|
+
priority: 20000101,
|
|
1551
|
+
text: `@${scope}:tokens.terms.tokens`,
|
|
1552
|
+
path: this.entityService.createPath(RootConfig.module.name, RootConfig.entities.token.name),
|
|
1553
|
+
icon: RootConfig.entities.token.icon,
|
|
1554
|
+
policy: {
|
|
1555
|
+
features: [RootConfig.module.name],
|
|
1556
|
+
permissions: [AXPPlatformManagementPermissionKeys.PlatformManagement.Token.Management],
|
|
1557
|
+
},
|
|
1558
|
+
},
|
|
1559
|
+
]);
|
|
1560
|
+
//#endregion
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
609
1563
|
|
|
610
1564
|
class AXMPermissionDefinitionProvider {
|
|
611
1565
|
constructor(injector) {
|
|
@@ -640,116 +1594,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
640
1594
|
type: Injectable
|
|
641
1595
|
}], ctorParameters: () => [{ type: i0.Injector }] });
|
|
642
1596
|
|
|
643
|
-
const AXPPlatformManagementMenuKeys = {
|
|
644
|
-
AdministrationGroup: 'administration:group',
|
|
645
|
-
Root: 'platform-management:menu',
|
|
646
|
-
Tokens: 'platform-management:menu:tokens',
|
|
647
|
-
Glossary: 'platform-management:menu:glossary',
|
|
648
|
-
UserMenuManagement: 'platform-management:user:menus',
|
|
649
|
-
MenuManagement: 'platform-management:menus',
|
|
650
|
-
};
|
|
651
|
-
|
|
652
|
-
class AXMMenuProvider {
|
|
653
|
-
constructor() {
|
|
654
|
-
this.entityService = inject(AXPEntityService);
|
|
655
|
-
}
|
|
656
|
-
async provide(context) {
|
|
657
|
-
const scope = RootConfig.config.i18n;
|
|
658
|
-
//#region ---- Administration Menu (Authorized Users) ----
|
|
659
|
-
context.find(AXPCommonMenuKeys.FoundationData).addItems([
|
|
660
|
-
{
|
|
661
|
-
name: AXPPlatformManagementMenuKeys.Tokens,
|
|
662
|
-
priority: 20000101,
|
|
663
|
-
text: `@${scope}:tokens.terms.tokens`,
|
|
664
|
-
path: this.entityService.createPath(RootConfig.module.name, RootConfig.entities.token.name),
|
|
665
|
-
icon: RootConfig.entities.token.icon,
|
|
666
|
-
policy: {
|
|
667
|
-
features: [RootConfig.module.name],
|
|
668
|
-
permissions: [AXPPlatformManagementPermissionKeys.PlatformManagement.Token.Management],
|
|
669
|
-
},
|
|
670
|
-
},
|
|
671
|
-
]);
|
|
672
|
-
//#endregion
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
class AXMEntityLoader {
|
|
677
|
-
constructor() {
|
|
678
|
-
this.injector = inject(Injector);
|
|
679
|
-
}
|
|
680
|
-
preload() {
|
|
681
|
-
const module = RootConfig.module.name;
|
|
682
|
-
return Array.from(Object.values(RootConfig.entities)).map((entity) => ({
|
|
683
|
-
module: module,
|
|
684
|
-
entity: entity.name,
|
|
685
|
-
}));
|
|
686
|
-
}
|
|
687
|
-
async get(moduleName, entityName) {
|
|
688
|
-
if (moduleName == RootConfig.module.name) {
|
|
689
|
-
return new Promise(async (resolve) => {
|
|
690
|
-
switch (entityName) {
|
|
691
|
-
case RootConfig.entities.token.name: {
|
|
692
|
-
const entity = (await Promise.resolve().then(function () { return index; })).tokenEntityFactory;
|
|
693
|
-
resolve(entity(this.injector));
|
|
694
|
-
break;
|
|
695
|
-
}
|
|
696
|
-
default:
|
|
697
|
-
resolve(null);
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
return null;
|
|
702
|
-
}
|
|
703
|
-
async list() {
|
|
704
|
-
const m = RootConfig.module.name;
|
|
705
|
-
return Promise.resolve(Object.values(RootConfig.entities).map((e) => ({ name: e.name, module: m })));
|
|
706
|
-
}
|
|
707
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMEntityLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
708
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMEntityLoader }); }
|
|
709
|
-
}
|
|
710
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMEntityLoader, decorators: [{
|
|
711
|
-
type: Injectable
|
|
712
|
-
}] });
|
|
713
|
-
|
|
714
|
-
//#region ---- Imports ----
|
|
715
|
-
//#endregion
|
|
716
|
-
//#region ---- Feature Definition Provider ----
|
|
717
|
-
/**
|
|
718
|
-
* Platform Management Feature Definition Provider.
|
|
719
|
-
* Provides feature definitions for the Platform Management module.
|
|
720
|
-
*/
|
|
721
|
-
class AXPPlatformManagementFeatureDefinitionProvider {
|
|
722
|
-
async provide(context) {
|
|
723
|
-
context.addFeature(AXPPlatformManagementFeatureKeys.MenuCustomization, {
|
|
724
|
-
title: '@platform-management:features.menu-customization.title',
|
|
725
|
-
description: '@platform-management:features.menu-customization.description',
|
|
726
|
-
defaultValue: true,
|
|
727
|
-
type: 'boolean',
|
|
728
|
-
});
|
|
729
|
-
context.addFeature(AXPPlatformManagementFeatureKeys.AutoCheckUpdates, {
|
|
730
|
-
title: '@platform-management:features.auto-check-updates.title',
|
|
731
|
-
description: '@platform-management:features.auto-check-updates.description',
|
|
732
|
-
defaultValue: true,
|
|
733
|
-
type: 'boolean',
|
|
734
|
-
});
|
|
735
|
-
context.addFeature(AXPPlatformManagementFeatureKeys.MaxTokens, {
|
|
736
|
-
title: '@platform-management:features.max-tokens.title',
|
|
737
|
-
description: '@platform-management:features.max-tokens.description',
|
|
738
|
-
defaultValue: 100,
|
|
739
|
-
type: 'number',
|
|
740
|
-
interface: {
|
|
741
|
-
type: 'number-editor',
|
|
742
|
-
options: {
|
|
743
|
-
min: 1,
|
|
744
|
-
max: 1000,
|
|
745
|
-
step: 1,
|
|
746
|
-
},
|
|
747
|
-
},
|
|
748
|
-
});
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
//#endregion
|
|
752
|
-
|
|
753
1597
|
async function tokenEntityFactory(injector) {
|
|
754
1598
|
const i18n = RootConfig.config.i18n;
|
|
755
1599
|
const entityDef = {
|
|
@@ -1189,7 +2033,7 @@ function routesFactory() {
|
|
|
1189
2033
|
children: [
|
|
1190
2034
|
{
|
|
1191
2035
|
path: '',
|
|
1192
|
-
loadComponent: () => import('./acorex-modules-platform-management-menu-list.component-
|
|
2036
|
+
loadComponent: () => import('./acorex-modules-platform-management-menu-list.component-C_mdsuRc.mjs').then((c) => c.AXMMenuListComponent),
|
|
1193
2037
|
data: { reuse: true },
|
|
1194
2038
|
},
|
|
1195
2039
|
],
|
|
@@ -1202,6 +2046,7 @@ class AXMPlatformManagementModule {
|
|
|
1202
2046
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMPlatformManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1203
2047
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: AXMPlatformManagementModule, imports: [AXMUpdaterModule,
|
|
1204
2048
|
AXMTokenModule,
|
|
2049
|
+
AXMMenuManagementModule,
|
|
1205
2050
|
// Entity Modules
|
|
1206
2051
|
AXMTokenEntityModule] }); }
|
|
1207
2052
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMPlatformManagementModule, providers: [
|
|
@@ -1245,6 +2090,7 @@ class AXMPlatformManagementModule {
|
|
|
1245
2090
|
},
|
|
1246
2091
|
], imports: [AXMUpdaterModule,
|
|
1247
2092
|
AXMTokenModule,
|
|
2093
|
+
AXMMenuManagementModule,
|
|
1248
2094
|
// Entity Modules
|
|
1249
2095
|
AXMTokenEntityModule] }); }
|
|
1250
2096
|
}
|
|
@@ -1254,6 +2100,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1254
2100
|
imports: [
|
|
1255
2101
|
AXMUpdaterModule,
|
|
1256
2102
|
AXMTokenModule,
|
|
2103
|
+
AXMMenuManagementModule,
|
|
1257
2104
|
// Entity Modules
|
|
1258
2105
|
AXMTokenEntityModule,
|
|
1259
2106
|
],
|
|
@@ -1308,5 +2155,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1308
2155
|
* Generated bundle index. Do not edit.
|
|
1309
2156
|
*/
|
|
1310
2157
|
|
|
1311
|
-
export {
|
|
1312
|
-
//# sourceMappingURL=acorex-modules-platform-management-acorex-modules-platform-management-
|
|
2158
|
+
export { AXPMenuManagementService as A, RootConfig as R, AXMPlatformManagementModule as a, AXMTokensService as b, AXMTokensServiceImpl as c, AXMTokenEntityModule as d, AXPPlatformManagementFeatureKeys as e, tokenEntityFactory as t };
|
|
2159
|
+
//# sourceMappingURL=acorex-modules-platform-management-acorex-modules-platform-management-DVkP3JKC.mjs.map
|