@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.
- package/fesm2022/flusys-ng-iam-action-form-page.component-DJ-A1gc2.mjs +685 -0
- package/fesm2022/flusys-ng-iam-action-form-page.component-DJ-A1gc2.mjs.map +1 -0
- package/fesm2022/{flusys-ng-iam-action-list-page.component-Cf4Dhh5S.mjs → flusys-ng-iam-action-list-page.component-Br0PbgRa.mjs} +369 -166
- package/fesm2022/flusys-ng-iam-action-list-page.component-Br0PbgRa.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-iam-container.component-CIdxVCSW.mjs +141 -0
- package/fesm2022/flusys-ng-iam-iam-container.component-CIdxVCSW.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-permission-api.service-C7-Yxvz8.mjs +76 -0
- package/fesm2022/flusys-ng-iam-permission-api.service-C7-Yxvz8.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-permission-page.component-BlNt83uR.mjs +306 -0
- package/fesm2022/flusys-ng-iam-permission-page.component-BlNt83uR.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-role-api.service-OwPgmSFc.mjs +33 -0
- package/fesm2022/flusys-ng-iam-role-api.service-OwPgmSFc.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-role-form-page.component-DnkWkbTF.mjs +427 -0
- package/fesm2022/flusys-ng-iam-role-form-page.component-DnkWkbTF.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-role-list-page.component-BCO_gQ8k.mjs +685 -0
- package/fesm2022/flusys-ng-iam-role-list-page.component-BCO_gQ8k.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-tree-utils-B1pBG4At.mjs +110 -0
- package/fesm2022/flusys-ng-iam-tree-utils-B1pBG4At.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam-user-action-selector.component-CAXEmJWx.mjs +4592 -0
- package/fesm2022/flusys-ng-iam-user-action-selector.component-CAXEmJWx.mjs.map +1 -0
- package/fesm2022/flusys-ng-iam.mjs +2051 -2
- package/fesm2022/flusys-ng-iam.mjs.map +1 -1
- package/package.json +5 -5
- package/types/flusys-ng-iam.d.ts +621 -604
- package/fesm2022/flusys-ng-iam-action-form-page.component-Dn0TD1Zu.mjs +0 -509
- package/fesm2022/flusys-ng-iam-action-form-page.component-Dn0TD1Zu.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-action-list-page.component-Cf4Dhh5S.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-Y7U2lGZk.mjs +0 -5584
- package/fesm2022/flusys-ng-iam-flusys-ng-iam-Y7U2lGZk.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-iam-container.component-XBoIeQ0t.mjs +0 -105
- package/fesm2022/flusys-ng-iam-iam-container.component-XBoIeQ0t.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-permission-page.component-CCAQuZSJ.mjs +0 -204
- package/fesm2022/flusys-ng-iam-permission-page.component-CCAQuZSJ.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-form-page.component-EFjxhBRY.mjs +0 -352
- package/fesm2022/flusys-ng-iam-role-form-page.component-EFjxhBRY.mjs.map +0 -1
- package/fesm2022/flusys-ng-iam-role-list-page.component-DBfhjdkM.mjs +0 -486
- package/fesm2022/flusys-ng-iam-role-list-page.component-DBfhjdkM.mjs.map +0 -1
|
@@ -1,2 +1,2051 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|