@acorex-platform/module-learning-management-client 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.
@@ -0,0 +1,1097 @@
1
+ import { AXPCommonMenuKeys, AXPCommonPermissionGroupKeys } from '@acorex-platform/module-common-client/contracts';
2
+ import { AXPEntityService, AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService } from '@acorex-platform/framework-client/layout/entity';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, Injectable, NgModule, DestroyRef, signal, input, output, computed, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
5
+ import { RootConfig, AXMLearningManagementMenuKeys, AXPLearningPermissionKeys } from '@acorex-platform/module-learning-management-client/contracts';
6
+ import { createEntityCommandOptions, AXPSearchCommandProvider, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER } from '@acorex-platform/framework-client/common';
7
+ import { AXP_WIDGETS_EDITOR_CATEGORY, AXPWidgetCoreModule, AXP_WIDGET_DEFINITION_PROVIDER, AXPValueWidgetComponent } from '@acorex-platform/framework-client/layout/widget-core';
8
+ import { AXP_MODULE_MANIFEST_PROVIDER } from '@acorex-platform/framework-client/core';
9
+ import { AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/auth';
10
+ import { AXPWidgetGroupEnum } from '@acorex-platform/framework-shared/widget-core';
11
+ import { AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_LABEL_PROPERTY, AXP_READONLY_PROPERTY, AXP_DISABLED_PROPERTY } from '@acorex-platform/framework-client/layout/widgets';
12
+ import { AXPWidgetsList } from '@acorex-platform/framework-shared/core';
13
+ import * as i3 from '@angular/common';
14
+ import { CommonModule } from '@angular/common';
15
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
16
+ import { AXPSpreadsheetComponent } from '@acorex-platform/framework-client/layout/components';
17
+ import * as i1 from '@acorex/components/button';
18
+ import { AXButtonModule } from '@acorex/components/button';
19
+ import * as i2 from '@acorex/components/decorators';
20
+ import { AXDecoratorModule } from '@acorex/components/decorators';
21
+ import * as i4 from '@acorex/core/translation';
22
+ import { AXTranslationService, resolveMultiLanguageString, AXTranslationModule } from '@acorex/core/translation';
23
+ import { get } from 'lodash';
24
+
25
+ //#region ---- Imports ----
26
+ //#endregion
27
+ //#region ---- Menu Provider ----
28
+ /**
29
+ * Learning Management Module Menu Provider.
30
+ * - Root "Learning": Skills, Courses, Trainings, Enrollments, Certificates, Licenses, Learning Paths (operational)
31
+ * - Configuration/Learning: Skill Levels, Course Types, Training Definitions/Types, Certificate Definitions/Types, License Types, Mandatory Training Rules (reference)
32
+ */
33
+ class AXMLearningManagementMenuProvider {
34
+ constructor() {
35
+ this.entityService = inject(AXPEntityService);
36
+ }
37
+ async provide(context) {
38
+ const module = RootConfig.module;
39
+ // Root "Learning" - single level, direct links with dividers
40
+ context.addItems([
41
+ {
42
+ name: AXMLearningManagementMenuKeys.Root,
43
+ priority: 8210,
44
+ text: '@learning-management:module.menus.root.title',
45
+ icon: module.icon,
46
+ policy: {
47
+ features: [module.name],
48
+ },
49
+ children: [
50
+ {
51
+ name: `${AXMLearningManagementMenuKeys.Root}:skills`,
52
+ text: RootConfig.entities.skill.titlePlural,
53
+ icon: RootConfig.entities.skill.icon,
54
+ path: this.entityService.createPath(module.name, RootConfig.entities.skill.name),
55
+ priority: 1,
56
+ },
57
+ {
58
+ name: `${AXMLearningManagementMenuKeys.Root}:courses`,
59
+ text: RootConfig.entities.course.titlePlural,
60
+ icon: RootConfig.entities.course.icon,
61
+ path: this.entityService.createPath(module.name, RootConfig.entities.course.name),
62
+ priority: 2,
63
+ },
64
+ {
65
+ name: `${AXMLearningManagementMenuKeys.Root}:trainings`,
66
+ text: RootConfig.entities.training.titlePlural,
67
+ icon: RootConfig.entities.training.icon,
68
+ path: this.entityService.createPath(module.name, RootConfig.entities.training.name),
69
+ priority: 3,
70
+ },
71
+ { name: `${AXMLearningManagementMenuKeys.Root}:divider1`, text: '', type: 'break', priority: 4 },
72
+ {
73
+ name: `${AXMLearningManagementMenuKeys.Root}:enrollments`,
74
+ text: RootConfig.entities.enrollment.titlePlural,
75
+ icon: RootConfig.entities.enrollment.icon,
76
+ path: this.entityService.createPath(module.name, RootConfig.entities.enrollment.name),
77
+ priority: 5,
78
+ },
79
+ {
80
+ name: `${AXMLearningManagementMenuKeys.Root}:attendance`,
81
+ text: RootConfig.entities.attendance.titlePlural,
82
+ icon: RootConfig.entities.attendance.icon,
83
+ path: this.entityService.createPath(module.name, RootConfig.entities.attendance.name),
84
+ priority: 6,
85
+ },
86
+ { name: `${AXMLearningManagementMenuKeys.Root}:divider2`, text: '', type: 'break', priority: 7 },
87
+ {
88
+ name: `${AXMLearningManagementMenuKeys.Root}:certificates`,
89
+ text: RootConfig.entities.certificate.titlePlural,
90
+ icon: RootConfig.entities.certificate.icon,
91
+ path: this.entityService.createPath(module.name, RootConfig.entities.certificate.name),
92
+ priority: 8,
93
+ },
94
+ {
95
+ name: `${AXMLearningManagementMenuKeys.Root}:licenses`,
96
+ text: RootConfig.entities.license.titlePlural,
97
+ icon: RootConfig.entities.license.icon,
98
+ path: this.entityService.createPath(module.name, RootConfig.entities.license.name),
99
+ priority: 9,
100
+ },
101
+ {
102
+ name: `${AXMLearningManagementMenuKeys.Root}:learning-paths`,
103
+ text: RootConfig.entities.learningPath.titlePlural,
104
+ icon: RootConfig.entities.learningPath.icon,
105
+ path: this.entityService.createPath(module.name, RootConfig.entities.learningPath.name),
106
+ priority: 10,
107
+ },
108
+ ],
109
+ },
110
+ ]);
111
+ // Configuration/Learning - reference data
112
+ context.find(AXPCommonMenuKeys.Configuration).addItems([
113
+ {
114
+ name: AXMLearningManagementMenuKeys.ConfigurationRoot,
115
+ priority: 8650,
116
+ text: '@learning-management:module.menus.configuration.title',
117
+ icon: module.icon,
118
+ policy: {
119
+ features: [module.name],
120
+ },
121
+ children: [
122
+ {
123
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:skill-levels`,
124
+ text: RootConfig.entities.skillLevel.titlePlural,
125
+ icon: RootConfig.entities.skillLevel.icon,
126
+ path: this.entityService.createPath(module.name, RootConfig.entities.skillLevel.name),
127
+ priority: 1,
128
+ },
129
+ {
130
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:course-types`,
131
+ text: RootConfig.entities.courseType.titlePlural,
132
+ icon: RootConfig.entities.courseType.icon,
133
+ path: this.entityService.createPath(module.name, RootConfig.entities.courseType.name),
134
+ priority: 2,
135
+ },
136
+ {
137
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:training-definitions`,
138
+ text: RootConfig.entities.trainingDefinition.titlePlural,
139
+ icon: RootConfig.entities.trainingDefinition.icon,
140
+ path: this.entityService.createPath(module.name, RootConfig.entities.trainingDefinition.name),
141
+ priority: 3,
142
+ },
143
+ {
144
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:training-types`,
145
+ text: RootConfig.entities.trainingType.titlePlural,
146
+ icon: RootConfig.entities.trainingType.icon,
147
+ path: this.entityService.createPath(module.name, RootConfig.entities.trainingType.name),
148
+ priority: 4,
149
+ },
150
+ {
151
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:certificate-definitions`,
152
+ text: RootConfig.entities.certificateDefinition.titlePlural,
153
+ icon: RootConfig.entities.certificateDefinition.icon,
154
+ path: this.entityService.createPath(module.name, RootConfig.entities.certificateDefinition.name),
155
+ priority: 5,
156
+ },
157
+ {
158
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:certificate-types`,
159
+ text: RootConfig.entities.certificateType.titlePlural,
160
+ icon: RootConfig.entities.certificateType.icon,
161
+ path: this.entityService.createPath(module.name, RootConfig.entities.certificateType.name),
162
+ priority: 6,
163
+ },
164
+ {
165
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:license-types`,
166
+ text: RootConfig.entities.licenseType.titlePlural,
167
+ icon: RootConfig.entities.licenseType.icon,
168
+ path: this.entityService.createPath(module.name, RootConfig.entities.licenseType.name),
169
+ priority: 7,
170
+ },
171
+ {
172
+ name: `${AXMLearningManagementMenuKeys.ConfigurationRoot}:mandatory-rules`,
173
+ text: RootConfig.entities.mandatoryTrainingRule.titlePlural,
174
+ icon: RootConfig.entities.mandatoryTrainingRule.icon,
175
+ path: this.entityService.createPath(module.name, RootConfig.entities.mandatoryTrainingRule.name),
176
+ priority: 8,
177
+ },
178
+ ],
179
+ },
180
+ ]);
181
+ }
182
+ }
183
+ //#endregion
184
+
185
+ //#endregion
186
+ //#region ---- Permission Definition Provider ----
187
+ /**
188
+ * Registers learning capabilities into the shared Learning group.
189
+ */
190
+ class AXMLearningManagementPermissionDefinitionProvider {
191
+ async define(context) {
192
+ const keys = AXPLearningPermissionKeys;
193
+ const groups = AXPCommonPermissionGroupKeys;
194
+ const P = '@common:learning.permissions';
195
+ const G = '@common:permission-groups';
196
+ context
197
+ .addGroup(groups.Learning.Root, `${G}.learning.title`, `${G}.learning.description`, { order: 20 })
198
+ .addPermission(keys.Access, `${P}.access.title`, `${P}.access.description`)
199
+ .endPermission()
200
+ .addPermission(keys.MaintainLearning, `${P}.maintain-learning.title`, `${P}.maintain-learning.description`)
201
+ .endPermission()
202
+ .addPermission(keys.Setup, `${P}.setup.title`, `${P}.setup.description`)
203
+ .endPermission()
204
+ .endGroup();
205
+ }
206
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementPermissionDefinitionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
207
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementPermissionDefinitionProvider }); }
208
+ }
209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementPermissionDefinitionProvider, decorators: [{
210
+ type: Injectable
211
+ }] });
212
+
213
+ //#region ---- Imports ----
214
+ //#endregion
215
+ //#region ---- Search Command Provider ----
216
+ function cmd(id, entityKey, e, title, desc) {
217
+ return {
218
+ id,
219
+ group: 'command',
220
+ title,
221
+ icon: e.icon,
222
+ description: desc,
223
+ command: {
224
+ name: 'Entity:Create',
225
+ options: createEntityCommandOptions(entityKey, { name: e.name, module: RootConfig.module.name, title: e.title }),
226
+ },
227
+ };
228
+ }
229
+ class AXMLearningManagementSearchCommandProvider extends AXPSearchCommandProvider {
230
+ constructor() {
231
+ super(...arguments);
232
+ this.commands = [
233
+ cmd('create-skill', `${RootConfig.module.name}.${RootConfig.entities.skill.name}`, RootConfig.entities.skill, '@learning-management:skills.search.create-skill.title', '@learning-management:skills.search.create-skill.description'),
234
+ cmd('create-course', `${RootConfig.module.name}.${RootConfig.entities.course.name}`, RootConfig.entities.course, '@learning-management:courses.search.create-course.title', '@learning-management:courses.search.create-course.description'),
235
+ cmd('create-training', `${RootConfig.module.name}.${RootConfig.entities.training.name}`, RootConfig.entities.training, '@learning-management:trainings.search.schedule-training.title', '@learning-management:trainings.search.schedule-training.description'),
236
+ cmd('create-training-definition', `${RootConfig.module.name}.${RootConfig.entities.trainingDefinition.name}`, RootConfig.entities.trainingDefinition, '@learning-management:trainings.search.create-training-definition.title', '@learning-management:trainings.search.create-training-definition.description'),
237
+ cmd('create-enrollment', `${RootConfig.module.name}.${RootConfig.entities.enrollment.name}`, RootConfig.entities.enrollment, '@learning-management:enrollments.search.create-enrollment.title', '@learning-management:enrollments.search.create-enrollment.description'),
238
+ cmd('create-learning-path', `${RootConfig.module.name}.${RootConfig.entities.learningPath.name}`, RootConfig.entities.learningPath, '@learning-management:learning-paths.search.create-learning-path.title', '@learning-management:learning-paths.search.create-learning-path.description'),
239
+ cmd('create-certificate', `${RootConfig.module.name}.${RootConfig.entities.certificate.name}`, RootConfig.entities.certificate, '@learning-management:certificates.search.issue-certificate.title', '@learning-management:certificates.search.issue-certificate.description'),
240
+ cmd('create-certificate-definition', `${RootConfig.module.name}.${RootConfig.entities.certificateDefinition.name}`, RootConfig.entities.certificateDefinition, '@learning-management:certificates.search.create-certificate-definition.title', '@learning-management:certificates.search.create-certificate-definition.description'),
241
+ cmd('create-attendance', `${RootConfig.module.name}.${RootConfig.entities.attendance.name}`, RootConfig.entities.attendance, '@learning-management:enrollments.search.create-attendance.title', '@learning-management:enrollments.search.create-attendance.description'),
242
+ cmd('create-skill-level', `${RootConfig.module.name}.${RootConfig.entities.skillLevel.name}`, RootConfig.entities.skillLevel, '@learning-management:skills.search.create-skill-level.title', '@learning-management:skills.search.create-skill-level.description'),
243
+ cmd('create-course-type', `${RootConfig.module.name}.${RootConfig.entities.courseType.name}`, RootConfig.entities.courseType, '@learning-management:courses.search.create-course-type.title', '@learning-management:courses.search.create-course-type.description'),
244
+ cmd('create-training-type', `${RootConfig.module.name}.${RootConfig.entities.trainingType.name}`, RootConfig.entities.trainingType, '@learning-management:trainings.search.create-training-type.title', '@learning-management:trainings.search.create-training-type.description'),
245
+ cmd('create-certificate-type', `${RootConfig.module.name}.${RootConfig.entities.certificateType.name}`, RootConfig.entities.certificateType, '@learning-management:certificates.search.create-certificate-type.title', '@learning-management:certificates.search.create-certificate-type.description'),
246
+ cmd('create-mandatory-training-rule', `${RootConfig.module.name}.${RootConfig.entities.mandatoryTrainingRule.name}`, RootConfig.entities.mandatoryTrainingRule, '@learning-management:compliance.search.create-mandatory-training-rule.title', '@learning-management:compliance.search.create-mandatory-training-rule.description'),
247
+ ];
248
+ }
249
+ }
250
+ //#endregion
251
+
252
+ //#region ---- Imports ----
253
+ //#endregion
254
+ //#region ---- Manifest Definition ----
255
+ /**
256
+ * Learning Management Module Manifest.
257
+ * Defines module metadata, features, and provider references.
258
+ */
259
+ const LearningManagementManifest = {
260
+ name: RootConfig.module.name,
261
+ version: '1.0.0',
262
+ title: RootConfig.module.title,
263
+ icon: RootConfig.module.icon,
264
+ i18n: RootConfig.config.i18n,
265
+ type: 'domain',
266
+ domain: 'assessment-learning',
267
+ // Module dependencies (optional)
268
+ };
269
+ //#endregion
270
+
271
+ const AXLSkillMatrixWidget = {
272
+ name: 'skill-matrix-editor',
273
+ title: 'Skill Matrix',
274
+ categories: AXP_WIDGETS_EDITOR_CATEGORY,
275
+ groups: [AXPWidgetGroupEnum.UtilityWidget],
276
+ description: 'Matrix widget for managing skill levels across different skills',
277
+ icon: 'fa-light fa-table',
278
+ type: 'editor',
279
+ options: {
280
+ needLabel: false,
281
+ },
282
+ properties: [
283
+ AXP_NAME_PROPERTY,
284
+ AXP_DATA_PATH_PROPERTY,
285
+ AXP_LABEL_PROPERTY,
286
+ AXP_READONLY_PROPERTY,
287
+ AXP_DISABLED_PROPERTY,
288
+ ],
289
+ components: {
290
+ view: {
291
+ component: () => Promise.resolve().then(function () { return skillMatrixWidgetView_component; }).then((c) => c.AXLSkillMatrixWidgetViewComponent),
292
+ },
293
+ edit: {
294
+ component: () => Promise.resolve().then(function () { return skillMatrixWidgetEdit_component; }).then((c) => c.AXLSkillMatrixWidgetEditComponent),
295
+ },
296
+ },
297
+ };
298
+
299
+ //#endregion
300
+ //#region ---- Learning Management Widgets Provider ----
301
+ class AXMLearningManagementWidgetsProvider {
302
+ getWidgets() {
303
+ return [AXLSkillMatrixWidget];
304
+ }
305
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementWidgetsProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
306
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementWidgetsProvider }); }
307
+ }
308
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementWidgetsProvider, decorators: [{
309
+ type: Injectable
310
+ }] });
311
+
312
+ //#region ---- Imports ----
313
+ //#endregion
314
+ //#region ---- Module ----
315
+ class AXMLearningManagementModule {
316
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
317
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementModule, imports: [AXPWidgetCoreModule] }); }
318
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementModule, providers: [
319
+ // Module Manifest Provider
320
+ {
321
+ provide: AXP_MODULE_MANIFEST_PROVIDER,
322
+ useValue: LearningManagementManifest,
323
+ multi: true,
324
+ },
325
+ // Provider references (now using tokens)
326
+ {
327
+ provide: AXP_PERMISSION_DEFINITION_PROVIDER,
328
+ useClass: AXMLearningManagementPermissionDefinitionProvider,
329
+ multi: true,
330
+ },
331
+ {
332
+ provide: AXP_MENU_PROVIDER,
333
+ useClass: AXMLearningManagementMenuProvider,
334
+ multi: true,
335
+ },
336
+ {
337
+ provide: AXP_SEARCH_PROVIDER,
338
+ useClass: AXMLearningManagementSearchCommandProvider,
339
+ multi: true,
340
+ },
341
+ {
342
+ provide: AXP_WIDGET_DEFINITION_PROVIDER,
343
+ useClass: AXMLearningManagementWidgetsProvider,
344
+ multi: true,
345
+ },
346
+ ], imports: [AXPWidgetCoreModule] }); }
347
+ }
348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementModule, decorators: [{
349
+ type: NgModule,
350
+ args: [{
351
+ imports: [
352
+ AXPWidgetCoreModule,
353
+ ],
354
+ providers: [
355
+ // Module Manifest Provider
356
+ {
357
+ provide: AXP_MODULE_MANIFEST_PROVIDER,
358
+ useValue: LearningManagementManifest,
359
+ multi: true,
360
+ },
361
+ // Provider references (now using tokens)
362
+ {
363
+ provide: AXP_PERMISSION_DEFINITION_PROVIDER,
364
+ useClass: AXMLearningManagementPermissionDefinitionProvider,
365
+ multi: true,
366
+ },
367
+ {
368
+ provide: AXP_MENU_PROVIDER,
369
+ useClass: AXMLearningManagementMenuProvider,
370
+ multi: true,
371
+ },
372
+ {
373
+ provide: AXP_SEARCH_PROVIDER,
374
+ useClass: AXMLearningManagementSearchCommandProvider,
375
+ multi: true,
376
+ },
377
+ {
378
+ provide: AXP_WIDGET_DEFINITION_PROVIDER,
379
+ useClass: AXMLearningManagementWidgetsProvider,
380
+ multi: true,
381
+ },
382
+ ],
383
+ }]
384
+ }] });
385
+
386
+ //#region ---- Imports ----
387
+ //#endregion
388
+ class AXMLearningManagementSkillMatrixComponent {
389
+ //#endregion
390
+ //#region ---- Lifecycle Methods ----
391
+ constructor() {
392
+ //#region ---- Services & Dependencies ----
393
+ this.entityService = inject(AXPEntityService);
394
+ this.skillLevelDataAccessor = this.entityService
395
+ .withEntity(RootConfig.module.name, RootConfig.entities.skillLevel.name)
396
+ .data();
397
+ this.skillDataAccessor = this.entityService
398
+ .withEntity(RootConfig.module.name, RootConfig.entities.skill.name)
399
+ .data();
400
+ this.skillCategoryDataAccessor = this.entityService
401
+ .withEntity(RootConfig.module.name, RootConfig.entities.skillCategory.name)
402
+ .data();
403
+ this.entityDataSelectorService = inject(AXPEntityDataSelectorService);
404
+ this.entityResolver = inject(AXPEntityDefinitionRegistryService);
405
+ this.translationService = inject(AXTranslationService);
406
+ this.destroyRef = inject(DestroyRef);
407
+ this.activeLocale = signal(this.translationService.getActiveLang(), /* @ts-ignore */
408
+ ...(ngDevMode ? [{ debugName: "activeLocale" }] : /* istanbul ignore next */ []));
409
+ //#endregion
410
+ //#region ---- Inputs ----
411
+ /**
412
+ * Array of job titles/positions to display as columns (e.g., Senior, Manager, Director)
413
+ */
414
+ this.titles = input([], /* @ts-ignore */
415
+ ...(ngDevMode ? [{ debugName: "titles" }] : /* istanbul ignore next */ []));
416
+ /**
417
+ * Initial matrix data: { [skillId]: { [title.id]: skillLevelId } }
418
+ */
419
+ this.value = input({}, /* @ts-ignore */
420
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
421
+ /**
422
+ * Whether the matrix is in readonly mode
423
+ */
424
+ this.readonly = input(false, /* @ts-ignore */
425
+ ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
426
+ /**
427
+ * Initial skill IDs (for syncing with parent entity)
428
+ */
429
+ this.skillIds = input([], /* @ts-ignore */
430
+ ...(ngDevMode ? [{ debugName: "skillIds" }] : /* istanbul ignore next */ []));
431
+ //#endregion
432
+ //#region ---- Outputs ----
433
+ /**
434
+ * Emitted when the matrix value changes
435
+ */
436
+ this.valueChange = output();
437
+ /**
438
+ * Emitted when a single cell value changes
439
+ */
440
+ this.cellChange = output();
441
+ /**
442
+ * Emitted when selected skills change (skill IDs array)
443
+ */
444
+ this.skillIdsChange = output();
445
+ //#endregion
446
+ //#region ---- Class Properties ----
447
+ /**
448
+ * Skill levels loaded from the service
449
+ */
450
+ this.skillLevels = signal([], /* @ts-ignore */
451
+ ...(ngDevMode ? [{ debugName: "skillLevels" }] : /* istanbul ignore next */ []));
452
+ /**
453
+ * Selected skills (internal state)
454
+ */
455
+ this.selectedSkills = signal([], /* @ts-ignore */
456
+ ...(ngDevMode ? [{ debugName: "selectedSkills" }] : /* istanbul ignore next */ []));
457
+ /**
458
+ * Skill entity definition
459
+ */
460
+ this.skillEntityDef = signal(null, /* @ts-ignore */
461
+ ...(ngDevMode ? [{ debugName: "skillEntityDef" }] : /* istanbul ignore next */ []));
462
+ /**
463
+ * Loading state
464
+ */
465
+ this.isLoading = signal(true, /* @ts-ignore */
466
+ ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
467
+ /**
468
+ * Loading state for skill entity
469
+ */
470
+ this.isLoadingSkillEntity = signal(false, /* @ts-ignore */
471
+ ...(ngDevMode ? [{ debugName: "isLoadingSkillEntity" }] : /* istanbul ignore next */ []));
472
+ //#endregion
473
+ //#region ---- Computed Properties ----
474
+ /**
475
+ * Vertical titles (skills) - rows of the matrix
476
+ */
477
+ this.verticalTitles = computed(() => {
478
+ const locale = this.activeLocale();
479
+ const skills = this.selectedSkills();
480
+ const result = (skills ?? []).map((skill) => ({
481
+ id: skill.id,
482
+ title: resolveMultiLanguageString(skill.title, locale),
483
+ description: skill.description != null ? resolveMultiLanguageString(skill.description, locale) : undefined,
484
+ }));
485
+ return result;
486
+ }, /* @ts-ignore */
487
+ ...(ngDevMode ? [{ debugName: "verticalTitles" }] : /* istanbul ignore next */ []));
488
+ /**
489
+ * Horizontal titles (job titles/positions) - columns of the matrix
490
+ */
491
+ this.horizontalTitles = computed(() => {
492
+ const titlesInput = this.titles();
493
+ const result = (titlesInput ?? []).map((title) => ({
494
+ id: title.id,
495
+ title: title.title,
496
+ description: title.description || undefined,
497
+ }));
498
+ return result;
499
+ }, /* @ts-ignore */
500
+ ...(ngDevMode ? [{ debugName: "horizontalTitles" }] : /* istanbul ignore next */ []));
501
+ /**
502
+ * Cell options (skill levels) - dropdown options for each cell, loaded from service
503
+ */
504
+ this.cellOptions = computed(() => {
505
+ const locale = this.activeLocale();
506
+ const levels = this.skillLevels();
507
+ return (levels ?? []).map((level) => ({
508
+ id: level.id,
509
+ title: resolveMultiLanguageString(level.title, locale),
510
+ description: level.description != null ? resolveMultiLanguageString(level.description, locale) : undefined,
511
+ }));
512
+ }, /* @ts-ignore */
513
+ ...(ngDevMode ? [{ debugName: "cellOptions" }] : /* istanbul ignore next */ []));
514
+ /**
515
+ * Spreadsheet columns - converted from horizontalTitles (job titles/positions)
516
+ */
517
+ this.spreadsheetColumns = computed(() => {
518
+ const horizontalTitles = this.horizontalTitles();
519
+ const cellOptions = this.cellOptions();
520
+ // Create SelectBox widget configuration for skill levels
521
+ const selectBoxWidget = {
522
+ type: AXPWidgetsList.Editors.SelectBox,
523
+ options: {
524
+ valueField: 'id',
525
+ textField: 'title',
526
+ dataSource: cellOptions.map(option => ({
527
+ id: option.id,
528
+ title: option.title,
529
+ description: option.description,
530
+ })),
531
+ },
532
+ };
533
+ // Convert horizontal titles to columns
534
+ return horizontalTitles.map((title) => ({
535
+ name: title.id,
536
+ title: title.title,
537
+ description: title.description,
538
+ path: title.id, // Path to access the value in row object
539
+ widget: selectBoxWidget,
540
+ }));
541
+ }, /* @ts-ignore */
542
+ ...(ngDevMode ? [{ debugName: "spreadsheetColumns" }] : /* istanbul ignore next */ []));
543
+ /**
544
+ * Spreadsheet rows - converted from matrix data and vertical titles
545
+ */
546
+ this.spreadsheetRows = computed(() => {
547
+ const verticalTitles = this.verticalTitles();
548
+ const horizontalTitles = this.horizontalTitles();
549
+ const matrixData = this.value();
550
+ // Convert matrix data to spreadsheet rows
551
+ return verticalTitles.map((skill) => {
552
+ const row = {
553
+ name: skill.id, // Required for fixed mode row identification
554
+ _skillTitle: skill.title, // For row header display
555
+ _skillDescription: skill.description, // For row header description
556
+ };
557
+ // Add cell values for each horizontal title (column)
558
+ horizontalTitles.forEach((title) => {
559
+ const cellValue = matrixData[skill.id]?.[title.id] ?? null;
560
+ row[title.id] = cellValue;
561
+ });
562
+ return row;
563
+ });
564
+ }, /* @ts-ignore */
565
+ ...(ngDevMode ? [{ debugName: "spreadsheetRows" }] : /* istanbul ignore next */ []));
566
+ this.translationService.langChanges$
567
+ .pipe(takeUntilDestroyed(this.destroyRef))
568
+ .subscribe((lang) => this.activeLocale.set(lang));
569
+ // Load skill levels and skill entity definition when component initializes
570
+ this.loadSkillLevels();
571
+ this.loadSkillEntityDef();
572
+ // Watch for skillIds input changes and sync selected skills
573
+ effect(() => {
574
+ const ids = this.skillIds();
575
+ if (ids && ids.length > 0 && this.skillEntityDef()) {
576
+ this.loadSkillsByIds(ids);
577
+ }
578
+ else if (!ids || ids.length === 0) {
579
+ // Try to extract skill IDs from matrix data keys
580
+ const matrixData = this.value();
581
+ const skillIdsFromMatrix = Object.keys(matrixData || {});
582
+ if (skillIdsFromMatrix.length > 0 && this.skillEntityDef()) {
583
+ this.loadSkillsByIds(skillIdsFromMatrix);
584
+ }
585
+ else {
586
+ this.selectedSkills.set([]);
587
+ }
588
+ }
589
+ });
590
+ // Watch for matrix value changes and extract skill IDs
591
+ effect(() => {
592
+ const matrixData = this.value();
593
+ const currentSkillIds = this.selectedSkills().map((s) => s.id);
594
+ const skillIdsFromMatrix = Object.keys(matrixData || {});
595
+ // If matrix has skills that aren't in selectedSkills, load them
596
+ const missingIds = skillIdsFromMatrix.filter((id) => !currentSkillIds.includes(id));
597
+ if (missingIds.length > 0 && this.skillEntityDef()) {
598
+ this.loadSkillsByIds(missingIds);
599
+ }
600
+ });
601
+ }
602
+ //#endregion
603
+ //#region ---- Data Loading Methods ----
604
+ /**
605
+ * Load skill levels from the service
606
+ */
607
+ async loadSkillLevels() {
608
+ try {
609
+ this.isLoading.set(true);
610
+ const query = {
611
+ skip: 0,
612
+ take: 1000,
613
+ sort: [{ field: 'levelNumber', dir: 'asc' }],
614
+ };
615
+ const result = await this.skillLevelDataAccessor.query(query);
616
+ this.skillLevels.set(result.items || []);
617
+ }
618
+ catch (error) {
619
+ console.error('Error loading skill levels:', error);
620
+ this.skillLevels.set([]);
621
+ }
622
+ finally {
623
+ this.isLoading.set(false);
624
+ }
625
+ }
626
+ /**
627
+ * Load skill entity definition
628
+ */
629
+ async loadSkillEntityDef() {
630
+ try {
631
+ this.isLoadingSkillEntity.set(true);
632
+ const entityDef = await this.entityResolver.resolve(RootConfig.module.name, RootConfig.entities.skill.name);
633
+ this.skillEntityDef.set(entityDef);
634
+ }
635
+ catch (error) {
636
+ console.error('Error loading skill entity definition:', error);
637
+ this.skillEntityDef.set(null);
638
+ }
639
+ finally {
640
+ this.isLoadingSkillEntity.set(false);
641
+ }
642
+ }
643
+ /**
644
+ * Load skills by IDs
645
+ */
646
+ async loadSkillsByIds(ids) {
647
+ try {
648
+ const skills = [];
649
+ for (const id of ids) {
650
+ try {
651
+ const skill = await this.skillDataAccessor.byKey(id);
652
+ if (skill) {
653
+ skills.push(skill);
654
+ }
655
+ }
656
+ catch (error) {
657
+ console.error(`Error loading skill ${id}:`, error);
658
+ }
659
+ }
660
+ this.selectedSkills.set(skills);
661
+ }
662
+ catch (error) {
663
+ console.error('Error loading skills by IDs:', error);
664
+ }
665
+ }
666
+ //#endregion
667
+ //#region ---- Data Transformation Methods ----
668
+ /**
669
+ * Convert spreadsheet rows back to matrix data format
670
+ */
671
+ convertSpreadsheetRowsToMatrixData(rows) {
672
+ const horizontalTitles = this.horizontalTitles();
673
+ const matrixData = {};
674
+ rows.forEach((row) => {
675
+ const skillId = row['name']; // Row identifier (skill ID)
676
+ if (!skillId) {
677
+ return;
678
+ }
679
+ matrixData[skillId] = {};
680
+ // Extract cell values for each column
681
+ horizontalTitles.forEach((title) => {
682
+ const cellValue = row[title.id] ?? null;
683
+ matrixData[skillId][title.id] = cellValue;
684
+ });
685
+ });
686
+ return matrixData;
687
+ }
688
+ //#endregion
689
+ //#region ---- Event Handlers ----
690
+ /**
691
+ * Handle spreadsheet change event - convert to matrix format
692
+ */
693
+ handleSpreadsheetChange(rows) {
694
+ const matrixData = this.convertSpreadsheetRowsToMatrixData(rows);
695
+ this.valueChange.emit(matrixData);
696
+ // Extract skill IDs from row names and emit
697
+ const skillIds = rows.map((row) => row['name']).filter((id) => id != null);
698
+ this.skillIdsChange.emit(skillIds);
699
+ }
700
+ /**
701
+ * Handle cell change event from spreadsheet
702
+ */
703
+ handleCellChange(event) {
704
+ this.cellChange.emit(event);
705
+ }
706
+ /**
707
+ * Open skill selector dialog with category filter
708
+ */
709
+ async handleSelectSkills() {
710
+ const entityDef = this.skillEntityDef();
711
+ if (!entityDef) {
712
+ console.error('Skill entity definition not loaded');
713
+ return;
714
+ }
715
+ try {
716
+ // Get currently selected skill IDs
717
+ const selectedItemIds = this.selectedSkills()
718
+ .map((skill) => skill.id)
719
+ .filter((id) => id != null);
720
+ // Create category tree data source
721
+ const categoryTreeDataSource = {
722
+ loadRootNodes: async () => {
723
+ const result = await this.skillCategoryDataAccessor.query({
724
+ skip: 0,
725
+ take: 1000,
726
+ filter: {
727
+ field: 'parentId',
728
+ operator: { type: 'isEmpty' },
729
+ value: true,
730
+ },
731
+ sort: [{ field: 'title', dir: 'asc' }],
732
+ });
733
+ return (result.items || []).map((item) => ({
734
+ id: item.id,
735
+ title: item.title || item.name,
736
+ description: item.description || '',
737
+ parentId: item.parentId,
738
+ childrenCount: item.childrenCount || 0,
739
+ }));
740
+ },
741
+ loadChildNodes: async (parentId) => {
742
+ const result = await this.skillCategoryDataAccessor.query({
743
+ skip: 0,
744
+ take: 1000,
745
+ filter: {
746
+ field: 'parentId',
747
+ operator: { type: 'equal' },
748
+ value: parentId,
749
+ },
750
+ sort: [{ field: 'title', dir: 'asc' }],
751
+ });
752
+ return (result.items || []).map((item) => ({
753
+ id: item.id,
754
+ title: item.title || item.name,
755
+ description: item.description || '',
756
+ parentId: item.parentId,
757
+ childrenCount: item.childrenCount || 0,
758
+ }));
759
+ },
760
+ searchNodes: async (searchValue) => {
761
+ const result = await this.skillCategoryDataAccessor.query({
762
+ skip: 0,
763
+ take: 1000,
764
+ filter: {
765
+ filters: [
766
+ {
767
+ field: 'title',
768
+ operator: { type: 'contains' },
769
+ value: searchValue,
770
+ },
771
+ {
772
+ field: 'name',
773
+ operator: { type: 'contains' },
774
+ value: searchValue,
775
+ },
776
+ ],
777
+ logic: 'or',
778
+ },
779
+ });
780
+ return (result.items || []).map((item) => ({
781
+ id: item.id,
782
+ title: item.title || item.name,
783
+ description: item.description || '',
784
+ parentId: item.parentId,
785
+ childrenCount: item.childrenCount || 0,
786
+ }));
787
+ },
788
+ };
789
+ const result = await this.entityDataSelectorService.open({
790
+ entity: entityDef,
791
+ title: 'Select Skills',
792
+ allowMultiple: true,
793
+ selectedItemIds: selectedItemIds.length > 0 ? selectedItemIds : undefined,
794
+ columns: ['title', 'description'],
795
+ showCategoryFilter: false,
796
+ categoryFilter: {
797
+ title: 'Categories',
798
+ dataSource: categoryTreeDataSource,
799
+ filterField: 'categoryIds',
800
+ filterOperator: 'contains',
801
+ width: '350px',
802
+ },
803
+ });
804
+ if (result && result.items && result.items.length > 0) {
805
+ // Update selected skills
806
+ this.selectedSkills.set(result.items);
807
+ // Emit skill IDs change
808
+ const skillIds = result.items.map((item) => item.id).filter((id) => id != null);
809
+ this.skillIdsChange.emit(skillIds);
810
+ }
811
+ }
812
+ catch (error) {
813
+ console.error('Error opening skill selector:', error);
814
+ }
815
+ }
816
+ /**
817
+ * Remove a skill from selection
818
+ */
819
+ handleRemoveSkill(skillId) {
820
+ const currentSkills = this.selectedSkills();
821
+ const updatedSkills = currentSkills.filter((skill) => skill.id !== skillId);
822
+ this.selectedSkills.set(updatedSkills);
823
+ // Remove skill data from matrix value
824
+ const currentMatrixData = this.value();
825
+ const updatedMatrixData = { ...currentMatrixData };
826
+ delete updatedMatrixData[skillId];
827
+ // Emit updated matrix data
828
+ this.valueChange.emit(updatedMatrixData);
829
+ // Emit skill IDs change
830
+ const skillIds = updatedSkills.map((skill) => skill.id).filter((id) => id != null);
831
+ this.skillIdsChange.emit(skillIds);
832
+ }
833
+ /**
834
+ * Handle row change event from spreadsheet (add/remove)
835
+ */
836
+ handleRowChange(event) {
837
+ if (event.type === 'remove') {
838
+ // Remove skill from selection
839
+ this.handleRemoveSkill(event.rowId);
840
+ }
841
+ // Note: 'add' type shouldn't happen in fixed mode, but if it does, we can handle it here
842
+ }
843
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementSkillMatrixComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
844
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMLearningManagementSkillMatrixComponent, isStandalone: true, selector: "axm-skill-matrix", inputs: { titles: { classPropertyName: "titles", publicName: "titles", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, skillIds: { classPropertyName: "skillIds", publicName: "skillIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", cellChange: "cellChange", skillIdsChange: "skillIdsChange" }, host: { classAttribute: "axm-skill-matrix" }, ngImport: i0, template: "<div class=\"__container\">\n <div class=\"__matrix-section\">\n <div class=\"__matrix-header ax-sm\">\n @if (!readonly()) {\n <ax-button color=\"primary\"\n [text]=\"'@learning-management:skills.components.skill-matrix.actions.choose-skills.title' | translate | async\"\n (onClick)=\"handleSelectSkills()\" [disabled]=\"isLoadingSkillEntity()\">\n <ax-icon icon=\"far fa-plus\"></ax-icon>\n </ax-button>\n }\n </div>\n @if (isLoading()) {\n <div class=\"__loading\">\n <span>{{ '@learning-management:skills.components.skill-matrix.messages.loading-skill-levels' | translate | async\n }}</span>\n </div>\n } @else {\n <axp-spreadsheet [title]=\"'Skill / Level'\" [columns]=\"spreadsheetColumns()\" [rowsInput]=\"spreadsheetRows()\"\n [rowMode]=\"'fixed'\" [readonly]=\"readonly()\" [allowRemoveRows]=\"true\" [rowTitlePath]=\"'_skillTitle'\"\n [rowDescriptionPath]=\"'_skillDescription'\" (cellChange)=\"handleCellChange($event)\"\n (spreadsheetChange)=\"handleSpreadsheetChange($event)\" (rowChange)=\"handleRowChange($event)\"></axp-spreadsheet>\n }\n </div>\n</div>", styles: [".skill-matrix{display:block;height:100%;width:100%}.skill-matrix .__container,.skill-matrix .__matrix-section{display:flex;flex-direction:column}.skill-matrix .__matrix-header{margin-bottom:calc(var(--spacing, .25rem) * 3);display:flex;justify-content:flex-end}.skill-matrix .__loading{display:flex;align-items:center;justify-content:center;padding:calc(var(--spacing, .25rem) * 8);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-600, oklch(43.9% 0 none))}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPSpreadsheetComponent, selector: "axp-spreadsheet", inputs: ["title", "columns", "rowMode", "rowsInput", "rowsModel", "readonly", "emptyCellPlaceholder", "rowTitlePath", "rowDescriptionPath", "allowAddRows", "allowRemoveRows"], outputs: ["rowsModelChange", "cellChange", "rowChange", "spreadsheetChange"] }, { 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: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
845
+ }
846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMLearningManagementSkillMatrixComponent, decorators: [{
847
+ type: Component,
848
+ args: [{ selector: 'axm-skill-matrix', standalone: true, imports: [
849
+ CommonModule,
850
+ AXPSpreadsheetComponent,
851
+ AXButtonModule,
852
+ AXDecoratorModule,
853
+ AXTranslationModule,
854
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
855
+ class: 'axm-skill-matrix',
856
+ }, template: "<div class=\"__container\">\n <div class=\"__matrix-section\">\n <div class=\"__matrix-header ax-sm\">\n @if (!readonly()) {\n <ax-button color=\"primary\"\n [text]=\"'@learning-management:skills.components.skill-matrix.actions.choose-skills.title' | translate | async\"\n (onClick)=\"handleSelectSkills()\" [disabled]=\"isLoadingSkillEntity()\">\n <ax-icon icon=\"far fa-plus\"></ax-icon>\n </ax-button>\n }\n </div>\n @if (isLoading()) {\n <div class=\"__loading\">\n <span>{{ '@learning-management:skills.components.skill-matrix.messages.loading-skill-levels' | translate | async\n }}</span>\n </div>\n } @else {\n <axp-spreadsheet [title]=\"'Skill / Level'\" [columns]=\"spreadsheetColumns()\" [rowsInput]=\"spreadsheetRows()\"\n [rowMode]=\"'fixed'\" [readonly]=\"readonly()\" [allowRemoveRows]=\"true\" [rowTitlePath]=\"'_skillTitle'\"\n [rowDescriptionPath]=\"'_skillDescription'\" (cellChange)=\"handleCellChange($event)\"\n (spreadsheetChange)=\"handleSpreadsheetChange($event)\" (rowChange)=\"handleRowChange($event)\"></axp-spreadsheet>\n }\n </div>\n</div>", styles: [".skill-matrix{display:block;height:100%;width:100%}.skill-matrix .__container,.skill-matrix .__matrix-section{display:flex;flex-direction:column}.skill-matrix .__matrix-header{margin-bottom:calc(var(--spacing, .25rem) * 3);display:flex;justify-content:flex-end}.skill-matrix .__loading{display:flex;align-items:center;justify-content:center;padding:calc(var(--spacing, .25rem) * 8);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-600, oklch(43.9% 0 none))}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
857
+ }], ctorParameters: () => [], propDecorators: { titles: [{ type: i0.Input, args: [{ isSignal: true, alias: "titles", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], skillIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "skillIds", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], skillIdsChange: [{ type: i0.Output, args: ["skillIdsChange"] }] } });
858
+
859
+ //#region ---- Imports ----
860
+ //#endregion
861
+ //#region ---- Component Definition ----
862
+ class AXLSkillMatrixWidgetEditComponent extends AXPValueWidgetComponent {
863
+ constructor() {
864
+ super(...arguments);
865
+ //#endregion
866
+ //#region ---- Computed Properties ----
867
+ /**
868
+ * Titles from context - reactively reads from context data signal
869
+ * This ensures the titles update immediately when requiredLevels changes in context
870
+ */
871
+ this.titles = computed(() => {
872
+ // Read directly from context data signal for reactive updates
873
+ const contextData = this.contextService.data();
874
+ const requiredLevelsFromContext = get(contextData, 'jobLevels');
875
+ if (Array.isArray(requiredLevelsFromContext) && requiredLevelsFromContext.length > 0) {
876
+ // Ensure each item has the required structure
877
+ return requiredLevelsFromContext.map((item) => {
878
+ if (typeof item === 'string') {
879
+ // If item is just a string (ID), convert to proper format
880
+ return { id: item, title: item };
881
+ }
882
+ // If item is an object, ensure it has id and title
883
+ return {
884
+ id: item.id || item.value || String(item),
885
+ title: item.title || item.name || String(item),
886
+ description: item.description,
887
+ };
888
+ });
889
+ }
890
+ // Fallback to options (for initial load or when context is not yet available)
891
+ const options = this.options();
892
+ const rawTitles = options?.['titles'];
893
+ // If titles is not set, return empty array
894
+ if (!rawTitles) {
895
+ return [];
896
+ }
897
+ // If it's already an array, return it (evaluated expression result)
898
+ if (Array.isArray(rawTitles)) {
899
+ // Ensure each item has the required structure
900
+ return rawTitles.map((item) => {
901
+ if (typeof item === 'string') {
902
+ // If item is just a string (ID), convert to proper format
903
+ return { id: item, title: item };
904
+ }
905
+ // If item is an object, ensure it has id and title
906
+ return {
907
+ id: item.id || item.value || String(item),
908
+ title: item.title || item.name || String(item),
909
+ description: item.description,
910
+ };
911
+ });
912
+ }
913
+ // If it's still a string (unevaluated expression), return empty array
914
+ // The expression will be evaluated by the widget renderer and options will update
915
+ if (typeof rawTitles === 'string') {
916
+ return [];
917
+ }
918
+ return [];
919
+ }, /* @ts-ignore */
920
+ ...(ngDevMode ? [{ debugName: "titles" }] : /* istanbul ignore next */ []));
921
+ /**
922
+ * Readonly mode from options - properly tracks options signal changes
923
+ */
924
+ this.readonly = computed(() => {
925
+ const options = this.options();
926
+ const result = options?.['readonly'] ?? false;
927
+ return result;
928
+ }, /* @ts-ignore */
929
+ ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
930
+ /**
931
+ * Current matrix value - tracks getValue signal changes
932
+ */
933
+ this.matrixValue = computed(() => {
934
+ const result = this.getValue() || {};
935
+ const keysCount = Object.keys(result).length;
936
+ return result;
937
+ }, /* @ts-ignore */
938
+ ...(ngDevMode ? [{ debugName: "matrixValue" }] : /* istanbul ignore next */ []));
939
+ /**
940
+ * Skill IDs extracted from matrix data keys or from options
941
+ */
942
+ this.skillIds = computed(() => {
943
+ const options = this.options();
944
+ const skillIdsFromOptions = options?.['skillIds'] ?? [];
945
+ // If skillIds from options is an array, use it
946
+ if (Array.isArray(skillIdsFromOptions) && skillIdsFromOptions.length > 0) {
947
+ return skillIdsFromOptions;
948
+ }
949
+ // Otherwise, extract from matrix data keys
950
+ const matrixData = this.matrixValue();
951
+ return Object.keys(matrixData || {});
952
+ }, /* @ts-ignore */
953
+ ...(ngDevMode ? [{ debugName: "skillIds" }] : /* istanbul ignore next */ []));
954
+ }
955
+ //#endregion
956
+ //#region ---- Event Handlers ----
957
+ /**
958
+ * Handle value change from skill-matrix component
959
+ */
960
+ handleValueChange(data) {
961
+ const dataKeysCount = Object.keys(data || {}).length;
962
+ const currentKeysCount = Object.keys(this.getValue() || {}).length;
963
+ if (data) {
964
+ this.setValue(data);
965
+ const afterKeysCount = Object.keys(this.getValue() || {}).length;
966
+ }
967
+ else {
968
+ }
969
+ }
970
+ /**
971
+ * Handle skill IDs change from skill-matrix component
972
+ * Skill IDs are stored as keys in the matrix data, so this is mainly for tracking
973
+ */
974
+ handleSkillIdsChange(skillIds) {
975
+ // Skill IDs are already reflected in the matrix data keys
976
+ // This handler is here for potential future use or side effects
977
+ console.log('Skill IDs changed:', skillIds);
978
+ }
979
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLSkillMatrixWidgetEditComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
980
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: AXLSkillMatrixWidgetEditComponent, isStandalone: true, selector: "axm-skill-matrix-widget-edit", host: { classAttribute: "block w-full" }, usesInheritance: true, ngImport: i0, template: `
981
+ <axm-skill-matrix
982
+ [titles]="titles()"
983
+ [value]="matrixValue()"
984
+ [skillIds]="skillIds()"
985
+ [readonly]="readonly()"
986
+ (valueChange)="handleValueChange($any($event))"
987
+ (skillIdsChange)="handleSkillIdsChange($any($event))"
988
+ ></axm-skill-matrix>
989
+ `, isInline: true, dependencies: [{ kind: "component", type: AXMLearningManagementSkillMatrixComponent, selector: "axm-skill-matrix", inputs: ["titles", "value", "readonly", "skillIds"], outputs: ["valueChange", "cellChange", "skillIdsChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
990
+ }
991
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLSkillMatrixWidgetEditComponent, decorators: [{
992
+ type: Component,
993
+ args: [{
994
+ selector: 'axm-skill-matrix-widget-edit',
995
+ standalone: true,
996
+ imports: [
997
+ AXMLearningManagementSkillMatrixComponent
998
+ ],
999
+ template: `
1000
+ <axm-skill-matrix
1001
+ [titles]="titles()"
1002
+ [value]="matrixValue()"
1003
+ [skillIds]="skillIds()"
1004
+ [readonly]="readonly()"
1005
+ (valueChange)="handleValueChange($any($event))"
1006
+ (skillIdsChange)="handleSkillIdsChange($any($event))"
1007
+ ></axm-skill-matrix>
1008
+ `,
1009
+ host: {
1010
+ class: 'block w-full',
1011
+ },
1012
+ encapsulation: ViewEncapsulation.None,
1013
+ changeDetection: ChangeDetectionStrategy.OnPush,
1014
+ }]
1015
+ }] });
1016
+
1017
+ var skillMatrixWidgetEdit_component = /*#__PURE__*/Object.freeze({
1018
+ __proto__: null,
1019
+ AXLSkillMatrixWidgetEditComponent: AXLSkillMatrixWidgetEditComponent
1020
+ });
1021
+
1022
+ //#region ---- Imports ----
1023
+ //#endregion
1024
+ //#region ---- Component Definition ----
1025
+ class AXLSkillMatrixWidgetViewComponent extends AXPValueWidgetComponent {
1026
+ constructor() {
1027
+ super(...arguments);
1028
+ //#endregion
1029
+ //#region ---- Computed Properties ----
1030
+ /**
1031
+ * Skill IDs from options
1032
+ */
1033
+ this.skills = computed(() => {
1034
+ return this.options()['skills'] || [];
1035
+ }, /* @ts-ignore */
1036
+ ...(ngDevMode ? [{ debugName: "skills" }] : /* istanbul ignore next */ []));
1037
+ /**
1038
+ * Current matrix value
1039
+ */
1040
+ this.matrixValue = computed(() => {
1041
+ return this.getValue() || {};
1042
+ }, /* @ts-ignore */
1043
+ ...(ngDevMode ? [{ debugName: "matrixValue" }] : /* istanbul ignore next */ []));
1044
+ }
1045
+ //#endregion
1046
+ //#region ---- Event Handlers ----
1047
+ /**
1048
+ * Handle value change from skill-matrix component
1049
+ */
1050
+ handleValueChange(data) {
1051
+ if (data) {
1052
+ this.setValue(data);
1053
+ }
1054
+ }
1055
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLSkillMatrixWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1056
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: AXLSkillMatrixWidgetViewComponent, isStandalone: true, selector: "axm-skill-matrix-widget-view", host: { classAttribute: "block w-full" }, usesInheritance: true, ngImport: i0, template: `
1057
+ <axm-skill-matrix
1058
+ [value]="matrixValue()"
1059
+ [readonly]="true"
1060
+ (valueChange)="handleValueChange($any($event))"
1061
+ ></axm-skill-matrix>
1062
+ `, isInline: true, dependencies: [{ kind: "component", type: AXMLearningManagementSkillMatrixComponent, selector: "axm-skill-matrix", inputs: ["titles", "value", "readonly", "skillIds"], outputs: ["valueChange", "cellChange", "skillIdsChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1063
+ }
1064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXLSkillMatrixWidgetViewComponent, decorators: [{
1065
+ type: Component,
1066
+ args: [{
1067
+ selector: 'axm-skill-matrix-widget-view',
1068
+ standalone: true,
1069
+ imports: [
1070
+ AXMLearningManagementSkillMatrixComponent
1071
+ ],
1072
+ template: `
1073
+ <axm-skill-matrix
1074
+ [value]="matrixValue()"
1075
+ [readonly]="true"
1076
+ (valueChange)="handleValueChange($any($event))"
1077
+ ></axm-skill-matrix>
1078
+ `,
1079
+ host: {
1080
+ class: 'block w-full',
1081
+ },
1082
+ encapsulation: ViewEncapsulation.None,
1083
+ changeDetection: ChangeDetectionStrategy.OnPush,
1084
+ }]
1085
+ }] });
1086
+
1087
+ var skillMatrixWidgetView_component = /*#__PURE__*/Object.freeze({
1088
+ __proto__: null,
1089
+ AXLSkillMatrixWidgetViewComponent: AXLSkillMatrixWidgetViewComponent
1090
+ });
1091
+
1092
+ /**
1093
+ * Generated bundle index. Do not edit.
1094
+ */
1095
+
1096
+ export { AXLSkillMatrixWidgetEditComponent, AXLSkillMatrixWidgetViewComponent, AXMLearningManagementMenuProvider, AXMLearningManagementModule, AXMLearningManagementPermissionDefinitionProvider, AXMLearningManagementSearchCommandProvider, AXMLearningManagementSkillMatrixComponent };
1097
+ //# sourceMappingURL=acorex-platform-module-learning-management-client.mjs.map