@acorex/modules 20.7.8 → 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/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-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-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 +6 -6
- package/platform-management/index.d.ts +12 -1
- package/fesm2022/acorex-modules-organization-management-org-chart.page-C85uluWf.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
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import * as i4 from '@acorex/components/badge';
|
|
2
|
+
import { AXBadgeModule } from '@acorex/components/badge';
|
|
3
|
+
import * as i1 from '@acorex/components/button';
|
|
4
|
+
import { AXButtonModule } from '@acorex/components/button';
|
|
5
|
+
import * as i2 from '@acorex/components/decorators';
|
|
6
|
+
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
7
|
+
import { AXDialogService } from '@acorex/components/dialog';
|
|
8
|
+
import * as i3 from '@acorex/components/dropdown';
|
|
9
|
+
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
10
|
+
import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
|
|
11
|
+
import { AXToastService } from '@acorex/components/toast';
|
|
12
|
+
import { AXTreeViewComponent } from '@acorex/components/tree-view';
|
|
13
|
+
import * as i6 from '@acorex/core/translation';
|
|
14
|
+
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
15
|
+
import { AXPPlatformScope } from '@acorex/platform/core';
|
|
16
|
+
import { AXPLayoutBuilderService } from '@acorex/platform/layout/builder';
|
|
17
|
+
import { AXPThemeLayoutBlockComponent, AXPStateMessageComponent } from '@acorex/platform/layout/components';
|
|
18
|
+
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex/platform/layout/views';
|
|
19
|
+
import * as i5 from '@angular/common';
|
|
20
|
+
import { CommonModule } from '@angular/common';
|
|
21
|
+
import * as i0 from '@angular/core';
|
|
22
|
+
import { inject, viewChild, signal, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
23
|
+
import { ActivatedRoute } from '@angular/router';
|
|
24
|
+
import { Subject, takeUntil } from 'rxjs';
|
|
25
|
+
import { A as AXPMenuManagementService } from './acorex-modules-platform-management-acorex-modules-platform-management-DVkP3JKC.mjs';
|
|
26
|
+
|
|
27
|
+
//#region ---- Menu List Component ----
|
|
28
|
+
class AXMMenuListComponent extends AXPPageLayoutBaseComponent {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(...arguments);
|
|
31
|
+
//#region ---- Dependencies ----
|
|
32
|
+
this.menuManagementService = inject(AXPMenuManagementService);
|
|
33
|
+
this.layoutBuilder = inject(AXPLayoutBuilderService);
|
|
34
|
+
this.dialogService = inject(AXDialogService);
|
|
35
|
+
this.toastService = inject(AXToastService);
|
|
36
|
+
this.translationService = inject(AXTranslationService);
|
|
37
|
+
this.route = inject(ActivatedRoute);
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region ---- Component State ----
|
|
40
|
+
this.tree = viewChild(AXTreeViewComponent, ...(ngDevMode ? [{ debugName: "tree" }] : []));
|
|
41
|
+
this.treeNodes = signal([], ...(ngDevMode ? [{ debugName: "treeNodes" }] : []));
|
|
42
|
+
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
43
|
+
this.error = signal('', ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
44
|
+
this.currentScope = signal(AXPPlatformScope.User, ...(ngDevMode ? [{ debugName: "currentScope" }] : []));
|
|
45
|
+
this.isSyncing = false; // Prevent concurrent sync operations
|
|
46
|
+
this.destroy$ = new Subject(); // For subscription cleanup
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region ---- Lifecycle ----
|
|
50
|
+
async ngOnInit() {
|
|
51
|
+
await super.ngOnInit();
|
|
52
|
+
// Get scope from route (with memory leak prevention)
|
|
53
|
+
this.route.params.pipe(takeUntil(this.destroy$)).subscribe(async (params) => {
|
|
54
|
+
const scope = params['scope'];
|
|
55
|
+
if (scope) {
|
|
56
|
+
this.currentScope.set(scope);
|
|
57
|
+
await this.loadMenuItems();
|
|
58
|
+
this.recompute(); // Update page header after loading
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
ngOnDestroy() {
|
|
63
|
+
this.destroy$.next();
|
|
64
|
+
this.destroy$.complete();
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region ---- Event Handlers ----
|
|
68
|
+
/**
|
|
69
|
+
* Handle before drop validation
|
|
70
|
+
*/
|
|
71
|
+
async handleBeforeDrop(e) {
|
|
72
|
+
console.log('[handleBeforeDrop] Event triggered!', {
|
|
73
|
+
movedNode: e.movedNode?.['id'],
|
|
74
|
+
previousParent: e.previousParent?.['id'],
|
|
75
|
+
currentParent: e.currentParent?.['id'],
|
|
76
|
+
previousIndex: e.previousIndex,
|
|
77
|
+
currentIndex: e.currentIndex,
|
|
78
|
+
});
|
|
79
|
+
const targetParent = e.currentParent?.['data'] || null;
|
|
80
|
+
// Prevent dropping into items with paths (leaf nodes)
|
|
81
|
+
if (targetParent?.menuItem?.path) {
|
|
82
|
+
e.canceled = true;
|
|
83
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.error.move');
|
|
84
|
+
this.toastService.warning(message);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Note: Circular reference validation is handled by the tree component itself
|
|
88
|
+
// Additional validation can be added here if needed based on business rules
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handle after drop event to sync changes
|
|
92
|
+
* The event contains information about the moved node and its new position
|
|
93
|
+
*/
|
|
94
|
+
async handleAfterDrop(event) {
|
|
95
|
+
console.log('[handleAfterDrop] Event triggered!', {
|
|
96
|
+
movedNode: event.node?.['id'],
|
|
97
|
+
movedNodeData: event.node?.['data'],
|
|
98
|
+
previousParent: event.previousParent?.['id'],
|
|
99
|
+
currentParent: event.currentParent?.['id'],
|
|
100
|
+
previousIndex: event.previousIndex,
|
|
101
|
+
currentIndex: event.currentIndex,
|
|
102
|
+
});
|
|
103
|
+
// Check what the tree component has
|
|
104
|
+
const treeComp = this.tree();
|
|
105
|
+
if (treeComp) {
|
|
106
|
+
console.log('[handleAfterDrop] Tree component datasource:', treeComp.datasource);
|
|
107
|
+
}
|
|
108
|
+
// Check our signal
|
|
109
|
+
console.log('[handleAfterDrop] Our treeNodes signal:', this.treeNodes());
|
|
110
|
+
await this.syncTreeChanges();
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region ---- Data Loading ----
|
|
114
|
+
/**
|
|
115
|
+
* Load menu tree for current scope
|
|
116
|
+
*/
|
|
117
|
+
async loadMenuItems() {
|
|
118
|
+
try {
|
|
119
|
+
this.isLoading.set(true);
|
|
120
|
+
this.error.set('');
|
|
121
|
+
const treeNodes = await this.menuManagementService.getMenuTreeByScope(this.currentScope());
|
|
122
|
+
this.treeNodes.set(treeNodes);
|
|
123
|
+
this.recompute();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
this.error.set(error instanceof Error ? error.message : 'Failed to load menu items');
|
|
127
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.error.load');
|
|
128
|
+
this.toastService.danger(message);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
this.isLoading.set(false);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Sync tree changes to backend
|
|
136
|
+
*/
|
|
137
|
+
async syncTreeChanges() {
|
|
138
|
+
// Prevent concurrent sync operations
|
|
139
|
+
if (this.isSyncing) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
this.isSyncing = true;
|
|
144
|
+
const scope = this.currentScope();
|
|
145
|
+
// Get nodes from signal - the tree component mutates the array in place
|
|
146
|
+
// so this.treeNodes() will have the updated structure after drag-drop
|
|
147
|
+
const nodes = this.treeNodes();
|
|
148
|
+
console.log('[syncTreeChanges] nodes count:', nodes?.length);
|
|
149
|
+
// Log detailed node structure
|
|
150
|
+
const logNode = (n, level = 0) => ({
|
|
151
|
+
id: n['id'],
|
|
152
|
+
title: n['title'],
|
|
153
|
+
level,
|
|
154
|
+
childrenCount: n['children']?.length ?? 0,
|
|
155
|
+
children: n['children']?.map((c) => logNode(c, level + 1)) ?? [],
|
|
156
|
+
});
|
|
157
|
+
console.log('[syncTreeChanges] Full tree structure:', JSON.stringify(nodes?.map(n => logNode(n)), null, 2));
|
|
158
|
+
if (!nodes || nodes.length === 0) {
|
|
159
|
+
console.log('[syncTreeChanges] No nodes to sync');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
await this.menuManagementService.syncTreeChangesByScope(scope, nodes);
|
|
163
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.success.reorder');
|
|
164
|
+
this.toastService.success(message);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error('Failed to sync tree changes:', error);
|
|
168
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.error.sync');
|
|
169
|
+
this.toastService.danger(message);
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
this.isSyncing = false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region ---- Page Layout Interface ----
|
|
177
|
+
/**
|
|
178
|
+
* Get page title
|
|
179
|
+
*/
|
|
180
|
+
async getPageTitle() {
|
|
181
|
+
const scopeName = this.currentScope();
|
|
182
|
+
const scopeKey = scopeName === AXPPlatformScope.User ? 'user' : 'tenant';
|
|
183
|
+
return this.translationService.translateAsync(`@platform-management:menu-management.menus.${scopeKey}.title`);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get page description
|
|
187
|
+
*/
|
|
188
|
+
async getPageDescription() {
|
|
189
|
+
return this.translationService.translateAsync('@platform-management:menu-management.components.menu-list.description');
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get primary menu items (actions)
|
|
193
|
+
*/
|
|
194
|
+
async getPrimaryMenuItems() {
|
|
195
|
+
return [
|
|
196
|
+
{
|
|
197
|
+
title: await this.translationService.translateAsync('@platform-management:menu-management.actions.add-root.title'),
|
|
198
|
+
icon: 'fa-light fa-plus',
|
|
199
|
+
color: 'primary',
|
|
200
|
+
command: { name: 'add-root' },
|
|
201
|
+
},
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get secondary menu items
|
|
206
|
+
*/
|
|
207
|
+
async getSecondaryMenuItems() {
|
|
208
|
+
return [
|
|
209
|
+
{
|
|
210
|
+
title: await this.translationService.translateAsync('@platform-management:menu-management.actions.collapse.title'),
|
|
211
|
+
icon: 'fa-light fa-minus-square',
|
|
212
|
+
command: { name: 'collapse' },
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
title: await this.translationService.translateAsync('@platform-management:menu-management.actions.expand.title'),
|
|
216
|
+
icon: 'fa-light fa-plus-square',
|
|
217
|
+
command: { name: 'expand' },
|
|
218
|
+
break: true,
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
title: await this.translationService.translateAsync('@platform-management:menu-management.actions.reset.title'),
|
|
222
|
+
icon: 'fa-light fa-rotate-left',
|
|
223
|
+
color: 'danger',
|
|
224
|
+
command: { name: 'reset' },
|
|
225
|
+
},
|
|
226
|
+
];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Execute commands from page actions
|
|
230
|
+
*/
|
|
231
|
+
async execute(command) {
|
|
232
|
+
switch (command.name) {
|
|
233
|
+
case 'add-root':
|
|
234
|
+
await this.addRootMenuItem();
|
|
235
|
+
break;
|
|
236
|
+
case 'collapse':
|
|
237
|
+
this.tree()?.collapseAll();
|
|
238
|
+
break;
|
|
239
|
+
case 'expand':
|
|
240
|
+
this.tree()?.expandAll();
|
|
241
|
+
break;
|
|
242
|
+
case 'reset':
|
|
243
|
+
await this.resetCustomizations();
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region ---- Action Handlers ----
|
|
249
|
+
/**
|
|
250
|
+
* Handle menu item action
|
|
251
|
+
*/
|
|
252
|
+
async onAction(action, nodeData) {
|
|
253
|
+
switch (action) {
|
|
254
|
+
case 'show':
|
|
255
|
+
await this.showMenuItem(nodeData);
|
|
256
|
+
break;
|
|
257
|
+
case 'hide':
|
|
258
|
+
await this.hideMenuItem(nodeData);
|
|
259
|
+
break;
|
|
260
|
+
case 'edit':
|
|
261
|
+
await this.editMenuItem(nodeData);
|
|
262
|
+
break;
|
|
263
|
+
case 'delete':
|
|
264
|
+
await this.deleteMenuItem(nodeData);
|
|
265
|
+
break;
|
|
266
|
+
case 'add-child':
|
|
267
|
+
await this.addChildMenuItem(nodeData);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Add new root menu item
|
|
273
|
+
*/
|
|
274
|
+
async addRootMenuItem() {
|
|
275
|
+
await this.showMenuItemDialog(null, null);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Add new child menu item
|
|
279
|
+
*/
|
|
280
|
+
async addChildMenuItem(parentNodeData) {
|
|
281
|
+
await this.showMenuItemDialog(null, parentNodeData.menuItem.name);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Reset customizations
|
|
285
|
+
*/
|
|
286
|
+
async resetCustomizations() {
|
|
287
|
+
const title = await this.translationService.translateAsync('@platform-management:menu-management.actions.reset.confirm.title');
|
|
288
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.actions.reset.confirm.message');
|
|
289
|
+
const confirmed = await this.dialogService.confirm(title, message);
|
|
290
|
+
if (!confirmed)
|
|
291
|
+
return;
|
|
292
|
+
try {
|
|
293
|
+
// Reset customizations for current scope
|
|
294
|
+
await this.menuManagementService.resetCustomizationsByScope(this.currentScope());
|
|
295
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.success.reset');
|
|
296
|
+
this.toastService.success(message);
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
console.error('Failed to reset customizations:', error);
|
|
300
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.error.reset');
|
|
301
|
+
this.toastService.danger(message);
|
|
302
|
+
}
|
|
303
|
+
finally {
|
|
304
|
+
// Reload anyway to show current state
|
|
305
|
+
await this.loadMenuItems();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region ---- Menu Item Actions ----
|
|
310
|
+
/**
|
|
311
|
+
* Show menu item
|
|
312
|
+
*/
|
|
313
|
+
async showMenuItem(nodeData) {
|
|
314
|
+
await this.executeMenuAction(() => this.menuManagementService.showMenuItemByScope(this.currentScope(), nodeData.menuItem.name), '@platform-management:menu-management.messages.success.show', '@platform-management:menu-management.messages.error.show');
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Hide menu item
|
|
318
|
+
*/
|
|
319
|
+
async hideMenuItem(nodeData) {
|
|
320
|
+
await this.executeMenuAction(() => this.menuManagementService.hideMenuItemByScope(this.currentScope(), nodeData.menuItem.name), '@platform-management:menu-management.messages.success.hide', '@platform-management:menu-management.messages.error.hide');
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Edit menu item
|
|
324
|
+
*/
|
|
325
|
+
async editMenuItem(nodeData) {
|
|
326
|
+
await this.showMenuItemDialog(nodeData);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Delete custom menu item
|
|
330
|
+
*/
|
|
331
|
+
async deleteMenuItem(nodeData) {
|
|
332
|
+
const title = await this.translationService.translateAsync('@general:actions.delete.title');
|
|
333
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.actions.delete.confirm.message');
|
|
334
|
+
const confirmed = await this.dialogService.confirm(title, message);
|
|
335
|
+
if (!confirmed)
|
|
336
|
+
return;
|
|
337
|
+
try {
|
|
338
|
+
const item = nodeData.menuItem;
|
|
339
|
+
if (!item.name)
|
|
340
|
+
return;
|
|
341
|
+
await this.menuManagementService.deleteCustomMenuItemByScope(this.currentScope(), item.name);
|
|
342
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.success.delete');
|
|
343
|
+
this.toastService.success(message);
|
|
344
|
+
await this.loadMenuItems();
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.error.delete');
|
|
348
|
+
this.toastService.danger(message);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region ---- Dialog Helpers ----
|
|
353
|
+
/**
|
|
354
|
+
* Show menu item dialog (add/edit)
|
|
355
|
+
*/
|
|
356
|
+
async showMenuItemDialog(nodeData, parentName = null) {
|
|
357
|
+
const item = nodeData?.menuItem;
|
|
358
|
+
const isEdit = !!item;
|
|
359
|
+
const title = isEdit
|
|
360
|
+
? '@platform-management:menu-management.components.edit-dialog.title'
|
|
361
|
+
: '@platform-management:menu-management.components.add-dialog.title';
|
|
362
|
+
const context = {
|
|
363
|
+
name: item?.name || '',
|
|
364
|
+
text: item?.text || '',
|
|
365
|
+
type: item?.type || 'menu',
|
|
366
|
+
icon: item?.icon || '',
|
|
367
|
+
path: item?.path || '',
|
|
368
|
+
priority: item?.priority || 0,
|
|
369
|
+
description: item?.description || '',
|
|
370
|
+
};
|
|
371
|
+
const dialogRef = await this.layoutBuilder
|
|
372
|
+
.create()
|
|
373
|
+
.dialog((dialog) => {
|
|
374
|
+
dialog
|
|
375
|
+
.setTitle(title)
|
|
376
|
+
.setContext(context)
|
|
377
|
+
.content((flex) => {
|
|
378
|
+
flex
|
|
379
|
+
.setDirection('column')
|
|
380
|
+
.formField('@platform-management:menu-management.fields.name', (field) => {
|
|
381
|
+
field.path('name');
|
|
382
|
+
field.textBox({
|
|
383
|
+
placeholder: '@platform-management:menu-management.fields.name',
|
|
384
|
+
validations: [{ rule: 'required' }],
|
|
385
|
+
disabled: isEdit && nodeData?.metadata?.isBuiltIn,
|
|
386
|
+
});
|
|
387
|
+
})
|
|
388
|
+
.formField('@platform-management:menu-management.fields.text', (field) => {
|
|
389
|
+
field.path('text');
|
|
390
|
+
field.textBox({
|
|
391
|
+
placeholder: '@platform-management:menu-management.fields.text',
|
|
392
|
+
validations: [{ rule: 'required' }],
|
|
393
|
+
});
|
|
394
|
+
})
|
|
395
|
+
.formField('@platform-management:menu-management.fields.icon', (field) => {
|
|
396
|
+
field.path('icon');
|
|
397
|
+
field.customWidget('icon-chooser', {});
|
|
398
|
+
})
|
|
399
|
+
.formField('@platform-management:menu-management.fields.path', (field) => {
|
|
400
|
+
field.path('path');
|
|
401
|
+
field.textBox({
|
|
402
|
+
placeholder: '@platform-management:menu-management.fields.path',
|
|
403
|
+
disabled: isEdit && nodeData?.metadata?.isBuiltIn,
|
|
404
|
+
});
|
|
405
|
+
})
|
|
406
|
+
.formField('@platform-management:menu-management.fields.priority', (field) => {
|
|
407
|
+
field.path('priority');
|
|
408
|
+
field.numberBox({
|
|
409
|
+
placeholder: '@platform-management:menu-management.fields.priority',
|
|
410
|
+
step: 10,
|
|
411
|
+
});
|
|
412
|
+
})
|
|
413
|
+
.formField('@platform-management:menu-management.fields.description', (field) => {
|
|
414
|
+
field.path('description');
|
|
415
|
+
field.largeTextBox({
|
|
416
|
+
placeholder: '@platform-management:menu-management.fields.description',
|
|
417
|
+
rows: 3,
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
})
|
|
421
|
+
.setActions((actions) => {
|
|
422
|
+
actions.cancel('@general:actions.cancel.title').submit('@general:actions.save.title');
|
|
423
|
+
});
|
|
424
|
+
})
|
|
425
|
+
.show();
|
|
426
|
+
const action = dialogRef.action();
|
|
427
|
+
if (action === 'cancel') {
|
|
428
|
+
dialogRef.close();
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
const formData = dialogRef.context();
|
|
432
|
+
try {
|
|
433
|
+
if (isEdit && item?.name) {
|
|
434
|
+
// Update existing item
|
|
435
|
+
if (nodeData?.metadata?.isCustom) {
|
|
436
|
+
await this.menuManagementService.updateCustomMenuItemByScope(this.currentScope(), item.name, formData);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
await this.menuManagementService.updateMenuPropertiesByScope(this.currentScope(), item.name, formData);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
// Add new custom item
|
|
444
|
+
const newItem = {
|
|
445
|
+
name: formData.name,
|
|
446
|
+
text: formData.text,
|
|
447
|
+
icon: formData.icon,
|
|
448
|
+
path: formData.path,
|
|
449
|
+
priority: formData.priority,
|
|
450
|
+
description: formData.description,
|
|
451
|
+
};
|
|
452
|
+
// If parent is specified, add as child
|
|
453
|
+
if (parentName) {
|
|
454
|
+
// Add custom item as child of parent
|
|
455
|
+
await this.menuManagementService.addCustomMenuItemByScope(this.currentScope(), newItem, parentName);
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
// Add as root level item
|
|
459
|
+
await this.menuManagementService.addCustomMenuItemByScope(this.currentScope(), newItem, null);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.success.save');
|
|
463
|
+
this.toastService.success(message);
|
|
464
|
+
await this.loadMenuItems();
|
|
465
|
+
dialogRef.close();
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
const message = await this.translationService.translateAsync('@platform-management:menu-management.messages.error.save');
|
|
469
|
+
this.toastService.danger(message);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Execute a menu action with common error handling
|
|
474
|
+
*/
|
|
475
|
+
async executeMenuAction(action, successMessageKey, errorMessageKey) {
|
|
476
|
+
try {
|
|
477
|
+
await action();
|
|
478
|
+
const message = await this.translationService.translateAsync(successMessageKey);
|
|
479
|
+
this.toastService.success(message);
|
|
480
|
+
await this.loadMenuItems();
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
console.error('Menu action failed:', error);
|
|
484
|
+
const message = await this.translationService.translateAsync(errorMessageKey);
|
|
485
|
+
this.toastService.danger(message);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMMenuListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
489
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AXMMenuListComponent, isStandalone: true, selector: "axm-menu-list", host: { classAttribute: "axm-menu-list-page" }, providers: [
|
|
490
|
+
{
|
|
491
|
+
provide: AXPPageLayoutBase,
|
|
492
|
+
useExisting: AXMMenuListComponent,
|
|
493
|
+
},
|
|
494
|
+
], viewQueries: [{ propertyName: "tree", first: true, predicate: AXTreeViewComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout>\n <axp-page-content>\n @if (isLoading()) {\n <!-- Loading State -->\n <axp-state-message\n mode=\"loading\"\n icon=\"fa-light fa-spinner-third fa-spin\"\n [title]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.loading.title' | translate | async)!\n \"\n [description]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.loading.description'\n | translate\n | async)!\n \"\n />\n } @else if (error()) {\n <!-- Error State -->\n <axp-state-message\n mode=\"error\"\n icon=\"fa-light fa-circle-exclamation\"\n [title]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.error.title' | translate | async)!\n \"\n [description]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.error.description'\n | translate\n | async)!\n \"\n >\n <ax-button\n slot=\"actions\"\n [text]=\"'@general:actions.retry.title' | translate | async\"\n [look]=\"'outline'\"\n [color]=\"'primary'\"\n (onClick)=\"loadMenuItems()\"\n >\n <i class=\"fa-light fa-rotate-left\"></i>\n </ax-button>\n </axp-state-message>\n } @else if (treeNodes().length === 0) {\n <!-- Empty State -->\n <axp-state-message\n mode=\"empty\"\n icon=\"fa-light fa-bars\"\n [title]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.no-data.title' | translate | async)!\n \"\n [description]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.no-data.description'\n | translate\n | async)!\n \"\n >\n <ax-button\n slot=\"actions\"\n [text]=\"'@platform-management:menu-management.actions.add-root.title' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n (onClick)=\"addRootMenuItem()\"\n >\n <i class=\"fa-light fa-plus\"></i>\n </ax-button>\n </axp-state-message>\n } @else {\n <!-- Menu Tree Content -->\n <div class=\"axm-menu-list__container\">\n <!-- Menu Tree -->\n <div class=\"axm-menu-list__tree\">\n <ax-tree-view\n [(datasource)]=\"treeNodes\"\n [look]=\"'default'\"\n [nodeTemplate]=\"itemTemplate\"\n [selectMode]=\"'none'\"\n [showIcons]=\"false\"\n [showChildrenBadge]=\"false\"\n [dragBehavior]=\"'move'\"\n [dragArea]=\"'handler'\"\n (onBeforeDrop)=\"handleBeforeDrop($event)\"\n (onItemsChange)=\"handleAfterDrop($event)\"\n ></ax-tree-view>\n </div>\n </div>\n }\n </axp-page-content>\n</axp-page-layout>\n\n<!-- Custom Item Template -->\n<ng-template #itemTemplate let-node=\"node\" let-level=\"level\">\n @let nodeData = node['data'];\n @let item = nodeData.menuItem;\n @let metadata = nodeData.metadata;\n <div\n class=\"axm-menu-tree-item__wrapper\"\n [class.axm-menu-tree-item__wrapper--hidden]=\"metadata.isHidden\"\n [class.axm-menu-tree-item__wrapper--custom]=\"metadata.isCustom\"\n [class.axm-menu-tree-item__wrapper--group]=\"item.type === 'group'\"\n >\n <!-- Icon (hidden for groups) -->\n @if (item.icon && item.type !== 'group') {\n <i class=\"axm-menu-tree-item__icon\" [class]=\"item.icon\"></i>\n }\n\n <!-- Text or Info -->\n @if (item.type === 'group') {\n <!-- Group Heading -->\n <span class=\"axm-menu-tree-item__group\">\n <i class=\"fa-light fa-layer-group\"></i>\n {{ item.text | translate | async }}\n </span>\n } @else if (item.type === 'break') {\n <!-- Divider -->\n <span class=\"axm-menu-tree-item__divider\">\n <i class=\"fa-light fa-minus\"></i>\n {{ '@platform-management:menu-management.states.divider' | translate | async }}\n </span>\n } @else if (item.text) {\n <!-- Regular Menu Item -->\n <span class=\"axm-menu-tree-item__text\">\n {{ item.text | translate | async }}\n </span>\n } @else if (item.path) {\n <!-- Path-only Item -->\n <span class=\"axm-menu-tree-item__path\">\n <i class=\"fa-light fa-link\"></i>\n {{ item.path }}\n </span>\n }\n\n <!-- Menu Name/Key -->\n @if (item.name) {\n <code class=\"axm-menu-tree-item__name\">{{ item.name }}</code>\n }\n\n <!-- Status Badges -->\n @if (metadata.isHidden) {\n <ax-badge\n [text]=\"('@platform-management:menu-management.states.hidden' | translate | async)!\"\n color=\"danger\"\n ></ax-badge>\n } @else if (metadata.isCustom) {\n <ax-badge\n [text]=\"('@platform-management:menu-management.states.custom' | translate | async)!\"\n color=\"success\"\n ></ax-badge>\n } @else if (metadata.isBuiltIn) {\n <ax-badge\n [text]=\"('@platform-management:menu-management.states.built-in' | translate | async)!\"\n color=\"primary\"\n ></ax-badge>\n }\n\n <!-- Actions Dropdown -->\n <ax-button class=\"axm-menu-tree-item__actions\" [look]=\"'blank'\" [size]=\"'sm'\" [iconOnly]=\"true\">\n <ax-prefix>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </ax-prefix>\n\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n <!-- Edit (only for items with names) -->\n @if (item.name) {\n <ax-button-item\n [text]=\"('@general:actions.edit.title' | translate | async)!\"\n (onClick)=\"onAction('edit', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-edit\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n\n <!-- Show/Hide (only for items with names) -->\n @if (item.name && metadata.isBuiltIn) {\n @if (metadata.isHidden) {\n <ax-button-item\n [text]=\"('@platform-management:menu-management.actions.show.title' | translate | async)!\"\n (onClick)=\"onAction('show', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-eye\"></i>\n </ax-prefix>\n </ax-button-item>\n } @else {\n <ax-button-item\n [text]=\"('@platform-management:menu-management.actions.hide.title' | translate | async)!\"\n (onClick)=\"onAction('hide', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-eye-slash\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n }\n\n @if (!item.path && (item.type === 'menu' || !item.type)) {\n <!-- Add Child -->\n <ax-button-item\n [text]=\"('@platform-management:menu-management.actions.add-child.title' | translate | async)!\"\n (onClick)=\"onAction('add-child', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-plus\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n\n <!-- Delete (only for custom items with names) -->\n @if (item.name && metadata.isCustom) {\n <ax-divider></ax-divider>\n <ax-button-item\n [color]=\"'danger'\"\n [text]=\"('@general:actions.delete.title' | translate | async)!\"\n (onClick)=\"onAction('delete', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-trash\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n\n <!-- Info message for items without names -->\n @if (!item.name) {\n <ax-divider></ax-divider>\n <div class=\"ax-p-2 ax-text-xs ax-text-neutral-500 ax-italic\">\n {{ '@platform-management:menu-management.messages.info.no-name' | translate | async }}\n </div>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n</ng-template>\n", styles: [".axm-menu-list-page .axm-menu-list__container{display:flex;flex-direction:column;gap:1rem;padding:1.5rem}.axm-menu-list-page .axm-menu-list__tree{display:flex;flex-direction:column;gap:.5rem}.axm-menu-list-page .axm-menu-tree-item__wrapper{display:flex;flex:1 1 0%;align-items:center;gap:1rem;border-radius:.375rem;padding:.5rem;border-width:1px;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface));transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.axm-menu-list-page .axm-menu-tree-item__wrapper:hover{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}.axm-menu-list-page .axm-menu-tree-item__wrapper--hidden{opacity:.5}.axm-menu-list-page .axm-menu-tree-item__wrapper--custom{--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__wrapper--group{padding-top:.75rem;padding-bottom:.75rem}.axm-menu-list-page .axm-menu-tree-item__icon{display:flex;align-items:center;justify-content:center;height:1.5rem;width:1.5rem;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-primary-500),var(--tw-text-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__text{flex:1 1 0%;font-size:.875rem;line-height:1.25rem;font-weight:500}.axm-menu-list-page .axm-menu-tree-item__group,.axm-menu-list-page .axm-menu-tree-item__divider,.axm-menu-list-page .axm-menu-tree-item__path{display:flex;flex:1 1 0%;align-items:center;gap:.5rem;font-size:.75rem;line-height:1rem;font-style:italic;--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__divider i,.axm-menu-list-page .axm-menu-tree-item__path i{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__name{display:flex;align-items:center;border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;--tw-bg-opacity: 1;background-color:rgb(245 245 245 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity, 1));font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-weight:400;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 229 229 / var(--tw-border-opacity, 1));white-space:nowrap;-webkit-user-select:all;user-select:all}.axm-menu-list-page .axm-menu-tree-item__actions{margin-left:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.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: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.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: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXTreeViewComponent, selector: "ax-tree-view", inputs: ["datasource", "selectMode", "selectionBehavior", "dragArea", "dragBehavior", "showIcons", "showChildrenBadge", "expandedIcon", "collapsedIcon", "indentSize", "look", "nodeTemplate", "idField", "titleField", "tooltipField", "iconField", "expandedField", "selectedField", "indeterminateField", "disabledField", "hiddenField", "childrenField", "childrenCountField", "dataField", "inheritDisabled", "expandOnDoubleClick", "doubleClickDuration", "tooltipDelay"], outputs: ["datasourceChange", "onBeforeDrop", "onNodeToggle", "onNodeSelect", "onNodeDoubleClick", "onNodeClick", "onSelectionChange", "onOrderChange", "onMoveChange", "onItemsChange"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-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: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "variant"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
495
|
+
}
|
|
496
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AXMMenuListComponent, decorators: [{
|
|
497
|
+
type: Component,
|
|
498
|
+
args: [{ selector: 'axm-menu-list', imports: [
|
|
499
|
+
CommonModule,
|
|
500
|
+
AXButtonModule,
|
|
501
|
+
AXDecoratorModule,
|
|
502
|
+
AXDropdownButtonModule,
|
|
503
|
+
AXDropdownModule,
|
|
504
|
+
AXTranslationModule,
|
|
505
|
+
AXTreeViewComponent,
|
|
506
|
+
AXPPageLayoutComponent,
|
|
507
|
+
AXPThemeLayoutBlockComponent,
|
|
508
|
+
AXPStateMessageComponent,
|
|
509
|
+
AXBadgeModule,
|
|
510
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
511
|
+
{
|
|
512
|
+
provide: AXPPageLayoutBase,
|
|
513
|
+
useExisting: AXMMenuListComponent,
|
|
514
|
+
},
|
|
515
|
+
], host: { class: 'axm-menu-list-page' }, template: "<axp-page-layout>\n <axp-page-content>\n @if (isLoading()) {\n <!-- Loading State -->\n <axp-state-message\n mode=\"loading\"\n icon=\"fa-light fa-spinner-third fa-spin\"\n [title]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.loading.title' | translate | async)!\n \"\n [description]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.loading.description'\n | translate\n | async)!\n \"\n />\n } @else if (error()) {\n <!-- Error State -->\n <axp-state-message\n mode=\"error\"\n icon=\"fa-light fa-circle-exclamation\"\n [title]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.error.title' | translate | async)!\n \"\n [description]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.error.description'\n | translate\n | async)!\n \"\n >\n <ax-button\n slot=\"actions\"\n [text]=\"'@general:actions.retry.title' | translate | async\"\n [look]=\"'outline'\"\n [color]=\"'primary'\"\n (onClick)=\"loadMenuItems()\"\n >\n <i class=\"fa-light fa-rotate-left\"></i>\n </ax-button>\n </axp-state-message>\n } @else if (treeNodes().length === 0) {\n <!-- Empty State -->\n <axp-state-message\n mode=\"empty\"\n icon=\"fa-light fa-bars\"\n [title]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.no-data.title' | translate | async)!\n \"\n [description]=\"\n ('@platform-management:menu-management.components.menu-list.empty-states.no-data.description'\n | translate\n | async)!\n \"\n >\n <ax-button\n slot=\"actions\"\n [text]=\"'@platform-management:menu-management.actions.add-root.title' | translate | async\"\n [look]=\"'solid'\"\n [color]=\"'primary'\"\n (onClick)=\"addRootMenuItem()\"\n >\n <i class=\"fa-light fa-plus\"></i>\n </ax-button>\n </axp-state-message>\n } @else {\n <!-- Menu Tree Content -->\n <div class=\"axm-menu-list__container\">\n <!-- Menu Tree -->\n <div class=\"axm-menu-list__tree\">\n <ax-tree-view\n [(datasource)]=\"treeNodes\"\n [look]=\"'default'\"\n [nodeTemplate]=\"itemTemplate\"\n [selectMode]=\"'none'\"\n [showIcons]=\"false\"\n [showChildrenBadge]=\"false\"\n [dragBehavior]=\"'move'\"\n [dragArea]=\"'handler'\"\n (onBeforeDrop)=\"handleBeforeDrop($event)\"\n (onItemsChange)=\"handleAfterDrop($event)\"\n ></ax-tree-view>\n </div>\n </div>\n }\n </axp-page-content>\n</axp-page-layout>\n\n<!-- Custom Item Template -->\n<ng-template #itemTemplate let-node=\"node\" let-level=\"level\">\n @let nodeData = node['data'];\n @let item = nodeData.menuItem;\n @let metadata = nodeData.metadata;\n <div\n class=\"axm-menu-tree-item__wrapper\"\n [class.axm-menu-tree-item__wrapper--hidden]=\"metadata.isHidden\"\n [class.axm-menu-tree-item__wrapper--custom]=\"metadata.isCustom\"\n [class.axm-menu-tree-item__wrapper--group]=\"item.type === 'group'\"\n >\n <!-- Icon (hidden for groups) -->\n @if (item.icon && item.type !== 'group') {\n <i class=\"axm-menu-tree-item__icon\" [class]=\"item.icon\"></i>\n }\n\n <!-- Text or Info -->\n @if (item.type === 'group') {\n <!-- Group Heading -->\n <span class=\"axm-menu-tree-item__group\">\n <i class=\"fa-light fa-layer-group\"></i>\n {{ item.text | translate | async }}\n </span>\n } @else if (item.type === 'break') {\n <!-- Divider -->\n <span class=\"axm-menu-tree-item__divider\">\n <i class=\"fa-light fa-minus\"></i>\n {{ '@platform-management:menu-management.states.divider' | translate | async }}\n </span>\n } @else if (item.text) {\n <!-- Regular Menu Item -->\n <span class=\"axm-menu-tree-item__text\">\n {{ item.text | translate | async }}\n </span>\n } @else if (item.path) {\n <!-- Path-only Item -->\n <span class=\"axm-menu-tree-item__path\">\n <i class=\"fa-light fa-link\"></i>\n {{ item.path }}\n </span>\n }\n\n <!-- Menu Name/Key -->\n @if (item.name) {\n <code class=\"axm-menu-tree-item__name\">{{ item.name }}</code>\n }\n\n <!-- Status Badges -->\n @if (metadata.isHidden) {\n <ax-badge\n [text]=\"('@platform-management:menu-management.states.hidden' | translate | async)!\"\n color=\"danger\"\n ></ax-badge>\n } @else if (metadata.isCustom) {\n <ax-badge\n [text]=\"('@platform-management:menu-management.states.custom' | translate | async)!\"\n color=\"success\"\n ></ax-badge>\n } @else if (metadata.isBuiltIn) {\n <ax-badge\n [text]=\"('@platform-management:menu-management.states.built-in' | translate | async)!\"\n color=\"primary\"\n ></ax-badge>\n }\n\n <!-- Actions Dropdown -->\n <ax-button class=\"axm-menu-tree-item__actions\" [look]=\"'blank'\" [size]=\"'sm'\" [iconOnly]=\"true\">\n <ax-prefix>\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </ax-prefix>\n\n <ax-dropdown-panel #panel>\n <ax-button-item-list>\n <!-- Edit (only for items with names) -->\n @if (item.name) {\n <ax-button-item\n [text]=\"('@general:actions.edit.title' | translate | async)!\"\n (onClick)=\"onAction('edit', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-edit\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n\n <!-- Show/Hide (only for items with names) -->\n @if (item.name && metadata.isBuiltIn) {\n @if (metadata.isHidden) {\n <ax-button-item\n [text]=\"('@platform-management:menu-management.actions.show.title' | translate | async)!\"\n (onClick)=\"onAction('show', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-eye\"></i>\n </ax-prefix>\n </ax-button-item>\n } @else {\n <ax-button-item\n [text]=\"('@platform-management:menu-management.actions.hide.title' | translate | async)!\"\n (onClick)=\"onAction('hide', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-eye-slash\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n }\n\n @if (!item.path && (item.type === 'menu' || !item.type)) {\n <!-- Add Child -->\n <ax-button-item\n [text]=\"('@platform-management:menu-management.actions.add-child.title' | translate | async)!\"\n (onClick)=\"onAction('add-child', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-plus\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n\n <!-- Delete (only for custom items with names) -->\n @if (item.name && metadata.isCustom) {\n <ax-divider></ax-divider>\n <ax-button-item\n [color]=\"'danger'\"\n [text]=\"('@general:actions.delete.title' | translate | async)!\"\n (onClick)=\"onAction('delete', nodeData); panel.close()\"\n >\n <ax-prefix>\n <i class=\"fa-light fa-trash\"></i>\n </ax-prefix>\n </ax-button-item>\n }\n\n <!-- Info message for items without names -->\n @if (!item.name) {\n <ax-divider></ax-divider>\n <div class=\"ax-p-2 ax-text-xs ax-text-neutral-500 ax-italic\">\n {{ '@platform-management:menu-management.messages.info.no-name' | translate | async }}\n </div>\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n</ng-template>\n", styles: [".axm-menu-list-page .axm-menu-list__container{display:flex;flex-direction:column;gap:1rem;padding:1.5rem}.axm-menu-list-page .axm-menu-list__tree{display:flex;flex-direction:column;gap:.5rem}.axm-menu-list-page .axm-menu-tree-item__wrapper{display:flex;flex:1 1 0%;align-items:center;gap:1rem;border-radius:.375rem;padding:.5rem;border-width:1px;background-color:rgb(var(--ax-sys-color-lightest-surface));color:rgb(var(--ax-sys-color-on-lightest-surface));border-color:rgb(var(--ax-sys-color-border-lightest-surface));transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.axm-menu-list-page .axm-menu-tree-item__wrapper:hover{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}.axm-menu-list-page .axm-menu-tree-item__wrapper--hidden{opacity:.5}.axm-menu-list-page .axm-menu-tree-item__wrapper--custom{--tw-border-opacity: 1;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__wrapper--group{padding-top:.75rem;padding-bottom:.75rem}.axm-menu-list-page .axm-menu-tree-item__icon{display:flex;align-items:center;justify-content:center;height:1.5rem;width:1.5rem;--tw-text-opacity: 1;color:rgba(var(--ax-sys-color-primary-500),var(--tw-text-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__text{flex:1 1 0%;font-size:.875rem;line-height:1.25rem;font-weight:500}.axm-menu-list-page .axm-menu-tree-item__group,.axm-menu-list-page .axm-menu-tree-item__divider,.axm-menu-list-page .axm-menu-tree-item__path{display:flex;flex:1 1 0%;align-items:center;gap:.5rem;font-size:.75rem;line-height:1rem;font-style:italic;--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__divider i,.axm-menu-list-page .axm-menu-tree-item__path i{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.axm-menu-list-page .axm-menu-tree-item__name{display:flex;align-items:center;border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;line-height:1rem;--tw-bg-opacity: 1;background-color:rgb(245 245 245 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity, 1));font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-weight:400;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 229 229 / var(--tw-border-opacity, 1));white-space:nowrap;-webkit-user-select:all;user-select:all}.axm-menu-list-page .axm-menu-tree-item__actions{margin-left:.5rem}\n"] }]
|
|
516
|
+
}], propDecorators: { tree: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXTreeViewComponent), { isSignal: true }] }] } });
|
|
517
|
+
|
|
518
|
+
export { AXMMenuListComponent };
|
|
519
|
+
//# sourceMappingURL=acorex-modules-platform-management-menu-list.component-C_mdsuRc.mjs.map
|