@flusys/ng-iam 9.1.0-rc.1 → 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flusys-ng-iam-user-action-selector.component-CAXEmJWx.mjs","names":[],"sources":["../../../projects/ng-iam/constants/pagination.constants.ts","../../../projects/ng-iam/utils/permission-logic.util.ts","../../../projects/ng-iam/services/action-permission-logic.service.ts","../../../projects/ng-iam/components/base-action-selector.ts","../../../projects/ng-iam/components/role-action-selector.component.ts","../../../projects/ng-iam/components/company-action-selector.component.ts","../../../projects/ng-iam/utils/user-branch.util.ts","../../../projects/ng-iam/components/user-role-selector.component.ts","../../../projects/ng-iam/components/user-action-selector.component.ts"],"sourcesContent":["/** Maximum items for dropdown lists (companies, roles, users, branches) */\nexport const MAX_DROPDOWN_ITEMS = 100;\n","import { ILogicNode } from '@flusys/ng-shared';\nimport { IAction } from '../interfaces/action.interface';\n\nexport interface IPrerequisiteValidationResult {\n valid: boolean;\n missingActions: IAction[];\n}\n\nexport function extractRequiredActionIds(logic: ILogicNode | null): Set<string> {\n const actionIds = new Set<string>();\n if (logic) {\n collectActionIds(logic, actionIds);\n }\n return actionIds;\n}\n\nfunction collectActionIds(node: ILogicNode, actionIds: Set<string>): void {\n if (node.type === 'action' && node.actionId) {\n actionIds.add(node.actionId);\n } else if (node.type === 'group' && node.children) {\n node.children.forEach((child) => collectActionIds(child, actionIds));\n }\n}\n\nexport function validateActionPrerequisites(\n action: IAction,\n selectedActionIds: Set<string>,\n allActions: IAction[],\n): IPrerequisiteValidationResult {\n if (!action.permissionLogic) {\n return { valid: true, missingActions: [] };\n }\n\n const result = evaluateLogicNodeWithMissing(action.permissionLogic, selectedActionIds);\n if (result.valid) {\n return { valid: true, missingActions: [] };\n }\n\n const missingActions = allActions.filter((a) => a.id && result.missingActionIds.has(a.id));\n return { valid: false, missingActions };\n}\n\nfunction evaluateLogicNodeWithMissing(\n node: ILogicNode,\n selectedActionIds: Set<string>,\n): { valid: boolean; missingActionIds: Set<string> } {\n if (node.type === 'action' && node.actionId) {\n const valid = selectedActionIds.has(node.actionId);\n return { valid, missingActionIds: valid ? new Set() : new Set([node.actionId]) };\n }\n\n if (node.type === 'group' && node.children?.length) {\n const operator = node.operator || 'AND';\n\n if (operator === 'AND') {\n const missingIds = new Set<string>();\n let allValid = true;\n for (const child of node.children) {\n const childResult = evaluateLogicNodeWithMissing(child, selectedActionIds);\n if (!childResult.valid) {\n allValid = false;\n childResult.missingActionIds.forEach((id) => missingIds.add(id));\n }\n }\n return { valid: allValid, missingActionIds: missingIds };\n }\n\n // OR operator\n for (const child of node.children) {\n const childResult = evaluateLogicNodeWithMissing(child, selectedActionIds);\n if (childResult.valid) {\n return { valid: true, missingActionIds: new Set() };\n }\n }\n const firstChildResult = evaluateLogicNodeWithMissing(node.children[0], selectedActionIds);\n return { valid: false, missingActionIds: firstChildResult.missingActionIds };\n }\n\n return { valid: true, missingActionIds: new Set() };\n}\n","import { inject, Service } from '@angular/core';\nimport { ILogicNode, TranslateService } from '@flusys/ng-shared';\nimport { ConfirmationService, MessageService } from '@flusys/ng-ui';\nimport { IAction } from '../interfaces/action.interface';\nimport { validateActionPrerequisites } from '../utils/permission-logic.util';\n\n/** Shared service for smart dependency management across action selectors */\n@Service()\nexport class ActionPermissionLogicService {\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private t(key: string, variables?: Record<string, string | number>): string {\n return this.translateAdapter?.translate(key, variables) ?? key;\n }\n\n /** Handle checking an action with prerequisite validation (recursive deep scan) */\n handleCheck(\n action: IAction,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n onUpdate: (newSelection: Record<string, boolean>) => void,\n onCancel: (previousState: Record<string, boolean>) => void,\n ): void {\n // Validate prerequisites with RECURSIVE DEEP SCAN\n if (action.permissionLogic) {\n const selectedActionIds = this.getSelectedIds(currentSelection);\n\n const validationResult = validateActionPrerequisites(\n action,\n selectedActionIds,\n allActions,\n );\n\n if (!validationResult.valid) {\n // Store previous state\n const previousState = { ...currentSelection };\n\n // Temporarily check the box\n const tempMap = { ...currentSelection };\n tempMap[action.id as string] = true;\n onUpdate(tempMap);\n\n // CRITICAL: Recursively collect ALL missing prerequisites (deep scan)\n const allMissingActions = this.getAllMissingPrerequisitesRecursive(\n action,\n currentSelection,\n allActions,\n );\n\n // Show prerequisite dialog with COMPLETE dependency chain\n this.showPrerequisiteDialog(\n action,\n allMissingActions,\n currentSelection,\n allActions,\n previousState,\n onUpdate,\n onCancel,\n );\n return;\n }\n }\n\n // All prerequisites satisfied, allow selection\n const selMap = { ...currentSelection };\n selMap[action.id as string] = true;\n onUpdate(selMap);\n }\n\n /** Handle unchecking an action with dependency detection */\n handleUncheck(\n action: IAction,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n onUpdate: (newSelection: Record<string, boolean>) => void,\n ): void {\n const affectedActions = this.findActionsDependingOn(\n action.id as string,\n currentSelection,\n allActions,\n );\n\n if (affectedActions.length > 0) {\n this.showDependencyDialog(\n action,\n affectedActions,\n currentSelection,\n allActions,\n onUpdate,\n );\n return;\n }\n\n // No dependencies, safe to uncheck\n const selMap = { ...currentSelection };\n selMap[action.id as string] = false;\n onUpdate(selMap);\n }\n\n /** Check if an action has unmet prerequisites */\n hasUnmetPrerequisites(\n action: IAction,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n ): boolean {\n const isSelected = currentSelection[action.id as string];\n\n if (!isSelected || !action.permissionLogic) {\n return false;\n }\n\n const selectedActionIds = this.getSelectedIds(currentSelection);\n selectedActionIds.delete(action.id as string);\n\n const validationResult = validateActionPrerequisites(\n action,\n selectedActionIds,\n allActions,\n );\n\n return !validationResult.valid;\n }\n\n /** Get all selected actions that have unmet prerequisites */\n getActionsWithUnmetPrerequisites(\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n ): IAction[] {\n const selectedActions = allActions.filter(\n (a) => currentSelection[a.id as string],\n );\n\n return selectedActions.filter((action) =>\n this.hasUnmetPrerequisites(action, currentSelection, allActions),\n );\n }\n\n /** Show validation error dialog with auto-fix options */\n showValidationErrorDialog(\n invalidActions: IAction[],\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n onUpdate: (newSelection: Record<string, boolean>) => void,\n ): void {\n const errorList = invalidActions\n .map((action) => {\n const selectedActionIds = this.getSelectedIds(currentSelection);\n selectedActionIds.delete(action.id as string);\n\n const validationResult = validateActionPrerequisites(\n action,\n selectedActionIds,\n allActions,\n );\n\n const sanitizedActionName = this.sanitizeHtml(\n action.name ?? this.t('iam.logic.unknown.action'),\n );\n const missingNames = validationResult.missingActions\n .map((a) =>\n this.sanitizeHtml(a.name ?? this.t('iam.logic.unknown.action')),\n )\n .join(', ');\n return `<li><strong>${sanitizedActionName}</strong> requires: ${missingNames}</li>`;\n })\n .join('');\n\n this.confirmationService.confirm({\n header: this.t('iam.logic.validation.failed'),\n message: `${this.t('iam.logic.validation.failed.message')}<br/><br/><ul class=\"pl-4\">${errorList}</ul><br/>${this.t('iam.logic.validation.failed.prompt')}`,\n icon: 'exclamation-triangle',\n acceptLabel: this.t('iam.logic.auto.fix'),\n rejectLabel: this.t('shared.cancel'),\n acceptIcon: 'trash',\n rejectIcon: 'times',\n acceptButtonStyleClass: 'p-button-warning',\n closeOnEscape: false,\n closable: false,\n accept: () => {\n // Remove all invalid actions\n const selMap = { ...currentSelection };\n invalidActions.forEach((action) => {\n selMap[action.id as string] = false;\n });\n onUpdate(selMap);\n\n this.messageService.add({\n severity: 'warn',\n summary: this.t('iam.logic.invalid.actions.removed'),\n detail: this.t('iam.logic.removed.actions.detail', {\n count: invalidActions.length,\n }),\n });\n },\n reject: () => {\n this.messageService.add({\n severity: 'info',\n summary: this.t('iam.logic.save.cancelled'),\n detail: this.t('iam.logic.fix.prerequisites.manually'),\n });\n },\n });\n }\n\n /** Get prerequisite description for tooltip display */\n getPrerequisiteTooltip(\n action: IAction,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n ): string {\n if (!action.permissionLogic) {\n return '';\n }\n\n const selectedActionIds = this.getSelectedIds(currentSelection);\n\n const validationResult = validateActionPrerequisites(\n action,\n selectedActionIds,\n allActions,\n );\n\n if (validationResult.valid) {\n return `${this.t('iam.logic.prerequisites.satisfied')}\\n\\n${this.t('iam.logic.all.required.selected')}`;\n }\n\n const allMissingActions = this.getAllMissingPrerequisitesRecursive(\n action,\n currentSelection,\n allActions,\n );\n\n const logicTree = this.buildTooltipLogicTree(\n action.permissionLogic,\n currentSelection,\n allActions,\n 0,\n );\n\n const missingCount = allMissingActions.length;\n const header = `⚠ ${this.t('iam.logic.prerequisites.required', { count: missingCount })}`;\n const hint = `\\n\\n💡 ${this.t('iam.logic.click.to.auto.select')}`;\n\n return `${header}\\n\\n${logicTree}${hint}`;\n }\n\n /** Build dynamic logic tree message with AND/OR operators and nesting */\n buildLogicMessage(\n logic: ILogicNode,\n _missingActions: IAction[],\n allActions: IAction[],\n currentSelection?: Record<string, boolean>,\n ): string {\n const selectedIds = currentSelection\n ? this.getSelectedIds(currentSelection)\n : new Set<string>();\n const actionMap = new Map(allActions.map((a) => [a.id, a]));\n return this.formatLogicNode(logic, selectedIds, actionMap, 0);\n }\n\n /** Extract selected action IDs from selection map */\n private getSelectedIds(\n currentSelection: Record<string, boolean>,\n ): Set<string> {\n return new Set(\n Object.keys(currentSelection).filter((id) => currentSelection[id]),\n );\n }\n\n private sanitizeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n }\n\n /** Recursively collect ALL missing prerequisites at all dependency levels */\n private getAllMissingPrerequisitesRecursive(\n action: IAction,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n ): IAction[] {\n if (!action.id) return [];\n\n const visited = new Set<string>();\n const allMissing = new Map<string, IAction>();\n const stack = new Set<string>();\n\n const collectMissing = (targetAction: IAction, depth: number = 0): void => {\n if (!targetAction.permissionLogic || !targetAction.id) return;\n\n if (depth > 50) {\n return;\n }\n\n if (visited.has(targetAction.id)) return;\n\n if (stack.has(targetAction.id)) {\n return;\n }\n\n visited.add(targetAction.id);\n stack.add(targetAction.id);\n\n const selectedActionIds = this.getSelectedIds(currentSelection);\n\n const result = validateActionPrerequisites(\n targetAction,\n selectedActionIds,\n allActions,\n );\n\n if (!result.valid) {\n result.missingActions.forEach((missingAction) => {\n if (missingAction.id && missingAction.id !== action.id) {\n allMissing.set(missingAction.id, missingAction);\n collectMissing(missingAction, depth + 1);\n }\n });\n }\n\n stack.delete(targetAction.id);\n };\n\n collectMissing(action);\n return Array.from(allMissing.values());\n }\n\n private showPrerequisiteDialog(\n action: IAction,\n missingActions: IAction[],\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n previousState: Record<string, boolean>,\n onUpdate: (newSelection: Record<string, boolean>) => void,\n onCancel: (previousState: Record<string, boolean>) => void,\n ): void {\n const logicMessage = action.permissionLogic\n ? this.buildLogicMessage(\n action.permissionLogic,\n missingActions,\n allActions,\n currentSelection,\n )\n : this.buildSimpleMessage(missingActions);\n\n const actionsToSelect = action.permissionLogic\n ? this.calculateSmartSelection(\n action.permissionLogic,\n missingActions,\n currentSelection,\n allActions,\n )\n : missingActions;\n\n const selectionCount = actionsToSelect.length;\n\n const sanitizedActionName = this.sanitizeHtml(\n action.name ?? this.t('iam.logic.unknown.action'),\n );\n\n const acceptLabel =\n selectionCount === 0\n ? this.t('iam.logic.select.action.label')\n : this.t('iam.logic.auto.select.actions');\n const detailMessage =\n selectionCount === 0\n ? this.t('iam.logic.action.selected.detail')\n : this.t('iam.logic.auto.selected.detail', { count: selectionCount });\n\n const suffix =\n selectionCount < missingActions.length\n ? this.t('iam.logic.minimum.required')\n : '';\n const autoSelectPrompt = this.t('iam.logic.auto.select.prompt', {\n count: selectionCount,\n suffix,\n });\n\n this.confirmationService.confirm({\n header: this.t('iam.logic.missing.prerequisites'),\n message: `<strong>${sanitizedActionName}</strong> ${this.t('iam.logic.requires.conditions')}<br/><br/>${logicMessage}<br/><br/><strong>${autoSelectPrompt}</strong><br/>${this.t('iam.logic.would.you.continue')}`,\n icon: 'exclamation-triangle',\n acceptLabel,\n rejectLabel: this.t('shared.cancel'),\n acceptIcon: 'check',\n rejectIcon: 'times',\n closeOnEscape: false,\n closable: false,\n accept: () => {\n const selMap = { ...currentSelection };\n selMap[action.id as string] = true;\n actionsToSelect.forEach((a) => {\n selMap[a.id as string] = true;\n });\n onUpdate(selMap);\n\n this.messageService.add({\n severity: 'info',\n summary: this.t('iam.logic.actions.selected.summary'),\n detail: detailMessage,\n });\n },\n reject: () => {\n onCancel(previousState);\n\n this.messageService.add({\n severity: 'info',\n summary: this.t('iam.logic.selection.cancelled'),\n detail: this.t('iam.logic.action.not.added'),\n });\n },\n });\n }\n\n private showDependencyDialog(\n action: IAction,\n affectedActions: IAction[],\n currentSelection: Record<string, boolean>,\n _allActions: IAction[],\n onUpdate: (newSelection: Record<string, boolean>) => void,\n ): void {\n if (!action.id) return;\n\n const alternatives = this.findAlternatives(\n action.id,\n affectedActions,\n currentSelection,\n );\n\n const sanitizedActionName = this.sanitizeHtml(\n action.name ?? this.t('iam.logic.unknown.action'),\n );\n let message = `<strong>${sanitizedActionName}</strong> ${this.t('iam.logic.required.by.actions')}<br/><br/><ul class=\"pl-4\">`;\n affectedActions.forEach((a) => {\n const sanitizedName = this.sanitizeHtml(\n a.name ?? this.t('iam.logic.unknown.action'),\n );\n message += `<li>${sanitizedName}</li>`;\n });\n message += '</ul><br/>';\n\n if (alternatives.length > 0) {\n message += `<strong>${this.t('iam.logic.alternatives.available')}</strong><br/><br/>`;\n message += `<em>${this.t('iam.logic.switch.to.alternatives')}</em>`;\n } else {\n message += `<em>${this.t('iam.logic.remove.dependents')}</em><br/><br/>`;\n message += this.t('iam.logic.would.you.continue');\n }\n\n this.confirmationService.confirm({\n header: this.t('iam.logic.dependency.warning'),\n message,\n icon: 'exclamation-triangle',\n acceptLabel:\n alternatives.length > 0\n ? this.t('iam.logic.use.alternatives')\n : this.t('iam.logic.remove.all'),\n rejectLabel: this.t('shared.cancel'),\n acceptIcon: 'check',\n rejectIcon: 'times',\n closeOnEscape: false,\n closable: false,\n accept: () => {\n const selMap = { ...currentSelection };\n\n if (alternatives.length > 0) {\n // Apply alternatives\n alternatives.forEach(({ alternativeId }) => {\n selMap[alternativeId] = true;\n });\n selMap[action.id as string] = false;\n\n this.messageService.add({\n severity: 'success',\n summary: this.t('iam.logic.alternatives.applied'),\n detail: this.t('iam.logic.switched.to.alternatives'),\n });\n } else {\n // Remove action and all dependents\n selMap[action.id as string] = false;\n affectedActions.forEach((a) => {\n selMap[a.id as string] = false;\n });\n\n this.messageService.add({\n severity: 'warn',\n summary: this.t('iam.logic.actions.removed'),\n detail: this.t('iam.logic.removed.with.dependents', {\n name: action.name ?? '',\n count: affectedActions.length,\n }),\n });\n }\n\n onUpdate(selMap);\n },\n reject: () => {\n this.messageService.add({\n severity: 'info',\n summary: this.t('iam.logic.cancelled'),\n detail: this.t('iam.logic.no.changes.made'),\n });\n },\n });\n }\n\n private findActionsDependingOn(\n actionId: string,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n ): IAction[] {\n const selectedActions = allActions.filter(\n (a) => currentSelection[a.id as string] && a.id !== actionId,\n );\n\n return selectedActions.filter((action) => {\n if (!action.permissionLogic) return false;\n return this.doesLogicDependOn(action.permissionLogic, actionId);\n });\n }\n\n private doesLogicDependOn(node: ILogicNode, targetActionId: string): boolean {\n if (node.type === 'action') {\n return node.actionId === targetActionId;\n }\n\n if (node.type === 'group' && node.children) {\n return node.children.some((child: ILogicNode) =>\n this.doesLogicDependOn(child, targetActionId),\n );\n }\n\n return false;\n }\n\n private findAlternatives(\n removingActionId: string,\n affectedActions: IAction[],\n currentSelection: Record<string, boolean>,\n ): Array<{ alternativeId: string }> {\n const alternatives: Array<{ alternativeId: string }> = [];\n\n for (const affectedAction of affectedActions) {\n if (!affectedAction.permissionLogic) continue;\n\n const alternative = this.findAlternativeInLogic(\n affectedAction.permissionLogic,\n removingActionId,\n currentSelection,\n );\n\n if (alternative) {\n alternatives.push({ alternativeId: alternative });\n }\n }\n\n return alternatives;\n }\n\n private findAlternativeInLogic(\n node: ILogicNode,\n removingActionId: string,\n currentSelection: Record<string, boolean>,\n ): string | null {\n if (node.type === 'group' && node.operator === 'OR' && node.children) {\n const hasRemoving = node.children.some(\n (child) =>\n child.type === 'action' && child.actionId === removingActionId,\n );\n\n if (hasRemoving) {\n for (const child of node.children) {\n if (\n child.type === 'action' &&\n child.actionId &&\n child.actionId !== removingActionId &&\n !currentSelection[child.actionId]\n ) {\n return child.actionId;\n }\n }\n }\n }\n\n if (node.type === 'group' && node.children) {\n for (const child of node.children) {\n const alternative = this.findAlternativeInLogic(\n child,\n removingActionId,\n currentSelection,\n );\n if (alternative) return alternative;\n }\n }\n\n return null;\n }\n\n private calculateSmartSelection(\n logic: ILogicNode,\n missingActions: IAction[],\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n ): IAction[] {\n const missingIds = new Set(missingActions.map((a) => a.id));\n const actionMap = new Map(allActions.map((a) => [a.id, a]));\n const selectedIds = this.getSelectedIds(currentSelection);\n\n const requiredIds = this.findRequiredActionIds(\n logic,\n missingIds,\n selectedIds,\n );\n return Array.from(requiredIds)\n .map((id) => actionMap.get(id))\n .filter((a): a is IAction => !!a);\n }\n\n private findRequiredActionIds(\n node: ILogicNode,\n missingIds: Set<string | undefined>,\n selectedIds: Set<string>,\n ): Set<string> {\n if (node.type === 'action' && node.actionId) {\n if (missingIds.has(node.actionId)) {\n return new Set([node.actionId]);\n }\n return new Set();\n }\n\n if (node.type === 'group' && node.children && node.children.length > 0) {\n const operator = node.operator || 'AND';\n\n if (operator === 'AND') {\n const required = new Set<string>();\n for (const child of node.children) {\n const childRequired = this.findRequiredActionIds(\n child,\n missingIds,\n selectedIds,\n );\n childRequired.forEach((id) => required.add(id));\n }\n return required;\n } else {\n let minRequired: Set<string> | null = null;\n let minSize = Infinity;\n\n for (const child of node.children) {\n const childRequired = this.findRequiredActionIds(\n child,\n missingIds,\n selectedIds,\n );\n\n if (childRequired.size === 0) {\n return new Set();\n }\n\n if (childRequired.size < minSize) {\n minSize = childRequired.size;\n minRequired = childRequired;\n }\n }\n\n return minRequired || new Set();\n }\n }\n\n return new Set();\n }\n\n private buildSimpleMessage(missingActions: IAction[]): string {\n return `<ul class=\"pl-4\">${missingActions.map((a) => `<li>${this.sanitizeHtml(a.name ?? this.t('iam.logic.unknown.action'))}</li>`).join('')}</ul>`;\n }\n\n private formatLogicNode(\n node: ILogicNode,\n selectedIds: Set<string | undefined>,\n actionMap: Map<string | undefined, IAction>,\n depth: number,\n ): string {\n const indent = ' '.repeat(depth);\n\n if (node.type === 'action' && node.actionId) {\n const action = actionMap.get(node.actionId);\n const actionName = this.sanitizeHtml(\n action?.name || this.t('iam.logic.unknown.action'),\n );\n const isSelected = selectedIds.has(node.actionId);\n\n if (isSelected) {\n return `${indent}<span style=\"color: #10b981; font-weight: 500;\">✓ ${actionName}</span> <em style=\"color: #059669;\">${this.t('iam.logic.satisfied')}</em>`;\n } else {\n return `${indent}<span style=\"color: #ef4444;\">✗ ${actionName}</span> <em style=\"color: #dc2626;\">${this.t('iam.logic.missing')}</em>`;\n }\n }\n\n if (node.type === 'group' && node.children) {\n const operator = node.operator || 'AND';\n const operatorColor = operator === 'AND' ? '#3b82f6' : '#8b5cf6';\n const lines: string[] = [];\n\n lines.push(\n `${indent}<strong style=\"color: ${operatorColor};\">${operator}</strong> <span style=\"color: #6b7280;\">(${node.children.length} condition${node.children.length !== 1 ? 's' : ''})</span>`,\n );\n\n node.children.forEach((child: ILogicNode, index: number) => {\n const childHtml = this.formatLogicNode(\n child,\n selectedIds,\n actionMap,\n depth + 1,\n );\n lines.push(childHtml);\n\n if (node.children && index < node.children.length - 1) {\n lines.push(\n `${indent} <em style=\"color: ${operatorColor}; font-size: 0.75rem;\">${operator.toLowerCase()}</em>`,\n );\n }\n });\n\n return lines.join('<br/>');\n }\n\n return `${indent}<em style=\"color: #9ca3af;\">${this.t('iam.logic.invalid.node')}</em>`;\n }\n\n /** Build clean text-based logic tree for tooltips */\n private buildTooltipLogicTree(\n node: ILogicNode,\n currentSelection: Record<string, boolean>,\n allActions: IAction[],\n depth: number,\n ): string {\n const indent = ' '.repeat(depth);\n const selectedIds = this.getSelectedIds(currentSelection);\n const actionMap = new Map(allActions.map((a) => [a.id, a]));\n\n if (node.type === 'action' && node.actionId) {\n const action = actionMap.get(node.actionId);\n const actionName = action?.name || this.t('iam.logic.unknown.action');\n const isSelected = selectedIds.has(node.actionId);\n\n if (isSelected) {\n return `${indent}✓ ${actionName}`;\n } else {\n return `${indent}✗ ${actionName}`;\n }\n }\n\n if (node.type === 'group' && node.children) {\n const operator = node.operator || 'AND';\n const lines: string[] = [];\n\n lines.push(`${indent}${operator}:`);\n\n node.children.forEach((child: ILogicNode, index: number) => {\n const childText = this.buildTooltipLogicTree(\n child,\n currentSelection,\n allActions,\n depth + 1,\n );\n lines.push(childText);\n\n if (\n node.children &&\n index < node.children.length - 1 &&\n operator === 'OR'\n ) {\n lines.push(`${indent} ${operator.toLowerCase()}`);\n }\n });\n\n return lines.join('\\n');\n }\n\n return `${indent}${this.t('iam.logic.invalid')}`;\n }\n}\n","import { computed, inject, signal } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-shared';\nimport { ConfirmationService } from '@flusys/ng-ui';\nimport {\n IAction,\n IActionTreeDto,\n PermissionAction,\n} from '../interfaces/public-api';\nimport { ActionPermissionLogicService } from '../services/action-permission-logic.service';\nimport { convertActionToTreeNode } from '../utils/tree-utils';\n\nexport abstract class BaseActionSelectorComponent {\n protected readonly permissionLogic = inject(ActionPermissionLogicService);\n protected readonly confirmationService = inject(ConfirmationService);\n protected readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n readonly loading = signal(false);\n readonly saving = signal(false);\n\n protected readonly _actions = signal<IAction[]>([]);\n readonly actions = this._actions.asReadonly();\n\n protected readonly _actionsTree = signal<IActionTreeDto[]>([]);\n protected readonly actionsTree = this._actionsTree.asReadonly();\n\n protected readonly _selectionMap = signal<Record<string, boolean>>({});\n readonly selectionMap = this._selectionMap.asReadonly();\n\n protected readonly _initialSelection = signal<Record<string, boolean>>({});\n protected readonly initialSelection = this._initialSelection.asReadonly();\n\n readonly treeNodes = computed(() =>\n convertActionToTreeNode(this.actionsTree()),\n );\n\n readonly allSelected = computed(() => {\n const selMap = this.selectionMap();\n const total = this.actions().length;\n if (total === 0) return false;\n return Object.values(selMap).filter((v) => v).length === total;\n });\n\n readonly hasChanges = computed(() => {\n const current = this.selectionMap();\n const initial = this.initialSelection();\n const currentKeys = Object.keys(current);\n if (currentKeys.length !== Object.keys(initial).length) return true;\n return currentKeys.some((key) => current[key] !== initial[key]);\n });\n\n readonly actionsWithUnmetPrerequisites = computed(() => {\n const selMap = this.selectionMap();\n const allActions = this.actions();\n const unmetSet = new Set<string>();\n for (const action of allActions) {\n if (\n action.id &&\n this.permissionLogic.hasUnmetPrerequisites(action, selMap, allActions)\n ) {\n unmetSet.add(action.id);\n }\n }\n return unmetSet;\n });\n\n readonly invalidActionsCount = computed(\n () => this.actionsWithUnmetPrerequisites().size,\n );\n\n readonly pendingAdd = computed(() => {\n const current = this.selectionMap();\n const initial = this.initialSelection();\n return this.actions().filter(\n (a) => current[a.id as string] && !initial[a.id as string],\n );\n });\n\n readonly pendingRemove = computed(() => {\n const current = this.selectionMap();\n const initial = this.initialSelection();\n return this.actions().filter(\n (a) => !current[a.id as string] && initial[a.id as string],\n );\n });\n\n readonly canSave = computed(\n () =>\n this.hasChanges() && !this.saving() && this.invalidActionsCount() === 0,\n );\n\n protected translate(\n key: string,\n vars?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n\n // Guards a selection change (role/user/company) behind a confirm dialog\n // when there are unsaved edits; runs onAccept directly otherwise.\n protected confirmSelectionChange(onAccept: () => void, onReject: () => void): void {\n if (!this.hasChanges()) {\n onAccept();\n return;\n }\n\n this.confirmationService.confirm({\n header: this.translate('iam.permission.unsaved.changes.title'),\n message: this.translate('iam.permission.unsaved.changes.message'),\n icon: 'exclamation-triangle',\n acceptLabel: this.translate('iam.permission.unsaved.changes.discard'),\n rejectLabel: this.translate('shared.cancel'),\n accept: onAccept,\n reject: onReject,\n });\n }\n\n hasUnmetPrerequisites(action: IAction): boolean {\n return action.id\n ? this.actionsWithUnmetPrerequisites().has(action.id)\n : false;\n }\n\n getTooltip(action: IAction): string {\n const selMap = this.selectionMap();\n const isCurrentlySelected = selMap[action.id as string];\n\n if (action.permissionLogic) {\n const prerequisiteInfo = this.permissionLogic.getPrerequisiteTooltip(\n action,\n selMap,\n this.actions(),\n );\n if (prerequisiteInfo) {\n const actionHint = isCurrentlySelected\n ? `\\n\\n---\\n[${this.translate('shared.remove')}] ${this.translate('iam.tooltip.remove.action')}`\n : `\\n\\n---\\n[${this.translate('shared.add')}] ${this.translate('iam.tooltip.add.action')}`;\n return `${prerequisiteInfo}${actionHint}`;\n }\n }\n\n return this.getDefaultTooltip(isCurrentlySelected);\n }\n\n protected abstract getDefaultTooltip(isSelected: boolean): string;\n\n onActionToggle(action: IAction, newValue: boolean): void {\n if (!newValue) {\n this.permissionLogic.handleUncheck(\n action,\n this.selectionMap(),\n this.actions(),\n (newMap) => this._selectionMap.set(newMap),\n );\n } else {\n this.permissionLogic.handleCheck(\n action,\n this.selectionMap(),\n this.actions(),\n (newMap) => this._selectionMap.set(newMap),\n (previousState) => this._selectionMap.set(previousState),\n );\n }\n }\n\n toggleAll(): void {\n this.setAllSelection(!this.allSelected());\n }\n\n protected setAllSelection(value: boolean): void {\n this._selectionMap.set(this.buildSelectionMap(this.actions(), () => value));\n }\n\n protected buildSelectionMap(\n actions: IAction[],\n predicate: (action: IAction) => boolean,\n ): Record<string, boolean> {\n const selMap: Record<string, boolean> = {};\n for (const action of actions) {\n selMap[action.id as string] = predicate(action);\n }\n return selMap;\n }\n\n protected buildPayloadItems(): Array<{\n id: string;\n action: PermissionAction;\n }> {\n const items: Array<{ id: string; action: PermissionAction }> = [];\n for (const action of this.pendingAdd()) {\n items.push({ id: action.id as string, action: 'add' });\n }\n for (const action of this.pendingRemove()) {\n items.push({ id: action.id as string, action: 'remove' });\n }\n return items;\n }\n\n protected resetState(): void {\n this._actionsTree.set([]);\n this._actions.set([]);\n this._selectionMap.set({});\n this._initialSelection.set({});\n }\n}\n","import { Component, DestroyRef, effect, inject, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n CheckboxComponent,\n FButtonDirective,\n MessageService,\n SelectComponent,\n TagComponent,\n TooltipDirective,\n TreeTableComponent,\n TreeTableTogglerComponent,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n HasPermissionDirective,\n ROLE_ACTION_PERMISSIONS,\n TranslatePipe,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { MAX_DROPDOWN_ITEMS } from '../constants/pagination.constants';\nimport { IActionTreeDto, IRole } from '../interfaces/public-api';\nimport { ActionApiService } from '../services/action-api.service';\nimport { PermissionApiService } from '../services/permission-api.service';\nimport { RoleApiService } from '../services/role-api.service';\nimport { buildTreeFromFlat } from '../utils/tree-utils';\nimport { BaseActionSelectorComponent } from './base-action-selector';\n\n@Component({\n selector: 'flusys-role-action-selector',\n imports: [\n FormsModule,\n CheckboxComponent,\n FButtonDirective,\n SelectComponent,\n TagComponent,\n TooltipDirective,\n TreeTableComponent,\n TreeTableTogglerComponent,\n UiIconComponent,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <div class=\"role-action-selector\">\n <div class=\"surface-card p-4 rounded-border mb-4 shadow-sm\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-5\">\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"shield\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.role' | translate }}\n </label>\n <f-select\n #roleSelect\n [ngModel]=\"selectedRoleId()\"\n (ngModelChange)=\"onRoleSelect($event)\"\n [options]=\"roles()\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"\n 'iam.permission.select.role.placeholder' | translate\n \"\n [showClear]=\"true\"\n [filter]=\"true\"\n class=\"w-full\"\n />\n </div>\n </div>\n </div>\n\n @if (!selectedRoleId()) {\n <div class=\"empty-state border border-dashed border-surface rounded-border p-8 text-center\">\n <div class=\"empty-state-icon mx-auto mb-3\">\n <ui-icon name=\"arrow-up\" class=\"text-primary\"></ui-icon>\n </div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.empty.role.actions.title' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{ 'iam.permission.empty.role.actions.description' | translate }}\n </p>\n </div>\n }\n\n @if (selectedRoleId()) {\n @if (loading()) {\n <div\n class=\"surface-card p-5 rounded-border shadow-sm flex justify-center\"\n >\n <ui-icon name=\"loader-circle\" spin class=\"text-primary text-5xl\"></ui-icon>\n </div>\n }\n\n @if (!loading() && actions().length > 0) {\n <div class=\"surface-card p-4 rounded-border shadow-sm\">\n <div\n class=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-3 mb-4\"\n >\n <div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.action.permissions' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{\n 'iam.permission.actions.available'\n | translate: { count: actions().length }\n }}\n </p>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelection(true)\"\n >\n <ui-icon pButtonIcon name=\"check\"></ui-icon>\n <span pButtonLabel>{{ 'shared.select.all' | translate }}</span>\n </button>\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelection(false)\"\n >\n <ui-icon pButtonIcon name=\"times\"></ui-icon>\n <span pButtonLabel>{{ 'shared.deselect.all' | translate }}</span>\n </button>\n <button\n fButton\n *hasPermission=\"ROLE_ACTION_PERMISSIONS.ASSIGN\"\n [disabled]=\"!canSave() || saving()\"\n size=\"small\"\n (click)=\"saveChanges()\"\n >\n @if (saving()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"save\"></ui-icon>\n }\n <span pButtonLabel>{{ 'shared.save.changes' | translate }}</span>\n </button>\n </div>\n </div>\n\n @if (invalidActionsCount() > 0) {\n <div class=\"validation-warning rounded-border p-3 mb-4\">\n <div class=\"flex items-start gap-2\">\n <ui-icon name=\"exclamation-triangle\" class=\"text-xl\"></ui-icon>\n <div class=\"flex-1\">\n <span class=\"font-semibold\"\n >{{ 'iam.validation.warning.title' | translate }}:</span\n >\n <p class=\"text-sm mt-1 mb-0\">\n {{\n (invalidActionsCount() > 1\n ? 'iam.validation.unmet.prerequisites.plural'\n : 'iam.validation.unmet.prerequisites.singular'\n ) | translate: { count: invalidActionsCount() }\n }}\n </p>\n </div>\n </div>\n </div>\n }\n\n <div class=\"overflow-x-auto -mx-4 sm:mx-0\">\n <f-treetable\n [value]=\"treeNodes()\"\n dataKey=\"id\"\n [tableStyle]=\"{ 'min-width': '50rem' }\"\n >\n <ng-template #header>\n <tr>\n <th class=\"w-12\">\n <f-checkbox\n [ngModel]=\"allSelected()\"\n [binary]=\"true\"\n (ngModelChange)=\"toggleAll()\"\n [fTooltip]=\"'shared.select.deselect.all' | translate\"\n tooltipPosition=\"top\"\n />\n </th>\n <th>{{ 'shared.name' | translate }}</th>\n <th class=\"hidden md:table-cell\">\n {{ 'shared.code' | translate }}\n </th>\n <th>{{ 'iam.action.type' | translate }}</th>\n <th class=\"hidden lg:table-cell\">\n {{ 'iam.permission.requirements' | translate }}\n </th>\n </tr>\n </ng-template>\n <ng-template #body let-rowNode let-rowData=\"rowData\">\n @let hasUnmet = hasUnmetPrerequisites(rowData);\n @let tooltip = getTooltip(rowData);\n <tr [class.highlight-warning]=\"hasUnmet\">\n <td class=\"w-12\">\n <f-checkbox\n [ngModel]=\"selectionMap()[rowData.id]\"\n [binary]=\"true\"\n (ngModelChange)=\"onActionToggle(rowData, $event)\"\n [fTooltip]=\"tooltip\"\n tooltipPosition=\"top\"\n />\n </td>\n <td>\n <f-treetabletoggler [rowNode]=\"rowNode\" />\n <span class=\"inline-flex items-center gap-2\">\n {{ rowData.name }}\n @if (hasUnmet) {\n <ui-icon name=\"exclamation-triangle\" class=\"text-orange-500\" [fTooltip]=\"\n 'iam.validation.unmet.prerequisites.tooltip'\n | translate\n \"\n tooltipPosition=\"top\"></ui-icon>\n }\n </span>\n </td>\n <td class=\"hidden md:table-cell\">\n {{ rowData.code || '-' }}\n </td>\n <td>\n <f-tag\n [value]=\"rowData.actionType\"\n [severity]=\"\n rowData.actionType === 'backend' ? 'info' : 'success'\n \"\n />\n </td>\n <td class=\"hidden lg:table-cell\">\n @if (rowData.permissionLogic) {\n <span class=\"text-sm text-muted-color\">{{\n 'iam.permission.has.prerequisites' | translate\n }}</span>\n } @else {\n <span class=\"text-muted-color\">-</span>\n }\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"5\" class=\"text-center p-4 text-muted-color\">\n @if (loading()) {\n <ui-icon name=\"loader-circle\" spin></ui-icon>\n {{ 'shared.loading.actions' | translate }}\n } @else {\n {{ 'iam.permission.no.actions.available' | translate }}\n }\n </td>\n </tr>\n </ng-template>\n </f-treetable>\n </div>\n </div>\n\n @if (hasChanges()) {\n <div class=\"border border-surface rounded-border p-3 mt-4\">\n <div class=\"flex items-center gap-2 mb-3\">\n <ui-icon name=\"info-circle\" class=\"text-primary\"></ui-icon>\n <span class=\"font-bold\">{{\n 'shared.pending.changes' | translate\n }}</span>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n @if (pendingAdd().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"plus-circle\" class=\"text-green-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.add' | translate }} ({{\n pendingAdd().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (action of pendingAdd(); track action.id) {\n <li class=\"text-sm mb-1\">{{ action.name }}</li>\n }\n </ul>\n </div>\n }\n @if (pendingRemove().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"minus-circle\" class=\"text-red-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.remove' | translate }} ({{\n pendingRemove().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (action of pendingRemove(); track action.id) {\n <li class=\"text-sm mb-1\">{{ action.name }}</li>\n }\n </ul>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (!loading() && actions().length === 0) {\n <div class=\"surface-card p-5 rounded-border shadow-sm text-center\">\n <ui-icon name=\"info-circle\" class=\"text-muted-color mb-3 block text-5xl\"></ui-icon>\n <p class=\"text-muted-color m-0\">\n {{ 'iam.permission.no.actions.for.role' | translate }}\n </p>\n </div>\n }\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n .empty-state-icon {\n width: 3rem;\n height: 3rem;\n border-radius: 9999px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--f-primary-50, rgba(59, 130, 246, 0.08));\n }\n :host-context(.app-dark) .empty-state-icon {\n background-color: rgba(96, 165, 250, 0.12);\n }\n .validation-warning {\n background-color: var(--f-yellow-50, #fefce8);\n border-left: 4px solid var(--f-yellow-500, #eab308);\n color: var(--f-yellow-700, #a16207);\n }\n :host-context(.app-dark) .validation-warning {\n background-color: rgba(234, 179, 8, 0.1);\n color: var(--f-yellow-400, #facc15);\n }\n :host ::ng-deep tr.highlight-warning {\n background-color: var(--f-red-50, rgba(239, 68, 68, 0.1)) !important;\n }\n :host-context(.app-dark) ::ng-deep tr.highlight-warning {\n background-color: rgba(239, 68, 68, 0.15) !important;\n }\n `,\n ],\n})\nexport class RoleActionSelectorComponent extends BaseActionSelectorComponent {\n readonly ROLE_ACTION_PERMISSIONS = ROLE_ACTION_PERMISSIONS;\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly roleApi = inject(RoleApiService);\n private readonly actionApi = inject(ActionApiService);\n private readonly permissionApi = inject(PermissionApiService);\n private readonly messageService = inject(MessageService);\n\n readonly selectedRoleId = signal<string | undefined>(undefined);\n readonly roles = signal<IRole[]>([]);\n\n private readonly roleSelectRef = viewChild<SelectComponent>('roleSelect');\n private loadDataAbortController: AbortController | null = null;\n\n constructor() {\n super();\n this.destroyRef.onDestroy(() => {\n this.loadDataAbortController?.abort();\n });\n\n this.loadRoles();\n\n effect(() => {\n const roleId = this.selectedRoleId();\n this.loadDataAbortController?.abort();\n\n if (roleId) {\n this.loadDataAbortController = new AbortController();\n this.onRoleChange(this.loadDataAbortController.signal).catch((err) => {\n if (err.name !== 'AbortError') {\n this.loading.set(false);\n }\n });\n } else {\n this.resetState();\n }\n });\n }\n\n onRoleSelect(roleId: string | undefined): void {\n const previousRoleId = this.selectedRoleId();\n if (roleId === previousRoleId) return;\n\n this.confirmSelectionChange(\n () => this.selectedRoleId.set(roleId),\n () => this.roleSelectRef()?.writeValue(previousRoleId),\n );\n }\n\n protected getDefaultTooltip(isSelected: boolean): string {\n if (isSelected) {\n return `[${this.translate('shared.assigned')}] ${this.translate('iam.tooltip.assigned.to.role')}\\n\\n[${this.translate('shared.remove')}] ${this.translate('iam.tooltip.click.to.remove.role')}`;\n }\n return `[${this.translate('shared.add')}] ${this.translate('iam.tooltip.click.to.assign.role')}`;\n }\n\n private async loadRoles(): Promise<void> {\n try {\n const response = await this.roleApi.getAll({\n pagination: { currentPage: 0, pageSize: MAX_DROPDOWN_ITEMS },\n });\n this.roles.set(response?.data ?? []);\n } catch {}\n }\n\n private async onRoleChange(signal: AbortSignal): Promise<void> {\n const roleId = this.selectedRoleId();\n if (!roleId) return;\n\n this.loading.set(true);\n try {\n const actionsResponse = await firstValueFrom(\n this.actionApi.getActionsForPermission(),\n );\n\n if (signal.aborted) return;\n\n const flatActions = (actionsResponse?.data ?? []).filter((a) => !!a.id);\n const actionsTree = buildTreeFromFlat(flatActions) as IActionTreeDto[];\n\n this._actionsTree.set(actionsTree);\n this._actions.set(flatActions);\n\n const assignedResponse = await firstValueFrom(\n this.permissionApi.getRoleActions(roleId),\n );\n\n if (signal.aborted) return;\n\n const assignedIds = new Set(\n (assignedResponse?.data || []).map((a) => a.actionId),\n );\n\n const selMap = this.buildSelectionMap(flatActions, (action) =>\n assignedIds.has(action.id as string),\n );\n this._selectionMap.set(selMap);\n this._initialSelection.set({ ...selMap });\n } finally {\n if (!signal.aborted) {\n this.loading.set(false);\n }\n }\n }\n\n async saveChanges(): Promise<void> {\n const roleId = this.selectedRoleId();\n if (!roleId) return;\n\n const invalidActions =\n this.permissionLogic.getActionsWithUnmetPrerequisites(\n this.selectionMap(),\n this.actions(),\n );\n if (invalidActions.length > 0) {\n this.permissionLogic.showValidationErrorDialog(\n invalidActions,\n this.selectionMap(),\n this.actions(),\n (newMap) => this._selectionMap.set(newMap),\n );\n return;\n }\n\n const items = this.buildPayloadItems();\n if (items.length === 0) return;\n\n this.saving.set(true);\n try {\n const response = await firstValueFrom(\n this.permissionApi.assignRoleActions({ roleId, items }),\n );\n\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response?.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : response?.message,\n });\n\n this._initialSelection.set({ ...this.selectionMap() });\n } catch {\n } finally {\n this.saving.set(false);\n }\n }\n}\n","import { Component, DestroyRef, effect, inject, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n CheckboxComponent,\n FButtonDirective,\n MessageService,\n SelectComponent,\n TagComponent,\n TooltipDirective,\n TreeTableComponent,\n TreeTableTogglerComponent,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n COMPANY_ACTION_PERMISSIONS,\n COMPANY_API_PROVIDER,\n HasPermissionDirective,\n TranslatePipe,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { MAX_DROPDOWN_ITEMS } from '../constants/pagination.constants';\nimport {\n ICompany,\n IPrerequisiteValidationError,\n} from '../interfaces/public-api';\nimport { ActionApiService } from '../services/action-api.service';\nimport { PermissionApiService } from '../services/permission-api.service';\nimport { flattenTree } from '../utils/tree-utils';\nimport { BaseActionSelectorComponent } from './base-action-selector';\n\n@Component({\n selector: 'flusys-company-action-selector',\n imports: [\n CheckboxComponent,\n FButtonDirective,\n SelectComponent,\n TagComponent,\n TooltipDirective,\n TreeTableComponent,\n TreeTableTogglerComponent,\n UiIconComponent,\n FormsModule,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <div class=\"company-action-selector\">\n <div class=\"surface-card p-4 rounded-border mb-4 shadow-sm\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-5\">\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"building\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.company' | translate }}\n </label>\n <f-select\n #companySelect\n [ngModel]=\"selectedCompanyId()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [options]=\"companies()\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"\n 'iam.permission.select.company.placeholder' | translate\n \"\n [showClear]=\"true\"\n [filter]=\"true\"\n class=\"w-full\"\n />\n </div>\n </div>\n </div>\n\n @if (!selectedCompanyId()) {\n <div class=\"empty-state border border-dashed border-surface rounded-border p-8 text-center\">\n <div class=\"empty-state-icon mx-auto mb-3\">\n <ui-icon name=\"building\" class=\"text-primary\"></ui-icon>\n </div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.empty.company.actions.title' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{ 'iam.permission.empty.company.actions.description' | translate }}\n </p>\n </div>\n }\n\n @if (selectedCompanyId()) {\n @if (loading()) {\n <div\n class=\"surface-card p-5 rounded-border shadow-sm flex justify-center\"\n >\n <ui-icon name=\"loader-circle\" spin class=\"text-primary text-5xl\"></ui-icon>\n </div>\n }\n\n @if (!loading() && actions().length > 0) {\n <div class=\"surface-card p-4 rounded-border shadow-sm\">\n <div\n class=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-3 mb-4\"\n >\n <div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.action.whitelist' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{\n 'iam.permission.actions.available'\n | translate: { count: actions().length }\n }}\n </p>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelection(true)\"\n >\n <ui-icon pButtonIcon name=\"check\"></ui-icon>\n <span pButtonLabel>{{ 'shared.select.all' | translate }}</span>\n </button>\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelection(false)\"\n >\n <ui-icon pButtonIcon name=\"times\"></ui-icon>\n <span pButtonLabel>{{ 'shared.deselect.all' | translate }}</span>\n </button>\n <button\n fButton\n *hasPermission=\"COMPANY_ACTION_PERMISSIONS.ASSIGN\"\n [disabled]=\"!canSave() || saving()\"\n size=\"small\"\n (click)=\"saveChanges()\"\n >\n @if (saving()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"save\"></ui-icon>\n }\n <span pButtonLabel>{{ 'shared.save.changes' | translate }}</span>\n </button>\n </div>\n </div>\n\n @if (invalidActionsCount() > 0) {\n <div class=\"validation-warning rounded-border p-3 mb-4\">\n <div class=\"flex items-start gap-2\">\n <ui-icon name=\"exclamation-triangle\" class=\"text-xl\"></ui-icon>\n <div class=\"flex-1\">\n <span class=\"font-semibold\"\n >{{ 'iam.validation.warning.title' | translate }}:</span\n >\n <p class=\"text-sm mt-1 mb-0\">\n {{\n (invalidActionsCount() > 1\n ? 'iam.validation.unmet.prerequisites.plural'\n : 'iam.validation.unmet.prerequisites.singular'\n ) | translate: { count: invalidActionsCount() }\n }}\n </p>\n </div>\n </div>\n </div>\n }\n\n <div class=\"overflow-x-auto -mx-4 sm:mx-0\">\n <f-treetable\n [value]=\"treeNodes()\"\n dataKey=\"id\"\n [tableStyle]=\"{ 'min-width': '50rem' }\"\n >\n <ng-template #header>\n <tr>\n <th class=\"w-12\">\n <f-checkbox\n [ngModel]=\"allSelected()\"\n [binary]=\"true\"\n (ngModelChange)=\"toggleAll()\"\n [fTooltip]=\"'shared.select.deselect.all' | translate\"\n tooltipPosition=\"top\"\n />\n </th>\n <th>{{ 'shared.name' | translate }}</th>\n <th class=\"hidden md:table-cell\">\n {{ 'shared.code' | translate }}\n </th>\n <th>{{ 'iam.action.type' | translate }}</th>\n <th class=\"hidden lg:table-cell\">\n {{ 'shared.description' | translate }}\n </th>\n </tr>\n </ng-template>\n <ng-template #body let-rowNode let-rowData=\"rowData\">\n @let hasUnmet = hasUnmetPrerequisites(rowData);\n <tr [class.highlight-warning]=\"hasUnmet\">\n <td class=\"w-12\">\n <f-checkbox\n [ngModel]=\"selectionMap()[rowData.id]\"\n [binary]=\"true\"\n (ngModelChange)=\"onActionToggle(rowData, $event)\"\n [fTooltip]=\"getTooltip(rowData)\"\n tooltipPosition=\"top\"\n />\n </td>\n <td>\n <f-treetabletoggler [rowNode]=\"rowNode\" />\n <span class=\"inline-flex items-center gap-2\">\n {{ rowData.name }}\n @if (hasUnmet) {\n <ui-icon name=\"exclamation-triangle\" class=\"text-orange-500\" [fTooltip]=\"\n 'iam.validation.unmet.prerequisites.tooltip'\n | translate\n \"\n tooltipPosition=\"top\"></ui-icon>\n }\n </span>\n </td>\n <td class=\"hidden md:table-cell\">\n {{ rowData.code || '-' }}\n </td>\n <td>\n <f-tag\n [value]=\"rowData.actionType\"\n [severity]=\"\n rowData.actionType === 'backend' ? 'info' : 'success'\n \"\n />\n </td>\n <td class=\"hidden lg:table-cell\">\n {{ rowData.description || '-' }}\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"5\" class=\"text-center p-4 text-muted-color\">\n @if (loading()) {\n <ui-icon name=\"loader-circle\" spin></ui-icon>\n {{ 'shared.loading.actions' | translate }}\n } @else {\n {{ 'iam.permission.no.actions.available' | translate }}\n }\n </td>\n </tr>\n </ng-template>\n </f-treetable>\n </div>\n </div>\n\n @if (hasChanges()) {\n <div class=\"border border-surface rounded-border p-3 mt-4\">\n <div class=\"flex items-center gap-2 mb-3\">\n <ui-icon name=\"info-circle\" class=\"text-primary\"></ui-icon>\n <span class=\"font-bold\">{{\n 'shared.pending.changes' | translate\n }}</span>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n @if (pendingAdd().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"plus-circle\" class=\"text-green-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.whitelist' | translate }} ({{\n pendingAdd().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (action of pendingAdd(); track action.id) {\n <li class=\"text-sm mb-1\">{{ action.name }}</li>\n }\n </ul>\n </div>\n }\n @if (pendingRemove().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"minus-circle\" class=\"text-red-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.remove' | translate }} ({{\n pendingRemove().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (action of pendingRemove(); track action.id) {\n <li class=\"text-sm mb-1\">{{ action.name }}</li>\n }\n </ul>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (!loading() && actions().length === 0) {\n <div class=\"surface-card p-5 rounded-border shadow-sm text-center\">\n <ui-icon name=\"info-circle\" class=\"text-muted-color mb-3 block text-5xl\"></ui-icon>\n <p class=\"text-muted-color m-0\">\n {{ 'iam.permission.no.actions.for.company' | translate }}\n </p>\n </div>\n }\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n .empty-state-icon {\n width: 3rem;\n height: 3rem;\n border-radius: 9999px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--f-primary-50, rgba(59, 130, 246, 0.08));\n }\n :host-context(.app-dark) .empty-state-icon {\n background-color: rgba(96, 165, 250, 0.12);\n }\n .validation-warning {\n background-color: var(--f-yellow-50, #fefce8);\n border-left: 4px solid var(--f-yellow-500, #eab308);\n color: var(--f-yellow-700, #a16207);\n }\n :host-context(.app-dark) .validation-warning {\n background-color: rgba(234, 179, 8, 0.1);\n color: var(--f-yellow-400, #facc15);\n }\n :host ::ng-deep tr.highlight-warning {\n background-color: var(--f-red-50, rgba(239, 68, 68, 0.1)) !important;\n }\n :host-context(.app-dark) ::ng-deep tr.highlight-warning {\n background-color: rgba(239, 68, 68, 0.15) !important;\n }\n `,\n ],\n})\nexport class CompanyActionSelectorComponent extends BaseActionSelectorComponent {\n readonly COMPANY_ACTION_PERMISSIONS = COMPANY_ACTION_PERMISSIONS;\n\n private readonly companyApiProvider = inject(COMPANY_API_PROVIDER);\n private readonly actionApi = inject(ActionApiService);\n private readonly permissionApi = inject(PermissionApiService);\n private readonly messageService = inject(MessageService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly selectedCompanyId = signal<string | undefined>(undefined);\n readonly companies = signal<ICompany[]>([]);\n\n private readonly companySelectRef = viewChild<SelectComponent>('companySelect');\n private loadDataAbortController: AbortController | null = null;\n\n constructor() {\n super();\n this.destroyRef.onDestroy(() => {\n this.loadDataAbortController?.abort();\n });\n\n this.loadCompanies();\n\n effect(() => {\n const companyId = this.selectedCompanyId();\n this.loadDataAbortController?.abort();\n\n if (companyId) {\n this.loadDataAbortController = new AbortController();\n this.loadData(this.loadDataAbortController.signal).catch((err) => {\n if (err.name !== 'AbortError') {\n this.loading.set(false);\n }\n });\n } else {\n this.resetState();\n }\n });\n }\n\n onCompanyChange(companyId: string | undefined): void {\n const previousCompanyId = this.selectedCompanyId();\n if (companyId === previousCompanyId) return;\n\n this.confirmSelectionChange(\n () => this.selectedCompanyId.set(companyId),\n () => this.companySelectRef()?.writeValue(previousCompanyId),\n );\n }\n\n protected getDefaultTooltip(isSelected: boolean): string {\n if (isSelected) {\n return `[${this.translate('iam.tooltip.selected')}] ${this.translate('iam.tooltip.selected')}\\n\\n[${this.translate('shared.remove')}] ${this.translate('iam.tooltip.click.to.remove')}`;\n }\n return `[${this.translate('shared.add')}] ${this.translate('iam.tooltip.click.to.add')}`;\n }\n\n private async loadCompanies(): Promise<void> {\n try {\n const response = await firstValueFrom(\n this.companyApiProvider.getCompanies({\n page: 0,\n pageSize: MAX_DROPDOWN_ITEMS,\n }),\n );\n this.companies.set(response?.data ?? []);\n } catch {}\n }\n\n private async loadData(signal: AbortSignal): Promise<void> {\n const companyId = this.selectedCompanyId();\n if (!companyId) return;\n\n this.loading.set(true);\n try {\n const actionsResponse = await firstValueFrom(\n this.actionApi.getTree(undefined, undefined, false),\n );\n\n if (signal.aborted) return;\n\n const actionsTree = actionsResponse?.data ?? [];\n const actionsList = flattenTree(actionsTree).filter((a) => !!a.id);\n\n this._actionsTree.set(actionsTree);\n this._actions.set(actionsList);\n\n const assignedResponse = await firstValueFrom(\n this.permissionApi.getCompanyActions(companyId),\n );\n\n if (signal.aborted) return;\n\n const assignedIds = new Set(\n (assignedResponse?.data || []).map((a) => a.actionId),\n );\n\n const selMap = this.buildSelectionMap(actionsList, (action) =>\n assignedIds.has(action.id as string),\n );\n this._selectionMap.set(selMap);\n this._initialSelection.set({ ...selMap });\n } finally {\n if (!signal.aborted) {\n this.loading.set(false);\n }\n }\n }\n\n async saveChanges(): Promise<void> {\n const companyId = this.selectedCompanyId();\n if (!companyId) return;\n\n const invalidActions =\n this.permissionLogic.getActionsWithUnmetPrerequisites(\n this.selectionMap(),\n this.actions(),\n );\n if (invalidActions.length > 0) {\n this.permissionLogic.showValidationErrorDialog(\n invalidActions,\n this.selectionMap(),\n this.actions(),\n (newMap) => this._selectionMap.set(newMap),\n );\n return;\n }\n\n const items = this.buildPayloadItems();\n if (items.length === 0) return;\n\n this.saving.set(true);\n try {\n const response = await firstValueFrom(\n this.permissionApi.assignCompanyActions({ companyId, items }),\n );\n\n if (\n response?.data?.prerequisiteErrors &&\n response.data.prerequisiteErrors.length > 0\n ) {\n this.handleBackendPrerequisiteErrors(response.data.prerequisiteErrors);\n return;\n }\n\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response?.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : (response?.message ?? ''),\n });\n\n this._initialSelection.set({ ...this.selectionMap() });\n } catch {\n } finally {\n this.saving.set(false);\n }\n }\n\n private handleBackendPrerequisiteErrors(\n prerequisiteErrors: IPrerequisiteValidationError[],\n ): void {\n const errorList = prerequisiteErrors\n .map((error) => {\n const requiredNames = error.requiredActions\n .map((a) => a.actionName)\n .join(', ');\n return `${error.actionName} ${this.translate('iam.permission.requires')}: ${requiredNames}`;\n })\n .join('\\n');\n\n this.confirmationService.confirm({\n header: this.translate('iam.permission.prerequisite.validation.failed'),\n message: `${this.translate('iam.permission.prerequisite.error.message')}\\n\\n${errorList}\\n\\n${this.translate('iam.permission.auto.select.prompt')}`,\n icon: 'exclamation-triangle',\n acceptLabel: this.translate('iam.permission.auto.select.required'),\n rejectLabel: this.translate('shared.cancel'),\n acceptIcon: 'check',\n rejectIcon: 'times',\n accept: () => {\n const selMap = { ...this.selectionMap() };\n prerequisiteErrors.forEach((error) => {\n error.requiredActions.forEach((a) => {\n selMap[a.actionId] = true;\n });\n });\n this._selectionMap.set(selMap);\n this.messageService.add({\n severity: 'info',\n summary: this.translate('iam.permission.actions.selected'),\n detail: this.translate('iam.permission.auto.selected.prerequisites'),\n });\n },\n reject: () => {\n this._selectionMap.set({ ...this.initialSelection() });\n this.messageService.add({\n severity: 'info',\n summary: this.translate('iam.permission.changes.reverted'),\n detail: this.translate('iam.permission.selection.reverted'),\n });\n },\n });\n }\n}\n","import { IUserBranchPermission } from '@flusys/ng-shared';\nimport { IBranch } from '../interfaces/user.interface';\n\nexport function toUserBranches(permissions: readonly IUserBranchPermission[] | null | undefined): IBranch[] {\n return (permissions ?? []).map((permission) => ({\n id: permission.branchId,\n name: permission.branchName,\n companyId: permission.companyId,\n parentId: permission.parentId ?? null,\n serial: permission.serial ?? null,\n displayParentId: permission.displayParentId,\n }));\n}\n","import { Component, computed, effect, inject, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport {\n CheckboxComponent,\n ConfirmationService,\n FButtonDirective,\n MessageService,\n TreeSelectComponent,\n TableComponent,\n TooltipDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n buildBranchTreeNodes,\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n USER_PERMISSION_PROVIDER,\n USER_ROLE_PERMISSIONS,\n UserSelectComponent,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { MAX_DROPDOWN_ITEMS } from '../constants/pagination.constants';\nimport { IBranch, IRole, PermissionAction } from '../interfaces/public-api';\nimport { PermissionApiService } from '../services/permission-api.service';\nimport { RoleApiService } from '../services/role-api.service';\nimport { toUserBranches } from '../utils/user-branch.util';\n\n/**\n * Manages user role assignments with branch-level granularity:\n * `branchId === undefined` means a company-wide assignment, a set value\n * scopes the assignment to that specific branch.\n */\n@Component({\n selector: 'flusys-user-role-selector',\n imports: [\n FormsModule,\n CheckboxComponent,\n FButtonDirective,\n TreeSelectComponent,\n TableComponent,\n TooltipDirective,\n UiIconComponent,\n HasPermissionDirective,\n UserSelectComponent,\n TranslatePipe,\n ],\n template: `\n <div class=\"user-role-selector\">\n <!-- User and Branch Selectors -->\n <div class=\"surface-card p-4 rounded-border mb-4 shadow-sm\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-5\">\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"user\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.user' | translate }}\n </label>\n <lib-user-select\n #userSelect\n [value]=\"selectedUserId()\"\n (valueChange)=\"onUserChange($event)\"\n [isEditMode]=\"true\"\n [placeHolder]=\"\n 'iam.permission.select.user.placeholder' | translate\n \"\n />\n </div>\n\n @if (showBranchSelector()) {\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"building\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.branch' | translate }}\n </label>\n <f-treeselect\n [ngModel]=\"selectedBranchId()\"\n (ngModelChange)=\"selectedBranchId.set($event ?? undefined)\"\n [options]=\"branchTreeNodes()\"\n [placeholder]=\"\n 'iam.permission.select.branch.placeholder' | translate\n \"\n [showClear]=\"true\"\n [filter]=\"true\"\n [filterPlaceholder]=\"'shared.search' | translate\"\n [emptyMessage]=\"'shared.no.results' | translate\"\n class=\"w-full\"\n />\n <small class=\"text-muted-color block mt-1\">\n {{\n (branches().length !== 1\n ? 'iam.branch.permitted.count.plural'\n : 'iam.branch.permitted.count'\n ) | translate: { count: branches().length }\n }}\n </small>\n </div>\n }\n </div>\n </div>\n\n @if (!selectedUserId()) {\n <div class=\"empty-state border border-dashed border-surface rounded-border p-8 text-center\">\n <div class=\"empty-state-icon mx-auto mb-3\">\n <ui-icon name=\"user\" class=\"text-primary\"></ui-icon>\n </div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.empty.user.roles.title' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{ 'iam.permission.empty.user.roles.description' | translate }}\n </p>\n </div>\n }\n\n @if (selectedUserId()) {\n <!-- Loading State -->\n @if (loading()) {\n <div\n class=\"surface-card p-5 rounded-border shadow-sm flex justify-center\"\n >\n <ui-icon name=\"loader-circle\" spin class=\"text-primary text-5xl\"></ui-icon>\n </div>\n }\n\n <!-- Role List -->\n @if (!loading() && roles().length > 0) {\n <div class=\"surface-card p-4 rounded-border shadow-sm\">\n <div\n class=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-3 mb-4\"\n >\n <div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.role.assignments' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{\n 'iam.permission.roles.available'\n | translate: { count: roles().length }\n }}\n </p>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelections(true)\"\n >\n <ui-icon pButtonIcon name=\"check\"></ui-icon>\n <span pButtonLabel>{{ 'shared.select.all' | translate }}</span>\n </button>\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelections(false)\"\n >\n <ui-icon pButtonIcon name=\"times\"></ui-icon>\n <span pButtonLabel>{{ 'shared.deselect.all' | translate }}</span>\n </button>\n <button\n fButton\n *hasPermission=\"USER_ROLE_PERMISSIONS.ASSIGN\"\n [disabled]=\"!canSave() || saving()\"\n size=\"small\"\n (click)=\"saveChanges()\"\n >\n @if (saving()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"save\"></ui-icon>\n }\n <span pButtonLabel>{{ 'shared.save.changes' | translate }}</span>\n </button>\n </div>\n </div>\n\n <!-- Role Table -->\n <div class=\"overflow-x-auto -mx-4 sm:mx-0\">\n <f-table\n [value]=\"roles()\"\n [rows]=\"10\"\n [paginator]=\"roles().length > 10\"\n [rowsPerPageOptions]=\"[10, 20, 50]\"\n [globalFilterFields]=\"['name', 'code', 'description']\"\n [showCurrentPageReport]=\"true\"\n [currentPageReportTemplate]=\"\n 'iam.pagination.roles.template' | translate\n \"\n [tableStyle]=\"{ 'min-width': '35rem' }\"\n >\n <ng-template #header>\n <tr>\n <th style=\"width: 3rem\">\n <f-checkbox\n [ngModel]=\"allSelected()\"\n [binary]=\"true\"\n (ngModelChange)=\"toggleAll()\"\n [fTooltip]=\"'shared.select.deselect.all' | translate\"\n tooltipPosition=\"top\"\n />\n </th>\n <th>{{ 'shared.name' | translate }}</th>\n <th class=\"hidden sm:table-cell\">\n {{ 'shared.code' | translate }}\n </th>\n <th class=\"hidden md:table-cell\">\n {{ 'shared.description' | translate }}\n </th>\n </tr>\n </ng-template>\n <ng-template #body let-role>\n <tr>\n <td>\n <f-checkbox\n [ngModel]=\"selectionMap()[role.id]\"\n [binary]=\"true\"\n (ngModelChange)=\"onRoleToggle(role, $event)\"\n [fTooltip]=\"getTooltip(role)\"\n tooltipPosition=\"top\"\n />\n </td>\n <td>{{ role.name }}</td>\n <td class=\"hidden sm:table-cell\">{{ role.code || '-' }}</td>\n <td class=\"hidden md:table-cell\">\n {{ role.description || '-' }}\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"4\" class=\"text-center p-4 text-muted-color\">\n @if (loading()) {\n <ui-icon name=\"loader-circle\" spin></ui-icon>\n {{ 'shared.loading.roles' | translate }}\n } @else {\n {{ 'iam.permission.no.roles.available' | translate }}\n }\n </td>\n </tr>\n </ng-template>\n </f-table>\n </div>\n </div>\n\n <!-- Change Summary -->\n @if (hasChanges()) {\n <div class=\"border border-surface rounded-border p-3 mt-4\">\n <div class=\"flex items-center gap-2 mb-3\">\n <ui-icon name=\"info-circle\" class=\"text-primary\"></ui-icon>\n <span class=\"font-bold\">{{\n 'shared.pending.changes' | translate\n }}</span>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n @if (pendingAdd().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"plus-circle\" class=\"text-green-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.assign' | translate }} ({{\n pendingAdd().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (role of pendingAdd(); track role.id) {\n <li class=\"text-sm mb-1\">{{ role.name }}</li>\n }\n </ul>\n </div>\n }\n @if (pendingRemove().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"minus-circle\" class=\"text-red-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.remove' | translate }} ({{\n pendingRemove().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (role of pendingRemove(); track role.id) {\n <li class=\"text-sm mb-1\">{{ role.name }}</li>\n }\n </ul>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (!loading() && roles().length === 0) {\n <div class=\"surface-card p-5 rounded-border shadow-sm text-center\">\n <ui-icon name=\"info-circle\" class=\"text-muted-color mb-3 block text-5xl\"></ui-icon>\n <p class=\"text-muted-color m-0\">\n {{ 'iam.permission.no.roles.for.user' | translate }}\n </p>\n </div>\n }\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n .empty-state-icon {\n width: 3rem;\n height: 3rem;\n border-radius: 9999px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--f-primary-50, rgba(59, 130, 246, 0.08));\n }\n :host-context(.app-dark) .empty-state-icon {\n background-color: rgba(96, 165, 250, 0.12);\n }\n `,\n ],\n})\nexport class UserRoleSelectorComponent {\n readonly USER_ROLE_PERMISSIONS = USER_ROLE_PERMISSIONS;\n\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n private readonly userPermissionProvider = inject(USER_PERMISSION_PROVIDER);\n private readonly roleApi = inject(RoleApiService);\n private readonly permissionApi = inject(PermissionApiService);\n private readonly messageService = inject(MessageService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n\n private readonly userSelectRef = viewChild<UserSelectComponent>('userSelect');\n\n private translate(\n key: string,\n vars?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n\n onUserChange(userId: string | null): void {\n const previousUserId = this.selectedUserId();\n if (userId === previousUserId) return;\n\n if (this.hasChanges()) {\n this.confirmationService.confirm({\n header: this.translate('iam.permission.unsaved.changes.title'),\n message: this.translate('iam.permission.unsaved.changes.message'),\n icon: 'exclamation-triangle',\n acceptLabel: this.translate('iam.permission.unsaved.changes.discard'),\n rejectLabel: this.translate('shared.cancel'),\n accept: () => this.selectedUserId.set(userId),\n reject: () => this.userSelectRef()?.value.set(previousUserId),\n });\n return;\n }\n\n this.selectedUserId.set(userId);\n }\n\n readonly selectedUserId = signal<string | null>(null);\n readonly selectedBranchId = signal<string | undefined>(undefined);\n private readonly _branches = signal<IBranch[]>([]);\n readonly branches = this._branches.asReadonly();\n\n readonly loading = signal(false);\n readonly saving = signal(false);\n\n private readonly _roles = signal<IRole[]>([]);\n readonly roles = this._roles.asReadonly();\n\n private readonly _selectionMap = signal<Record<string, boolean>>({});\n readonly selectionMap = this._selectionMap.asReadonly();\n\n private readonly _initialSelection = signal<Record<string, boolean>>({});\n private readonly initialSelection = this._initialSelection.asReadonly();\n\n readonly showBranchSelector = computed(\n () => isCompanyFeatureEnabled(this.appConfig) === true,\n );\n\n readonly branchTreeNodes = computed(() =>\n buildBranchTreeNodes(this.branches()),\n );\n\n readonly allSelected = computed(() => {\n const selMap = this.selectionMap();\n const total = this.roles().length;\n if (total === 0) return false;\n\n const selected = Object.values(selMap).filter((v) => v).length;\n return selected === total;\n });\n\n readonly hasChanges = computed(() => {\n const current = this.selectionMap();\n const initial = this.initialSelection();\n\n const currentKeys = Object.keys(current);\n const initialKeys = Object.keys(initial);\n\n if (currentKeys.length !== initialKeys.length) return true;\n return currentKeys.some((key) => current[key] !== initial[key]);\n });\n\n readonly pendingAdd = computed(() => {\n const current = this.selectionMap();\n const initial = this.initialSelection();\n const allRoles = this.roles();\n\n return allRoles.filter(\n (role) => current[role.id as string] && !initial[role.id as string],\n );\n });\n\n readonly pendingRemove = computed(() => {\n const current = this.selectionMap();\n const initial = this.initialSelection();\n const allRoles = this.roles();\n\n return allRoles.filter(\n (role) => !current[role.id as string] && initial[role.id as string],\n );\n });\n\n readonly canSave = computed(() => {\n return this.hasChanges() && !this.saving();\n });\n\n constructor() {\n effect(() => {\n const userId = this.selectedUserId();\n\n if (userId) {\n if (isCompanyFeatureEnabled(this.appConfig)) {\n this.loadUserBranches(userId);\n }\n this.loadData();\n } else {\n this._branches.set([]);\n this.selectedBranchId.set(undefined);\n this.resetState();\n }\n });\n\n effect(() => {\n const userId = this.selectedUserId();\n const branchId = this.selectedBranchId();\n\n if (\n isCompanyFeatureEnabled(this.appConfig) &&\n userId &&\n branchId !== undefined\n ) {\n this.loadData();\n }\n });\n }\n\n private async loadUserBranches(userId: string): Promise<void> {\n try {\n const companyId =\n this.companyContext.currentCompanyInfo()?.id || undefined;\n if (!companyId) {\n this._branches.set([]);\n return;\n }\n\n const response = await firstValueFrom(\n this.userPermissionProvider.getUserBranchPermissions(userId, companyId),\n );\n if (this.selectedUserId() !== userId) return;\n this._branches.set(toUserBranches(response?.data));\n } catch {\n // Error toast handled by global interceptor\n }\n }\n\n private async loadData(): Promise<void> {\n const userId = this.selectedUserId();\n if (!userId) return;\n\n const branchId = this.selectedBranchId();\n\n this.loading.set(true);\n try {\n const rolesResponse = await this.roleApi.getAll({\n pagination: { currentPage: 0, pageSize: MAX_DROPDOWN_ITEMS },\n });\n const rolesList = rolesResponse?.data ?? [];\n\n this._roles.set(rolesList);\n\n const query =\n isCompanyFeatureEnabled(this.appConfig) && branchId\n ? { branchId }\n : undefined;\n\n const assignedResponse = await firstValueFrom(\n this.permissionApi.getUserRoles(userId, query),\n );\n const assignedIds = new Set(\n (assignedResponse?.data || []).map((r) => r.roleId),\n );\n\n const selMap: Record<string, boolean> = {};\n rolesList.forEach((role: IRole) => {\n selMap[role.id as string] = assignedIds.has(role.id as string);\n });\n\n this._selectionMap.set(selMap);\n this._initialSelection.set({ ...selMap });\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.loading.set(false);\n }\n }\n\n getTooltip(role: IRole): string {\n const selMap = this.selectionMap();\n const isCurrentlySelected = selMap[role.id as string];\n\n if (isCurrentlySelected) {\n return `[${this.translate('shared.assigned')}] ${this.translate('iam.tooltip.assigned.to.user')}\\n\\n[${this.translate('shared.remove')}] ${this.translate('iam.tooltip.click.to.remove.role.from.user')}`;\n }\n\n return `[${this.translate('shared.add')}] ${this.translate('iam.tooltip.click.to.assign.role.to.user')}`;\n }\n\n onRoleToggle(role: IRole, newValue: boolean): void {\n const selMap = { ...this.selectionMap() };\n selMap[role.id as string] = newValue;\n this._selectionMap.set(selMap);\n }\n\n toggleAll(): void {\n this.setAllSelections(!this.allSelected());\n }\n\n protected setAllSelections(value: boolean): void {\n const selMap: Record<string, boolean> = {};\n this.roles().forEach((role) => {\n selMap[role.id as string] = value;\n });\n this._selectionMap.set(selMap);\n }\n\n async saveChanges(): Promise<void> {\n const userId = this.selectedUserId();\n if (!userId) return;\n\n const branchId = this.selectedBranchId();\n const companyId = this.companyContext.currentCompanyInfo()?.id || undefined;\n\n if (isCompanyFeatureEnabled(this.appConfig) && !companyId) {\n this.messageService.add({\n severity: 'warn',\n summary: this.translate('shared.warning'),\n detail: this.translate('iam.permission.company.required'),\n });\n return;\n }\n\n const items: Array<{ id: string; action: PermissionAction }> = [];\n\n this.pendingAdd().forEach((role) => {\n items.push({ id: role.id as string, action: 'add' });\n });\n\n this.pendingRemove().forEach((role) => {\n items.push({ id: role.id as string, action: 'remove' });\n });\n\n if (items.length === 0) return;\n\n this.saving.set(true);\n try {\n const payload: {\n userId: string;\n items: typeof items;\n companyId?: string;\n branchId?: string;\n } = { userId, items };\n\n if (isCompanyFeatureEnabled(this.appConfig)) {\n if (companyId) {\n payload.companyId = companyId;\n }\n if (branchId) {\n payload.branchId = branchId;\n }\n }\n\n const response = await firstValueFrom(\n this.permissionApi.assignUserRoles(payload),\n );\n\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response?.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : response?.message,\n });\n\n this._initialSelection.set({ ...this.selectionMap() });\n } catch {\n // Error toast handled by global interceptor\n } finally {\n this.saving.set(false);\n }\n }\n\n private resetState(): void {\n this._roles.set([]);\n this._selectionMap.set({});\n this._initialSelection.set({});\n }\n}\n","import { Component, computed, effect, inject, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { APP_CONFIG, isCompanyFeatureEnabled } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport {\n CheckboxComponent,\n FButtonDirective,\n MessageService,\n SelectComponent,\n TreeSelectComponent,\n TagComponent,\n TooltipDirective,\n TreeTableComponent,\n TreeTableTogglerComponent,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n buildBranchTreeNodes,\n HasPermissionDirective,\n TranslatePipe,\n USER_ACTION_PERMISSIONS,\n USER_PERMISSION_PROVIDER,\n UserSelectComponent,\n} from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { IActionTreeDto, IBranch, ICompany } from '../interfaces/public-api';\nimport { ActionApiService } from '../services/action-api.service';\nimport { PermissionApiService } from '../services/permission-api.service';\nimport { buildTreeFromFlat } from '../utils/tree-utils';\nimport { toUserBranches } from '../utils/user-branch.util';\nimport { BaseActionSelectorComponent } from './base-action-selector';\n\n@Component({\n selector: 'flusys-user-action-selector',\n imports: [\n FormsModule,\n CheckboxComponent,\n FButtonDirective,\n SelectComponent,\n TreeSelectComponent,\n TagComponent,\n TooltipDirective,\n TreeTableComponent,\n TreeTableTogglerComponent,\n UiIconComponent,\n HasPermissionDirective,\n UserSelectComponent,\n TranslatePipe,\n ],\n template: `\n <div class=\"user-action-selector\">\n <div class=\"surface-card p-4 rounded-border mb-4 shadow-sm\">\n <div\n class=\"grid grid-cols-1 gap-5\"\n [class.sm:grid-cols-3]=\"showCompanySelector()\"\n [class.sm:grid-cols-2]=\"!showCompanySelector()\"\n >\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"user\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.user' | translate }}\n </label>\n <lib-user-select\n #userSelect\n [value]=\"selectedUserId()\"\n (valueChange)=\"onUserSelect($event)\"\n [isEditMode]=\"true\"\n [placeHolder]=\"\n 'iam.permission.select.user.placeholder' | translate\n \"\n />\n </div>\n\n @if (showCompanySelector()) {\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"building\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.company' | translate }}\n </label>\n <f-select\n [ngModel]=\"selectedCompanyId()\"\n (ngModelChange)=\"onCompanyChange($event)\"\n [options]=\"companies()\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"\n 'iam.permission.select.company.placeholder' | translate\n \"\n [filter]=\"true\"\n class=\"w-full\"\n />\n </div>\n }\n\n @if (showBranchSelector()) {\n <div>\n <label class=\"block font-semibold mb-2\">\n <ui-icon name=\"building\" class=\"mr-2 text-primary\"></ui-icon>\n {{ 'iam.permission.select.branch' | translate }}\n </label>\n <f-treeselect\n [ngModel]=\"selectedBranchId()\"\n (ngModelChange)=\"onBranchChange($event ?? undefined)\"\n [options]=\"branchTreeNodes()\"\n [placeholder]=\"\n 'iam.permission.select.branch.placeholder' | translate\n \"\n [showClear]=\"true\"\n [filter]=\"true\"\n [filterPlaceholder]=\"'shared.search' | translate\"\n [emptyMessage]=\"'shared.no.results' | translate\"\n class=\"w-full\"\n />\n <small class=\"text-muted-color block mt-1\">\n {{\n (branches().length !== 1\n ? 'iam.branch.permitted.count.plural'\n : 'iam.branch.permitted.count'\n ) | translate: { count: branches().length }\n }}\n </small>\n </div>\n }\n </div>\n </div>\n\n @if (!selectedUserId()) {\n <div class=\"empty-state border border-dashed border-surface rounded-border p-8 text-center\">\n <div class=\"empty-state-icon mx-auto mb-3\">\n <ui-icon name=\"key\" class=\"text-primary\"></ui-icon>\n </div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.empty.user.actions.title' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{ 'iam.permission.empty.user.actions.description' | translate }}\n </p>\n </div>\n }\n\n @if (selectedUserId()) {\n @if (loading()) {\n <div class=\"flex justify-center p-5\">\n <ui-icon name=\"loader-circle\" spin class=\"text-4xl\"></ui-icon>\n </div>\n }\n\n @if (!loading() && actions().length > 0) {\n <div class=\"surface-card p-4 rounded-border shadow-sm\">\n <div\n class=\"flex flex-col md:flex-row justify-between items-start md:items-center gap-3 mb-4\"\n >\n <div>\n <h5 class=\"m-0 mb-1\">\n {{ 'iam.permission.direct.action.permissions' | translate }}\n </h5>\n <p class=\"text-sm text-muted-color m-0\">\n {{\n 'iam.permission.actions.available'\n | translate: { count: actions().length }\n }}\n </p>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelection(true)\"\n >\n <ui-icon pButtonIcon name=\"check\"></ui-icon>\n <span pButtonLabel>{{ 'shared.select.all' | translate }}</span>\n </button>\n <button\n fButton\n [outlined]=\"true\"\n size=\"small\"\n severity=\"secondary\"\n (click)=\"setAllSelection(false)\"\n >\n <ui-icon pButtonIcon name=\"times\"></ui-icon>\n <span pButtonLabel>{{ 'shared.deselect.all' | translate }}</span>\n </button>\n <button\n fButton\n *hasPermission=\"USER_ACTION_PERMISSIONS.ASSIGN\"\n [disabled]=\"!canSave() || saving()\"\n size=\"small\"\n (click)=\"saveChanges()\"\n >\n @if (saving()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"save\"></ui-icon>\n }\n <span pButtonLabel>{{ 'shared.save.changes' | translate }}</span>\n </button>\n </div>\n </div>\n\n @if (invalidActionsCount() > 0) {\n <div class=\"validation-warning rounded-border p-3 mb-4\">\n <div class=\"flex items-start gap-2\">\n <ui-icon name=\"exclamation-triangle\" class=\"text-xl\"></ui-icon>\n <div class=\"flex-1\">\n <span class=\"font-semibold\"\n >{{ 'iam.validation.warning.title' | translate }}:</span\n >\n <p class=\"text-sm mt-1 mb-0\">\n {{\n (invalidActionsCount() > 1\n ? 'iam.validation.unmet.prerequisites.plural'\n : 'iam.validation.unmet.prerequisites.singular'\n ) | translate: { count: invalidActionsCount() }\n }}\n </p>\n </div>\n </div>\n </div>\n }\n\n <div class=\"overflow-x-auto -mx-4 sm:mx-0\">\n <f-treetable\n [value]=\"treeNodes()\"\n dataKey=\"id\"\n [tableStyle]=\"{ 'min-width': '50rem' }\"\n >\n <ng-template #header>\n <tr>\n <th class=\"w-12\">\n <f-checkbox\n [ngModel]=\"allSelected()\"\n [binary]=\"true\"\n (ngModelChange)=\"toggleAll()\"\n [fTooltip]=\"'shared.select.deselect.all' | translate\"\n tooltipPosition=\"top\"\n />\n </th>\n <th>{{ 'shared.name' | translate }}</th>\n <th class=\"hidden md:table-cell\">\n {{ 'shared.code' | translate }}\n </th>\n <th>{{ 'iam.action.type' | translate }}</th>\n <th class=\"hidden lg:table-cell\">\n {{ 'shared.description' | translate }}\n </th>\n </tr>\n </ng-template>\n <ng-template #body let-rowNode let-rowData=\"rowData\">\n @let hasUnmet = hasUnmetPrerequisites(rowData);\n @let tooltip = getTooltip(rowData);\n <tr [class.highlight-warning]=\"hasUnmet\">\n <td class=\"w-12\">\n <f-checkbox\n [ngModel]=\"selectionMap()[rowData.id]\"\n [binary]=\"true\"\n (ngModelChange)=\"onActionToggle(rowData, $event)\"\n [fTooltip]=\"tooltip\"\n tooltipPosition=\"top\"\n />\n </td>\n <td>\n <f-treetabletoggler [rowNode]=\"rowNode\" />\n <span class=\"inline-flex items-center gap-2\">\n {{ rowData.name }}\n @if (hasUnmet) {\n <ui-icon name=\"exclamation-triangle\" class=\"text-orange-500\" [fTooltip]=\"\n 'iam.validation.unmet.prerequisites.tooltip'\n | translate\n \"\n tooltipPosition=\"top\"></ui-icon>\n }\n </span>\n </td>\n <td class=\"hidden md:table-cell\">\n {{ rowData.code || '-' }}\n </td>\n <td>\n <f-tag\n [value]=\"rowData.actionType\"\n [severity]=\"\n rowData.actionType === 'backend' ? 'info' : 'success'\n \"\n />\n </td>\n <td class=\"hidden lg:table-cell\">\n {{ rowData.description || '-' }}\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"5\" class=\"text-center p-4 text-muted-color\">\n @if (loading()) {\n <ui-icon name=\"loader-circle\" spin></ui-icon>\n {{ 'shared.loading.actions' | translate }}\n } @else {\n {{ 'iam.permission.no.actions.available' | translate }}\n }\n </td>\n </tr>\n </ng-template>\n </f-treetable>\n </div>\n </div>\n\n @if (hasChanges()) {\n <div class=\"border border-surface rounded-border p-3 mt-4\">\n <div class=\"flex items-center gap-2 mb-3\">\n <ui-icon name=\"info-circle\" class=\"text-primary\"></ui-icon>\n <span class=\"font-bold\">{{\n 'shared.pending.changes' | translate\n }}</span>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n @if (pendingAdd().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"plus-circle\" class=\"text-green-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.assign' | translate }} ({{\n pendingAdd().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (action of pendingAdd(); track action.id) {\n <li class=\"text-sm mb-1\">{{ action.name }}</li>\n }\n </ul>\n </div>\n }\n @if (pendingRemove().length > 0) {\n <div>\n <div class=\"flex items-center gap-2 mb-2\">\n <ui-icon name=\"minus-circle\" class=\"text-red-500\"></ui-icon>\n <strong class=\"text-sm\"\n >{{ 'shared.to.remove' | translate }} ({{\n pendingRemove().length\n }})</strong\n >\n </div>\n <ul class=\"list-none p-0 m-0 pl-4\">\n @for (action of pendingRemove(); track action.id) {\n <li class=\"text-sm mb-1\">{{ action.name }}</li>\n }\n </ul>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (!loading() && actions().length === 0) {\n <div class=\"surface-card p-5 rounded-border shadow-sm text-center\">\n <ui-icon name=\"info-circle\" class=\"text-muted-color mb-3 block text-5xl\"></ui-icon>\n <p class=\"text-muted-color m-0\">\n {{ 'iam.permission.no.actions.for.user' | translate }}\n </p>\n </div>\n }\n }\n </div>\n `,\n styles: [\n `\n :host {\n display: block;\n }\n .empty-state-icon {\n width: 3rem;\n height: 3rem;\n border-radius: 9999px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: var(--f-primary-50, rgba(59, 130, 246, 0.08));\n }\n :host-context(.app-dark) .empty-state-icon {\n background-color: rgba(96, 165, 250, 0.12);\n }\n .validation-warning {\n background-color: var(--f-yellow-50, #fefce8);\n border-left: 4px solid var(--f-yellow-500, #eab308);\n color: var(--f-yellow-700, #a16207);\n }\n :host-context(.app-dark) .validation-warning {\n background-color: rgba(234, 179, 8, 0.1);\n color: var(--f-yellow-400, #facc15);\n }\n :host ::ng-deep tr.highlight-warning {\n background-color: var(--f-red-50, rgba(239, 68, 68, 0.1)) !important;\n }\n :host-context(.app-dark) ::ng-deep tr.highlight-warning {\n background-color: rgba(239, 68, 68, 0.15) !important;\n }\n `,\n ],\n})\nexport class UserActionSelectorComponent extends BaseActionSelectorComponent {\n readonly USER_ACTION_PERMISSIONS = USER_ACTION_PERMISSIONS;\n\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n private readonly userPermissionProvider = inject(USER_PERMISSION_PROVIDER);\n private readonly actionApi = inject(ActionApiService);\n private readonly permissionApi = inject(PermissionApiService);\n private readonly messageService = inject(MessageService);\n\n private readonly userSelectRef = viewChild<UserSelectComponent>('userSelect');\n\n private readonly _selectedUserId = signal<string | null>(null);\n readonly selectedUserId = this._selectedUserId.asReadonly();\n\n private readonly _selectedBranchId = signal<string | undefined>(undefined);\n readonly selectedBranchId = this._selectedBranchId.asReadonly();\n\n private readonly _selectedCompanyId = signal<string | undefined>(undefined);\n readonly selectedCompanyId = this._selectedCompanyId.asReadonly();\n\n private readonly _branches = signal<IBranch[]>([]);\n readonly branches = this._branches.asReadonly();\n\n private readonly _companies = signal<ICompany[]>([]);\n readonly companies = this._companies.asReadonly();\n\n private readonly isCompanyFeatureActive = computed(\n () => isCompanyFeatureEnabled(this.appConfig) === true,\n );\n\n readonly showCompanySelector = computed(\n () => this.isCompanyFeatureActive() && this.companies().length > 1,\n );\n\n readonly showBranchSelector = this.isCompanyFeatureActive;\n\n readonly branchTreeNodes = computed(() =>\n buildBranchTreeNodes(this.branches()),\n );\n\n constructor() {\n super();\n\n effect(() => {\n const userId = this.selectedUserId();\n this._selectedBranchId.set(undefined);\n this._selectedCompanyId.set(undefined);\n\n if (!userId) {\n this._branches.set([]);\n this._companies.set([]);\n this.resetState();\n return;\n }\n\n if (this.isCompanyFeatureActive()) {\n void this.selectUser(userId);\n } else {\n this.loadData();\n }\n });\n\n effect(() => {\n const branchId = this.selectedBranchId();\n const userId = this.selectedUserId();\n\n if (this.isCompanyFeatureActive() && userId && branchId !== undefined) {\n this.loadData();\n }\n });\n }\n\n onUserSelect(userId: string | null): void {\n const previousUserId = this.selectedUserId();\n if (userId === previousUserId) return;\n\n this.confirmSelectionChange(\n () => this._selectedUserId.set(userId),\n () => this.userSelectRef()?.value.set(previousUserId),\n );\n }\n\n onBranchChange(branchId: string | undefined): void {\n this._selectedBranchId.set(branchId);\n }\n\n // Runs directly (not via effect) so it can't race selectUser()'s async resolution\n onCompanyChange(companyId: string | undefined): void {\n this._selectedCompanyId.set(companyId);\n const userId = this.selectedUserId();\n if (!userId || !this.isCompanyFeatureActive()) return;\n void this.applyCompanySelection(userId, companyId);\n }\n\n private async selectUser(userId: string): Promise<void> {\n const companyId = await this.loadUserCompanies(userId);\n await this.applyCompanySelection(userId, companyId);\n }\n\n private async applyCompanySelection(\n userId: string,\n companyId: string | undefined,\n ): Promise<void> {\n this._selectedBranchId.set(undefined);\n this._branches.set([]);\n\n if (!companyId) {\n this._actionsTree.set([]);\n this._actions.set([]);\n return;\n }\n\n await this.loadUserBranches(userId, companyId);\n await this.loadData();\n }\n\n // Returns the company to scope to: the user's single company, the admin's own\n // company if the user belongs to it, or undefined if neither applies\n private async loadUserCompanies(userId: string): Promise<string | undefined> {\n try {\n const response = await firstValueFrom(\n this.userPermissionProvider.getUserCompanyPermissions(userId),\n );\n const userCompanies = response?.data ?? [];\n this._companies.set(userCompanies);\n\n if (userCompanies.length === 1) {\n this._selectedCompanyId.set(userCompanies[0].id);\n return userCompanies[0].id;\n }\n\n const ownCompanyId = this.companyContext.currentCompanyInfo()?.id;\n const fallbackId = userCompanies.find((c) => c.id === ownCompanyId)?.id;\n this._selectedCompanyId.set(fallbackId);\n return fallbackId;\n } catch {\n this._companies.set([]);\n this._selectedCompanyId.set(undefined);\n return undefined;\n }\n }\n\n protected getDefaultTooltip(isSelected: boolean): string {\n if (isSelected) {\n return `[${this.translate('shared.assigned')}] ${this.translate('iam.tooltip.assigned.to.user')}\\n\\n[${this.translate('shared.remove')}] ${this.translate('iam.tooltip.click.to.remove.user')}`;\n }\n return `[${this.translate('shared.add')}] ${this.translate('iam.tooltip.click.to.assign.user')}`;\n }\n\n private async loadUserBranches(userId: string, companyId: string): Promise<void> {\n try {\n const response = await firstValueFrom(\n this.userPermissionProvider.getUserBranchPermissions(userId, companyId),\n );\n if (!this.isCurrentSelection(userId, companyId)) return;\n this._branches.set(toUserBranches(response?.data));\n } catch {\n if (this.isCurrentSelection(userId, companyId)) this._branches.set([]);\n }\n }\n\n private isCurrentSelection(userId: string, companyId: string): boolean {\n return this.selectedUserId() === userId && this.selectedCompanyId() === companyId;\n }\n\n private async loadData(): Promise<void> {\n const userId = this.selectedUserId();\n if (!userId) return;\n\n const branchId = this.selectedBranchId();\n const companyId = this.selectedCompanyId();\n\n this.loading.set(true);\n try {\n const actionsResponse = await firstValueFrom(\n this.actionApi.getActionsForPermission(\n this.isCompanyFeatureActive() ? companyId : undefined,\n ),\n );\n\n const flatActions = actionsResponse?.data ?? [];\n const actionsTree = buildTreeFromFlat(flatActions) as IActionTreeDto[];\n\n this._actionsTree.set(actionsTree);\n this._actions.set(flatActions);\n\n const query = this.isCompanyFeatureActive()\n ? { companyId, branchId }\n : undefined;\n\n const assignedResponse = await firstValueFrom(\n this.permissionApi.getUserActions(userId, query),\n );\n const assignedIds = new Set(\n (assignedResponse?.data || []).map((a) => a.actionId),\n );\n\n const selMap = this.buildSelectionMap(flatActions, (action) =>\n assignedIds.has(action.id as string),\n );\n this._selectionMap.set(selMap);\n this._initialSelection.set({ ...selMap });\n } catch {\n } finally {\n this.loading.set(false);\n }\n }\n\n async saveChanges(): Promise<void> {\n const userId = this.selectedUserId();\n if (!userId) return;\n\n const branchId = this.selectedBranchId();\n const companyId = this.selectedCompanyId();\n\n if (this.isCompanyFeatureActive() && !companyId) {\n this.messageService.add({\n severity: 'warn',\n summary: this.translate('shared.warning'),\n detail: this.translate('iam.permission.company.required'),\n });\n return;\n }\n\n const invalidActions =\n this.permissionLogic.getActionsWithUnmetPrerequisites(\n this.selectionMap(),\n this.actions(),\n );\n if (invalidActions.length > 0) {\n this.permissionLogic.showValidationErrorDialog(\n invalidActions,\n this.selectionMap(),\n this.actions(),\n (newMap) => this._selectionMap.set(newMap),\n );\n return;\n }\n\n const items = this.buildPayloadItems();\n if (items.length === 0) return;\n\n this.saving.set(true);\n try {\n const payload: {\n userId: string;\n items: typeof items;\n companyId?: string;\n branchId?: string;\n } = { userId, items };\n\n if (this.isCompanyFeatureActive()) {\n if (companyId) payload.companyId = companyId;\n if (branchId) payload.branchId = branchId;\n }\n\n const response = await firstValueFrom(\n this.permissionApi.assignUserActions(payload),\n );\n\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response?.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : response?.message,\n });\n\n this._initialSelection.set({ ...this.selectionMap() });\n } catch {\n } finally {\n this.saving.set(false);\n }\n }\n}\n"],"mappings":"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"}
|