@flusys/ng-iam 9.1.0 → 9.1.1

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 (37) hide show
  1. package/fesm2022/flusys-ng-iam-action-form-page.component-DJ-A1gc2.mjs +685 -0
  2. package/fesm2022/flusys-ng-iam-action-form-page.component-DJ-A1gc2.mjs.map +1 -0
  3. package/fesm2022/{flusys-ng-iam-action-list-page.component-Cf4Dhh5S.mjs → flusys-ng-iam-action-list-page.component-Br0PbgRa.mjs} +369 -166
  4. package/fesm2022/flusys-ng-iam-action-list-page.component-Br0PbgRa.mjs.map +1 -0
  5. package/fesm2022/flusys-ng-iam-iam-container.component-CIdxVCSW.mjs +141 -0
  6. package/fesm2022/flusys-ng-iam-iam-container.component-CIdxVCSW.mjs.map +1 -0
  7. package/fesm2022/flusys-ng-iam-permission-api.service-C7-Yxvz8.mjs +76 -0
  8. package/fesm2022/flusys-ng-iam-permission-api.service-C7-Yxvz8.mjs.map +1 -0
  9. package/fesm2022/flusys-ng-iam-permission-page.component-BlNt83uR.mjs +306 -0
  10. package/fesm2022/flusys-ng-iam-permission-page.component-BlNt83uR.mjs.map +1 -0
  11. package/fesm2022/flusys-ng-iam-role-api.service-OwPgmSFc.mjs +33 -0
  12. package/fesm2022/flusys-ng-iam-role-api.service-OwPgmSFc.mjs.map +1 -0
  13. package/fesm2022/flusys-ng-iam-role-form-page.component-DnkWkbTF.mjs +427 -0
  14. package/fesm2022/flusys-ng-iam-role-form-page.component-DnkWkbTF.mjs.map +1 -0
  15. package/fesm2022/flusys-ng-iam-role-list-page.component-BCO_gQ8k.mjs +685 -0
  16. package/fesm2022/flusys-ng-iam-role-list-page.component-BCO_gQ8k.mjs.map +1 -0
  17. package/fesm2022/flusys-ng-iam-tree-utils-B1pBG4At.mjs +110 -0
  18. package/fesm2022/flusys-ng-iam-tree-utils-B1pBG4At.mjs.map +1 -0
  19. package/fesm2022/flusys-ng-iam-user-action-selector.component-CAXEmJWx.mjs +4592 -0
  20. package/fesm2022/flusys-ng-iam-user-action-selector.component-CAXEmJWx.mjs.map +1 -0
  21. package/fesm2022/flusys-ng-iam.mjs +2051 -2
  22. package/fesm2022/flusys-ng-iam.mjs.map +1 -1
  23. package/package.json +5 -5
  24. package/types/flusys-ng-iam.d.ts +621 -604
  25. package/fesm2022/flusys-ng-iam-action-form-page.component-Dn0TD1Zu.mjs +0 -509
  26. package/fesm2022/flusys-ng-iam-action-form-page.component-Dn0TD1Zu.mjs.map +0 -1
  27. package/fesm2022/flusys-ng-iam-action-list-page.component-Cf4Dhh5S.mjs.map +0 -1
  28. package/fesm2022/flusys-ng-iam-flusys-ng-iam-Y7U2lGZk.mjs +0 -5584
  29. package/fesm2022/flusys-ng-iam-flusys-ng-iam-Y7U2lGZk.mjs.map +0 -1
  30. package/fesm2022/flusys-ng-iam-iam-container.component-XBoIeQ0t.mjs +0 -105
  31. package/fesm2022/flusys-ng-iam-iam-container.component-XBoIeQ0t.mjs.map +0 -1
  32. package/fesm2022/flusys-ng-iam-permission-page.component-CCAQuZSJ.mjs +0 -204
  33. package/fesm2022/flusys-ng-iam-permission-page.component-CCAQuZSJ.mjs.map +0 -1
  34. package/fesm2022/flusys-ng-iam-role-form-page.component-EFjxhBRY.mjs +0 -352
  35. package/fesm2022/flusys-ng-iam-role-form-page.component-EFjxhBRY.mjs.map +0 -1
  36. package/fesm2022/flusys-ng-iam-role-list-page.component-DBfhjdkM.mjs +0 -486
  37. package/fesm2022/flusys-ng-iam-role-list-page.component-DBfhjdkM.mjs.map +0 -1
@@ -1,2 +1,2051 @@
1
- export { A as ActionApiService, h as ActionPermissionLogicService, b as ActionPermittedUsersDialogComponent, i as ActionProviderAdapter, a as ActionType, C as CompanyActionSelectorComponent, I as IAM_MESSAGES, j as IAM_ROUTES, L as LogicBuilderComponent, M as MAX_DROPDOWN_ITEMS, k as MyPermissionsApiService, P as PermissionApiService, l as PermissionScopeResolverService, m as PermissionStateService, n as ProfilePermissionProviderAdapter, f as RoleActionSelectorComponent, R as RoleApiService, e as RolePermittedUsersDialogComponent, g as UserActionSelectorComponent, U as UserRoleSelectorComponent, p as provideIamProviders } from './flusys-ng-iam-flusys-ng-iam-Y7U2lGZk.mjs';
2
- //# sourceMappingURL=flusys-ng-iam.mjs.map
1
+ import { a as ActionPermissionLogicService, i as RoleActionSelectorComponent, n as UserRoleSelectorComponent, o as MAX_DROPDOWN_ITEMS, r as CompanyActionSelectorComponent, t as UserActionSelectorComponent } from "./flusys-ng-iam-user-action-selector.component-CAXEmJWx.mjs";
2
+ import { t as RoleApiService } from "./flusys-ng-iam-role-api.service-OwPgmSFc.mjs";
3
+ import { a as ActionApiService } from "./flusys-ng-iam-tree-utils-B1pBG4At.mjs";
4
+ import { t as PermissionApiService } from "./flusys-ng-iam-permission-api.service-C7-Yxvz8.mjs";
5
+ import * as i0 from "@angular/core";
6
+ import { Component, Service, effect, inject, input, output, signal } from "@angular/core";
7
+ import { ACTION_PERMISSIONS, ACTION_PROVIDER, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, HasPermissionDirective, PROFILE_PERMISSION_PROVIDER, PermissionValidatorService, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, SHARED_MESSAGES, TranslatePipe, TranslateService, USER_ACTION_PERMISSIONS, USER_PROVIDER, USER_ROLE_PERMISSIONS, anyPermissionGuard, permissionGuard, resolveTranslationModule } from "@flusys/ng-shared";
8
+ import { APP_CONFIG, getPermissionMode, getServiceUrl, isServiceEnabled } from "@flusys/ng-core";
9
+ import { ConfirmationService, DialogComponent, FButtonDirective, MessageService, ProgressSpinnerComponent, SelectComponent, TooltipDirective, UiIconComponent } from "@flusys/ng-ui";
10
+ import { HttpClient } from "@angular/common/http";
11
+ import { firstValueFrom, map, of } from "rxjs";
12
+ import { catchError, map as map$1, tap } from "rxjs/operators";
13
+ import { NgTemplateOutlet } from "@angular/common";
14
+ import * as i1 from "@angular/forms";
15
+ import { FormsModule } from "@angular/forms";
16
+ var ActionType;
17
+ (function(ActionType) {
18
+ ActionType["BACKEND"] = "backend";
19
+ ActionType["FRONTEND"] = "frontend";
20
+ ActionType["BOTH"] = "both";
21
+ })(ActionType || (ActionType = {}));
22
+ const IAM_MESSAGES = {
23
+ "action.create.success": "Action created successfully",
24
+ "action.create.many.success": "{{count}} actions created successfully",
25
+ "action.get.success": "Action retrieved successfully",
26
+ "action.get.by.ids.success": "Actions retrieved successfully by Ids",
27
+ "action.get.by.filter.success": "Actions retrieved successfully by filter",
28
+ "action.get.all.success": "Actions retrieved successfully",
29
+ "action.update.success": "Action updated successfully",
30
+ "action.update.many.success": "{{count}} actions updated successfully",
31
+ "action.delete.success": "Action deleted successfully",
32
+ "action.restore.success": "Action restored successfully",
33
+ "action.readonly.update.forbidden": "Cannot modify readonly action(s): {{names}}",
34
+ "action.readonly.delete.forbidden": "Cannot delete readonly action(s): {{names}}",
35
+ "role.create.success": "Role created successfully",
36
+ "role.create.many.success": "{{count}} roles created successfully",
37
+ "role.get.success": "Role retrieved successfully",
38
+ "role.get.by.ids.success": "Roles retrieved successfully by Ids",
39
+ "role.get.by.filter.success": "Roles retrieved successfully by filter",
40
+ "role.get.all.success": "Roles retrieved successfully",
41
+ "role.update.success": "Role updated successfully",
42
+ "role.update.many.success": "{{count}} roles updated successfully",
43
+ "role.delete.success": "Role deleted successfully",
44
+ "role.restore.success": "Role restored successfully",
45
+ "role.readonly.update.forbidden": "Cannot modify readonly role(s): {{names}}",
46
+ "role.readonly.delete.forbidden": "Cannot delete readonly role(s): {{names}}",
47
+ "permission.process.success": "Successfully processed {{total}} items: {{added}} added, {{removed}} removed",
48
+ "permission.user.required": "User is required for {{method}}",
49
+ "permission.already.exists": "Permission already exists",
50
+ "role.permission.actions.success": "Role actions retrieved successfully",
51
+ "role.permission.user.roles.success": "User roles retrieved successfully",
52
+ "user.action.permission.get.success": "User action permissions retrieved successfully",
53
+ "company.action.permission.get.success": "Company action permissions retrieved successfully",
54
+ "my.permission.get.success": "Permissions loaded successfully",
55
+ "iam.direct.mode.unavailable": "Direct permission assignment not available in RBAC-only mode",
56
+ "iam.rbac.mode.unavailable": "Role-based permission assignment not available in direct-only mode",
57
+ "iam.role.assignment.unavailable": "Role assignment not available in direct-only mode",
58
+ "iam.title": "Identity & Access Management",
59
+ "iam.subtitle": "Manage roles, permissions, and access control",
60
+ "iam.action.title": "Actions",
61
+ "iam.role.title": "Roles",
62
+ "iam.permission.title": "Permissions",
63
+ "iam.action.new": "New Action",
64
+ "iam.action.name": "Action Name",
65
+ "iam.action.code": "Action Code",
66
+ "iam.action.type": "Type",
67
+ "iam.action.no.actions": "No actions found",
68
+ "iam.action.type.backend": "Backend",
69
+ "iam.action.type.frontend": "Frontend",
70
+ "iam.action.type.both": "Both",
71
+ "iam.permission.view.users": "View Users",
72
+ "iam.permission.no.users": "No users found",
73
+ "iam.permission.remove": "Remove Access",
74
+ "iam.permission.remove.confirm": "Remove access for {{name}}?",
75
+ "iam.action.delete.title": "Delete Action",
76
+ "iam.company.name": "Company",
77
+ "iam.branch.name": "Branch",
78
+ "iam.branch.all": "All branches",
79
+ "iam.action.edit": "Edit Action",
80
+ "iam.action.name.placeholder": "Enter action name",
81
+ "iam.action.code.placeholder": "Enter action code",
82
+ "iam.action.parent": "Parent Action",
83
+ "iam.action.select.parent": "Select Parent Action",
84
+ "iam.action.type.backend.label": "Backend Only",
85
+ "iam.action.type.frontend.label": "Frontend Only",
86
+ "iam.action.type.both.label": "Backend & Frontend",
87
+ "iam.action.readonly.edit.forbidden": "This is a system action and cannot be edited",
88
+ "iam.company.title": "Companies",
89
+ "iam.role.new": "New Role",
90
+ "iam.role.name": "Role Name",
91
+ "iam.role.no.roles": "No roles found",
92
+ "iam.role.delete.title": "Delete Role",
93
+ "iam.role.edit": "Edit Role",
94
+ "iam.role.name.placeholder": "Enter role name",
95
+ "iam.role.readonly.edit.forbidden": "This is a system role and cannot be edited",
96
+ "iam.permission.subtitle": "Assign and manage access across roles, users, and companies",
97
+ "iam.permission.role.actions": "Role Actions",
98
+ "iam.permission.user.roles": "User Roles",
99
+ "iam.permission.user.actions": "User Actions",
100
+ "iam.permission.company.actions": "Company Actions",
101
+ "iam.permission.empty.role.actions.title": "Select a role to get started",
102
+ "iam.permission.empty.role.actions.description": "Choose a role from the dropdown above to view and manage its assigned actions.",
103
+ "iam.permission.empty.user.roles.title": "Select a user to get started",
104
+ "iam.permission.empty.user.roles.description": "Choose a user above to view and manage their assigned roles.",
105
+ "iam.permission.empty.user.actions.title": "Select a user to get started",
106
+ "iam.permission.empty.user.actions.description": "Choose a user above to view and manage their direct action permissions.",
107
+ "iam.permission.empty.company.actions.title": "Select a company to get started",
108
+ "iam.permission.empty.company.actions.description": "Choose a company from the dropdown above to view and manage its action whitelist.",
109
+ "iam.permission.unsaved.changes.title": "Unsaved Changes",
110
+ "iam.permission.unsaved.changes.message": "You have unsaved permission changes. Switching now will discard them.",
111
+ "iam.permission.unsaved.changes.discard": "Discard Changes",
112
+ "iam.logic.title": "Permission Logic",
113
+ "iam.logic.add.logic": "Add Logic",
114
+ "iam.logic.clear.logic": "Clear Logic",
115
+ "iam.logic.description": "Define permission requirements using AND/OR logic with actions",
116
+ "iam.logic.click.to.toggle": "Click to toggle",
117
+ "iam.logic.conditions": "{{count}} conditions",
118
+ "iam.logic.select.action": "Select Action...",
119
+ "iam.logic.actions.available": "{{count}} available",
120
+ "iam.logic.add.condition": "Add Condition:",
121
+ "iam.logic.group": "Group",
122
+ "iam.logic.action": "Action",
123
+ "iam.permission.select.role": "Select Role",
124
+ "iam.permission.select.role.placeholder": "Search and select a role",
125
+ "iam.permission.action.permissions": "Action Permissions",
126
+ "iam.permission.actions.available": "{{count}} actions available",
127
+ "iam.validation.warning.title": "Validation Warning",
128
+ "iam.validation.unmet.prerequisites.plural": "{{count}} selected actions have unmet prerequisites. Fix before saving or use auto-fix on save.",
129
+ "iam.validation.unmet.prerequisites.singular": "{{count}} selected action has unmet prerequisites. Fix before saving or use auto-fix on save.",
130
+ "iam.permission.requirements": "Requirements",
131
+ "iam.validation.unmet.prerequisites.tooltip": "This action has unmet prerequisites and will fail validation on save",
132
+ "iam.permission.has.prerequisites": "Has prerequisites",
133
+ "iam.permission.no.actions.available": "No actions available",
134
+ "iam.permission.no.actions.for.role": "No actions available for this role",
135
+ "iam.tooltip.remove.action": "Click to remove",
136
+ "iam.tooltip.add.action": "Click to add (auto-selects required)",
137
+ "iam.tooltip.assigned.to.role": "Assigned to role",
138
+ "iam.tooltip.click.to.remove.role": "Click to remove",
139
+ "iam.tooltip.click.to.assign.role": "Click to assign to role",
140
+ "iam.permission.select.user": "Select User",
141
+ "iam.permission.select.user.placeholder": "Search and select a user",
142
+ "iam.permission.select.branch": "Select Branch",
143
+ "iam.permission.select.branch.placeholder": "Search and select a branch",
144
+ "iam.branch.permitted.count.plural": "{{count}} permitted branches in current company",
145
+ "iam.branch.permitted.count": "{{count}} permitted branch in current company",
146
+ "iam.permission.direct.action.permissions": "Direct Action Permissions",
147
+ "iam.permission.no.actions.for.user": "No actions available for this user",
148
+ "iam.tooltip.assigned.to.user": "Assigned to user",
149
+ "iam.tooltip.click.to.remove.user": "Click to remove direct permission",
150
+ "iam.tooltip.click.to.assign.user": "Click to assign direct permission",
151
+ "iam.permission.company.required": "Please select a company first",
152
+ "iam.permission.select.company": "Select Company",
153
+ "iam.permission.select.company.placeholder": "Search and select a company",
154
+ "iam.permission.action.whitelist": "Action Whitelist",
155
+ "iam.permission.no.actions.for.company": "No actions available for this company",
156
+ "iam.tooltip.selected": "Selected",
157
+ "iam.tooltip.click.to.remove": "Click to remove from company whitelist",
158
+ "iam.tooltip.click.to.add": "Click to add to company whitelist",
159
+ "iam.permission.requires": "requires",
160
+ "iam.permission.prerequisite.validation.failed": "Prerequisite Validation Failed",
161
+ "iam.permission.prerequisite.error.message": "The following actions have unmet prerequisites:",
162
+ "iam.permission.auto.select.required": "Auto-select Required",
163
+ "iam.permission.actions.selected": "Actions Selected",
164
+ "iam.permission.auto.selected.prerequisites": "Required prerequisites have been auto-selected. Click Save to apply changes.",
165
+ "iam.permission.changes.reverted": "Changes Reverted",
166
+ "iam.permission.selection.reverted": "Selection has been reverted to the initial state.",
167
+ "iam.permission.role.assignments": "Role Assignments",
168
+ "iam.permission.roles.available": "{{count}} roles available",
169
+ "iam.pagination.roles.template": "Showing {first} to {last} of {totalRecords} roles",
170
+ "iam.permission.no.roles.available": "No roles available",
171
+ "iam.permission.no.roles.for.user": "No roles available for this user",
172
+ "iam.tooltip.click.to.remove.role.from.user": "Click to remove role",
173
+ "iam.tooltip.click.to.assign.role.to.user": "Click to assign role to user",
174
+ "iam.logic.unknown.action": "Unknown Action",
175
+ "iam.logic.validation.failed": "Validation Failed",
176
+ "iam.logic.validation.failed.message": "The following actions have unmet prerequisites:",
177
+ "iam.logic.validation.failed.prompt": "Would you like to:",
178
+ "iam.logic.auto.fix": "Auto-fix (Remove Invalid)",
179
+ "iam.logic.invalid.actions.removed": "Invalid Actions Removed",
180
+ "iam.logic.removed.actions.detail": "Removed {{count}} action(s) with unmet prerequisites. You can now save.",
181
+ "iam.logic.save.cancelled": "Save Cancelled",
182
+ "iam.logic.fix.prerequisites.manually": "Please fix the prerequisites manually before saving",
183
+ "iam.logic.prerequisites.satisfied": "[OK] Prerequisites Satisfied",
184
+ "iam.logic.all.required.selected": "All required actions are already selected.\nYou can safely add this action.",
185
+ "iam.logic.prerequisites.required": "Prerequisites Required ({{count}} missing)",
186
+ "iam.logic.click.to.auto.select": "Click to auto-select required actions",
187
+ "iam.logic.select.action.label": "Select Action",
188
+ "iam.logic.auto.select.actions": "Auto-select Actions",
189
+ "iam.logic.action.selected.detail": "Action selected successfully (prerequisites already satisfied)",
190
+ "iam.logic.auto.selected.detail": "Automatically selected {{count}} action(s) including prerequisites",
191
+ "iam.logic.minimum.required": " (minimum required)",
192
+ "iam.logic.auto.select.prompt": "Auto-select will choose {{count}} action(s){{suffix}}.",
193
+ "iam.logic.missing.prerequisites": "Missing Prerequisites",
194
+ "iam.logic.requires.conditions": "requires the following conditions to be satisfied:",
195
+ "iam.logic.would.you.continue": "Would you like to continue?",
196
+ "iam.logic.actions.selected.summary": "Actions Selected",
197
+ "iam.logic.selection.cancelled": "Selection Cancelled",
198
+ "iam.logic.action.not.added": "Action not added to whitelist",
199
+ "iam.logic.required.by.actions": "is required by the following action(s):",
200
+ "iam.logic.alternatives.available": "Alternative options available:",
201
+ "iam.logic.switch.to.alternatives": "Would you like to automatically switch to alternatives?",
202
+ "iam.logic.remove.dependents": "Removing this will also remove the dependent action(s).",
203
+ "iam.logic.dependency.warning": "Dependency Warning",
204
+ "iam.logic.use.alternatives": "Use Alternatives",
205
+ "iam.logic.remove.all": "Remove All",
206
+ "iam.logic.alternatives.applied": "Alternatives Applied",
207
+ "iam.logic.switched.to.alternatives": "Automatically switched to alternative action(s)",
208
+ "iam.logic.actions.removed": "Actions Removed",
209
+ "iam.logic.removed.with.dependents": "Removed {{name}} and {{count}} dependent action(s)",
210
+ "iam.logic.cancelled": "Cancelled",
211
+ "iam.logic.no.changes.made": "No changes made",
212
+ "iam.logic.satisfied": "(satisfied)",
213
+ "iam.logic.missing": "(missing)",
214
+ "iam.logic.invalid.node": "Invalid logic node",
215
+ "iam.logic.invalid": "(invalid)"
216
+ };
217
+ var MyPermissionsApiService = class MyPermissionsApiService {
218
+ http = inject(HttpClient);
219
+ appConfig = inject(APP_CONFIG);
220
+ baseUrl = `${getServiceUrl(this.appConfig, "iam")}/permissions`;
221
+ getMyPermissions(dto = {}) {
222
+ return this.http.post(`${this.baseUrl}/my-permissions`, dto);
223
+ }
224
+ static ɵfac = i0.ɵɵngDeclareFactory({
225
+ minVersion: "12.0.0",
226
+ version: "22.2.1",
227
+ ngImport: i0,
228
+ type: MyPermissionsApiService,
229
+ deps: [],
230
+ target: i0.ɵɵFactoryTarget.Service
231
+ });
232
+ static ɵprov = i0.ɵɵngDeclareService({
233
+ minVersion: "22.0.0",
234
+ version: "22.2.1",
235
+ ngImport: i0,
236
+ type: MyPermissionsApiService
237
+ });
238
+ };
239
+ i0.ɵɵngDeclareClassMetadata({
240
+ minVersion: "12.0.0",
241
+ version: "22.2.1",
242
+ ngImport: i0,
243
+ type: MyPermissionsApiService,
244
+ decorators: [{ type: Service }]
245
+ });
246
+ var PermissionStateService = class PermissionStateService {
247
+ permissionApi = inject(MyPermissionsApiService);
248
+ permissionValidator = inject(PermissionValidatorService);
249
+ _permissions = signal(null, ...ngDevMode ? [{ debugName: "_permissions" }] : /* istanbul ignore next */ []);
250
+ permissions = this._permissions.asReadonly();
251
+ _isLoading = signal(false, ...ngDevMode ? [{ debugName: "_isLoading" }] : /* istanbul ignore next */ []);
252
+ isLoading = this._isLoading.asReadonly();
253
+ loadPermissions(dto) {
254
+ this._isLoading.set(true);
255
+ return this.permissionApi.getMyPermissions(dto).pipe(tap((response) => {
256
+ this._permissions.set(response.data ?? null);
257
+ this._isLoading.set(false);
258
+ const actionCodes = response.data?.frontendActions.map((a) => a.code) ?? [];
259
+ this.permissionValidator.setPermissions(actionCodes);
260
+ }), catchError(() => {
261
+ this._permissions.set(null);
262
+ this._isLoading.set(false);
263
+ this.permissionValidator.clearPermissions();
264
+ return of(void 0);
265
+ }), map$1(() => void 0));
266
+ }
267
+ isLoaded() {
268
+ return this._permissions() !== null && this.permissionValidator.isLoaded();
269
+ }
270
+ static ɵfac = i0.ɵɵngDeclareFactory({
271
+ minVersion: "12.0.0",
272
+ version: "22.2.1",
273
+ ngImport: i0,
274
+ type: PermissionStateService,
275
+ deps: [],
276
+ target: i0.ɵɵFactoryTarget.Service
277
+ });
278
+ static ɵprov = i0.ɵɵngDeclareService({
279
+ minVersion: "22.0.0",
280
+ version: "22.2.1",
281
+ ngImport: i0,
282
+ type: PermissionStateService
283
+ });
284
+ };
285
+ i0.ɵɵngDeclareClassMetadata({
286
+ minVersion: "12.0.0",
287
+ version: "22.2.1",
288
+ ngImport: i0,
289
+ type: PermissionStateService,
290
+ decorators: [{ type: Service }]
291
+ });
292
+ var PermissionScopeResolverService = class PermissionScopeResolverService {
293
+ companyProvider = inject(COMPANY_API_PROVIDER);
294
+ async resolveCompanyInfo(companyIds) {
295
+ if (companyIds.length === 0 || !this.companyProvider.getCompaniesByIds) return /* @__PURE__ */ new Map();
296
+ try {
297
+ const response = await firstValueFrom(this.companyProvider.getCompaniesByIds(companyIds));
298
+ return new Map((response.data ?? []).map((c) => [c.id, c]));
299
+ } catch {
300
+ return /* @__PURE__ */ new Map();
301
+ }
302
+ }
303
+ async resolveBranchInfo(branchIds) {
304
+ if (branchIds.length === 0 || !this.companyProvider.getBranchesByIds) return /* @__PURE__ */ new Map();
305
+ try {
306
+ const response = await firstValueFrom(this.companyProvider.getBranchesByIds(branchIds));
307
+ return new Map((response.data ?? []).map((b) => [b.id, b]));
308
+ } catch {
309
+ return /* @__PURE__ */ new Map();
310
+ }
311
+ }
312
+ static ɵfac = i0.ɵɵngDeclareFactory({
313
+ minVersion: "12.0.0",
314
+ version: "22.2.1",
315
+ ngImport: i0,
316
+ type: PermissionScopeResolverService,
317
+ deps: [],
318
+ target: i0.ɵɵFactoryTarget.Service
319
+ });
320
+ static ɵprov = i0.ɵɵngDeclareService({
321
+ minVersion: "22.0.0",
322
+ version: "22.2.1",
323
+ ngImport: i0,
324
+ type: PermissionScopeResolverService
325
+ });
326
+ };
327
+ i0.ɵɵngDeclareClassMetadata({
328
+ minVersion: "12.0.0",
329
+ version: "22.2.1",
330
+ ngImport: i0,
331
+ type: PermissionScopeResolverService,
332
+ decorators: [{ type: Service }]
333
+ });
334
+ function toLogicNode(node) {
335
+ if (node.type === "action") return {
336
+ type: "action",
337
+ actionId: node.actionId
338
+ };
339
+ return {
340
+ type: "group",
341
+ operator: node.operator,
342
+ children: node.children?.map(toLogicNode) ?? []
343
+ };
344
+ }
345
+ function toBuilderNode(node) {
346
+ if (node.type === "action") return createActionNode(node.actionId);
347
+ return {
348
+ ...createGroupNode(node.operator),
349
+ children: node.children?.map(toBuilderNode) ?? []
350
+ };
351
+ }
352
+ function createGroupNode(operator = "AND") {
353
+ return {
354
+ id: crypto.randomUUID(),
355
+ type: "group",
356
+ operator,
357
+ children: []
358
+ };
359
+ }
360
+ function createActionNode(actionId = "") {
361
+ return {
362
+ id: crypto.randomUUID(),
363
+ type: "action",
364
+ actionId
365
+ };
366
+ }
367
+ var LogicBuilderComponent = class LogicBuilderComponent {
368
+ logic = input(null, ...ngDevMode ? [{ debugName: "logic" }] : /* istanbul ignore next */ []);
369
+ actions = input([], ...ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []);
370
+ logicChange = output();
371
+ _builderTree = signal(null, ...ngDevMode ? [{ debugName: "_builderTree" }] : /* istanbul ignore next */ []);
372
+ builderLogic = this._builderTree.asReadonly();
373
+ constructor() {
374
+ effect(() => {
375
+ const logic = this.logic();
376
+ if (!logic) this._builderTree.set(null);
377
+ else if (!this._builderTree()) this._builderTree.set(toBuilderNode(logic));
378
+ });
379
+ }
380
+ initializeLogic() {
381
+ this.updateTreeAndEmit(createGroupNode());
382
+ }
383
+ clearLogic() {
384
+ this._builderTree.set(null);
385
+ this.logicChange.emit(null);
386
+ }
387
+ toggleOperator(nodeId) {
388
+ this.updateNode(nodeId, (node) => ({
389
+ ...node,
390
+ operator: node.operator === "AND" ? "OR" : "AND"
391
+ }));
392
+ }
393
+ addChildNode(parentId, type) {
394
+ const newNode = type === "group" ? createGroupNode() : createActionNode();
395
+ this.updateNode(parentId, (node) => ({
396
+ ...node,
397
+ children: [...node.children || [], newNode]
398
+ }));
399
+ }
400
+ removeNode(nodeId) {
401
+ const tree = this._builderTree();
402
+ if (!tree) return;
403
+ if (tree.id === nodeId) {
404
+ this.clearLogic();
405
+ return;
406
+ }
407
+ this.updateTreeAndEmit(this.removeNodeFromTree(tree, nodeId));
408
+ }
409
+ updateActionId(nodeId, actionId) {
410
+ this.updateNode(nodeId, (node) => ({
411
+ ...node,
412
+ actionId
413
+ }));
414
+ }
415
+ updateNode(nodeId, updater) {
416
+ const tree = this._builderTree();
417
+ if (!tree) return;
418
+ this.updateTreeAndEmit(this.updateNodeInTree(tree, nodeId, updater));
419
+ }
420
+ updateTreeAndEmit(tree) {
421
+ this._builderTree.set(tree);
422
+ this.logicChange.emit(toLogicNode(tree));
423
+ }
424
+ updateNodeInTree(node, targetId, updater) {
425
+ if (node.id === targetId) return updater(node);
426
+ if (!node.children) return node;
427
+ return {
428
+ ...node,
429
+ children: node.children.map((child) => this.updateNodeInTree(child, targetId, updater))
430
+ };
431
+ }
432
+ removeNodeFromTree(node, targetId) {
433
+ if (!node.children) return node;
434
+ return {
435
+ ...node,
436
+ children: node.children.filter((child) => child.id !== targetId).map((child) => this.removeNodeFromTree(child, targetId))
437
+ };
438
+ }
439
+ static ɵfac = i0.ɵɵngDeclareFactory({
440
+ minVersion: "12.0.0",
441
+ version: "22.2.1",
442
+ ngImport: i0,
443
+ type: LogicBuilderComponent,
444
+ deps: [],
445
+ target: i0.ɵɵFactoryTarget.Component
446
+ });
447
+ static ɵcmp = i0.ɵɵngDeclareComponent({
448
+ minVersion: "17.0.0",
449
+ version: "22.2.1",
450
+ type: LogicBuilderComponent,
451
+ isStandalone: true,
452
+ selector: "lib-logic-builder",
453
+ inputs: {
454
+ logic: {
455
+ classPropertyName: "logic",
456
+ publicName: "logic",
457
+ isSignal: true,
458
+ isRequired: false,
459
+ transformFunction: null
460
+ },
461
+ actions: {
462
+ classPropertyName: "actions",
463
+ publicName: "actions",
464
+ isSignal: true,
465
+ isRequired: false,
466
+ transformFunction: null
467
+ }
468
+ },
469
+ outputs: { logicChange: "logicChange" },
470
+ ngImport: i0,
471
+ template: `
472
+ <div class="logic-builder">
473
+ <div class="flex justify-between items-center mb-3">
474
+ <h4 class="text-sm font-semibold m-0">
475
+ {{ 'iam.logic.title' | translate }}
476
+ </h4>
477
+ @if (!builderLogic()) {
478
+ <button
479
+ fButton
480
+ size="small"
481
+ (click)="initializeLogic()"
482
+ >
483
+ <ui-icon pButtonIcon name="plus"></ui-icon>
484
+ <span pButtonLabel>{{ 'iam.logic.add.logic' | translate }}</span>
485
+ </button>
486
+ } @else {
487
+ <button
488
+ fButton
489
+ size="small"
490
+ severity="danger"
491
+ [outlined]="true"
492
+ (click)="clearLogic()"
493
+ >
494
+ <ui-icon pButtonIcon name="trash"></ui-icon>
495
+ <span pButtonLabel>{{ 'iam.logic.clear.logic' | translate }}</span>
496
+ </button>
497
+ }
498
+ </div>
499
+
500
+ @if (builderLogic()) {
501
+ <div class="border border-surface rounded p-3 bg-surface-50 dark:bg-surface-800">
502
+ <div class="mb-3 text-sm text-muted-color">
503
+ {{ 'iam.logic.description' | translate }}
504
+ </div>
505
+
506
+ <!-- Root Node -->
507
+ <div class="text-sm bg-surface-0 dark:bg-surface-900 rounded border border-surface">
508
+ <ng-container
509
+ [ngTemplateOutlet]="nodeTemplate"
510
+ [ngTemplateOutletContext]="{ $implicit: builderLogic()!, depth: 0 }"
511
+ ></ng-container>
512
+ </div>
513
+ </div>
514
+ }
515
+ </div>
516
+
517
+ <!-- Recursive Node Template -->
518
+ <ng-template #nodeTemplate let-node let-depth="depth">
519
+ <div
520
+ class="p-3 border-b border-surface"
521
+ [class.bg-surface-0]="depth % 2 === 0"
522
+ [class.dark:bg-surface-900]="depth % 2 === 0"
523
+ [class.bg-surface-50]="depth % 2 !== 0"
524
+ [class.dark:bg-surface-800]="depth % 2 !== 0"
525
+ >
526
+ <div class="flex items-center gap-3 mb-2">
527
+ <span
528
+ class="node-type"
529
+ [class.group]="node.type === 'group'"
530
+ [class.action]="node.type === 'action'"
531
+ >{{ node.type.toUpperCase() }}</span
532
+ >
533
+
534
+ <div class="flex-1 flex items-center gap-2">
535
+ @if (node.type === 'group') {
536
+ <!-- Group: show operator toggle -->
537
+ <span
538
+ class="operator-badge"
539
+ [class.and]="node.operator === 'AND'"
540
+ [class.or]="node.operator !== 'AND'"
541
+ (click)="toggleOperator(node.id)"
542
+ [fTooltip]="'iam.logic.click.to.toggle' | translate"
543
+ >
544
+ {{ node.operator }}
545
+ </span>
546
+ <span class="text-muted-color text-xs"
547
+ >({{
548
+ 'iam.logic.conditions'
549
+ | translate: { count: node.children?.length || 0 }
550
+ }})</span
551
+ >
552
+ }
553
+
554
+ @if (node.type === 'action') {
555
+ <f-select
556
+ class="flex-1"
557
+ [options]="actions()"
558
+ optionLabel="name"
559
+ optionValue="id"
560
+ [ngModel]="node.actionId"
561
+ (ngModelChange)="updateActionId(node.id, $event)"
562
+ [placeholder]="'iam.logic.select.action' | translate"
563
+ [filter]="true"
564
+ />
565
+ }
566
+ </div>
567
+
568
+ <div class="flex gap-1">
569
+ <button
570
+ fButton
571
+ [text]="true"
572
+ severity="danger"
573
+ size="small"
574
+ (click)="removeNode(node.id)"
575
+ [fTooltip]="'shared.remove' | translate"
576
+ >
577
+ <ui-icon pButtonIcon name="trash"></ui-icon>
578
+ </button>
579
+ </div>
580
+ </div>
581
+
582
+ <!-- Children for group nodes -->
583
+ @if (
584
+ node.type === 'group' && node.children && node.children.length > 0
585
+ ) {
586
+ <div class="ml-5 mt-2 pl-3 border-l-2 border-surface">
587
+ @for (child of node.children; track child.id) {
588
+ <ng-container
589
+ [ngTemplateOutlet]="nodeTemplate"
590
+ [ngTemplateOutletContext]="{ $implicit: child, depth: depth + 1 }"
591
+ ></ng-container>
592
+ }
593
+ </div>
594
+ }
595
+
596
+ <!-- Add child buttons for group nodes -->
597
+ @if (node.type === 'group') {
598
+ <div
599
+ class="mt-3 p-3 bg-surface-50 dark:bg-surface-800 rounded border border-dashed border-surface"
600
+ >
601
+ <div class="text-xs font-semibold text-muted-color mb-2">
602
+ {{ 'iam.logic.add.condition' | translate }}
603
+ </div>
604
+ <div class="flex gap-2 flex-wrap">
605
+ <button
606
+ fButton
607
+ size="small"
608
+ [outlined]="true"
609
+ (click)="addChildNode(node.id, 'group')"
610
+ >
611
+ <ui-icon pButtonIcon name="sitemap"></ui-icon>
612
+ <span pButtonLabel>{{ 'iam.logic.group' | translate }}</span>
613
+ </button>
614
+ <button
615
+ fButton
616
+ size="small"
617
+ severity="success"
618
+ [outlined]="true"
619
+ (click)="addChildNode(node.id, 'action')"
620
+ >
621
+ <ui-icon pButtonIcon name="bolt"></ui-icon>
622
+ <span pButtonLabel>{{ 'iam.logic.action' | translate }}</span>
623
+ </button>
624
+ </div>
625
+ </div>
626
+ }
627
+ </div>
628
+ </ng-template>
629
+ `,
630
+ isInline: true,
631
+ styles: [":host{display:block}.node-type{display:inline-flex;align-items:center;padding:.25rem .5rem;border-radius:.25rem;font-weight:600;font-size:.75rem;text-transform:uppercase}.node-type.group{background-color:var(--f-blue-100, #dbeafe);color:var(--f-blue-700, #1e40af)}.node-type.action{background-color:var(--f-green-100, #d1fae5);color:var(--f-green-700, #065f46)}:host-context(.app-dark) .node-type.group{background-color:#3b82f633;color:var(--f-blue-400, #60a5fa)}:host-context(.app-dark) .node-type.action{background-color:#22c55e33;color:var(--f-green-400, #4ade80)}.operator-badge{display:inline-flex;align-items:center;padding:.125rem .5rem;border-radius:9999px;font-weight:600;font-size:.75rem;cursor:pointer;transition:opacity .2s}.operator-badge.and{background-color:var(--f-yellow-100, #fef3c7);color:var(--f-yellow-700, #92400e)}.operator-badge.or{background-color:var(--f-indigo-100, #e0e7ff);color:var(--f-indigo-700, #3730a3)}:host-context(.app-dark) .operator-badge.and{background-color:#eab30833;color:var(--f-yellow-400, #facc15)}:host-context(.app-dark) .operator-badge.or{background-color:#6366f133;color:var(--f-indigo-400, #818cf8)}.operator-badge:hover{opacity:.8}.action-select{background-color:var(--f-surface-0, #ffffff);color:var(--f-text-color, #1f2937)}:host-context(.app-dark) .action-select{background-color:var(--f-surface-900, #1f2937);color:var(--f-text-color, #f9fafb)}.action-select:focus{outline:none;border-color:var(--f-primary-color, #3b82f6)}\n"],
632
+ dependencies: [
633
+ {
634
+ kind: "ngmodule",
635
+ type: FormsModule
636
+ },
637
+ {
638
+ kind: "directive",
639
+ type: i1.NgControlStatus,
640
+ selector: "[formControlName],[ngModel],[formControl]"
641
+ },
642
+ {
643
+ kind: "directive",
644
+ type: i1.NgModel,
645
+ selector: "[ngModel]:not([formControlName]):not([formControl])",
646
+ inputs: [
647
+ "name",
648
+ "disabled",
649
+ "ngModel",
650
+ "ngModelOptions"
651
+ ],
652
+ outputs: ["ngModelChange"],
653
+ exportAs: ["ngModel"]
654
+ },
655
+ {
656
+ kind: "directive",
657
+ type: NgTemplateOutlet,
658
+ selector: "[ngTemplateOutlet]",
659
+ inputs: [
660
+ "ngTemplateOutletContext",
661
+ "ngTemplateOutlet",
662
+ "ngTemplateOutletInjector"
663
+ ]
664
+ },
665
+ {
666
+ kind: "directive",
667
+ type: FButtonDirective,
668
+ selector: "[fButton]",
669
+ inputs: [
670
+ "severity",
671
+ "text",
672
+ "outlined",
673
+ "link",
674
+ "variant",
675
+ "rounded",
676
+ "raised",
677
+ "fluid",
678
+ "disabled",
679
+ "loading",
680
+ "loadingIcon",
681
+ "size",
682
+ "label",
683
+ "icon",
684
+ "iconPos",
685
+ "ariaLabel",
686
+ "plain"
687
+ ]
688
+ },
689
+ {
690
+ kind: "component",
691
+ type: SelectComponent,
692
+ selector: "f-select",
693
+ inputs: [
694
+ "options",
695
+ "optionLabel",
696
+ "optionValue",
697
+ "placeholder",
698
+ "disabled",
699
+ "filter",
700
+ "filterBy",
701
+ "filterMatchMode",
702
+ "filterLocale",
703
+ "filterPlaceholder",
704
+ "resetFilterOnHide",
705
+ "autofocusFilter",
706
+ "emptyMessage",
707
+ "emptyFilterMessage",
708
+ "showClear",
709
+ "loading",
710
+ "loadingIcon",
711
+ "dropdownIcon",
712
+ "clearIcon",
713
+ "inputId",
714
+ "invalid",
715
+ "touched",
716
+ "styleClass",
717
+ "style",
718
+ "appendTo",
719
+ "editable",
720
+ "readonly",
721
+ "autofocus",
722
+ "checkmark",
723
+ "group",
724
+ "optionGroupLabel",
725
+ "optionGroupChildren",
726
+ "virtualScroll",
727
+ "virtualScrollItemSize",
728
+ "lazy",
729
+ "selectedObject"
730
+ ],
731
+ outputs: [
732
+ "onFilter",
733
+ "onChange",
734
+ "onShow",
735
+ "onHide",
736
+ "onBlur",
737
+ "onFocus",
738
+ "onClear",
739
+ "onLazyLoad"
740
+ ]
741
+ },
742
+ {
743
+ kind: "directive",
744
+ type: TooltipDirective,
745
+ selector: "[fTooltip]",
746
+ inputs: [
747
+ "fTooltip",
748
+ "tooltipPosition",
749
+ "positionStyle",
750
+ "tooltipStyleClass",
751
+ "disabled",
752
+ "tooltipEvent",
753
+ "showDelay",
754
+ "hideDelay",
755
+ "life",
756
+ "autoHide",
757
+ "positionTop",
758
+ "positionLeft",
759
+ "escape"
760
+ ]
761
+ },
762
+ {
763
+ kind: "component",
764
+ type: UiIconComponent,
765
+ selector: "ui-icon",
766
+ inputs: [
767
+ "name",
768
+ "size",
769
+ "spin",
770
+ "fill",
771
+ "severity"
772
+ ]
773
+ },
774
+ {
775
+ kind: "pipe",
776
+ type: TranslatePipe,
777
+ name: "translate"
778
+ }
779
+ ]
780
+ });
781
+ };
782
+ i0.ɵɵngDeclareClassMetadata({
783
+ minVersion: "12.0.0",
784
+ version: "22.2.1",
785
+ ngImport: i0,
786
+ type: LogicBuilderComponent,
787
+ decorators: [{
788
+ type: Component,
789
+ args: [{
790
+ selector: "lib-logic-builder",
791
+ imports: [
792
+ FormsModule,
793
+ NgTemplateOutlet,
794
+ FButtonDirective,
795
+ SelectComponent,
796
+ TooltipDirective,
797
+ UiIconComponent,
798
+ TranslatePipe
799
+ ],
800
+ template: `
801
+ <div class="logic-builder">
802
+ <div class="flex justify-between items-center mb-3">
803
+ <h4 class="text-sm font-semibold m-0">
804
+ {{ 'iam.logic.title' | translate }}
805
+ </h4>
806
+ @if (!builderLogic()) {
807
+ <button
808
+ fButton
809
+ size="small"
810
+ (click)="initializeLogic()"
811
+ >
812
+ <ui-icon pButtonIcon name="plus"></ui-icon>
813
+ <span pButtonLabel>{{ 'iam.logic.add.logic' | translate }}</span>
814
+ </button>
815
+ } @else {
816
+ <button
817
+ fButton
818
+ size="small"
819
+ severity="danger"
820
+ [outlined]="true"
821
+ (click)="clearLogic()"
822
+ >
823
+ <ui-icon pButtonIcon name="trash"></ui-icon>
824
+ <span pButtonLabel>{{ 'iam.logic.clear.logic' | translate }}</span>
825
+ </button>
826
+ }
827
+ </div>
828
+
829
+ @if (builderLogic()) {
830
+ <div class="border border-surface rounded p-3 bg-surface-50 dark:bg-surface-800">
831
+ <div class="mb-3 text-sm text-muted-color">
832
+ {{ 'iam.logic.description' | translate }}
833
+ </div>
834
+
835
+ <!-- Root Node -->
836
+ <div class="text-sm bg-surface-0 dark:bg-surface-900 rounded border border-surface">
837
+ <ng-container
838
+ [ngTemplateOutlet]="nodeTemplate"
839
+ [ngTemplateOutletContext]="{ $implicit: builderLogic()!, depth: 0 }"
840
+ ></ng-container>
841
+ </div>
842
+ </div>
843
+ }
844
+ </div>
845
+
846
+ <!-- Recursive Node Template -->
847
+ <ng-template #nodeTemplate let-node let-depth="depth">
848
+ <div
849
+ class="p-3 border-b border-surface"
850
+ [class.bg-surface-0]="depth % 2 === 0"
851
+ [class.dark:bg-surface-900]="depth % 2 === 0"
852
+ [class.bg-surface-50]="depth % 2 !== 0"
853
+ [class.dark:bg-surface-800]="depth % 2 !== 0"
854
+ >
855
+ <div class="flex items-center gap-3 mb-2">
856
+ <span
857
+ class="node-type"
858
+ [class.group]="node.type === 'group'"
859
+ [class.action]="node.type === 'action'"
860
+ >{{ node.type.toUpperCase() }}</span
861
+ >
862
+
863
+ <div class="flex-1 flex items-center gap-2">
864
+ @if (node.type === 'group') {
865
+ <!-- Group: show operator toggle -->
866
+ <span
867
+ class="operator-badge"
868
+ [class.and]="node.operator === 'AND'"
869
+ [class.or]="node.operator !== 'AND'"
870
+ (click)="toggleOperator(node.id)"
871
+ [fTooltip]="'iam.logic.click.to.toggle' | translate"
872
+ >
873
+ {{ node.operator }}
874
+ </span>
875
+ <span class="text-muted-color text-xs"
876
+ >({{
877
+ 'iam.logic.conditions'
878
+ | translate: { count: node.children?.length || 0 }
879
+ }})</span
880
+ >
881
+ }
882
+
883
+ @if (node.type === 'action') {
884
+ <f-select
885
+ class="flex-1"
886
+ [options]="actions()"
887
+ optionLabel="name"
888
+ optionValue="id"
889
+ [ngModel]="node.actionId"
890
+ (ngModelChange)="updateActionId(node.id, $event)"
891
+ [placeholder]="'iam.logic.select.action' | translate"
892
+ [filter]="true"
893
+ />
894
+ }
895
+ </div>
896
+
897
+ <div class="flex gap-1">
898
+ <button
899
+ fButton
900
+ [text]="true"
901
+ severity="danger"
902
+ size="small"
903
+ (click)="removeNode(node.id)"
904
+ [fTooltip]="'shared.remove' | translate"
905
+ >
906
+ <ui-icon pButtonIcon name="trash"></ui-icon>
907
+ </button>
908
+ </div>
909
+ </div>
910
+
911
+ <!-- Children for group nodes -->
912
+ @if (
913
+ node.type === 'group' && node.children && node.children.length > 0
914
+ ) {
915
+ <div class="ml-5 mt-2 pl-3 border-l-2 border-surface">
916
+ @for (child of node.children; track child.id) {
917
+ <ng-container
918
+ [ngTemplateOutlet]="nodeTemplate"
919
+ [ngTemplateOutletContext]="{ $implicit: child, depth: depth + 1 }"
920
+ ></ng-container>
921
+ }
922
+ </div>
923
+ }
924
+
925
+ <!-- Add child buttons for group nodes -->
926
+ @if (node.type === 'group') {
927
+ <div
928
+ class="mt-3 p-3 bg-surface-50 dark:bg-surface-800 rounded border border-dashed border-surface"
929
+ >
930
+ <div class="text-xs font-semibold text-muted-color mb-2">
931
+ {{ 'iam.logic.add.condition' | translate }}
932
+ </div>
933
+ <div class="flex gap-2 flex-wrap">
934
+ <button
935
+ fButton
936
+ size="small"
937
+ [outlined]="true"
938
+ (click)="addChildNode(node.id, 'group')"
939
+ >
940
+ <ui-icon pButtonIcon name="sitemap"></ui-icon>
941
+ <span pButtonLabel>{{ 'iam.logic.group' | translate }}</span>
942
+ </button>
943
+ <button
944
+ fButton
945
+ size="small"
946
+ severity="success"
947
+ [outlined]="true"
948
+ (click)="addChildNode(node.id, 'action')"
949
+ >
950
+ <ui-icon pButtonIcon name="bolt"></ui-icon>
951
+ <span pButtonLabel>{{ 'iam.logic.action' | translate }}</span>
952
+ </button>
953
+ </div>
954
+ </div>
955
+ }
956
+ </div>
957
+ </ng-template>
958
+ `,
959
+ styles: [":host{display:block}.node-type{display:inline-flex;align-items:center;padding:.25rem .5rem;border-radius:.25rem;font-weight:600;font-size:.75rem;text-transform:uppercase}.node-type.group{background-color:var(--f-blue-100, #dbeafe);color:var(--f-blue-700, #1e40af)}.node-type.action{background-color:var(--f-green-100, #d1fae5);color:var(--f-green-700, #065f46)}:host-context(.app-dark) .node-type.group{background-color:#3b82f633;color:var(--f-blue-400, #60a5fa)}:host-context(.app-dark) .node-type.action{background-color:#22c55e33;color:var(--f-green-400, #4ade80)}.operator-badge{display:inline-flex;align-items:center;padding:.125rem .5rem;border-radius:9999px;font-weight:600;font-size:.75rem;cursor:pointer;transition:opacity .2s}.operator-badge.and{background-color:var(--f-yellow-100, #fef3c7);color:var(--f-yellow-700, #92400e)}.operator-badge.or{background-color:var(--f-indigo-100, #e0e7ff);color:var(--f-indigo-700, #3730a3)}:host-context(.app-dark) .operator-badge.and{background-color:#eab30833;color:var(--f-yellow-400, #facc15)}:host-context(.app-dark) .operator-badge.or{background-color:#6366f133;color:var(--f-indigo-400, #818cf8)}.operator-badge:hover{opacity:.8}.action-select{background-color:var(--f-surface-0, #ffffff);color:var(--f-text-color, #1f2937)}:host-context(.app-dark) .action-select{background-color:var(--f-surface-900, #1f2937);color:var(--f-text-color, #f9fafb)}.action-select:focus{outline:none;border-color:var(--f-primary-color, #3b82f6)}\n"]
960
+ }]
961
+ }],
962
+ ctorParameters: () => [],
963
+ propDecorators: {
964
+ logic: [{
965
+ type: i0.Input,
966
+ args: [{
967
+ isSignal: true,
968
+ alias: "logic",
969
+ required: false
970
+ }]
971
+ }],
972
+ actions: [{
973
+ type: i0.Input,
974
+ args: [{
975
+ isSignal: true,
976
+ alias: "actions",
977
+ required: false
978
+ }]
979
+ }],
980
+ logicChange: [{
981
+ type: i0.Output,
982
+ args: ["logicChange"]
983
+ }]
984
+ }
985
+ });
986
+ var RolePermittedUsersDialogComponent = class RolePermittedUsersDialogComponent {
987
+ USER_ROLE_PERMISSIONS = USER_ROLE_PERMISSIONS;
988
+ permissionApi = inject(PermissionApiService);
989
+ userProvider = inject(USER_PROVIDER);
990
+ scopeResolver = inject(PermissionScopeResolverService);
991
+ confirmationService = inject(ConfirmationService);
992
+ messageService = inject(MessageService);
993
+ translateAdapter = inject(TranslateService, { optional: true });
994
+ t(key, params) {
995
+ return this.translateAdapter?.translate(key, params) ?? key;
996
+ }
997
+ visible = input.required(...ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []);
998
+ role = input.required(...ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []);
999
+ closed = output();
1000
+ isLoading = signal(false, ...ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []);
1001
+ isRemoving = signal(false, ...ngDevMode ? [{ debugName: "isRemoving" }] : /* istanbul ignore next */ []);
1002
+ users = signal([], ...ngDevMode ? [{ debugName: "users" }] : /* istanbul ignore next */ []);
1003
+ showCompanyColumn = signal(false, ...ngDevMode ? [{ debugName: "showCompanyColumn" }] : /* istanbul ignore next */ []);
1004
+ constructor() {
1005
+ effect(() => {
1006
+ if (this.visible() && this.role()) this.loadUsers();
1007
+ });
1008
+ }
1009
+ async loadUsers() {
1010
+ const role = this.role();
1011
+ if (!role) return;
1012
+ this.isLoading.set(true);
1013
+ try {
1014
+ const rows = (await firstValueFrom(this.permissionApi.getRoleUsers(role.id))).data ?? [];
1015
+ const userIds = [...new Set(rows.map((r) => r.userId))];
1016
+ const companyIds = [...new Set(rows.map((r) => r.companyId).filter((id) => !!id))];
1017
+ const branchIds = [...new Set(rows.map((r) => r.branchId).filter((id) => !!id))];
1018
+ const [userInfoMap, companyInfoMap, branchInfoMap] = await Promise.all([
1019
+ this.resolveUserInfo(userIds),
1020
+ this.scopeResolver.resolveCompanyInfo(companyIds),
1021
+ this.scopeResolver.resolveBranchInfo(branchIds)
1022
+ ]);
1023
+ this.showCompanyColumn.set(companyIds.length > 0);
1024
+ this.users.set(rows.map((r) => {
1025
+ const info = userInfoMap.get(r.userId);
1026
+ return {
1027
+ id: r.id,
1028
+ userId: r.userId,
1029
+ userName: info?.name ?? r.userId,
1030
+ userEmail: info?.email ?? "",
1031
+ companyId: r.companyId,
1032
+ companyName: r.companyId ? companyInfoMap.get(r.companyId)?.name ?? r.companyId : null,
1033
+ branchId: r.branchId,
1034
+ branchName: r.branchId ? branchInfoMap.get(r.branchId)?.name ?? r.branchId : null
1035
+ };
1036
+ }));
1037
+ } catch {} finally {
1038
+ this.isLoading.set(false);
1039
+ }
1040
+ }
1041
+ async resolveUserInfo(userIds) {
1042
+ if (userIds.length === 0 || !this.userProvider.getUsersByIds) return /* @__PURE__ */ new Map();
1043
+ try {
1044
+ const response = await firstValueFrom(this.userProvider.getUsersByIds(userIds));
1045
+ return new Map((response.data ?? []).map((u) => [u.id, u]));
1046
+ } catch {
1047
+ return /* @__PURE__ */ new Map();
1048
+ }
1049
+ }
1050
+ onRemove(user) {
1051
+ const role = this.role();
1052
+ if (!role) return;
1053
+ this.confirmationService.confirm({
1054
+ message: this.t("iam.permission.remove.confirm", { name: user.userName }),
1055
+ header: this.t("iam.permission.remove"),
1056
+ icon: "exclamation-triangle",
1057
+ acceptButtonStyleClass: "p-button-danger",
1058
+ accept: async () => {
1059
+ this.isRemoving.set(true);
1060
+ try {
1061
+ const response = await firstValueFrom(this.permissionApi.assignUserRoles({
1062
+ userId: user.userId,
1063
+ companyId: user.companyId ?? void 0,
1064
+ branchId: user.branchId ?? void 0,
1065
+ items: [{
1066
+ id: role.id,
1067
+ action: "remove"
1068
+ }]
1069
+ }));
1070
+ if (response.success) {
1071
+ this.users.update((list) => list.filter((u) => u.id !== user.id));
1072
+ this.messageService.add({
1073
+ severity: "success",
1074
+ summary: this.t("shared.success"),
1075
+ detail: response?.messageKey ? this.t(response.messageKey, response.messageVariables) : response?.message ?? ""
1076
+ });
1077
+ }
1078
+ } catch {} finally {
1079
+ this.isRemoving.set(false);
1080
+ }
1081
+ }
1082
+ });
1083
+ }
1084
+ onClose() {
1085
+ this.closed.emit();
1086
+ }
1087
+ static ɵfac = i0.ɵɵngDeclareFactory({
1088
+ minVersion: "12.0.0",
1089
+ version: "22.2.1",
1090
+ ngImport: i0,
1091
+ type: RolePermittedUsersDialogComponent,
1092
+ deps: [],
1093
+ target: i0.ɵɵFactoryTarget.Component
1094
+ });
1095
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1096
+ minVersion: "17.0.0",
1097
+ version: "22.2.1",
1098
+ type: RolePermittedUsersDialogComponent,
1099
+ isStandalone: true,
1100
+ selector: "flusys-role-permitted-users-dialog",
1101
+ inputs: {
1102
+ visible: {
1103
+ classPropertyName: "visible",
1104
+ publicName: "visible",
1105
+ isSignal: true,
1106
+ isRequired: true,
1107
+ transformFunction: null
1108
+ },
1109
+ role: {
1110
+ classPropertyName: "role",
1111
+ publicName: "role",
1112
+ isSignal: true,
1113
+ isRequired: true,
1114
+ transformFunction: null
1115
+ }
1116
+ },
1117
+ outputs: { closed: "closed" },
1118
+ ngImport: i0,
1119
+ template: `
1120
+ <f-dialog
1121
+ [visible]="visible()"
1122
+ [modal]="true"
1123
+ [closable]="true"
1124
+ [breakpoints]="{ '960px': '90vw', '640px': '95vw' }"
1125
+ [style]="{ width: '50vw', maxWidth: '600px' }"
1126
+ [header]="'iam.permission.view.users' | translate"
1127
+ (onHide)="onClose()"
1128
+ >
1129
+ <div class="mb-4">
1130
+ <p class="text-sm text-muted-color">
1131
+ {{ 'iam.role.name' | translate }}:
1132
+ <strong>{{ role()?.name }}</strong>
1133
+ </p>
1134
+ </div>
1135
+
1136
+ @if (isLoading()) {
1137
+ <div class="flex justify-center items-center py-8">
1138
+ <f-progressspinner />
1139
+ </div>
1140
+ } @else {
1141
+ <div class="flex flex-col gap-3">
1142
+ @for (user of users(); track user.id) {
1143
+ <div
1144
+ class="flex items-center justify-between p-3 border border-surface rounded"
1145
+ >
1146
+ <div>
1147
+ <div class="font-semibold">{{ user.userName }}</div>
1148
+ <div class="text-sm text-muted-color">{{ user.userEmail }}</div>
1149
+ @if (showCompanyColumn() && user.companyName) {
1150
+ <div class="text-xs text-muted-color mt-1">
1151
+ {{ 'iam.company.name' | translate }}: {{ user.companyName }}
1152
+ @if (user.branchName) {
1153
+ · {{ 'iam.branch.name' | translate }}: {{ user.branchName }}
1154
+ } @else {
1155
+ · {{ 'iam.branch.all' | translate }}
1156
+ }
1157
+ </div>
1158
+ }
1159
+ </div>
1160
+ <button
1161
+ fButton
1162
+ *hasPermission="USER_ROLE_PERMISSIONS.ASSIGN"
1163
+ [text]="true"
1164
+ severity="danger"
1165
+ size="small"
1166
+ [disabled]="isRemoving()"
1167
+ [fTooltip]="'shared.remove' | translate"
1168
+ (click)="onRemove(user)"
1169
+ >
1170
+ <ui-icon pButtonIcon name="trash"></ui-icon>
1171
+ </button>
1172
+ </div>
1173
+ } @empty {
1174
+ <div class="text-center py-4 text-muted-color">
1175
+ {{ 'iam.permission.no.users' | translate }}
1176
+ </div>
1177
+ }
1178
+ </div>
1179
+ }
1180
+
1181
+ <ng-template #footer>
1182
+ <button
1183
+ fButton
1184
+ severity="secondary"
1185
+ [outlined]="true"
1186
+ (click)="onClose()"
1187
+ >
1188
+ <span pButtonLabel>{{ 'shared.close' | translate }}</span>
1189
+ </button>
1190
+ </ng-template>
1191
+ </f-dialog>
1192
+ `,
1193
+ isInline: true,
1194
+ dependencies: [
1195
+ {
1196
+ kind: "component",
1197
+ type: DialogComponent,
1198
+ selector: "f-dialog",
1199
+ inputs: [
1200
+ "header",
1201
+ "visible",
1202
+ "modal",
1203
+ "closable",
1204
+ "closeOnEscape",
1205
+ "dismissableMask",
1206
+ "resizable",
1207
+ "draggable",
1208
+ "maximizable",
1209
+ "blockScroll",
1210
+ "returnFocusOnClose",
1211
+ "position",
1212
+ "style",
1213
+ "styleClass",
1214
+ "breakpoints"
1215
+ ],
1216
+ outputs: [
1217
+ "visibleChange",
1218
+ "onShow",
1219
+ "onHide",
1220
+ "onMaximize"
1221
+ ]
1222
+ },
1223
+ {
1224
+ kind: "directive",
1225
+ type: FButtonDirective,
1226
+ selector: "[fButton]",
1227
+ inputs: [
1228
+ "severity",
1229
+ "text",
1230
+ "outlined",
1231
+ "link",
1232
+ "variant",
1233
+ "rounded",
1234
+ "raised",
1235
+ "fluid",
1236
+ "disabled",
1237
+ "loading",
1238
+ "loadingIcon",
1239
+ "size",
1240
+ "label",
1241
+ "icon",
1242
+ "iconPos",
1243
+ "ariaLabel",
1244
+ "plain"
1245
+ ]
1246
+ },
1247
+ {
1248
+ kind: "component",
1249
+ type: ProgressSpinnerComponent,
1250
+ selector: "f-progressspinner",
1251
+ inputs: [
1252
+ "size",
1253
+ "strokeWidth",
1254
+ "animationDuration",
1255
+ "styleClass",
1256
+ "ariaLabel"
1257
+ ]
1258
+ },
1259
+ {
1260
+ kind: "directive",
1261
+ type: TooltipDirective,
1262
+ selector: "[fTooltip]",
1263
+ inputs: [
1264
+ "fTooltip",
1265
+ "tooltipPosition",
1266
+ "positionStyle",
1267
+ "tooltipStyleClass",
1268
+ "disabled",
1269
+ "tooltipEvent",
1270
+ "showDelay",
1271
+ "hideDelay",
1272
+ "life",
1273
+ "autoHide",
1274
+ "positionTop",
1275
+ "positionLeft",
1276
+ "escape"
1277
+ ]
1278
+ },
1279
+ {
1280
+ kind: "component",
1281
+ type: UiIconComponent,
1282
+ selector: "ui-icon",
1283
+ inputs: [
1284
+ "name",
1285
+ "size",
1286
+ "spin",
1287
+ "fill",
1288
+ "severity"
1289
+ ]
1290
+ },
1291
+ {
1292
+ kind: "directive",
1293
+ type: HasPermissionDirective,
1294
+ selector: "[hasPermission]",
1295
+ inputs: ["hasPermission"]
1296
+ },
1297
+ {
1298
+ kind: "pipe",
1299
+ type: TranslatePipe,
1300
+ name: "translate"
1301
+ }
1302
+ ]
1303
+ });
1304
+ };
1305
+ i0.ɵɵngDeclareClassMetadata({
1306
+ minVersion: "12.0.0",
1307
+ version: "22.2.1",
1308
+ ngImport: i0,
1309
+ type: RolePermittedUsersDialogComponent,
1310
+ decorators: [{
1311
+ type: Component,
1312
+ args: [{
1313
+ selector: "flusys-role-permitted-users-dialog",
1314
+ imports: [
1315
+ DialogComponent,
1316
+ FButtonDirective,
1317
+ ProgressSpinnerComponent,
1318
+ TooltipDirective,
1319
+ UiIconComponent,
1320
+ HasPermissionDirective,
1321
+ TranslatePipe
1322
+ ],
1323
+ template: `
1324
+ <f-dialog
1325
+ [visible]="visible()"
1326
+ [modal]="true"
1327
+ [closable]="true"
1328
+ [breakpoints]="{ '960px': '90vw', '640px': '95vw' }"
1329
+ [style]="{ width: '50vw', maxWidth: '600px' }"
1330
+ [header]="'iam.permission.view.users' | translate"
1331
+ (onHide)="onClose()"
1332
+ >
1333
+ <div class="mb-4">
1334
+ <p class="text-sm text-muted-color">
1335
+ {{ 'iam.role.name' | translate }}:
1336
+ <strong>{{ role()?.name }}</strong>
1337
+ </p>
1338
+ </div>
1339
+
1340
+ @if (isLoading()) {
1341
+ <div class="flex justify-center items-center py-8">
1342
+ <f-progressspinner />
1343
+ </div>
1344
+ } @else {
1345
+ <div class="flex flex-col gap-3">
1346
+ @for (user of users(); track user.id) {
1347
+ <div
1348
+ class="flex items-center justify-between p-3 border border-surface rounded"
1349
+ >
1350
+ <div>
1351
+ <div class="font-semibold">{{ user.userName }}</div>
1352
+ <div class="text-sm text-muted-color">{{ user.userEmail }}</div>
1353
+ @if (showCompanyColumn() && user.companyName) {
1354
+ <div class="text-xs text-muted-color mt-1">
1355
+ {{ 'iam.company.name' | translate }}: {{ user.companyName }}
1356
+ @if (user.branchName) {
1357
+ · {{ 'iam.branch.name' | translate }}: {{ user.branchName }}
1358
+ } @else {
1359
+ · {{ 'iam.branch.all' | translate }}
1360
+ }
1361
+ </div>
1362
+ }
1363
+ </div>
1364
+ <button
1365
+ fButton
1366
+ *hasPermission="USER_ROLE_PERMISSIONS.ASSIGN"
1367
+ [text]="true"
1368
+ severity="danger"
1369
+ size="small"
1370
+ [disabled]="isRemoving()"
1371
+ [fTooltip]="'shared.remove' | translate"
1372
+ (click)="onRemove(user)"
1373
+ >
1374
+ <ui-icon pButtonIcon name="trash"></ui-icon>
1375
+ </button>
1376
+ </div>
1377
+ } @empty {
1378
+ <div class="text-center py-4 text-muted-color">
1379
+ {{ 'iam.permission.no.users' | translate }}
1380
+ </div>
1381
+ }
1382
+ </div>
1383
+ }
1384
+
1385
+ <ng-template #footer>
1386
+ <button
1387
+ fButton
1388
+ severity="secondary"
1389
+ [outlined]="true"
1390
+ (click)="onClose()"
1391
+ >
1392
+ <span pButtonLabel>{{ 'shared.close' | translate }}</span>
1393
+ </button>
1394
+ </ng-template>
1395
+ </f-dialog>
1396
+ `
1397
+ }]
1398
+ }],
1399
+ ctorParameters: () => [],
1400
+ propDecorators: {
1401
+ visible: [{
1402
+ type: i0.Input,
1403
+ args: [{
1404
+ isSignal: true,
1405
+ alias: "visible",
1406
+ required: true
1407
+ }]
1408
+ }],
1409
+ role: [{
1410
+ type: i0.Input,
1411
+ args: [{
1412
+ isSignal: true,
1413
+ alias: "role",
1414
+ required: true
1415
+ }]
1416
+ }],
1417
+ closed: [{
1418
+ type: i0.Output,
1419
+ args: ["closed"]
1420
+ }]
1421
+ }
1422
+ });
1423
+ var ActionPermittedUsersDialogComponent = class ActionPermittedUsersDialogComponent {
1424
+ USER_ACTION_PERMISSIONS = USER_ACTION_PERMISSIONS;
1425
+ permissionApi = inject(PermissionApiService);
1426
+ userProvider = inject(USER_PROVIDER);
1427
+ scopeResolver = inject(PermissionScopeResolverService);
1428
+ confirmationService = inject(ConfirmationService);
1429
+ messageService = inject(MessageService);
1430
+ translateAdapter = inject(TranslateService, { optional: true });
1431
+ t(key, params) {
1432
+ return this.translateAdapter?.translate(key, params) ?? key;
1433
+ }
1434
+ visible = input.required(...ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []);
1435
+ action = input.required(...ngDevMode ? [{ debugName: "action" }] : /* istanbul ignore next */ []);
1436
+ closed = output();
1437
+ isLoading = signal(false, ...ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []);
1438
+ isRemoving = signal(false, ...ngDevMode ? [{ debugName: "isRemoving" }] : /* istanbul ignore next */ []);
1439
+ users = signal([], ...ngDevMode ? [{ debugName: "users" }] : /* istanbul ignore next */ []);
1440
+ showCompanyColumn = signal(false, ...ngDevMode ? [{ debugName: "showCompanyColumn" }] : /* istanbul ignore next */ []);
1441
+ constructor() {
1442
+ effect(() => {
1443
+ if (this.visible() && this.action()) this.loadUsers();
1444
+ });
1445
+ }
1446
+ async loadUsers() {
1447
+ const action = this.action();
1448
+ if (!action) return;
1449
+ this.isLoading.set(true);
1450
+ try {
1451
+ const rows = (await firstValueFrom(this.permissionApi.getActionUsers(action.id))).data ?? [];
1452
+ const userIds = [...new Set(rows.map((r) => r.userId))];
1453
+ const companyIds = [...new Set(rows.map((r) => r.companyId).filter((id) => !!id))];
1454
+ const branchIds = [...new Set(rows.map((r) => r.branchId).filter((id) => !!id))];
1455
+ const [userInfoMap, companyInfoMap, branchInfoMap] = await Promise.all([
1456
+ this.resolveUserInfo(userIds),
1457
+ this.scopeResolver.resolveCompanyInfo(companyIds),
1458
+ this.scopeResolver.resolveBranchInfo(branchIds)
1459
+ ]);
1460
+ this.showCompanyColumn.set(companyIds.length > 0);
1461
+ this.users.set(rows.map((r) => {
1462
+ const info = userInfoMap.get(r.userId);
1463
+ return {
1464
+ id: r.id,
1465
+ userId: r.userId,
1466
+ userName: info?.name ?? r.userId,
1467
+ userEmail: info?.email ?? "",
1468
+ companyId: r.companyId,
1469
+ companyName: r.companyId ? companyInfoMap.get(r.companyId)?.name ?? r.companyId : null,
1470
+ branchId: r.branchId,
1471
+ branchName: r.branchId ? branchInfoMap.get(r.branchId)?.name ?? r.branchId : null
1472
+ };
1473
+ }));
1474
+ } catch {} finally {
1475
+ this.isLoading.set(false);
1476
+ }
1477
+ }
1478
+ async resolveUserInfo(userIds) {
1479
+ if (userIds.length === 0 || !this.userProvider.getUsersByIds) return /* @__PURE__ */ new Map();
1480
+ try {
1481
+ const response = await firstValueFrom(this.userProvider.getUsersByIds(userIds));
1482
+ return new Map((response.data ?? []).map((u) => [u.id, u]));
1483
+ } catch {
1484
+ return /* @__PURE__ */ new Map();
1485
+ }
1486
+ }
1487
+ onRemove(user) {
1488
+ const action = this.action();
1489
+ if (!action) return;
1490
+ this.confirmationService.confirm({
1491
+ message: this.t("iam.permission.remove.confirm", { name: user.userName }),
1492
+ header: this.t("iam.permission.remove"),
1493
+ icon: "exclamation-triangle",
1494
+ acceptButtonStyleClass: "p-button-danger",
1495
+ accept: async () => {
1496
+ this.isRemoving.set(true);
1497
+ try {
1498
+ const response = await firstValueFrom(this.permissionApi.assignUserActions({
1499
+ userId: user.userId,
1500
+ companyId: user.companyId ?? void 0,
1501
+ branchId: user.branchId ?? void 0,
1502
+ items: [{
1503
+ id: action.id,
1504
+ action: "remove"
1505
+ }]
1506
+ }));
1507
+ if (response.success) {
1508
+ this.users.update((list) => list.filter((u) => u.id !== user.id));
1509
+ this.messageService.add({
1510
+ severity: "success",
1511
+ summary: this.t("shared.success"),
1512
+ detail: response?.messageKey ? this.t(response.messageKey, response.messageVariables) : response?.message ?? ""
1513
+ });
1514
+ }
1515
+ } catch {} finally {
1516
+ this.isRemoving.set(false);
1517
+ }
1518
+ }
1519
+ });
1520
+ }
1521
+ onClose() {
1522
+ this.closed.emit();
1523
+ }
1524
+ static ɵfac = i0.ɵɵngDeclareFactory({
1525
+ minVersion: "12.0.0",
1526
+ version: "22.2.1",
1527
+ ngImport: i0,
1528
+ type: ActionPermittedUsersDialogComponent,
1529
+ deps: [],
1530
+ target: i0.ɵɵFactoryTarget.Component
1531
+ });
1532
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1533
+ minVersion: "17.0.0",
1534
+ version: "22.2.1",
1535
+ type: ActionPermittedUsersDialogComponent,
1536
+ isStandalone: true,
1537
+ selector: "flusys-action-permitted-users-dialog",
1538
+ inputs: {
1539
+ visible: {
1540
+ classPropertyName: "visible",
1541
+ publicName: "visible",
1542
+ isSignal: true,
1543
+ isRequired: true,
1544
+ transformFunction: null
1545
+ },
1546
+ action: {
1547
+ classPropertyName: "action",
1548
+ publicName: "action",
1549
+ isSignal: true,
1550
+ isRequired: true,
1551
+ transformFunction: null
1552
+ }
1553
+ },
1554
+ outputs: { closed: "closed" },
1555
+ ngImport: i0,
1556
+ template: `
1557
+ <f-dialog
1558
+ [visible]="visible()"
1559
+ [modal]="true"
1560
+ [closable]="true"
1561
+ [breakpoints]="{ '960px': '90vw', '640px': '95vw' }"
1562
+ [style]="{ width: '50vw', maxWidth: '600px' }"
1563
+ [header]="'iam.permission.view.users' | translate"
1564
+ (onHide)="onClose()"
1565
+ >
1566
+ <div class="mb-4">
1567
+ <p class="text-sm text-muted-color">
1568
+ {{ 'iam.action.name' | translate }}:
1569
+ <strong>{{ action()?.name }}</strong>
1570
+ </p>
1571
+ </div>
1572
+
1573
+ @if (isLoading()) {
1574
+ <div class="flex justify-center items-center py-8">
1575
+ <f-progressspinner />
1576
+ </div>
1577
+ } @else {
1578
+ <div class="flex flex-col gap-3">
1579
+ @for (user of users(); track user.id) {
1580
+ <div
1581
+ class="flex items-center justify-between p-3 border border-surface rounded"
1582
+ >
1583
+ <div>
1584
+ <div class="font-semibold">{{ user.userName }}</div>
1585
+ <div class="text-sm text-muted-color">{{ user.userEmail }}</div>
1586
+ @if (showCompanyColumn() && user.companyName) {
1587
+ <div class="text-xs text-muted-color mt-1">
1588
+ {{ 'iam.company.name' | translate }}: {{ user.companyName }}
1589
+ @if (user.branchName) {
1590
+ · {{ 'iam.branch.name' | translate }}: {{ user.branchName }}
1591
+ } @else {
1592
+ · {{ 'iam.branch.all' | translate }}
1593
+ }
1594
+ </div>
1595
+ }
1596
+ </div>
1597
+ <button
1598
+ fButton
1599
+ *hasPermission="USER_ACTION_PERMISSIONS.ASSIGN"
1600
+ [text]="true"
1601
+ severity="danger"
1602
+ size="small"
1603
+ [disabled]="isRemoving()"
1604
+ [fTooltip]="'shared.remove' | translate"
1605
+ (click)="onRemove(user)"
1606
+ >
1607
+ <ui-icon pButtonIcon name="trash"></ui-icon>
1608
+ </button>
1609
+ </div>
1610
+ } @empty {
1611
+ <div class="text-center py-4 text-muted-color">
1612
+ {{ 'iam.permission.no.users' | translate }}
1613
+ </div>
1614
+ }
1615
+ </div>
1616
+ }
1617
+
1618
+ <ng-template #footer>
1619
+ <button
1620
+ fButton
1621
+ severity="secondary"
1622
+ [outlined]="true"
1623
+ (click)="onClose()"
1624
+ >
1625
+ <span pButtonLabel>{{ 'shared.close' | translate }}</span>
1626
+ </button>
1627
+ </ng-template>
1628
+ </f-dialog>
1629
+ `,
1630
+ isInline: true,
1631
+ dependencies: [
1632
+ {
1633
+ kind: "component",
1634
+ type: DialogComponent,
1635
+ selector: "f-dialog",
1636
+ inputs: [
1637
+ "header",
1638
+ "visible",
1639
+ "modal",
1640
+ "closable",
1641
+ "closeOnEscape",
1642
+ "dismissableMask",
1643
+ "resizable",
1644
+ "draggable",
1645
+ "maximizable",
1646
+ "blockScroll",
1647
+ "returnFocusOnClose",
1648
+ "position",
1649
+ "style",
1650
+ "styleClass",
1651
+ "breakpoints"
1652
+ ],
1653
+ outputs: [
1654
+ "visibleChange",
1655
+ "onShow",
1656
+ "onHide",
1657
+ "onMaximize"
1658
+ ]
1659
+ },
1660
+ {
1661
+ kind: "directive",
1662
+ type: FButtonDirective,
1663
+ selector: "[fButton]",
1664
+ inputs: [
1665
+ "severity",
1666
+ "text",
1667
+ "outlined",
1668
+ "link",
1669
+ "variant",
1670
+ "rounded",
1671
+ "raised",
1672
+ "fluid",
1673
+ "disabled",
1674
+ "loading",
1675
+ "loadingIcon",
1676
+ "size",
1677
+ "label",
1678
+ "icon",
1679
+ "iconPos",
1680
+ "ariaLabel",
1681
+ "plain"
1682
+ ]
1683
+ },
1684
+ {
1685
+ kind: "component",
1686
+ type: ProgressSpinnerComponent,
1687
+ selector: "f-progressspinner",
1688
+ inputs: [
1689
+ "size",
1690
+ "strokeWidth",
1691
+ "animationDuration",
1692
+ "styleClass",
1693
+ "ariaLabel"
1694
+ ]
1695
+ },
1696
+ {
1697
+ kind: "directive",
1698
+ type: TooltipDirective,
1699
+ selector: "[fTooltip]",
1700
+ inputs: [
1701
+ "fTooltip",
1702
+ "tooltipPosition",
1703
+ "positionStyle",
1704
+ "tooltipStyleClass",
1705
+ "disabled",
1706
+ "tooltipEvent",
1707
+ "showDelay",
1708
+ "hideDelay",
1709
+ "life",
1710
+ "autoHide",
1711
+ "positionTop",
1712
+ "positionLeft",
1713
+ "escape"
1714
+ ]
1715
+ },
1716
+ {
1717
+ kind: "component",
1718
+ type: UiIconComponent,
1719
+ selector: "ui-icon",
1720
+ inputs: [
1721
+ "name",
1722
+ "size",
1723
+ "spin",
1724
+ "fill",
1725
+ "severity"
1726
+ ]
1727
+ },
1728
+ {
1729
+ kind: "directive",
1730
+ type: HasPermissionDirective,
1731
+ selector: "[hasPermission]",
1732
+ inputs: ["hasPermission"]
1733
+ },
1734
+ {
1735
+ kind: "pipe",
1736
+ type: TranslatePipe,
1737
+ name: "translate"
1738
+ }
1739
+ ]
1740
+ });
1741
+ };
1742
+ i0.ɵɵngDeclareClassMetadata({
1743
+ minVersion: "12.0.0",
1744
+ version: "22.2.1",
1745
+ ngImport: i0,
1746
+ type: ActionPermittedUsersDialogComponent,
1747
+ decorators: [{
1748
+ type: Component,
1749
+ args: [{
1750
+ selector: "flusys-action-permitted-users-dialog",
1751
+ imports: [
1752
+ DialogComponent,
1753
+ FButtonDirective,
1754
+ ProgressSpinnerComponent,
1755
+ TooltipDirective,
1756
+ UiIconComponent,
1757
+ HasPermissionDirective,
1758
+ TranslatePipe
1759
+ ],
1760
+ template: `
1761
+ <f-dialog
1762
+ [visible]="visible()"
1763
+ [modal]="true"
1764
+ [closable]="true"
1765
+ [breakpoints]="{ '960px': '90vw', '640px': '95vw' }"
1766
+ [style]="{ width: '50vw', maxWidth: '600px' }"
1767
+ [header]="'iam.permission.view.users' | translate"
1768
+ (onHide)="onClose()"
1769
+ >
1770
+ <div class="mb-4">
1771
+ <p class="text-sm text-muted-color">
1772
+ {{ 'iam.action.name' | translate }}:
1773
+ <strong>{{ action()?.name }}</strong>
1774
+ </p>
1775
+ </div>
1776
+
1777
+ @if (isLoading()) {
1778
+ <div class="flex justify-center items-center py-8">
1779
+ <f-progressspinner />
1780
+ </div>
1781
+ } @else {
1782
+ <div class="flex flex-col gap-3">
1783
+ @for (user of users(); track user.id) {
1784
+ <div
1785
+ class="flex items-center justify-between p-3 border border-surface rounded"
1786
+ >
1787
+ <div>
1788
+ <div class="font-semibold">{{ user.userName }}</div>
1789
+ <div class="text-sm text-muted-color">{{ user.userEmail }}</div>
1790
+ @if (showCompanyColumn() && user.companyName) {
1791
+ <div class="text-xs text-muted-color mt-1">
1792
+ {{ 'iam.company.name' | translate }}: {{ user.companyName }}
1793
+ @if (user.branchName) {
1794
+ · {{ 'iam.branch.name' | translate }}: {{ user.branchName }}
1795
+ } @else {
1796
+ · {{ 'iam.branch.all' | translate }}
1797
+ }
1798
+ </div>
1799
+ }
1800
+ </div>
1801
+ <button
1802
+ fButton
1803
+ *hasPermission="USER_ACTION_PERMISSIONS.ASSIGN"
1804
+ [text]="true"
1805
+ severity="danger"
1806
+ size="small"
1807
+ [disabled]="isRemoving()"
1808
+ [fTooltip]="'shared.remove' | translate"
1809
+ (click)="onRemove(user)"
1810
+ >
1811
+ <ui-icon pButtonIcon name="trash"></ui-icon>
1812
+ </button>
1813
+ </div>
1814
+ } @empty {
1815
+ <div class="text-center py-4 text-muted-color">
1816
+ {{ 'iam.permission.no.users' | translate }}
1817
+ </div>
1818
+ }
1819
+ </div>
1820
+ }
1821
+
1822
+ <ng-template #footer>
1823
+ <button
1824
+ fButton
1825
+ severity="secondary"
1826
+ [outlined]="true"
1827
+ (click)="onClose()"
1828
+ >
1829
+ <span pButtonLabel>{{ 'shared.close' | translate }}</span>
1830
+ </button>
1831
+ </ng-template>
1832
+ </f-dialog>
1833
+ `
1834
+ }]
1835
+ }],
1836
+ ctorParameters: () => [],
1837
+ propDecorators: {
1838
+ visible: [{
1839
+ type: i0.Input,
1840
+ args: [{
1841
+ isSignal: true,
1842
+ alias: "visible",
1843
+ required: true
1844
+ }]
1845
+ }],
1846
+ action: [{
1847
+ type: i0.Input,
1848
+ args: [{
1849
+ isSignal: true,
1850
+ alias: "action",
1851
+ required: true
1852
+ }]
1853
+ }],
1854
+ closed: [{
1855
+ type: i0.Output,
1856
+ args: ["closed"]
1857
+ }]
1858
+ }
1859
+ });
1860
+ function flatten(nodes) {
1861
+ return nodes.flatMap(({ children, ...action }) => [action, ...flatten(children ?? [])]);
1862
+ }
1863
+ var ActionProviderAdapter = class ActionProviderAdapter {
1864
+ actionApi = inject(ActionApiService);
1865
+ appConfig = inject(APP_CONFIG);
1866
+ isAvailable() {
1867
+ return isServiceEnabled(this.appConfig, "iam");
1868
+ }
1869
+ getActions(scope = "company") {
1870
+ return (scope === "all" ? this.actionApi.getTree(void 0, true).pipe(map((response) => ({
1871
+ ...response,
1872
+ data: flatten(response.data ?? [])
1873
+ }))) : this.actionApi.getActionsForPermission()).pipe(map((response) => ({
1874
+ success: response.success,
1875
+ message: response.message,
1876
+ data: (response.data ?? []).filter((action) => action.isActive).map((action) => ({
1877
+ id: action.id,
1878
+ name: action.name,
1879
+ code: action.code,
1880
+ description: action.description,
1881
+ parentId: action.parentId,
1882
+ serial: action.serial
1883
+ }))
1884
+ })));
1885
+ }
1886
+ static ɵfac = i0.ɵɵngDeclareFactory({
1887
+ minVersion: "12.0.0",
1888
+ version: "22.2.1",
1889
+ ngImport: i0,
1890
+ type: ActionProviderAdapter,
1891
+ deps: [],
1892
+ target: i0.ɵɵFactoryTarget.Service
1893
+ });
1894
+ static ɵprov = i0.ɵɵngDeclareService({
1895
+ minVersion: "22.0.0",
1896
+ version: "22.2.1",
1897
+ ngImport: i0,
1898
+ type: ActionProviderAdapter,
1899
+ autoProvided: false
1900
+ });
1901
+ };
1902
+ i0.ɵɵngDeclareClassMetadata({
1903
+ minVersion: "12.0.0",
1904
+ version: "22.2.1",
1905
+ ngImport: i0,
1906
+ type: ActionProviderAdapter,
1907
+ decorators: [{
1908
+ type: Service,
1909
+ args: [{ autoProvided: false }]
1910
+ }]
1911
+ });
1912
+ var ProfilePermissionProviderAdapter = class ProfilePermissionProviderAdapter {
1913
+ permissionApi = inject(PermissionApiService);
1914
+ getUserRoles() {
1915
+ return this.permissionApi.getMyRoles().pipe(map((response) => ({
1916
+ success: response.success,
1917
+ message: response.message,
1918
+ data: (response.data ?? []).map((role) => ({
1919
+ id: role.roleId,
1920
+ name: role.roleName,
1921
+ description: null
1922
+ }))
1923
+ })));
1924
+ }
1925
+ getUserActions() {
1926
+ return this.permissionApi.getMyActions().pipe(map((response) => ({
1927
+ success: response.success,
1928
+ message: response.message,
1929
+ data: (response.data ?? []).map((action) => ({
1930
+ id: action.actionId,
1931
+ name: action.actionName,
1932
+ code: action.actionCode,
1933
+ description: null
1934
+ }))
1935
+ })));
1936
+ }
1937
+ static ɵfac = i0.ɵɵngDeclareFactory({
1938
+ minVersion: "12.0.0",
1939
+ version: "22.2.1",
1940
+ ngImport: i0,
1941
+ type: ProfilePermissionProviderAdapter,
1942
+ deps: [],
1943
+ target: i0.ɵɵFactoryTarget.Service
1944
+ });
1945
+ static ɵprov = i0.ɵɵngDeclareService({
1946
+ minVersion: "22.0.0",
1947
+ version: "22.2.1",
1948
+ ngImport: i0,
1949
+ type: ProfilePermissionProviderAdapter,
1950
+ autoProvided: false
1951
+ });
1952
+ };
1953
+ i0.ɵɵngDeclareClassMetadata({
1954
+ minVersion: "12.0.0",
1955
+ version: "22.2.1",
1956
+ ngImport: i0,
1957
+ type: ProfilePermissionProviderAdapter,
1958
+ decorators: [{
1959
+ type: Service,
1960
+ args: [{ autoProvided: false }]
1961
+ }]
1962
+ });
1963
+ function provideIamProviders() {
1964
+ return [{
1965
+ provide: PROFILE_PERMISSION_PROVIDER,
1966
+ useClass: ProfilePermissionProviderAdapter
1967
+ }, {
1968
+ provide: ACTION_PROVIDER,
1969
+ useClass: ActionProviderAdapter
1970
+ }];
1971
+ }
1972
+ function resolveIamDefaultTab() {
1973
+ const permissionValidator = inject(PermissionValidatorService);
1974
+ const permissionMode = getPermissionMode(inject(APP_CONFIG));
1975
+ if (permissionValidator.hasPermission(ACTION_PERMISSIONS.READ)) return "actions";
1976
+ if (permissionValidator.hasPermission(ROLE_PERMISSIONS.READ) && (permissionMode === "rbac" || permissionMode === "full")) return "roles";
1977
+ if (permissionValidator.hasAnyPermission([
1978
+ ROLE_ACTION_PERMISSIONS.READ,
1979
+ USER_ROLE_PERMISSIONS.READ,
1980
+ USER_ACTION_PERMISSIONS.READ,
1981
+ COMPANY_ACTION_PERMISSIONS.READ
1982
+ ])) return "permissions";
1983
+ return "actions";
1984
+ }
1985
+ const IAM_ROUTES = [{
1986
+ path: "",
1987
+ resolve: { translations: resolveTranslationModule({
1988
+ modules: ["iam"],
1989
+ fallbackMessages: {
1990
+ ...IAM_MESSAGES,
1991
+ ...SHARED_MESSAGES
1992
+ }
1993
+ }) },
1994
+ loadComponent: () => import("./flusys-ng-iam-iam-container.component-CIdxVCSW.mjs").then((m) => m.IamContainerComponent),
1995
+ children: [
1996
+ {
1997
+ path: "actions",
1998
+ canActivate: [permissionGuard(ACTION_PERMISSIONS.READ)],
1999
+ children: [
2000
+ {
2001
+ path: "",
2002
+ loadComponent: () => import("./flusys-ng-iam-action-list-page.component-Br0PbgRa.mjs").then((m) => m.ActionListPageComponent)
2003
+ },
2004
+ {
2005
+ path: "new",
2006
+ loadComponent: () => import("./flusys-ng-iam-action-form-page.component-DJ-A1gc2.mjs").then((m) => m.ActionFormPageComponent)
2007
+ },
2008
+ {
2009
+ path: ":id",
2010
+ loadComponent: () => import("./flusys-ng-iam-action-form-page.component-DJ-A1gc2.mjs").then((m) => m.ActionFormPageComponent)
2011
+ }
2012
+ ]
2013
+ },
2014
+ {
2015
+ path: "roles",
2016
+ canActivate: [permissionGuard(ROLE_PERMISSIONS.READ)],
2017
+ children: [
2018
+ {
2019
+ path: "",
2020
+ loadComponent: () => import("./flusys-ng-iam-role-list-page.component-BCO_gQ8k.mjs").then((m) => m.RoleListPageComponent)
2021
+ },
2022
+ {
2023
+ path: "new",
2024
+ loadComponent: () => import("./flusys-ng-iam-role-form-page.component-DnkWkbTF.mjs").then((m) => m.RoleFormPageComponent)
2025
+ },
2026
+ {
2027
+ path: ":id",
2028
+ loadComponent: () => import("./flusys-ng-iam-role-form-page.component-DnkWkbTF.mjs").then((m) => m.RoleFormPageComponent)
2029
+ }
2030
+ ]
2031
+ },
2032
+ {
2033
+ path: "permissions",
2034
+ canActivate: [anyPermissionGuard([
2035
+ ROLE_ACTION_PERMISSIONS.READ,
2036
+ USER_ROLE_PERMISSIONS.READ,
2037
+ USER_ACTION_PERMISSIONS.READ,
2038
+ COMPANY_ACTION_PERMISSIONS.READ
2039
+ ])],
2040
+ loadComponent: () => import("./flusys-ng-iam-permission-page.component-BlNt83uR.mjs").then((m) => m.PermissionPageComponent)
2041
+ },
2042
+ {
2043
+ path: "",
2044
+ redirectTo: () => resolveIamDefaultTab(),
2045
+ pathMatch: "full"
2046
+ }
2047
+ ]
2048
+ }];
2049
+ export { ActionApiService, ActionPermissionLogicService, ActionPermittedUsersDialogComponent, ActionProviderAdapter, ActionType, CompanyActionSelectorComponent, IAM_MESSAGES, IAM_ROUTES, LogicBuilderComponent, MAX_DROPDOWN_ITEMS, MyPermissionsApiService, PermissionApiService, PermissionScopeResolverService, PermissionStateService, ProfilePermissionProviderAdapter, RoleActionSelectorComponent, RoleApiService, RolePermittedUsersDialogComponent, UserActionSelectorComponent, UserRoleSelectorComponent, provideIamProviders };
2050
+
2051
+ //# sourceMappingURL=flusys-ng-iam.mjs.map