@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,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("./index-
|
|
2
|
-
//# sourceMappingURL=UserTicketDetailPage-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("./index-IgLVXPg8.js");function i(){return e.jsx(t.TicketDetailView,{mode:"client"})}exports.UserTicketDetailPage=i;
|
|
2
|
+
//# sourceMappingURL=UserTicketDetailPage-CWoYQgH-.js.map
|
package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserTicketDetailPage-
|
|
1
|
+
{"version":3,"file":"UserTicketDetailPage-CWoYQgH-.js","sources":["../../src/pages/platform/support/UserTicketDetailPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { TicketDetailView } from '@/components/platform/support/TicketDetailView';\r\n\r\nexport function UserTicketDetailPage(): ReactElement {\r\n return <TicketDetailView mode=\"client\" />;\r\n}\r\n"],"names":["UserTicketDetailPage","jsx","TicketDetailView"],"mappings":"sJAGO,SAASA,GAAqC,CACnD,OAAOC,EAAAA,IAACC,EAAAA,iBAAA,CAAiB,KAAK,QAAA,CAAS,CACzC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
-
import { $ as t } from "./index-
|
|
2
|
+
import { $ as t } from "./index-lpIzhufD.js";
|
|
3
3
|
function o() {
|
|
4
4
|
return /* @__PURE__ */ e(t, { mode: "client" });
|
|
5
5
|
}
|
|
6
6
|
export {
|
|
7
7
|
o as UserTicketDetailPage
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=UserTicketDetailPage-
|
|
9
|
+
//# sourceMappingURL=UserTicketDetailPage-DkufSlvZ.js.map
|
package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserTicketDetailPage-
|
|
1
|
+
{"version":3,"file":"UserTicketDetailPage-DkufSlvZ.js","sources":["../../src/pages/platform/support/UserTicketDetailPage.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport { TicketDetailView } from '@/components/platform/support/TicketDetailView';\r\n\r\nexport function UserTicketDetailPage(): ReactElement {\r\n return <TicketDetailView mode=\"client\" />;\r\n}\r\n"],"names":["UserTicketDetailPage","jsx","TicketDetailView"],"mappings":";;AAGO,SAASA,IAAqC;AACnD,SAAO,gBAAAC,EAACC,GAAA,EAAiB,MAAK,SAAA,CAAS;AACzC;"}
|
|
@@ -2,9 +2,9 @@ import { jsx as r, jsxs as a } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState as n, useCallback as re, useEffect as fe } from "react";
|
|
3
3
|
import { useTranslation as Ne } from "react-i18next";
|
|
4
4
|
import { useNavigate as we, Link as Ge } from "react-router-dom";
|
|
5
|
-
import { a as Ce, k as te, B as Se } from "./index-
|
|
5
|
+
import { a as Ce, k as te, B as Se } from "./index-lpIzhufD.js";
|
|
6
6
|
import { Loader2 as L, Users as M, RefreshCw as ke, Plus as I, AlertTriangle as Ee, X as T, Search as Ae, Filter as Fe, Cloud as V, LayoutGrid as De, List as Me, CornerDownRight as ae, Shield as P, Building2 as se, GitBranch as ne, CloudOff as oe, Trash2 as ie, ChevronUp as Pe, ChevronDown as $e, Check as Re } from "lucide-react";
|
|
7
|
-
import { g as h } from "./groupsApi-
|
|
7
|
+
import { g as h } from "./groupsApi-QzXI-5xu.js";
|
|
8
8
|
const le = (t) => t ? "bg-[var(--color-accent-500)] text-white" : "text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]";
|
|
9
9
|
function je(t) {
|
|
10
10
|
const d = /* @__PURE__ */ new Map();
|
|
@@ -579,4 +579,4 @@ function Oe() {
|
|
|
579
579
|
export {
|
|
580
580
|
Oe as UsersGroupsPage
|
|
581
581
|
};
|
|
582
|
-
//# sourceMappingURL=UsersGroupsPage-
|
|
582
|
+
//# sourceMappingURL=UsersGroupsPage-C38s2-Rq.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersGroupsPage-CmdaU-z-.js","sources":["../../src/pages/platform/administration/users/UsersGroupsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link, useNavigate } from 'react-router-dom';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport {\r\n Building2,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n Search,\r\n Users,\r\n Shield,\r\n Plus,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n LayoutGrid,\r\n List,\r\n Filter,\r\n Cloud,\r\n CloudOff,\r\n Trash2,\r\n Check,\r\n GitBranch,\r\n CornerDownRight,\r\n} from 'lucide-react';\r\nimport {\r\n groupsApi,\r\n type GroupListDto,\r\n type GroupMemberDto,\r\n type GroupRoleDto,\r\n} from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\n\r\ntype ViewMode = 'cards' | 'table';\r\ntype GroupTypeFilter = 'all' | 'security' | 'distribution';\r\ntype SyncFilter = 'all' | 'local' | 'synced';\r\n\r\ninterface GroupWithDetails extends GroupListDto {\r\n membersLoaded?: GroupMemberDto[];\r\n rolesLoaded?: GroupRoleDto[];\r\n}\r\n\r\nconst getViewModeButtonClass = (isActive: boolean): string => {\r\n if (isActive) {\r\n return 'bg-[var(--color-accent-500)] text-white';\r\n }\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]';\r\n};\r\n\r\n/** Build a hierarchical list: root groups first, then their children indented, recursively */\r\nfunction buildHierarchicalList<T extends { id: string; parentGroupId: string | null }>(\r\n items: T[]\r\n): { item: T; depth: number }[] {\r\n const childrenMap = new Map<string | null, T[]>();\r\n for (const item of items) {\r\n const parentId = item.parentGroupId;\r\n if (!childrenMap.has(parentId)) childrenMap.set(parentId, []);\r\n childrenMap.get(parentId)!.push(item);\r\n }\r\n\r\n const result: { item: T; depth: number }[] = [];\r\n const addChildren = (parentId: string | null, depth: number) => {\r\n const children = childrenMap.get(parentId) || [];\r\n for (const child of children) {\r\n result.push({ item: child, depth });\r\n addChildren(child.id, depth + 1);\r\n }\r\n };\r\n\r\n // Start with root groups (parentGroupId is null or parent not in current filtered list)\r\n const itemIds = new Set(items.map(i => i.id));\r\n const roots = items.filter(i => !i.parentGroupId || !itemIds.has(i.parentGroupId));\r\n for (const root of roots) {\r\n result.push({ item: root, depth: 0 });\r\n addChildren(root.id, 1);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function UsersGroupsPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'common']);\r\n const navigate = useNavigate();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const [loading, setLoading] = useState(true);\r\n const [groups, setGroups] = useState<GroupWithDetails[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [selectedGroup, setSelectedGroup] = useState<GroupWithDetails | null>(null);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [showCreateModal, setShowCreateModal] = useState(false);\r\n const [expandedGroupId, setExpandedGroupId] = useState<string | null>(null);\r\n const [members, setMembers] = useState<Record<string, GroupMemberDto[]>>({});\r\n const [loadingMembers, setLoadingMembers] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [groupTypeFilter, setGroupTypeFilter] = useState<GroupTypeFilter>('all');\r\n const [syncFilter, setSyncFilter] = useState<SyncFilter>('all');\r\n\r\n // Create group form state\r\n const [newGroupName, setNewGroupName] = useState('');\r\n const [newGroupDescription, setNewGroupDescription] = useState('');\r\n const [newGroupIsSecurityGroup, setNewGroupIsSecurityGroup] = useState(true);\r\n const [newGroupParentId, setNewGroupParentId] = useState<string>('');\r\n const [creating, setCreating] = useState(false);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n setGroups(Array.isArray(groupsData) ? groupsData : []);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load groups:', err);\r\n setGroups([]);\r\n setRoles([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('admin:groups.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n // TENANT ISOLATION: Re-fetch when tenant changes\r\n }, [t, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await groupsApi.getMembers(groupId);\r\n setMembers(prev => ({ ...prev, [groupId]: data }));\r\n setExpandedGroupId(groupId);\r\n } catch (err) {\r\n console.error('Failed to load members:', err);\r\n setError(t('admin:groups.loadError'));\r\n } finally {\r\n setLoadingMembers(null);\r\n }\r\n };\r\n\r\n const reloadGroupsAndRoles = useCallback(async () => {\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n const safeGroupsData = Array.isArray(groupsData) ? groupsData : [];\r\n setGroups(safeGroupsData);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n return safeGroupsData;\r\n }, []);\r\n\r\n const handleCreateGroup = async () => {\r\n if (!newGroupName.trim()) return;\r\n\r\n setCreating(true);\r\n try {\r\n await groupsApi.create({\r\n name: newGroupName.trim(),\r\n description: newGroupDescription.trim() || undefined,\r\n isSecurityGroup: newGroupIsSecurityGroup,\r\n parentGroupId: newGroupParentId || undefined,\r\n });\r\n await loadData();\r\n setShowCreateModal(false);\r\n setNewGroupName('');\r\n setNewGroupDescription('');\r\n setNewGroupIsSecurityGroup(true);\r\n setNewGroupParentId('');\r\n } catch (err) {\r\n console.error('Failed to create group:', err);\r\n const axiosError = err as { response?: { status?: number; data?: { message?: string } } };\r\n if (axiosError.response?.status === 409) {\r\n setError(axiosError.response.data?.message || t('admin:groups.createError'));\r\n } else {\r\n setError(t('admin:groups.createError'));\r\n }\r\n } finally {\r\n setCreating(false);\r\n }\r\n };\r\n\r\n const handleDeleteGroup = async (groupId: string, groupName: string, isSyncedFromEntra: boolean = false) => {\r\n const confirmMessage = isSyncedFromEntra\r\n ? t('admin:groups.deleteConfirmEntra', { name: groupName, defaultValue: `Le groupe \"${groupName}\" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.\\n\\nÊtes-vous sûr de vouloir le supprimer ?` })\r\n : t('admin:groups.deleteConfirm', { name: groupName });\r\n\r\n if (!confirm(confirmMessage)) return;\r\n\r\n try {\r\n await groupsApi.delete(groupId);\r\n await loadData();\r\n } catch (err) {\r\n console.error('Failed to delete group:', err);\r\n setError(t('admin:groups.deleteError'));\r\n }\r\n };\r\n\r\n const handleAssignRole = async (roleId: string) => {\r\n if (!selectedGroup) return;\r\n try {\r\n await groupsApi.assignRole(selectedGroup.id, { roleId });\r\n const safeGroupsData = await reloadGroupsAndRoles();\r\n const updatedGroup = safeGroupsData.find(g => g.id === selectedGroup.id);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('admin:groups.assignError'));\r\n }\r\n };\r\n\r\n const filteredGroups = groups.filter((g) => {\r\n const matchesSearch =\r\n g.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\r\n g.description?.toLowerCase().includes(searchQuery.toLowerCase());\r\n\r\n const matchesType =\r\n groupTypeFilter === 'all' ||\r\n (groupTypeFilter === 'security' && g.isSecurityGroup) ||\r\n (groupTypeFilter === 'distribution' && !g.isSecurityGroup);\r\n\r\n const matchesSync =\r\n syncFilter === 'all' ||\r\n (syncFilter === 'local' && !g.isSyncedFromEntra) ||\r\n (syncFilter === 'synced' && g.isSyncedFromEntra);\r\n\r\n return matchesSearch && matchesType && matchesSync;\r\n });\r\n\r\n const hierarchicalGroups = buildHierarchicalList(filteredGroups);\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return '-';\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\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 <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('admin:header.title'), href: '/administration' },\r\n { label: t('admin:users.title', 'Users'), href: '/administration/users' },\r\n { label: t('admin:groups.title', 'Groups') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <Users className=\"w-6 h-6 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('admin:groups.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('admin:groups.subtitle', { count: groups.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n <button\r\n onClick={() => setShowCreateModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.createGroup')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-4\">\r\n {/* Search */}\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('admin:groups.searchPlaceholder')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Type Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={groupTypeFilter}\r\n onChange={(e) => setGroupTypeFilter(e.target.value as GroupTypeFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allTypes')}</option>\r\n <option value=\"security\">{t('admin:groups.securityGroup')}</option>\r\n <option value=\"distribution\">{t('admin:groups.distributionGroup')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Sync Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Cloud className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={syncFilter}\r\n onChange={(e) => setSyncFilter(e.target.value as SyncFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allSyncStatus')}</option>\r\n <option value=\"local\">{t('admin:groups.localOnly')}</option>\r\n <option value=\"synced\">{t('admin:groups.syncedFromEntra')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setViewMode('cards')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'cards')}`}\r\n title={t('admin:groups.cardView')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'table')}`}\r\n title={t('admin:groups.tableView')}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Groups List */}\r\n {filteredGroups.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {searchQuery || groupTypeFilter !== 'all' || syncFilter !== 'all'\r\n ? t('admin:groups.noResults')\r\n : t('admin:groups.noGroups')}\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-secondary)]\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.groupName')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.parentGroup')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:type')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.source')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.members')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.assignedRoles')}\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:actionsColumn')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {hierarchicalGroups.map(({ item: group, depth }) => (\r\n <tr key={group.id} className=\"hover:bg-[var(--bg-hover)] cursor-pointer\" onClick={() => navigate(`/administration/users/groups/${group.id}`)}>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\" style={{ paddingLeft: `${depth * 24}px` }}>\r\n {depth > 0 && (\r\n <CornerDownRight className=\"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0\" />\r\n )}\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-4 h-4\" />\r\n ) : (\r\n <Building2 className=\"w-4 h-4\" />\r\n )}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)] hover:underline\">{group.name}</span>\r\n {group.childCount > 0 && (\r\n <span className=\"flex items-center gap-0.5 px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.childCount}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate max-w-xs\">\r\n {group.description}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {group.parentGroupName ? (\r\n <span className=\"text-[var(--text-secondary)]\">{group.parentGroupName}</span>\r\n ) : (\r\n <span className=\"text-[var(--text-tertiary)]\">-</span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"flex items-center gap-1 text-sm text-blue-500\">\r\n <Cloud className=\"w-4 h-4\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"flex items-center gap-1 text-sm text-[var(--text-tertiary)]\">\r\n <CloudOff className=\"w-4 h-4\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n <span className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n {group.memberCount}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {group.roles.slice(0, 2).map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\"\r\n >\r\n {role}\r\n </span>\r\n ))}\r\n {group.roles.length > 2 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n +{group.roles.length - 2}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-right\" onClick={(e) => e.stopPropagation()}>\r\n <div className=\"flex items-center justify-end gap-2\">\r\n <button\r\n onClick={() => {\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n title={t('admin:groups.assignRole')}\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra)}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n title={t('common:delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode !== 'table' && (\r\n /* Cards View */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {hierarchicalGroups.map(({ item: group }) => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={group.id}\r\n className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left flex flex-col\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/users/groups/${group.id}`); } }}\r\n >\r\n {/* Card Header */}\r\n <div className=\"p-4 flex-1\">\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-5 h-5\" />\r\n ) : (\r\n <Building2 className=\"w-5 h-5\" />\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <span className=\"font-semibold text-[var(--text-primary)] truncate\">\r\n {group.name}\r\n </span>\r\n {group.isSecurityGroup && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20\">\r\n {t('admin:groups.securityGroup')}\r\n </span>\r\n )}\r\n {!group.isActive && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n {t('common:inactive')}\r\n </span>\r\n )}\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20 flex items-center gap-1\">\r\n <Cloud className=\"w-3 h-3\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CloudOff className=\"w-3 h-3\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n {group.parentGroupName && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CornerDownRight className=\"w-3 h-3\" />\r\n {group.parentGroupName}\r\n </span>\r\n )}\r\n {group.childCount > 0 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('admin:groups.childGroupCount', { count: group.childCount })}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2\">\r\n {group.description}\r\n </p>\r\n )}\r\n <div className=\"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); loadMembers(group.id); }}\r\n className=\"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.memberCount', { count: group.memberCount })}\r\n {loadingMembers === group.id && (\r\n <Loader2 className=\"w-3 h-3 animate-spin ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId === group.id && (\r\n <ChevronUp className=\"w-3 h-3 ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId !== group.id && (\r\n <ChevronDown className=\"w-3 h-3 ml-1\" />\r\n )}\r\n </button>\r\n </div>\r\n {group.isSyncedFromEntra && group.lastEntraSyncAt && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.lastSynced', { date: formatDate(group.lastEntraSyncAt) })}\r\n </p>\r\n )}\r\n {!group.isSyncedFromEntra && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.createdAt', { date: formatDate(group.createdAt) })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"flex flex-col gap-2 flex-shrink-0\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); setSelectedGroup(group); setShowAssignModal(true); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.assignRole')}\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--error-border)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n {t('common:delete')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Assigned Roles */}\r\n {group.roles.length > 0 && (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {t('admin:groups.assignedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {group.roles.map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Shield className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n <span className=\"text-sm text-[var(--text-primary)]\">{role}</span>\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Members Panel */}\r\n {expandedGroupId === group.id && members[group.id] && (\r\n <div className=\"border-t border-[var(--border-color)] bg-[var(--bg-primary)]\">\r\n <div className=\"p-4\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2\">\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.members')} ({members[group.id].length})\r\n </h4>\r\n {members[group.id].length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.noMembers')}\r\n </p>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto\">\r\n {members[group.id].slice(0, 10).map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0).toUpperCase()}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">\r\n {member.email}\r\n </p>\r\n </div>\r\n </Link>\r\n ))}\r\n </div>\r\n )}\r\n {members[group.id].length > 10 && (\r\n <p className=\"mt-3 text-center text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.showingMembers', {\r\n shown: 10,\r\n total: members[group.id].length,\r\n })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Create Group Modal */}\r\n {showCreateModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.createGroup')}\r\n </h2>\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4 space-y-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.groupName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newGroupName}\r\n onChange={(e) => setNewGroupName(e.target.value)}\r\n placeholder={t('admin:groups.groupNamePlaceholder')}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('common:description')}\r\n </label>\r\n <textarea\r\n value={newGroupDescription}\r\n onChange={(e) => setNewGroupDescription(e.target.value)}\r\n placeholder={t('admin:groups.descriptionPlaceholder')}\r\n rows={3}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setNewGroupIsSecurityGroup(!newGroupIsSecurityGroup)}\r\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\r\n newGroupIsSecurityGroup\r\n ? 'bg-[var(--color-accent-500)]'\r\n : 'bg-[var(--bg-tertiary)]'\r\n }`}\r\n >\r\n <span\r\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\r\n newGroupIsSecurityGroup ? 'translate-x-6' : 'translate-x-1'\r\n }`}\r\n />\r\n </button>\r\n <span className=\"text-sm text-[var(--text-primary)]\">\r\n {t('admin:groups.isSecurityGroup')}\r\n </span>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.parentGroup')}\r\n </label>\r\n <select\r\n value={newGroupParentId}\r\n onChange={(e) => setNewGroupParentId(e.target.value)}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"\">{t('admin:groups.noParent')}</option>\r\n {groups.filter(g => g.isActive).map(g => (\r\n <option key={g.id} value={g.id}>{g.name}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-end gap-3 p-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common:cancel')}\r\n </button>\r\n <button\r\n onClick={handleCreateGroup}\r\n disabled={!newGroupName.trim() || creating}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {creating ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Check className=\"w-4 h-4\" />\r\n )}\r\n {t('common:create')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {showAssignModal && selectedGroup && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.assignRoleTitle')}\r\n </h2>\r\n <button\r\n onClick={() => {\r\n setShowAssignModal(false);\r\n setSelectedGroup(null);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4\">\r\n <p className=\"text-sm text-[var(--text-secondary)] mb-4\">\r\n {t('admin:groups.assignRoleDescription', { group: selectedGroup.name })}\r\n </p>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {roles\r\n .filter((role) => !selectedGroup.roles.includes(role.name))\r\n .map((role) => (\r\n <button\r\n key={role.id}\r\n onClick={() => handleAssignRole(role.id)}\r\n className=\"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n <div>\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n </button>\r\n ))}\r\n {roles.filter((role) => !selectedGroup.roles.includes(role.name)).length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('admin:groups.allRolesAssigned')}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["getViewModeButtonClass","isActive","buildHierarchicalList","items","childrenMap","item","parentId","result","addChildren","depth","children","child","itemIds","roots","root","UsersGroupsPage","useTranslation","navigate","useNavigate","currentTenant","isGlobalView","useTenant","loading","setLoading","useState","groups","setGroups","roles","setRoles","error","setError","searchQuery","setSearchQuery","selectedGroup","setSelectedGroup","showAssignModal","setShowAssignModal","showCreateModal","setShowCreateModal","expandedGroupId","setExpandedGroupId","members","setMembers","loadingMembers","setLoadingMembers","viewMode","setViewMode","groupTypeFilter","setGroupTypeFilter","syncFilter","setSyncFilter","newGroupName","setNewGroupName","newGroupDescription","setNewGroupDescription","newGroupIsSecurityGroup","setNewGroupIsSecurityGroup","newGroupParentId","setNewGroupParentId","creating","setCreating","loadData","useCallback","groupsData","rolesData","groupsApi","adminApi","err","axiosError","useEffect","loadMembers","groupId","data","prev","reloadGroupsAndRoles","safeGroupsData","handleCreateGroup","handleDeleteGroup","groupName","isSyncedFromEntra","confirmMessage","handleAssignRole","roleId","updatedGroup","g","filteredGroups","matchesSearch","matchesType","matchesSync","hierarchicalGroups","formatDate","date","jsx","Loader2","jsxs","Breadcrumb","Users","RefreshCw","Plus","AlertTriangle","X","Search","Filter","Cloud","LayoutGrid","List","group","CornerDownRight","Shield","Building2","GitBranch","CloudOff","role","index","e","Trash2","ChevronUp","ChevronDown","member","Link","Check"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UsersGroupsPage-C38s2-Rq.js","sources":["../../src/pages/platform/administration/users/UsersGroupsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { Link, useNavigate } from 'react-router-dom';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport {\r\n Building2,\r\n RefreshCw,\r\n Loader2,\r\n AlertTriangle,\r\n Search,\r\n Users,\r\n Shield,\r\n Plus,\r\n X,\r\n ChevronDown,\r\n ChevronUp,\r\n LayoutGrid,\r\n List,\r\n Filter,\r\n Cloud,\r\n CloudOff,\r\n Trash2,\r\n Check,\r\n GitBranch,\r\n CornerDownRight,\r\n} from 'lucide-react';\r\nimport {\r\n groupsApi,\r\n type GroupListDto,\r\n type GroupMemberDto,\r\n type GroupRoleDto,\r\n} from '@/services/api/groupsApi';\r\nimport { adminApi, type RoleListDto } from '@/services/api/adminApi';\r\n\r\ntype ViewMode = 'cards' | 'table';\r\ntype GroupTypeFilter = 'all' | 'security' | 'distribution';\r\ntype SyncFilter = 'all' | 'local' | 'synced';\r\n\r\ninterface GroupWithDetails extends GroupListDto {\r\n membersLoaded?: GroupMemberDto[];\r\n rolesLoaded?: GroupRoleDto[];\r\n}\r\n\r\nconst getViewModeButtonClass = (isActive: boolean): string => {\r\n if (isActive) {\r\n return 'bg-[var(--color-accent-500)] text-white';\r\n }\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]';\r\n};\r\n\r\n/** Build a hierarchical list: root groups first, then their children indented, recursively */\r\nfunction buildHierarchicalList<T extends { id: string; parentGroupId: string | null }>(\r\n items: T[]\r\n): { item: T; depth: number }[] {\r\n const childrenMap = new Map<string | null, T[]>();\r\n for (const item of items) {\r\n const parentId = item.parentGroupId;\r\n if (!childrenMap.has(parentId)) childrenMap.set(parentId, []);\r\n childrenMap.get(parentId)!.push(item);\r\n }\r\n\r\n const result: { item: T; depth: number }[] = [];\r\n const addChildren = (parentId: string | null, depth: number) => {\r\n const children = childrenMap.get(parentId) || [];\r\n for (const child of children) {\r\n result.push({ item: child, depth });\r\n addChildren(child.id, depth + 1);\r\n }\r\n };\r\n\r\n // Start with root groups (parentGroupId is null or parent not in current filtered list)\r\n const itemIds = new Set(items.map(i => i.id));\r\n const roots = items.filter(i => !i.parentGroupId || !itemIds.has(i.parentGroupId));\r\n for (const root of roots) {\r\n result.push({ item: root, depth: 0 });\r\n addChildren(root.id, 1);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport function UsersGroupsPage(): ReactElement {\r\n const { t } = useTranslation(['admin', 'common']);\r\n const navigate = useNavigate();\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const [loading, setLoading] = useState(true);\r\n const [groups, setGroups] = useState<GroupWithDetails[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [searchQuery, setSearchQuery] = useState('');\r\n const [selectedGroup, setSelectedGroup] = useState<GroupWithDetails | null>(null);\r\n const [showAssignModal, setShowAssignModal] = useState(false);\r\n const [showCreateModal, setShowCreateModal] = useState(false);\r\n const [expandedGroupId, setExpandedGroupId] = useState<string | null>(null);\r\n const [members, setMembers] = useState<Record<string, GroupMemberDto[]>>({});\r\n const [loadingMembers, setLoadingMembers] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('cards');\r\n const [groupTypeFilter, setGroupTypeFilter] = useState<GroupTypeFilter>('all');\r\n const [syncFilter, setSyncFilter] = useState<SyncFilter>('all');\r\n\r\n // Create group form state\r\n const [newGroupName, setNewGroupName] = useState('');\r\n const [newGroupDescription, setNewGroupDescription] = useState('');\r\n const [newGroupIsSecurityGroup, setNewGroupIsSecurityGroup] = useState(true);\r\n const [newGroupParentId, setNewGroupParentId] = useState<string>('');\r\n const [creating, setCreating] = useState(false);\r\n\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n setError(null);\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n setGroups(Array.isArray(groupsData) ? groupsData : []);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n } catch (err: unknown) {\r\n console.error('Failed to load groups:', err);\r\n setGroups([]);\r\n setRoles([]);\r\n const axiosError = err as { response?: { status?: number } };\r\n if (axiosError.response?.status === 401) {\r\n setError(t('common:errors.sessionExpired'));\r\n } else if (axiosError.response?.status === 403) {\r\n setError(t('common:errors.noPermission'));\r\n } else {\r\n setError(t('admin:groups.loadError'));\r\n }\r\n } finally {\r\n setLoading(false);\r\n }\r\n // TENANT ISOLATION: Re-fetch when tenant changes\r\n }, [t, currentTenant?.id, isGlobalView]);\r\n\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const loadMembers = async (groupId: string) => {\r\n if (members[groupId]) {\r\n setExpandedGroupId(expandedGroupId === groupId ? null : groupId);\r\n return;\r\n }\r\n\r\n setLoadingMembers(groupId);\r\n try {\r\n const data = await groupsApi.getMembers(groupId);\r\n setMembers(prev => ({ ...prev, [groupId]: data }));\r\n setExpandedGroupId(groupId);\r\n } catch (err) {\r\n console.error('Failed to load members:', err);\r\n setError(t('admin:groups.loadError'));\r\n } finally {\r\n setLoadingMembers(null);\r\n }\r\n };\r\n\r\n const reloadGroupsAndRoles = useCallback(async () => {\r\n const [groupsData, rolesData] = await Promise.all([\r\n groupsApi.getAll(),\r\n adminApi.roles.getAssignable(),\r\n ]);\r\n const safeGroupsData = Array.isArray(groupsData) ? groupsData : [];\r\n setGroups(safeGroupsData);\r\n setRoles(Array.isArray(rolesData) ? rolesData : []);\r\n return safeGroupsData;\r\n }, []);\r\n\r\n const handleCreateGroup = async () => {\r\n if (!newGroupName.trim()) return;\r\n\r\n setCreating(true);\r\n try {\r\n await groupsApi.create({\r\n name: newGroupName.trim(),\r\n description: newGroupDescription.trim() || undefined,\r\n isSecurityGroup: newGroupIsSecurityGroup,\r\n parentGroupId: newGroupParentId || undefined,\r\n });\r\n await loadData();\r\n setShowCreateModal(false);\r\n setNewGroupName('');\r\n setNewGroupDescription('');\r\n setNewGroupIsSecurityGroup(true);\r\n setNewGroupParentId('');\r\n } catch (err) {\r\n console.error('Failed to create group:', err);\r\n const axiosError = err as { response?: { status?: number; data?: { message?: string } } };\r\n if (axiosError.response?.status === 409) {\r\n setError(axiosError.response.data?.message || t('admin:groups.createError'));\r\n } else {\r\n setError(t('admin:groups.createError'));\r\n }\r\n } finally {\r\n setCreating(false);\r\n }\r\n };\r\n\r\n const handleDeleteGroup = async (groupId: string, groupName: string, isSyncedFromEntra: boolean = false) => {\r\n const confirmMessage = isSyncedFromEntra\r\n ? t('admin:groups.deleteConfirmEntra', { name: groupName, defaultValue: `Le groupe \"${groupName}\" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.\\n\\nÊtes-vous sûr de vouloir le supprimer ?` })\r\n : t('admin:groups.deleteConfirm', { name: groupName });\r\n\r\n if (!confirm(confirmMessage)) return;\r\n\r\n try {\r\n await groupsApi.delete(groupId);\r\n await loadData();\r\n } catch (err) {\r\n console.error('Failed to delete group:', err);\r\n setError(t('admin:groups.deleteError'));\r\n }\r\n };\r\n\r\n const handleAssignRole = async (roleId: string) => {\r\n if (!selectedGroup) return;\r\n try {\r\n await groupsApi.assignRole(selectedGroup.id, { roleId });\r\n const safeGroupsData = await reloadGroupsAndRoles();\r\n const updatedGroup = safeGroupsData.find(g => g.id === selectedGroup.id);\r\n if (updatedGroup) setSelectedGroup(updatedGroup);\r\n } catch (err) {\r\n console.error('Failed to assign role:', err);\r\n setError(t('admin:groups.assignError'));\r\n }\r\n };\r\n\r\n const filteredGroups = groups.filter((g) => {\r\n const matchesSearch =\r\n g.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\r\n g.description?.toLowerCase().includes(searchQuery.toLowerCase());\r\n\r\n const matchesType =\r\n groupTypeFilter === 'all' ||\r\n (groupTypeFilter === 'security' && g.isSecurityGroup) ||\r\n (groupTypeFilter === 'distribution' && !g.isSecurityGroup);\r\n\r\n const matchesSync =\r\n syncFilter === 'all' ||\r\n (syncFilter === 'local' && !g.isSyncedFromEntra) ||\r\n (syncFilter === 'synced' && g.isSyncedFromEntra);\r\n\r\n return matchesSearch && matchesType && matchesSync;\r\n });\r\n\r\n const hierarchicalGroups = buildHierarchicalList(filteredGroups);\r\n\r\n const formatDate = (date: string | null) => {\r\n if (!date) return '-';\r\n return new Intl.DateTimeFormat('fr-FR', {\r\n dateStyle: 'medium',\r\n timeStyle: 'short',\r\n }).format(new Date(date));\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 <Loader2 className=\"w-8 h-8 animate-spin text-[var(--color-accent-500)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n <Breadcrumb\r\n items={[\r\n { label: t('admin:header.title'), href: '/administration' },\r\n { label: t('admin:users.title', 'Users'), href: '/administration/users' },\r\n { label: t('admin:groups.title', 'Groups') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10\">\r\n <Users className=\"w-6 h-6 text-[var(--color-accent-500)]\" />\r\n </div>\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('admin:groups.title')}\r\n </h1>\r\n <p className=\"text-sm text-[var(--text-secondary)]\">\r\n {t('admin:groups.subtitle', { count: groups.length })}\r\n </p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={loadData}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <RefreshCw className=\"w-4 h-4\" />\r\n {t('common:refresh')}\r\n </button>\r\n <button\r\n onClick={() => setShowCreateModal(true)}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.createGroup')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]\">\r\n <div className=\"flex items-center gap-2 text-[var(--error-text)]\">\r\n <AlertTriangle className=\"w-5 h-5\" />\r\n <span>{error}</span>\r\n <button\r\n onClick={() => setError(null)}\r\n className=\"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Search & Filters */}\r\n <div className=\"flex flex-col sm:flex-row gap-4\">\r\n {/* Search */}\r\n <div className=\"relative flex-1\">\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]\" />\r\n <input\r\n type=\"text\"\r\n placeholder={t('admin:groups.searchPlaceholder')}\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n className=\"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n\r\n {/* Type Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Filter className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={groupTypeFilter}\r\n onChange={(e) => setGroupTypeFilter(e.target.value as GroupTypeFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allTypes')}</option>\r\n <option value=\"security\">{t('admin:groups.securityGroup')}</option>\r\n <option value=\"distribution\">{t('admin:groups.distributionGroup')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Sync Filter */}\r\n <div className=\"flex items-center gap-2\">\r\n <Cloud className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <select\r\n value={syncFilter}\r\n onChange={(e) => setSyncFilter(e.target.value as SyncFilter)}\r\n className=\"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"all\">{t('admin:groups.allSyncStatus')}</option>\r\n <option value=\"local\">{t('admin:groups.localOnly')}</option>\r\n <option value=\"synced\">{t('admin:groups.syncedFromEntra')}</option>\r\n </select>\r\n </div>\r\n\r\n {/* View Mode Toggle */}\r\n <div className=\"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setViewMode('cards')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'cards')}`}\r\n title={t('admin:groups.cardView')}\r\n >\r\n <LayoutGrid className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('table')}\r\n className={`p-2 rounded-[var(--radius-button)] transition-colors ${getViewModeButtonClass(viewMode === 'table')}`}\r\n title={t('admin:groups.tableView')}\r\n >\r\n <List className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Groups List */}\r\n {filteredGroups.length === 0 && (\r\n <div className=\"text-center py-12 text-[var(--text-secondary)]\">\r\n {searchQuery || groupTypeFilter !== 'all' || syncFilter !== 'all'\r\n ? t('admin:groups.noResults')\r\n : t('admin:groups.noGroups')}\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode === 'table' && (\r\n /* Table View */\r\n <div className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead className=\"bg-[var(--bg-secondary)]\">\r\n <tr>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.groupName')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.parentGroup')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:type')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.source')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.members')}\r\n </th>\r\n <th className=\"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('admin:groups.assignedRoles')}\r\n </th>\r\n <th className=\"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]\">\r\n {t('common:actionsColumn')}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {hierarchicalGroups.map(({ item: group, depth }) => (\r\n <tr key={group.id} className=\"hover:bg-[var(--bg-hover)] cursor-pointer\" onClick={() => navigate(`/administration/users/groups/${group.id}`)}>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\" style={{ paddingLeft: `${depth * 24}px` }}>\r\n {depth > 0 && (\r\n <CornerDownRight className=\"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0\" />\r\n )}\r\n <div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-4 h-4\" />\r\n ) : (\r\n <Building2 className=\"w-4 h-4\" />\r\n )}\r\n </div>\r\n <div>\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)] hover:underline\">{group.name}</span>\r\n {group.childCount > 0 && (\r\n <span className=\"flex items-center gap-0.5 px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {group.childCount}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate max-w-xs\">\r\n {group.description}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n {group.parentGroupName ? (\r\n <span className=\"text-[var(--text-secondary)]\">{group.parentGroupName}</span>\r\n ) : (\r\n <span className=\"text-[var(--text-tertiary)]\">-</span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <span className={`px-2 py-1 text-xs rounded-[var(--radius-badge)] ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-purple-500/10 text-purple-500'\r\n }`}>\r\n {group.isSecurityGroup ? t('admin:groups.securityGroup') : t('admin:groups.distributionGroup')}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"flex items-center gap-1 text-sm text-blue-500\">\r\n <Cloud className=\"w-4 h-4\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"flex items-center gap-1 text-sm text-[var(--text-tertiary)]\">\r\n <CloudOff className=\"w-4 h-4\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n </td>\r\n <td className=\"px-4 py-3 text-sm text-[var(--text-secondary)]\">\r\n <span className=\"flex items-center gap-1\">\r\n <Users className=\"w-4 h-4\" />\r\n {group.memberCount}\r\n </span>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex flex-wrap gap-1\">\r\n {group.roles.slice(0, 2).map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\"\r\n >\r\n {role}\r\n </span>\r\n ))}\r\n {group.roles.length > 2 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]\">\r\n +{group.roles.length - 2}\r\n </span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 text-right\" onClick={(e) => e.stopPropagation()}>\r\n <div className=\"flex items-center justify-end gap-2\">\r\n <button\r\n onClick={() => {\r\n setSelectedGroup(group);\r\n setShowAssignModal(true);\r\n }}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n title={t('admin:groups.assignRole')}\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={() => handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra)}\r\n className=\"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n title={t('common:delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n {filteredGroups.length > 0 && viewMode !== 'table' && (\r\n /* Cards View */\r\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n {hierarchicalGroups.map(({ item: group }) => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={group.id}\r\n className=\"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left flex flex-col\"\r\n onClick={() => navigate(`/administration/users/groups/${group.id}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/users/groups/${group.id}`); } }}\r\n >\r\n {/* Card Header */}\r\n <div className=\"p-4 flex-1\">\r\n <div className=\"flex items-start justify-between gap-4\">\r\n <div className=\"flex items-start gap-3 min-w-0\">\r\n <div className={`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${\r\n group.isSecurityGroup\r\n ? 'bg-blue-500/10 text-blue-500'\r\n : 'bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]'\r\n }`}>\r\n {group.isSecurityGroup ? (\r\n <Shield className=\"w-5 h-5\" />\r\n ) : (\r\n <Building2 className=\"w-5 h-5\" />\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n <span className=\"font-semibold text-[var(--text-primary)] truncate\">\r\n {group.name}\r\n </span>\r\n {group.isSecurityGroup && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20\">\r\n {t('admin:groups.securityGroup')}\r\n </span>\r\n )}\r\n {!group.isActive && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]\">\r\n {t('common:inactive')}\r\n </span>\r\n )}\r\n {group.isSyncedFromEntra ? (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20 flex items-center gap-1\">\r\n <Cloud className=\"w-3 h-3\" />\r\n Entra\r\n </span>\r\n ) : (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CloudOff className=\"w-3 h-3\" />\r\n {t('admin:groups.local')}\r\n </span>\r\n )}\r\n {group.parentGroupName && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <CornerDownRight className=\"w-3 h-3\" />\r\n {group.parentGroupName}\r\n </span>\r\n )}\r\n {group.childCount > 0 && (\r\n <span className=\"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1\">\r\n <GitBranch className=\"w-3 h-3\" />\r\n {t('admin:groups.childGroupCount', { count: group.childCount })}\r\n </span>\r\n )}\r\n </div>\r\n {group.description && (\r\n <p className=\"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2\">\r\n {group.description}\r\n </p>\r\n )}\r\n <div className=\"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); loadMembers(group.id); }}\r\n className=\"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors\"\r\n >\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.memberCount', { count: group.memberCount })}\r\n {loadingMembers === group.id && (\r\n <Loader2 className=\"w-3 h-3 animate-spin ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId === group.id && (\r\n <ChevronUp className=\"w-3 h-3 ml-1\" />\r\n )}\r\n {loadingMembers !== group.id && expandedGroupId !== group.id && (\r\n <ChevronDown className=\"w-3 h-3 ml-1\" />\r\n )}\r\n </button>\r\n </div>\r\n {group.isSyncedFromEntra && group.lastEntraSyncAt && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.lastSynced', { date: formatDate(group.lastEntraSyncAt) })}\r\n </p>\r\n )}\r\n {!group.isSyncedFromEntra && (\r\n <p className=\"text-xs text-[var(--text-tertiary)] mt-1\">\r\n {t('admin:groups.createdAt', { date: formatDate(group.createdAt) })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n <div className=\"flex flex-col gap-2 flex-shrink-0\" onClick={(e) => e.stopPropagation()}>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); setSelectedGroup(group); setShowAssignModal(true); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors\"\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('admin:groups.assignRole')}\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); handleDeleteGroup(group.id, group.name, group.isSyncedFromEntra); }}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--error-border)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors\"\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n {t('common:delete')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Assigned Roles */}\r\n {group.roles.length > 0 && (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-2\">\r\n {t('admin:groups.assignedRoles')}\r\n </h4>\r\n <div className=\"flex flex-wrap gap-2\">\r\n {group.roles.map((role, index) => (\r\n <span\r\n key={`${group.id}-role-${index}`}\r\n className=\"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)]\"\r\n >\r\n <Shield className=\"w-4 h-4 text-[var(--color-accent-500)]\" />\r\n <span className=\"text-sm text-[var(--text-primary)]\">{role}</span>\r\n </span>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Members Panel */}\r\n {expandedGroupId === group.id && members[group.id] && (\r\n <div className=\"border-t border-[var(--border-color)] bg-[var(--bg-primary)]\">\r\n <div className=\"p-4\">\r\n <h4 className=\"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2\">\r\n <Users className=\"w-4 h-4\" />\r\n {t('admin:groups.members')} ({members[group.id].length})\r\n </h4>\r\n {members[group.id].length === 0 ? (\r\n <p className=\"text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.noMembers')}\r\n </p>\r\n ) : (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto\">\r\n {members[group.id].slice(0, 10).map((member) => (\r\n <Link\r\n key={member.userId}\r\n to={`/administration/users/${member.userId}`}\r\n className=\"flex items-center gap-3 p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n <div className=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]\">\r\n {member.fullName.charAt(0).toUpperCase()}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <p className=\"text-sm font-medium text-[var(--text-primary)] truncate\">\r\n {member.fullName}\r\n </p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">\r\n {member.email}\r\n </p>\r\n </div>\r\n </Link>\r\n ))}\r\n </div>\r\n )}\r\n {members[group.id].length > 10 && (\r\n <p className=\"mt-3 text-center text-sm text-[var(--text-tertiary)]\">\r\n {t('admin:groups.showingMembers', {\r\n shown: 10,\r\n total: members[group.id].length,\r\n })}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Create Group Modal */}\r\n {showCreateModal && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.createGroup')}\r\n </h2>\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4 space-y-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.groupName')} *\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={newGroupName}\r\n onChange={(e) => setNewGroupName(e.target.value)}\r\n placeholder={t('admin:groups.groupNamePlaceholder')}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('common:description')}\r\n </label>\r\n <textarea\r\n value={newGroupDescription}\r\n onChange={(e) => setNewGroupDescription(e.target.value)}\r\n placeholder={t('admin:groups.descriptionPlaceholder')}\r\n rows={3}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none\"\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setNewGroupIsSecurityGroup(!newGroupIsSecurityGroup)}\r\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\r\n newGroupIsSecurityGroup\r\n ? 'bg-[var(--color-accent-500)]'\r\n : 'bg-[var(--bg-tertiary)]'\r\n }`}\r\n >\r\n <span\r\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\r\n newGroupIsSecurityGroup ? 'translate-x-6' : 'translate-x-1'\r\n }`}\r\n />\r\n </button>\r\n <span className=\"text-sm text-[var(--text-primary)]\">\r\n {t('admin:groups.isSecurityGroup')}\r\n </span>\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-primary)] mb-1\">\r\n {t('admin:groups.parentGroup')}\r\n </label>\r\n <select\r\n value={newGroupParentId}\r\n onChange={(e) => setNewGroupParentId(e.target.value)}\r\n className=\"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]\"\r\n >\r\n <option value=\"\">{t('admin:groups.noParent')}</option>\r\n {groups.filter(g => g.isActive).map(g => (\r\n <option key={g.id} value={g.id}>{g.name}</option>\r\n ))}\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-end gap-3 p-4 border-t border-[var(--border-color)]\">\r\n <button\r\n onClick={() => setShowCreateModal(false)}\r\n className=\"px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors\"\r\n >\r\n {t('common:cancel')}\r\n </button>\r\n <button\r\n onClick={handleCreateGroup}\r\n disabled={!newGroupName.trim() || creating}\r\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\r\n >\r\n {creating ? (\r\n <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n ) : (\r\n <Check className=\"w-4 h-4\" />\r\n )}\r\n {t('common:create')}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Assign Role Modal */}\r\n {showAssignModal && selectedGroup && (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\">\r\n <div className=\"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl\">\r\n <div className=\"flex items-center justify-between p-4 border-b border-[var(--border-color)]\">\r\n <h2 className=\"text-lg font-semibold text-[var(--text-primary)]\">\r\n {t('admin:groups.assignRoleTitle')}\r\n </h2>\r\n <button\r\n onClick={() => {\r\n setShowAssignModal(false);\r\n setSelectedGroup(null);\r\n }}\r\n className=\"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]\"\r\n >\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n <div className=\"p-4\">\r\n <p className=\"text-sm text-[var(--text-secondary)] mb-4\">\r\n {t('admin:groups.assignRoleDescription', { group: selectedGroup.name })}\r\n </p>\r\n <div className=\"space-y-2 max-h-64 overflow-y-auto\">\r\n {roles\r\n .filter((role) => !selectedGroup.roles.includes(role.name))\r\n .map((role) => (\r\n <button\r\n key={role.id}\r\n onClick={() => handleAssignRole(role.id)}\r\n className=\"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left\"\r\n >\r\n <Shield className=\"w-5 h-5 text-[var(--color-accent-500)]\" />\r\n <div>\r\n <p className=\"font-medium text-[var(--text-primary)]\">{role.name}</p>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n </button>\r\n ))}\r\n {roles.filter((role) => !selectedGroup.roles.includes(role.name)).length === 0 && (\r\n <p className=\"text-sm text-[var(--text-tertiary)] text-center py-4\">\r\n {t('admin:groups.allRolesAssigned')}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["getViewModeButtonClass","isActive","buildHierarchicalList","items","childrenMap","item","parentId","result","addChildren","depth","children","child","itemIds","roots","root","UsersGroupsPage","useTranslation","navigate","useNavigate","currentTenant","isGlobalView","useTenant","loading","setLoading","useState","groups","setGroups","roles","setRoles","error","setError","searchQuery","setSearchQuery","selectedGroup","setSelectedGroup","showAssignModal","setShowAssignModal","showCreateModal","setShowCreateModal","expandedGroupId","setExpandedGroupId","members","setMembers","loadingMembers","setLoadingMembers","viewMode","setViewMode","groupTypeFilter","setGroupTypeFilter","syncFilter","setSyncFilter","newGroupName","setNewGroupName","newGroupDescription","setNewGroupDescription","newGroupIsSecurityGroup","setNewGroupIsSecurityGroup","newGroupParentId","setNewGroupParentId","creating","setCreating","loadData","useCallback","groupsData","rolesData","groupsApi","adminApi","err","axiosError","useEffect","loadMembers","groupId","data","prev","reloadGroupsAndRoles","safeGroupsData","handleCreateGroup","handleDeleteGroup","groupName","isSyncedFromEntra","confirmMessage","handleAssignRole","roleId","updatedGroup","g","filteredGroups","matchesSearch","matchesType","matchesSync","hierarchicalGroups","formatDate","date","jsx","Loader2","jsxs","Breadcrumb","Users","RefreshCw","Plus","AlertTriangle","X","Search","Filter","Cloud","LayoutGrid","List","group","CornerDownRight","Shield","Building2","GitBranch","CloudOff","role","index","e","Trash2","ChevronUp","ChevronDown","member","Link","Check"],"mappings":";;;;;;;AA6CA,MAAMA,KAAyB,CAACC,MAC1BA,IACK,4CAEF;AAIT,SAASC,GACPC,GAC8B;AAC9B,QAAMC,wBAAkB,IAAA;AACxB,aAAWC,KAAQF,GAAO;AACxB,UAAMG,IAAWD,EAAK;AACtB,IAAKD,EAAY,IAAIE,CAAQ,KAAGF,EAAY,IAAIE,GAAU,EAAE,GAC5DF,EAAY,IAAIE,CAAQ,EAAG,KAAKD,CAAI;AAAA,EACtC;AAEA,QAAME,IAAuC,CAAA,GACvCC,IAAc,CAACF,GAAyBG,MAAkB;AAC9D,UAAMC,IAAWN,EAAY,IAAIE,CAAQ,KAAK,CAAA;AAC9C,eAAWK,KAASD;AAClB,MAAAH,EAAO,KAAK,EAAE,MAAMI,GAAO,OAAAF,GAAO,GAClCD,EAAYG,EAAM,IAAIF,IAAQ,CAAC;AAAA,EAEnC,GAGMG,IAAU,IAAI,IAAIT,EAAM,IAAI,CAAA,MAAK,EAAE,EAAE,CAAC,GACtCU,IAAQV,EAAM,OAAO,CAAA,MAAK,CAAC,EAAE,iBAAiB,CAACS,EAAQ,IAAI,EAAE,aAAa,CAAC;AACjF,aAAWE,KAAQD;AACjB,IAAAN,EAAO,KAAK,EAAE,MAAMO,GAAM,OAAO,GAAG,GACpCN,EAAYM,EAAK,IAAI,CAAC;AAGxB,SAAOP;AACT;AAEO,SAASQ,KAAgC;AAC9C,QAAM,EAAE,EAAA,IAAMC,GAAe,CAAC,SAAS,QAAQ,CAAC,GAC1CC,IAAWC,GAAA,GACX,EAAE,eAAAC,GAAe,cAAAC,EAAA,IAAiBC,GAAA,GAClC,CAACC,GAASC,CAAU,IAAIC,EAAS,EAAI,GACrC,CAACC,GAAQC,CAAS,IAAIF,EAA6B,CAAA,CAAE,GACrD,CAACG,GAAOC,CAAQ,IAAIJ,EAAwB,CAAA,CAAE,GAC9C,CAACK,GAAOC,CAAQ,IAAIN,EAAwB,IAAI,GAChD,CAACO,GAAaC,EAAc,IAAIR,EAAS,EAAE,GAC3C,CAACS,GAAeC,CAAgB,IAAIV,EAAkC,IAAI,GAC1E,CAACW,IAAiBC,CAAkB,IAAIZ,EAAS,EAAK,GACtD,CAACa,IAAiBC,CAAkB,IAAId,EAAS,EAAK,GACtD,CAACe,GAAiBC,CAAkB,IAAIhB,EAAwB,IAAI,GACpE,CAACiB,GAASC,EAAU,IAAIlB,EAA2C,CAAA,CAAE,GACrE,CAACmB,GAAgBC,CAAiB,IAAIpB,EAAwB,IAAI,GAClE,CAACqB,GAAUC,CAAW,IAAItB,EAAmB,OAAO,GACpD,CAACuB,GAAiBC,EAAkB,IAAIxB,EAA0B,KAAK,GACvE,CAACyB,GAAYC,EAAa,IAAI1B,EAAqB,KAAK,GAGxD,CAAC2B,GAAcC,CAAe,IAAI5B,EAAS,EAAE,GAC7C,CAAC6B,GAAqBC,CAAsB,IAAI9B,EAAS,EAAE,GAC3D,CAAC+B,GAAyBC,CAA0B,IAAIhC,EAAS,EAAI,GACrE,CAACiC,GAAkBC,CAAmB,IAAIlC,EAAiB,EAAE,GAC7D,CAACmC,GAAUC,CAAW,IAAIpC,EAAS,EAAK,GAExCqC,IAAWC,GAAY,YAAY;AACvC,QAAI;AACF,MAAAvC,EAAW,EAAI,GACfO,EAAS,IAAI;AACb,YAAM,CAACiC,GAAYC,CAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,QAChDC,EAAU,OAAA;AAAA,QACVC,GAAS,MAAM,cAAA;AAAA,MAAc,CAC9B;AACD,MAAAxC,EAAU,MAAM,QAAQqC,CAAU,IAAIA,IAAa,CAAA,CAAE,GACrDnC,EAAS,MAAM,QAAQoC,CAAS,IAAIA,IAAY,CAAA,CAAE;AAAA,IACpD,SAASG,GAAc;AACrB,cAAQ,MAAM,0BAA0BA,CAAG,GAC3CzC,EAAU,CAAA,CAAE,GACZE,EAAS,CAAA,CAAE;AACX,YAAMwC,IAAaD;AACnB,MAAIC,EAAW,UAAU,WAAW,MAClCtC,EAAS,EAAE,8BAA8B,CAAC,IACjCsC,EAAW,UAAU,WAAW,MACzCtC,EAAS,EAAE,4BAA4B,CAAC,IAExCA,EAAS,EAAE,wBAAwB,CAAC;AAAA,IAExC,UAAA;AACE,MAAAP,EAAW,EAAK;AAAA,IAClB;AAAA,EAEF,GAAG,CAAC,GAAGJ,GAAe,IAAIC,CAAY,CAAC;AAEvC,EAAAiD,GAAU,MAAM;AACd,IAAAR,EAAA;AAAA,EACF,GAAG,CAACA,CAAQ,CAAC;AAEb,QAAMS,KAAc,OAAOC,MAAoB;AAC7C,QAAI9B,EAAQ8B,CAAO,GAAG;AACpB,MAAA/B,EAAmBD,MAAoBgC,IAAU,OAAOA,CAAO;AAC/D;AAAA,IACF;AAEA,IAAA3B,EAAkB2B,CAAO;AACzB,QAAI;AACF,YAAMC,IAAO,MAAMP,EAAU,WAAWM,CAAO;AAC/C,MAAA7B,GAAW,CAAA+B,OAAS,EAAE,GAAGA,GAAM,CAACF,CAAO,GAAGC,IAAO,GACjDhC,EAAmB+B,CAAO;AAAA,IAC5B,SAASJ,GAAK;AACZ,cAAQ,MAAM,2BAA2BA,CAAG,GAC5CrC,EAAS,EAAE,wBAAwB,CAAC;AAAA,IACtC,UAAA;AACE,MAAAc,EAAkB,IAAI;AAAA,IACxB;AAAA,EACF,GAEM8B,KAAuBZ,GAAY,YAAY;AACnD,UAAM,CAACC,GAAYC,CAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,MAChDC,EAAU,OAAA;AAAA,MACVC,GAAS,MAAM,cAAA;AAAA,IAAc,CAC9B,GACKS,IAAiB,MAAM,QAAQZ,CAAU,IAAIA,IAAa,CAAA;AAChE,WAAArC,EAAUiD,CAAc,GACxB/C,EAAS,MAAM,QAAQoC,CAAS,IAAIA,IAAY,CAAA,CAAE,GAC3CW;AAAA,EACT,GAAG,CAAA,CAAE,GAECC,KAAoB,YAAY;AACpC,QAAKzB,EAAa,QAElB;AAAA,MAAAS,EAAY,EAAI;AAChB,UAAI;AACF,cAAMK,EAAU,OAAO;AAAA,UACrB,MAAMd,EAAa,KAAA;AAAA,UACnB,aAAaE,EAAoB,KAAA,KAAU;AAAA,UAC3C,iBAAiBE;AAAA,UACjB,eAAeE,KAAoB;AAAA,QAAA,CACpC,GACD,MAAMI,EAAA,GACNvB,EAAmB,EAAK,GACxBc,EAAgB,EAAE,GAClBE,EAAuB,EAAE,GACzBE,EAA2B,EAAI,GAC/BE,EAAoB,EAAE;AAAA,MACxB,SAASS,GAAK;AACZ,gBAAQ,MAAM,2BAA2BA,CAAG;AAC5C,cAAMC,IAAaD;AACnB,QAAIC,EAAW,UAAU,WAAW,MAClCtC,EAASsC,EAAW,SAAS,MAAM,WAAW,EAAE,0BAA0B,CAAC,IAE3EtC,EAAS,EAAE,0BAA0B,CAAC;AAAA,MAE1C,UAAA;AACE,QAAA8B,EAAY,EAAK;AAAA,MACnB;AAAA;AAAA,EACF,GAEMiB,IAAoB,OAAON,GAAiBO,GAAmBC,IAA6B,OAAU;AAC1G,UAAMC,IAAiBD,IACnB,EAAE,mCAAmC,EAAE,MAAMD,GAAW,cAAc,cAAcA,CAAS;AAAA;AAAA,yCAAA,CAAsI,IACnO,EAAE,8BAA8B,EAAE,MAAMA,GAAW;AAEvD,QAAK,QAAQE,CAAc;AAE3B,UAAI;AACF,cAAMf,EAAU,OAAOM,CAAO,GAC9B,MAAMV,EAAA;AAAA,MACR,SAASM,IAAK;AACZ,gBAAQ,MAAM,2BAA2BA,EAAG,GAC5CrC,EAAS,EAAE,0BAA0B,CAAC;AAAA,MACxC;AAAA,EACF,GAEMmD,KAAmB,OAAOC,MAAmB;AACjD,QAAKjD;AACL,UAAI;AACF,cAAMgC,EAAU,WAAWhC,EAAc,IAAI,EAAE,QAAAiD,GAAQ;AAEvD,cAAMC,KADiB,MAAMT,GAAA,GACO,KAAK,OAAKU,EAAE,OAAOnD,EAAc,EAAE;AACvE,QAAIkD,OAA+BA,CAAY;AAAA,MACjD,SAAShB,GAAK;AACZ,gBAAQ,MAAM,0BAA0BA,CAAG,GAC3CrC,EAAS,EAAE,0BAA0B,CAAC;AAAA,MACxC;AAAA,EACF,GAEMuD,IAAiB5D,EAAO,OAAO,CAAC2D,MAAM;AAC1C,UAAME,IACJF,EAAE,KAAK,YAAA,EAAc,SAASrD,EAAY,YAAA,CAAa,KACvDqD,EAAE,aAAa,YAAA,EAAc,SAASrD,EAAY,aAAa,GAE3DwD,IACJxC,MAAoB,SACnBA,MAAoB,cAAcqC,EAAE,mBACpCrC,MAAoB,kBAAkB,CAACqC,EAAE,iBAEtCI,IACJvC,MAAe,SACdA,MAAe,WAAW,CAACmC,EAAE,qBAC7BnC,MAAe,YAAYmC,EAAE;AAEhC,WAAOE,KAAiBC,KAAeC;AAAA,EACzC,CAAC,GAEKC,IAAqBvF,GAAsBmF,CAAc,GAEzDK,KAAa,CAACC,MACbA,IACE,IAAI,KAAK,eAAe,SAAS;AAAA,IACtC,WAAW;AAAA,IACX,WAAW;AAAA,EAAA,CACZ,EAAE,OAAO,IAAI,KAAKA,CAAI,CAAC,IAJN;AAOpB,SAAIrE,IAEA,gBAAAsE,EAAC,SAAI,WAAU,kDACb,4BAACC,GAAA,EAAQ,WAAU,uDAAsD,EAAA,CAC3E,IAKF,gBAAAC,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,gBAAAF;AAAA,MAACG;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,EAAE,OAAO,EAAE,oBAAoB,GAAG,MAAM,kBAAA;AAAA,UACxC,EAAE,OAAO,EAAE,qBAAqB,OAAO,GAAG,MAAM,wBAAA;AAAA,UAChD,EAAE,OAAO,EAAE,sBAAsB,QAAQ,EAAA;AAAA,QAAE;AAAA,MAC7C;AAAA,IAAA;AAAA,IAIF,gBAAAD,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAF,EAAC,SAAI,WAAU,sEACb,4BAACI,GAAA,EAAM,WAAU,0CAAyC,EAAA,CAC5D;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAJ,EAAC,MAAA,EAAG,WAAU,iDACX,UAAA,EAAE,oBAAoB,GACzB;AAAA,UACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,wCACV,UAAA,EAAE,yBAAyB,EAAE,OAAOnE,EAAO,OAAA,CAAQ,EAAA,CACtD;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MACA,gBAAAqE,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASjC;AAAA,YACT,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAA+B,EAACK,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,cAC9B,EAAE,gBAAgB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAErB,gBAAAH;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAMxD,EAAmB,EAAI;AAAA,YACtC,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAsD,EAACM,GAAA,EAAK,WAAU,UAAA,CAAU;AAAA,cACzB,EAAE,0BAA0B;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAC/B,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGCrE,uBACE,OAAA,EAAI,WAAU,6FACb,UAAA,gBAAAiE,EAAC,OAAA,EAAI,WAAU,oDACb,UAAA;AAAA,MAAA,gBAAAF,EAACO,IAAA,EAAc,WAAU,UAAA,CAAU;AAAA,MACnC,gBAAAP,EAAC,UAAM,UAAA/D,EAAA,CAAM;AAAA,MACb,gBAAA+D;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,MAAM9D,EAAS,IAAI;AAAA,UAC5B,WAAU;AAAA,UAEV,UAAA,gBAAA8D,EAACQ,GAAA,EAAE,WAAU,UAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACzB,EAAA,CACF,EAAA,CACF;AAAA,IAIF,gBAAAN,EAAC,OAAA,EAAI,WAAU,mCAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,QAAA,gBAAAF,EAACS,IAAA,EAAO,WAAU,+EAAA,CAA+E;AAAA,QACjG,gBAAAT;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,aAAa,EAAE,gCAAgC;AAAA,YAC/C,OAAO7D;AAAA,YACP,UAAU,CAAC,MAAMC,GAAe,EAAE,OAAO,KAAK;AAAA,YAC9C,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,GACF;AAAA,MAGA,gBAAA8D,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAF,EAACU,IAAA,EAAO,WAAU,sCAAA,CAAsC;AAAA,QACxD,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO/C;AAAA,YACP,UAAU,CAAC,MAAMC,GAAmB,EAAE,OAAO,KAAwB;AAAA,YACrE,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAA4C,EAAC,UAAA,EAAO,OAAM,OAAO,UAAA,EAAE,uBAAuB,GAAE;AAAA,gCAC/C,UAAA,EAAO,OAAM,YAAY,UAAA,EAAE,4BAA4B,GAAE;AAAA,gCACzD,UAAA,EAAO,OAAM,gBAAgB,UAAA,EAAE,gCAAgC,EAAA,CAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACpE,GACF;AAAA,MAGA,gBAAAE,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAF,EAACW,GAAA,EAAM,WAAU,sCAAA,CAAsC;AAAA,QACvD,gBAAAT;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO7C;AAAA,YACP,UAAU,CAAC,MAAMC,GAAc,EAAE,OAAO,KAAmB;AAAA,YAC3D,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAA0C,EAAC,UAAA,EAAO,OAAM,OAAO,UAAA,EAAE,4BAA4B,GAAE;AAAA,gCACpD,UAAA,EAAO,OAAM,SAAS,UAAA,EAAE,wBAAwB,GAAE;AAAA,gCAClD,UAAA,EAAO,OAAM,UAAU,UAAA,EAAE,8BAA8B,EAAA,CAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAC5D,GACF;AAAA,MAGA,gBAAAE,EAAC,OAAA,EAAI,WAAU,2HACb,UAAA;AAAA,QAAA,gBAAAF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM9C,EAAY,OAAO;AAAA,YAClC,WAAW,wDAAwD9C,GAAuB6C,MAAa,OAAO,CAAC;AAAA,YAC/G,OAAO,EAAE,uBAAuB;AAAA,YAEhC,UAAA,gBAAA+C,EAACY,IAAA,EAAW,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAElC,gBAAAZ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM9C,EAAY,OAAO;AAAA,YAClC,WAAW,wDAAwD9C,GAAuB6C,MAAa,OAAO,CAAC;AAAA,YAC/G,OAAO,EAAE,wBAAwB;AAAA,YAEjC,UAAA,gBAAA+C,EAACa,IAAA,EAAK,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAC5B,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGCpB,EAAe,WAAW,KACzB,gBAAAO,EAAC,OAAA,EAAI,WAAU,kDACZ,UACG,EADH7D,KAAegB,MAAoB,SAASE,MAAe,QACtD,2BACA,uBADwB,GAEhC;AAAA,IAEDoC,EAAe,SAAS,KAAKxC,MAAa;AAAA,sBAExC,OAAA,EAAI,WAAU,oFACb,UAAA,gBAAAiD,EAAC,SAAA,EAAM,WAAU,UACf,UAAA;AAAA,MAAA,gBAAAF,EAAC,SAAA,EAAM,WAAU,4BACf,UAAA,gBAAAE,EAAC,MAAA,EACC,UAAA;AAAA,QAAA,gBAAAF,EAAC,MAAA,EAAG,WAAU,wEACX,UAAA,EAAE,wBAAwB,GAC7B;AAAA,0BACC,MAAA,EAAG,WAAU,wEACX,UAAA,EAAE,0BAA0B,GAC/B;AAAA,0BACC,MAAA,EAAG,WAAU,wEACX,UAAA,EAAE,aAAa,GAClB;AAAA,0BACC,MAAA,EAAG,WAAU,wEACX,UAAA,EAAE,qBAAqB,GAC1B;AAAA,0BACC,MAAA,EAAG,WAAU,wEACX,UAAA,EAAE,sBAAsB,GAC3B;AAAA,0BACC,MAAA,EAAG,WAAU,wEACX,UAAA,EAAE,4BAA4B,GACjC;AAAA,0BACC,MAAA,EAAG,WAAU,yEACX,UAAA,EAAE,sBAAsB,EAAA,CAC3B;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,MACA,gBAAAA,EAAC,WAAM,WAAU,yCACd,YAAmB,IAAI,CAAC,EAAE,MAAMc,GAAO,OAAAjG,EAAA,MACtC,gBAAAqF,EAAC,MAAA,EAAkB,WAAU,6CAA4C,SAAS,MAAM7E,EAAS,gCAAgCyF,EAAM,EAAE,EAAE,GACzI,UAAA;AAAA,QAAA,gBAAAd,EAAC,MAAA,EAAG,WAAU,aACZ,UAAA,gBAAAE,EAAC,SAAI,WAAU,2BAA0B,OAAO,EAAE,aAAa,GAAGrF,IAAQ,EAAE,QACzE,UAAA;AAAA,UAAAA,IAAQ,KACP,gBAAAmF,EAACe,IAAA,EAAgB,WAAU,qDAAoD;AAAA,UAEjF,gBAAAf,EAAC,SAAI,WAAW,uEACdc,EAAM,kBACF,iCACA,gEACN,IACG,UAAAA,EAAM,kBACL,gBAAAd,EAACgB,GAAA,EAAO,WAAU,UAAA,CAAU,sBAE3BC,IAAA,EAAU,WAAU,WAAU,EAAA,CAEnC;AAAA,4BACC,OAAA,EACC,UAAA;AAAA,YAAA,gBAAAf,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,gBAAAF,EAAC,QAAA,EAAK,WAAU,+FAA+F,UAAAc,EAAM,MAAK;AAAA,cACzHA,EAAM,aAAa,KAClB,gBAAAZ,EAAC,QAAA,EAAK,WAAU,qIACd,UAAA;AAAA,gBAAA,gBAAAF,EAACkB,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,gBAC9BJ,EAAM;AAAA,cAAA,EAAA,CACT;AAAA,YAAA,GAEJ;AAAA,YACCA,EAAM,eACL,gBAAAd,EAAC,OAAE,WAAU,yDACV,YAAM,YAAA,CACT;AAAA,UAAA,EAAA,CAEJ;AAAA,QAAA,EAAA,CACF,EAAA,CACF;AAAA,0BACC,MAAA,EAAG,WAAU,kDACX,UAAAc,EAAM,oCACJ,QAAA,EAAK,WAAU,gCAAgC,UAAAA,EAAM,iBAAgB,IAEtE,gBAAAd,EAAC,UAAK,WAAU,+BAA8B,eAAC,EAAA,CAEnD;AAAA,QACA,gBAAAA,EAAC,QAAG,WAAU,aACZ,4BAAC,QAAA,EAAK,WAAW,mDACfc,EAAM,kBACF,iCACA,kCACN,IACG,YAAM,kBAAkB,EAAE,4BAA4B,IAAI,EAAE,gCAAgC,EAAA,CAC/F,EAAA,CACF;AAAA,QACA,gBAAAd,EAAC,QAAG,WAAU,aACX,YAAM,oBACL,gBAAAE,EAAC,QAAA,EAAK,WAAU,iDACd,UAAA;AAAA,UAAA,gBAAAF,EAACW,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,UAAE;AAAA,QAAA,EAAA,CAE/B,IAEA,gBAAAT,EAAC,QAAA,EAAK,WAAU,+DACd,UAAA;AAAA,UAAA,gBAAAF,EAACmB,IAAA,EAAS,WAAU,UAAA,CAAU;AAAA,UAC7B,EAAE,oBAAoB;AAAA,QAAA,EAAA,CACzB,EAAA,CAEJ;AAAA,0BACC,MAAA,EAAG,WAAU,kDACZ,UAAA,gBAAAjB,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAF,EAACI,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,UAC1BU,EAAM;AAAA,QAAA,EAAA,CACT,EAAA,CACF;AAAA,0BACC,MAAA,EAAG,WAAU,aACZ,UAAA,gBAAAZ,EAAC,OAAA,EAAI,WAAU,wBACZ,UAAA;AAAA,UAAAY,EAAM,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,CAACM,GAAMC,MAClC,gBAAArB;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,WAAU;AAAA,cAET,UAAAoB;AAAA,YAAA;AAAA,YAHI,GAAGN,EAAM,EAAE,SAASO,CAAK;AAAA,UAAA,CAKjC;AAAA,UACAP,EAAM,MAAM,SAAS,KACpB,gBAAAZ,EAAC,QAAA,EAAK,WAAU,yGAAwG,UAAA;AAAA,YAAA;AAAA,YACpHY,EAAM,MAAM,SAAS;AAAA,UAAA,EAAA,CACzB;AAAA,QAAA,EAAA,CAEJ,EAAA,CACF;AAAA,QACA,gBAAAd,EAAC,MAAA,EAAG,WAAU,wBAAuB,SAAS,CAACsB,MAAMA,EAAE,gBAAA,GACrD,UAAA,gBAAApB,EAAC,OAAA,EAAI,WAAU,uCACb,UAAA;AAAA,UAAA,gBAAAF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAM;AACb,gBAAA1D,EAAiBwE,CAAK,GACtBtE,EAAmB,EAAI;AAAA,cACzB;AAAA,cACA,WAAU;AAAA,cACV,OAAO,EAAE,yBAAyB;AAAA,cAElC,UAAA,gBAAAwD,EAACM,GAAA,EAAK,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAE5B,gBAAAN;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAMf,EAAkB6B,EAAM,IAAIA,EAAM,MAAMA,EAAM,iBAAiB;AAAA,cAC9E,WAAU;AAAA,cACV,OAAO,EAAE,eAAe;AAAA,cAExB,UAAA,gBAAAd,EAACuB,IAAA,EAAO,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QAC9B,EAAA,CACF,EAAA,CACF;AAAA,MAAA,KA3GOT,EAAM,EA4Gf,CACD,EAAA,CACH;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,IAEDrB,EAAe,SAAS,KAAKxC,MAAa;AAAA,IAEzC,gBAAA+C,EAAC,OAAA,EAAI,WAAU,yCACZ,UAAAH,EAAmB,IAAI,CAAC,EAAE,MAAMiB,EAAA,MAC/B,gBAAAZ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAU;AAAA,QAEV,WAAU;AAAA,QACV,SAAS,MAAM7E,EAAS,gCAAgCyF,EAAM,EAAE,EAAE;AAAA,QAClE,WAAW,CAACQ,MAAM;AAAE,WAAIA,EAAE,QAAQ,WAAWA,EAAE,QAAQ,SAAOA,EAAE,eAAA,GAAkBjG,EAAS,gCAAgCyF,EAAM,EAAE,EAAE;AAAA,QAAK;AAAA,QAG1I,UAAA;AAAA,UAAA,gBAAAZ,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,cAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,gBAAA,gBAAAF,EAAC,SAAI,WAAW,sDACdc,EAAM,kBACF,iCACA,gEACN,IACG,UAAAA,EAAM,kBACL,gBAAAd,EAACgB,GAAA,EAAO,WAAU,UAAA,CAAU,sBAE3BC,IAAA,EAAU,WAAU,WAAU,EAAA,CAEnC;AAAA,gBACA,gBAAAf,EAAC,OAAA,EAAI,WAAU,WACb,UAAA;AAAA,kBAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,oBAAA,gBAAAF,EAAC,QAAA,EAAK,WAAU,qDACb,UAAAc,EAAM,MACT;AAAA,oBACCA,EAAM,mBACL,gBAAAd,EAAC,QAAA,EAAK,WAAU,4GACb,UAAA,EAAE,4BAA4B,GACjC;AAAA,oBAED,CAACc,EAAM,YACN,gBAAAd,EAAC,UAAK,WAAU,6IACb,UAAA,EAAE,iBAAiB,EAAA,CACtB;AAAA,oBAEDc,EAAM,oBACL,gBAAAZ,EAAC,QAAA,EAAK,WAAU,oIACd,UAAA;AAAA,sBAAA,gBAAAF,EAACW,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,sBAAE;AAAA,oBAAA,EAAA,CAE/B,IAEA,gBAAAT,EAAC,QAAA,EAAK,WAAU,qKACd,UAAA;AAAA,sBAAA,gBAAAF,EAACmB,IAAA,EAAS,WAAU,UAAA,CAAU;AAAA,sBAC7B,EAAE,oBAAoB;AAAA,oBAAA,GACzB;AAAA,oBAEDL,EAAM,mBACL,gBAAAZ,EAAC,QAAA,EAAK,WAAU,qKACd,UAAA;AAAA,sBAAA,gBAAAF,EAACe,IAAA,EAAgB,WAAU,UAAA,CAAU;AAAA,sBACpCD,EAAM;AAAA,oBAAA,GACT;AAAA,oBAEDA,EAAM,aAAa,KAClB,gBAAAZ,EAAC,QAAA,EAAK,WAAU,qKACd,UAAA;AAAA,sBAAA,gBAAAF,EAACkB,IAAA,EAAU,WAAU,UAAA,CAAU;AAAA,sBAC9B,EAAE,gCAAgC,EAAE,OAAOJ,EAAM,YAAY;AAAA,oBAAA,EAAA,CAChE;AAAA,kBAAA,GAEJ;AAAA,kBACCA,EAAM,eACL,gBAAAd,EAAC,OAAE,WAAU,0DACV,YAAM,aACT;AAAA,kBAEF,gBAAAA,EAAC,SAAI,WAAU,8EAA6E,SAAS,CAACsB,MAAMA,EAAE,gBAAA,GAC5G,UAAA,gBAAApB;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,SAAS,CAACoB,MAAM;AAAE,wBAAAA,EAAE,gBAAA,GAAmB5C,GAAYoC,EAAM,EAAE;AAAA,sBAAG;AAAA,sBAC9D,WAAU;AAAA,sBAEV,UAAA;AAAA,wBAAA,gBAAAd,EAACI,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,wBAC1B,EAAE,4BAA4B,EAAE,OAAOU,EAAM,aAAa;AAAA,wBAC1D/D,MAAmB+D,EAAM,MACxB,gBAAAd,EAACC,GAAA,EAAQ,WAAU,6BAA4B;AAAA,wBAEhDlD,MAAmB+D,EAAM,MAAMnE,MAAoBmE,EAAM,MACxD,gBAAAd,EAACwB,IAAA,EAAU,WAAU,eAAA,CAAe;AAAA,wBAErCzE,MAAmB+D,EAAM,MAAMnE,MAAoBmE,EAAM,MACxD,gBAAAd,EAACyB,IAAA,EAAY,WAAU,eAAA,CAAe;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAAA,GAG5C;AAAA,kBACCX,EAAM,qBAAqBA,EAAM,mBAChC,gBAAAd,EAAC,OAAE,WAAU,4CACV,UAAA,EAAE,2BAA2B,EAAE,MAAMF,GAAWgB,EAAM,eAAe,EAAA,CAAG,GAC3E;AAAA,kBAED,CAACA,EAAM,qBACN,gBAAAd,EAAC,KAAA,EAAE,WAAU,4CACV,UAAA,EAAE,0BAA0B,EAAE,MAAMF,GAAWgB,EAAM,SAAS,EAAA,CAAG,EAAA,CACpE;AAAA,gBAAA,EAAA,CAEJ;AAAA,cAAA,GACF;AAAA,cACA,gBAAAZ,EAAC,SAAI,WAAU,qCAAoC,SAAS,CAACoB,MAAMA,EAAE,gBAAA,GACnE,UAAA;AAAA,gBAAA,gBAAApB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAS,CAACoB,MAAM;AAAE,sBAAAA,EAAE,gBAAA,GAAmBhF,EAAiBwE,CAAK,GAAGtE,EAAmB,EAAI;AAAA,oBAAG;AAAA,oBAC1F,WAAU;AAAA,oBAEV,UAAA;AAAA,sBAAA,gBAAAwD,EAACM,GAAA,EAAK,WAAU,UAAA,CAAU;AAAA,sBACzB,EAAE,yBAAyB;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAE9B,gBAAAJ;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAS,CAACoB,MAAM;AAAE,sBAAAA,EAAE,gBAAA,GAAmBrC,EAAkB6B,EAAM,IAAIA,EAAM,MAAMA,EAAM,iBAAiB;AAAA,oBAAG;AAAA,oBACzG,WAAU;AAAA,oBAEV,UAAA;AAAA,sBAAA,gBAAAd,EAACuB,IAAA,EAAO,WAAU,UAAA,CAAU;AAAA,sBAC3B,EAAE,eAAe;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACpB,EAAA,CACF;AAAA,YAAA,GACF;AAAA,YAGCT,EAAM,MAAM,SAAS,KACpB,gBAAAZ,EAAC,OAAA,EAAI,WAAU,mDACb,UAAA;AAAA,cAAA,gBAAAF,EAAC,MAAA,EAAG,WAAU,uDACX,UAAA,EAAE,4BAA4B,GACjC;AAAA,cACA,gBAAAA,EAAC,SAAI,WAAU,wBACZ,YAAM,MAAM,IAAI,CAACoB,GAAMC,MACtB,gBAAAnB;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,WAAU;AAAA,kBAEV,UAAA;AAAA,oBAAA,gBAAAF,EAACgB,GAAA,EAAO,WAAU,yCAAA,CAAyC;AAAA,oBAC3D,gBAAAhB,EAAC,QAAA,EAAK,WAAU,sCAAsC,UAAAoB,EAAA,CAAK;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAJtD,GAAGN,EAAM,EAAE,SAASO,CAAK;AAAA,cAAA,CAMjC,EAAA,CACH;AAAA,YAAA,EAAA,CACF;AAAA,UAAA,GAEJ;AAAA,UAGC1E,MAAoBmE,EAAM,MAAMjE,EAAQiE,EAAM,EAAE,KAC/C,gBAAAd,EAAC,OAAA,EAAI,WAAU,gEACb,UAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,+EACZ,UAAA;AAAA,cAAA,gBAAAF,EAACI,GAAA,EAAM,WAAU,UAAA,CAAU;AAAA,cAC1B,EAAE,sBAAsB;AAAA,cAAE;AAAA,cAAGvD,EAAQiE,EAAM,EAAE,EAAE;AAAA,cAAO;AAAA,YAAA,GACzD;AAAA,YACCjE,EAAQiE,EAAM,EAAE,EAAE,WAAW,IAC5B,gBAAAd,EAAC,KAAA,EAAE,WAAU,uCACV,UAAA,EAAE,wBAAwB,EAAA,CAC7B,IAEA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kEACZ,UAAAnD,EAAQiE,EAAM,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,IAAI,CAACY,MACnC,gBAAAxB;AAAA,cAACyB;AAAA,cAAA;AAAA,gBAEC,IAAI,yBAAyBD,EAAO,MAAM;AAAA,gBAC1C,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAA,gBAAA1B,EAAC,OAAA,EAAI,WAAU,4IACZ,UAAA0B,EAAO,SAAS,OAAO,CAAC,EAAE,YAAA,EAAY,CACzC;AAAA,kBACA,gBAAAxB,EAAC,OAAA,EAAI,WAAU,WACb,UAAA;AAAA,oBAAA,gBAAAF,EAAC,KAAA,EAAE,WAAU,2DACV,UAAA0B,EAAO,UACV;AAAA,oBACA,gBAAA1B,EAAC,KAAA,EAAE,WAAU,gDACV,YAAO,MAAA,CACV;AAAA,kBAAA,EAAA,CACF;AAAA,gBAAA;AAAA,cAAA;AAAA,cAdK0B,EAAO;AAAA,YAAA,CAgBf,GACH;AAAA,YAED7E,EAAQiE,EAAM,EAAE,EAAE,SAAS,MAC1B,gBAAAd,EAAC,KAAA,EAAE,WAAU,wDACV,UAAA,EAAE,+BAA+B;AAAA,cAChC,OAAO;AAAA,cACP,OAAOnD,EAAQiE,EAAM,EAAE,EAAE;AAAA,YAAA,CAC1B,EAAA,CACH;AAAA,UAAA,EAAA,CAEJ,EAAA,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,MAjLGA,EAAM;AAAA,IAAA,CAoLd,GACH;AAAA,IAIDrE,wBACE,OAAA,EAAI,WAAU,mEACb,UAAA,gBAAAyD,EAAC,OAAA,EAAI,WAAU,uHACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,+EACb,UAAA;AAAA,QAAA,gBAAAF,EAAC,MAAA,EAAG,WAAU,oDACX,UAAA,EAAE,0BAA0B,GAC/B;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAMtD,EAAmB,EAAK;AAAA,YACvC,WAAU;AAAA,YAEV,UAAA,gBAAAsD,EAACQ,GAAA,EAAE,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACzB,GACF;AAAA,MACA,gBAAAN,EAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAA,EAAC,SAAA,EAAM,WAAU,6DACd,UAAA;AAAA,YAAA,EAAE,wBAAwB;AAAA,YAAE;AAAA,UAAA,GAC/B;AAAA,UACA,gBAAAF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAOzC;AAAA,cACP,UAAU,CAAC,MAAMC,EAAgB,EAAE,OAAO,KAAK;AAAA,cAC/C,aAAa,EAAE,mCAAmC;AAAA,cAClD,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACZ,GACF;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAwC,EAAC,SAAA,EAAM,WAAU,6DACd,UAAA,EAAE,oBAAoB,GACzB;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAOvC;AAAA,cACP,UAAU,CAAC,MAAMC,EAAuB,EAAE,OAAO,KAAK;AAAA,cACtD,aAAa,EAAE,qCAAqC;AAAA,cACpD,MAAM;AAAA,cACN,WAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACZ,GACF;AAAA,QACA,gBAAAwC,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAMpC,EAA2B,CAACD,CAAuB;AAAA,cAClE,WAAW,6EACTA,IACI,iCACA,yBACN;AAAA,cAEA,UAAA,gBAAAqC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAW,6EACTrC,IAA0B,kBAAkB,eAC9C;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF;AAAA,UAAA;AAAA,4BAED,QAAA,EAAK,WAAU,sCACb,UAAA,EAAE,8BAA8B,EAAA,CACnC;AAAA,QAAA,GACF;AAAA,0BACC,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAqC,EAAC,SAAA,EAAM,WAAU,6DACd,UAAA,EAAE,0BAA0B,GAC/B;AAAA,UACA,gBAAAE;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAOrC;AAAA,cACP,UAAU,CAAC,MAAMC,EAAoB,EAAE,OAAO,KAAK;AAAA,cACnD,WAAU;AAAA,cAEV,UAAA;AAAA,gBAAA,gBAAAkC,EAAC,UAAA,EAAO,OAAM,IAAI,UAAA,EAAE,uBAAuB,GAAE;AAAA,gBAC5CnE,EAAO,OAAO,CAAA2D,MAAKA,EAAE,QAAQ,EAAE,IAAI,CAAAA,MAClC,gBAAAQ,EAAC,UAAA,EAAkB,OAAOR,EAAE,IAAK,YAAE,KAAA,GAAtBA,EAAE,EAAyB,CACzC;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MACA,gBAAAU,EAAC,OAAA,EAAI,WAAU,iFACb,UAAA;AAAA,QAAA,gBAAAF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAMtD,EAAmB,EAAK;AAAA,YACvC,WAAU;AAAA,YAET,YAAE,eAAe;AAAA,UAAA;AAAA,QAAA;AAAA,QAEpB,gBAAAwD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASlB;AAAA,YACT,UAAU,CAACzB,EAAa,KAAA,KAAUQ;AAAA,YAClC,WAAU;AAAA,YAET,UAAA;AAAA,cAAAA,IACC,gBAAAiC,EAACC,KAAQ,WAAU,uBAAA,CAAuB,IAE1C,gBAAAD,EAAC4B,IAAA,EAAM,WAAU,UAAA,CAAU;AAAA,cAE5B,EAAE,eAAe;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACpB,EAAA,CACF;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,IAIDrF,MAAmBF,KAClB,gBAAA2D,EAAC,OAAA,EAAI,WAAU,mEACb,UAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,uHACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,+EACb,UAAA;AAAA,QAAA,gBAAAF,EAAC,MAAA,EAAG,WAAU,oDACX,UAAA,EAAE,8BAA8B,GACnC;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM;AACb,cAAAxD,EAAmB,EAAK,GACxBF,EAAiB,IAAI;AAAA,YACvB;AAAA,YACA,WAAU;AAAA,YAEV,UAAA,gBAAA0D,EAACQ,GAAA,EAAE,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACzB,GACF;AAAA,MACA,gBAAAN,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,QAAA,gBAAAF,EAAC,KAAA,EAAE,WAAU,6CACV,UAAA,EAAE,sCAAsC,EAAE,OAAO3D,EAAc,KAAA,CAAM,EAAA,CACxE;AAAA,QACA,gBAAA6D,EAAC,OAAA,EAAI,WAAU,sCACZ,UAAA;AAAA,UAAAnE,EACE,OAAO,CAACqF,MAAS,CAAC/E,EAAc,MAAM,SAAS+E,EAAK,IAAI,CAAC,EACzD,IAAI,CAACA,MACJ,gBAAAlB;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,SAAS,MAAMb,GAAiB+B,EAAK,EAAE;AAAA,cACvC,WAAU;AAAA,cAEV,UAAA;AAAA,gBAAA,gBAAApB,EAACgB,GAAA,EAAO,WAAU,yCAAA,CAAyC;AAAA,kCAC1D,OAAA,EACC,UAAA;AAAA,kBAAA,gBAAAhB,EAAC,KAAA,EAAE,WAAU,0CAA0C,UAAAoB,EAAK,MAAK;AAAA,kBAChEA,EAAK,eACJ,gBAAApB,EAAC,OAAE,WAAU,uCAAuC,YAAK,YAAA,CAAY;AAAA,gBAAA,EAAA,CAEzE;AAAA,cAAA;AAAA,YAAA;AAAA,YAVKoB,EAAK;AAAA,UAAA,CAYb;AAAA,UACFrF,EAAM,OAAO,CAACqF,MAAS,CAAC/E,EAAc,MAAM,SAAS+E,EAAK,IAAI,CAAC,EAAE,WAAW,KAC3E,gBAAApB,EAAC,KAAA,EAAE,WAAU,wDACV,UAAA,EAAE,+BAA+B,EAAA,CACpC;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("react"),ce=require("react-i18next"),W=require("react-router-dom"),F=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("react"),ce=require("react-i18next"),W=require("react-router-dom"),F=require("./index-IgLVXPg8.js"),a=require("lucide-react"),h=require("./groupsApi-hB9kSWEd.js"),Y=t=>t?"bg-[var(--color-accent-500)] text-white":"text-[var(--text-tertiary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-hover)]";function de(t){const d=new Map;for(const i of t){const l=i.parentGroupId;d.has(l)||d.set(l,[]),d.get(l).push(i)}const v=[],f=(i,l)=>{const N=d.get(i)||[];for(const p of N)v.push({item:p,depth:l}),f(p.id,l+1)},P=new Set(t.map(i=>i.id)),j=t.filter(i=>!i.parentGroupId||!P.has(i.parentGroupId));for(const i of j)v.push({item:i,depth:0}),f(i.id,1);return v}function xe(){const{t}=ce.useTranslation(["admin","common"]),d=W.useNavigate(),{currentTenant:v,isGlobalView:f}=F.useTenant(),[P,j]=n.useState(!0),[i,l]=n.useState([]),[N,p]=n.useState([]),[$,c]=n.useState(null),[w,Z]=n.useState(""),[x,C]=n.useState(null),[_,R]=n.useState(!1),[ee,G]=n.useState(!1),[S,L]=n.useState(null),[m,re]=n.useState({}),[M,I]=n.useState(null),[k,T]=n.useState("cards"),[b,te]=n.useState("all"),[g,se]=n.useState("all"),[A,U]=n.useState(""),[q,B]=n.useState(""),[E,V]=n.useState(!0),[O,z]=n.useState(""),[X,Q]=n.useState(!1),y=n.useCallback(async()=>{try{j(!0),c(null);const[r,s]=await Promise.all([h.groupsApi.getAll(),F.adminApi.roles.getAssignable()]);l(Array.isArray(r)?r:[]),p(Array.isArray(s)?s:[])}catch(r){console.error("Failed to load groups:",r),l([]),p([]);const s=r;s.response?.status===401?c(t("common:errors.sessionExpired")):s.response?.status===403?c(t("common:errors.noPermission")):c(t("admin:groups.loadError"))}finally{j(!1)}},[t,v?.id,f]);n.useEffect(()=>{y()},[y]);const ae=async r=>{if(m[r]){L(S===r?null:r);return}I(r);try{const s=await h.groupsApi.getMembers(r);re(o=>({...o,[r]:s})),L(r)}catch(s){console.error("Failed to load members:",s),c(t("admin:groups.loadError"))}finally{I(null)}},ne=n.useCallback(async()=>{const[r,s]=await Promise.all([h.groupsApi.getAll(),F.adminApi.roles.getAssignable()]),o=Array.isArray(r)?r:[];return l(o),p(Array.isArray(s)?s:[]),o},[]),oe=async()=>{if(A.trim()){Q(!0);try{await h.groupsApi.create({name:A.trim(),description:q.trim()||void 0,isSecurityGroup:E,parentGroupId:O||void 0}),await y(),G(!1),U(""),B(""),V(!0),z("")}catch(r){console.error("Failed to create group:",r);const s=r;s.response?.status===409?c(s.response.data?.message||t("admin:groups.createError")):c(t("admin:groups.createError"))}finally{Q(!1)}}},H=async(r,s,o=!1)=>{const u=o?t("admin:groups.deleteConfirmEntra",{name:s,defaultValue:`Le groupe "${s}" est synchronisé depuis Entra ID. Il sera recréé lors de la prochaine synchronisation.
|
|
2
2
|
|
|
3
3
|
Êtes-vous sûr de vouloir le supprimer ?`}):t("admin:groups.deleteConfirm",{name:s});if(confirm(u))try{await h.groupsApi.delete(r),await y()}catch(le){console.error("Failed to delete group:",le),c(t("admin:groups.deleteError"))}},ie=async r=>{if(x)try{await h.groupsApi.assignRole(x.id,{roleId:r});const o=(await ne()).find(u=>u.id===x.id);o&&C(o)}catch(s){console.error("Failed to assign role:",s),c(t("admin:groups.assignError"))}},D=i.filter(r=>{const s=r.name.toLowerCase().includes(w.toLowerCase())||r.description?.toLowerCase().includes(w.toLowerCase()),o=b==="all"||b==="security"&&r.isSecurityGroup||b==="distribution"&&!r.isSecurityGroup,u=g==="all"||g==="local"&&!r.isSyncedFromEntra||g==="synced"&&r.isSyncedFromEntra;return s&&o&&u}),K=de(D),J=r=>r?new Intl.DateTimeFormat("fr-FR",{dateStyle:"medium",timeStyle:"short"}).format(new Date(r)):"-";return P?e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(a.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-500)]"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsx(F.Breadcrumb,{items:[{label:t("admin:header.title"),href:"/administration"},{label:t("admin:users.title","Users"),href:"/administration/users"},{label:t("admin:groups.title","Groups")}]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-[var(--radius-button)] bg-[var(--color-accent-500)]/10",children:e.jsx(a.Users,{className:"w-6 h-6 text-[var(--color-accent-500)]"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:t("admin:groups.title")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:t("admin:groups.subtitle",{count:i.length})})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{onClick:y,className:"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] bg-[var(--bg-secondary)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors",children:[e.jsx(a.RefreshCw,{className:"w-4 h-4"}),t("common:refresh")]}),e.jsxs("button",{onClick:()=>G(!0),className:"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors",children:[e.jsx(a.Plus,{className:"w-4 h-4"}),t("admin:groups.createGroup")]})]})]}),$&&e.jsx("div",{className:"p-4 rounded-[var(--radius-card)] bg-[var(--error-bg)] border border-[var(--error-border)]",children:e.jsxs("div",{className:"flex items-center gap-2 text-[var(--error-text)]",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5"}),e.jsx("span",{children:$}),e.jsx("button",{onClick:()=>c(null),className:"ml-auto p-1 hover:bg-[var(--error-text)]/10 rounded",children:e.jsx(a.X,{className:"w-4 h-4"})})]})}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-4",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(a.Search,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-[var(--text-tertiary)]"}),e.jsx("input",{type:"text",placeholder:t("admin:groups.searchPlaceholder"),value:w,onChange:r=>Z(r.target.value),className:"w-full pl-10 pr-4 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] placeholder:text-[var(--text-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(a.Filter,{className:"w-4 h-4 text-[var(--text-tertiary)]"}),e.jsxs("select",{value:b,onChange:r=>te(r.target.value),className:"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]",children:[e.jsx("option",{value:"all",children:t("admin:groups.allTypes")}),e.jsx("option",{value:"security",children:t("admin:groups.securityGroup")}),e.jsx("option",{value:"distribution",children:t("admin:groups.distributionGroup")})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(a.Cloud,{className:"w-4 h-4 text-[var(--text-tertiary)]"}),e.jsxs("select",{value:g,onChange:r=>se(r.target.value),className:"px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]",children:[e.jsx("option",{value:"all",children:t("admin:groups.allSyncStatus")}),e.jsx("option",{value:"local",children:t("admin:groups.localOnly")}),e.jsx("option",{value:"synced",children:t("admin:groups.syncedFromEntra")})]})]}),e.jsxs("div",{className:"flex items-center gap-1 p-1 rounded-[var(--radius-button)] bg-[var(--bg-secondary)] border border-[var(--border-color)]",children:[e.jsx("button",{onClick:()=>T("cards"),className:`p-2 rounded-[var(--radius-button)] transition-colors ${Y(k==="cards")}`,title:t("admin:groups.cardView"),children:e.jsx(a.LayoutGrid,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>T("table"),className:`p-2 rounded-[var(--radius-button)] transition-colors ${Y(k==="table")}`,title:t("admin:groups.tableView"),children:e.jsx(a.List,{className:"w-4 h-4"})})]})]}),D.length===0&&e.jsx("div",{className:"text-center py-12 text-[var(--text-secondary)]",children:t(w||b!=="all"||g!=="all"?"admin:groups.noResults":"admin:groups.noGroups")}),D.length>0&&k==="table"&&e.jsx("div",{className:"rounded-[var(--radius-card)] border border-[var(--border-color)] overflow-hidden",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{className:"bg-[var(--bg-secondary)]",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]",children:t("admin:groups.groupName")}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]",children:t("admin:groups.parentGroup")}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]",children:t("common:type")}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]",children:t("admin:groups.source")}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]",children:t("admin:groups.members")}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-medium text-[var(--text-secondary)]",children:t("admin:groups.assignedRoles")}),e.jsx("th",{className:"px-4 py-3 text-right text-sm font-medium text-[var(--text-secondary)]",children:t("common:actionsColumn")})]})}),e.jsx("tbody",{className:"divide-y divide-[var(--border-color)]",children:K.map(({item:r,depth:s})=>e.jsxs("tr",{className:"hover:bg-[var(--bg-hover)] cursor-pointer",onClick:()=>d(`/administration/users/groups/${r.id}`),children:[e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-3",style:{paddingLeft:`${s*24}px`},children:[s>0&&e.jsx(a.CornerDownRight,{className:"w-4 h-4 text-[var(--text-tertiary)] flex-shrink-0"}),e.jsx("div",{className:`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${r.isSecurityGroup?"bg-blue-500/10 text-blue-500":"bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]"}`,children:r.isSecurityGroup?e.jsx(a.Shield,{className:"w-4 h-4"}):e.jsx(a.Building2,{className:"w-4 h-4"})}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)] hover:text-[var(--color-accent-500)] hover:underline",children:r.name}),r.childCount>0&&e.jsxs("span",{className:"flex items-center gap-0.5 px-1.5 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]",children:[e.jsx(a.GitBranch,{className:"w-3 h-3"}),r.childCount]})]}),r.description&&e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] truncate max-w-xs",children:r.description})]})]})}),e.jsx("td",{className:"px-4 py-3 text-sm text-[var(--text-secondary)]",children:r.parentGroupName?e.jsx("span",{className:"text-[var(--text-secondary)]",children:r.parentGroupName}):e.jsx("span",{className:"text-[var(--text-tertiary)]",children:"-"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("span",{className:`px-2 py-1 text-xs rounded-[var(--radius-badge)] ${r.isSecurityGroup?"bg-blue-500/10 text-blue-500":"bg-purple-500/10 text-purple-500"}`,children:r.isSecurityGroup?t("admin:groups.securityGroup"):t("admin:groups.distributionGroup")})}),e.jsx("td",{className:"px-4 py-3",children:r.isSyncedFromEntra?e.jsxs("span",{className:"flex items-center gap-1 text-sm text-blue-500",children:[e.jsx(a.Cloud,{className:"w-4 h-4"}),"Entra"]}):e.jsxs("span",{className:"flex items-center gap-1 text-sm text-[var(--text-tertiary)]",children:[e.jsx(a.CloudOff,{className:"w-4 h-4"}),t("admin:groups.local")]})}),e.jsx("td",{className:"px-4 py-3 text-sm text-[var(--text-secondary)]",children:e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(a.Users,{className:"w-4 h-4"}),r.memberCount]})}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[r.roles.slice(0,2).map((o,u)=>e.jsx("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]",children:o},`${r.id}-role-${u}`)),r.roles.length>2&&e.jsxs("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)]",children:["+",r.roles.length-2]})]})}),e.jsx("td",{className:"px-4 py-3 text-right",onClick:o=>o.stopPropagation(),children:e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx("button",{onClick:()=>{C(r),R(!0)},className:"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors",title:t("admin:groups.assignRole"),children:e.jsx(a.Plus,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>H(r.id,r.name,r.isSyncedFromEntra),className:"p-2 rounded-[var(--radius-button)] text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors",title:t("common:delete"),children:e.jsx(a.Trash2,{className:"w-4 h-4"})})]})})]},r.id))})]})}),D.length>0&&k!=="table"&&e.jsx("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:K.map(({item:r})=>e.jsxs("div",{role:"button",tabIndex:0,className:"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-secondary)] overflow-hidden hover:border-[var(--color-accent-500)] transition-colors cursor-pointer text-left flex flex-col",onClick:()=>d(`/administration/users/groups/${r.id}`),onKeyDown:s=>{(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),d(`/administration/users/groups/${r.id}`))},children:[e.jsxs("div",{className:"p-4 flex-1",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex items-start gap-3 min-w-0",children:[e.jsx("div",{className:`p-2.5 rounded-[var(--radius-button)] flex-shrink-0 ${r.isSecurityGroup?"bg-blue-500/10 text-blue-500":"bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]"}`,children:r.isSecurityGroup?e.jsx(a.Shield,{className:"w-5 h-5"}):e.jsx(a.Building2,{className:"w-5 h-5"})}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"font-semibold text-[var(--text-primary)] truncate",children:r.name}),r.isSecurityGroup&&e.jsx("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20",children:t("admin:groups.securityGroup")}),!r.isActive&&e.jsx("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]",children:t("common:inactive")}),r.isSyncedFromEntra?e.jsxs("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-blue-500/10 text-blue-500 border border-blue-500/20 flex items-center gap-1",children:[e.jsx(a.Cloud,{className:"w-3 h-3"}),"Entra"]}):e.jsxs("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1",children:[e.jsx(a.CloudOff,{className:"w-3 h-3"}),t("admin:groups.local")]}),r.parentGroupName&&e.jsxs("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1",children:[e.jsx(a.CornerDownRight,{className:"w-3 h-3"}),r.parentGroupName]}),r.childCount>0&&e.jsxs("span",{className:"px-2 py-0.5 text-xs rounded-[var(--radius-badge)] bg-[var(--bg-tertiary)] text-[var(--text-tertiary)] border border-[var(--border-color)] flex items-center gap-1",children:[e.jsx(a.GitBranch,{className:"w-3 h-3"}),t("admin:groups.childGroupCount",{count:r.childCount})]})]}),r.description&&e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1 line-clamp-2",children:r.description}),e.jsx("div",{className:"flex items-center gap-4 mt-2 text-sm text-[var(--text-tertiary)] flex-wrap",onClick:s=>s.stopPropagation(),children:e.jsxs("button",{onClick:s=>{s.stopPropagation(),ae(r.id)},className:"flex items-center gap-1 hover:text-[var(--color-accent-500)] transition-colors",children:[e.jsx(a.Users,{className:"w-4 h-4"}),t("admin:groups.memberCount",{count:r.memberCount}),M===r.id&&e.jsx(a.Loader2,{className:"w-3 h-3 animate-spin ml-1"}),M!==r.id&&S===r.id&&e.jsx(a.ChevronUp,{className:"w-3 h-3 ml-1"}),M!==r.id&&S!==r.id&&e.jsx(a.ChevronDown,{className:"w-3 h-3 ml-1"})]})}),r.isSyncedFromEntra&&r.lastEntraSyncAt&&e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] mt-1",children:t("admin:groups.lastSynced",{date:J(r.lastEntraSyncAt)})}),!r.isSyncedFromEntra&&e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] mt-1",children:t("admin:groups.createdAt",{date:J(r.createdAt)})})]})]}),e.jsxs("div",{className:"flex flex-col gap-2 flex-shrink-0",onClick:s=>s.stopPropagation(),children:[e.jsxs("button",{onClick:s=>{s.stopPropagation(),C(r),R(!0)},className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] transition-colors",children:[e.jsx(a.Plus,{className:"w-4 h-4"}),t("admin:groups.assignRole")]}),e.jsxs("button",{onClick:s=>{s.stopPropagation(),H(r.id,r.name,r.isSyncedFromEntra)},className:"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--error-border)] text-[var(--error-text)] hover:bg-[var(--error-bg)] transition-colors",children:[e.jsx(a.Trash2,{className:"w-4 h-4"}),t("common:delete")]})]})]}),r.roles.length>0&&e.jsxs("div",{className:"mt-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsx("h4",{className:"text-sm font-medium text-[var(--text-primary)] mb-2",children:t("admin:groups.assignedRoles")}),e.jsx("div",{className:"flex flex-wrap gap-2",children:r.roles.map((s,o)=>e.jsxs("span",{className:"inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-badge)] bg-[var(--bg-primary)] border border-[var(--border-color)]",children:[e.jsx(a.Shield,{className:"w-4 h-4 text-[var(--color-accent-500)]"}),e.jsx("span",{className:"text-sm text-[var(--text-primary)]",children:s})]},`${r.id}-role-${o}`))})]})]}),S===r.id&&m[r.id]&&e.jsx("div",{className:"border-t border-[var(--border-color)] bg-[var(--bg-primary)]",children:e.jsxs("div",{className:"p-4",children:[e.jsxs("h4",{className:"text-sm font-medium text-[var(--text-primary)] mb-3 flex items-center gap-2",children:[e.jsx(a.Users,{className:"w-4 h-4"}),t("admin:groups.members")," (",m[r.id].length,")"]}),m[r.id].length===0?e.jsx("p",{className:"text-sm text-[var(--text-tertiary)]",children:t("admin:groups.noMembers")}):e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-64 overflow-y-auto",children:m[r.id].slice(0,10).map(s=>e.jsxs(W.Link,{to:`/administration/users/${s.userId}`,className:"flex items-center gap-3 p-2 rounded-[var(--radius-button)] hover:bg-[var(--bg-hover)] transition-colors",children:[e.jsx("div",{className:"w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium bg-[var(--color-accent-500)]/10 text-[var(--color-accent-500)]",children:s.fullName.charAt(0).toUpperCase()}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium text-[var(--text-primary)] truncate",children:s.fullName}),e.jsx("p",{className:"text-xs text-[var(--text-tertiary)] truncate",children:s.email})]})]},s.userId))}),m[r.id].length>10&&e.jsx("p",{className:"mt-3 text-center text-sm text-[var(--text-tertiary)]",children:t("admin:groups.showingMembers",{shown:10,total:m[r.id].length})})]})})]},r.id))}),ee&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:e.jsxs("div",{className:"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-[var(--border-color)]",children:[e.jsx("h2",{className:"text-lg font-semibold text-[var(--text-primary)]",children:t("admin:groups.createGroup")}),e.jsx("button",{onClick:()=>G(!1),className:"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]",children:e.jsx(a.X,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"p-4 space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-[var(--text-primary)] mb-1",children:[t("admin:groups.groupName")," *"]}),e.jsx("input",{type:"text",value:A,onChange:r=>U(r.target.value),placeholder:t("admin:groups.groupNamePlaceholder"),className:"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-primary)] mb-1",children:t("common:description")}),e.jsx("textarea",{value:q,onChange:r=>B(r.target.value),placeholder:t("admin:groups.descriptionPlaceholder"),rows:3,className:"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)] resize-none"})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{type:"button",onClick:()=>V(!E),className:`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${E?"bg-[var(--color-accent-500)]":"bg-[var(--bg-tertiary)]"}`,children:e.jsx("span",{className:`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${E?"translate-x-6":"translate-x-1"}`})}),e.jsx("span",{className:"text-sm text-[var(--text-primary)]",children:t("admin:groups.isSecurityGroup")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-[var(--text-primary)] mb-1",children:t("admin:groups.parentGroup")}),e.jsxs("select",{value:O,onChange:r=>z(r.target.value),className:"w-full px-3 py-2 rounded-[var(--radius-input)] border border-[var(--border-color)] bg-[var(--bg-primary)] text-[var(--text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent-500)]",children:[e.jsx("option",{value:"",children:t("admin:groups.noParent")}),i.filter(r=>r.isActive).map(r=>e.jsx("option",{value:r.id,children:r.name},r.id))]})]})]}),e.jsxs("div",{className:"flex items-center justify-end gap-3 p-4 border-t border-[var(--border-color)]",children:[e.jsx("button",{onClick:()=>G(!1),className:"px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] border border-[var(--border-color)] text-[var(--text-primary)] hover:bg-[var(--bg-hover)] transition-colors",children:t("common:cancel")}),e.jsxs("button",{onClick:oe,disabled:!A.trim()||X,className:"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-[var(--radius-button)] bg-[var(--color-accent-600)] text-white hover:bg-[var(--color-accent-700)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",children:[X?e.jsx(a.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(a.Check,{className:"w-4 h-4"}),t("common:create")]})]})]})}),_&&x&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:e.jsxs("div",{className:"w-full max-w-md rounded-[var(--radius-card)] bg-[var(--bg-secondary)] border border-[var(--border-color)] shadow-xl",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b border-[var(--border-color)]",children:[e.jsx("h2",{className:"text-lg font-semibold text-[var(--text-primary)]",children:t("admin:groups.assignRoleTitle")}),e.jsx("button",{onClick:()=>{R(!1),C(null)},className:"p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-tertiary)]",children:e.jsx(a.X,{className:"w-5 h-5"})})]}),e.jsxs("div",{className:"p-4",children:[e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mb-4",children:t("admin:groups.assignRoleDescription",{group:x.name})}),e.jsxs("div",{className:"space-y-2 max-h-64 overflow-y-auto",children:[N.filter(r=>!x.roles.includes(r.name)).map(r=>e.jsxs("button",{onClick:()=>ie(r.id),className:"w-full flex items-center gap-3 p-3 rounded-[var(--radius-button)] border border-[var(--border-color)] hover:border-[var(--color-accent-500)] hover:bg-[var(--bg-hover)] transition-colors text-left",children:[e.jsx(a.Shield,{className:"w-5 h-5 text-[var(--color-accent-500)]"}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-[var(--text-primary)]",children:r.name}),r.description&&e.jsx("p",{className:"text-xs text-[var(--text-tertiary)]",children:r.description})]})]},r.id)),N.filter(r=>!x.roles.includes(r.name)).length===0&&e.jsx("p",{className:"text-sm text-[var(--text-tertiary)] text-center py-4",children:t("admin:groups.allRolesAssigned")})]})]})]})})]})}exports.UsersGroupsPage=xe;
|
|
4
|
-
//# sourceMappingURL=UsersGroupsPage-
|
|
4
|
+
//# sourceMappingURL=UsersGroupsPage-Dq3rAteo.js.map
|