@acorex-platform/module-organization-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.
Files changed (53) hide show
  1. package/fesm2022/acorex-platform-module-organization-management-client-acorex-platform-module-organization-management-client-Dn8Ss1nL.mjs +433 -0
  2. package/fesm2022/acorex-platform-module-organization-management-client-acorex-platform-module-organization-management-client-Dn8Ss1nL.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-module-organization-management-client-add-business-unit-to-business-unit.command-CA2uZQyC.mjs +161 -0
  4. package/fesm2022/acorex-platform-module-organization-management-client-add-business-unit-to-business-unit.command-CA2uZQyC.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-module-organization-management-client-add-position-to-business-unit.command-F7jD3jKs.mjs +137 -0
  6. package/fesm2022/acorex-platform-module-organization-management-client-add-position-to-business-unit.command-F7jD3jKs.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-module-organization-management-client-add-team-to-business-unit.command-BLQFjhS5.mjs +127 -0
  8. package/fesm2022/acorex-platform-module-organization-management-client-add-team-to-business-unit.command-BLQFjhS5.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-module-organization-management-client-contracts.mjs +468 -0
  10. package/fesm2022/acorex-platform-module-organization-management-client-contracts.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-organization-management-client-feature-definition.provider-BQKtvXOM.mjs +19 -0
  12. package/fesm2022/acorex-platform-module-organization-management-client-feature-definition.provider-BQKtvXOM.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-module-organization-management-client-generate-org-chart.command-DJnFJKuo.mjs +91 -0
  14. package/fesm2022/acorex-platform-module-organization-management-client-generate-org-chart.command-DJnFJKuo.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-matrix-page.utils-DD3jLujN.mjs +61 -0
  16. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-matrix-page.utils-DD3jLujN.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-pages-component.provider-BNhXJfjr.mjs +28 -0
  18. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-pages-component.provider-BNhXJfjr.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-responsibilities-page.component-BlUzsSy3.mjs +237 -0
  20. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-responsibilities-page.component-BlUzsSy3.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-skills-page.component--pyAaXB4.mjs +233 -0
  22. package/fesm2022/acorex-platform-module-organization-management-client-job-definition-skills-page.component--pyAaXB4.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-module-organization-management-client-menu.provider-BgRoEC48.mjs +175 -0
  24. package/fesm2022/acorex-platform-module-organization-management-client-menu.provider-BgRoEC48.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-default-node-contribution.provider-BQ0ihb43.mjs +229 -0
  26. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-default-node-contribution.provider-BQ0ihb43.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-employee-flyout-contribution.provider-Bz8nVm04.mjs +179 -0
  28. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-employee-flyout-contribution.provider-Bz8nVm04.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-position-employee-node-contribution.provider-BTicXn9n.mjs +168 -0
  30. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-position-employee-node-contribution.provider-BTicXn9n.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-ux-node-contribution.provider-C5TItnOp.mjs +338 -0
  32. package/fesm2022/acorex-platform-module-organization-management-client-org-chart-ux-node-contribution.provider-C5TItnOp.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-module-organization-management-client-org-chart.page-g_3oPPH0.mjs +3744 -0
  34. package/fesm2022/acorex-platform-module-organization-management-client-org-chart.page-g_3oPPH0.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-module-organization-management-client-permission-definition.provider-CiCdTBGo.mjs +43 -0
  36. package/fesm2022/acorex-platform-module-organization-management-client-permission-definition.provider-CiCdTBGo.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-module-organization-management-client-remove-position-from-business-unit.command-BFQVTpfy.mjs +91 -0
  38. package/fesm2022/acorex-platform-module-organization-management-client-remove-position-from-business-unit.command-BFQVTpfy.mjs.map +1 -0
  39. package/fesm2022/acorex-platform-module-organization-management-client-replace-position-assignee.command-CSgERqLG.mjs +64 -0
  40. package/fesm2022/acorex-platform-module-organization-management-client-replace-position-assignee.command-CSgERqLG.mjs.map +1 -0
  41. package/fesm2022/acorex-platform-module-organization-management-client-responsibilities-matrix-widget-edit.component-DHmUxlnu.mjs +143 -0
  42. package/fesm2022/acorex-platform-module-organization-management-client-responsibilities-matrix-widget-edit.component-DHmUxlnu.mjs.map +1 -0
  43. package/fesm2022/acorex-platform-module-organization-management-client-responsibilities-matrix-widget-view.component-BkLZhXhM.mjs +65 -0
  44. package/fesm2022/acorex-platform-module-organization-management-client-responsibilities-matrix-widget-view.component-BkLZhXhM.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-module-organization-management-client-responsibilities-matrix.component-DqO6xE2p.mjs +400 -0
  46. package/fesm2022/acorex-platform-module-organization-management-client-responsibilities-matrix.component-DqO6xE2p.mjs.map +1 -0
  47. package/fesm2022/acorex-platform-module-organization-management-client-settings.provider-Dnrkq9Ku.mjs +432 -0
  48. package/fesm2022/acorex-platform-module-organization-management-client-settings.provider-Dnrkq9Ku.mjs.map +1 -0
  49. package/fesm2022/acorex-platform-module-organization-management-client.mjs +2 -0
  50. package/fesm2022/acorex-platform-module-organization-management-client.mjs.map +1 -0
  51. package/package.json +28 -0
  52. package/types/acorex-platform-module-organization-management-client-contracts.d.ts +501 -0
  53. package/types/acorex-platform-module-organization-management-client.d.ts +273 -0
@@ -0,0 +1,229 @@
1
+ import { AXTranslationService, createMultiLanguageString, resolveMultiLanguageString } from '@acorex/core/translation';
2
+ import { AXPSessionService } from '@acorex-platform/framework-client/auth';
3
+ import { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';
4
+ import { AXPCommandService } from '@acorex-platform/framework-client/runtime';
5
+ import * as i0 from '@angular/core';
6
+ import { inject, LOCALE_ID, Injectable } from '@angular/core';
7
+ import { AXPPeopleOrganizationPermissionKeys, AXMOrganizationManagementCommandKeys, RootConfig } from '@acorex-platform/module-organization-management-client/contracts';
8
+
9
+ //#region ---- Imports ----
10
+ //#endregion
11
+ //#region ---- Module Constants ----
12
+ const orgChartNodeActionKey = (suffix) => `@organization-management:organization-chart.node-actions.${suffix}`;
13
+ //#endregion
14
+ class AXMOrgChartDefaultNodeContributionProvider {
15
+ constructor() {
16
+ //#region ---- Services & Dependencies ----
17
+ this.commandService = inject(AXPCommandService);
18
+ this.sessionService = inject(AXPSessionService);
19
+ this.entityService = inject(AXPEntityService);
20
+ this.localeId = inject(LOCALE_ID);
21
+ this.translationService = inject(AXTranslationService);
22
+ }
23
+ //#endregion
24
+ //#region ---- Menu Actions ----
25
+ async getMenuActions(context) {
26
+ if (context.nodeKind !== 'company-root' && context.nodeKind !== 'business-unit') {
27
+ return [];
28
+ }
29
+ const businessUnitId = this.resolveBusinessUnitId(context);
30
+ const parentId = context.nodeKind === 'business-unit' ? businessUnitId : undefined;
31
+ const typeAllowsDirectPositions = context.nodeKind === 'business-unit' && businessUnitId
32
+ ? await this.resolveTypeAllowsDirectPositions(context, businessUnitId)
33
+ : false;
34
+ /** When true, a separator goes after the last “Add BU by type” row before the Add position row. */
35
+ const hasPositionRowAfterBuTypes = context.nodeKind === 'business-unit' && Boolean(businessUnitId) && typeAllowsDirectPositions;
36
+ const canMaintainOrganization = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainOrganization);
37
+ const canViewOrganization = this.authorize(AXPPeopleOrganizationPermissionKeys.ViewOrganization);
38
+ const canCreateBusinessUnit = canMaintainOrganization;
39
+ const canUpdateBusinessUnit = canMaintainOrganization;
40
+ const canDeleteBusinessUnit = canMaintainOrganization;
41
+ const canViewPosition = canViewOrganization || canMaintainOrganization;
42
+ const canCreateTeam = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainTeams);
43
+ const buTypeRows = await this.loadBusinessUnitTypes();
44
+ const addNewBuKey = orgChartNodeActionKey('add-new-bu-with-type');
45
+ const addBuActions = await Promise.all(buTypeRows.map(async (row, index) => ({
46
+ id: `organization-management.add-bu-type.${row.id}`,
47
+ title: await this.menuTitleDualLocale(addNewBuKey, { type: row.title }),
48
+ nestedInAddFlyout: true,
49
+ icon: 'fa-light fa-sitemap',
50
+ order: 10 + index,
51
+ disabled: !canCreateBusinessUnit,
52
+ break: hasPositionRowAfterBuTypes && index === buTypeRows.length - 1 && buTypeRows.length > 0 ? 'after' : undefined,
53
+ execute: async () => {
54
+ const result = await this.commandService.execute(AXMOrganizationManagementCommandKeys.OrganizationChart.AddBusinessUnitToBusinessUnit, { parentBusinessUnitId: parentId, typeId: row.id });
55
+ if (result?.success) {
56
+ await context.refreshChart();
57
+ }
58
+ },
59
+ })));
60
+ const addPositionToBuAction = context.nodeKind === 'business-unit' && businessUnitId && typeAllowsDirectPositions
61
+ ? {
62
+ id: 'organization-management.add-position-to-business-unit',
63
+ title: orgChartNodeActionKey('add-new-position'),
64
+ nestedInAddFlyout: true,
65
+ icon: 'fa-light fa-briefcase',
66
+ order: 10 + buTypeRows.length,
67
+ disabled: !canUpdateBusinessUnit || !canViewPosition,
68
+ execute: async () => {
69
+ const result = await this.commandService.execute(AXMOrganizationManagementCommandKeys.OrganizationChart.AddPositionToBusinessUnit, { businessUnitId });
70
+ if (result?.success) {
71
+ await context.refreshChart();
72
+ }
73
+ },
74
+ }
75
+ : null;
76
+ const addNewTeamToBuAction = context.nodeKind === 'business-unit' && businessUnitId
77
+ ? {
78
+ id: 'organization-management.org-chart.add-new-team',
79
+ title: orgChartNodeActionKey('add-new-team'),
80
+ nestedInAddFlyout: true,
81
+ icon: 'fa-light fa-people-group',
82
+ order: 10 + buTypeRows.length + (addPositionToBuAction ? 1 : 0),
83
+ disabled: !canCreateTeam,
84
+ execute: async () => {
85
+ const result = await this.commandService.execute(AXMOrganizationManagementCommandKeys.OrganizationChart.AddTeamToBusinessUnit, { businessUnitId });
86
+ if (result?.success) {
87
+ await context.refreshChart();
88
+ }
89
+ },
90
+ }
91
+ : null;
92
+ const removeBuActions = context.nodeKind === 'business-unit'
93
+ ? [
94
+ {
95
+ id: 'organization-management.remove-bu',
96
+ title: orgChartNodeActionKey('remove'),
97
+ icon: 'fa-light fa-trash',
98
+ color: 'danger',
99
+ order: 120,
100
+ break: 'before',
101
+ disabled: !canDeleteBusinessUnit || !businessUnitId,
102
+ execute: async () => {
103
+ await this.commandService.execute('Entity:Remove', {
104
+ entity: RootConfig.entities.businessUnit.source,
105
+ data: { id: businessUnitId },
106
+ options: { process: { showResult: true } },
107
+ });
108
+ await context.refreshChart();
109
+ },
110
+ },
111
+ ]
112
+ : [];
113
+ return [
114
+ ...addBuActions,
115
+ ...(addPositionToBuAction ? [addPositionToBuAction] : []),
116
+ ...(addNewTeamToBuAction ? [addNewTeamToBuAction] : []),
117
+ ...removeBuActions,
118
+ ];
119
+ }
120
+ //#endregion
121
+ //#region ---- Authorization ----
122
+ authorize(permission) {
123
+ return this.sessionService.authorize(permission);
124
+ }
125
+ //#endregion
126
+ //#region ---- Menu Labels ----
127
+ /**
128
+ * Resolves copy for menu rows: nested `translate` bindings do not pass interpolation params into the pipe;
129
+ * use per-locale strings via {@link createMultiLanguageString}.
130
+ *
131
+ * TODO: Remove this dual-locale pre-resolution once we can pass interpolation params through
132
+ * {@link AXPMultiLanguageString} and/or the menu `translate` pipe (see `@acorex/components/menu` item template).
133
+ */
134
+ async menuTitleDualLocale(key, params) {
135
+ const [enUs, faIr] = await Promise.all([
136
+ this.translationService.translateAsync(key, { lang: 'en-US', params }),
137
+ this.translationService.translateAsync(key, { lang: 'fa-IR', params }),
138
+ ]);
139
+ return createMultiLanguageString(enUs, faIr);
140
+ }
141
+ //#endregion
142
+ //#region ---- Business Unit Types ----
143
+ /**
144
+ * Resolves whether the BU's type allows direct positions (metadata from chart, nested type, or type lookup).
145
+ */
146
+ async resolveTypeAllowsDirectPositions(context, businessUnitId) {
147
+ const fromMeta = context.node.metadata?.['typeAllowsDirectPositions'];
148
+ if (typeof fromMeta === 'boolean') {
149
+ return fromMeta;
150
+ }
151
+ try {
152
+ const bu = await this.entityService
153
+ .withEntity(RootConfig.module.name, RootConfig.entities.businessUnit.name)
154
+ .data()
155
+ .byKey(businessUnitId);
156
+ const row = bu;
157
+ const nested = row?.type?.allowsDirectPositions;
158
+ if (typeof nested === 'boolean') {
159
+ return nested;
160
+ }
161
+ const typeId = row?.typeId?.trim();
162
+ if (typeId) {
163
+ const ty = await this.entityService
164
+ .withEntity(RootConfig.module.name, RootConfig.entities.businessUnitType.name)
165
+ .data()
166
+ .byKey(typeId);
167
+ return ty?.allowsDirectPositions !== false;
168
+ }
169
+ }
170
+ catch {
171
+ // fall through
172
+ }
173
+ return true;
174
+ }
175
+ async loadBusinessUnitTypes() {
176
+ try {
177
+ const result = await this.entityService
178
+ .withEntity(RootConfig.module.name, RootConfig.entities.businessUnitType.name)
179
+ .data()
180
+ .query({
181
+ skip: 0,
182
+ take: 500,
183
+ sort: [{ field: 'title', dir: 'asc' }],
184
+ });
185
+ const items = (result.items ?? []);
186
+ return items
187
+ .map((row) => {
188
+ const id = String(row.id ?? '');
189
+ const title = this.resolveBusinessUnitTypeLabel(row);
190
+ return { id, title: title || id };
191
+ })
192
+ .filter((row) => row.id.length > 0);
193
+ }
194
+ catch {
195
+ return [];
196
+ }
197
+ }
198
+ /**
199
+ * API rows use {@link AXPMultiLanguageString} for `title`; treating it as a string breaks `.trim()` and drops all types.
200
+ */
201
+ resolveBusinessUnitTypeLabel(row) {
202
+ const raw = row.title;
203
+ if (raw == null) {
204
+ return '';
205
+ }
206
+ if (typeof raw === 'string') {
207
+ return raw.trim();
208
+ }
209
+ return resolveMultiLanguageString(raw, this.localeId).trim();
210
+ }
211
+ //#endregion
212
+ //#region ---- Node Metadata ----
213
+ resolveBusinessUnitId(context) {
214
+ if (context.nodeKind === 'business-unit') {
215
+ return (context.node.entity?.id ??
216
+ context.node.metadata?.['businessUnitId'] ??
217
+ context.node.metadata?.['unitId']);
218
+ }
219
+ return context.node.metadata?.['businessUnitId'];
220
+ }
221
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartDefaultNodeContributionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
222
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartDefaultNodeContributionProvider }); }
223
+ }
224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartDefaultNodeContributionProvider, decorators: [{
225
+ type: Injectable
226
+ }] });
227
+
228
+ export { AXMOrgChartDefaultNodeContributionProvider };
229
+ //# sourceMappingURL=acorex-platform-module-organization-management-client-org-chart-default-node-contribution.provider-BQ0ihb43.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-module-organization-management-client-org-chart-default-node-contribution.provider-BQ0ihb43.mjs","sources":["../../../../libs/modules/organization-management/client/src/lib/features/organization-chart/contributions/org-chart-default-node-contribution.provider.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXTranslationService, createMultiLanguageString, resolveMultiLanguageString } from '@acorex/core/translation';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\nimport type { AXPMultiLanguageString } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { inject, Injectable, LOCALE_ID } from '@angular/core';\nimport {\n AXMOrganizationManagementCommandKeys,\n AXPPeopleOrganizationPermissionKeys\n} from '@acorex-platform/module-organization-management-client/contracts';\nimport { RootConfig } from '@acorex-platform/module-organization-management-client/contracts';\n\nimport {\n AXMOrgChartNodeContributionContext,\n AXMOrgChartNodeContributionProvider,\n AXMOrgChartNodeMenuAction,\n} from '../tokens/org-chart-node-contribution.token';\n\n//#endregion\n\n//#region ---- Module Constants ----\n\nconst orgChartNodeActionKey = (suffix: string): string =>\n `@organization-management:organization-chart.node-actions.${suffix}`;\n\n//#endregion\n\n@Injectable()\nexport class AXMOrgChartDefaultNodeContributionProvider implements AXMOrgChartNodeContributionProvider {\n //#region ---- Services & Dependencies ----\n\n private readonly commandService = inject(AXPCommandService);\n private readonly sessionService = inject(AXPSessionService);\n private readonly entityService = inject(AXPEntityService);\n private readonly localeId = inject(LOCALE_ID);\n private readonly translationService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ---- Menu Actions ----\n\n async getMenuActions(context: AXMOrgChartNodeContributionContext): Promise<AXMOrgChartNodeMenuAction[]> {\n if (context.nodeKind !== 'company-root' && context.nodeKind !== 'business-unit') {\n return [];\n }\n\n const businessUnitId = this.resolveBusinessUnitId(context);\n const parentId = context.nodeKind === 'business-unit' ? businessUnitId : undefined;\n\n const typeAllowsDirectPositions =\n context.nodeKind === 'business-unit' && businessUnitId\n ? await this.resolveTypeAllowsDirectPositions(context, businessUnitId)\n : false;\n\n /** When true, a separator goes after the last “Add BU by type” row before the Add position row. */\n const hasPositionRowAfterBuTypes =\n context.nodeKind === 'business-unit' && Boolean(businessUnitId) && typeAllowsDirectPositions;\n\n const canMaintainOrganization = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainOrganization);\n const canViewOrganization = this.authorize(AXPPeopleOrganizationPermissionKeys.ViewOrganization);\n const canCreateBusinessUnit = canMaintainOrganization;\n const canUpdateBusinessUnit = canMaintainOrganization;\n const canDeleteBusinessUnit = canMaintainOrganization;\n const canViewPosition = canViewOrganization || canMaintainOrganization;\n const canCreateTeam = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainTeams);\n\n const buTypeRows = await this.loadBusinessUnitTypes();\n const addNewBuKey = orgChartNodeActionKey('add-new-bu-with-type');\n const addBuActions: AXMOrgChartNodeMenuAction[] = await Promise.all(\n buTypeRows.map(async (row, index) => ({\n id: `organization-management.add-bu-type.${row.id}`,\n title: await this.menuTitleDualLocale(addNewBuKey, { type: row.title }),\n nestedInAddFlyout: true,\n icon: 'fa-light fa-sitemap',\n order: 10 + index,\n disabled: !canCreateBusinessUnit,\n break: hasPositionRowAfterBuTypes && index === buTypeRows.length - 1 && buTypeRows.length > 0 ? 'after' : undefined,\n execute: async () => {\n const result = await this.commandService.execute(\n AXMOrganizationManagementCommandKeys.OrganizationChart.AddBusinessUnitToBusinessUnit,\n { parentBusinessUnitId: parentId, typeId: row.id },\n );\n if (result?.success) {\n await context.refreshChart();\n }\n },\n })),\n );\n\n const addPositionToBuAction: AXMOrgChartNodeMenuAction | null =\n context.nodeKind === 'business-unit' && businessUnitId && typeAllowsDirectPositions\n ? {\n id: 'organization-management.add-position-to-business-unit',\n title: orgChartNodeActionKey('add-new-position'),\n nestedInAddFlyout: true,\n icon: 'fa-light fa-briefcase',\n order: 10 + buTypeRows.length,\n disabled: !canUpdateBusinessUnit || !canViewPosition,\n execute: async () => {\n const result = await this.commandService.execute(\n AXMOrganizationManagementCommandKeys.OrganizationChart.AddPositionToBusinessUnit,\n { businessUnitId },\n );\n if (result?.success) {\n await context.refreshChart();\n }\n },\n }\n : null;\n\n const addNewTeamToBuAction: AXMOrgChartNodeMenuAction | null =\n context.nodeKind === 'business-unit' && businessUnitId\n ? {\n id: 'organization-management.org-chart.add-new-team',\n title: orgChartNodeActionKey('add-new-team'),\n nestedInAddFlyout: true,\n icon: 'fa-light fa-people-group',\n order: 10 + buTypeRows.length + (addPositionToBuAction ? 1 : 0),\n disabled: !canCreateTeam,\n execute: async () => {\n const result = await this.commandService.execute(\n AXMOrganizationManagementCommandKeys.OrganizationChart.AddTeamToBusinessUnit,\n { businessUnitId },\n );\n if (result?.success) {\n await context.refreshChart();\n }\n },\n }\n : null;\n\n const removeBuActions: AXMOrgChartNodeMenuAction[] =\n context.nodeKind === 'business-unit'\n ? [\n {\n id: 'organization-management.remove-bu',\n title: orgChartNodeActionKey('remove'),\n icon: 'fa-light fa-trash',\n color: 'danger',\n order: 120,\n break: 'before',\n disabled: !canDeleteBusinessUnit || !businessUnitId,\n execute: async () => {\n await this.commandService.execute('Entity:Remove', {\n entity: RootConfig.entities.businessUnit.source,\n data: { id: businessUnitId },\n options: { process: { showResult: true } },\n \n });\n await context.refreshChart();\n },\n },\n ]\n : [];\n\n return [\n ...addBuActions,\n ...(addPositionToBuAction ? [addPositionToBuAction] : []),\n ...(addNewTeamToBuAction ? [addNewTeamToBuAction] : []),\n ...removeBuActions,\n ];\n }\n\n //#endregion\n\n //#region ---- Authorization ----\n\n private authorize(permission: string): boolean {\n return this.sessionService.authorize(permission);\n }\n\n //#endregion\n\n //#region ---- Menu Labels ----\n\n /**\n * Resolves copy for menu rows: nested `translate` bindings do not pass interpolation params into the pipe;\n * use per-locale strings via {@link createMultiLanguageString}.\n *\n * TODO: Remove this dual-locale pre-resolution once we can pass interpolation params through\n * {@link AXPMultiLanguageString} and/or the menu `translate` pipe (see `@acorex/components/menu` item template).\n */\n private async menuTitleDualLocale(\n key: string,\n params: Record<string, string | number>,\n ): Promise<ReturnType<typeof createMultiLanguageString>> {\n const [enUs, faIr] = await Promise.all([\n this.translationService.translateAsync(key, { lang: 'en-US', params }),\n this.translationService.translateAsync(key, { lang: 'fa-IR', params }),\n ]);\n return createMultiLanguageString(enUs, faIr);\n }\n\n //#endregion\n\n //#region ---- Business Unit Types ----\n\n /**\n * Resolves whether the BU's type allows direct positions (metadata from chart, nested type, or type lookup).\n */\n private async resolveTypeAllowsDirectPositions(\n context: AXMOrgChartNodeContributionContext,\n businessUnitId: string,\n ): Promise<boolean> {\n const fromMeta = context.node.metadata?.['typeAllowsDirectPositions'];\n if (typeof fromMeta === 'boolean') {\n return fromMeta;\n }\n try {\n const bu = await this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.businessUnit.name)\n .data()\n .byKey(businessUnitId);\n const row = bu as { type?: { allowsDirectPositions?: boolean }; typeId?: string } | null;\n const nested = row?.type?.allowsDirectPositions;\n if (typeof nested === 'boolean') {\n return nested;\n }\n const typeId = row?.typeId?.trim();\n if (typeId) {\n const ty = await this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.businessUnitType.name)\n .data()\n .byKey(typeId);\n return (ty as { allowsDirectPositions?: boolean } | null)?.allowsDirectPositions !== false;\n }\n } catch {\n // fall through\n }\n return true;\n }\n\n private async loadBusinessUnitTypes(): Promise<Array<{ id: string; title: string }>> {\n try {\n const result = await this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.businessUnitType.name)\n .data()\n .query({\n skip: 0,\n take: 500,\n sort: [{ field: 'title', dir: 'asc' }],\n });\n const items = (result.items ?? []) as Array<{ id: string; title?: unknown }>;\n return items\n .map((row) => {\n const id = String(row.id ?? '');\n const title = this.resolveBusinessUnitTypeLabel(row);\n return { id, title: title || id };\n })\n .filter((row) => row.id.length > 0);\n } catch {\n return [];\n }\n }\n\n /**\n * API rows use {@link AXPMultiLanguageString} for `title`; treating it as a string breaks `.trim()` and drops all types.\n */\n private resolveBusinessUnitTypeLabel(row: { title?: unknown }): string {\n const raw = row.title;\n if (raw == null) {\n return '';\n }\n if (typeof raw === 'string') {\n return raw.trim();\n }\n return resolveMultiLanguageString(raw as AXPMultiLanguageString, this.localeId).trim();\n }\n\n //#endregion\n\n //#region ---- Node Metadata ----\n\n private resolveBusinessUnitId(context: AXMOrgChartNodeContributionContext): string | undefined {\n if (context.nodeKind === 'business-unit') {\n return (\n context.node.entity?.id ??\n (context.node.metadata?.['businessUnitId'] as string | undefined) ??\n (context.node.metadata?.['unitId'] as string | undefined)\n );\n }\n return context.node.metadata?.['businessUnitId'] as string | undefined;\n }\n\n //#endregion\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ import { AXDialogService } from '@acorex/components/dialog';
2
+ import { AXTranslationService } from '@acorex/core/translation';
3
+ import { AXPSessionService } from '@acorex-platform/framework-client/auth';
4
+ import { AXPEntityDefinitionRegistryService, AXPEntityDataSelectorService } from '@acorex-platform/framework-client/layout/entity';
5
+ import { AXPCommandService } from '@acorex-platform/framework-client/runtime';
6
+ import * as i0 from '@angular/core';
7
+ import { inject, Injectable } from '@angular/core';
8
+ import { RootConfig, AXPPeopleOrganizationPermissionKeys } from '@acorex-platform/module-organization-management-client/contracts';
9
+ import { e as axmResolveOrgChartFlyoutEmployeeId, f as AXM_ORG_CHART_EMPLOYEE_SUBMENU_ICON, g as AXM_ORG_CHART_EMPLOYEE_SUBMENU_TITLE_I18N_KEY, d as AXM_ORG_CHART_EMPLOYEE_SUBMENU_GROUP_ID } from './acorex-platform-module-organization-management-client-acorex-platform-module-organization-management-client-Dn8Ss1nL.mjs';
10
+
11
+ //#region ---- Imports ----
12
+ //#endregion
13
+ //#region ---- Constants ----
14
+ const actionKey = (suffix) => `@organization-management:organization-chart.node-actions.${suffix}`;
15
+ const HCM_EMPLOYEE_MODULE = 'HumanCapitalManagement';
16
+ const HCM_EMPLOYEE_NAME = 'Employee';
17
+ const HCM_EMPLOYEE_SOURCE = `${HCM_EMPLOYEE_MODULE}.${HCM_EMPLOYEE_NAME}`;
18
+ //#endregion
19
+ /**
20
+ * **Employee** context-submenu: open employee record (`Entity:OpenDetails`), HR placeholders, schedule, add-to-team — plus chat/email from extensions.
21
+ * Shown for {@link AXMOrgChartNodeKind} `employee` and for company / business unit / filled position when an
22
+ * assigned person id is available; hidden when head or top role is vacant.
23
+ */
24
+ class AXMOrgChartEmployeeFlyoutContributionProvider {
25
+ constructor() {
26
+ //#region ---- Services & Dependencies ----
27
+ this.commandService = inject(AXPCommandService);
28
+ this.sessionService = inject(AXPSessionService);
29
+ this.dialogService = inject(AXDialogService);
30
+ this.translationService = inject(AXTranslationService);
31
+ this.entityRegistry = inject(AXPEntityDefinitionRegistryService);
32
+ this.entityDataSelector = inject(AXPEntityDataSelectorService);
33
+ this.teamMemberEntityInfo = {
34
+ module: RootConfig.module.name,
35
+ name: RootConfig.entities.teamMember.name,
36
+ title: RootConfig.entities.teamMember.title,
37
+ };
38
+ }
39
+ //#endregion
40
+ //#region ---- AXMOrgChartNodeContributionProvider ----
41
+ async getMenuActions(context) {
42
+ const employeeId = axmResolveOrgChartFlyoutEmployeeId(context);
43
+ if (!employeeId) {
44
+ return [];
45
+ }
46
+ return this.buildFlyoutActions(context, employeeId);
47
+ }
48
+ //#endregion
49
+ //#region ---- Flyout actions ----
50
+ buildFlyoutActions(context, employeeId) {
51
+ void context;
52
+ const canViewEmployee = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainEmployees);
53
+ const canTeam = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainTeams);
54
+ return [
55
+ this.withEmployeeSubmenu({
56
+ id: 'organization-management.org-chart.open-employee-details',
57
+ title: actionKey('open'),
58
+ icon: 'fa-light fa-arrow-up-right-from-square',
59
+ order: 35,
60
+ disabled: !canViewEmployee,
61
+ execute: async () => {
62
+ await this.commandService.execute('Entity:OpenDetails', {
63
+ entity: HCM_EMPLOYEE_SOURCE,
64
+ data: { id: employeeId },
65
+ });
66
+ },
67
+ }),
68
+ this.withEmployeeSubmenu({
69
+ id: 'organization-management.org-chart.hr-transfer',
70
+ title: actionKey('hr-workflow-transfer'),
71
+ icon: 'fa-light fa-right-left',
72
+ order: 60,
73
+ submenuSectionBreak: true,
74
+ execute: async () => {
75
+ await this.showPlaceholder(actionKey('placeholders.hr-workflow.title'), actionKey('placeholders.hr-workflow.transfer'));
76
+ },
77
+ }),
78
+ this.withEmployeeSubmenu({
79
+ id: 'organization-management.org-chart.hr-promotion',
80
+ title: actionKey('hr-workflow-promotion'),
81
+ icon: 'fa-light fa-arrow-trend-up',
82
+ order: 61,
83
+ execute: async () => {
84
+ await this.showPlaceholder(actionKey('placeholders.hr-workflow.title'), actionKey('placeholders.hr-workflow.promotion'));
85
+ },
86
+ }),
87
+ this.withEmployeeSubmenu({
88
+ id: 'organization-management.org-chart.hr-offboarding',
89
+ title: actionKey('hr-workflow-offboarding'),
90
+ icon: 'fa-light fa-door-open',
91
+ order: 62,
92
+ execute: async () => {
93
+ await this.showPlaceholder(actionKey('placeholders.hr-workflow.title'), actionKey('placeholders.hr-workflow.offboarding'));
94
+ },
95
+ }),
96
+ this.withEmployeeSubmenu({
97
+ id: 'organization-management.org-chart.schedule-meeting',
98
+ title: actionKey('schedule-meeting'),
99
+ icon: 'fa-light fa-calendar-plus',
100
+ order: 70,
101
+ submenuSectionBreak: true,
102
+ execute: async () => {
103
+ await this.showPlaceholder(actionKey('placeholders.schedule-meeting.title'), actionKey('placeholders.schedule-meeting.message'));
104
+ },
105
+ }),
106
+ this.withEmployeeSubmenu({
107
+ id: 'organization-management.org-chart.add-to-team',
108
+ title: actionKey('add-to-team'),
109
+ icon: 'fa-light fa-user-plus',
110
+ order: 75,
111
+ /** Trailing group break: separator after the Employee row on the root menu (inner last-row break is normalized away). */
112
+ break: 'after',
113
+ disabled: !canTeam,
114
+ execute: async (ctx) => {
115
+ await this.openTeamSelectorThenCreateTeamMember(ctx, employeeId);
116
+ },
117
+ }),
118
+ ];
119
+ }
120
+ /**
121
+ * Picks a team via {@link AXPEntityDataSelectorService}, then opens **Create Team Member** with both `teamId` and
122
+ * `employeeId` set.
123
+ */
124
+ async openTeamSelectorThenCreateTeamMember(ctx, employeeId) {
125
+ const teamEntity = await this.entityRegistry.resolve(RootConfig.module.name, RootConfig.entities.team.name);
126
+ if (!teamEntity) {
127
+ return;
128
+ }
129
+ const title = await this.translationService.translateAsync(actionKey('add-to-team-select-team'));
130
+ const pick = await this.entityDataSelector.open({
131
+ entity: teamEntity,
132
+ title,
133
+ allowMultiple: false,
134
+ });
135
+ const teamId = pick?.items?.[0]?.id;
136
+ if (teamId == null || String(teamId).trim().length === 0) {
137
+ return;
138
+ }
139
+ const result = await this.commandService.execute('Entity:Create', {
140
+ entity: RootConfig.entities.teamMember.source,
141
+ entityInfo: this.teamMemberEntityInfo,
142
+ data: { employeeId, teamId: String(teamId).trim() },
143
+ options: {
144
+ process: {
145
+ redirect: false,
146
+ },
147
+ },
148
+ });
149
+ if (result?.success) {
150
+ await ctx.refreshChart();
151
+ }
152
+ }
153
+ withEmployeeSubmenu(action) {
154
+ return {
155
+ ...action,
156
+ submenuGroupId: AXM_ORG_CHART_EMPLOYEE_SUBMENU_GROUP_ID,
157
+ submenuGroupTitle: AXM_ORG_CHART_EMPLOYEE_SUBMENU_TITLE_I18N_KEY,
158
+ submenuGroupIcon: AXM_ORG_CHART_EMPLOYEE_SUBMENU_ICON,
159
+ };
160
+ }
161
+ //#endregion
162
+ //#region ---- Resolvers ----
163
+ authorize(permission) {
164
+ return this.sessionService.authorize(permission);
165
+ }
166
+ async showPlaceholder(titleKey, messageKey) {
167
+ const title = await this.translationService.translateAsync(titleKey);
168
+ const message = await this.translationService.translateAsync(messageKey);
169
+ await this.dialogService.alert(title, message, 'primary');
170
+ }
171
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartEmployeeFlyoutContributionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
172
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartEmployeeFlyoutContributionProvider }); }
173
+ }
174
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartEmployeeFlyoutContributionProvider, decorators: [{
175
+ type: Injectable
176
+ }] });
177
+
178
+ export { AXMOrgChartEmployeeFlyoutContributionProvider };
179
+ //# sourceMappingURL=acorex-platform-module-organization-management-client-org-chart-employee-flyout-contribution.provider-Bz8nVm04.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-module-organization-management-client-org-chart-employee-flyout-contribution.provider-Bz8nVm04.mjs","sources":["../../../../libs/modules/organization-management/client/src/lib/features/organization-chart/contributions/org-chart-employee-flyout-contribution.provider.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXDialogService } from '@acorex/components/dialog';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\nimport { AXPEntityDataSelectorService, AXPEntityDefinitionRegistryService } from '@acorex-platform/framework-client/layout/entity';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { inject, Injectable } from '@angular/core';\nimport {\n RootConfig,\n AXPPeopleOrganizationPermissionKeys\n} from '@acorex-platform/module-organization-management-client/contracts';\n\nimport {\n AXM_ORG_CHART_EMPLOYEE_SUBMENU_GROUP_ID,\n AXM_ORG_CHART_EMPLOYEE_SUBMENU_ICON,\n AXM_ORG_CHART_EMPLOYEE_SUBMENU_TITLE_I18N_KEY,\n} from '../constants/org-chart-employee-submenu.const';\nimport {\n AXMOrgChartNodeContributionContext,\n AXMOrgChartNodeContributionProvider,\n AXMOrgChartNodeMenuAction,\n} from '../tokens/org-chart-node-contribution.token';\nimport { axmResolveOrgChartFlyoutEmployeeId } from '../utils/org-chart-resolve-flyout-employee-id.util';\n\n//#endregion\n\n//#region ---- Constants ----\n\nconst actionKey = (suffix: string): string =>\n `@organization-management:organization-chart.node-actions.${suffix}`;\n\nconst HCM_EMPLOYEE_MODULE = 'HumanCapitalManagement';\nconst HCM_EMPLOYEE_NAME = 'Employee';\nconst HCM_EMPLOYEE_SOURCE = `${HCM_EMPLOYEE_MODULE}.${HCM_EMPLOYEE_NAME}`;\n\n//#endregion\n\n/**\n * **Employee** context-submenu: open employee record (`Entity:OpenDetails`), HR placeholders, schedule, add-to-team — plus chat/email from extensions.\n * Shown for {@link AXMOrgChartNodeKind} `employee` and for company / business unit / filled position when an\n * assigned person id is available; hidden when head or top role is vacant.\n */\n@Injectable()\nexport class AXMOrgChartEmployeeFlyoutContributionProvider implements AXMOrgChartNodeContributionProvider {\n //#region ---- Services & Dependencies ----\n\n private readonly commandService = inject(AXPCommandService);\n private readonly sessionService = inject(AXPSessionService);\n private readonly dialogService = inject(AXDialogService);\n private readonly translationService = inject(AXTranslationService);\n private readonly entityRegistry = inject(AXPEntityDefinitionRegistryService);\n private readonly entityDataSelector = inject(AXPEntityDataSelectorService);\n\n private readonly teamMemberEntityInfo = {\n module: RootConfig.module.name,\n name: RootConfig.entities.teamMember.name,\n title: RootConfig.entities.teamMember.title,\n };\n\n //#endregion\n\n //#region ---- AXMOrgChartNodeContributionProvider ----\n\n async getMenuActions(context: AXMOrgChartNodeContributionContext): Promise<AXMOrgChartNodeMenuAction[]> {\n const employeeId = axmResolveOrgChartFlyoutEmployeeId(context);\n if (!employeeId) {\n return [];\n }\n return this.buildFlyoutActions(context, employeeId);\n }\n\n //#endregion\n\n //#region ---- Flyout actions ----\n\n private buildFlyoutActions(\n context: AXMOrgChartNodeContributionContext,\n employeeId: string,\n ): AXMOrgChartNodeMenuAction[] {\n void context;\n const canViewEmployee = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainEmployees);\n const canTeam = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainTeams);\n\n return [\n this.withEmployeeSubmenu({\n id: 'organization-management.org-chart.open-employee-details',\n title: actionKey('open'),\n icon: 'fa-light fa-arrow-up-right-from-square',\n order: 35,\n disabled: !canViewEmployee,\n execute: async () => {\n await this.commandService.execute('Entity:OpenDetails', {\n entity: HCM_EMPLOYEE_SOURCE,\n data: { id: employeeId },\n });\n },\n }),\n this.withEmployeeSubmenu({\n id: 'organization-management.org-chart.hr-transfer',\n title: actionKey('hr-workflow-transfer'),\n icon: 'fa-light fa-right-left',\n order: 60,\n submenuSectionBreak: true,\n execute: async () => {\n await this.showPlaceholder(\n actionKey('placeholders.hr-workflow.title'),\n actionKey('placeholders.hr-workflow.transfer'),\n );\n },\n }),\n this.withEmployeeSubmenu({\n id: 'organization-management.org-chart.hr-promotion',\n title: actionKey('hr-workflow-promotion'),\n icon: 'fa-light fa-arrow-trend-up',\n order: 61,\n execute: async () => {\n await this.showPlaceholder(\n actionKey('placeholders.hr-workflow.title'),\n actionKey('placeholders.hr-workflow.promotion'),\n );\n },\n }),\n this.withEmployeeSubmenu({\n id: 'organization-management.org-chart.hr-offboarding',\n title: actionKey('hr-workflow-offboarding'),\n icon: 'fa-light fa-door-open',\n order: 62,\n execute: async () => {\n await this.showPlaceholder(\n actionKey('placeholders.hr-workflow.title'),\n actionKey('placeholders.hr-workflow.offboarding'),\n );\n },\n }),\n this.withEmployeeSubmenu({\n id: 'organization-management.org-chart.schedule-meeting',\n title: actionKey('schedule-meeting'),\n icon: 'fa-light fa-calendar-plus',\n order: 70,\n submenuSectionBreak: true,\n execute: async () => {\n await this.showPlaceholder(\n actionKey('placeholders.schedule-meeting.title'),\n actionKey('placeholders.schedule-meeting.message'),\n );\n },\n }),\n this.withEmployeeSubmenu({\n id: 'organization-management.org-chart.add-to-team',\n title: actionKey('add-to-team'),\n icon: 'fa-light fa-user-plus',\n order: 75,\n /** Trailing group break: separator after the Employee row on the root menu (inner last-row break is normalized away). */\n break: 'after',\n disabled: !canTeam,\n execute: async (ctx) => {\n await this.openTeamSelectorThenCreateTeamMember(ctx, employeeId);\n },\n }),\n ];\n }\n\n /**\n * Picks a team via {@link AXPEntityDataSelectorService}, then opens **Create Team Member** with both `teamId` and\n * `employeeId` set.\n */\n private async openTeamSelectorThenCreateTeamMember(\n ctx: AXMOrgChartNodeContributionContext,\n employeeId: string,\n ): Promise<void> {\n const teamEntity = await this.entityRegistry.resolve(RootConfig.module.name, RootConfig.entities.team.name);\n if (!teamEntity) {\n return;\n }\n const title = await this.translationService.translateAsync(actionKey('add-to-team-select-team'));\n const pick = await this.entityDataSelector.open({\n entity: teamEntity,\n title,\n allowMultiple: false,\n });\n const teamId = pick?.items?.[0]?.id;\n if (teamId == null || String(teamId).trim().length === 0) {\n return;\n }\n\n const result = await this.commandService.execute('Entity:Create', {\n entity: RootConfig.entities.teamMember.source,\n entityInfo: this.teamMemberEntityInfo,\n data: { employeeId, teamId: String(teamId).trim() },\n options: {\n process: {\n redirect: false,\n },\n },\n \n });\n if (result?.success) {\n await ctx.refreshChart();\n }\n }\n\n private withEmployeeSubmenu(\n action: AXMOrgChartNodeMenuAction,\n ): AXMOrgChartNodeMenuAction {\n return {\n ...action,\n submenuGroupId: AXM_ORG_CHART_EMPLOYEE_SUBMENU_GROUP_ID,\n submenuGroupTitle: AXM_ORG_CHART_EMPLOYEE_SUBMENU_TITLE_I18N_KEY,\n submenuGroupIcon: AXM_ORG_CHART_EMPLOYEE_SUBMENU_ICON,\n };\n }\n\n //#endregion\n\n //#region ---- Resolvers ----\n\n private authorize(permission: string): boolean {\n return this.sessionService.authorize(permission);\n }\n\n private async showPlaceholder(titleKey: string, messageKey: string): Promise<void> {\n const title = await this.translationService.translateAsync(titleKey);\n const message = await this.translationService.translateAsync(messageKey);\n await this.dialogService.alert(title, message, 'primary');\n }\n\n //#endregion\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { AXPSessionService } from '@acorex-platform/framework-client/auth';
2
+ import { AXPCommandService } from '@acorex-platform/framework-client/runtime';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, Injectable } from '@angular/core';
5
+ import { RootConfig, AXPPeopleOrganizationPermissionKeys, AXM_HCM_POSITION_ASSIGNMENT_ASSIGN_COMMAND, AXMOrganizationManagementCommandKeys } from '@acorex-platform/module-organization-management-client/contracts';
6
+
7
+ //#region ---- Imports ----
8
+ //#endregion
9
+ //#region ---- Module Constants ----
10
+ const orgChartNodeActionKey = (suffix) => `@organization-management:organization-chart.node-actions.${suffix}`;
11
+ const POSITION_ENTITY_SOURCE = RootConfig.entities.position.source;
12
+ //#endregion
13
+ /**
14
+ * Context menu actions for org chart **position** nodes (structure / location / etc.).
15
+ */
16
+ class AXMOrgChartPositionEmployeeNodeContributionProvider {
17
+ constructor() {
18
+ //#region ---- Services & Dependencies ----
19
+ this.commandService = inject(AXPCommandService);
20
+ this.sessionService = inject(AXPSessionService);
21
+ }
22
+ //#endregion
23
+ //#region ---- AXMOrgChartNodeContributionProvider Implementation ----
24
+ async getMenuActions(context) {
25
+ if (context.nodeKind === 'position') {
26
+ return this.getPositionNodeActions(context);
27
+ }
28
+ return [];
29
+ }
30
+ //#endregion
31
+ //#region ---- Position Node Actions ----
32
+ getPositionNodeActions(context) {
33
+ const positionId = this.resolvePositionId(context);
34
+ if (!positionId) {
35
+ return [];
36
+ }
37
+ const businessUnitId = this.resolveBusinessUnitIdForPosition(context);
38
+ const vacant = context.node.metadata?.['vacant'] === true;
39
+ const occupant = context.node.metadata?.['occupant'];
40
+ const occupantEmployeeId = typeof occupant?.['employeeId'] === 'string' && occupant['employeeId'].trim().length > 0
41
+ ? occupant['employeeId'].trim()
42
+ : undefined;
43
+ const canMaintainOrganization = this.authorize(AXPPeopleOrganizationPermissionKeys.MaintainOrganization);
44
+ const canUpdateBusinessUnit = canMaintainOrganization;
45
+ const canCreateAssignment = canMaintainOrganization;
46
+ const canEditAssignment = canMaintainOrganization;
47
+ const actions = [];
48
+ if (vacant && businessUnitId) {
49
+ actions.push({
50
+ id: 'organization-management.assign-employee-to-position-from-chart',
51
+ title: orgChartNodeActionKey('assign-employee-to-position'),
52
+ icon: 'fa-light fa-user-plus',
53
+ order: 110,
54
+ disabled: !canCreateAssignment,
55
+ execute: async (ctx) => {
56
+ const pid = this.resolvePositionId(ctx);
57
+ const buId = this.resolveBusinessUnitIdForPosition(ctx);
58
+ if (!pid || !buId) {
59
+ return;
60
+ }
61
+ const result = await this.commandService.execute(AXM_HCM_POSITION_ASSIGNMENT_ASSIGN_COMMAND, {
62
+ data: {
63
+ businessUnitId: buId,
64
+ positionId: pid,
65
+ isPrimary: false,
66
+ },
67
+ });
68
+ if (result?.success) {
69
+ await ctx.refreshChart();
70
+ }
71
+ },
72
+ });
73
+ }
74
+ if (!vacant && occupantEmployeeId && businessUnitId) {
75
+ actions.push({
76
+ id: 'organization-management.replace-position-assignee-from-chart',
77
+ title: orgChartNodeActionKey('assign-new-employee-to-position'),
78
+ icon: 'fa-light fa-arrows-rotate',
79
+ order: 115,
80
+ disabled: !canCreateAssignment || !canEditAssignment,
81
+ execute: async (ctx) => {
82
+ const pid = this.resolvePositionId(ctx);
83
+ const buId = this.resolveBusinessUnitIdForPosition(ctx);
84
+ const occ = ctx.node.metadata?.['occupant'];
85
+ const eid = typeof occ?.['employeeId'] === 'string' && occ['employeeId'].trim().length > 0
86
+ ? occ['employeeId'].trim()
87
+ : '';
88
+ if (!pid || !buId || !eid) {
89
+ return;
90
+ }
91
+ const result = await this.commandService.execute(AXMOrganizationManagementCommandKeys.OrganizationChart.ReplacePositionAssignee, { businessUnitId: buId, positionId: pid, currentEmployeeId: eid });
92
+ if (result?.success) {
93
+ await ctx.refreshChart();
94
+ }
95
+ },
96
+ });
97
+ }
98
+ if (businessUnitId) {
99
+ actions.push({
100
+ id: 'organization-management.remove-position-from-unit-from-chart',
101
+ title: orgChartNodeActionKey('remove-from-unit'),
102
+ icon: 'fa-light fa-link-slash',
103
+ color: 'danger',
104
+ order: 120,
105
+ disabled: !canUpdateBusinessUnit,
106
+ execute: async (ctx) => {
107
+ const pid = this.resolvePositionId(ctx);
108
+ const buId = this.resolveBusinessUnitIdForPosition(ctx);
109
+ if (!pid || !buId) {
110
+ return;
111
+ }
112
+ const occ = ctx.node.metadata?.['occupant'];
113
+ const occId = typeof occ?.['employeeId'] === 'string' && occ['employeeId'].trim().length > 0
114
+ ? occ['employeeId'].trim()
115
+ : undefined;
116
+ const result = await this.commandService.execute(AXMOrganizationManagementCommandKeys.OrganizationChart.RemovePositionFromBusinessUnit, {
117
+ businessUnitId: buId,
118
+ positionId: pid,
119
+ ...(occId ? { occupantEmployeeId: occId } : {}),
120
+ });
121
+ if (result?.success) {
122
+ await ctx.refreshChart();
123
+ }
124
+ },
125
+ });
126
+ }
127
+ return actions;
128
+ }
129
+ //#endregion
130
+ //#region ---- Resolvers & Authorization ----
131
+ authorize(permission) {
132
+ return this.sessionService.authorize(permission);
133
+ }
134
+ resolvePositionId(context) {
135
+ const entity = context.node.entity;
136
+ if (entity?.id != null && this.isPositionEntityType(entity.type)) {
137
+ const id = String(entity.id).trim();
138
+ return id.length > 0 ? id : undefined;
139
+ }
140
+ const metaPid = context.node.metadata?.['positionId'];
141
+ if (typeof metaPid === 'string' && metaPid.trim().length > 0) {
142
+ return metaPid.trim();
143
+ }
144
+ return undefined;
145
+ }
146
+ isPositionEntityType(entityType) {
147
+ if (!entityType || typeof entityType !== 'string') {
148
+ return false;
149
+ }
150
+ return entityType === POSITION_ENTITY_SOURCE || entityType.endsWith('.Position');
151
+ }
152
+ resolveBusinessUnitIdForPosition(context) {
153
+ const meta = context.node.metadata ?? {};
154
+ const a = meta['businessUnitId'];
155
+ const b = meta['organizationalUnitId'];
156
+ const raw = (typeof a === 'string' && a.trim().length > 0 ? a : typeof b === 'string' ? b : '');
157
+ const id = String(raw).trim();
158
+ return id.length > 0 ? id : undefined;
159
+ }
160
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartPositionEmployeeNodeContributionProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
161
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartPositionEmployeeNodeContributionProvider }); }
162
+ }
163
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMOrgChartPositionEmployeeNodeContributionProvider, decorators: [{
164
+ type: Injectable
165
+ }] });
166
+
167
+ export { AXMOrgChartPositionEmployeeNodeContributionProvider };
168
+ //# sourceMappingURL=acorex-platform-module-organization-management-client-org-chart-position-employee-node-contribution.provider-BTicXn9n.mjs.map