@acorex-platform/module-application-management-client 0.0.18 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/fesm2022/{acorex-platform-module-application-management-client-application-status.provider-DqPlbWuW.mjs → acorex-platform-module-application-management-client-application-status.provider-Bz6cknzi.mjs} +4 -4
  2. package/fesm2022/{acorex-platform-module-application-management-client-application-status.provider-DqPlbWuW.mjs.map → acorex-platform-module-application-management-client-application-status.provider-Bz6cknzi.mjs.map} +1 -1
  3. package/fesm2022/{acorex-platform-module-application-management-client-assign-features.command-R7y4QKhC.mjs → acorex-platform-module-application-management-client-assign-features.command-BG986HtP.mjs} +23 -21
  4. package/fesm2022/acorex-platform-module-application-management-client-assign-features.command-BG986HtP.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-module-application-management-client-contracts.mjs +79 -1930
  6. package/fesm2022/acorex-platform-module-application-management-client-contracts.mjs.map +1 -1
  7. package/fesm2022/{acorex-platform-module-application-management-client-feature-definition.provider-Depetn50.mjs → acorex-platform-module-application-management-client-feature-definition.provider-V-wfUEZf.mjs} +4 -4
  8. package/fesm2022/{acorex-platform-module-application-management-client-feature-definition.provider-Depetn50.mjs.map → acorex-platform-module-application-management-client-feature-definition.provider-V-wfUEZf.mjs.map} +1 -1
  9. package/fesm2022/acorex-platform-module-application-management-client-features-editor.component-B5yrn7eX.mjs +584 -0
  10. package/fesm2022/acorex-platform-module-application-management-client-features-editor.component-B5yrn7eX.mjs.map +1 -0
  11. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-column.component-CiBGmw6I.mjs → acorex-platform-module-application-management-client-features-widget-column.component-C2OEG0LL.mjs} +7 -8
  12. package/fesm2022/acorex-platform-module-application-management-client-features-widget-column.component-C2OEG0LL.mjs.map +1 -0
  13. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-designer.component-nStj9BAw.mjs → acorex-platform-module-application-management-client-features-widget-designer.component-CMJwcY5f.mjs} +4 -4
  14. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-designer.component-nStj9BAw.mjs.map → acorex-platform-module-application-management-client-features-widget-designer.component-CMJwcY5f.mjs.map} +1 -1
  15. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-edit.component-BdHYm0Yr.mjs → acorex-platform-module-application-management-client-features-widget-edit.component-D_IBCjfM.mjs} +5 -5
  16. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-edit.component-BdHYm0Yr.mjs.map → acorex-platform-module-application-management-client-features-widget-edit.component-D_IBCjfM.mjs.map} +1 -1
  17. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-print.component-C6Z9uzRr.mjs → acorex-platform-module-application-management-client-features-widget-print.component-CkTEfzcY.mjs} +4 -4
  18. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-print.component-C6Z9uzRr.mjs.map → acorex-platform-module-application-management-client-features-widget-print.component-CkTEfzcY.mjs.map} +1 -1
  19. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-view.component-ysM1jD08.mjs → acorex-platform-module-application-management-client-features-widget-view.component-yKbBTqym.mjs} +12 -8
  20. package/fesm2022/{acorex-platform-module-application-management-client-features-widget-view.component-ysM1jD08.mjs.map → acorex-platform-module-application-management-client-features-widget-view.component-yKbBTqym.mjs.map} +1 -1
  21. package/fesm2022/acorex-platform-module-application-management-client-permission-definition.provider-MTs9VAE_.mjs +44 -0
  22. package/fesm2022/acorex-platform-module-application-management-client-permission-definition.provider-MTs9VAE_.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-module-application-management-client.mjs +256 -217
  24. package/fesm2022/acorex-platform-module-application-management-client.mjs.map +1 -1
  25. package/package.json +1 -1
  26. package/types/acorex-platform-module-application-management-client-contracts.d.ts +166 -51
  27. package/types/acorex-platform-module-application-management-client.d.ts +9 -17
  28. package/fesm2022/acorex-platform-module-application-management-client-assign-features.command-R7y4QKhC.mjs.map +0 -1
  29. package/fesm2022/acorex-platform-module-application-management-client-features-editor.component-BiYXAqYJ.mjs +0 -548
  30. package/fesm2022/acorex-platform-module-application-management-client-features-editor.component-BiYXAqYJ.mjs.map +0 -1
  31. package/fesm2022/acorex-platform-module-application-management-client-features-widget-column.component-CiBGmw6I.mjs.map +0 -1
  32. package/fesm2022/acorex-platform-module-application-management-client-permission-definition.provider-Dn5WiubC.mjs +0 -32
  33. package/fesm2022/acorex-platform-module-application-management-client-permission-definition.provider-Dn5WiubC.mjs.map +0 -1
@@ -1,548 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, signal, computed, input, output, ViewEncapsulation, Component } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import * as i2 from '@angular/forms';
6
- import { FormsModule } from '@angular/forms';
7
- import { AXFormModule } from '@acorex/components/form';
8
- import * as i2$1 from '@acorex/components/check-box';
9
- import { AXCheckBoxModule } from '@acorex/components/check-box';
10
- import { AXLabelModule } from '@acorex/components/label';
11
- import * as i6 from '@acorex/core/translation';
12
- import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
13
- import * as i4 from '@acorex/components/tooltip';
14
- import { AXTooltipModule } from '@acorex/components/tooltip';
15
- import { AXPModuleManifestRegistry } from '@acorex-platform/framework-client/core';
16
- import * as i5 from '@acorex-platform/framework-client/layout/widget-core';
17
- import { AXPWidgetCoreModule } from '@acorex-platform/framework-client/layout/widget-core';
18
-
19
- //#endregion
20
- //#region ---- Features Editor Component ----
21
- class AXPFeaturesEditorComponent {
22
- constructor() {
23
- //#region ---- Class Properties ----
24
- /** Service for fetching module manifests and feature definitions */
25
- this.manifestRegistry = inject(AXPModuleManifestRegistry);
26
- /** Translation service for loading translated titles */
27
- this.translationService = inject(AXTranslationService);
28
- /** All available module manifests with translated titles */
29
- this.allModules = signal([], ...(ngDevMode ? [{ debugName: "allModules" }] : /* istanbul ignore next */ []));
30
- /** Sorted modules by translated title */
31
- this.modules = computed(() => {
32
- const modules = [...this.allModules()];
33
- return modules.sort((a, b) => {
34
- const titleA = a.translatedTitle || a.title || '';
35
- const titleB = b.translatedTitle || b.title || '';
36
- return titleA.localeCompare(titleB, undefined, { sensitivity: 'base' });
37
- });
38
- }, ...(ngDevMode ? [{ debugName: "modules" }] : /* istanbul ignore next */ []));
39
- /** Initial value: { modules: string[], features: Record<string, any> } */
40
- this.initialValue = input({}, ...(ngDevMode ? [{ debugName: "initialValue" }] : /* istanbul ignore next */ []));
41
- /** Whether the editor is in read-only mode */
42
- this.readOnly = input(false, ...(ngDevMode ? [{ debugName: "readOnly" }] : /* istanbul ignore next */ []));
43
- /** Selected module names */
44
- this.selectedModules = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedModules" }] : /* istanbul ignore next */ []));
45
- /** Expanded module names */
46
- this.expandedModules = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedModules" }] : /* istanbul ignore next */ []));
47
- /** Expanded feature full names */
48
- this.expandedFeatures = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedFeatures" }] : /* istanbul ignore next */ []));
49
- /** Map of feature values: Record<featureName, featureValue> */
50
- this.featureValues = signal({}, ...(ngDevMode ? [{ debugName: "featureValues" }] : /* istanbul ignore next */ []));
51
- /** Required module names (always enabled, cannot be disabled) */
52
- this.requiredModules = computed(() => {
53
- return new Set(this.allModules()
54
- .filter((m) => m.required === true)
55
- .map((m) => m.name));
56
- }, ...(ngDevMode ? [{ debugName: "requiredModules" }] : /* istanbul ignore next */ []));
57
- /** Modules that are dependencies of selected modules (auto-selected and disabled) */
58
- this.dependencyModules = computed(() => {
59
- const selected = this.selectedModules();
60
- const allManifests = this.manifestRegistry.getAll();
61
- const dependencySet = new Set();
62
- // Find all modules that are dependencies of selected modules
63
- for (const manifest of allManifests) {
64
- if (selected.has(manifest.name) && manifest.dependencies) {
65
- for (const dep of manifest.dependencies) {
66
- // Only add module dependencies (skip features which contain a dot)
67
- if (!dep.includes('.')) {
68
- dependencySet.add(dep);
69
- }
70
- }
71
- }
72
- }
73
- return dependencySet;
74
- }, ...(ngDevMode ? [{ debugName: "dependencyModules" }] : /* istanbul ignore next */ []));
75
- /** Event emitted when modules/features selection/values change */
76
- this.valueChanged = output();
77
- /** Cache for widget nodes to prevent re-creation and blinking */
78
- this.widgetNodeCache = new Map();
79
- /** Cache for feature data to prevent re-computation */
80
- this.moduleFeaturesCache = new Map();
81
- /** Set of modules that are currently loading features */
82
- this.loadingFeatures = signal(new Set(), ...(ngDevMode ? [{ debugName: "loadingFeatures" }] : /* istanbul ignore next */ []));
83
- /** Signal to trigger change detection when features are loaded */
84
- this.featuresLoaded = signal(0, ...(ngDevMode ? [{ debugName: "featuresLoaded" }] : /* istanbul ignore next */ []));
85
- }
86
- //#endregion
87
- //#region ---- Lifecycle Methods ----
88
- /**
89
- * Initializes the component and loads module manifests.
90
- */
91
- async ngOnInit() {
92
- // Ensure registry is initialized before loading manifests
93
- await this.manifestRegistry.initialize();
94
- // Load all modules regardless of whether they have features
95
- const manifests = this.manifestRegistry.getAll();
96
- // Load translated titles for all modules
97
- const modulesWithTranslations = await Promise.all(manifests.map(async (manifest) => {
98
- const translatedTitle = await this.translationService.translateAsync(manifest.title);
99
- return {
100
- ...manifest,
101
- translatedTitle,
102
- };
103
- }));
104
- this.allModules.set(modulesWithTranslations);
105
- // Load initial value
106
- const initialValue = this.initialValue();
107
- const initialModules = new Set(initialValue.modules || []);
108
- // Extract module names from feature keys (both module-level and regular features)
109
- if (initialValue.features) {
110
- for (const featureKey of Object.keys(initialValue.features)) {
111
- // Extract module name from feature key (format: ModuleName:Feature:...)
112
- const [moduleName] = featureKey.split(':');
113
- if (moduleName) {
114
- initialModules.add(moduleName);
115
- }
116
- }
117
- }
118
- // Always include required modules
119
- const requiredModules = this.requiredModules();
120
- requiredModules.forEach((moduleName) => {
121
- initialModules.add(moduleName);
122
- });
123
- // Auto-select dependencies for initially selected modules
124
- this.ensureDependencies(initialModules);
125
- this.selectedModules.set(initialModules);
126
- // Update dependency modules after setting selected modules
127
- // This ensures dependencyModules computed signal is updated
128
- if (initialValue.features) {
129
- this.featureValues.set(initialValue.features);
130
- }
131
- // Clear caches when initializing
132
- this.widgetNodeCache.clear();
133
- this.moduleFeaturesCache.clear();
134
- }
135
- //#endregion
136
- //#region ---- Utility Methods ----
137
- /**
138
- * Creates or retrieves a cached widget node from feature interface definition.
139
- * Uses caching to prevent widget re-rendering and blinking.
140
- */
141
- createWidgetNode(definition, fullName) {
142
- if (!definition.interface) {
143
- return null;
144
- }
145
- const currentValue = this.featureValues()[fullName];
146
- const defaultValue = currentValue !== undefined && currentValue !== null ? currentValue : definition.defaultValue;
147
- // Check cache first
148
- let widgetNode = this.widgetNodeCache.get(fullName);
149
- if (!widgetNode) {
150
- // Create new widget node
151
- widgetNode = {
152
- type: definition.interface.type,
153
- name: fullName,
154
- defaultValue: defaultValue,
155
- options: definition.interface.options || {},
156
- };
157
- this.widgetNodeCache.set(fullName, widgetNode);
158
- }
159
- else {
160
- // Update defaultValue only if it actually changed (to prevent re-renders)
161
- if (widgetNode.defaultValue !== defaultValue) {
162
- widgetNode.defaultValue = defaultValue;
163
- }
164
- // Keep the same reference to prevent widget re-initialization
165
- }
166
- return widgetNode;
167
- }
168
- /**
169
- * Gets the current value (modules and features).
170
- */
171
- getValue() {
172
- return {
173
- modules: Array.from(this.selectedModules()),
174
- features: this.featureValues(),
175
- };
176
- }
177
- /**
178
- * Sets the value (modules and features).
179
- */
180
- setValue(value) {
181
- if (value.modules) {
182
- this.selectedModules.set(new Set(value.modules));
183
- }
184
- if (value.features) {
185
- this.featureValues.set(value.features);
186
- }
187
- this.emitValueChanged();
188
- }
189
- /**
190
- * Emits the current value.
191
- */
192
- emitValueChanged() {
193
- this.valueChanged.emit(this.getValue());
194
- }
195
- /**
196
- * Ensures all dependencies for the given modules are selected.
197
- * Recursively checks and adds dependencies.
198
- */
199
- ensureDependencies(modules) {
200
- const allManifests = this.manifestRegistry.getAll();
201
- let changed = true;
202
- while (changed) {
203
- changed = false;
204
- for (const manifest of allManifests) {
205
- if (modules.has(manifest.name) && manifest.dependencies) {
206
- for (const dep of manifest.dependencies) {
207
- // Only add module dependencies (skip features which contain a dot)
208
- if (!dep.includes('.')) {
209
- if (!modules.has(dep)) {
210
- modules.add(dep);
211
- changed = true;
212
- }
213
- }
214
- }
215
- }
216
- }
217
- }
218
- }
219
- /**
220
- * Gets features for a module with caching to prevent re-computation.
221
- * Features are loaded from feature definition providers and registered in the manifest registry.
222
- * This method is read-only and should not update signals during template rendering.
223
- */
224
- getModuleFeatures(module) {
225
- // Access featuresLoaded signal to make this reactive to feature loading
226
- // This is a read operation, which is safe during template rendering
227
- this.featuresLoaded();
228
- // Get features from manifest registry
229
- const moduleFeatures = this.manifestRegistry.getModuleFeatures(module.name);
230
- if (moduleFeatures.length === 0) {
231
- return [];
232
- }
233
- const cacheKey = module.name;
234
- const currentValues = this.featureValues();
235
- // Check if we need to invalidate cache (if feature values changed)
236
- const cached = this.moduleFeaturesCache.get(cacheKey);
237
- if (cached) {
238
- // Update isEnabled status and widget node values without recreating objects
239
- cached.forEach((feature) => {
240
- const currentValue = currentValues[feature.fullName];
241
- feature.isEnabled = currentValue !== undefined && currentValue !== null;
242
- // Update widget node defaultValue if it exists
243
- if (feature.widgetNode) {
244
- const newDefaultValue = currentValue !== undefined && currentValue !== null
245
- ? currentValue
246
- : feature.definition.defaultValue;
247
- if (feature.widgetNode.defaultValue !== newDefaultValue) {
248
- feature.widgetNode.defaultValue = newDefaultValue;
249
- }
250
- }
251
- });
252
- return cached;
253
- }
254
- // Create new cache entry from registry features
255
- const features = moduleFeatures.map((featureDef) => {
256
- const fullName = featureDef.name;
257
- const shortKey = featureDef.key;
258
- const currentValue = currentValues[fullName];
259
- const isEnabled = currentValue !== undefined && currentValue !== null;
260
- const widgetNode = this.createWidgetNode(featureDef, fullName);
261
- return {
262
- key: shortKey,
263
- fullName,
264
- definition: featureDef,
265
- isEnabled,
266
- widgetNode,
267
- };
268
- });
269
- this.moduleFeaturesCache.set(cacheKey, features);
270
- return features;
271
- }
272
- /**
273
- * Loads features for a module.
274
- * Features are already loaded and registered during manifest registry initialization,
275
- * so this method just triggers cache invalidation for change detection.
276
- */
277
- async loadModuleFeatures(module) {
278
- try {
279
- // Features are already loaded during manifest registry initialization
280
- // Just clear cache to force re-computation
281
- this.moduleFeaturesCache.delete(module.name);
282
- // Trigger change detection
283
- this.featuresLoaded.update(v => v + 1);
284
- }
285
- finally {
286
- // Remove from loading set
287
- this.loadingFeatures.update(set => {
288
- const newSet = new Set(set);
289
- newSet.delete(module.name);
290
- return newSet;
291
- });
292
- }
293
- }
294
- //#endregion
295
- //#region ---- UI Handlers ----
296
- /**
297
- * Toggles module expansion.
298
- */
299
- toggleModule(module) {
300
- const moduleName = module.name;
301
- const expanded = new Set(this.expandedModules());
302
- if (expanded.has(moduleName)) {
303
- expanded.delete(moduleName);
304
- }
305
- else {
306
- expanded.add(moduleName);
307
- // Features are already loaded during manifest registry initialization
308
- // Just trigger cache refresh if needed
309
- if (!this.loadingFeatures().has(moduleName)) {
310
- this.loadingFeatures.update(set => new Set(set).add(moduleName));
311
- this.loadModuleFeatures(module).catch(error => {
312
- console.error(`Failed to refresh features for module ${moduleName}:`, error);
313
- });
314
- }
315
- }
316
- this.expandedModules.set(expanded);
317
- }
318
- /**
319
- * Toggles feature expansion.
320
- */
321
- toggleFeature(fullName) {
322
- const expanded = new Set(this.expandedFeatures());
323
- if (expanded.has(fullName)) {
324
- expanded.delete(fullName);
325
- }
326
- else {
327
- expanded.add(fullName);
328
- }
329
- this.expandedFeatures.set(expanded);
330
- }
331
- /**
332
- * Checks if module is expanded.
333
- */
334
- isModuleExpanded(moduleName) {
335
- return this.expandedModules().has(moduleName);
336
- }
337
- /**
338
- * Checks if feature is expanded.
339
- */
340
- isFeatureExpanded(fullName) {
341
- return this.expandedFeatures().has(fullName);
342
- }
343
- /**
344
- * Checks if module is selected.
345
- * A module is considered selected if:
346
- * 1. It's in the selectedModules set, OR
347
- * 2. The module name is enabled as a feature (module name itself is used as feature key)
348
- */
349
- isModuleSelected(moduleName) {
350
- if (this.selectedModules().has(moduleName)) {
351
- return true;
352
- }
353
- // Check if module name is enabled as a feature
354
- const featureValue = this.featureValues()[moduleName];
355
- return featureValue !== undefined && featureValue !== null;
356
- }
357
- /**
358
- * Checks if module is required (always enabled, cannot be disabled).
359
- */
360
- isModuleRequired(moduleName) {
361
- return this.requiredModules().has(moduleName);
362
- }
363
- /**
364
- * Checks if module is a dependency of other selected modules (auto-selected and disabled).
365
- */
366
- isModuleDependency(moduleName) {
367
- return this.dependencyModules().has(moduleName);
368
- }
369
- /**
370
- * Checks if module should be disabled (required or dependency).
371
- */
372
- isModuleDisabled(moduleName) {
373
- return this.isModuleRequired(moduleName) || this.isModuleDependency(moduleName);
374
- }
375
- /**
376
- * Checks if module can be enabled (dependencies are satisfied).
377
- */
378
- canEnableModule(moduleName) {
379
- const manifest = this.manifestRegistry.get(moduleName);
380
- if (!manifest?.dependencies || manifest.dependencies.length === 0) {
381
- return true;
382
- }
383
- const selected = this.selectedModules();
384
- // Only check module dependencies (skip features which contain a dot)
385
- const moduleDeps = manifest.dependencies.filter((dep) => !dep.includes('.'));
386
- return moduleDeps.every((dep) => selected.has(dep));
387
- }
388
- /**
389
- * Gets missing dependencies for a module.
390
- */
391
- getMissingDependencies(moduleName) {
392
- const manifest = this.manifestRegistry.get(moduleName);
393
- if (!manifest?.dependencies || manifest.dependencies.length === 0) {
394
- return [];
395
- }
396
- const selected = this.selectedModules();
397
- // Only check module dependencies (skip features which contain a dot)
398
- const moduleDeps = manifest.dependencies.filter((dep) => !dep.includes('.'));
399
- return moduleDeps.filter((dep) => !selected.has(dep));
400
- }
401
- /**
402
- * Gets modules that depend on the given module.
403
- */
404
- getDependentModules(moduleName) {
405
- const allManifests = this.manifestRegistry.getAll();
406
- return allManifests
407
- .filter((m) => m.dependencies?.includes(moduleName))
408
- .map((m) => m.name);
409
- }
410
- /**
411
- * Gets the tooltip text for a dependency module showing which modules depend on it.
412
- */
413
- getDependencyTooltip(moduleName) {
414
- const dependentModules = this.getDependentModules(moduleName);
415
- const selectedDependents = dependentModules.filter((m) => this.isModuleSelected(m));
416
- if (selectedDependents.length === 0) {
417
- return 'Required dependency';
418
- }
419
- return `Required dependency of: ${selectedDependents.join(', ')}`;
420
- }
421
- /**
422
- * Gets the icon class for a module, with fallback to default cube icon.
423
- */
424
- getModuleIcon(module) {
425
- return module.icon || 'fa-light fa-cube';
426
- }
427
- /**
428
- * Checks if module has features.
429
- * Returns true if features are already loaded.
430
- * Features are loaded from feature definition providers on-demand.
431
- */
432
- hasModuleFeatures(module) {
433
- const moduleFeatures = this.manifestRegistry.getModuleFeatures(module.name);
434
- // If features are already loaded, return true
435
- return moduleFeatures.length > 0;
436
- }
437
- /**
438
- * Handles module checkbox toggle.
439
- * When enabled, enables the module name as a feature (module name itself is used as feature key).
440
- * When disabled, removes the module name feature.
441
- */
442
- onModuleToggle(module, event) {
443
- if (this.readOnly() || this.isModuleDisabled(module.name)) {
444
- return;
445
- }
446
- const selectedModules = new Set(this.selectedModules());
447
- const currentValues = { ...this.featureValues() };
448
- if (event.value) {
449
- selectedModules.add(module.name);
450
- // Enable module name as feature (module name itself is used as feature key)
451
- currentValues[module.name] = true;
452
- // Auto-select dependencies recursively
453
- this.ensureDependencies(selectedModules);
454
- // Features are already loaded during manifest registry initialization
455
- // Just trigger cache refresh if needed
456
- if (!this.loadingFeatures().has(module.name)) {
457
- setTimeout(() => {
458
- this.loadingFeatures.update(set => new Set(set).add(module.name));
459
- this.loadModuleFeatures(module).catch(error => {
460
- console.error(`Failed to refresh features for module ${module.name}:`, error);
461
- this.loadingFeatures.update(set => {
462
- const newSet = new Set(set);
463
- newSet.delete(module.name);
464
- return newSet;
465
- });
466
- });
467
- }, 0);
468
- }
469
- }
470
- else {
471
- // Check if other modules depend on this one
472
- const dependentModules = this.getDependentModules(module.name);
473
- const hasSelectedDependents = dependentModules.some((dep) => selectedModules.has(dep));
474
- if (hasSelectedDependents) {
475
- // Don't allow disabling if other selected modules depend on it
476
- return;
477
- }
478
- selectedModules.delete(module.name);
479
- // Remove module name feature when module is deselected
480
- delete currentValues[module.name];
481
- }
482
- this.selectedModules.set(selectedModules);
483
- this.featureValues.set(currentValues);
484
- this.emitValueChanged();
485
- }
486
- /**
487
- * Handles feature checkbox toggle.
488
- */
489
- onFeatureToggle(feature, event) {
490
- if (this.readOnly()) {
491
- return;
492
- }
493
- const currentValues = { ...this.featureValues() };
494
- if (event.value) {
495
- // Enable feature - use default value if not set
496
- if (currentValues[feature.fullName] === undefined || currentValues[feature.fullName] === null) {
497
- currentValues[feature.fullName] = feature.definition.defaultValue;
498
- }
499
- }
500
- else {
501
- // Disable feature - remove from values
502
- delete currentValues[feature.fullName];
503
- }
504
- this.featureValues.set(currentValues);
505
- this.emitValueChanged();
506
- }
507
- /**
508
- * Handles feature widget value change.
509
- */
510
- onFeatureValueChange(featureFullName, value) {
511
- if (this.readOnly()) {
512
- return;
513
- }
514
- const currentValues = { ...this.featureValues() };
515
- currentValues[featureFullName] = value;
516
- this.featureValues.set(currentValues);
517
- this.emitValueChanged();
518
- }
519
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFeaturesEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
520
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPFeaturesEditorComponent, isStandalone: true, selector: "axm-features-editor", inputs: { initialValue: { classPropertyName: "initialValue", publicName: "initialValue", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, host: { classAttribute: "flex" }, ngImport: i0, template: "<div class=\"px-3 py-6\">\n <div class=\"flex flex-col gap-3\">\n @for (module of modules(); track module.name) {\n <ng-container *ngTemplateOutlet=\"moduleTemplate; context: { $implicit: module, level: 0 }\">\n </ng-container>\n }\n </div>\n</div>\n\n<!-- Module Template -->\n<ng-template #moduleTemplate let-module let-level=\"level\">\n <div class=\"flex flex-col\">\n <!-- Module Row -->\n <div class=\"flex items-center gap-3 rounded hover:bg-surface-lowest\"\n [style.padding-left.px]=\"level * 32\">\n <!-- Spacer for alignment -->\n <span class=\"w-4\"></span>\n\n <!-- Module Checkbox -->\n <ax-check-box [ngModel]=\"isModuleSelected(module.name)\" [readonly]=\"readOnly() || isModuleDisabled(module.name)\"\n [class.opacity-50]=\"isModuleDependency(module.name) && !isModuleRequired(module.name)\"\n (onValueChanged)=\"onModuleToggle(module, $event)\" (click)=\"$event.stopPropagation()\">\n </ax-check-box>\n\n <!-- Module Icon -->\n <i [class]=\"getModuleIcon(module) + ' text-primary fa-fw'\"></i>\n\n <!-- Module Title -->\n <span class=\"flex-1 font-semibold\">{{ module.title | translate | async }}</span>\n\n <!-- Required Badge -->\n @if (isModuleRequired(module.name)) {\n <span class=\"text-xs text-primary font-medium\" [axTooltip]=\"'Required module'\">\n (Required)\n </span>\n }\n\n <!-- Dependency Badge -->\n @if (isModuleDependency(module.name) && !isModuleRequired(module.name)) {\n <span class=\"text-xs text-secondary font-medium\" [axTooltip]=\"getDependencyTooltip(module.name)\">\n (Dependency)\n </span>\n }\n </div>\n\n <!-- Features (shown when module is checked and has features) -->\n @if (isModuleSelected(module.name) && hasModuleFeatures(module)) {\n <div class=\"flex flex-col gap-3 py-6 px-3\">\n @for (feature of getModuleFeatures(module); track feature.fullName) {\n <ng-container\n *ngTemplateOutlet=\"featureTemplate; context: { $implicit: feature, module: module, level: level + 1 }\">\n </ng-container>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<!-- Feature Template -->\n<ng-template #featureTemplate let-feature let-module=\"module\" let-level=\"level\">\n <div class=\"flex flex-col\">\n <!-- Feature Row -->\n <div class=\"flex items-start gap-3 rounded hover:bg-surface-lowest\"\n [style.padding-left.px]=\"level * 32\">\n <!-- Spacer for alignment -->\n <span class=\"w-4\"></span>\n\n <!-- Feature Checkbox -->\n <ax-check-box [ngModel]=\"feature.isEnabled\" [readonly]=\"readOnly()\"\n (onValueChanged)=\"onFeatureToggle(feature, $event)\" (click)=\"$event.stopPropagation()\"></ax-check-box>\n\n <!-- Feature Content (Icon, Title, Description) -->\n <div class=\"flex flex-col flex-1 gap-1.5\">\n <div class=\"flex items-center gap-2\">\n <!-- Feature Icon -->\n <i class=\"fa-light fa-toggle-on text-secondary\"></i>\n <!-- Feature Title -->\n <span class=\"font-semibold\">{{ feature.definition.title | translate | async }}</span>\n </div>\n\n <!-- Feature Description -->\n @if (feature.definition.description) {\n <div class=\"text-sm text-muted ms-6 leading-relaxed\">\n {{ feature.definition.description | translate | async }}\n </div>\n }\n <!-- Widget (shown when feature is enabled and has widget) -->\n @if (feature.isEnabled && feature.widgetNode) {\n <div class=\"mt-3 ms-6 ax-sm\">\n <ng-container axp-widget-renderer [node]=\"feature.widgetNode\" [mode]=\"readOnly() ? 'view' : 'edit'\"\n (onValueChanged)=\"onFeatureValueChange(feature.fullName, $event.widget.getValue())\">\n </ng-container>\n </div>\n }\n </div>\n </div>\n\n\n </div>\n</ng-template>", styles: ["@layer properties;.features-editor{display:flex;height:100%;flex-direction:column}.features-editor .__modules .__tabs{height:100%}.features-editor .__features .__header .__title{font-size:1rem;font-weight:500;line-height:1rem}.features-editor .__features .__content .__feature-item{width:100%}.features-editor .__features .__content .__feature-item .__feature-widget{border-left-style:var(--tw-border-style);border-left-width:1px;--tw-border-style: dashed;border-style:dashed;border-color:rgba(var(--ax-sys-color-border-lighter-surface));padding-left:calc(var(--spacing, .25rem) * 4)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type:
521
- // Angular
522
- CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type:
523
- // ACoreX
524
- AXFormModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i2$1.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXTooltipModule }, { kind: "directive", type: i4.AXTooltipDirective, selector: "[axTooltip]", inputs: ["axTooltipDisabled", "axTooltip", "axTooltipContext", "axTooltipPlacement", "axTooltipOffsetX", "axTooltipOffsetY", "axTooltipOpenAfter", "axTooltipCloseAfter"] }, { kind: "ngmodule", type:
525
- // Widget Renderer
526
- AXPWidgetCoreModule }, { kind: "directive", type: i5.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
527
- }
528
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFeaturesEditorComponent, decorators: [{
529
- type: Component,
530
- args: [{ selector: 'axm-features-editor', imports: [
531
- // Angular
532
- CommonModule,
533
- FormsModule,
534
- // ACoreX
535
- AXFormModule,
536
- AXCheckBoxModule,
537
- AXLabelModule,
538
- AXTranslationModule,
539
- AXTooltipModule,
540
- // Widget Renderer
541
- AXPWidgetCoreModule,
542
- ], encapsulation: ViewEncapsulation.None, host: {
543
- class: 'flex',
544
- }, template: "<div class=\"px-3 py-6\">\n <div class=\"flex flex-col gap-3\">\n @for (module of modules(); track module.name) {\n <ng-container *ngTemplateOutlet=\"moduleTemplate; context: { $implicit: module, level: 0 }\">\n </ng-container>\n }\n </div>\n</div>\n\n<!-- Module Template -->\n<ng-template #moduleTemplate let-module let-level=\"level\">\n <div class=\"flex flex-col\">\n <!-- Module Row -->\n <div class=\"flex items-center gap-3 rounded hover:bg-surface-lowest\"\n [style.padding-left.px]=\"level * 32\">\n <!-- Spacer for alignment -->\n <span class=\"w-4\"></span>\n\n <!-- Module Checkbox -->\n <ax-check-box [ngModel]=\"isModuleSelected(module.name)\" [readonly]=\"readOnly() || isModuleDisabled(module.name)\"\n [class.opacity-50]=\"isModuleDependency(module.name) && !isModuleRequired(module.name)\"\n (onValueChanged)=\"onModuleToggle(module, $event)\" (click)=\"$event.stopPropagation()\">\n </ax-check-box>\n\n <!-- Module Icon -->\n <i [class]=\"getModuleIcon(module) + ' text-primary fa-fw'\"></i>\n\n <!-- Module Title -->\n <span class=\"flex-1 font-semibold\">{{ module.title | translate | async }}</span>\n\n <!-- Required Badge -->\n @if (isModuleRequired(module.name)) {\n <span class=\"text-xs text-primary font-medium\" [axTooltip]=\"'Required module'\">\n (Required)\n </span>\n }\n\n <!-- Dependency Badge -->\n @if (isModuleDependency(module.name) && !isModuleRequired(module.name)) {\n <span class=\"text-xs text-secondary font-medium\" [axTooltip]=\"getDependencyTooltip(module.name)\">\n (Dependency)\n </span>\n }\n </div>\n\n <!-- Features (shown when module is checked and has features) -->\n @if (isModuleSelected(module.name) && hasModuleFeatures(module)) {\n <div class=\"flex flex-col gap-3 py-6 px-3\">\n @for (feature of getModuleFeatures(module); track feature.fullName) {\n <ng-container\n *ngTemplateOutlet=\"featureTemplate; context: { $implicit: feature, module: module, level: level + 1 }\">\n </ng-container>\n }\n </div>\n }\n </div>\n</ng-template>\n\n<!-- Feature Template -->\n<ng-template #featureTemplate let-feature let-module=\"module\" let-level=\"level\">\n <div class=\"flex flex-col\">\n <!-- Feature Row -->\n <div class=\"flex items-start gap-3 rounded hover:bg-surface-lowest\"\n [style.padding-left.px]=\"level * 32\">\n <!-- Spacer for alignment -->\n <span class=\"w-4\"></span>\n\n <!-- Feature Checkbox -->\n <ax-check-box [ngModel]=\"feature.isEnabled\" [readonly]=\"readOnly()\"\n (onValueChanged)=\"onFeatureToggle(feature, $event)\" (click)=\"$event.stopPropagation()\"></ax-check-box>\n\n <!-- Feature Content (Icon, Title, Description) -->\n <div class=\"flex flex-col flex-1 gap-1.5\">\n <div class=\"flex items-center gap-2\">\n <!-- Feature Icon -->\n <i class=\"fa-light fa-toggle-on text-secondary\"></i>\n <!-- Feature Title -->\n <span class=\"font-semibold\">{{ feature.definition.title | translate | async }}</span>\n </div>\n\n <!-- Feature Description -->\n @if (feature.definition.description) {\n <div class=\"text-sm text-muted ms-6 leading-relaxed\">\n {{ feature.definition.description | translate | async }}\n </div>\n }\n <!-- Widget (shown when feature is enabled and has widget) -->\n @if (feature.isEnabled && feature.widgetNode) {\n <div class=\"mt-3 ms-6 ax-sm\">\n <ng-container axp-widget-renderer [node]=\"feature.widgetNode\" [mode]=\"readOnly() ? 'view' : 'edit'\"\n (onValueChanged)=\"onFeatureValueChange(feature.fullName, $event.widget.getValue())\">\n </ng-container>\n </div>\n }\n </div>\n </div>\n\n\n </div>\n</ng-template>", styles: ["@layer properties;.features-editor{display:flex;height:100%;flex-direction:column}.features-editor .__modules .__tabs{height:100%}.features-editor .__features .__header .__title{font-size:1rem;font-weight:500;line-height:1rem}.features-editor .__features .__content .__feature-item{width:100%}.features-editor .__features .__content .__feature-item .__feature-widget{border-left-style:var(--tw-border-style);border-left-width:1px;--tw-border-style: dashed;border-style:dashed;border-color:rgba(var(--ax-sys-color-border-lighter-surface));padding-left:calc(var(--spacing, .25rem) * 4)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
545
- }], propDecorators: { initialValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValue", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }] } });
546
-
547
- export { AXPFeaturesEditorComponent as A };
548
- //# sourceMappingURL=acorex-platform-module-application-management-client-features-editor.component-BiYXAqYJ.mjs.map