@atlashub/smartstack 3.21.0 → 3.25.0
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/dist/chunks/{AgentSkillsPage-7si3Ng8e.js → AgentSkillsPage-BWQSCYl-.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js.map → AgentSkillsPage-BWQSCYl-.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js → AgentSkillsPage-IQcMnBaD.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js.map → AgentSkillsPage-IQcMnBaD.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js → AgentWorkloadPage-DqrjkvWL.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js.map → AgentWorkloadPage-DqrjkvWL.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js → AgentWorkloadPage-w-HiyFYP.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js.map → AgentWorkloadPage-w-HiyFYP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js → ApiCatalogDetailPage-D3L8Yf4G.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js.map → ApiCatalogDetailPage-D3L8Yf4G.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js → ApiCatalogDetailPage-MPT3Kz6H.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js.map → ApiCatalogDetailPage-MPT3Kz6H.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js → ApiCatalogPage-D4Hg3uiS.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js.map → ApiCatalogPage-D4Hg3uiS.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js → ApiCatalogPage-DRg5Cz0r.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js.map → ApiCatalogPage-DRg5Cz0r.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js → ApplicationDetailPage-Caizuyn2.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js.map → ApplicationDetailPage-Caizuyn2.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js → ApplicationDetailPage-CuCW6aMB.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js.map → ApplicationDetailPage-CuCW6aMB.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js → ApplicationsDashboardPage-B2MW8-Kc.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js.map → ApplicationsDashboardPage-B2MW8-Kc.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js → ApplicationsDashboardPage-BDIjFIYZ.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js.map → ApplicationsDashboardPage-BDIjFIYZ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js → ApplicationsGridPage-DV-FihKj.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js.map → ApplicationsGridPage-DV-FihKj.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js → ApplicationsGridPage-DXsTfXPI.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js.map → ApplicationsGridPage-DXsTfXPI.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js → ApplicationsListPage--CGkyBuJ.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js.map → ApplicationsListPage--CGkyBuJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js → ApplicationsListPage-JUX823bh.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js.map → ApplicationsListPage-JUX823bh.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js → ApplicationsPage-6zgFye6w.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js.map → ApplicationsPage-6zgFye6w.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js → ApplicationsPage-CQPuuiO6.js} +4 -4
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js.map → ApplicationsPage-CQPuuiO6.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js → AssignmentRulesPage-CFffeEbo.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js.map → AssignmentRulesPage-CFffeEbo.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js → AssignmentRulesPage-D78UeUId.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js.map → AssignmentRulesPage-D78UeUId.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js → AssignmentsPage-Cww2ifZF.js} +2 -2
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js.map → AssignmentsPage-Cww2ifZF.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js → AssignmentsPage-DE_QS2LO.js} +2 -2
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js.map → AssignmentsPage-DE_QS2LO.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js → AuthCallbackPage-CA2nO6DG.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js.map → AuthCallbackPage-CA2nO6DG.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js → AuthCallbackPage-CDUAoX-N.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js.map → AuthCallbackPage-CDUAoX-N.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js → ConfirmEmailPage-BqsILAYH.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js.map → ConfirmEmailPage-BqsILAYH.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js → ConfirmEmailPage-INeHCuMB.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js.map → ConfirmEmailPage-INeHCuMB.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js → CreateSupportTicketPage-BWeuV2aU.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js.map → CreateSupportTicketPage-BWeuV2aU.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js → CreateSupportTicketPage-OBwF4v7b.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js.map → CreateSupportTicketPage-OBwF4v7b.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZ80NGV.js → DashboardPage-CKHqWrdS.js} +3 -3
- package/dist/chunks/{DashboardPage-CUZ80NGV.js.map → DashboardPage-CKHqWrdS.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CaNOAstg.js → DashboardPage-COmc9b__.js} +3 -3
- package/dist/chunks/{DashboardPage-CaNOAstg.js.map → DashboardPage-COmc9b__.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B48_rQFi.js → DashboardPage-CfKZHiSj.js} +2 -2
- package/dist/chunks/{DashboardPage-B48_rQFi.js.map → DashboardPage-CfKZHiSj.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZV1J9t.js → DashboardPage-CwEZZ3jx.js} +2 -2
- package/dist/chunks/{DashboardPage-CUZV1J9t.js.map → DashboardPage-CwEZZ3jx.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js → EscalationConfigPage--7lgZ0kJ.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js.map → EscalationConfigPage--7lgZ0kJ.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js → EscalationConfigPage-DPyiBcqV.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js.map → EscalationConfigPage-DPyiBcqV.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js → ForceChangePasswordPage-BE-6umub.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js.map → ForceChangePasswordPage-BE-6umub.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js → ForceChangePasswordPage-CnsYoWmV.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js.map → ForceChangePasswordPage-CnsYoWmV.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js → ForgotPasswordPage-CSq4DnFF.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js.map → ForgotPasswordPage-CSq4DnFF.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js → ForgotPasswordPage-DZLVolAC.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js.map → ForgotPasswordPage-DZLVolAC.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js → GroupDetailPage-Bf9Wb_2j.js} +5 -5
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js.map → GroupDetailPage-Bf9Wb_2j.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js → GroupDetailPage-R-hf3rJ7.js} +2 -2
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js.map → GroupDetailPage-R-hf3rJ7.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js → MyAccessRequestsPage-BIisvWM6.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js.map → MyAccessRequestsPage-BIisvWM6.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js → MyAccessRequestsPage-BLSV7Tbx.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js.map → MyAccessRequestsPage-BLSV7Tbx.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js → MyTenantsPage-D-7k9CP1.js} +3 -3
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js.map → MyTenantsPage-D-7k9CP1.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js → MyTenantsPage-DqGW6aDt.js} +2 -2
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js.map → MyTenantsPage-DqGW6aDt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js → MyTicketsPage--DgDsnZA.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js.map → MyTicketsPage--DgDsnZA.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js → MyTicketsPage-CqJ3Aqob.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js.map → MyTicketsPage-CqJ3Aqob.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js → NavigationAppsPage-Bebis_RT.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js.map → NavigationAppsPage-Bebis_RT.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js → NavigationAppsPage-THNPOAjv.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js.map → NavigationAppsPage-THNPOAjv.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-C29Lln5o.js → NotificationsPage-CAbNW_Cn.js} +2 -2
- package/dist/chunks/{NotificationsPage-C29Lln5o.js.map → NotificationsPage-CAbNW_Cn.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js → NotificationsPage-DxwizUhL.js} +2 -2
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js.map → NotificationsPage-DxwizUhL.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js → OnboardingWizardPage-C6HlbJ3K.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js.map → OnboardingWizardPage-C6HlbJ3K.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js → OnboardingWizardPage-CyC2zONO.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js.map → OnboardingWizardPage-CyC2zONO.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js → PermissionDetailPage-BDHiNgky.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js.map → PermissionDetailPage-BDHiNgky.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js → PermissionDetailPage-C5K17ydY.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js.map → PermissionDetailPage-C5K17ydY.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js → PermissionsPage-COI5LJPo.js} +2 -2
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js.map → PermissionsPage-COI5LJPo.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js → PermissionsPage-CkOwH2_d.js} +2 -2
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js.map → PermissionsPage-CkOwH2_d.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js → PortalDashboardPage-CoEC4CmC.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js → PortalDashboardPage-DrYymEf-.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js → PreferencesPage-CJRaU3ba.js} +2 -2
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js.map → PreferencesPage-CJRaU3ba.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-B81MsNV1.js → PreferencesPage-Cqr9mAab.js} +2 -2
- package/dist/chunks/{PreferencesPage-B81MsNV1.js.map → PreferencesPage-Cqr9mAab.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DDrl10zj.js → ProfilePage-BZVpg6-l.js} +2 -2
- package/dist/chunks/{ProfilePage-DDrl10zj.js.map → ProfilePage-BZVpg6-l.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DPoXwdnc.js → ProfilePage-Cu_FITeL.js} +2 -2
- package/dist/chunks/{ProfilePage-DPoXwdnc.js.map → ProfilePage-Cu_FITeL.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js → ReferencesManagementPage-DUlVk9Ps.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js.map → ReferencesManagementPage-DUlVk9Ps.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js → ReferencesManagementPage-ZCuYtqd7.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js.map → ReferencesManagementPage-ZCuYtqd7.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CiQib3-6.js → RegisterPage-C4xmVwh9.js} +2 -2
- package/dist/chunks/{RegisterPage-CiQib3-6.js.map → RegisterPage-C4xmVwh9.js.map} +1 -1
- package/dist/chunks/{RegisterPage-bXCcJD88.js → RegisterPage-DGyzoIHT.js} +2 -2
- package/dist/chunks/{RegisterPage-bXCcJD88.js.map → RegisterPage-DGyzoIHT.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js → ResetPasswordPage-DqDD6VPR.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js.map → ResetPasswordPage-DqDD6VPR.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js → ResetPasswordPage-Glu-aeqv.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js.map → ResetPasswordPage-Glu-aeqv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js → ResolutionModal-CxjANAOP.js} +2 -2
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js.map → ResolutionModal-CxjANAOP.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js → ResolutionModal-Duat18qV.js} +2 -2
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js.map → ResolutionModal-Duat18qV.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js → RoleDetailPage-BQffUSnt.js} +3 -3
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js.map → RoleDetailPage-BQffUSnt.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js → RoleDetailPage-JTm5lD1_.js} +2 -2
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js.map → RoleDetailPage-JTm5lD1_.js.map} +1 -1
- package/dist/chunks/{RolesPage-Pm-RN3lP.js → RolesPage-B9rRzciI.js} +2 -2
- package/dist/chunks/{RolesPage-Pm-RN3lP.js.map → RolesPage-B9rRzciI.js.map} +1 -1
- package/dist/chunks/{RolesPage-Cb8joqdJ.js → RolesPage-BN8_zMOC.js} +2 -2
- package/dist/chunks/{RolesPage-Cb8joqdJ.js.map → RolesPage-BN8_zMOC.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-B86McKM6.js → SlaConfigPage-B7kZNig4.js} +2 -2
- package/dist/chunks/{SlaConfigPage-B86McKM6.js.map → SlaConfigPage-B7kZNig4.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js → SlaConfigPage-okvZfA_K.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js.map → SlaConfigPage-okvZfA_K.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js → SupportPermissionsPage-DGAPqJbl.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js.map → SupportPermissionsPage-DGAPqJbl.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js → SupportPermissionsPage-Dg_wLOme.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js.map → SupportPermissionsPage-Dg_wLOme.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-BDguJ401.js → TemplatesPage-DT9fhlAU.js} +2 -2
- package/dist/chunks/{TemplatesPage-BDguJ401.js.map → TemplatesPage-DT9fhlAU.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DdnGgioU.js → TemplatesPage-DiEk538p.js} +2 -2
- package/dist/chunks/{TemplatesPage-DdnGgioU.js.map → TemplatesPage-DiEk538p.js.map} +1 -1
- package/dist/chunks/{TenantCard-ffwWsgFQ.js → TenantCard-BbSYk9_Z.js} +2 -2
- package/dist/chunks/{TenantCard-ffwWsgFQ.js.map → TenantCard-BbSYk9_Z.js.map} +1 -1
- package/dist/chunks/{TenantCard-CUjb6og9.js → TenantCard-CEkiKxcZ.js} +2 -2
- package/dist/chunks/{TenantCard-CUjb6og9.js.map → TenantCard-CEkiKxcZ.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js → TenantScopeSelector-BWfYxvEa.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js.map → TenantScopeSelector-BWfYxvEa.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js → TenantScopeSelector-D-BKgQPV.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js.map → TenantScopeSelector-D-BKgQPV.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js → TicketDetailPage-C1mNS9Up.js} +2 -2
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js.map → TicketDetailPage-C1mNS9Up.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js → TicketDetailPage-ieVDRh42.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js.map → TicketDetailPage-ieVDRh42.js.map} +1 -1
- package/dist/chunks/{TicketsPage-Bqd6moQy.js → TicketsPage-CnuWsnIW.js} +2 -2
- package/dist/chunks/{TicketsPage-Bqd6moQy.js.map → TicketsPage-CnuWsnIW.js.map} +1 -1
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js → TicketsPage-jjyY15_D.js} +2 -2
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js.map → TicketsPage-jjyY15_D.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js → UserCreateTicketPage-B8Tvf-ag.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js.map → UserCreateTicketPage-B8Tvf-ag.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js → UserCreateTicketPage-DnOsDlfO.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js.map → UserCreateTicketPage-DnOsDlfO.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js → UserDashboardPage-BrtkJ-NB.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js.map → UserDashboardPage-BrtkJ-NB.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js → UserDashboardPage-KLB5CQP5.js} +2 -2
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js.map → UserDashboardPage-KLB5CQP5.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-B110bmGX.js → UserDetailPage-U7smBQoF.js} +5 -5
- package/dist/chunks/{UserDetailPage-B110bmGX.js.map → UserDetailPage-U7smBQoF.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-CV2VCE46.js → UserDetailPage-_J6lcKAU.js} +2 -2
- package/dist/chunks/{UserDetailPage-CV2VCE46.js.map → UserDetailPage-_J6lcKAU.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js → UserTicketDetailPage-CWoYQgH-.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js → UserTicketDetailPage-DkufSlvZ.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js → UsersGroupsPage-C38s2-Rq.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js.map → UsersGroupsPage-C38s2-Rq.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js → UsersGroupsPage-Dq3rAteo.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js.map → UsersGroupsPage-Dq3rAteo.js.map} +1 -1
- package/dist/chunks/{UsersPage-Bg7033pp.js → UsersPage-B5C5KEUR.js} +2 -2
- package/dist/chunks/{UsersPage-Bg7033pp.js.map → UsersPage-B5C5KEUR.js.map} +1 -1
- package/dist/chunks/{UsersPage-TYAfwPY1.js → UsersPage-CXC9Hvq6.js} +2 -2
- package/dist/chunks/{UsersPage-TYAfwPY1.js.map → UsersPage-CXC9Hvq6.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js → accessRequestsApi-B-4TJ5_U.js} +2 -2
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js.map → accessRequestsApi-B-4TJ5_U.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js → accessRequestsApi-DZSfThpd.js} +2 -2
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js.map → accessRequestsApi-DZSfThpd.js.map} +1 -1
- package/dist/chunks/{aiApi-CsH8DXgs.js → aiApi-B20Teu2v.js} +2 -2
- package/dist/chunks/{aiApi-CsH8DXgs.js.map → aiApi-B20Teu2v.js.map} +1 -1
- package/dist/chunks/{aiApi-CVPzFTXa.js → aiApi-DMGz-RPM.js} +2 -2
- package/dist/chunks/{aiApi-CVPzFTXa.js.map → aiApi-DMGz-RPM.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js → applicationAnalyticsApi-Bwa75Fzd.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js.map → applicationAnalyticsApi-Bwa75Fzd.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js → applicationAnalyticsApi-CLBqRPfN.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js.map → applicationAnalyticsApi-CLBqRPfN.js.map} +1 -1
- package/dist/chunks/{groupsApi-BgCk2fsp.js → groupsApi-QzXI-5xu.js} +2 -2
- package/dist/chunks/{groupsApi-BgCk2fsp.js.map → groupsApi-QzXI-5xu.js.map} +1 -1
- package/dist/chunks/{groupsApi-BIbG665N.js → groupsApi-hB9kSWEd.js} +2 -2
- package/dist/chunks/{groupsApi-BIbG665N.js.map → groupsApi-hB9kSWEd.js.map} +1 -1
- package/dist/chunks/{index-Cb3LotuT.js → index--NGcBYUu.js} +3 -3
- package/dist/chunks/{index-Cb3LotuT.js.map → index--NGcBYUu.js.map} +1 -1
- package/dist/chunks/{index-C33zcyF4.js → index--aPwOFjF.js} +2 -2
- package/dist/chunks/{index-C33zcyF4.js.map → index--aPwOFjF.js.map} +1 -1
- package/dist/chunks/{index-sMr9qND_.js → index-0VrOtwP0.js} +2 -2
- package/dist/chunks/{index-sMr9qND_.js.map → index-0VrOtwP0.js.map} +1 -1
- package/dist/chunks/{index-DDKetfKq.js → index-37U271aw.js} +2 -2
- package/dist/chunks/{index-DDKetfKq.js.map → index-37U271aw.js.map} +1 -1
- package/dist/chunks/{index-B9fS7ir6.js → index-B7qZTuQ-.js} +2 -2
- package/dist/chunks/{index-B9fS7ir6.js.map → index-B7qZTuQ-.js.map} +1 -1
- package/dist/chunks/{index-CdjBY7L8.js → index-Bedzmqr-.js} +2 -2
- package/dist/chunks/{index-CdjBY7L8.js.map → index-Bedzmqr-.js.map} +1 -1
- package/dist/chunks/{index-CHG_O1fS.js → index-Betxo5g5.js} +2 -2
- package/dist/chunks/{index-CHG_O1fS.js.map → index-Betxo5g5.js.map} +1 -1
- package/dist/chunks/{index-jiGu-H8x.js → index-BmaJz475.js} +2 -2
- package/dist/chunks/{index-jiGu-H8x.js.map → index-BmaJz475.js.map} +1 -1
- package/dist/chunks/{index-C53JoVNk.js → index-Buhqag3v.js} +2 -2
- package/dist/chunks/{index-C53JoVNk.js.map → index-Buhqag3v.js.map} +1 -1
- package/dist/chunks/{index-DO0Rw7hX.js → index-C3VxlfKq.js} +2 -2
- package/dist/chunks/{index-DO0Rw7hX.js.map → index-C3VxlfKq.js.map} +1 -1
- package/dist/chunks/{index-CSQ60fpG.js → index-CgpRo8Oe.js} +2 -2
- package/dist/chunks/{index-CSQ60fpG.js.map → index-CgpRo8Oe.js.map} +1 -1
- package/dist/chunks/{index-B-e-ELsf.js → index-DOY0w8Iu.js} +8 -8
- package/dist/chunks/{index-B-e-ELsf.js.map → index-DOY0w8Iu.js.map} +1 -1
- package/dist/chunks/{index-D2REDIRX.js → index-DwuvIOrQ.js} +2 -2
- package/dist/chunks/{index-D2REDIRX.js.map → index-DwuvIOrQ.js.map} +1 -1
- package/dist/chunks/{index-DCcl7Qof.js → index-DzedSLdI.js} +2 -2
- package/dist/chunks/{index-DCcl7Qof.js.map → index-DzedSLdI.js.map} +1 -1
- package/dist/chunks/{index-2wUhd9Lu.js → index-IgLVXPg8.js} +10 -10
- package/dist/chunks/index-IgLVXPg8.js.map +1 -0
- package/dist/chunks/{index-CwSaRXXg.js → index-lpIzhufD.js} +1916 -1900
- package/dist/chunks/index-lpIzhufD.js.map +1 -0
- package/dist/chunks/{index-Cuwn2q-f.js → index-mLUKwbGl.js} +4 -4
- package/dist/chunks/{index-Cuwn2q-f.js.map → index-mLUKwbGl.js.map} +1 -1
- package/dist/chunks/{index-B0mk2tNY.js → index-tO6MMIFB.js} +2 -2
- package/dist/chunks/{index-B0mk2tNY.js.map → index-tO6MMIFB.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js → tenantIconMap-BQD9byc8.js} +2 -2
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js.map → tenantIconMap-BQD9byc8.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js → tenantIconMap-CTMuSt18.js} +2 -2
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js.map → tenantIconMap-CTMuSt18.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js → ticketingApi-BNIdox5t.js} +2 -2
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js.map → ticketingApi-BNIdox5t.js.map} +1 -1
- package/dist/chunks/{ticketingApi-r4Avm9iS.js → ticketingApi-J0vC_t7r.js} +2 -2
- package/dist/chunks/{ticketingApi-r4Avm9iS.js.map → ticketingApi-J0vC_t7r.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-B9bF4swg.js → useAccessRequests-DCNNLnxk.js} +3 -3
- package/dist/chunks/{useAccessRequests-B9bF4swg.js.map → useAccessRequests-DCNNLnxk.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js → useAccessRequests-DT7X4FAK.js} +2 -2
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js.map → useAccessRequests-DT7X4FAK.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js → useUserAccessRequests-BYbmG4c7.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js.map → useUserAccessRequests-BYbmG4c7.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js → useUserAccessRequests-CylKxRN6.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js.map → useUserAccessRequests-CylKxRN6.js.map} +1 -1
- package/dist/hooks/useCollapsibleState.d.ts +5 -2
- package/dist/hooks/useCollapsibleState.d.ts.map +1 -1
- package/dist/i18n/config.d.ts +1 -0
- package/dist/i18n/config.d.ts.map +1 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/dist/utils/permissions.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-2wUhd9Lu.js.map +0 -1
- package/dist/chunks/index-CwSaRXXg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssignmentsPage-sRCCBmRc.js","sources":["../../src/components/platform/administration/PermissionMatrixTable.tsx","../../src/components/platform/administration/PermissionMatrixFilters.tsx","../../src/pages/platform/administration/permissions/AssignmentsPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport React, { useState, createRef, useMemo, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Lock, ChevronRight, ChevronDown, FolderOpen, Box, FileText, Database } from 'lucide-react';\r\nimport type { ResourceNode, RolePermissions, PermissionInheritanceInfo } from '@/hooks/usePermissionMatrix';\r\nimport type { MatrixRoleDto } from '@/services/api/adminApi';\r\nimport type { PermissionStatus, ApplicationGroupWithSections, ModuleWithSections } from './permissions/types';\r\nimport { groupByApplicationWithSections, calculatePermissionStatus, getPermissionCellBackground } from '@/utils/permissionUtils';\r\nimport { PermissionStatusIndicator } from './permissions/PermissionStatusIndicator';\r\nimport { PermissionPopover } from './PermissionPopover';\r\n\r\n// Sub-component for rendering section and resource rows\r\ninterface SectionResourceRowsProps {\r\n readonly section: ResourceNode;\r\n readonly resources: ResourceNode[];\r\n readonly moduleIndex: number;\r\n readonly sectionIndex: number;\r\n readonly isCollapsed: boolean;\r\n readonly collapsedSections: Set<string>;\r\n readonly paginatedRoles: MatrixRoleDto[];\r\n readonly canEditSystemRoles?: boolean;\r\n readonly statusFilters?: Set<PermissionStatus>;\r\n readonly openPopover: { roleId: string; resourceId: string } | null;\r\n readonly onToggleCollapse: (resourceId: string, level: 'module' | 'section' | 'resource') => void;\r\n readonly onTogglePermission: (roleId: string, permissionId: string) => void;\r\n readonly onCellClick: (roleId: string, resourceId: string) => void;\r\n readonly setOpenPopover: (state: { roleId: string; resourceId: string } | null) => void;\r\n readonly renderResourceRow: (resource: ResourceNode, rowIndex: number, level: 'module' | 'section' | 'resource', hasChildren: boolean, isCollapsed: boolean) => React.ReactNode;\r\n}\r\n\r\nfunction SectionResourceRows({\r\n section,\r\n resources,\r\n moduleIndex,\r\n sectionIndex,\r\n isCollapsed: _isCollapsed,\r\n collapsedSections,\r\n paginatedRoles: _paginatedRoles,\r\n canEditSystemRoles: _canEditSystemRoles,\r\n statusFilters: _statusFilters,\r\n openPopover: _openPopover,\r\n onToggleCollapse: _onToggleCollapse,\r\n onTogglePermission: _onTogglePermission,\r\n onCellClick: _onCellClick,\r\n setOpenPopover: _setOpenPopover,\r\n renderResourceRow,\r\n}: SectionResourceRowsProps) {\r\n const isSectionCollapsed = collapsedSections.has(section.id);\r\n const hasResources = resources.length > 0;\r\n\r\n return (\r\n <React.Fragment key={section.id}>\r\n {/* Section Row */}\r\n {renderResourceRow(section, moduleIndex + sectionIndex + 1, 'section', hasResources, isSectionCollapsed)}\r\n\r\n {/* Resource Rows (if section has resources and is not collapsed) */}\r\n {hasResources && !isSectionCollapsed && resources.map((resource, resourceIndex) =>\r\n renderResourceRow(resource, moduleIndex + sectionIndex + resourceIndex + 2, 'resource', false, false)\r\n )}\r\n </React.Fragment>\r\n );\r\n}\r\n\r\ninterface PermissionMatrixTableProps {\r\n readonly roles: MatrixRoleDto[];\r\n readonly resources: ResourceNode[];\r\n readonly assignments: RolePermissions;\r\n readonly canEditSystemRoles?: boolean;\r\n readonly onTogglePermission: (roleId: string, permissionId: string) => void;\r\n readonly getPermissionInheritance: (roleId: string, permissionId: string) => PermissionInheritanceInfo;\r\n // Role pagination props (controlled from parent)\r\n readonly rolesPerPage: number;\r\n readonly rolePageIndex: number;\r\n // Module pagination props (controlled from parent)\r\n readonly modulesPerPage: number;\r\n readonly modulePageIndex: number;\r\n // Collapsed state (controlled from parent for proper pagination)\r\n readonly collapsedApps: Set<string>;\r\n readonly onToggleApp: (appKey: string) => void;\r\n // Status filter - cells not matching will be dimmed\r\n readonly statusFilters?: Set<PermissionStatus>;\r\n}\r\n\r\nexport function PermissionMatrixTable({\r\n roles,\r\n resources,\r\n canEditSystemRoles = false,\r\n onTogglePermission,\r\n getPermissionInheritance,\r\n rolesPerPage,\r\n rolePageIndex,\r\n modulesPerPage,\r\n modulePageIndex,\r\n collapsedApps,\r\n onToggleApp,\r\n statusFilters,\r\n}: PermissionMatrixTableProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const [openPopover, setOpenPopover] = useState<{ roleId: string; resourceId: string } | null>(null);\r\n const [collapsedModules, setCollapsedModules] = useState<Set<string>>(new Set());\r\n const [collapsedSections, setCollapsedSections] = useState<Set<string>>(new Set());\r\n\r\n const toggleCollapsedItem = useCallback((id: string, setCollapsed: (fn: (prev: Set<string>) => Set<string>) => void) => {\r\n setCollapsed(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n }, []);\r\n\r\n // Toggle module collapse state\r\n const toggleModule = useCallback((moduleId: string) => {\r\n toggleCollapsedItem(moduleId, setCollapsedModules);\r\n }, [toggleCollapsedItem]);\r\n\r\n // Toggle section collapse state\r\n const toggleSection = useCallback((sectionId: string) => {\r\n toggleCollapsedItem(sectionId, setCollapsedSections);\r\n }, [toggleCollapsedItem]);\r\n\r\n // Get total modules count (only modules, not sections)\r\n const moduleCount = useMemo(() => {\r\n return resources.filter(r => r.level === 'module').length;\r\n }, [resources]);\r\n\r\n // Paginate roles based on props\r\n const paginatedRoles = useMemo(() => {\r\n const start = rolePageIndex * rolesPerPage;\r\n return roles.slice(start, start + rolesPerPage);\r\n }, [roles, rolePageIndex, rolesPerPage]);\r\n\r\n // Group ALL resources by context with sections\r\n const allGroupedResources = useMemo(() => {\r\n return groupByApplicationWithSections(resources);\r\n }, [resources]);\r\n\r\n\r\n const paginateAppGroups = useCallback(() => {\r\n const startIndex = modulePageIndex * modulesPerPage;\r\n const endIndex = startIndex + modulesPerPage;\r\n const visibleIndexRef = { current: 0 };\r\n const result: ApplicationGroupWithSections[] = [];\r\n\r\n for (const appGroup of allGroupedResources) {\r\n const isAppCollapsed = collapsedApps.has(appGroup.application);\r\n const paginatedModules: ModuleWithSections[] = [];\r\n\r\n if (!isAppCollapsed) {\r\n for (const moduleWithSections of appGroup.modules) {\r\n if (visibleIndexRef.current >= startIndex && visibleIndexRef.current < endIndex) {\r\n paginatedModules.push(moduleWithSections);\r\n }\r\n visibleIndexRef.current++;\r\n }\r\n }\r\n\r\n result.push({\r\n application: appGroup.application,\r\n modules: paginatedModules,\r\n });\r\n }\r\n\r\n return result;\r\n }, [allGroupedResources, modulePageIndex, modulesPerPage, collapsedApps]);\r\n\r\n const groupedResources = useMemo(() => {\r\n return paginateAppGroups();\r\n }, [paginateAppGroups]);\r\n\r\n const isPermissionGranted = useCallback((roleId: string, permissionId: string): boolean => {\r\n const inheritanceInfo = getPermissionInheritance(roleId, permissionId);\r\n return inheritanceInfo.isDirect || inheritanceInfo.isInherited;\r\n }, [getPermissionInheritance]);\r\n\r\n const getPermissionStatusForRole = useCallback((roleId: string, resource: ResourceNode): { status: PermissionStatus; grantedCount: number } => {\r\n return calculatePermissionStatus(resource, (permId) => isPermissionGranted(roleId, permId));\r\n }, [isPermissionGranted]);\r\n\r\n const handleCellClick = (roleId: string, resourceId: string) => {\r\n if (openPopover?.roleId === roleId && openPopover?.resourceId === resourceId) {\r\n setOpenPopover(null);\r\n } else {\r\n setOpenPopover({ roleId, resourceId });\r\n }\r\n };\r\n\r\n if (roles.length === 0 || moduleCount === 0) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {roles.length === 0 ? t('assignments.noRoles') : t('assignments.noResources')}\r\n </div>\r\n );\r\n }\r\n\r\n const getPaddingForLevel = (level: 'module' | 'section' | 'resource'): string => {\r\n switch (level) {\r\n case 'resource': return 'pl-28';\r\n case 'section': return 'pl-22';\r\n default: return 'pl-16';\r\n }\r\n };\r\n\r\n const getResourceIcon = (level: 'module' | 'section' | 'resource') => {\r\n if (level === 'resource') return <Database className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n if (level === 'section') return <FileText className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n return <Box className=\"h-3.5 w-3.5 text-[var(--text-secondary)]\" />;\r\n };\r\n\r\n const getResourceLabelClass = (level: 'module' | 'section' | 'resource'): string => {\r\n if (level === 'resource') return 'text-[var(--text-muted)] italic';\r\n if (level === 'section') return 'text-[var(--text-secondary)]';\r\n return 'font-medium text-[var(--text-primary)]';\r\n };\r\n\r\n const handleToggleCollapse = useCallback((resourceId: string, level: 'module' | 'section' | 'resource') => {\r\n if (level === 'module') {\r\n toggleModule(resourceId);\r\n } else if (level === 'section') {\r\n toggleSection(resourceId);\r\n }\r\n }, [toggleModule, toggleSection]);\r\n\r\n const renderToggleButton = (hasChildren: boolean, resourceId: string, level: 'module' | 'section' | 'resource', isCollapsed: boolean) => {\r\n if (!hasChildren) return null;\r\n return (\r\n <button\r\n onClick={() => handleToggleCollapse(resourceId, level)}\r\n className=\"p-0.5 hover:bg-[var(--bg-hover)] rounded\"\r\n >\r\n {isCollapsed ? (\r\n <ChevronRight className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n );\r\n };\r\n\r\n const renderCellsForRoles = (resource: ResourceNode) => {\r\n return paginatedRoles.map((role) => {\r\n const { status, grantedCount } = getPermissionStatusForRole(role.id, resource);\r\n const isPopoverOpen = openPopover?.roleId === role.id && openPopover?.resourceId === resource.id;\r\n const buttonRef = createRef<HTMLButtonElement>();\r\n const isRoleEditable = !role.isSystem || canEditSystemRoles;\r\n const cellBg = getPermissionCellBackground(status);\r\n const isFilteredOut = (statusFilters?.size ?? 0) > 0 && !statusFilters?.has(status);\r\n\r\n return (\r\n <td\r\n key={`${role.id}-${resource.id}`}\r\n className={`px-0 py-1 text-center relative ${isFilteredOut ? '' : cellBg}`}\r\n style={{ width: '44px', minWidth: '44px', maxWidth: '44px' }}\r\n >\r\n <button\r\n ref={buttonRef}\r\n type=\"button\"\r\n onClick={() => isRoleEditable && !isFilteredOut && handleCellClick(role.id, resource.id)}\r\n disabled={!isRoleEditable || isFilteredOut}\r\n className={`w-full h-full min-h-[36px] flex items-center justify-center rounded transition-colors ${\r\n isFilteredOut\r\n ? 'opacity-10 cursor-default'\r\n : !isRoleEditable\r\n ? 'cursor-not-allowed opacity-50'\r\n : 'hover:opacity-80'\r\n } ${\r\n isPopoverOpen ? 'ring-2 ring-[var(--color-accent-500)]' : ''\r\n }`}\r\n title={isFilteredOut\r\n ? undefined\r\n : !isRoleEditable\r\n ? `${role.name} - ${t('assignments.systemRoleReadOnly')}`\r\n : `${role.name} - ${resource.moduleLabel}: ${grantedCount}/${resource.permissions.length}`\r\n }\r\n >\r\n <PermissionStatusIndicator\r\n status={status}\r\n grantedCount={grantedCount}\r\n totalCount={resource.permissions.length}\r\n />\r\n </button>\r\n {isPopoverOpen && isRoleEditable && !isFilteredOut && (\r\n <PermissionPopover\r\n mode=\"editable\"\r\n role={role}\r\n resource={resource}\r\n onTogglePermission={(permId) => onTogglePermission(role.id, permId)}\r\n onClose={() => setOpenPopover(null)}\r\n getPermissionInheritance={getPermissionInheritance}\r\n />\r\n )}\r\n </td>\r\n );\r\n });\r\n };\r\n\r\n const renderResourceRow = (\r\n resource: ResourceNode,\r\n rowIndex: number,\r\n level: 'module' | 'section' | 'resource',\r\n hasChildren: boolean = false,\r\n isCollapsed: boolean = false\r\n ) => {\r\n const paddingLeft = getPaddingForLevel(level);\r\n const rowBgClass = rowIndex % 2 === 0 ? 'item-light' : 'item-medium';\r\n\r\n return (\r\n <tr\r\n key={resource.id}\r\n className={`hover:bg-[var(--bg-hover)] ${rowBgClass}`}\r\n >\r\n <td\r\n className={`sticky left-0 z-10 ${rowBgClass} px-3 py-2 ${paddingLeft}`}\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n {renderToggleButton(hasChildren, resource.id, level, isCollapsed)}\r\n {getResourceIcon(level)}\r\n <span className={`text-sm ${getResourceLabelClass(level)}`}>\r\n {resource.moduleLabel}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n ({resource.permissions.length})\r\n </span>\r\n </div>\r\n </td>\r\n {renderCellsForRoles(resource)}\r\n </tr>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"overflow-x-auto overflow-y-visible\">\r\n <table className=\"border-collapse\" style={{ width: 'auto' }}>\r\n <thead className=\"item-medium border-b border-[var(--item-color-border)]\">\r\n <tr>\r\n <th\r\n scope=\"col\"\r\n className=\"sticky left-0 z-20 item-medium px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px', height: '180px', verticalAlign: 'bottom', paddingBottom: '12px' }}\r\n >\r\n {t('assignments.resource')}\r\n </th>\r\n {paginatedRoles.map((role) => (\r\n <th\r\n key={role.id}\r\n scope=\"col\"\r\n className=\"relative overflow-visible\"\r\n style={{ width: '44px', minWidth: '44px', maxWidth: '44px', height: '180px', padding: 0, verticalAlign: 'bottom' }}\r\n >\r\n <div\r\n className=\"absolute bottom-2 left-1/2\"\r\n style={{\r\n transform: 'translateX(-6px) rotate(-55deg)',\r\n transformOrigin: 'bottom left',\r\n width: '160px',\r\n }}\r\n >\r\n <div className=\"flex items-center gap-1\">\r\n {role.isSystem && (\r\n <Lock className=\"h-3 w-3 flex-shrink-0 text-[var(--warning-dot)]\" />\r\n )}\r\n <span\r\n className=\"text-[10px] font-medium text-[var(--text-primary)] whitespace-nowrap\"\r\n title={role.name}\r\n >\r\n {role.name}\r\n </span>\r\n </div>\r\n </div>\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--item-color-border)]\">\r\n {groupedResources.map((appGroup) => {\r\n const isAppCollapsed = collapsedApps.has(appGroup.application);\r\n const colSpan = paginatedRoles.length;\r\n\r\n return (\r\n <React.Fragment key={appGroup.application}>\r\n {/* Application Header Row */}\r\n <tr className=\"bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\">\r\n <td\r\n className=\"sticky left-0 z-10 px-3 py-3 bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <button\r\n onClick={() => onToggleApp(appGroup.application)}\r\n className=\"flex items-center gap-3 w-full text-left hover:opacity-80\"\r\n >\r\n {isAppCollapsed ? (\r\n <ChevronRight className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n )}\r\n <FolderOpen className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n <span className=\"text-sm font-bold text-[var(--color-accent-300)] uppercase tracking-wider\">\r\n {appGroup.application}\r\n </span>\r\n <span className=\"text-xs text-[var(--color-accent-400)] ml-auto\">\r\n {t('assignments.moduleCount', { count: appGroup.modules.length })}\r\n </span>\r\n </button>\r\n </td>\r\n <td colSpan={colSpan} className=\"px-0 py-3\" />\r\n </tr>\r\n\r\n {/* Module, Section and Resource Rows */}\r\n {!isAppCollapsed && appGroup.modules.map((moduleWithSections, moduleIndex) => {\r\n const { module, sections } = moduleWithSections;\r\n const hasSections = sections.length > 0;\r\n const isModuleCollapsed = collapsedModules.has(module.id);\r\n\r\n return (\r\n <React.Fragment key={module.id}>\r\n {/* Module Row */}\r\n {renderResourceRow(module, moduleIndex, 'module', hasSections, isModuleCollapsed)}\r\n\r\n {/* Section and Resource Rows (if module has sections and is not collapsed) */}\r\n {hasSections && !isModuleCollapsed && sections.map((sectionWithResources, sectionIndex) => {\r\n const { section, resources } = sectionWithResources;\r\n\r\n return (\r\n <SectionResourceRows\r\n key={section.id}\r\n section={section}\r\n resources={resources}\r\n moduleIndex={moduleIndex}\r\n sectionIndex={sectionIndex}\r\n isCollapsed={isModuleCollapsed}\r\n collapsedSections={collapsedSections}\r\n paginatedRoles={paginatedRoles}\r\n canEditSystemRoles={canEditSystemRoles}\r\n statusFilters={statusFilters}\r\n openPopover={openPopover}\r\n onToggleCollapse={handleToggleCollapse}\r\n onTogglePermission={onTogglePermission}\r\n onCellClick={handleCellClick}\r\n setOpenPopover={setOpenPopover}\r\n renderResourceRow={renderResourceRow}\r\n />\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n );\r\n}\r\n","import { useState, useRef, useEffect, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Search, Filter, RotateCcw, ChevronDown, Check, X } from 'lucide-react';\r\nimport type { MatrixFilters } from '@/hooks/usePermissionMatrix';\r\nimport type { MatrixRoleDto, RoleCategory } from '@/services/api/adminApi';\r\n\r\ninterface PermissionMatrixFiltersProps {\r\n readonly filters: MatrixFilters;\r\n readonly roles: MatrixRoleDto[];\r\n readonly categories: RoleCategory[];\r\n readonly applications: { app: string; label: string }[];\r\n readonly modules: { app: string; module: string; label: string }[];\r\n readonly hasChanges: boolean;\r\n readonly onFilterChange: (filters: Partial<MatrixFilters>) => void;\r\n readonly onReset: () => void;\r\n}\r\n\r\nexport function PermissionMatrixFilters({\r\n filters,\r\n roles,\r\n categories,\r\n applications,\r\n modules,\r\n hasChanges,\r\n onFilterChange,\r\n onReset,\r\n}: PermissionMatrixFiltersProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const [isRoleDropdownOpen, setIsRoleDropdownOpen] = useState(false);\r\n const [roleSearchTerm, setRoleSearchTerm] = useState('');\r\n const roleDropdownRef = useRef<HTMLDivElement>(null);\r\n const roleSearchInputRef = useRef<HTMLInputElement>(null);\r\n\r\n // Filter roles based on category and search term\r\n const filteredRoles = useMemo(() => {\r\n let result = roles;\r\n\r\n // Filter by category first\r\n if (filters.categoryFilter !== 'all') {\r\n result = result.filter(role => role.category === filters.categoryFilter);\r\n }\r\n\r\n // Then filter by search term\r\n if (roleSearchTerm.trim()) {\r\n const searchLower = roleSearchTerm.toLowerCase();\r\n result = result.filter(role =>\r\n role.name.toLowerCase().includes(searchLower) ||\r\n role.shortName?.toLowerCase().includes(searchLower)\r\n );\r\n }\r\n\r\n return result;\r\n }, [roles, filters.categoryFilter, roleSearchTerm]);\r\n\r\n // Focus search input when dropdown opens\r\n useEffect(() => {\r\n if (isRoleDropdownOpen && roleSearchInputRef.current) {\r\n setTimeout(() => roleSearchInputRef.current?.focus(), 50);\r\n }\r\n }, [isRoleDropdownOpen]);\r\n\r\n // Helper to toggle dropdown and reset search when closing\r\n const toggleRoleDropdown = (open: boolean) => {\r\n setIsRoleDropdownOpen(open);\r\n if (!open) {\r\n setRoleSearchTerm('');\r\n }\r\n };\r\n\r\n // Filter modules based on selected application\r\n const filteredModules = modules.filter(m => {\r\n if (filters.applicationFilter !== 'all' && m.app !== filters.applicationFilter) {\r\n return false;\r\n }\r\n return true;\r\n });\r\n\r\n // Close dropdown when clicking outside\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (roleDropdownRef.current && !roleDropdownRef.current.contains(event.target as Node)) {\r\n toggleRoleDropdown(false);\r\n }\r\n }\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, []);\r\n\r\n const handleRoleToggle = (roleId: string) => {\r\n const newSelectedRoles = filters.selectedRoleIds.includes(roleId)\r\n ? filters.selectedRoleIds.filter(id => id !== roleId)\r\n : [...filters.selectedRoleIds, roleId];\r\n onFilterChange({ selectedRoleIds: newSelectedRoles });\r\n };\r\n\r\n const handleSelectAllRoles = () => {\r\n onFilterChange({ selectedRoleIds: filteredRoles.map(r => r.id) });\r\n };\r\n\r\n const handleClearRoles = () => {\r\n onFilterChange({ selectedRoleIds: [] });\r\n };\r\n\r\n const handleApplicationChange = (app: string) => {\r\n // Reset module filter when application changes\r\n onFilterChange({ applicationFilter: app, moduleFilter: 'all' });\r\n };\r\n\r\n const handleCategoryChange = (category: string) => {\r\n // Reset selected roles when category changes\r\n onFilterChange({ categoryFilter: category, selectedRoleIds: [] });\r\n };\r\n\r\n const hasActiveFilters = filters.selectedRoleIds.length > 0 ||\r\n filters.categoryFilter !== 'all' ||\r\n filters.applicationFilter !== 'all' ||\r\n filters.moduleFilter !== 'all';\r\n\r\n const selectedRolesLabel = filters.selectedRoleIds.length === 0\r\n ? t('permissions.filters.allRoles')\r\n : filters.selectedRoleIds.length === 1\r\n ? roles.find(r => r.id === filters.selectedRoleIds[0])?.name || t('assignments.oneRoleSelected')\r\n : `${filters.selectedRoleIds.length} ${t('permissions.filters.rolesSelected')}`;\r\n\r\n return (\r\n <div className=\"bg-[var(--bg-card)] border border-[var(--item-color-border)] rounded-[var(--radius-card)] p-4 space-y-4\">\r\n <div className=\"flex items-center gap-2 text-sm font-medium text-[var(--text-secondary)]\">\r\n <Filter className=\"h-4 w-4\" />\r\n <span>{t('assignments.filters')}</span>\r\n </div>\r\n\r\n <div className=\"flex flex-wrap gap-4\">\r\n {/* Category Filter */}\r\n <div className=\"min-w-[160px] flex-1\">\r\n <label htmlFor=\"category-filter\" className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('permissions.filters.selectCategory')}\r\n </label>\r\n <select\r\n id=\"category-filter\"\r\n value={filters.categoryFilter}\r\n onChange={(e) => handleCategoryChange(e.target.value)}\r\n className=\"block w-full px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] leading-5 bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] sm:text-sm\"\r\n >\r\n <option value=\"all\">{t('permissions.filters.allCategories')}</option>\r\n {categories.map((cat) => (\r\n <option key={cat} value={cat}>\r\n {t(`roles.categories.${cat.toLowerCase()}`)}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Role Multi-Select - Larger with search */}\r\n <div ref={roleDropdownRef} className=\"relative min-w-[200px] flex-[2]\">\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('permissions.filters.selectRoles')}\r\n </label>\r\n <button\r\n type=\"button\"\r\n onClick={() => toggleRoleDropdown(!isRoleDropdownOpen)}\r\n className=\"w-full flex items-center justify-between px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] bg-[var(--bg-primary)] text-[var(--text-primary)] hover:bg-[var(--bg-secondary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] text-sm\"\r\n >\r\n <span className=\"truncate\">{selectedRolesLabel}</span>\r\n <ChevronDown className={`h-4 w-4 text-[var(--text-muted)] transition-transform ${isRoleDropdownOpen ? 'rotate-180' : ''}`} />\r\n </button>\r\n\r\n {isRoleDropdownOpen && (\r\n <div className=\"absolute z-50 mt-1 w-full bg-[var(--bg-card)] border border-[var(--border-color)] rounded-[var(--radius-card)] shadow-lg\">\r\n {/* Search Input */}\r\n <div className=\"px-3 py-2 border-b border-[var(--border-color)]\">\r\n <div className=\"relative\">\r\n <div className=\"absolute inset-y-0 left-0 pl-2 flex items-center pointer-events-none\">\r\n <Search className=\"h-4 w-4 text-[var(--text-muted)]\" />\r\n </div>\r\n <input\r\n ref={roleSearchInputRef}\r\n type=\"text\"\r\n value={roleSearchTerm}\r\n onChange={(e) => setRoleSearchTerm(e.target.value)}\r\n placeholder={t('permissions.filters.searchRoles')}\r\n className=\"block w-full pl-8 pr-3 py-1.5 text-sm border border-[var(--border-color)] rounded-[var(--radius-input)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder-[var(--text-muted)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Actions */}\r\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <button\r\n type=\"button\"\r\n onClick={handleSelectAllRoles}\r\n className=\"text-xs text-[var(--color-accent-600)] hover:text-[var(--color-accent-700)]\"\r\n >\r\n {t('permissions.filters.selectAll')}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={handleClearRoles}\r\n className=\"text-xs text-[var(--text-muted)] hover:text-[var(--text-secondary)]\"\r\n >\r\n {t('permissions.filters.clearSelection')}\r\n </button>\r\n </div>\r\n\r\n {/* Role List */}\r\n <div className=\"max-h-64 overflow-auto\">\r\n {filteredRoles.length === 0 ? (\r\n <div className=\"px-3 py-4 text-sm text-[var(--text-muted)] text-center\">\r\n {t('permissions.filters.noRolesFound')}\r\n </div>\r\n ) : (\r\n filteredRoles.map(role => (\r\n <button\r\n type=\"button\"\r\n key={role.id}\r\n onClick={() => handleRoleToggle(role.id)}\r\n className=\"w-full flex items-center gap-3 px-3 py-2 hover:bg-[var(--bg-secondary)] cursor-pointer text-left\"\r\n >\r\n <div className={`w-4 h-4 rounded border flex items-center justify-center flex-shrink-0 ${\r\n filters.selectedRoleIds.includes(role.id)\r\n ? 'bg-[var(--color-accent-600)] border-[var(--color-accent-600)]'\r\n : 'border-[var(--border-color)] bg-[var(--bg-primary)]'\r\n }`}>\r\n {filters.selectedRoleIds.includes(role.id) && (\r\n <Check className=\"h-3 w-3 text-white\" />\r\n )}\r\n </div>\r\n <span className=\"text-sm text-[var(--text-primary)] truncate\">{role.name}</span>\r\n {role.isSystem && (\r\n <span className=\"text-xs px-1.5 py-0.5 rounded bg-[var(--bg-tertiary)] text-[var(--text-muted)] flex-shrink-0\">\r\n {t('assignments.systemRole')}\r\n </span>\r\n )}\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Application Filter */}\r\n <div className=\"min-w-[160px] flex-1\">\r\n <label htmlFor=\"application-filter\" className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('assignments.filterByApplication')}\r\n </label>\r\n <select\r\n id=\"application-filter\"\r\n value={filters.applicationFilter}\r\n onChange={(e) => handleApplicationChange(e.target.value)}\r\n disabled={applications.length === 0}\r\n className=\"block w-full px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] leading-5 bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n <option value=\"all\">{t('assignments.allApplications')}</option>\r\n {applications.map((app) => (\r\n <option key={app.app} value={app.app}>\r\n {app.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Module Filter */}\r\n <div className=\"min-w-[160px] flex-1\">\r\n <label htmlFor=\"module-filter\" className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('permissions.filters.selectModule')}\r\n </label>\r\n <select\r\n id=\"module-filter\"\r\n value={filters.moduleFilter}\r\n onChange={(e) => onFilterChange({ moduleFilter: e.target.value })}\r\n disabled={filteredModules.length === 0}\r\n className=\"block w-full px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] leading-5 bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n <option value=\"all\">{t('permissions.filters.allModules')}</option>\r\n {filteredModules.map((mod) => (\r\n <option key={`${mod.app}:${mod.module}`} value={mod.module}>\r\n {mod.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Reset Button */}\r\n <div className=\"flex items-end flex-shrink-0\">\r\n {hasActiveFilters && (\r\n <button\r\n type=\"button\"\r\n onClick={onReset}\r\n className=\"w-full inline-flex items-center justify-center gap-2 px-3 py-2 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] border border-[var(--border-color)] rounded-[var(--radius-input)] hover:bg-[var(--bg-secondary)] transition-colors\"\r\n >\r\n <RotateCcw className=\"h-4 w-4\" />\r\n {t('assignments.clearFilters')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Selected Roles Pills */}\r\n {filters.selectedRoleIds.length > 0 && (\r\n <div className=\"flex flex-wrap gap-2\">\r\n {filters.selectedRoleIds.map(roleId => {\r\n const role = roles.find(r => r.id === roleId);\r\n return role ? (\r\n <span\r\n key={roleId}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)]\"\r\n >\r\n {role.name}\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRoleToggle(roleId)}\r\n className=\"hover:text-[var(--color-accent-900)] dark:hover:text-[var(--color-accent-100)]\"\r\n >\r\n <X className=\"h-3 w-3\" />\r\n </button>\r\n </span>\r\n ) : null;\r\n })}\r\n </div>\r\n )}\r\n\r\n {/* Unsaved Changes Warning */}\r\n {hasChanges && (\r\n <div className=\"flex items-center justify-end pt-2 border-t border-[var(--border-color)]\">\r\n <div className=\"text-sm text-[var(--warning-text)]\">\r\n {t('assignments.unsavedChanges')}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useMemo, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Loader2, AlertCircle, Sparkles, Eye, User, Pencil, ShieldCheck, Info, Check, Star, Ban, ChevronLeft, ChevronRight, BookOpen, ChevronDown, ChevronUp, Lock } from 'lucide-react';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { usePermissionMatrix } from '@/hooks/usePermissionMatrix';\r\nimport { PermissionMatrixTable } from '@/components/platform/administration/PermissionMatrixTable';\r\nimport { PermissionMatrixFilters } from '@/components/platform/administration/PermissionMatrixFilters';\r\nimport { adminApi } from '@/services/api/adminApi';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { hasFullAccess } from '@/utils/permissions';\r\n\r\ninterface RoleTemplate {\r\n nameKey: string;\r\n descriptionKey: string;\r\n icon: typeof Eye;\r\n color: string;\r\n permissions: string[];\r\n}\r\n\r\nconst ROLE_TEMPLATES: Record<string, RoleTemplate> = {\r\n viewer: {\r\n nameKey: 'assignments.templates.viewer.name',\r\n descriptionKey: 'assignments.templates.viewer.description',\r\n icon: Eye,\r\n color: 'blue',\r\n permissions: ['*.read'],\r\n },\r\n member: {\r\n nameKey: 'assignments.templates.member.name',\r\n descriptionKey: 'assignments.templates.member.description',\r\n icon: User,\r\n color: 'green',\r\n permissions: ['*.read', '*.create'],\r\n },\r\n contributor: {\r\n nameKey: 'assignments.templates.contributor.name',\r\n descriptionKey: 'assignments.templates.contributor.description',\r\n icon: Pencil,\r\n color: 'orange',\r\n permissions: ['*.read', '*.create', '*.update'],\r\n },\r\n admin: {\r\n nameKey: 'assignments.templates.admin.name',\r\n descriptionKey: 'assignments.templates.admin.description',\r\n icon: ShieldCheck,\r\n color: 'red',\r\n permissions: ['*.*'],\r\n },\r\n};\r\n\r\nconst PAGE_SIZE_OPTIONS = [10, 25, 50];\r\nconst ROLES_PER_PAGE_OPTIONS = [10, 15, 20, 25];\r\n\r\ntype PermissionStatus = 'all' | 'some' | 'read-only' | 'none';\r\n\r\nexport function AssignmentsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const { user } = useAuth();\r\n const [showTemplateModal, setShowTemplateModal] = useState(false);\r\n const [templateError, setTemplateError] = useState<string | null>(null);\r\n const [pageSize, setPageSize] = useState(25);\r\n const [currentPage, setCurrentPage] = useState(1);\r\n // Role pagination\r\n const [rolesPerPage, setRolesPerPage] = useState(10);\r\n const [rolePageIndex, setRolePageIndex] = useState(0);\r\n // Collapsed state (lifted from PermissionMatrixTable for proper pagination)\r\n const [collapsedApps, setCollapsedApps] = useState<Set<string>>(new Set());\r\n // Status filters\r\n const [statusFilters, setStatusFilters] = useState<Set<PermissionStatus>>(new Set());\r\n const [showGuide, setShowGuide] = useState(false);\r\n\r\n const toggleStatusFilter = (status: PermissionStatus) => {\r\n setStatusFilters(prev => {\r\n const next = new Set(prev);\r\n if (next.has(status)) {\r\n next.delete(status);\r\n } else {\r\n next.add(status);\r\n }\r\n return next;\r\n });\r\n // Reset both paginations when filter changes\r\n setCurrentPage(1);\r\n setRolePageIndex(0);\r\n };\r\n\r\n // Toggle function for collapsed state\r\n const handleToggleApp = (appKey: string) => {\r\n setCollapsedApps(prev => {\r\n const next = new Set(prev);\r\n if (next.has(appKey)) {\r\n next.delete(appKey);\r\n } else {\r\n next.add(appKey);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n // Super Admin (with \"*\" permission) can edit system roles\r\n const canEditSystemRoles = useMemo(() => {\r\n if (!user) return false;\r\n return hasFullAccess(user.permissions);\r\n }, [user]);\r\n\r\n const {\r\n loading,\r\n error,\r\n saveError,\r\n saving,\r\n roles,\r\n assignments,\r\n filters,\r\n filteredRoles,\r\n filteredResources,\r\n hasChanges,\r\n applications,\r\n modules,\r\n categories,\r\n togglePermission,\r\n updateFilters,\r\n reloadData,\r\n resetChanges,\r\n clearSaveError,\r\n getPermissionInheritance,\r\n } = usePermissionMatrix({ canEditSystemRoles });\r\n\r\n // Helper function to calculate status for a role-module combination\r\n const getStatusForRoleModule = useCallback(\r\n (roleId: string, resource: typeof filteredResources[0]): PermissionStatus => {\r\n const grantedPerms = resource.permissions.filter(perm => {\r\n const info = getPermissionInheritance(roleId, perm.id);\r\n return info.isDirect || info.isInherited;\r\n });\r\n const grantedCount = grantedPerms.length;\r\n const totalCount = resource.totalPermissions;\r\n\r\n if (grantedCount === 0) return 'none';\r\n if (grantedCount === totalCount) return 'all';\r\n if (grantedCount === 1 && grantedPerms[0]?.action === 'read') return 'read-only';\r\n return 'some';\r\n },\r\n [getPermissionInheritance]\r\n );\r\n\r\n // Get all modules from resources for status calculations\r\n const allModules = useMemo(() =>\r\n filteredResources.filter(r => r.level === 'module'),\r\n [filteredResources]\r\n );\r\n\r\n // OPTION B: Filter BOTH modules (rows) AND roles (columns) by status\r\n // Step 1: Filter roles - keep only roles that have the selected status for at least one module\r\n const statusFilteredRoles = useMemo(() => {\r\n if (statusFilters.size === 0) {\r\n return filteredRoles;\r\n }\r\n\r\n return filteredRoles.filter(role => {\r\n // Check if this role has the selected status for ANY module\r\n for (const module of allModules) {\r\n const status = getStatusForRoleModule(role.id, module);\r\n if (statusFilters.has(status)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n });\r\n }, [filteredRoles, allModules, statusFilters, getStatusForRoleModule]);\r\n\r\n // Step 2: Filter resources - keep only modules that have the selected status for at least one role\r\n const statusFilteredResources = useMemo(() => {\r\n if (statusFilters.size === 0) {\r\n return filteredResources;\r\n }\r\n\r\n return filteredResources.filter(resource => {\r\n // Keep context/app headers\r\n if (resource.level !== 'module') return true;\r\n\r\n // Check each role's status for this module\r\n for (const role of filteredRoles) {\r\n const status = getStatusForRoleModule(role.id, resource);\r\n if (statusFilters.has(status)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n });\r\n }, [filteredResources, filteredRoles, statusFilters, getStatusForRoleModule]);\r\n\r\n // Calculate total assigned permissions\r\n const totalAssignedPermissions = useMemo(() => {\r\n let count = 0;\r\n Object.values(assignments).forEach(perms => {\r\n count += perms.size;\r\n });\r\n return count;\r\n }, [assignments]);\r\n\r\n // Module pagination - count only VISIBLE modules (not in collapsed apps)\r\n const visibleModuleCount = useMemo(() => {\r\n return statusFilteredResources.filter(r => {\r\n if (r.level !== 'module') return false;\r\n // Check if parent app is collapsed\r\n if (collapsedApps.has(r.applicationLabel)) return false;\r\n return true;\r\n }).length;\r\n }, [statusFilteredResources, collapsedApps]);\r\n\r\n const totalModuleCount = useMemo(() => {\r\n return statusFilteredResources.filter(r => r.level === 'module').length;\r\n }, [statusFilteredResources]);\r\n\r\n const totalPages = Math.ceil(visibleModuleCount / pageSize);\r\n\r\n // Reset to page 1 when filters change\r\n const handleFilterChange = (newFilters: Parameters<typeof updateFilters>[0]) => {\r\n setCurrentPage(1);\r\n updateFilters(newFilters);\r\n };\r\n\r\n const handlePageSizeChange = (newSize: number) => {\r\n setPageSize(newSize);\r\n setCurrentPage(1);\r\n };\r\n\r\n // Role pagination - use statusFilteredRoles for Option B filtering\r\n const totalRolePages = Math.ceil(statusFilteredRoles.length / rolesPerPage);\r\n const handleRolesPerPageChange = (newSize: number) => {\r\n setRolesPerPage(newSize);\r\n setRolePageIndex(0);\r\n };\r\n\r\n const createRoleFromTemplate = async (templateKey: string) => {\r\n const template = ROLE_TEMPLATES[templateKey];\r\n if (!template) return;\r\n\r\n const roleName = prompt(t('assignments.enterRoleName'), t(template.nameKey));\r\n if (!roleName) return;\r\n\r\n try {\r\n setTemplateError(null);\r\n await adminApi.roles.create({\r\n name: roleName,\r\n description: t(template.descriptionKey),\r\n permissionIds: [],\r\n });\r\n setShowTemplateModal(false);\r\n await reloadData();\r\n } catch (err) {\r\n setTemplateError(err instanceof Error ? err.message : 'Failed to create role from template');\r\n }\r\n };\r\n\r\n const handleResetFilters = () => {\r\n setCurrentPage(1);\r\n updateFilters({\r\n selectedRoleIds: [],\r\n resourceSearch: '',\r\n applicationFilter: 'all',\r\n moduleFilter: 'all',\r\n });\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <div className=\"text-center\">\r\n <Loader2 className=\"h-8 w-8 animate-spin text-[var(--color-accent-500)] mx-auto mb-4\" />\r\n <p className=\"text-[var(--text-secondary)]\">{t('assignments.loading')}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"p-6\">\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] p-4\">\r\n <div className=\"flex\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <div className=\"ml-3\">\r\n <h3 className=\"text-sm font-medium text-[var(--error-text)]\">{t('common.error')}</h3>\r\n <div className=\"mt-2 text-sm text-[var(--error-text)] opacity-80\">\r\n <p>{error}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"p-6 space-y-4\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('assignments.title', 'Assignments') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('assignments.title')}</h1>\r\n <p className=\"mt-1 text-sm text-[var(--text-secondary)]\">{t('assignments.subtitle')}</p>\r\n </div>\r\n <div className=\"flex items-center gap-3 flex-shrink-0\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowTemplateModal(true)}\r\n className=\"inline-flex items-center px-4 py-2 border border-[var(--border-color)] text-sm font-medium rounded-[var(--radius-button)] text-[var(--text-secondary)] bg-[var(--bg-card)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Sparkles className=\"h-4 w-4 mr-2\" />\r\n {t('assignments.createFromTemplate')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Save error alert */}\r\n {saveError && (\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--error-bg)] p-3 border border-[var(--error-border)]\">\r\n <div className=\"flex items-center\">\r\n <AlertCircle className=\"h-4 w-4 text-[var(--error-text)]\" />\r\n <p className=\"ml-2 text-sm text-[var(--error-text)]\">\r\n {saveError}\r\n </p>\r\n <button\r\n type=\"button\"\r\n onClick={clearSaveError}\r\n className=\"ml-auto text-sm text-[var(--error-text)] hover:opacity-80 font-medium\"\r\n >\r\n {t('common.dismiss')}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Auto-save warning */}\r\n {(hasChanges || saving) && (\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--warning-bg)] p-3 border border-[var(--warning-border)]\">\r\n <div className=\"flex items-center\">\r\n {saving ? (\r\n <Loader2 className=\"h-4 w-4 text-[var(--warning-dot)] animate-spin\" />\r\n ) : (\r\n <Info className=\"h-4 w-4 text-[var(--warning-dot)]\" />\r\n )}\r\n <p className=\"ml-2 text-sm text-[var(--warning-text)]\">\r\n {saving ? t('assignments.saving') : t('assignments.autoSaveActive')}\r\n </p>\r\n {!saving && (\r\n <button\r\n type=\"button\"\r\n onClick={resetChanges}\r\n className=\"ml-auto text-sm text-[var(--warning-text)] hover:opacity-80 font-medium\"\r\n >\r\n {t('assignments.discardChanges')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Filters */}\r\n <PermissionMatrixFilters\r\n filters={filters}\r\n roles={roles}\r\n categories={categories}\r\n applications={applications}\r\n modules={modules}\r\n hasChanges={hasChanges}\r\n onFilterChange={handleFilterChange}\r\n onReset={handleResetFilters}\r\n />\r\n\r\n {/* Stats bar + Legend + Role Pagination (top) */}\r\n <div className=\"flex flex-wrap items-center justify-between gap-3 py-2\">\r\n <div className=\"flex flex-wrap items-center gap-4\">\r\n {/* Stats badges */}\r\n <div className=\"flex flex-wrap items-center gap-3\">\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)]\">\r\n {statusFilteredRoles.length} {t('assignments.roles')}\r\n </span>\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--bg-tertiary)] text-[var(--text-secondary)]\">\r\n {visibleModuleCount}/{totalModuleCount} {t('assignments.modules')}\r\n </span>\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]\">\r\n {totalAssignedPermissions} {t('assignments.permissionsAssigned')}\r\n </span>\r\n </div>\r\n\r\n {/* Role Pagination (columns) - Top Left */}\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--text-secondary)] border-l border-[var(--border-color)] pl-4\">\r\n <span>{t('assignments.rolesPerPage')}:</span>\r\n <select\r\n value={rolesPerPage}\r\n onChange={(e) => handleRolesPerPageChange(Number(e.target.value))}\r\n className=\"px-2 py-1 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n {ROLES_PER_PAGE_OPTIONS.map(size => (\r\n <option key={size} value={size}>{size}</option>\r\n ))}\r\n </select>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {rolePageIndex * rolesPerPage + 1}-{Math.min((rolePageIndex + 1) * rolesPerPage, statusFilteredRoles.length)} / {statusFilteredRoles.length}\r\n </span>\r\n {totalRolePages > 1 && (\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setRolePageIndex(p => Math.max(0, p - 1))}\r\n disabled={rolePageIndex === 0}\r\n className=\"p-1 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronLeft className=\"h-3.5 w-3.5\" />\r\n </button>\r\n <span className=\"text-xs min-w-[50px] text-center\">\r\n {rolePageIndex + 1} / {totalRolePages}\r\n </span>\r\n <button\r\n onClick={() => setRolePageIndex(p => Math.min(totalRolePages - 1, p + 1))}\r\n disabled={rolePageIndex >= totalRolePages - 1}\r\n className=\"p-1 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronRight className=\"h-3.5 w-3.5\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Status Filter Buttons */}\r\n <div className=\"flex flex-wrap items-center gap-2\">\r\n <button\r\n onClick={() => toggleStatusFilter('none')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('none')\r\n ? 'bg-red-500/30 border-red-500 text-red-700 dark:text-red-300'\r\n : 'bg-red-500/10 border-red-500/30 text-red-600 dark:text-red-400 hover:bg-red-500/20 hover:border-red-500'\r\n }`}\r\n >\r\n <Ban className=\"h-3.5 w-3.5\" />\r\n {t('assignments.none')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('read-only')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('read-only')\r\n ? 'bg-sky-500/30 border-sky-500 text-sky-700 dark:text-sky-300'\r\n : 'bg-sky-500/10 border-sky-500/30 text-sky-600 dark:text-sky-400 hover:bg-sky-500/20 hover:border-sky-500'\r\n }`}\r\n >\r\n <Eye className=\"h-3.5 w-3.5\" />\r\n {t('assignments.readOnly')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('some')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('some')\r\n ? 'bg-amber-500/30 border-amber-500 text-amber-700 dark:text-amber-300'\r\n : 'bg-amber-500/10 border-amber-500/30 text-amber-600 dark:text-amber-400 hover:bg-amber-500/20 hover:border-amber-500'\r\n }`}\r\n >\r\n <Star className=\"h-3.5 w-3.5\" />\r\n {t('assignments.partial')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('all')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('all')\r\n ? 'bg-emerald-500/30 border-emerald-500 text-emerald-700 dark:text-emerald-300'\r\n : 'bg-emerald-500/10 border-emerald-500/30 text-emerald-600 dark:text-emerald-400 hover:bg-emerald-500/20 hover:border-emerald-500'\r\n }`}\r\n >\r\n <Check className=\"h-3.5 w-3.5\" />\r\n {t('assignments.complete')}\r\n </button>\r\n {statusFilters.size > 0 && (\r\n <button\r\n onClick={() => setStatusFilters(new Set())}\r\n className=\"text-xs text-[var(--color-accent-500)] hover:text-[var(--color-accent-600)] underline ml-2\"\r\n >\r\n {t('assignments.clearFilters')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* User Guide - Collapsible */}\r\n <div className=\"bg-[var(--bg-card)] border border-[var(--item-color-border)] rounded-[var(--radius-card)] overflow-hidden\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowGuide(!showGuide)}\r\n className=\"w-full flex items-center justify-between px-4 py-2.5 text-sm font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n <BookOpen className=\"h-4 w-4 text-[var(--color-accent-500)]\" />\r\n <span>{t('assignments.guide.title')}</span>\r\n </div>\r\n {showGuide ? (\r\n <ChevronUp className=\"h-4 w-4 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-4 w-4 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n\r\n {showGuide && (\r\n <div className=\"px-4 pb-4 border-t border-[var(--item-color-border)]\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 pt-3\">\r\n {/* Color Legend */}\r\n <div>\r\n <h4 className=\"text-xs font-semibold text-[var(--text-primary)] uppercase tracking-wider mb-2\">\r\n {t('assignments.guide.colorLegendTitle')}\r\n </h4>\r\n <div className=\"space-y-1.5\">\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-red-500/10 border border-red-500/20 text-red-600 dark:text-red-400\">\r\n <Ban className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.noneDesc')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-sky-500/20 border border-sky-500/30 text-sky-700 dark:text-sky-300\">\r\n <Eye className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.readOnlyDesc')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-amber-500/20 border border-amber-500/30 text-amber-700 dark:text-amber-300\">\r\n <Star className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.partialDesc')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-emerald-500/20 border border-emerald-500/30 text-emerald-700 dark:text-emerald-300\">\r\n <Check className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.completeDesc')}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* How to Use */}\r\n <div>\r\n <h4 className=\"text-xs font-semibold text-[var(--text-primary)] uppercase tracking-wider mb-2\">\r\n {t('assignments.guide.howToUseTitle')}\r\n </h4>\r\n <ul className=\"space-y-1.5 text-xs text-[var(--text-secondary)]\">\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.clickCell')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <Lock className=\"h-3 w-3 flex-shrink-0 mt-0.5 text-[var(--warning-dot)]\" />\r\n {t('assignments.guide.systemRoles')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.inheritance')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.autoSave')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.filterButtons')}\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Matrix Table */}\r\n <div className=\"bg-[var(--bg-card)] shadow-[var(--shadow-md)] rounded-[var(--radius-card)] border border-[var(--item-color-border)]\">\r\n <PermissionMatrixTable\r\n roles={statusFilteredRoles}\r\n resources={statusFilteredResources}\r\n assignments={assignments}\r\n canEditSystemRoles={canEditSystemRoles}\r\n onTogglePermission={togglePermission}\r\n getPermissionInheritance={getPermissionInheritance}\r\n rolesPerPage={rolesPerPage}\r\n rolePageIndex={rolePageIndex}\r\n modulesPerPage={pageSize}\r\n modulePageIndex={currentPage - 1}\r\n collapsedApps={collapsedApps}\r\n onToggleApp={handleToggleApp}\r\n statusFilters={statusFilters}\r\n />\r\n </div>\r\n\r\n {/* Module Pagination - Below Table */}\r\n <div className=\"py-3 px-4 bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--item-color-border)]\">\r\n <div className=\"flex items-center gap-3 text-sm text-[var(--text-secondary)]\">\r\n <span>{t('assignments.itemsPerPage')}:</span>\r\n <select\r\n value={pageSize}\r\n onChange={(e) => handlePageSizeChange(Number(e.target.value))}\r\n className=\"px-2 py-1 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n {PAGE_SIZE_OPTIONS.map(size => (\r\n <option key={size} value={size}>{size}</option>\r\n ))}\r\n </select>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {(currentPage - 1) * pageSize + 1}-{Math.min(currentPage * pageSize, visibleModuleCount)} / {visibleModuleCount}\r\n </span>\r\n {totalPages > 1 && (\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setCurrentPage(p => Math.max(1, p - 1))}\r\n disabled={currentPage === 1}\r\n className=\"p-1.5 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronLeft className=\"h-4 w-4\" />\r\n </button>\r\n <span className=\"text-sm min-w-[60px] text-center\">\r\n {currentPage} / {totalPages}\r\n </span>\r\n <button\r\n onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}\r\n disabled={currentPage >= totalPages}\r\n className=\"p-1.5 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronRight className=\"h-4 w-4\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Template Modal */}\r\n {showTemplateModal && (\r\n <div className=\"fixed inset-0 z-50 overflow-y-auto\">\r\n <div className=\"flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0\">\r\n <button type=\"button\" className=\"fixed inset-0 bg-black/50 transition-opacity\" onClick={() => setShowTemplateModal(false)} aria-label=\"Close modal\" />\r\n <div className=\"inline-block align-bottom bg-[var(--bg-card)] rounded-[var(--radius-modal)] px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full sm:p-6 border border-[var(--border-color)]\">\r\n <div className=\"mb-4\">\r\n <h3 className=\"text-lg font-medium text-[var(--text-primary)]\">\r\n {t('assignments.createFromTemplate')}\r\n </h3>\r\n <p className=\"mt-1 text-sm text-[var(--text-secondary)]\">\r\n {t('assignments.templateDescription')}\r\n </p>\r\n </div>\r\n\r\n {templateError && (\r\n <div className=\"mb-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] p-3\">\r\n <div className=\"flex\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <div className=\"ml-3\">\r\n <p className=\"text-sm text-[var(--error-text)]\">{templateError}</p>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\r\n {Object.entries(ROLE_TEMPLATES).map(([key, template]) => {\r\n const Icon = template.icon;\r\n return (\r\n <button\r\n key={key}\r\n onClick={() => createRoleFromTemplate(key)}\r\n className=\"relative p-4 rounded-[var(--radius-card)] border-2 text-left transition-all hover:shadow-lg hover:scale-105 border-[var(--border-color)] hover:border-[var(--color-accent-500)]\"\r\n >\r\n <div className=\"flex items-start gap-3\">\r\n <Icon className=\"h-6 w-6 text-[var(--color-accent-500)]\" />\r\n <div className=\"flex-1\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)]\">{t(template.nameKey)}</h4>\r\n <p className=\"mt-1 text-xs text-[var(--text-secondary)]\">{t(template.descriptionKey)}</p>\r\n </div>\r\n </div>\r\n </button>\r\n );\r\n })}\r\n </div>\r\n <div className=\"mt-5 sm:mt-6\">\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n setShowTemplateModal(false);\r\n setTemplateError(null);\r\n }}\r\n className=\"w-full inline-flex justify-center rounded-[var(--radius-button)] border border-[var(--border-color)] shadow-sm px-4 py-2 bg-[var(--bg-secondary)] text-base font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["SectionResourceRows","section","resources","moduleIndex","sectionIndex","_isCollapsed","collapsedSections","_paginatedRoles","_canEditSystemRoles","_statusFilters","_openPopover","_onToggleCollapse","_onTogglePermission","_onCellClick","_setOpenPopover","renderResourceRow","isSectionCollapsed","hasResources","jsxs","React","resource","resourceIndex","PermissionMatrixTable","roles","canEditSystemRoles","onTogglePermission","getPermissionInheritance","rolesPerPage","rolePageIndex","modulesPerPage","modulePageIndex","collapsedApps","onToggleApp","statusFilters","t","useTranslation","openPopover","setOpenPopover","useState","collapsedModules","setCollapsedModules","setCollapsedSections","toggleCollapsedItem","useCallback","id","setCollapsed","prev","next","toggleModule","moduleId","toggleSection","sectionId","moduleCount","useMemo","r","paginatedRoles","start","allGroupedResources","groupByApplicationWithSections","paginateAppGroups","startIndex","endIndex","visibleIndexRef","result","appGroup","isAppCollapsed","paginatedModules","moduleWithSections","groupedResources","isPermissionGranted","roleId","permissionId","inheritanceInfo","getPermissionStatusForRole","calculatePermissionStatus","permId","handleCellClick","resourceId","jsx","getPaddingForLevel","level","getResourceIcon","Database","FileText","Box","getResourceLabelClass","handleToggleCollapse","renderToggleButton","hasChildren","isCollapsed","ChevronRight","ChevronDown","renderCellsForRoles","role","status","grantedCount","isPopoverOpen","buttonRef","createRef","isRoleEditable","cellBg","getPermissionCellBackground","isFilteredOut","PermissionStatusIndicator","PermissionPopover","rowIndex","paddingLeft","rowBgClass","Lock","colSpan","FolderOpen","module","sections","hasSections","isModuleCollapsed","sectionWithResources","PermissionMatrixFilters","filters","categories","applications","modules","hasChanges","onFilterChange","onReset","isRoleDropdownOpen","setIsRoleDropdownOpen","roleSearchTerm","setRoleSearchTerm","roleDropdownRef","useRef","roleSearchInputRef","filteredRoles","searchLower","useEffect","toggleRoleDropdown","open","filteredModules","m","handleClickOutside","event","handleRoleToggle","newSelectedRoles","handleSelectAllRoles","handleClearRoles","handleApplicationChange","app","handleCategoryChange","category","hasActiveFilters","selectedRolesLabel","Filter","e","cat","Search","Check","mod","RotateCcw","X","ROLE_TEMPLATES","Eye","User","Pencil","ShieldCheck","PAGE_SIZE_OPTIONS","ROLES_PER_PAGE_OPTIONS","AssignmentsPage","user","useAuth","showTemplateModal","setShowTemplateModal","templateError","setTemplateError","pageSize","setPageSize","currentPage","setCurrentPage","setRolesPerPage","setRolePageIndex","setCollapsedApps","setStatusFilters","showGuide","setShowGuide","toggleStatusFilter","handleToggleApp","appKey","hasFullAccess","loading","error","saveError","saving","assignments","filteredResources","togglePermission","updateFilters","reloadData","resetChanges","clearSaveError","usePermissionMatrix","getStatusForRoleModule","grantedPerms","perm","info","totalCount","allModules","statusFilteredRoles","statusFilteredResources","totalAssignedPermissions","count","perms","visibleModuleCount","totalModuleCount","totalPages","handleFilterChange","newFilters","handlePageSizeChange","newSize","totalRolePages","handleRolesPerPageChange","createRoleFromTemplate","templateKey","template","roleName","adminApi","err","handleResetFilters","Loader2","AlertCircle","Breadcrumb","Sparkles","Info","size","p","ChevronLeft","Ban","Star","BookOpen","ChevronUp","key","Icon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AssignmentsPage-DE_QS2LO.js","sources":["../../src/components/platform/administration/PermissionMatrixTable.tsx","../../src/components/platform/administration/PermissionMatrixFilters.tsx","../../src/pages/platform/administration/permissions/AssignmentsPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport React, { useState, createRef, useMemo, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Lock, ChevronRight, ChevronDown, FolderOpen, Box, FileText, Database } from 'lucide-react';\r\nimport type { ResourceNode, RolePermissions, PermissionInheritanceInfo } from '@/hooks/usePermissionMatrix';\r\nimport type { MatrixRoleDto } from '@/services/api/adminApi';\r\nimport type { PermissionStatus, ApplicationGroupWithSections, ModuleWithSections } from './permissions/types';\r\nimport { groupByApplicationWithSections, calculatePermissionStatus, getPermissionCellBackground } from '@/utils/permissionUtils';\r\nimport { PermissionStatusIndicator } from './permissions/PermissionStatusIndicator';\r\nimport { PermissionPopover } from './PermissionPopover';\r\n\r\n// Sub-component for rendering section and resource rows\r\ninterface SectionResourceRowsProps {\r\n readonly section: ResourceNode;\r\n readonly resources: ResourceNode[];\r\n readonly moduleIndex: number;\r\n readonly sectionIndex: number;\r\n readonly isCollapsed: boolean;\r\n readonly collapsedSections: Set<string>;\r\n readonly paginatedRoles: MatrixRoleDto[];\r\n readonly canEditSystemRoles?: boolean;\r\n readonly statusFilters?: Set<PermissionStatus>;\r\n readonly openPopover: { roleId: string; resourceId: string } | null;\r\n readonly onToggleCollapse: (resourceId: string, level: 'module' | 'section' | 'resource') => void;\r\n readonly onTogglePermission: (roleId: string, permissionId: string) => void;\r\n readonly onCellClick: (roleId: string, resourceId: string) => void;\r\n readonly setOpenPopover: (state: { roleId: string; resourceId: string } | null) => void;\r\n readonly renderResourceRow: (resource: ResourceNode, rowIndex: number, level: 'module' | 'section' | 'resource', hasChildren: boolean, isCollapsed: boolean) => React.ReactNode;\r\n}\r\n\r\nfunction SectionResourceRows({\r\n section,\r\n resources,\r\n moduleIndex,\r\n sectionIndex,\r\n isCollapsed: _isCollapsed,\r\n collapsedSections,\r\n paginatedRoles: _paginatedRoles,\r\n canEditSystemRoles: _canEditSystemRoles,\r\n statusFilters: _statusFilters,\r\n openPopover: _openPopover,\r\n onToggleCollapse: _onToggleCollapse,\r\n onTogglePermission: _onTogglePermission,\r\n onCellClick: _onCellClick,\r\n setOpenPopover: _setOpenPopover,\r\n renderResourceRow,\r\n}: SectionResourceRowsProps) {\r\n const isSectionCollapsed = collapsedSections.has(section.id);\r\n const hasResources = resources.length > 0;\r\n\r\n return (\r\n <React.Fragment key={section.id}>\r\n {/* Section Row */}\r\n {renderResourceRow(section, moduleIndex + sectionIndex + 1, 'section', hasResources, isSectionCollapsed)}\r\n\r\n {/* Resource Rows (if section has resources and is not collapsed) */}\r\n {hasResources && !isSectionCollapsed && resources.map((resource, resourceIndex) =>\r\n renderResourceRow(resource, moduleIndex + sectionIndex + resourceIndex + 2, 'resource', false, false)\r\n )}\r\n </React.Fragment>\r\n );\r\n}\r\n\r\ninterface PermissionMatrixTableProps {\r\n readonly roles: MatrixRoleDto[];\r\n readonly resources: ResourceNode[];\r\n readonly assignments: RolePermissions;\r\n readonly canEditSystemRoles?: boolean;\r\n readonly onTogglePermission: (roleId: string, permissionId: string) => void;\r\n readonly getPermissionInheritance: (roleId: string, permissionId: string) => PermissionInheritanceInfo;\r\n // Role pagination props (controlled from parent)\r\n readonly rolesPerPage: number;\r\n readonly rolePageIndex: number;\r\n // Module pagination props (controlled from parent)\r\n readonly modulesPerPage: number;\r\n readonly modulePageIndex: number;\r\n // Collapsed state (controlled from parent for proper pagination)\r\n readonly collapsedApps: Set<string>;\r\n readonly onToggleApp: (appKey: string) => void;\r\n // Status filter - cells not matching will be dimmed\r\n readonly statusFilters?: Set<PermissionStatus>;\r\n}\r\n\r\nexport function PermissionMatrixTable({\r\n roles,\r\n resources,\r\n canEditSystemRoles = false,\r\n onTogglePermission,\r\n getPermissionInheritance,\r\n rolesPerPage,\r\n rolePageIndex,\r\n modulesPerPage,\r\n modulePageIndex,\r\n collapsedApps,\r\n onToggleApp,\r\n statusFilters,\r\n}: PermissionMatrixTableProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const [openPopover, setOpenPopover] = useState<{ roleId: string; resourceId: string } | null>(null);\r\n const [collapsedModules, setCollapsedModules] = useState<Set<string>>(new Set());\r\n const [collapsedSections, setCollapsedSections] = useState<Set<string>>(new Set());\r\n\r\n const toggleCollapsedItem = useCallback((id: string, setCollapsed: (fn: (prev: Set<string>) => Set<string>) => void) => {\r\n setCollapsed(prev => {\r\n const next = new Set(prev);\r\n if (next.has(id)) {\r\n next.delete(id);\r\n } else {\r\n next.add(id);\r\n }\r\n return next;\r\n });\r\n }, []);\r\n\r\n // Toggle module collapse state\r\n const toggleModule = useCallback((moduleId: string) => {\r\n toggleCollapsedItem(moduleId, setCollapsedModules);\r\n }, [toggleCollapsedItem]);\r\n\r\n // Toggle section collapse state\r\n const toggleSection = useCallback((sectionId: string) => {\r\n toggleCollapsedItem(sectionId, setCollapsedSections);\r\n }, [toggleCollapsedItem]);\r\n\r\n // Get total modules count (only modules, not sections)\r\n const moduleCount = useMemo(() => {\r\n return resources.filter(r => r.level === 'module').length;\r\n }, [resources]);\r\n\r\n // Paginate roles based on props\r\n const paginatedRoles = useMemo(() => {\r\n const start = rolePageIndex * rolesPerPage;\r\n return roles.slice(start, start + rolesPerPage);\r\n }, [roles, rolePageIndex, rolesPerPage]);\r\n\r\n // Group ALL resources by context with sections\r\n const allGroupedResources = useMemo(() => {\r\n return groupByApplicationWithSections(resources);\r\n }, [resources]);\r\n\r\n\r\n const paginateAppGroups = useCallback(() => {\r\n const startIndex = modulePageIndex * modulesPerPage;\r\n const endIndex = startIndex + modulesPerPage;\r\n const visibleIndexRef = { current: 0 };\r\n const result: ApplicationGroupWithSections[] = [];\r\n\r\n for (const appGroup of allGroupedResources) {\r\n const isAppCollapsed = collapsedApps.has(appGroup.application);\r\n const paginatedModules: ModuleWithSections[] = [];\r\n\r\n if (!isAppCollapsed) {\r\n for (const moduleWithSections of appGroup.modules) {\r\n if (visibleIndexRef.current >= startIndex && visibleIndexRef.current < endIndex) {\r\n paginatedModules.push(moduleWithSections);\r\n }\r\n visibleIndexRef.current++;\r\n }\r\n }\r\n\r\n result.push({\r\n application: appGroup.application,\r\n modules: paginatedModules,\r\n });\r\n }\r\n\r\n return result;\r\n }, [allGroupedResources, modulePageIndex, modulesPerPage, collapsedApps]);\r\n\r\n const groupedResources = useMemo(() => {\r\n return paginateAppGroups();\r\n }, [paginateAppGroups]);\r\n\r\n const isPermissionGranted = useCallback((roleId: string, permissionId: string): boolean => {\r\n const inheritanceInfo = getPermissionInheritance(roleId, permissionId);\r\n return inheritanceInfo.isDirect || inheritanceInfo.isInherited;\r\n }, [getPermissionInheritance]);\r\n\r\n const getPermissionStatusForRole = useCallback((roleId: string, resource: ResourceNode): { status: PermissionStatus; grantedCount: number } => {\r\n return calculatePermissionStatus(resource, (permId) => isPermissionGranted(roleId, permId));\r\n }, [isPermissionGranted]);\r\n\r\n const handleCellClick = (roleId: string, resourceId: string) => {\r\n if (openPopover?.roleId === roleId && openPopover?.resourceId === resourceId) {\r\n setOpenPopover(null);\r\n } else {\r\n setOpenPopover({ roleId, resourceId });\r\n }\r\n };\r\n\r\n if (roles.length === 0 || moduleCount === 0) {\r\n return (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {roles.length === 0 ? t('assignments.noRoles') : t('assignments.noResources')}\r\n </div>\r\n );\r\n }\r\n\r\n const getPaddingForLevel = (level: 'module' | 'section' | 'resource'): string => {\r\n switch (level) {\r\n case 'resource': return 'pl-28';\r\n case 'section': return 'pl-22';\r\n default: return 'pl-16';\r\n }\r\n };\r\n\r\n const getResourceIcon = (level: 'module' | 'section' | 'resource') => {\r\n if (level === 'resource') return <Database className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n if (level === 'section') return <FileText className=\"h-3.5 w-3.5 text-[var(--text-muted)]\" />;\r\n return <Box className=\"h-3.5 w-3.5 text-[var(--text-secondary)]\" />;\r\n };\r\n\r\n const getResourceLabelClass = (level: 'module' | 'section' | 'resource'): string => {\r\n if (level === 'resource') return 'text-[var(--text-muted)] italic';\r\n if (level === 'section') return 'text-[var(--text-secondary)]';\r\n return 'font-medium text-[var(--text-primary)]';\r\n };\r\n\r\n const handleToggleCollapse = useCallback((resourceId: string, level: 'module' | 'section' | 'resource') => {\r\n if (level === 'module') {\r\n toggleModule(resourceId);\r\n } else if (level === 'section') {\r\n toggleSection(resourceId);\r\n }\r\n }, [toggleModule, toggleSection]);\r\n\r\n const renderToggleButton = (hasChildren: boolean, resourceId: string, level: 'module' | 'section' | 'resource', isCollapsed: boolean) => {\r\n if (!hasChildren) return null;\r\n return (\r\n <button\r\n onClick={() => handleToggleCollapse(resourceId, level)}\r\n className=\"p-0.5 hover:bg-[var(--bg-hover)] rounded\"\r\n >\r\n {isCollapsed ? (\r\n <ChevronRight className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-3 w-3 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n );\r\n };\r\n\r\n const renderCellsForRoles = (resource: ResourceNode) => {\r\n return paginatedRoles.map((role) => {\r\n const { status, grantedCount } = getPermissionStatusForRole(role.id, resource);\r\n const isPopoverOpen = openPopover?.roleId === role.id && openPopover?.resourceId === resource.id;\r\n const buttonRef = createRef<HTMLButtonElement>();\r\n const isRoleEditable = !role.isSystem || canEditSystemRoles;\r\n const cellBg = getPermissionCellBackground(status);\r\n const isFilteredOut = (statusFilters?.size ?? 0) > 0 && !statusFilters?.has(status);\r\n\r\n return (\r\n <td\r\n key={`${role.id}-${resource.id}`}\r\n className={`px-0 py-1 text-center relative ${isFilteredOut ? '' : cellBg}`}\r\n style={{ width: '44px', minWidth: '44px', maxWidth: '44px' }}\r\n >\r\n <button\r\n ref={buttonRef}\r\n type=\"button\"\r\n onClick={() => isRoleEditable && !isFilteredOut && handleCellClick(role.id, resource.id)}\r\n disabled={!isRoleEditable || isFilteredOut}\r\n className={`w-full h-full min-h-[36px] flex items-center justify-center rounded transition-colors ${\r\n isFilteredOut\r\n ? 'opacity-10 cursor-default'\r\n : !isRoleEditable\r\n ? 'cursor-not-allowed opacity-50'\r\n : 'hover:opacity-80'\r\n } ${\r\n isPopoverOpen ? 'ring-2 ring-[var(--color-accent-500)]' : ''\r\n }`}\r\n title={isFilteredOut\r\n ? undefined\r\n : !isRoleEditable\r\n ? `${role.name} - ${t('assignments.systemRoleReadOnly')}`\r\n : `${role.name} - ${resource.moduleLabel}: ${grantedCount}/${resource.permissions.length}`\r\n }\r\n >\r\n <PermissionStatusIndicator\r\n status={status}\r\n grantedCount={grantedCount}\r\n totalCount={resource.permissions.length}\r\n />\r\n </button>\r\n {isPopoverOpen && isRoleEditable && !isFilteredOut && (\r\n <PermissionPopover\r\n mode=\"editable\"\r\n role={role}\r\n resource={resource}\r\n onTogglePermission={(permId) => onTogglePermission(role.id, permId)}\r\n onClose={() => setOpenPopover(null)}\r\n getPermissionInheritance={getPermissionInheritance}\r\n />\r\n )}\r\n </td>\r\n );\r\n });\r\n };\r\n\r\n const renderResourceRow = (\r\n resource: ResourceNode,\r\n rowIndex: number,\r\n level: 'module' | 'section' | 'resource',\r\n hasChildren: boolean = false,\r\n isCollapsed: boolean = false\r\n ) => {\r\n const paddingLeft = getPaddingForLevel(level);\r\n const rowBgClass = rowIndex % 2 === 0 ? 'item-light' : 'item-medium';\r\n\r\n return (\r\n <tr\r\n key={resource.id}\r\n className={`hover:bg-[var(--bg-hover)] ${rowBgClass}`}\r\n >\r\n <td\r\n className={`sticky left-0 z-10 ${rowBgClass} px-3 py-2 ${paddingLeft}`}\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n {renderToggleButton(hasChildren, resource.id, level, isCollapsed)}\r\n {getResourceIcon(level)}\r\n <span className={`text-sm ${getResourceLabelClass(level)}`}>\r\n {resource.moduleLabel}\r\n </span>\r\n <span className=\"text-xs text-[var(--text-muted)]\">\r\n ({resource.permissions.length})\r\n </span>\r\n </div>\r\n </td>\r\n {renderCellsForRoles(resource)}\r\n </tr>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"overflow-x-auto overflow-y-visible\">\r\n <table className=\"border-collapse\" style={{ width: 'auto' }}>\r\n <thead className=\"item-medium border-b border-[var(--item-color-border)]\">\r\n <tr>\r\n <th\r\n scope=\"col\"\r\n className=\"sticky left-0 z-20 item-medium px-3 text-left text-xs font-medium text-[var(--text-secondary)] uppercase tracking-wider\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px', height: '180px', verticalAlign: 'bottom', paddingBottom: '12px' }}\r\n >\r\n {t('assignments.resource')}\r\n </th>\r\n {paginatedRoles.map((role) => (\r\n <th\r\n key={role.id}\r\n scope=\"col\"\r\n className=\"relative overflow-visible\"\r\n style={{ width: '44px', minWidth: '44px', maxWidth: '44px', height: '180px', padding: 0, verticalAlign: 'bottom' }}\r\n >\r\n <div\r\n className=\"absolute bottom-2 left-1/2\"\r\n style={{\r\n transform: 'translateX(-6px) rotate(-55deg)',\r\n transformOrigin: 'bottom left',\r\n width: '160px',\r\n }}\r\n >\r\n <div className=\"flex items-center gap-1\">\r\n {role.isSystem && (\r\n <Lock className=\"h-3 w-3 flex-shrink-0 text-[var(--warning-dot)]\" />\r\n )}\r\n <span\r\n className=\"text-[10px] font-medium text-[var(--text-primary)] whitespace-nowrap\"\r\n title={role.name}\r\n >\r\n {role.name}\r\n </span>\r\n </div>\r\n </div>\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--item-color-border)]\">\r\n {groupedResources.map((appGroup) => {\r\n const isAppCollapsed = collapsedApps.has(appGroup.application);\r\n const colSpan = paginatedRoles.length;\r\n\r\n return (\r\n <React.Fragment key={appGroup.application}>\r\n {/* Application Header Row */}\r\n <tr className=\"bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\">\r\n <td\r\n className=\"sticky left-0 z-10 px-3 py-3 bg-[var(--color-accent-900)]/30 dark:bg-[var(--color-accent-900)]/50\"\r\n style={{ width: '280px', minWidth: '280px', maxWidth: '280px' }}\r\n >\r\n <button\r\n onClick={() => onToggleApp(appGroup.application)}\r\n className=\"flex items-center gap-3 w-full text-left hover:opacity-80\"\r\n >\r\n {isAppCollapsed ? (\r\n <ChevronRight className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n )}\r\n <FolderOpen className=\"h-5 w-5 text-[var(--color-accent-400)]\" />\r\n <span className=\"text-sm font-bold text-[var(--color-accent-300)] uppercase tracking-wider\">\r\n {appGroup.application}\r\n </span>\r\n <span className=\"text-xs text-[var(--color-accent-400)] ml-auto\">\r\n {t('assignments.moduleCount', { count: appGroup.modules.length })}\r\n </span>\r\n </button>\r\n </td>\r\n <td colSpan={colSpan} className=\"px-0 py-3\" />\r\n </tr>\r\n\r\n {/* Module, Section and Resource Rows */}\r\n {!isAppCollapsed && appGroup.modules.map((moduleWithSections, moduleIndex) => {\r\n const { module, sections } = moduleWithSections;\r\n const hasSections = sections.length > 0;\r\n const isModuleCollapsed = collapsedModules.has(module.id);\r\n\r\n return (\r\n <React.Fragment key={module.id}>\r\n {/* Module Row */}\r\n {renderResourceRow(module, moduleIndex, 'module', hasSections, isModuleCollapsed)}\r\n\r\n {/* Section and Resource Rows (if module has sections and is not collapsed) */}\r\n {hasSections && !isModuleCollapsed && sections.map((sectionWithResources, sectionIndex) => {\r\n const { section, resources } = sectionWithResources;\r\n\r\n return (\r\n <SectionResourceRows\r\n key={section.id}\r\n section={section}\r\n resources={resources}\r\n moduleIndex={moduleIndex}\r\n sectionIndex={sectionIndex}\r\n isCollapsed={isModuleCollapsed}\r\n collapsedSections={collapsedSections}\r\n paginatedRoles={paginatedRoles}\r\n canEditSystemRoles={canEditSystemRoles}\r\n statusFilters={statusFilters}\r\n openPopover={openPopover}\r\n onToggleCollapse={handleToggleCollapse}\r\n onTogglePermission={onTogglePermission}\r\n onCellClick={handleCellClick}\r\n setOpenPopover={setOpenPopover}\r\n renderResourceRow={renderResourceRow}\r\n />\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </React.Fragment>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n </div>\r\n );\r\n}\r\n","import { useState, useRef, useEffect, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Search, Filter, RotateCcw, ChevronDown, Check, X } from 'lucide-react';\r\nimport type { MatrixFilters } from '@/hooks/usePermissionMatrix';\r\nimport type { MatrixRoleDto, RoleCategory } from '@/services/api/adminApi';\r\n\r\ninterface PermissionMatrixFiltersProps {\r\n readonly filters: MatrixFilters;\r\n readonly roles: MatrixRoleDto[];\r\n readonly categories: RoleCategory[];\r\n readonly applications: { app: string; label: string }[];\r\n readonly modules: { app: string; module: string; label: string }[];\r\n readonly hasChanges: boolean;\r\n readonly onFilterChange: (filters: Partial<MatrixFilters>) => void;\r\n readonly onReset: () => void;\r\n}\r\n\r\nexport function PermissionMatrixFilters({\r\n filters,\r\n roles,\r\n categories,\r\n applications,\r\n modules,\r\n hasChanges,\r\n onFilterChange,\r\n onReset,\r\n}: PermissionMatrixFiltersProps): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const [isRoleDropdownOpen, setIsRoleDropdownOpen] = useState(false);\r\n const [roleSearchTerm, setRoleSearchTerm] = useState('');\r\n const roleDropdownRef = useRef<HTMLDivElement>(null);\r\n const roleSearchInputRef = useRef<HTMLInputElement>(null);\r\n\r\n // Filter roles based on category and search term\r\n const filteredRoles = useMemo(() => {\r\n let result = roles;\r\n\r\n // Filter by category first\r\n if (filters.categoryFilter !== 'all') {\r\n result = result.filter(role => role.category === filters.categoryFilter);\r\n }\r\n\r\n // Then filter by search term\r\n if (roleSearchTerm.trim()) {\r\n const searchLower = roleSearchTerm.toLowerCase();\r\n result = result.filter(role =>\r\n role.name.toLowerCase().includes(searchLower) ||\r\n role.shortName?.toLowerCase().includes(searchLower)\r\n );\r\n }\r\n\r\n return result;\r\n }, [roles, filters.categoryFilter, roleSearchTerm]);\r\n\r\n // Focus search input when dropdown opens\r\n useEffect(() => {\r\n if (isRoleDropdownOpen && roleSearchInputRef.current) {\r\n setTimeout(() => roleSearchInputRef.current?.focus(), 50);\r\n }\r\n }, [isRoleDropdownOpen]);\r\n\r\n // Helper to toggle dropdown and reset search when closing\r\n const toggleRoleDropdown = (open: boolean) => {\r\n setIsRoleDropdownOpen(open);\r\n if (!open) {\r\n setRoleSearchTerm('');\r\n }\r\n };\r\n\r\n // Filter modules based on selected application\r\n const filteredModules = modules.filter(m => {\r\n if (filters.applicationFilter !== 'all' && m.app !== filters.applicationFilter) {\r\n return false;\r\n }\r\n return true;\r\n });\r\n\r\n // Close dropdown when clicking outside\r\n useEffect(() => {\r\n function handleClickOutside(event: MouseEvent) {\r\n if (roleDropdownRef.current && !roleDropdownRef.current.contains(event.target as Node)) {\r\n toggleRoleDropdown(false);\r\n }\r\n }\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, []);\r\n\r\n const handleRoleToggle = (roleId: string) => {\r\n const newSelectedRoles = filters.selectedRoleIds.includes(roleId)\r\n ? filters.selectedRoleIds.filter(id => id !== roleId)\r\n : [...filters.selectedRoleIds, roleId];\r\n onFilterChange({ selectedRoleIds: newSelectedRoles });\r\n };\r\n\r\n const handleSelectAllRoles = () => {\r\n onFilterChange({ selectedRoleIds: filteredRoles.map(r => r.id) });\r\n };\r\n\r\n const handleClearRoles = () => {\r\n onFilterChange({ selectedRoleIds: [] });\r\n };\r\n\r\n const handleApplicationChange = (app: string) => {\r\n // Reset module filter when application changes\r\n onFilterChange({ applicationFilter: app, moduleFilter: 'all' });\r\n };\r\n\r\n const handleCategoryChange = (category: string) => {\r\n // Reset selected roles when category changes\r\n onFilterChange({ categoryFilter: category, selectedRoleIds: [] });\r\n };\r\n\r\n const hasActiveFilters = filters.selectedRoleIds.length > 0 ||\r\n filters.categoryFilter !== 'all' ||\r\n filters.applicationFilter !== 'all' ||\r\n filters.moduleFilter !== 'all';\r\n\r\n const selectedRolesLabel = filters.selectedRoleIds.length === 0\r\n ? t('permissions.filters.allRoles')\r\n : filters.selectedRoleIds.length === 1\r\n ? roles.find(r => r.id === filters.selectedRoleIds[0])?.name || t('assignments.oneRoleSelected')\r\n : `${filters.selectedRoleIds.length} ${t('permissions.filters.rolesSelected')}`;\r\n\r\n return (\r\n <div className=\"bg-[var(--bg-card)] border border-[var(--item-color-border)] rounded-[var(--radius-card)] p-4 space-y-4\">\r\n <div className=\"flex items-center gap-2 text-sm font-medium text-[var(--text-secondary)]\">\r\n <Filter className=\"h-4 w-4\" />\r\n <span>{t('assignments.filters')}</span>\r\n </div>\r\n\r\n <div className=\"flex flex-wrap gap-4\">\r\n {/* Category Filter */}\r\n <div className=\"min-w-[160px] flex-1\">\r\n <label htmlFor=\"category-filter\" className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('permissions.filters.selectCategory')}\r\n </label>\r\n <select\r\n id=\"category-filter\"\r\n value={filters.categoryFilter}\r\n onChange={(e) => handleCategoryChange(e.target.value)}\r\n className=\"block w-full px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] leading-5 bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] sm:text-sm\"\r\n >\r\n <option value=\"all\">{t('permissions.filters.allCategories')}</option>\r\n {categories.map((cat) => (\r\n <option key={cat} value={cat}>\r\n {t(`roles.categories.${cat.toLowerCase()}`)}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Role Multi-Select - Larger with search */}\r\n <div ref={roleDropdownRef} className=\"relative min-w-[200px] flex-[2]\">\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('permissions.filters.selectRoles')}\r\n </label>\r\n <button\r\n type=\"button\"\r\n onClick={() => toggleRoleDropdown(!isRoleDropdownOpen)}\r\n className=\"w-full flex items-center justify-between px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] bg-[var(--bg-primary)] text-[var(--text-primary)] hover:bg-[var(--bg-secondary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] text-sm\"\r\n >\r\n <span className=\"truncate\">{selectedRolesLabel}</span>\r\n <ChevronDown className={`h-4 w-4 text-[var(--text-muted)] transition-transform ${isRoleDropdownOpen ? 'rotate-180' : ''}`} />\r\n </button>\r\n\r\n {isRoleDropdownOpen && (\r\n <div className=\"absolute z-50 mt-1 w-full bg-[var(--bg-card)] border border-[var(--border-color)] rounded-[var(--radius-card)] shadow-lg\">\r\n {/* Search Input */}\r\n <div className=\"px-3 py-2 border-b border-[var(--border-color)]\">\r\n <div className=\"relative\">\r\n <div className=\"absolute inset-y-0 left-0 pl-2 flex items-center pointer-events-none\">\r\n <Search className=\"h-4 w-4 text-[var(--text-muted)]\" />\r\n </div>\r\n <input\r\n ref={roleSearchInputRef}\r\n type=\"text\"\r\n value={roleSearchTerm}\r\n onChange={(e) => setRoleSearchTerm(e.target.value)}\r\n placeholder={t('permissions.filters.searchRoles')}\r\n className=\"block w-full pl-8 pr-3 py-1.5 text-sm border border-[var(--border-color)] rounded-[var(--radius-input)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder-[var(--text-muted)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Actions */}\r\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-[var(--border-color)] bg-[var(--bg-secondary)]\">\r\n <button\r\n type=\"button\"\r\n onClick={handleSelectAllRoles}\r\n className=\"text-xs text-[var(--color-accent-600)] hover:text-[var(--color-accent-700)]\"\r\n >\r\n {t('permissions.filters.selectAll')}\r\n </button>\r\n <button\r\n type=\"button\"\r\n onClick={handleClearRoles}\r\n className=\"text-xs text-[var(--text-muted)] hover:text-[var(--text-secondary)]\"\r\n >\r\n {t('permissions.filters.clearSelection')}\r\n </button>\r\n </div>\r\n\r\n {/* Role List */}\r\n <div className=\"max-h-64 overflow-auto\">\r\n {filteredRoles.length === 0 ? (\r\n <div className=\"px-3 py-4 text-sm text-[var(--text-muted)] text-center\">\r\n {t('permissions.filters.noRolesFound')}\r\n </div>\r\n ) : (\r\n filteredRoles.map(role => (\r\n <button\r\n type=\"button\"\r\n key={role.id}\r\n onClick={() => handleRoleToggle(role.id)}\r\n className=\"w-full flex items-center gap-3 px-3 py-2 hover:bg-[var(--bg-secondary)] cursor-pointer text-left\"\r\n >\r\n <div className={`w-4 h-4 rounded border flex items-center justify-center flex-shrink-0 ${\r\n filters.selectedRoleIds.includes(role.id)\r\n ? 'bg-[var(--color-accent-600)] border-[var(--color-accent-600)]'\r\n : 'border-[var(--border-color)] bg-[var(--bg-primary)]'\r\n }`}>\r\n {filters.selectedRoleIds.includes(role.id) && (\r\n <Check className=\"h-3 w-3 text-white\" />\r\n )}\r\n </div>\r\n <span className=\"text-sm text-[var(--text-primary)] truncate\">{role.name}</span>\r\n {role.isSystem && (\r\n <span className=\"text-xs px-1.5 py-0.5 rounded bg-[var(--bg-tertiary)] text-[var(--text-muted)] flex-shrink-0\">\r\n {t('assignments.systemRole')}\r\n </span>\r\n )}\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Application Filter */}\r\n <div className=\"min-w-[160px] flex-1\">\r\n <label htmlFor=\"application-filter\" className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('assignments.filterByApplication')}\r\n </label>\r\n <select\r\n id=\"application-filter\"\r\n value={filters.applicationFilter}\r\n onChange={(e) => handleApplicationChange(e.target.value)}\r\n disabled={applications.length === 0}\r\n className=\"block w-full px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] leading-5 bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n <option value=\"all\">{t('assignments.allApplications')}</option>\r\n {applications.map((app) => (\r\n <option key={app.app} value={app.app}>\r\n {app.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Module Filter */}\r\n <div className=\"min-w-[160px] flex-1\">\r\n <label htmlFor=\"module-filter\" className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('permissions.filters.selectModule')}\r\n </label>\r\n <select\r\n id=\"module-filter\"\r\n value={filters.moduleFilter}\r\n onChange={(e) => onFilterChange({ moduleFilter: e.target.value })}\r\n disabled={filteredModules.length === 0}\r\n className=\"block w-full px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-input)] leading-5 bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)] sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed\"\r\n >\r\n <option value=\"all\">{t('permissions.filters.allModules')}</option>\r\n {filteredModules.map((mod) => (\r\n <option key={`${mod.app}:${mod.module}`} value={mod.module}>\r\n {mod.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Reset Button */}\r\n <div className=\"flex items-end flex-shrink-0\">\r\n {hasActiveFilters && (\r\n <button\r\n type=\"button\"\r\n onClick={onReset}\r\n className=\"w-full inline-flex items-center justify-center gap-2 px-3 py-2 text-sm text-[var(--text-secondary)] hover:text-[var(--text-primary)] border border-[var(--border-color)] rounded-[var(--radius-input)] hover:bg-[var(--bg-secondary)] transition-colors\"\r\n >\r\n <RotateCcw className=\"h-4 w-4\" />\r\n {t('assignments.clearFilters')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Selected Roles Pills */}\r\n {filters.selectedRoleIds.length > 0 && (\r\n <div className=\"flex flex-wrap gap-2\">\r\n {filters.selectedRoleIds.map(roleId => {\r\n const role = roles.find(r => r.id === roleId);\r\n return role ? (\r\n <span\r\n key={roleId}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)]\"\r\n >\r\n {role.name}\r\n <button\r\n type=\"button\"\r\n onClick={() => handleRoleToggle(roleId)}\r\n className=\"hover:text-[var(--color-accent-900)] dark:hover:text-[var(--color-accent-100)]\"\r\n >\r\n <X className=\"h-3 w-3\" />\r\n </button>\r\n </span>\r\n ) : null;\r\n })}\r\n </div>\r\n )}\r\n\r\n {/* Unsaved Changes Warning */}\r\n {hasChanges && (\r\n <div className=\"flex items-center justify-end pt-2 border-t border-[var(--border-color)]\">\r\n <div className=\"text-sm text-[var(--warning-text)]\">\r\n {t('assignments.unsavedChanges')}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useMemo, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Loader2, AlertCircle, Sparkles, Eye, User, Pencil, ShieldCheck, Info, Check, Star, Ban, ChevronLeft, ChevronRight, BookOpen, ChevronDown, ChevronUp, Lock } from 'lucide-react';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { usePermissionMatrix } from '@/hooks/usePermissionMatrix';\r\nimport { PermissionMatrixTable } from '@/components/platform/administration/PermissionMatrixTable';\r\nimport { PermissionMatrixFilters } from '@/components/platform/administration/PermissionMatrixFilters';\r\nimport { adminApi } from '@/services/api/adminApi';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\nimport { hasFullAccess } from '@/utils/permissions';\r\n\r\ninterface RoleTemplate {\r\n nameKey: string;\r\n descriptionKey: string;\r\n icon: typeof Eye;\r\n color: string;\r\n permissions: string[];\r\n}\r\n\r\nconst ROLE_TEMPLATES: Record<string, RoleTemplate> = {\r\n viewer: {\r\n nameKey: 'assignments.templates.viewer.name',\r\n descriptionKey: 'assignments.templates.viewer.description',\r\n icon: Eye,\r\n color: 'blue',\r\n permissions: ['*.read'],\r\n },\r\n member: {\r\n nameKey: 'assignments.templates.member.name',\r\n descriptionKey: 'assignments.templates.member.description',\r\n icon: User,\r\n color: 'green',\r\n permissions: ['*.read', '*.create'],\r\n },\r\n contributor: {\r\n nameKey: 'assignments.templates.contributor.name',\r\n descriptionKey: 'assignments.templates.contributor.description',\r\n icon: Pencil,\r\n color: 'orange',\r\n permissions: ['*.read', '*.create', '*.update'],\r\n },\r\n admin: {\r\n nameKey: 'assignments.templates.admin.name',\r\n descriptionKey: 'assignments.templates.admin.description',\r\n icon: ShieldCheck,\r\n color: 'red',\r\n permissions: ['*.*'],\r\n },\r\n};\r\n\r\nconst PAGE_SIZE_OPTIONS = [10, 25, 50];\r\nconst ROLES_PER_PAGE_OPTIONS = [10, 15, 20, 25];\r\n\r\ntype PermissionStatus = 'all' | 'some' | 'read-only' | 'none';\r\n\r\nexport function AssignmentsPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const { user } = useAuth();\r\n const [showTemplateModal, setShowTemplateModal] = useState(false);\r\n const [templateError, setTemplateError] = useState<string | null>(null);\r\n const [pageSize, setPageSize] = useState(25);\r\n const [currentPage, setCurrentPage] = useState(1);\r\n // Role pagination\r\n const [rolesPerPage, setRolesPerPage] = useState(10);\r\n const [rolePageIndex, setRolePageIndex] = useState(0);\r\n // Collapsed state (lifted from PermissionMatrixTable for proper pagination)\r\n const [collapsedApps, setCollapsedApps] = useState<Set<string>>(new Set());\r\n // Status filters\r\n const [statusFilters, setStatusFilters] = useState<Set<PermissionStatus>>(new Set());\r\n const [showGuide, setShowGuide] = useState(false);\r\n\r\n const toggleStatusFilter = (status: PermissionStatus) => {\r\n setStatusFilters(prev => {\r\n const next = new Set(prev);\r\n if (next.has(status)) {\r\n next.delete(status);\r\n } else {\r\n next.add(status);\r\n }\r\n return next;\r\n });\r\n // Reset both paginations when filter changes\r\n setCurrentPage(1);\r\n setRolePageIndex(0);\r\n };\r\n\r\n // Toggle function for collapsed state\r\n const handleToggleApp = (appKey: string) => {\r\n setCollapsedApps(prev => {\r\n const next = new Set(prev);\r\n if (next.has(appKey)) {\r\n next.delete(appKey);\r\n } else {\r\n next.add(appKey);\r\n }\r\n return next;\r\n });\r\n };\r\n\r\n // Super Admin (with \"*\" permission) can edit system roles\r\n const canEditSystemRoles = useMemo(() => {\r\n if (!user) return false;\r\n return hasFullAccess(user.permissions);\r\n }, [user]);\r\n\r\n const {\r\n loading,\r\n error,\r\n saveError,\r\n saving,\r\n roles,\r\n assignments,\r\n filters,\r\n filteredRoles,\r\n filteredResources,\r\n hasChanges,\r\n applications,\r\n modules,\r\n categories,\r\n togglePermission,\r\n updateFilters,\r\n reloadData,\r\n resetChanges,\r\n clearSaveError,\r\n getPermissionInheritance,\r\n } = usePermissionMatrix({ canEditSystemRoles });\r\n\r\n // Helper function to calculate status for a role-module combination\r\n const getStatusForRoleModule = useCallback(\r\n (roleId: string, resource: typeof filteredResources[0]): PermissionStatus => {\r\n const grantedPerms = resource.permissions.filter(perm => {\r\n const info = getPermissionInheritance(roleId, perm.id);\r\n return info.isDirect || info.isInherited;\r\n });\r\n const grantedCount = grantedPerms.length;\r\n const totalCount = resource.totalPermissions;\r\n\r\n if (grantedCount === 0) return 'none';\r\n if (grantedCount === totalCount) return 'all';\r\n if (grantedCount === 1 && grantedPerms[0]?.action === 'read') return 'read-only';\r\n return 'some';\r\n },\r\n [getPermissionInheritance]\r\n );\r\n\r\n // Get all modules from resources for status calculations\r\n const allModules = useMemo(() =>\r\n filteredResources.filter(r => r.level === 'module'),\r\n [filteredResources]\r\n );\r\n\r\n // OPTION B: Filter BOTH modules (rows) AND roles (columns) by status\r\n // Step 1: Filter roles - keep only roles that have the selected status for at least one module\r\n const statusFilteredRoles = useMemo(() => {\r\n if (statusFilters.size === 0) {\r\n return filteredRoles;\r\n }\r\n\r\n return filteredRoles.filter(role => {\r\n // Check if this role has the selected status for ANY module\r\n for (const module of allModules) {\r\n const status = getStatusForRoleModule(role.id, module);\r\n if (statusFilters.has(status)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n });\r\n }, [filteredRoles, allModules, statusFilters, getStatusForRoleModule]);\r\n\r\n // Step 2: Filter resources - keep only modules that have the selected status for at least one role\r\n const statusFilteredResources = useMemo(() => {\r\n if (statusFilters.size === 0) {\r\n return filteredResources;\r\n }\r\n\r\n return filteredResources.filter(resource => {\r\n // Keep context/app headers\r\n if (resource.level !== 'module') return true;\r\n\r\n // Check each role's status for this module\r\n for (const role of filteredRoles) {\r\n const status = getStatusForRoleModule(role.id, resource);\r\n if (statusFilters.has(status)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n });\r\n }, [filteredResources, filteredRoles, statusFilters, getStatusForRoleModule]);\r\n\r\n // Calculate total assigned permissions\r\n const totalAssignedPermissions = useMemo(() => {\r\n let count = 0;\r\n Object.values(assignments).forEach(perms => {\r\n count += perms.size;\r\n });\r\n return count;\r\n }, [assignments]);\r\n\r\n // Module pagination - count only VISIBLE modules (not in collapsed apps)\r\n const visibleModuleCount = useMemo(() => {\r\n return statusFilteredResources.filter(r => {\r\n if (r.level !== 'module') return false;\r\n // Check if parent app is collapsed\r\n if (collapsedApps.has(r.applicationLabel)) return false;\r\n return true;\r\n }).length;\r\n }, [statusFilteredResources, collapsedApps]);\r\n\r\n const totalModuleCount = useMemo(() => {\r\n return statusFilteredResources.filter(r => r.level === 'module').length;\r\n }, [statusFilteredResources]);\r\n\r\n const totalPages = Math.ceil(visibleModuleCount / pageSize);\r\n\r\n // Reset to page 1 when filters change\r\n const handleFilterChange = (newFilters: Parameters<typeof updateFilters>[0]) => {\r\n setCurrentPage(1);\r\n updateFilters(newFilters);\r\n };\r\n\r\n const handlePageSizeChange = (newSize: number) => {\r\n setPageSize(newSize);\r\n setCurrentPage(1);\r\n };\r\n\r\n // Role pagination - use statusFilteredRoles for Option B filtering\r\n const totalRolePages = Math.ceil(statusFilteredRoles.length / rolesPerPage);\r\n const handleRolesPerPageChange = (newSize: number) => {\r\n setRolesPerPage(newSize);\r\n setRolePageIndex(0);\r\n };\r\n\r\n const createRoleFromTemplate = async (templateKey: string) => {\r\n const template = ROLE_TEMPLATES[templateKey];\r\n if (!template) return;\r\n\r\n const roleName = prompt(t('assignments.enterRoleName'), t(template.nameKey));\r\n if (!roleName) return;\r\n\r\n try {\r\n setTemplateError(null);\r\n await adminApi.roles.create({\r\n name: roleName,\r\n description: t(template.descriptionKey),\r\n permissionIds: [],\r\n });\r\n setShowTemplateModal(false);\r\n await reloadData();\r\n } catch (err) {\r\n setTemplateError(err instanceof Error ? err.message : 'Failed to create role from template');\r\n }\r\n };\r\n\r\n const handleResetFilters = () => {\r\n setCurrentPage(1);\r\n updateFilters({\r\n selectedRoleIds: [],\r\n resourceSearch: '',\r\n applicationFilter: 'all',\r\n moduleFilter: 'all',\r\n });\r\n };\r\n\r\n if (loading) {\r\n return (\r\n <div className=\"flex items-center justify-center min-h-[400px]\">\r\n <div className=\"text-center\">\r\n <Loader2 className=\"h-8 w-8 animate-spin text-[var(--color-accent-500)] mx-auto mb-4\" />\r\n <p className=\"text-[var(--text-secondary)]\">{t('assignments.loading')}</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"p-6\">\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] p-4\">\r\n <div className=\"flex\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <div className=\"ml-3\">\r\n <h3 className=\"text-sm font-medium text-[var(--error-text)]\">{t('common.error')}</h3>\r\n <div className=\"mt-2 text-sm text-[var(--error-text)] opacity-80\">\r\n <p>{error}</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"p-6 space-y-4\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('assignments.title', 'Assignments') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('assignments.title')}</h1>\r\n <p className=\"mt-1 text-sm text-[var(--text-secondary)]\">{t('assignments.subtitle')}</p>\r\n </div>\r\n <div className=\"flex items-center gap-3 flex-shrink-0\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowTemplateModal(true)}\r\n className=\"inline-flex items-center px-4 py-2 border border-[var(--border-color)] text-sm font-medium rounded-[var(--radius-button)] text-[var(--text-secondary)] bg-[var(--bg-card)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <Sparkles className=\"h-4 w-4 mr-2\" />\r\n {t('assignments.createFromTemplate')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Save error alert */}\r\n {saveError && (\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--error-bg)] p-3 border border-[var(--error-border)]\">\r\n <div className=\"flex items-center\">\r\n <AlertCircle className=\"h-4 w-4 text-[var(--error-text)]\" />\r\n <p className=\"ml-2 text-sm text-[var(--error-text)]\">\r\n {saveError}\r\n </p>\r\n <button\r\n type=\"button\"\r\n onClick={clearSaveError}\r\n className=\"ml-auto text-sm text-[var(--error-text)] hover:opacity-80 font-medium\"\r\n >\r\n {t('common.dismiss')}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Auto-save warning */}\r\n {(hasChanges || saving) && (\r\n <div className=\"rounded-[var(--radius-card)] bg-[var(--warning-bg)] p-3 border border-[var(--warning-border)]\">\r\n <div className=\"flex items-center\">\r\n {saving ? (\r\n <Loader2 className=\"h-4 w-4 text-[var(--warning-dot)] animate-spin\" />\r\n ) : (\r\n <Info className=\"h-4 w-4 text-[var(--warning-dot)]\" />\r\n )}\r\n <p className=\"ml-2 text-sm text-[var(--warning-text)]\">\r\n {saving ? t('assignments.saving') : t('assignments.autoSaveActive')}\r\n </p>\r\n {!saving && (\r\n <button\r\n type=\"button\"\r\n onClick={resetChanges}\r\n className=\"ml-auto text-sm text-[var(--warning-text)] hover:opacity-80 font-medium\"\r\n >\r\n {t('assignments.discardChanges')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Filters */}\r\n <PermissionMatrixFilters\r\n filters={filters}\r\n roles={roles}\r\n categories={categories}\r\n applications={applications}\r\n modules={modules}\r\n hasChanges={hasChanges}\r\n onFilterChange={handleFilterChange}\r\n onReset={handleResetFilters}\r\n />\r\n\r\n {/* Stats bar + Legend + Role Pagination (top) */}\r\n <div className=\"flex flex-wrap items-center justify-between gap-3 py-2\">\r\n <div className=\"flex flex-wrap items-center gap-4\">\r\n {/* Stats badges */}\r\n <div className=\"flex flex-wrap items-center gap-3\">\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--color-accent-100)] text-[var(--color-accent-700)] dark:bg-[var(--color-accent-900)] dark:text-[var(--color-accent-300)]\">\r\n {statusFilteredRoles.length} {t('assignments.roles')}\r\n </span>\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--bg-tertiary)] text-[var(--text-secondary)]\">\r\n {visibleModuleCount}/{totalModuleCount} {t('assignments.modules')}\r\n </span>\r\n <span className=\"px-2.5 py-1 text-xs font-semibold rounded-full bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]\">\r\n {totalAssignedPermissions} {t('assignments.permissionsAssigned')}\r\n </span>\r\n </div>\r\n\r\n {/* Role Pagination (columns) - Top Left */}\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--text-secondary)] border-l border-[var(--border-color)] pl-4\">\r\n <span>{t('assignments.rolesPerPage')}:</span>\r\n <select\r\n value={rolesPerPage}\r\n onChange={(e) => handleRolesPerPageChange(Number(e.target.value))}\r\n className=\"px-2 py-1 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n {ROLES_PER_PAGE_OPTIONS.map(size => (\r\n <option key={size} value={size}>{size}</option>\r\n ))}\r\n </select>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {rolePageIndex * rolesPerPage + 1}-{Math.min((rolePageIndex + 1) * rolesPerPage, statusFilteredRoles.length)} / {statusFilteredRoles.length}\r\n </span>\r\n {totalRolePages > 1 && (\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setRolePageIndex(p => Math.max(0, p - 1))}\r\n disabled={rolePageIndex === 0}\r\n className=\"p-1 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronLeft className=\"h-3.5 w-3.5\" />\r\n </button>\r\n <span className=\"text-xs min-w-[50px] text-center\">\r\n {rolePageIndex + 1} / {totalRolePages}\r\n </span>\r\n <button\r\n onClick={() => setRolePageIndex(p => Math.min(totalRolePages - 1, p + 1))}\r\n disabled={rolePageIndex >= totalRolePages - 1}\r\n className=\"p-1 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronRight className=\"h-3.5 w-3.5\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Status Filter Buttons */}\r\n <div className=\"flex flex-wrap items-center gap-2\">\r\n <button\r\n onClick={() => toggleStatusFilter('none')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('none')\r\n ? 'bg-red-500/30 border-red-500 text-red-700 dark:text-red-300'\r\n : 'bg-red-500/10 border-red-500/30 text-red-600 dark:text-red-400 hover:bg-red-500/20 hover:border-red-500'\r\n }`}\r\n >\r\n <Ban className=\"h-3.5 w-3.5\" />\r\n {t('assignments.none')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('read-only')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('read-only')\r\n ? 'bg-sky-500/30 border-sky-500 text-sky-700 dark:text-sky-300'\r\n : 'bg-sky-500/10 border-sky-500/30 text-sky-600 dark:text-sky-400 hover:bg-sky-500/20 hover:border-sky-500'\r\n }`}\r\n >\r\n <Eye className=\"h-3.5 w-3.5\" />\r\n {t('assignments.readOnly')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('some')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('some')\r\n ? 'bg-amber-500/30 border-amber-500 text-amber-700 dark:text-amber-300'\r\n : 'bg-amber-500/10 border-amber-500/30 text-amber-600 dark:text-amber-400 hover:bg-amber-500/20 hover:border-amber-500'\r\n }`}\r\n >\r\n <Star className=\"h-3.5 w-3.5\" />\r\n {t('assignments.partial')}\r\n </button>\r\n <button\r\n onClick={() => toggleStatusFilter('all')}\r\n className={`inline-flex items-center gap-1.5 px-2.5 py-1 text-xs rounded-full border transition-colors cursor-pointer ${\r\n statusFilters.has('all')\r\n ? 'bg-emerald-500/30 border-emerald-500 text-emerald-700 dark:text-emerald-300'\r\n : 'bg-emerald-500/10 border-emerald-500/30 text-emerald-600 dark:text-emerald-400 hover:bg-emerald-500/20 hover:border-emerald-500'\r\n }`}\r\n >\r\n <Check className=\"h-3.5 w-3.5\" />\r\n {t('assignments.complete')}\r\n </button>\r\n {statusFilters.size > 0 && (\r\n <button\r\n onClick={() => setStatusFilters(new Set())}\r\n className=\"text-xs text-[var(--color-accent-500)] hover:text-[var(--color-accent-600)] underline ml-2\"\r\n >\r\n {t('assignments.clearFilters')}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* User Guide - Collapsible */}\r\n <div className=\"bg-[var(--bg-card)] border border-[var(--item-color-border)] rounded-[var(--radius-card)] overflow-hidden\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowGuide(!showGuide)}\r\n className=\"w-full flex items-center justify-between px-4 py-2.5 text-sm font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n <BookOpen className=\"h-4 w-4 text-[var(--color-accent-500)]\" />\r\n <span>{t('assignments.guide.title')}</span>\r\n </div>\r\n {showGuide ? (\r\n <ChevronUp className=\"h-4 w-4 text-[var(--text-muted)]\" />\r\n ) : (\r\n <ChevronDown className=\"h-4 w-4 text-[var(--text-muted)]\" />\r\n )}\r\n </button>\r\n\r\n {showGuide && (\r\n <div className=\"px-4 pb-4 border-t border-[var(--item-color-border)]\">\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 pt-3\">\r\n {/* Color Legend */}\r\n <div>\r\n <h4 className=\"text-xs font-semibold text-[var(--text-primary)] uppercase tracking-wider mb-2\">\r\n {t('assignments.guide.colorLegendTitle')}\r\n </h4>\r\n <div className=\"space-y-1.5\">\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-red-500/10 border border-red-500/20 text-red-600 dark:text-red-400\">\r\n <Ban className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.noneDesc')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-sky-500/20 border border-sky-500/30 text-sky-700 dark:text-sky-300\">\r\n <Eye className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.readOnlyDesc')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-amber-500/20 border border-amber-500/30 text-amber-700 dark:text-amber-300\">\r\n <Star className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.partialDesc')}</span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-xs\">\r\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-emerald-500/20 border border-emerald-500/30 text-emerald-700 dark:text-emerald-300\">\r\n <Check className=\"h-3 w-3\" />\r\n </span>\r\n <span className=\"text-[var(--text-secondary)]\">{t('assignments.guide.completeDesc')}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* How to Use */}\r\n <div>\r\n <h4 className=\"text-xs font-semibold text-[var(--text-primary)] uppercase tracking-wider mb-2\">\r\n {t('assignments.guide.howToUseTitle')}\r\n </h4>\r\n <ul className=\"space-y-1.5 text-xs text-[var(--text-secondary)]\">\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.clickCell')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <Lock className=\"h-3 w-3 flex-shrink-0 mt-0.5 text-[var(--warning-dot)]\" />\r\n {t('assignments.guide.systemRoles')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.inheritance')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.autoSave')}\r\n </li>\r\n <li className=\"flex items-start gap-2\">\r\n <span className=\"text-[var(--color-accent-500)] mt-0.5\">•</span>\r\n {t('assignments.guide.filterButtons')}\r\n </li>\r\n </ul>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Matrix Table */}\r\n <div className=\"bg-[var(--bg-card)] shadow-[var(--shadow-md)] rounded-[var(--radius-card)] border border-[var(--item-color-border)]\">\r\n <PermissionMatrixTable\r\n roles={statusFilteredRoles}\r\n resources={statusFilteredResources}\r\n assignments={assignments}\r\n canEditSystemRoles={canEditSystemRoles}\r\n onTogglePermission={togglePermission}\r\n getPermissionInheritance={getPermissionInheritance}\r\n rolesPerPage={rolesPerPage}\r\n rolePageIndex={rolePageIndex}\r\n modulesPerPage={pageSize}\r\n modulePageIndex={currentPage - 1}\r\n collapsedApps={collapsedApps}\r\n onToggleApp={handleToggleApp}\r\n statusFilters={statusFilters}\r\n />\r\n </div>\r\n\r\n {/* Module Pagination - Below Table */}\r\n <div className=\"py-3 px-4 bg-[var(--bg-card)] rounded-[var(--radius-card)] border border-[var(--item-color-border)]\">\r\n <div className=\"flex items-center gap-3 text-sm text-[var(--text-secondary)]\">\r\n <span>{t('assignments.itemsPerPage')}:</span>\r\n <select\r\n value={pageSize}\r\n onChange={(e) => handlePageSizeChange(Number(e.target.value))}\r\n className=\"px-2 py-1 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded text-[var(--text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n {PAGE_SIZE_OPTIONS.map(size => (\r\n <option key={size} value={size}>{size}</option>\r\n ))}\r\n </select>\r\n <span className=\"text-[var(--text-muted)]\">\r\n {(currentPage - 1) * pageSize + 1}-{Math.min(currentPage * pageSize, visibleModuleCount)} / {visibleModuleCount}\r\n </span>\r\n {totalPages > 1 && (\r\n <div className=\"flex items-center gap-1\">\r\n <button\r\n onClick={() => setCurrentPage(p => Math.max(1, p - 1))}\r\n disabled={currentPage === 1}\r\n className=\"p-1.5 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronLeft className=\"h-4 w-4\" />\r\n </button>\r\n <span className=\"text-sm min-w-[60px] text-center\">\r\n {currentPage} / {totalPages}\r\n </span>\r\n <button\r\n onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}\r\n disabled={currentPage >= totalPages}\r\n className=\"p-1.5 rounded border border-[var(--border-color)] bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] disabled:opacity-30 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n <ChevronRight className=\"h-4 w-4\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Template Modal */}\r\n {showTemplateModal && (\r\n <div className=\"fixed inset-0 z-50 overflow-y-auto\">\r\n <div className=\"flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:p-0\">\r\n <button type=\"button\" className=\"fixed inset-0 bg-black/50 transition-opacity\" onClick={() => setShowTemplateModal(false)} aria-label=\"Close modal\" />\r\n <div className=\"inline-block align-bottom bg-[var(--bg-card)] rounded-[var(--radius-modal)] px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full sm:p-6 border border-[var(--border-color)]\">\r\n <div className=\"mb-4\">\r\n <h3 className=\"text-lg font-medium text-[var(--text-primary)]\">\r\n {t('assignments.createFromTemplate')}\r\n </h3>\r\n <p className=\"mt-1 text-sm text-[var(--text-secondary)]\">\r\n {t('assignments.templateDescription')}\r\n </p>\r\n </div>\r\n\r\n {templateError && (\r\n <div className=\"mb-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)] p-3\">\r\n <div className=\"flex\">\r\n <AlertCircle className=\"h-5 w-5 text-[var(--error-text)]\" />\r\n <div className=\"ml-3\">\r\n <p className=\"text-sm text-[var(--error-text)]\">{templateError}</p>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\r\n {Object.entries(ROLE_TEMPLATES).map(([key, template]) => {\r\n const Icon = template.icon;\r\n return (\r\n <button\r\n key={key}\r\n onClick={() => createRoleFromTemplate(key)}\r\n className=\"relative p-4 rounded-[var(--radius-card)] border-2 text-left transition-all hover:shadow-lg hover:scale-105 border-[var(--border-color)] hover:border-[var(--color-accent-500)]\"\r\n >\r\n <div className=\"flex items-start gap-3\">\r\n <Icon className=\"h-6 w-6 text-[var(--color-accent-500)]\" />\r\n <div className=\"flex-1\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)]\">{t(template.nameKey)}</h4>\r\n <p className=\"mt-1 text-xs text-[var(--text-secondary)]\">{t(template.descriptionKey)}</p>\r\n </div>\r\n </div>\r\n </button>\r\n );\r\n })}\r\n </div>\r\n <div className=\"mt-5 sm:mt-6\">\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n setShowTemplateModal(false);\r\n setTemplateError(null);\r\n }}\r\n className=\"w-full inline-flex justify-center rounded-[var(--radius-button)] border border-[var(--border-color)] shadow-sm px-4 py-2 bg-[var(--bg-secondary)] text-base font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["SectionResourceRows","section","resources","moduleIndex","sectionIndex","_isCollapsed","collapsedSections","_paginatedRoles","_canEditSystemRoles","_statusFilters","_openPopover","_onToggleCollapse","_onTogglePermission","_onCellClick","_setOpenPopover","renderResourceRow","isSectionCollapsed","hasResources","jsxs","React","resource","resourceIndex","PermissionMatrixTable","roles","canEditSystemRoles","onTogglePermission","getPermissionInheritance","rolesPerPage","rolePageIndex","modulesPerPage","modulePageIndex","collapsedApps","onToggleApp","statusFilters","t","useTranslation","openPopover","setOpenPopover","useState","collapsedModules","setCollapsedModules","setCollapsedSections","toggleCollapsedItem","useCallback","id","setCollapsed","prev","next","toggleModule","moduleId","toggleSection","sectionId","moduleCount","useMemo","r","paginatedRoles","start","allGroupedResources","groupByApplicationWithSections","paginateAppGroups","startIndex","endIndex","visibleIndexRef","result","appGroup","isAppCollapsed","paginatedModules","moduleWithSections","groupedResources","isPermissionGranted","roleId","permissionId","inheritanceInfo","getPermissionStatusForRole","calculatePermissionStatus","permId","handleCellClick","resourceId","jsx","getPaddingForLevel","level","getResourceIcon","Database","FileText","Box","getResourceLabelClass","handleToggleCollapse","renderToggleButton","hasChildren","isCollapsed","ChevronRight","ChevronDown","renderCellsForRoles","role","status","grantedCount","isPopoverOpen","buttonRef","createRef","isRoleEditable","cellBg","getPermissionCellBackground","isFilteredOut","PermissionStatusIndicator","PermissionPopover","rowIndex","paddingLeft","rowBgClass","Lock","colSpan","FolderOpen","module","sections","hasSections","isModuleCollapsed","sectionWithResources","PermissionMatrixFilters","filters","categories","applications","modules","hasChanges","onFilterChange","onReset","isRoleDropdownOpen","setIsRoleDropdownOpen","roleSearchTerm","setRoleSearchTerm","roleDropdownRef","useRef","roleSearchInputRef","filteredRoles","searchLower","useEffect","toggleRoleDropdown","open","filteredModules","m","handleClickOutside","event","handleRoleToggle","newSelectedRoles","handleSelectAllRoles","handleClearRoles","handleApplicationChange","app","handleCategoryChange","category","hasActiveFilters","selectedRolesLabel","Filter","e","cat","Search","Check","mod","RotateCcw","X","ROLE_TEMPLATES","Eye","User","Pencil","ShieldCheck","PAGE_SIZE_OPTIONS","ROLES_PER_PAGE_OPTIONS","AssignmentsPage","user","useAuth","showTemplateModal","setShowTemplateModal","templateError","setTemplateError","pageSize","setPageSize","currentPage","setCurrentPage","setRolesPerPage","setRolePageIndex","setCollapsedApps","setStatusFilters","showGuide","setShowGuide","toggleStatusFilter","handleToggleApp","appKey","hasFullAccess","loading","error","saveError","saving","assignments","filteredResources","togglePermission","updateFilters","reloadData","resetChanges","clearSaveError","usePermissionMatrix","getStatusForRoleModule","grantedPerms","perm","info","totalCount","allModules","statusFilteredRoles","statusFilteredResources","totalAssignedPermissions","count","perms","visibleModuleCount","totalModuleCount","totalPages","handleFilterChange","newFilters","handlePageSizeChange","newSize","totalRolePages","handleRolesPerPageChange","createRoleFromTemplate","templateKey","template","roleName","adminApi","err","handleResetFilters","Loader2","AlertCircle","Breadcrumb","Sparkles","Info","size","p","ChevronLeft","Ban","Star","BookOpen","ChevronUp","key","Icon"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),u=require("react"),h=require("react-router-dom"),c=require("lucide-react"),m=require("./index-
|
|
2
|
-
//# sourceMappingURL=AuthCallbackPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),u=require("react"),h=require("react-router-dom"),c=require("lucide-react"),m=require("./index-IgLVXPg8.js"),v={auth_failed:"L'authentification a échoué. Veuillez réessayer.",no_email:"Impossible de récupérer votre adresse email depuis le fournisseur.",account_disabled:"Votre compte est désactivé. Contactez l'administrateur.",account_locked:"Votre compte est verrouillé. Contactez l'administrateur.",internal_error:"Une erreur interne est survenue. Veuillez réessayer."};function y(){const[o]=h.useSearchParams(),g=h.useNavigate(),[l,a]=u.useState("processing"),[x,d]=u.useState("");u.useEffect(()=>{const r=o.get("token"),i=o.get("refreshToken"),s=o.get("error");if(s){a("error"),d(v[s]||"Une erreur est survenue lors de l'authentification.");return}r&&i?f(r,i):(a("error"),d("Paramètres d'authentification manquants."))},[o]);const f=async(r,i)=>{try{localStorage.setItem("token",r),localStorage.setItem("refreshToken",i);try{const t=await m.getClientIpAddress(),n=m.detectDeviceType();(t||n)&&await fetch("/api/auth/update-session-client-info",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`},body:JSON.stringify({clientIp:t,deviceType:n})})}catch{}const s=await fetch("/api/auth/me",{headers:{Authorization:`Bearer ${r}`}});if(!s.ok)throw new Error("Failed to fetch user info");const p=await s.json();localStorage.setItem("user",JSON.stringify(p));try{const t=await fetch("/api/onboarding/status",{headers:{Authorization:`Bearer ${r}`}});if(t.ok&&!(await t.json()).hasCompletedOnboarding){a("success"),setTimeout(()=>{window.location.href="/auth/onboarding"},1500);return}}catch{}try{const t=await m.userApi.preferences.get(),n={mode:t.theme||"dark",accentColorKey:t.accentColorKey||"indigo",borderRadius:t.borderRadius||{},itemPaletteKey:t.itemPaletteKey||"neutral"};localStorage.setItem("smartstack-theme-config",JSON.stringify(n)),t.language&&localStorage.setItem("i18nextLng",t.language)}catch{}a("success"),localStorage.removeItem("currentTenantId"),localStorage.removeItem("currentTenantSlug"),localStorage.removeItem("isGlobalView"),setTimeout(()=>{window.location.href="/myspace"},1500)}catch(s){console.error("Auth callback error:",s),a("error"),d("Erreur lors de la finalisation de l'authentification.")}},b=()=>{g("/login")};return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-[var(--bg-primary)]",children:e.jsx("div",{className:"max-w-md w-full mx-4",children:e.jsxs("div",{className:"bg-[var(--bg-secondary)] rounded-2xl p-8 shadow-lg border border-[var(--border-color)]",children:[l==="processing"&&e.jsxs("div",{className:"text-center",children:[e.jsx(c.Loader2,{className:"w-16 h-16 mx-auto text-[var(--color-accent-500)] animate-spin mb-4"}),e.jsx("h2",{className:"text-xl font-semibold mb-2",children:"Authentification en cours..."}),e.jsx("p",{className:"text-[var(--text-secondary)]",children:"Veuillez patienter pendant que nous finalisons votre connexion."})]}),l==="success"&&e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-16 h-16 mx-auto bg-green-100 dark:bg-green-900/30 rounded-full flex items-center justify-center mb-4",children:e.jsx(c.CheckCircle,{className:"w-10 h-10 text-green-600 dark:text-green-400"})}),e.jsx("h2",{className:"text-xl font-semibold mb-2",children:"Connexion réussie !"}),e.jsx("p",{className:"text-[var(--text-secondary)]",children:"Vous allez être redirigé vers votre espace personnel..."})]}),l==="error"&&e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-16 h-16 mx-auto bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center mb-4",children:e.jsx(c.XCircle,{className:"w-10 h-10 text-red-600 dark:text-red-400"})}),e.jsx("h2",{className:"text-xl font-semibold mb-2",children:"Échec de l'authentification"}),e.jsx("div",{className:"bg-red-50 dark:bg-red-900/20 rounded-lg p-4 mb-6",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(c.AlertCircle,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5"}),e.jsx("p",{className:"text-sm text-red-700 dark:text-red-300",children:x})]})}),e.jsx("button",{onClick:b,className:"btn btn-primary w-full",children:"Retourner à la connexion"})]})]})})})}exports.AuthCallbackPage=y;
|
|
2
|
+
//# sourceMappingURL=AuthCallbackPage-CA2nO6DG.js.map
|