@atlashub/smartstack 3.30.0 → 3.32.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-DJb49NMA.js → AgentSkillsPage-BMxOA-nm.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-DJb49NMA.js.map → AgentSkillsPage-BMxOA-nm.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-CVq3qZoe.js → AgentSkillsPage-DSwfoazB.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-CVq3qZoe.js.map → AgentSkillsPage-DSwfoazB.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-oHEi-sFh.js → AgentWorkloadPage-B_emq8kd.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-oHEi-sFh.js.map → AgentWorkloadPage-B_emq8kd.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-D_nk3gKj.js → AgentWorkloadPage-_USTeYWz.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-D_nk3gKj.js.map → AgentWorkloadPage-_USTeYWz.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-Cr0q2HnB.js → ApiCatalogDetailPage-BC_HxVu5.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-Cr0q2HnB.js.map → ApiCatalogDetailPage-BC_HxVu5.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-DX8buBkV.js → ApiCatalogDetailPage-BI7zyZAd.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-DX8buBkV.js.map → ApiCatalogDetailPage-BI7zyZAd.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-DqboIzZE.js → ApiCatalogPage-CutaHo5K.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-DqboIzZE.js.map → ApiCatalogPage-CutaHo5K.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-DN7sazvI.js → ApiCatalogPage-M80MorHU.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-DN7sazvI.js.map → ApiCatalogPage-M80MorHU.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage--9YwwS5A.js → ApplicationDetailPage-DVY0wua0.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage--9YwwS5A.js.map → ApplicationDetailPage-DVY0wua0.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CCNjr64K.js → ApplicationDetailPage-DzszwaIZ.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-CCNjr64K.js.map → ApplicationDetailPage-DzszwaIZ.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-Bs-Xgca4.js → ApplicationsDashboardPage-B3ptvnJz.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-Bs-Xgca4.js.map → ApplicationsDashboardPage-B3ptvnJz.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BSsHN3Yj.js → ApplicationsDashboardPage-D0pxqbEc.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BSsHN3Yj.js.map → ApplicationsDashboardPage-D0pxqbEc.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-DDysNWJ5.js → ApplicationsGridPage-Ca23FBSP.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-DDysNWJ5.js.map → ApplicationsGridPage-Ca23FBSP.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-s1WEzOXS.js → ApplicationsGridPage-qi2UCD24.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-s1WEzOXS.js.map → ApplicationsGridPage-qi2UCD24.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B3CSMiV0.js → ApplicationsListPage-CEUmBXN0.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B3CSMiV0.js.map → ApplicationsListPage-CEUmBXN0.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B6ZCecIl.js → ApplicationsListPage-cE82bv8j.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B6ZCecIl.js.map → ApplicationsListPage-cE82bv8j.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-ztPwoAGt.js → ApplicationsPage-DW1BrVVN.js} +4 -4
- package/dist/chunks/{ApplicationsPage-ztPwoAGt.js.map → ApplicationsPage-DW1BrVVN.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BBaiBM--.js → ApplicationsPage-RAqTs5HI.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BBaiBM--.js.map → ApplicationsPage-RAqTs5HI.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CK4L4rBO.js → AssignmentRulesPage-C0qnk3oR.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CK4L4rBO.js.map → AssignmentRulesPage-C0qnk3oR.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-DFSVFFXr.js → AssignmentRulesPage-CVgFmhEs.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-DFSVFFXr.js.map → AssignmentRulesPage-CVgFmhEs.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-JCLpyg94.js → AssignmentsPage-Bv9HYtYN.js} +2 -2
- package/dist/chunks/{AssignmentsPage-JCLpyg94.js.map → AssignmentsPage-Bv9HYtYN.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-Bp7oQD7Q.js → AssignmentsPage-z1q1C9Uz.js} +2 -2
- package/dist/chunks/{AssignmentsPage-Bp7oQD7Q.js.map → AssignmentsPage-z1q1C9Uz.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-Bl9xlJ3h.js → AuthCallbackPage-CcteN6Kv.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-Bl9xlJ3h.js.map → AuthCallbackPage-CcteN6Kv.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-CzMHz4jy.js → AuthCallbackPage-DL5PJUYJ.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-CzMHz4jy.js.map → AuthCallbackPage-DL5PJUYJ.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-D_8T1vqV.js → ConfirmEmailPage-BP8VUz-A.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-D_8T1vqV.js.map → ConfirmEmailPage-BP8VUz-A.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-M7mJgXvn.js → ConfirmEmailPage-CeflKXpN.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-M7mJgXvn.js.map → ConfirmEmailPage-CeflKXpN.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-BNEGavlu.js → CreateSupportTicketPage-BAdvWb_8.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-BNEGavlu.js.map → CreateSupportTicketPage-BAdvWb_8.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-C2X2mfds.js → CreateSupportTicketPage-DDiv79-p.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-C2X2mfds.js.map → CreateSupportTicketPage-DDiv79-p.js.map} +1 -1
- package/dist/chunks/{DashboardPage-4oy2YqvT.js → DashboardPage-B_uyyRRE.js} +2 -2
- package/dist/chunks/{DashboardPage-4oy2YqvT.js.map → DashboardPage-B_uyyRRE.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CPArUG-S.js → DashboardPage-CpoduSu7.js} +2 -2
- package/dist/chunks/{DashboardPage-CPArUG-S.js.map → DashboardPage-CpoduSu7.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CO-8B8EI.js → DashboardPage-D4pyUgdM.js} +3 -3
- package/dist/chunks/{DashboardPage-CO-8B8EI.js.map → DashboardPage-D4pyUgdM.js.map} +1 -1
- package/dist/chunks/{DashboardPage-D5MRMxEV.js → DashboardPage-Kp-MCxW4.js} +3 -3
- package/dist/chunks/{DashboardPage-D5MRMxEV.js.map → DashboardPage-Kp-MCxW4.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-DnjLFXnL.js → EscalationConfigPage-D-WCN6YS.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-DnjLFXnL.js.map → EscalationConfigPage-D-WCN6YS.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CwdnfJbJ.js → EscalationConfigPage-UrLJarSI.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CwdnfJbJ.js.map → EscalationConfigPage-UrLJarSI.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-sh-3h_H9.js → ForceChangePasswordPage-BIh1SF5C.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-sh-3h_H9.js.map → ForceChangePasswordPage-BIh1SF5C.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-ZEIfyqwE.js → ForceChangePasswordPage-FFZZRpU7.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-ZEIfyqwE.js.map → ForceChangePasswordPage-FFZZRpU7.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-B4M6-xeM.js → ForgotPasswordPage-BKqRF7SF.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-B4M6-xeM.js.map → ForgotPasswordPage-BKqRF7SF.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-MIu-U7p0.js → ForgotPasswordPage-BXp8qQUX.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-MIu-U7p0.js.map → ForgotPasswordPage-BXp8qQUX.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-4XK3Bs_r.js → GroupDetailPage-a0hBx-LO.js} +5 -5
- package/dist/chunks/{GroupDetailPage-4XK3Bs_r.js.map → GroupDetailPage-a0hBx-LO.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-C-kvtd2T.js → GroupDetailPage-eGGJCqgq.js} +2 -2
- package/dist/chunks/{GroupDetailPage-C-kvtd2T.js.map → GroupDetailPage-eGGJCqgq.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-CP41FzHi.js → MyAccessRequestsPage-BgQSyy5d.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-CP41FzHi.js.map → MyAccessRequestsPage-BgQSyy5d.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-DzrXTrVi.js → MyAccessRequestsPage-Dmb0rUHO.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-DzrXTrVi.js.map → MyAccessRequestsPage-Dmb0rUHO.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-V_SwYio2.js → MyTenantsPage-BZTeqyDr.js} +3 -3
- package/dist/chunks/{MyTenantsPage-V_SwYio2.js.map → MyTenantsPage-BZTeqyDr.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-CZRkMbh8.js → MyTenantsPage-kCHBF2uA.js} +2 -2
- package/dist/chunks/{MyTenantsPage-CZRkMbh8.js.map → MyTenantsPage-kCHBF2uA.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DOUhaLal.js → MyTicketsPage-BwNIqpCE.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DOUhaLal.js.map → MyTicketsPage-BwNIqpCE.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DnvAIeyr.js → MyTicketsPage-CTpjkA5t.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DnvAIeyr.js.map → MyTicketsPage-CTpjkA5t.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-DfTa4jCG.js → NavigationAppsPage-DO5bTibb.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-DfTa4jCG.js.map → NavigationAppsPage-DO5bTibb.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-DXvpLsbt.js → NavigationAppsPage-vx_n07SD.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-DXvpLsbt.js.map → NavigationAppsPage-vx_n07SD.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-I1yCk7tk.js → NotificationsPage-Br9sb9AQ.js} +2 -2
- package/dist/chunks/{NotificationsPage-I1yCk7tk.js.map → NotificationsPage-Br9sb9AQ.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-D76MdAs-.js → NotificationsPage-CRhd752L.js} +2 -2
- package/dist/chunks/{NotificationsPage-D76MdAs-.js.map → NotificationsPage-CRhd752L.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-DtWUPCh3.js → OnboardingWizardPage-BIl3Usew.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-DtWUPCh3.js.map → OnboardingWizardPage-BIl3Usew.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-BRUzcl1A.js → OnboardingWizardPage-CjqxWX7h.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-BRUzcl1A.js.map → OnboardingWizardPage-CjqxWX7h.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-DJJGbXoX.js → PermissionDetailPage-COIuJXH-.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-DJJGbXoX.js.map → PermissionDetailPage-COIuJXH-.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-CUNKbl7t.js → PermissionDetailPage-P_d6xnY0.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-CUNKbl7t.js.map → PermissionDetailPage-P_d6xnY0.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-B8wmawPV.js → PermissionsPage-BhjnMyFY.js} +2 -2
- package/dist/chunks/{PermissionsPage-B8wmawPV.js.map → PermissionsPage-BhjnMyFY.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-Dbjcctuh.js → PermissionsPage-CHYy8XFr.js} +2 -2
- package/dist/chunks/{PermissionsPage-Dbjcctuh.js.map → PermissionsPage-CHYy8XFr.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-zii0ll57.js → PortalDashboardPage-BwQ4NQrH.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-zii0ll57.js.map → PortalDashboardPage-BwQ4NQrH.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-BeNfBZmb.js → PortalDashboardPage-hLJcfGnT.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-BeNfBZmb.js.map → PortalDashboardPage-hLJcfGnT.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BmvrBaAD.js → PreferencesPage-DYYqisR0.js} +2 -2
- package/dist/chunks/{PreferencesPage-BmvrBaAD.js.map → PreferencesPage-DYYqisR0.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BCpuIGzv.js → PreferencesPage-DzpM-lpD.js} +2 -2
- package/dist/chunks/{PreferencesPage-BCpuIGzv.js.map → PreferencesPage-DzpM-lpD.js.map} +1 -1
- package/dist/chunks/{ProfilePage-eowQd59_.js → ProfilePage-D98bvXeT.js} +2 -2
- package/dist/chunks/{ProfilePage-eowQd59_.js.map → ProfilePage-D98bvXeT.js.map} +1 -1
- package/dist/chunks/{ProfilePage-mf5wI0-n.js → ProfilePage-DWRDN0fo.js} +2 -2
- package/dist/chunks/{ProfilePage-mf5wI0-n.js.map → ProfilePage-DWRDN0fo.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-CLsaUNqA.js → ReferencesManagementPage-B0Cq9BHS.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-CLsaUNqA.js.map → ReferencesManagementPage-B0Cq9BHS.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-8UPgkVE8.js → ReferencesManagementPage-CxbfOBs2.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-8UPgkVE8.js.map → ReferencesManagementPage-CxbfOBs2.js.map} +1 -1
- package/dist/chunks/{RegisterPage-57X-ILDb.js → RegisterPage-DMeq3GzW.js} +2 -2
- package/dist/chunks/{RegisterPage-57X-ILDb.js.map → RegisterPage-DMeq3GzW.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CNyHSbqs.js → RegisterPage-DvG2Php7.js} +2 -2
- package/dist/chunks/{RegisterPage-CNyHSbqs.js.map → RegisterPage-DvG2Php7.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-JW8-mh_k.js → ResetPasswordPage-DOTswepm.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-JW8-mh_k.js.map → ResetPasswordPage-DOTswepm.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-CyV8l-Zo.js → ResetPasswordPage-ntMMFvDo.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-CyV8l-Zo.js.map → ResetPasswordPage-ntMMFvDo.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-wddG59kg.js → ResolutionModal-CKt73sIZ.js} +2 -2
- package/dist/chunks/{ResolutionModal-wddG59kg.js.map → ResolutionModal-CKt73sIZ.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-CjwE73NX.js → ResolutionModal-XGHCELez.js} +2 -2
- package/dist/chunks/{ResolutionModal-CjwE73NX.js.map → ResolutionModal-XGHCELez.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CrioVHFI.js → RoleDetailPage-BtnYTVN6.js} +3 -3
- package/dist/chunks/{RoleDetailPage-CrioVHFI.js.map → RoleDetailPage-BtnYTVN6.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-TUOGR1ow.js → RoleDetailPage-DAp65p0d.js} +2 -2
- package/dist/chunks/{RoleDetailPage-TUOGR1ow.js.map → RoleDetailPage-DAp65p0d.js.map} +1 -1
- package/dist/chunks/{RolesPage-CAcols3D.js → RolesPage-DyEhJHxw.js} +2 -2
- package/dist/chunks/{RolesPage-CAcols3D.js.map → RolesPage-DyEhJHxw.js.map} +1 -1
- package/dist/chunks/{RolesPage-sJBWaNff.js → RolesPage-FmZCLEYo.js} +2 -2
- package/dist/chunks/{RolesPage-sJBWaNff.js.map → RolesPage-FmZCLEYo.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BPGRloOS.js → SlaConfigPage-DTtP2Q4t.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BPGRloOS.js.map → SlaConfigPage-DTtP2Q4t.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-D5TRn7Ir.js → SlaConfigPage-LpVD_ai4.js} +2 -2
- package/dist/chunks/{SlaConfigPage-D5TRn7Ir.js.map → SlaConfigPage-LpVD_ai4.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-UXmYLrIq.js → SupportPermissionsPage-BV8F_Tl3.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-UXmYLrIq.js.map → SupportPermissionsPage-BV8F_Tl3.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-Dc2bWTzG.js → SupportPermissionsPage-Bzfq6pKf.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-Dc2bWTzG.js.map → SupportPermissionsPage-Bzfq6pKf.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-nTY85sNA.js → TemplatesPage-CYHH5WlP.js} +2 -2
- package/dist/chunks/{TemplatesPage-nTY85sNA.js.map → TemplatesPage-CYHH5WlP.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-dmPlqqiD.js → TemplatesPage-czt_RH5f.js} +2 -2
- package/dist/chunks/{TemplatesPage-dmPlqqiD.js.map → TemplatesPage-czt_RH5f.js.map} +1 -1
- package/dist/chunks/{TenantCard-BhT-31ls.js → TenantCard-Bqh5PGJx.js} +2 -2
- package/dist/chunks/{TenantCard-BhT-31ls.js.map → TenantCard-Bqh5PGJx.js.map} +1 -1
- package/dist/chunks/{TenantCard-BUXfstRZ.js → TenantCard-C6qKD480.js} +2 -2
- package/dist/chunks/{TenantCard-BUXfstRZ.js.map → TenantCard-C6qKD480.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-B-SRDR2R.js → TenantScopeSelector-DWUP8Le7.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-B-SRDR2R.js.map → TenantScopeSelector-DWUP8Le7.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-3_mzBLNI.js → TenantScopeSelector-DxQ7HNbh.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-3_mzBLNI.js.map → TenantScopeSelector-DxQ7HNbh.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-xN3wPnFL.js → TicketDetailPage-BuxXLcJi.js} +2 -2
- package/dist/chunks/{TicketDetailPage-xN3wPnFL.js.map → TicketDetailPage-BuxXLcJi.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-B4cR3rOC.js → TicketDetailPage-Dy4pg33-.js} +2 -2
- package/dist/chunks/{TicketDetailPage-B4cR3rOC.js.map → TicketDetailPage-Dy4pg33-.js.map} +1 -1
- package/dist/chunks/{TicketsPage-CkHgXSxU.js → TicketsPage-Ck-HUgte.js} +2 -2
- package/dist/chunks/{TicketsPage-CkHgXSxU.js.map → TicketsPage-Ck-HUgte.js.map} +1 -1
- package/dist/chunks/{TicketsPage-Dwi2xpMI.js → TicketsPage-jlN9JDzm.js} +2 -2
- package/dist/chunks/{TicketsPage-Dwi2xpMI.js.map → TicketsPage-jlN9JDzm.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-D2a3EOey.js → UserCreateTicketPage-BrRZyXMn.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-D2a3EOey.js.map → UserCreateTicketPage-BrRZyXMn.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-bcbSLglE.js → UserCreateTicketPage-D58Ro4Nb.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-bcbSLglE.js.map → UserCreateTicketPage-D58Ro4Nb.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-DwnDRNoW.js → UserDashboardPage-C5ulSzaI.js} +2 -2
- package/dist/chunks/{UserDashboardPage-DwnDRNoW.js.map → UserDashboardPage-C5ulSzaI.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-ZMsx8LWw.js → UserDashboardPage-CjAx5OHh.js} +2 -2
- package/dist/chunks/{UserDashboardPage-ZMsx8LWw.js.map → UserDashboardPage-CjAx5OHh.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BRFowOFL.js → UserDetailPage-Bhpry9xq.js} +2 -2
- package/dist/chunks/{UserDetailPage-BRFowOFL.js.map → UserDetailPage-Bhpry9xq.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-CZyV-zsg.js → UserDetailPage-DUu2mA_n.js} +5 -5
- package/dist/chunks/{UserDetailPage-CZyV-zsg.js.map → UserDetailPage-DUu2mA_n.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-DzB_pELt.js → UserTicketDetailPage-DpFFjIso.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-DzB_pELt.js.map → UserTicketDetailPage-DpFFjIso.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-BstGk_BP.js → UserTicketDetailPage-YJvBWFEu.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-BstGk_BP.js.map → UserTicketDetailPage-YJvBWFEu.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-DTmhzttW.js → UsersGroupsPage-b2PTQX_m.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-DTmhzttW.js.map → UsersGroupsPage-b2PTQX_m.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-BygTv_kK.js → UsersGroupsPage-l33K3Nca.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-BygTv_kK.js.map → UsersGroupsPage-l33K3Nca.js.map} +1 -1
- package/dist/chunks/{UsersPage-TIqSHgHj.js → UsersPage-BjC5ZqTa.js} +2 -2
- package/dist/chunks/{UsersPage-TIqSHgHj.js.map → UsersPage-BjC5ZqTa.js.map} +1 -1
- package/dist/chunks/{UsersPage-DcwLyMAX.js → UsersPage-NsTukS8m.js} +2 -2
- package/dist/chunks/{UsersPage-DcwLyMAX.js.map → UsersPage-NsTukS8m.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-B6dsJzvH.js → accessRequestsApi-C2usKVGJ.js} +2 -2
- package/dist/chunks/{accessRequestsApi-B6dsJzvH.js.map → accessRequestsApi-C2usKVGJ.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-3FjMFbpa.js → accessRequestsApi-LuovcP6l.js} +2 -2
- package/dist/chunks/{accessRequestsApi-3FjMFbpa.js.map → accessRequestsApi-LuovcP6l.js.map} +1 -1
- package/dist/chunks/{aiApi-DXOdsoxr.js → aiApi-B03u3zUH.js} +2 -2
- package/dist/chunks/{aiApi-DXOdsoxr.js.map → aiApi-B03u3zUH.js.map} +1 -1
- package/dist/chunks/{aiApi-9G4wG_mT.js → aiApi-Cwg0B8PJ.js} +2 -2
- package/dist/chunks/{aiApi-9G4wG_mT.js.map → aiApi-Cwg0B8PJ.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-DhOd6idI.js → applicationAnalyticsApi-BobBdehV.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-DhOd6idI.js.map → applicationAnalyticsApi-BobBdehV.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-D0DEp9Y-.js → applicationAnalyticsApi-jCZhWKOx.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-D0DEp9Y-.js.map → applicationAnalyticsApi-jCZhWKOx.js.map} +1 -1
- package/dist/chunks/{groupsApi-Db8G2lLs.js → groupsApi-CoxnW9vH.js} +2 -2
- package/dist/chunks/{groupsApi-Db8G2lLs.js.map → groupsApi-CoxnW9vH.js.map} +1 -1
- package/dist/chunks/{groupsApi-lbxNsHFv.js → groupsApi-D2lFFcgu.js} +2 -2
- package/dist/chunks/{groupsApi-lbxNsHFv.js.map → groupsApi-D2lFFcgu.js.map} +1 -1
- package/dist/chunks/{index-xhRXN1Jq.js → index-B5U_Jp0-.js} +2 -2
- package/dist/chunks/{index-xhRXN1Jq.js.map → index-B5U_Jp0-.js.map} +1 -1
- package/dist/chunks/{index-Bn8HzILk.js → index-BDB_a-p7.js} +4 -4
- package/dist/chunks/{index-Bn8HzILk.js.map → index-BDB_a-p7.js.map} +1 -1
- package/dist/chunks/{index-DF93KQFR.js → index-BbHRJz-n.js} +2 -2
- package/dist/chunks/{index-DF93KQFR.js.map → index-BbHRJz-n.js.map} +1 -1
- package/dist/chunks/{index-DqbVFB1H.js → index-CI2WU5ZZ.js} +2 -2
- package/dist/chunks/{index-DqbVFB1H.js.map → index-CI2WU5ZZ.js.map} +1 -1
- package/dist/chunks/{index-DjC1u2hI.js → index-CLk9ClC2.js} +3 -3
- package/dist/chunks/{index-DjC1u2hI.js.map → index-CLk9ClC2.js.map} +1 -1
- package/dist/chunks/{index-CgtbaFf5.js → index-CmTKGOa_.js} +2 -2
- package/dist/chunks/{index-CgtbaFf5.js.map → index-CmTKGOa_.js.map} +1 -1
- package/dist/chunks/{index-DwqLhQ8S.js → index-D5oIr6PO.js} +2 -2
- package/dist/chunks/{index-DwqLhQ8S.js.map → index-D5oIr6PO.js.map} +1 -1
- package/dist/chunks/{index-CTGSmYvs.js → index-DC6TBJV_.js} +2 -2
- package/dist/chunks/{index-CTGSmYvs.js.map → index-DC6TBJV_.js.map} +1 -1
- package/dist/chunks/{index-CN2WRyg1.js → index-DN97bp_f.js} +1145 -1108
- package/dist/chunks/index-DN97bp_f.js.map +1 -0
- package/dist/chunks/{index-DUS-tunb.js → index-DRW5qV_L.js} +2 -2
- package/dist/chunks/{index-DUS-tunb.js.map → index-DRW5qV_L.js.map} +1 -1
- package/dist/chunks/{index-DLekpNSE.js → index-DcLZao1q.js} +2 -2
- package/dist/chunks/{index-DLekpNSE.js.map → index-DcLZao1q.js.map} +1 -1
- package/dist/chunks/{index-HsAOBno4.js → index-DcMOmGtX.js} +2 -2
- package/dist/chunks/{index-HsAOBno4.js.map → index-DcMOmGtX.js.map} +1 -1
- package/dist/chunks/{index-cAikSVW0.js → index-DnML-nfd.js} +10 -10
- package/dist/chunks/index-DnML-nfd.js.map +1 -0
- package/dist/chunks/{index-DEtq-xUL.js → index-Drd59qAP.js} +8 -8
- package/dist/chunks/{index-DEtq-xUL.js.map → index-Drd59qAP.js.map} +1 -1
- package/dist/chunks/{index-TiWOcC0g.js → index-EiIHjIgi.js} +2 -2
- package/dist/chunks/{index-TiWOcC0g.js.map → index-EiIHjIgi.js.map} +1 -1
- package/dist/chunks/{index-D0HS542b.js → index-axYz6ptj.js} +2 -2
- package/dist/chunks/{index-D0HS542b.js.map → index-axYz6ptj.js.map} +1 -1
- package/dist/chunks/{index-BI2dc1FS.js → index-lXrXnhFc.js} +2 -2
- package/dist/chunks/{index-BI2dc1FS.js.map → index-lXrXnhFc.js.map} +1 -1
- package/dist/chunks/{index-CUICSveU.js → index-rI-1r6c2.js} +2 -2
- package/dist/chunks/{index-CUICSveU.js.map → index-rI-1r6c2.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-__FKj6CN.js → tenantIconMap-B4wAYGWP.js} +2 -2
- package/dist/chunks/{tenantIconMap-__FKj6CN.js.map → tenantIconMap-B4wAYGWP.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-CHeS7oLt.js → tenantIconMap-Cfm15HwB.js} +2 -2
- package/dist/chunks/{tenantIconMap-CHeS7oLt.js.map → tenantIconMap-Cfm15HwB.js.map} +1 -1
- package/dist/chunks/{ticketingApi-DF4RwD_6.js → ticketingApi-CLMAPZDw.js} +2 -2
- package/dist/chunks/{ticketingApi-DF4RwD_6.js.map → ticketingApi-CLMAPZDw.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Cj239hYB.js → ticketingApi-CTap4NdE.js} +2 -2
- package/dist/chunks/{ticketingApi-Cj239hYB.js.map → ticketingApi-CTap4NdE.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CViOUwyF.js → useAccessRequests-CBpDkq9o.js} +2 -2
- package/dist/chunks/{useAccessRequests-CViOUwyF.js.map → useAccessRequests-CBpDkq9o.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CFam8zFR.js → useAccessRequests-Cj2-OoAW.js} +3 -3
- package/dist/chunks/{useAccessRequests-CFam8zFR.js.map → useAccessRequests-Cj2-OoAW.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-CslSQeBJ.js → useUserAccessRequests-C6l2VMe1.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-CslSQeBJ.js.map → useUserAccessRequests-C6l2VMe1.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-B-Cs6NX1.js → useUserAccessRequests-Ds3K-ENU.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-B-Cs6NX1.js.map → useUserAccessRequests-Ds3K-ENU.js.map} +1 -1
- package/dist/components/routing/DynamicRouter.d.ts.map +1 -1
- package/dist/contexts/AuthContext.d.ts.map +1 -1
- package/dist/contexts/NavigationContext.d.ts.map +1 -1
- package/dist/extensions/PageRegistry.d.ts +2 -0
- package/dist/extensions/PageRegistry.d.ts.map +1 -1
- package/dist/services/api/adminApi/settings.d.ts +8 -3
- package/dist/services/api/adminApi/settings.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-CN2WRyg1.js.map +0 -1
- package/dist/chunks/index-cAikSVW0.js.map +0 -1
|
@@ -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-DN97bp_f.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-DpFFjIso.js.map
|
package/dist/chunks/{UserTicketDetailPage-DzB_pELt.js.map → UserTicketDetailPage-DpFFjIso.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserTicketDetailPage-
|
|
1
|
+
{"version":3,"file":"UserTicketDetailPage-DpFFjIso.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;"}
|
|
@@ -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-DnML-nfd.js");function i(){return e.jsx(t.TicketDetailView,{mode:"client"})}exports.UserTicketDetailPage=i;
|
|
2
|
+
//# sourceMappingURL=UserTicketDetailPage-YJvBWFEu.js.map
|
package/dist/chunks/{UserTicketDetailPage-BstGk_BP.js.map → UserTicketDetailPage-YJvBWFEu.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserTicketDetailPage-
|
|
1
|
+
{"version":3,"file":"UserTicketDetailPage-YJvBWFEu.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,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-DnML-nfd.js"),a=require("lucide-react"),h=require("./groupsApi-D2lFFcgu.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-b2PTQX_m.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersGroupsPage-DTmhzttW.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","e","Filter","Cloud","LayoutGrid","List","group","CornerDownRight","Shield","Building2","GitBranch","CloudOff","role","index","Trash2","ChevronUp","ChevronDown","member","Link","Check"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UsersGroupsPage-b2PTQX_m.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","e","Filter","Cloud","LayoutGrid","List","group","CornerDownRight","Shield","Building2","GitBranch","CloudOff","role","index","Trash2","ChevronUp","ChevronDown","member","Link","Check"],"mappings":"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"}
|
|
@@ -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-DN97bp_f.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-CoxnW9vH.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-l33K3Nca.js.map
|