@atlashub/smartstack 3.21.0 → 3.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js → AgentSkillsPage-BWQSCYl-.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-7si3Ng8e.js.map → AgentSkillsPage-BWQSCYl-.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js → AgentSkillsPage-IQcMnBaD.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-D0cD1QdM.js.map → AgentSkillsPage-IQcMnBaD.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js → AgentWorkloadPage-DqrjkvWL.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-H_7ze33H.js.map → AgentWorkloadPage-DqrjkvWL.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js → AgentWorkloadPage-w-HiyFYP.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-D4d86cdV.js.map → AgentWorkloadPage-w-HiyFYP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js → ApiCatalogDetailPage-D3L8Yf4G.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-2ktkRrCb.js.map → ApiCatalogDetailPage-D3L8Yf4G.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js → ApiCatalogDetailPage-MPT3Kz6H.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-BQ53xuwD.js.map → ApiCatalogDetailPage-MPT3Kz6H.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js → ApiCatalogPage-D4Hg3uiS.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BEqTDJz8.js.map → ApiCatalogPage-D4Hg3uiS.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js → ApiCatalogPage-DRg5Cz0r.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BBkWSLI8.js.map → ApiCatalogPage-DRg5Cz0r.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js → ApplicationDetailPage-Caizuyn2.js} +2 -2
- package/dist/chunks/{ApplicationDetailPage-BYJ2YMPq.js.map → ApplicationDetailPage-Caizuyn2.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js → ApplicationDetailPage-CuCW6aMB.js} +4 -4
- package/dist/chunks/{ApplicationDetailPage-D8-bf1as.js.map → ApplicationDetailPage-CuCW6aMB.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js → ApplicationsDashboardPage-B2MW8-Kc.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BBlLms2r.js.map → ApplicationsDashboardPage-B2MW8-Kc.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js → ApplicationsDashboardPage-BDIjFIYZ.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-DTWZxJJM.js.map → ApplicationsDashboardPage-BDIjFIYZ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js → ApplicationsGridPage-DV-FihKj.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-BQaMsK1K.js.map → ApplicationsGridPage-DV-FihKj.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js → ApplicationsGridPage-DXsTfXPI.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-DbVcvezt.js.map → ApplicationsGridPage-DXsTfXPI.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js → ApplicationsListPage--CGkyBuJ.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-DYKM2Yeo.js.map → ApplicationsListPage--CGkyBuJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js → ApplicationsListPage-JUX823bh.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-C91v2rZt.js.map → ApplicationsListPage-JUX823bh.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js → ApplicationsPage-6zgFye6w.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BCbgotIx.js.map → ApplicationsPage-6zgFye6w.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js → ApplicationsPage-CQPuuiO6.js} +4 -4
- package/dist/chunks/{ApplicationsPage-CW3-Hjlu.js.map → ApplicationsPage-CQPuuiO6.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js → AssignmentRulesPage-CFffeEbo.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-D8vfGDBN.js.map → AssignmentRulesPage-CFffeEbo.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js → AssignmentRulesPage-D78UeUId.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CxktlEMB.js.map → AssignmentRulesPage-D78UeUId.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js → AssignmentsPage-Cww2ifZF.js} +2 -2
- package/dist/chunks/{AssignmentsPage-DmfBYQAD.js.map → AssignmentsPage-Cww2ifZF.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js → AssignmentsPage-DE_QS2LO.js} +2 -2
- package/dist/chunks/{AssignmentsPage-sRCCBmRc.js.map → AssignmentsPage-DE_QS2LO.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js → AuthCallbackPage-CA2nO6DG.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-C7XiZxKb.js.map → AuthCallbackPage-CA2nO6DG.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js → AuthCallbackPage-CDUAoX-N.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BCe_bwJM.js.map → AuthCallbackPage-CDUAoX-N.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js → ConfirmEmailPage-BqsILAYH.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-BUfGSqxF.js.map → ConfirmEmailPage-BqsILAYH.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js → ConfirmEmailPage-INeHCuMB.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-Buj4x-rx.js.map → ConfirmEmailPage-INeHCuMB.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js → CreateSupportTicketPage-BWeuV2aU.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CKDX_HQm.js.map → CreateSupportTicketPage-BWeuV2aU.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js → CreateSupportTicketPage-OBwF4v7b.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-0LgY-_pu.js.map → CreateSupportTicketPage-OBwF4v7b.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZ80NGV.js → DashboardPage-CKHqWrdS.js} +3 -3
- package/dist/chunks/{DashboardPage-CUZ80NGV.js.map → DashboardPage-CKHqWrdS.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CaNOAstg.js → DashboardPage-COmc9b__.js} +3 -3
- package/dist/chunks/{DashboardPage-CaNOAstg.js.map → DashboardPage-COmc9b__.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B48_rQFi.js → DashboardPage-CfKZHiSj.js} +2 -2
- package/dist/chunks/{DashboardPage-B48_rQFi.js.map → DashboardPage-CfKZHiSj.js.map} +1 -1
- package/dist/chunks/{DashboardPage-CUZV1J9t.js → DashboardPage-CwEZZ3jx.js} +2 -2
- package/dist/chunks/{DashboardPage-CUZV1J9t.js.map → DashboardPage-CwEZZ3jx.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js → EscalationConfigPage--7lgZ0kJ.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CdzAbnGy.js.map → EscalationConfigPage--7lgZ0kJ.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js → EscalationConfigPage-DPyiBcqV.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-CYGIl_e6.js.map → EscalationConfigPage-DPyiBcqV.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js → ForceChangePasswordPage-BE-6umub.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-lRpkwcX7.js.map → ForceChangePasswordPage-BE-6umub.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js → ForceChangePasswordPage-CnsYoWmV.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CvmYAV3r.js.map → ForceChangePasswordPage-CnsYoWmV.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js → ForgotPasswordPage-CSq4DnFF.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-0u49E4Pw.js.map → ForgotPasswordPage-CSq4DnFF.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js → ForgotPasswordPage-DZLVolAC.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CxQUqKOm.js.map → ForgotPasswordPage-DZLVolAC.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js → GroupDetailPage-Bf9Wb_2j.js} +5 -5
- package/dist/chunks/{GroupDetailPage-DFBvVO1S.js.map → GroupDetailPage-Bf9Wb_2j.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js → GroupDetailPage-R-hf3rJ7.js} +2 -2
- package/dist/chunks/{GroupDetailPage-B2FkKrGG.js.map → GroupDetailPage-R-hf3rJ7.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js → MyAccessRequestsPage-BIisvWM6.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-C9IX4c0K.js.map → MyAccessRequestsPage-BIisvWM6.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js → MyAccessRequestsPage-BLSV7Tbx.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-D6pVULNM.js.map → MyAccessRequestsPage-BLSV7Tbx.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js → MyTenantsPage-D-7k9CP1.js} +3 -3
- package/dist/chunks/{MyTenantsPage-BEcYYdGR.js.map → MyTenantsPage-D-7k9CP1.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js → MyTenantsPage-DqGW6aDt.js} +2 -2
- package/dist/chunks/{MyTenantsPage-D9f85zjF.js.map → MyTenantsPage-DqGW6aDt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js → MyTicketsPage--DgDsnZA.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DJR8h6y1.js.map → MyTicketsPage--DgDsnZA.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js → MyTicketsPage-CqJ3Aqob.js} +2 -2
- package/dist/chunks/{MyTicketsPage-DiOUExKJ.js.map → MyTicketsPage-CqJ3Aqob.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js → NavigationAppsPage-Bebis_RT.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CeHbxfZw.js.map → NavigationAppsPage-Bebis_RT.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js → NavigationAppsPage-THNPOAjv.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-If7tmCFY.js.map → NavigationAppsPage-THNPOAjv.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-C29Lln5o.js → NotificationsPage-CAbNW_Cn.js} +2 -2
- package/dist/chunks/{NotificationsPage-C29Lln5o.js.map → NotificationsPage-CAbNW_Cn.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js → NotificationsPage-DxwizUhL.js} +2 -2
- package/dist/chunks/{NotificationsPage-BiaLRb0s.js.map → NotificationsPage-DxwizUhL.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js → OnboardingWizardPage-C6HlbJ3K.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-DQrBKNBq.js.map → OnboardingWizardPage-C6HlbJ3K.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js → OnboardingWizardPage-CyC2zONO.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-BQah4cI8.js.map → OnboardingWizardPage-CyC2zONO.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js → PermissionDetailPage-BDHiNgky.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Ckjdjvf9.js.map → PermissionDetailPage-BDHiNgky.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js → PermissionDetailPage-C5K17ydY.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-Dh8v7mGj.js.map → PermissionDetailPage-C5K17ydY.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js → PermissionsPage-COI5LJPo.js} +2 -2
- package/dist/chunks/{PermissionsPage-l0PnY-EE.js.map → PermissionsPage-COI5LJPo.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js → PermissionsPage-CkOwH2_d.js} +2 -2
- package/dist/chunks/{PermissionsPage-DLy9U3P3.js.map → PermissionsPage-CkOwH2_d.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js → PortalDashboardPage-CoEC4CmC.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DFBx38-x.js.map → PortalDashboardPage-CoEC4CmC.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js → PortalDashboardPage-DrYymEf-.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-rQYhrX0q.js.map → PortalDashboardPage-DrYymEf-.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js → PreferencesPage-CJRaU3ba.js} +2 -2
- package/dist/chunks/{PreferencesPage-BBu8yZQB.js.map → PreferencesPage-CJRaU3ba.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-B81MsNV1.js → PreferencesPage-Cqr9mAab.js} +2 -2
- package/dist/chunks/{PreferencesPage-B81MsNV1.js.map → PreferencesPage-Cqr9mAab.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DDrl10zj.js → ProfilePage-BZVpg6-l.js} +2 -2
- package/dist/chunks/{ProfilePage-DDrl10zj.js.map → ProfilePage-BZVpg6-l.js.map} +1 -1
- package/dist/chunks/{ProfilePage-DPoXwdnc.js → ProfilePage-Cu_FITeL.js} +2 -2
- package/dist/chunks/{ProfilePage-DPoXwdnc.js.map → ProfilePage-Cu_FITeL.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js → ReferencesManagementPage-DUlVk9Ps.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-eFsKjIEK.js.map → ReferencesManagementPage-DUlVk9Ps.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js → ReferencesManagementPage-ZCuYtqd7.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DhVsuElE.js.map → ReferencesManagementPage-ZCuYtqd7.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CiQib3-6.js → RegisterPage-C4xmVwh9.js} +2 -2
- package/dist/chunks/{RegisterPage-CiQib3-6.js.map → RegisterPage-C4xmVwh9.js.map} +1 -1
- package/dist/chunks/{RegisterPage-bXCcJD88.js → RegisterPage-DGyzoIHT.js} +2 -2
- package/dist/chunks/{RegisterPage-bXCcJD88.js.map → RegisterPage-DGyzoIHT.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js → ResetPasswordPage-DqDD6VPR.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-Dqiahhnj.js.map → ResetPasswordPage-DqDD6VPR.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js → ResetPasswordPage-Glu-aeqv.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-CubPG3yv.js.map → ResetPasswordPage-Glu-aeqv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js → ResolutionModal-CxjANAOP.js} +2 -2
- package/dist/chunks/{ResolutionModal-Bg7XZmR1.js.map → ResolutionModal-CxjANAOP.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js → ResolutionModal-Duat18qV.js} +2 -2
- package/dist/chunks/{ResolutionModal-DqRk_T0n.js.map → ResolutionModal-Duat18qV.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js → RoleDetailPage-BQffUSnt.js} +3 -3
- package/dist/chunks/{RoleDetailPage-Blau6_4c.js.map → RoleDetailPage-BQffUSnt.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js → RoleDetailPage-JTm5lD1_.js} +2 -2
- package/dist/chunks/{RoleDetailPage-CiRVxxIP.js.map → RoleDetailPage-JTm5lD1_.js.map} +1 -1
- package/dist/chunks/{RolesPage-Pm-RN3lP.js → RolesPage-B9rRzciI.js} +2 -2
- package/dist/chunks/{RolesPage-Pm-RN3lP.js.map → RolesPage-B9rRzciI.js.map} +1 -1
- package/dist/chunks/{RolesPage-Cb8joqdJ.js → RolesPage-BN8_zMOC.js} +2 -2
- package/dist/chunks/{RolesPage-Cb8joqdJ.js.map → RolesPage-BN8_zMOC.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-B86McKM6.js → SlaConfigPage-B7kZNig4.js} +2 -2
- package/dist/chunks/{SlaConfigPage-B86McKM6.js.map → SlaConfigPage-B7kZNig4.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js → SlaConfigPage-okvZfA_K.js} +2 -2
- package/dist/chunks/{SlaConfigPage-BY7gvYU6.js.map → SlaConfigPage-okvZfA_K.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js → SupportPermissionsPage-DGAPqJbl.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-BYxcLMSd.js.map → SupportPermissionsPage-DGAPqJbl.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js → SupportPermissionsPage-Dg_wLOme.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-MXqXNJIZ.js.map → SupportPermissionsPage-Dg_wLOme.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-BDguJ401.js → TemplatesPage-DT9fhlAU.js} +2 -2
- package/dist/chunks/{TemplatesPage-BDguJ401.js.map → TemplatesPage-DT9fhlAU.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DdnGgioU.js → TemplatesPage-DiEk538p.js} +2 -2
- package/dist/chunks/{TemplatesPage-DdnGgioU.js.map → TemplatesPage-DiEk538p.js.map} +1 -1
- package/dist/chunks/{TenantCard-ffwWsgFQ.js → TenantCard-BbSYk9_Z.js} +2 -2
- package/dist/chunks/{TenantCard-ffwWsgFQ.js.map → TenantCard-BbSYk9_Z.js.map} +1 -1
- package/dist/chunks/{TenantCard-CUjb6og9.js → TenantCard-CEkiKxcZ.js} +2 -2
- package/dist/chunks/{TenantCard-CUjb6og9.js.map → TenantCard-CEkiKxcZ.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js → TenantScopeSelector-BWfYxvEa.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Dz7i1I43.js.map → TenantScopeSelector-BWfYxvEa.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js → TenantScopeSelector-D-BKgQPV.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-Cym_Zyps.js.map → TenantScopeSelector-D-BKgQPV.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js → TicketDetailPage-C1mNS9Up.js} +2 -2
- package/dist/chunks/{TicketDetailPage-GOh9GX7E.js.map → TicketDetailPage-C1mNS9Up.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js → TicketDetailPage-ieVDRh42.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Du8WMyqf.js.map → TicketDetailPage-ieVDRh42.js.map} +1 -1
- package/dist/chunks/{TicketsPage-Bqd6moQy.js → TicketsPage-CnuWsnIW.js} +2 -2
- package/dist/chunks/{TicketsPage-Bqd6moQy.js.map → TicketsPage-CnuWsnIW.js.map} +1 -1
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js → TicketsPage-jjyY15_D.js} +2 -2
- package/dist/chunks/{TicketsPage-WdU4Bb7M.js.map → TicketsPage-jjyY15_D.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js → UserCreateTicketPage-B8Tvf-ag.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-Cm1emgwR.js.map → UserCreateTicketPage-B8Tvf-ag.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js → UserCreateTicketPage-DnOsDlfO.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-BPw-5Y_D.js.map → UserCreateTicketPage-DnOsDlfO.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js → UserDashboardPage-BrtkJ-NB.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BP5WeXPS.js.map → UserDashboardPage-BrtkJ-NB.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js → UserDashboardPage-KLB5CQP5.js} +2 -2
- package/dist/chunks/{UserDashboardPage-B53C8fUq.js.map → UserDashboardPage-KLB5CQP5.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-B110bmGX.js → UserDetailPage-U7smBQoF.js} +5 -5
- package/dist/chunks/{UserDetailPage-B110bmGX.js.map → UserDetailPage-U7smBQoF.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-CV2VCE46.js → UserDetailPage-_J6lcKAU.js} +2 -2
- package/dist/chunks/{UserDetailPage-CV2VCE46.js.map → UserDetailPage-_J6lcKAU.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js → UserTicketDetailPage-CWoYQgH-.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CCNJON1V.js.map → UserTicketDetailPage-CWoYQgH-.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js → UserTicketDetailPage-DkufSlvZ.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-V0mLXrox.js.map → UserTicketDetailPage-DkufSlvZ.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js → UsersGroupsPage-C38s2-Rq.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CmdaU-z-.js.map → UsersGroupsPage-C38s2-Rq.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js → UsersGroupsPage-Dq3rAteo.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-BgfAMgEP.js.map → UsersGroupsPage-Dq3rAteo.js.map} +1 -1
- package/dist/chunks/{UsersPage-Bg7033pp.js → UsersPage-B5C5KEUR.js} +2 -2
- package/dist/chunks/{UsersPage-Bg7033pp.js.map → UsersPage-B5C5KEUR.js.map} +1 -1
- package/dist/chunks/{UsersPage-TYAfwPY1.js → UsersPage-CXC9Hvq6.js} +2 -2
- package/dist/chunks/{UsersPage-TYAfwPY1.js.map → UsersPage-CXC9Hvq6.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js → accessRequestsApi-B-4TJ5_U.js} +2 -2
- package/dist/chunks/{accessRequestsApi-DZeDvzwv.js.map → accessRequestsApi-B-4TJ5_U.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js → accessRequestsApi-DZSfThpd.js} +2 -2
- package/dist/chunks/{accessRequestsApi-ZXFPCid2.js.map → accessRequestsApi-DZSfThpd.js.map} +1 -1
- package/dist/chunks/{aiApi-CsH8DXgs.js → aiApi-B20Teu2v.js} +2 -2
- package/dist/chunks/{aiApi-CsH8DXgs.js.map → aiApi-B20Teu2v.js.map} +1 -1
- package/dist/chunks/{aiApi-CVPzFTXa.js → aiApi-DMGz-RPM.js} +2 -2
- package/dist/chunks/{aiApi-CVPzFTXa.js.map → aiApi-DMGz-RPM.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js → applicationAnalyticsApi-Bwa75Fzd.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-B8AhFYLr.js.map → applicationAnalyticsApi-Bwa75Fzd.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js → applicationAnalyticsApi-CLBqRPfN.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-Ce_1qOk-.js.map → applicationAnalyticsApi-CLBqRPfN.js.map} +1 -1
- package/dist/chunks/{groupsApi-BgCk2fsp.js → groupsApi-QzXI-5xu.js} +2 -2
- package/dist/chunks/{groupsApi-BgCk2fsp.js.map → groupsApi-QzXI-5xu.js.map} +1 -1
- package/dist/chunks/{groupsApi-BIbG665N.js → groupsApi-hB9kSWEd.js} +2 -2
- package/dist/chunks/{groupsApi-BIbG665N.js.map → groupsApi-hB9kSWEd.js.map} +1 -1
- package/dist/chunks/{index-Cb3LotuT.js → index--NGcBYUu.js} +3 -3
- package/dist/chunks/{index-Cb3LotuT.js.map → index--NGcBYUu.js.map} +1 -1
- package/dist/chunks/{index-C33zcyF4.js → index--aPwOFjF.js} +2 -2
- package/dist/chunks/{index-C33zcyF4.js.map → index--aPwOFjF.js.map} +1 -1
- package/dist/chunks/{index-sMr9qND_.js → index-0VrOtwP0.js} +2 -2
- package/dist/chunks/{index-sMr9qND_.js.map → index-0VrOtwP0.js.map} +1 -1
- package/dist/chunks/{index-DDKetfKq.js → index-37U271aw.js} +2 -2
- package/dist/chunks/{index-DDKetfKq.js.map → index-37U271aw.js.map} +1 -1
- package/dist/chunks/{index-B9fS7ir6.js → index-B7qZTuQ-.js} +2 -2
- package/dist/chunks/{index-B9fS7ir6.js.map → index-B7qZTuQ-.js.map} +1 -1
- package/dist/chunks/{index-CdjBY7L8.js → index-Bedzmqr-.js} +2 -2
- package/dist/chunks/{index-CdjBY7L8.js.map → index-Bedzmqr-.js.map} +1 -1
- package/dist/chunks/{index-CHG_O1fS.js → index-Betxo5g5.js} +2 -2
- package/dist/chunks/{index-CHG_O1fS.js.map → index-Betxo5g5.js.map} +1 -1
- package/dist/chunks/{index-jiGu-H8x.js → index-BmaJz475.js} +2 -2
- package/dist/chunks/{index-jiGu-H8x.js.map → index-BmaJz475.js.map} +1 -1
- package/dist/chunks/{index-C53JoVNk.js → index-Buhqag3v.js} +2 -2
- package/dist/chunks/{index-C53JoVNk.js.map → index-Buhqag3v.js.map} +1 -1
- package/dist/chunks/{index-DO0Rw7hX.js → index-C3VxlfKq.js} +2 -2
- package/dist/chunks/{index-DO0Rw7hX.js.map → index-C3VxlfKq.js.map} +1 -1
- package/dist/chunks/{index-CSQ60fpG.js → index-CgpRo8Oe.js} +2 -2
- package/dist/chunks/{index-CSQ60fpG.js.map → index-CgpRo8Oe.js.map} +1 -1
- package/dist/chunks/{index-B-e-ELsf.js → index-DOY0w8Iu.js} +8 -8
- package/dist/chunks/{index-B-e-ELsf.js.map → index-DOY0w8Iu.js.map} +1 -1
- package/dist/chunks/{index-D2REDIRX.js → index-DwuvIOrQ.js} +2 -2
- package/dist/chunks/{index-D2REDIRX.js.map → index-DwuvIOrQ.js.map} +1 -1
- package/dist/chunks/{index-DCcl7Qof.js → index-DzedSLdI.js} +2 -2
- package/dist/chunks/{index-DCcl7Qof.js.map → index-DzedSLdI.js.map} +1 -1
- package/dist/chunks/{index-2wUhd9Lu.js → index-IgLVXPg8.js} +10 -10
- package/dist/chunks/index-IgLVXPg8.js.map +1 -0
- package/dist/chunks/{index-CwSaRXXg.js → index-lpIzhufD.js} +1916 -1900
- package/dist/chunks/index-lpIzhufD.js.map +1 -0
- package/dist/chunks/{index-Cuwn2q-f.js → index-mLUKwbGl.js} +4 -4
- package/dist/chunks/{index-Cuwn2q-f.js.map → index-mLUKwbGl.js.map} +1 -1
- package/dist/chunks/{index-B0mk2tNY.js → index-tO6MMIFB.js} +2 -2
- package/dist/chunks/{index-B0mk2tNY.js.map → index-tO6MMIFB.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js → tenantIconMap-BQD9byc8.js} +2 -2
- package/dist/chunks/{tenantIconMap-BpNANQ5s.js.map → tenantIconMap-BQD9byc8.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js → tenantIconMap-CTMuSt18.js} +2 -2
- package/dist/chunks/{tenantIconMap-DtdUgvJO.js.map → tenantIconMap-CTMuSt18.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js → ticketingApi-BNIdox5t.js} +2 -2
- package/dist/chunks/{ticketingApi-Bu4rKwLl.js.map → ticketingApi-BNIdox5t.js.map} +1 -1
- package/dist/chunks/{ticketingApi-r4Avm9iS.js → ticketingApi-J0vC_t7r.js} +2 -2
- package/dist/chunks/{ticketingApi-r4Avm9iS.js.map → ticketingApi-J0vC_t7r.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-B9bF4swg.js → useAccessRequests-DCNNLnxk.js} +3 -3
- package/dist/chunks/{useAccessRequests-B9bF4swg.js.map → useAccessRequests-DCNNLnxk.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js → useAccessRequests-DT7X4FAK.js} +2 -2
- package/dist/chunks/{useAccessRequests-JyPUX3Om.js.map → useAccessRequests-DT7X4FAK.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js → useUserAccessRequests-BYbmG4c7.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-DjPQenC2.js.map → useUserAccessRequests-BYbmG4c7.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js → useUserAccessRequests-CylKxRN6.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BB6FHW14.js.map → useUserAccessRequests-CylKxRN6.js.map} +1 -1
- package/dist/hooks/useCollapsibleState.d.ts +5 -2
- package/dist/hooks/useCollapsibleState.d.ts.map +1 -1
- package/dist/i18n/config.d.ts +1 -0
- package/dist/i18n/config.d.ts.map +1 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/dist/utils/permissions.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/index-2wUhd9Lu.js.map +0 -1
- package/dist/chunks/index-CwSaRXXg.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UsersPage-TYAfwPY1.js","sources":["../../src/hooks/useRestrictedModuleCheck.ts","../../src/components/ui/RestrictedModuleBanner.tsx","../../src/pages/platform/administration/users/UsersPage.tsx"],"sourcesContent":["import { useTenant } from '@/contexts/TenantContext';\r\nimport { useNavigation } from '@/contexts/NavigationContext';\r\n\r\n/**\r\n * Hook to check if Super Admin is viewing a module the current tenant cannot access.\r\n *\r\n * Logic:\r\n * - currentModuleCode: parsed from URL (always available)\r\n * - getCurrentModule(): returns the module IF it's in the tenant's filtered menu\r\n * - If currentModuleCode exists BUT getCurrentModule() returns undefined\r\n * → The module is restricted for this tenant\r\n */\r\nexport function useRestrictedModuleCheck(): {\n isRestrictedModule: boolean;\n tenantName: string | null;\n} {\r\n const { currentTenant, hasGlobalRoles, isGlobalView } = useTenant();\r\n const { currentModuleCode, getCurrentModule, isLoading, menu } = useNavigation();\r\n\r\n // Only applies when:\r\n // 1. User has global roles (Super Admin)\r\n // 2. User is in tenant context (not global view)\r\n // 3. There's a current module in the URL\r\n // 4. Menu is loaded\r\n const shouldCheck = hasGlobalRoles && !isGlobalView && currentTenant && currentModuleCode && !isLoading && menu;\r\n\r\n if (!shouldCheck) {\r\n return { isRestrictedModule: false, tenantName: null };\r\n }\r\n\r\n const moduleInMenu = getCurrentModule();\r\n\r\n return {\r\n isRestrictedModule: !moduleInMenu,\r\n tenantName: currentTenant?.name || null,\r\n };\r\n}\r\n","import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { AlertTriangle } from 'lucide-react';\r\nimport { useRestrictedModuleCheck } from '@/hooks/useRestrictedModuleCheck';\r\n\r\n/**\r\n * Warning banner displayed when Super Admin views a module that the current\r\n * tenant does not have access to.\r\n *\r\n * Uses amber warning styling to clearly indicate the restricted state.\r\n */\r\nexport function RestrictedModuleBanner(): ReactElement | null {\r\n const { t } = useTranslation('admin');\r\n const { isRestrictedModule, tenantName } = useRestrictedModuleCheck();\r\n\r\n if (!isRestrictedModule) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n className=\"flex items-center gap-3 px-4 py-2.5 border bg-amber-500/10 border-amber-500/20\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n {/* Warning Icon */}\r\n <div\r\n className=\"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-amber-500/10\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <AlertTriangle className=\"w-4 h-4 text-amber-600\" />\r\n </div>\r\n\r\n {/* Warning Text */}\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"font-medium text-amber-700\">\r\n {t('scope.banner.restrictedModule', 'Module restreint')}\r\n </span>\r\n <p className=\"text-xs text-amber-600/70 mt-0.5\">\r\n {t(\r\n 'scope.banner.restrictedModuleDesc',\r\n 'Le tenant \"{{tenantName}}\" n\\'a pas accès à ce module. Données affichées grâce à vos privilèges administrateur.',\r\n { tenantName }\r\n )}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate, useSearchParams } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\nimport { Plus, Search, Edit2, Trash2, UserCheck, UserX, X, Loader2, Eye, Mail, Shield, Filter, Cloud, ChevronDown, ArrowUpDown, RotateCcw, Users } from 'lucide-react';\r\nimport { adminApi, type UserListDto, type RoleListDto, type CreateUserRequest, type UpdateUserRequest } from '@/services/api/adminApi';\r\nimport { ViewToggle, Avatar, StatusBadge, RoleBadge, KanbanColumn, KanbanCard, Pagination, type ViewMode } from '@/components/ui/DataView';\r\nimport { Slot, useTableColumnExtensions } from '@/extensions';\r\nimport { RestrictedModuleBanner } from '@/components/ui/RestrictedModuleBanner';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\n\r\n// Debounce hook for search\r\nfunction useDebounce<T>(value: T, delay: number): T {\r\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\r\n useEffect(() => {\r\n const handler = setTimeout(() => setDebouncedValue(value), delay);\r\n return () => clearTimeout(handler);\r\n }, [value, delay]);\r\n return debouncedValue;\r\n}\r\n\r\n// Filter state type\r\ninterface FilterState {\r\n search: string;\r\n status: 'all' | 'active' | 'inactive';\r\n roleId: string;\r\n source: 'all' | 'entra' | 'local';\r\n userType: string;\r\n sortBy: string;\r\n sortDesc: boolean;\r\n}\r\n\r\nconst defaultFilters: FilterState = {\r\n search: '',\r\n status: 'all',\r\n roleId: '',\r\n source: 'all',\r\n userType: '',\r\n sortBy: 'lastname',\r\n sortDesc: false,\r\n};\r\n\r\nexport function UsersPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n const extensionColumns = useTableColumnExtensions('users');\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const { hasPermission } = useAuth();\r\n\r\n // Permission checks for action buttons\r\n const canCreate = hasPermission('administration.users.create');\r\n const canUpdate = hasPermission('administration.users.update');\r\n const canDelete = hasPermission('administration.users.delete');\r\n\r\n // Initialize filters from URL params\r\n const initialFilters: FilterState = useMemo(() => ({\r\n search: searchParams.get('search') || '',\r\n status: (searchParams.get('status') as FilterState['status']) || 'all',\r\n roleId: searchParams.get('roleId') || '',\r\n source: (searchParams.get('source') as FilterState['source']) || 'all',\r\n userType: searchParams.get('userType') || '',\r\n sortBy: searchParams.get('sortBy') || 'lastname',\r\n sortDesc: searchParams.get('sortDesc') === 'true',\r\n }), []);\r\n\r\n const [users, setUsers] = useState<UserListDto[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [filters, setFilters] = useState<FilterState>(initialFilters);\r\n const [showFilters, setShowFilters] = useState(false);\r\n const [page, setPage] = useState(parseInt(searchParams.get('page') || '1'));\r\n const [totalPages, setTotalPages] = useState(1);\r\n const [totalCount, setTotalCount] = useState(0);\r\n const [showModal, setShowModal] = useState(false);\r\n const [editingUser, setEditingUser] = useState<UserListDto | null>(null);\r\n const [formData, setFormData] = useState<CreateUserRequest>({\r\n email: '',\r\n password: '',\r\n firstName: '',\r\n lastName: '',\r\n roleIds: []\r\n });\r\n const [saving, setSaving] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('table');\r\n\r\n // Sync filters from URL when URL changes (e.g., browser back/forward navigation)\r\n useEffect(() => {\r\n const urlFilters: FilterState = {\r\n search: searchParams.get('search') || '',\r\n status: (searchParams.get('status') as FilterState['status']) || 'all',\r\n roleId: searchParams.get('roleId') || '',\r\n source: (searchParams.get('source') as FilterState['source']) || 'all',\r\n userType: searchParams.get('userType') || '',\r\n sortBy: searchParams.get('sortBy') || 'lastname',\r\n sortDesc: searchParams.get('sortDesc') === 'true',\r\n };\r\n // Only update if different to avoid loops\r\n if (JSON.stringify(urlFilters) !== JSON.stringify(filters)) {\r\n setFilters(urlFilters);\r\n }\r\n const urlPage = parseInt(searchParams.get('page') || '1');\r\n if (urlPage !== page) {\r\n setPage(urlPage);\r\n }\r\n }, [searchParams]); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n // Debounce search input\r\n const debouncedSearch = useDebounce(filters.search, 300);\r\n\r\n // Count active filters (excluding search and default sort)\r\n const activeFilterCount = useMemo(() => {\r\n let count = 0;\r\n if (filters.status !== 'all') count++;\r\n if (filters.roleId) count++;\r\n if (filters.source !== 'all') count++;\r\n if (filters.userType) count++;\r\n return count;\r\n }, [filters]);\r\n\r\n const loadUsers = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.users.getAll({\r\n page,\r\n pageSize: 20,\r\n search: debouncedSearch || undefined,\r\n isActive: filters.status === 'all' ? undefined : filters.status === 'active',\r\n entraOnly: filters.source === 'entra' ? true : undefined,\r\n roleId: filters.roleId || undefined,\r\n userType: filters.userType || undefined,\r\n sortBy: filters.sortBy || undefined,\r\n sortDesc: filters.sortDesc,\r\n });\r\n setUsers(result.items);\r\n setTotalPages(result.totalPages);\r\n setTotalCount(result.totalCount);\r\n } catch (err) {\r\n console.error('Failed to load users:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n // TENANT ISOLATION: Re-fetch when tenant changes (currentTenant or isGlobalView)\r\n }, [page, debouncedSearch, filters.status, filters.source, filters.roleId, filters.userType, filters.sortBy, filters.sortDesc, currentTenant?.id, isGlobalView]);\r\n\r\n // Update URL params when filters change\r\n useEffect(() => {\r\n const params = new URLSearchParams();\r\n if (filters.search) params.set('search', filters.search);\r\n if (filters.status !== 'all') params.set('status', filters.status);\r\n if (filters.roleId) params.set('roleId', filters.roleId);\r\n if (filters.source !== 'all') params.set('source', filters.source);\r\n if (filters.userType) params.set('userType', filters.userType);\r\n if (filters.sortBy !== 'lastname') params.set('sortBy', filters.sortBy);\r\n if (filters.sortDesc) params.set('sortDesc', 'true');\r\n if (page > 1) params.set('page', page.toString());\r\n setSearchParams(params, { replace: true });\r\n }, [filters, page, setSearchParams]);\r\n\r\n const loadRoles = async () => {\r\n try {\r\n const result = await adminApi.roles.getAll();\r\n setRoles(result);\r\n } catch (err) {\r\n console.error('Failed to load roles:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadUsers();\r\n }, [loadUsers]);\r\n\r\n useEffect(() => {\r\n loadRoles();\r\n }, []);\r\n\r\n const handleResetFilters = () => {\r\n setFilters(defaultFilters);\r\n setPage(1);\r\n };\r\n\r\n const updateFilter = <K extends keyof FilterState>(key: K, value: FilterState[K]) => {\r\n setFilters(prev => ({ ...prev, [key]: value }));\r\n setPage(1);\r\n };\r\n\r\n const openCreateModal = () => {\r\n setEditingUser(null);\r\n setFormData({ email: '', password: '', firstName: '', lastName: '', roleIds: [] });\r\n setError(null);\r\n setShowModal(true);\r\n };\r\n\r\n const openEditModal = async (user: UserListDto) => {\r\n try {\r\n const detail = await adminApi.users.getById(user.id);\r\n setEditingUser(user);\r\n setFormData({\r\n email: detail.email,\r\n password: '',\r\n firstName: detail.firstName,\r\n lastName: detail.lastName,\r\n roleIds: detail.roles.map(r => r.id)\r\n });\r\n setError(null);\r\n setShowModal(true);\r\n } catch (err) {\r\n console.error('Failed to load user details:', err);\r\n }\r\n };\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSaving(true);\r\n setError(null);\r\n\r\n try {\r\n if (editingUser) {\r\n const updateData: UpdateUserRequest = {\r\n email: formData.email !== editingUser.email ? formData.email : undefined,\r\n firstName: formData.firstName,\r\n lastName: formData.lastName,\r\n roleIds: formData.roleIds\r\n };\r\n await adminApi.users.update(editingUser.id, updateData);\r\n } else {\r\n await adminApi.users.create(formData);\r\n }\r\n setShowModal(false);\r\n loadUsers();\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : 'An error occurred';\r\n setError(message);\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleToggleStatus = async (user: UserListDto, e?: React.MouseEvent) => {\r\n e?.stopPropagation();\r\n try {\r\n if (user.isActive) {\r\n await adminApi.users.deactivate(user.id);\r\n } else {\r\n await adminApi.users.activate(user.id);\r\n }\r\n loadUsers();\r\n } catch (err) {\r\n console.error('Failed to toggle user status:', err);\r\n }\r\n };\r\n\r\n const handleDelete = async (user: UserListDto, e?: React.MouseEvent) => {\r\n e?.stopPropagation();\r\n if (!confirm(t('users.confirmDelete', { name: user.fullName }))) return;\r\n\r\n try {\r\n await adminApi.users.delete(user.id);\r\n loadUsers();\r\n } catch (err) {\r\n console.error('Failed to delete user:', err);\r\n }\r\n };\r\n\r\n const handleRoleToggle = (roleId: string) => {\r\n setFormData(prev => ({\r\n ...prev,\r\n roleIds: prev.roleIds?.includes(roleId)\r\n ? prev.roleIds.filter(id => id !== roleId)\r\n : [...(prev.roleIds || []), roleId]\r\n }));\r\n };\r\n\r\n // Grouper les utilisateurs par statut pour le Kanban\r\n const activeUsers = users.filter(u => u.isActive);\r\n const inactiveUsers = users.filter(u => !u.isActive);\r\n const onlineCount = Math.floor(activeUsers.length * 0.3); // Simulation\r\n\r\n const getToggleStatusButtonClass = (canManage: boolean, isActive: boolean): string => {\r\n if (!canManage) return 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]';\r\n return isActive\r\n ? 'text-[var(--text-tertiary)] hover:text-[var(--warning-text)] hover:bg-[var(--warning-bg)]'\r\n : 'text-[var(--text-tertiary)] hover:text-[var(--success-text)] hover:bg-[var(--success-bg)]';\r\n };\r\n\r\n const getToggleStatusTitle = (canManage: boolean, isActive: boolean, t: TFunction): string => {\r\n if (!canManage) return t('common.noPermission', 'Permission insuffisante');\r\n return isActive ? t('users.deactivate') : t('users.activate');\r\n };\r\n\r\n const getEditButtonClass = (canManage: boolean): string => {\r\n if (!canManage) return 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]';\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]';\r\n };\r\n\r\n const getEditButtonTitle = (canManage: boolean, t: TFunction): string => {\r\n if (!canManage) return t('common.noPermission', 'Permission insuffisante');\r\n return t('common.edit');\r\n };\r\n\r\n const getDeleteButtonClass = (canManage: boolean): string => {\r\n if (!canManage) return 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]';\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]';\r\n };\r\n\r\n const getDeleteButtonTitle = (canManage: boolean, t: TFunction): string => {\r\n if (!canManage) return t('common.noPermission', 'Permission insuffisante');\r\n return t('common.delete');\r\n };\r\n\r\n const getMembershipSourceBadge = (membershipSource: string) => {\r\n const colorMap: Record<string, string> = {\r\n Direct: 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300',\r\n Group: 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300',\r\n Both: 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300'\r\n };\r\n const labelMap: Record<string, string> = {\r\n Direct: t('users.membershipDirect', 'Direct'),\r\n Group: t('users.membershipGroup', 'Via groupe'),\r\n Both: t('users.membershipBoth', 'Mixte')\r\n };\r\n return { color: colorMap[membershipSource] || '', label: labelMap[membershipSource] || '' };\r\n };\r\n\r\n // Render functions for each view\r\n const renderTableView = () => (\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"w-12 px-4 py-3\">\r\n <input type=\"checkbox\" className=\"w-4 h-4 rounded border-[var(--border-color)]\" />\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('users.columns.name')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('users.columns.email')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('users.columns.role')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('users.columns.status')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell\">{t('users.columns.source', 'Source')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell\">{t('users.columns.group', 'Groupe')}</th>\r\n {/* Extension columns headers */}\r\n {extensionColumns.map(col => (\r\n <th key={col.key} className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell\" style={col.width ? { width: col.width } : undefined}>\r\n {col.label}\r\n </th>\r\n ))}\r\n <th className=\"w-32 px-4 py-3\"></th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={8} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center gap-3\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-primary-500\" />\r\n <span className=\"text-sm text-[var(--text-secondary)]\">Chargement...</span>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && users.length === 0 && (\r\n <tr>\r\n <td colSpan={8} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center gap-3\">\r\n <div className=\"w-16 h-16 rounded-full bg-[var(--bg-secondary)] flex items-center justify-center\">\r\n <Search className=\"w-8 h-8 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('users.noUsers')}</span>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && users.length > 0 && (\r\n users.map(user => (\r\n <tr\r\n key={user.id}\r\n className=\"group hover:bg-[var(--bg-hover)] transition-all cursor-pointer\"\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n >\r\n <td className=\"px-4 py-3\" onClick={e => e.stopPropagation()}>\r\n <input type=\"checkbox\" className=\"w-4 h-4 rounded border-[var(--border-color)]\" />\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-2.5 h-2.5 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <p className=\"font-medium text-[var(--text-primary)] group-hover:text-primary-600 transition-colors truncate\">\r\n {user.fullName}\r\n </p>\r\n {user.entraObjectId && (\r\n <span className=\"hidden sm:inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400\">\r\n <Cloud className=\"w-2.5 h-2.5\" />\r\n AAD\r\n </span>\r\n )}\r\n </div>\r\n <p className=\"text-sm text-[var(--text-tertiary)] truncate md:hidden flex items-center gap-1\">\r\n <Mail className=\"w-3 h-3\" />\r\n {user.email}\r\n </p>\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <div className=\"flex items-center gap-2 text-[var(--text-secondary)]\">\r\n <Mail className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <span className=\"truncate\">{user.email}</span>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden lg:table-cell\">\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {user.roles.length > 0 ? user.roles.map((role, index) => (\r\n <RoleBadge\r\n key={`${role}-${index}`}\r\n role={role}\r\n variant={role.toLowerCase().includes('admin') ? 'accent' : 'default'}\r\n icon={<Shield className=\"w-3 h-3\" />}\r\n />\r\n )) : (\r\n <span className=\"text-sm text-[var(--text-tertiary)] italic\">Aucun rôle</span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <StatusBadge\r\n status={user.isActive ? 'active' : 'inactive'}\r\n label={user.isActive ? t('users.status.active') : t('users.status.inactive')}\r\n />\r\n </td>\r\n <td className=\"px-4 py-3 hidden xl:table-cell\">\r\n {(() => {\r\n const { color, label } = getMembershipSourceBadge(user.membershipSource);\r\n return <span className={`inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium ${color}`}>{label}</span>;\r\n })()}\r\n </td>\r\n <td className=\"px-4 py-3 hidden xl:table-cell\">\r\n {user.primaryGroupId ? (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n navigate(`/administration/groups/${user.primaryGroupId}`);\r\n }}\r\n className=\"inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs font-medium bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-primary-600 transition-colors\"\r\n >\r\n <Users className=\"w-3 h-3\" />\r\n {user.primaryGroupName}\r\n </button>\r\n ) : (\r\n <span className=\"text-[var(--text-tertiary)]\">—</span>\r\n )}\r\n </td>\r\n {/* Extension columns data */}\r\n {extensionColumns.map(col => (\r\n <td key={col.key} className=\"px-4 py-3 hidden xl:table-cell text-[var(--text-secondary)]\">\r\n {col.render(user as unknown as Record<string, unknown>, { tableId: 'users', rowIndex: users.indexOf(user) })}\r\n </td>\r\n ))}\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center justify-end gap-1\" onClick={e => e.stopPropagation()}>\r\n <button\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n className=\"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all\"\r\n title={t('users.view')}\r\n >\r\n <Eye className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); openEditModal(user); }}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${!canUpdate ? 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]' : 'text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]'}`}\r\n title={!canUpdate ? t('common.noPermission', 'Permission insuffisante') : t('common.edit')}\r\n >\r\n <Edit2 className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => handleToggleStatus(user, e)}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${getToggleStatusButtonClass(canUpdate, user.isActive)}`}\r\n title={getToggleStatusTitle(canUpdate, user.isActive, t)}\r\n >\r\n {user.isActive ? <UserX className=\"w-4 h-4\" /> : <UserCheck className=\"w-4 h-4\" />}\r\n </button>\r\n {user.userType !== 'System' && user.userType !== 'LocalAdmin' && (\r\n <button\r\n onClick={(e) => handleDelete(user, e)}\r\n disabled={!canDelete}\r\n className={`p-2 rounded-lg transition-all ${!canDelete ? 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]' : 'text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]'}`}\r\n title={!canDelete ? t('common.noPermission', 'Permission insuffisante') : t('common.delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n {/* Extension row actions */}\r\n <Slot name=\"users.table.row.actions\" context={{ user, reload: loadUsers }} />\r\n </div>\r\n </td>\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n );\r\n\r\n const renderCardsView = () => (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\r\n {loading && (\r\n <div className=\"col-span-full flex flex-col items-center justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-primary-500\" />\r\n <span className=\"mt-3 text-sm text-[var(--text-secondary)]\">Chargement...</span>\r\n </div>\r\n )}\r\n {!loading && users.length === 0 && (\r\n <div className=\"col-span-full flex flex-col items-center justify-center py-16\">\r\n <div className=\"w-16 h-16 rounded-lg bg-[var(--bg-secondary)] flex items-center justify-center mb-3\">\r\n <Search className=\"w-8 h-8 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('users.noUsers')}</span>\r\n </div>\r\n )}\r\n {!loading && users.length > 0 && (\r\n users.map(user => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={user.id}\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/users/${user.id}`); } }}\r\n className=\"bg-[var(--bg-card)] border-2 border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)] rounded-[var(--radius-card)] overflow-hidden transition-all hover:shadow-lg hover:border-[var(--color-accent-400)] cursor-pointer flex flex-col text-left\"\r\n >\r\n {/* Header with colored background */}\r\n <div className=\"bg-[var(--color-accent-50)] dark:bg-[var(--color-accent-900)]/20 p-4 border-b border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} size=\"lg\" className=\"rounded-lg\" />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-5 h-5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-3 h-3 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)] truncate\">{user.fullName}</h3>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate flex items-center gap-1\">\r\n <Mail className=\"w-3 h-3\" />\r\n {user.email}\r\n </p>\r\n </div>\r\n </div>\r\n {/* Status badges */}\r\n <div className=\"flex flex-col items-end gap-1\">\r\n <span className={`inline-flex items-center gap-1.5 px-2 py-0.5 text-xs rounded-full font-medium ${\r\n user.isActive\r\n ? 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400'\r\n : 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400'\r\n }`}>\r\n {user.isActive ? t('users.status.active') : t('users.status.inactive')}\r\n </span>\r\n {user.entraObjectId && (\r\n <span className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400\">\r\n <Cloud className=\"w-2.5 h-2.5\" />\r\n AAD\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n {/* Body */}\r\n <div className=\"p-4 flex flex-col flex-1\">\r\n {/* Roles */}\r\n <div className=\"flex flex-wrap gap-1 mb-3\">\r\n {user.roles.length > 0 ? user.roles.slice(0, 2).map(role => (\r\n <RoleBadge\r\n key={role}\r\n role={role}\r\n variant={role.toLowerCase().includes('admin') ? 'accent' : 'default'}\r\n icon={<Shield className=\"w-3 h-3\" />}\r\n />\r\n )) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">Aucun rôle</span>\r\n )}\r\n {user.roles.length > 2 && (\r\n <span className=\"text-xs px-2 py-0.5 rounded-md bg-[var(--bg-secondary)] text-[var(--text-muted)]\">+{user.roles.length - 2}</span>\r\n )}\r\n </div>\r\n {/* Extension card content */}\r\n <Slot name=\"users.card.content\" context={{ user }} />\r\n {/* Spacer */}\r\n <div className=\"flex-1\" />\r\n {/* Actions */}\r\n <div className=\"flex items-center justify-end gap-1 pt-3 border-t border-[var(--border-color)]\" onClick={e => e.stopPropagation()}>\r\n <button\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n className=\"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all\"\r\n title={t('users.view')}\r\n >\r\n <Eye className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); openEditModal(user); }}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${getEditButtonClass(canUpdate)}`}\r\n title={getEditButtonTitle(canUpdate, t)}\r\n >\r\n <Edit2 className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => handleToggleStatus(user, e)}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${getToggleStatusButtonClass(canUpdate, user.isActive)}`}\r\n title={getToggleStatusTitle(canUpdate, user.isActive, t)}\r\n >\r\n {user.isActive ? <UserX className=\"w-4 h-4\" /> : <UserCheck className=\"w-4 h-4\" />}\r\n </button>\r\n {user.userType !== 'System' && user.userType !== 'LocalAdmin' && (\r\n <button\r\n onClick={(e) => handleDelete(user, e)}\r\n disabled={!canDelete}\r\n className={`p-2 rounded-lg transition-all ${getDeleteButtonClass(canDelete)}`}\r\n title={getDeleteButtonTitle(canDelete, t)}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n );\r\n\r\n const renderKanbanView = () => (\r\n <div className=\"flex gap-6 overflow-x-auto pb-4\">\r\n {loading ? (\r\n <div className=\"flex-1 flex flex-col items-center justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-primary-500\" />\r\n <span className=\"mt-3 text-sm text-[var(--text-secondary)]\">Chargement...</span>\r\n </div>\r\n ) : (\r\n <>\r\n <KanbanColumn title=\"Actifs\" count={activeUsers.length} color=\"success\">\r\n {activeUsers.map(user => (\r\n <KanbanCard key={user.id} onClick={() => navigate(`/administration/users/${user.id}`)}>\r\n <div className=\"flex items-center gap-3 mb-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} size=\"sm\" />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-2 h-2 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"font-medium text-sm text-[var(--text-primary)] truncate\">{user.fullName}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{user.email}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-between\">\r\n {user.roles.length > 0 ? (\r\n <RoleBadge\r\n role={user.roles[0]}\r\n variant={user.roles[0].toLowerCase().includes('admin') ? 'accent' : 'default'}\r\n />\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n <span className=\"text-xs text-[var(--text-muted)]\">En ligne</span>\r\n </div>\r\n </KanbanCard>\r\n ))}\r\n </KanbanColumn>\r\n\r\n <KanbanColumn title=\"Inactifs\" count={inactiveUsers.length} color=\"error\">\r\n {inactiveUsers.map(user => (\r\n <KanbanCard key={user.id} onClick={() => navigate(`/administration/users/${user.id}`)}>\r\n <div className=\"flex items-center gap-3 mb-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} size=\"sm\" />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-2 h-2 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"font-medium text-sm text-[var(--text-primary)] truncate\">{user.fullName}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{user.email}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-between\">\r\n {user.roles.length > 0 ? (\r\n <RoleBadge role={user.roles[0]} />\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n <button\r\n onClick={(e) => handleToggleStatus(user, e)}\r\n disabled={!canUpdate}\r\n className={`text-xs px-2 py-1 rounded transition-opacity ${!canUpdate ? 'opacity-50 cursor-not-allowed bg-[var(--bg-secondary)] text-[var(--text-tertiary)]' : 'bg-[var(--success-bg)] text-[var(--success-text)] hover:opacity-80'}`}\r\n title={!canUpdate ? t('common.noPermission', 'Permission insuffisante') : undefined}\r\n >\r\n Réactiver\r\n </button>\r\n </div>\r\n </KanbanCard>\r\n ))}\r\n {inactiveUsers.length === 0 && (\r\n <div className=\"border border-dashed border-[var(--border-color)] rounded-lg p-6 text-center\">\r\n <UserCheck className=\"w-6 h-6 mx-auto mb-2 text-[var(--text-muted)]\" />\r\n <p className=\"text-xs text-[var(--text-muted)]\">Aucun utilisateur inactif</p>\r\n </div>\r\n )}\r\n </KanbanColumn>\r\n </>\r\n )}\r\n </div>\r\n );\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('users.title') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-4\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('users.title')}</h1>\r\n <p className=\"text-sm text-[var(--text-tertiary)] mt-1\">\r\n {totalCount} utilisateurs • {onlineCount} en ligne\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Slot name=\"users.header.actions\" context={{ users, totalCount, reload: loadUsers }} />\r\n <button\r\n onClick={openCreateModal}\r\n disabled={!canCreate}\r\n className={`btn btn-primary ${!canCreate ? 'opacity-50 cursor-not-allowed' : ''}`}\r\n title={!canCreate ? t('common.noPermission', 'Permission insuffisante') : undefined}\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('users.create')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <RestrictedModuleBanner />\r\n\r\n {/* Toolbar */}\r\n <div className=\"card p-4\">\r\n <div className=\"flex flex-col gap-4\">\r\n {/* Search row */}\r\n <div className=\"flex flex-col md:flex-row md:items-center justify-between gap-4\">\r\n {/* Search & Filter Toggle */}\r\n <div className=\"flex items-center gap-3 flex-1\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n {!filters.search && (\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)] pointer-events-none\" />\r\n )}\r\n <input\r\n type=\"text\"\r\n value={filters.search}\r\n onChange={e => updateFilter('search', e.target.value)}\r\n placeholder={t('users.filters.searchPlaceholder')}\r\n className=\"input w-full\"\r\n style={!filters.search ? { paddingLeft: '2.5rem' } : undefined}\r\n />\r\n {filters.search && (\r\n <button\r\n onClick={() => updateFilter('search', '')}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-[var(--bg-secondary)]\"\r\n >\r\n <X className=\"w-3 h-3 text-[var(--text-tertiary)]\" />\r\n </button>\r\n )}\r\n </div>\r\n <button\r\n onClick={() => setShowFilters(!showFilters)}\r\n className={`btn ${showFilters ? 'btn-primary' : 'btn-secondary'} relative`}\r\n >\r\n <Filter className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('users.filters.title')}</span>\r\n {activeFilterCount > 0 && (\r\n <span className=\"absolute -top-1.5 -right-1.5 w-5 h-5 rounded-full bg-[var(--color-accent-500)] text-white text-xs flex items-center justify-center\">\r\n {activeFilterCount}\r\n </span>\r\n )}\r\n </button>\r\n {activeFilterCount > 0 && (\r\n <button\r\n onClick={handleResetFilters}\r\n className=\"btn btn-ghost text-[var(--text-tertiary)] hover:text-[var(--text-primary)]\"\r\n title={t('users.filters.reset')}\r\n >\r\n <RotateCcw className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* View Toggle - hidden on mobile (always cards on mobile) */}\r\n <div className=\"hidden md:block\">\r\n <ViewToggle\r\n viewMode={viewMode}\r\n onChange={setViewMode}\r\n tableLabel=\"Table\"\r\n cardsLabel=\"Cards\"\r\n kanbanLabel=\"Kanban\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Advanced Filters Panel */}\r\n {showFilters && (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 pt-4 border-t border-[var(--border-color)]\">\r\n {/* Status Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.status')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.status}\r\n onChange={e => updateFilter('status', e.target.value as FilterState['status'])}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"all\">{t('users.filters.allStatuses')}</option>\r\n <option value=\"active\">{t('users.filters.activeOnly')}</option>\r\n <option value=\"inactive\">{t('users.filters.inactiveOnly')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* Role Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.role')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.roleId}\r\n onChange={e => updateFilter('roleId', e.target.value)}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"\">{t('users.filters.allRoles')}</option>\r\n {roles.map(role => (\r\n <option key={role.id} value={role.id}>{role.name}</option>\r\n ))}\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* Source Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.source')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.source}\r\n onChange={e => updateFilter('source', e.target.value as FilterState['source'])}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"all\">{t('users.filters.allSources')}</option>\r\n <option value=\"entra\">{t('users.filters.entraOnly')}</option>\r\n <option value=\"local\">{t('users.filters.localOnly')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* User Type Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.userType')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.userType}\r\n onChange={e => updateFilter('userType', e.target.value)}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"\">{t('users.filters.allTypes')}</option>\r\n <option value=\"User\">{t('users.filters.typeUser')}</option>\r\n <option value=\"System\">{t('users.filters.typeSystem')}</option>\r\n <option value=\"LocalAdmin\">{t('users.filters.typeLocalAdmin')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* Sort By */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.sortBy')}\r\n </label>\r\n <div className=\"flex gap-2\">\r\n <div className=\"relative flex-1\">\r\n <select\r\n value={filters.sortBy}\r\n onChange={e => updateFilter('sortBy', e.target.value)}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"lastname\">{t('users.filters.sortName')}</option>\r\n <option value=\"email\">{t('users.filters.sortEmail')}</option>\r\n <option value=\"lastlogin\">{t('users.filters.sortLastLogin')}</option>\r\n <option value=\"createdat\">{t('users.filters.sortCreatedAt')}</option>\r\n <option value=\"status\">{t('users.filters.sortStatus')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n <button\r\n onClick={() => updateFilter('sortDesc', !filters.sortDesc)}\r\n className={`btn ${filters.sortDesc ? 'btn-primary' : 'btn-secondary'} px-2.5`}\r\n title={filters.sortDesc ? t('users.filters.sortDesc') : t('users.filters.sortAsc')}\r\n >\r\n <ArrowUpDown className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Active filters summary */}\r\n {activeFilterCount > 0 && !showFilters && (\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--text-tertiary)]\">\r\n <Filter className=\"w-4 h-4\" />\r\n <span>{t('users.filters.activeFilters', { count: activeFilterCount })}</span>\r\n <button\r\n onClick={() => setShowFilters(true)}\r\n className=\"text-[var(--color-accent-600)] hover:underline\"\r\n >\r\n {t('users.filters.title')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Content based on view mode */}\r\n {/* Mobile: Always show cards (responsive) */}\r\n <div className=\"md:hidden\">\r\n {renderCardsView()}\r\n </div>\r\n {/* Tablet+: Show selected view mode */}\r\n <div className=\"hidden md:block\">\r\n {viewMode === 'table' && renderTableView()}\r\n {viewMode === 'cards' && renderCardsView()}\r\n {viewMode === 'kanban' && renderKanbanView()}\r\n </div>\r\n\r\n {/* Pagination (only for table and cards) */}\r\n {viewMode !== 'kanban' && (\r\n <Pagination\r\n page={page}\r\n totalPages={totalPages}\r\n totalCount={totalCount}\r\n pageSize={20}\r\n onPageChange={setPage}\r\n itemLabel=\"utilisateurs\"\r\n />\r\n )}\r\n\r\n {/* Modal */}\r\n {showModal && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\r\n <div className=\"card w-full max-w-lg p-6 m-4 max-h-[90vh] overflow-y-auto\">\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">\r\n {editingUser ? t('users.edit') : t('users.create')}\r\n </h2>\r\n <button onClick={() => setShowModal(false)} className=\"btn btn-ghost p-2\">\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n\r\n {error && (\r\n <div className=\"mb-4 p-3 rounded-lg bg-[var(--error-bg)] text-[var(--error-text)] text-sm border border-[var(--error-border)]\">\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit} className=\"space-y-4\">\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.form.firstName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.firstName}\r\n onChange={e => setFormData(prev => ({ ...prev, firstName: e.target.value }))}\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.form.lastName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.lastName}\r\n onChange={e => setFormData(prev => ({ ...prev, lastName: e.target.value }))}\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.columns.email')}\r\n </label>\r\n <input\r\n type=\"email\"\r\n required\r\n value={formData.email}\r\n onChange={e => setFormData(prev => ({ ...prev, email: e.target.value }))}\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n\r\n {!editingUser && (\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.form.password')}\r\n </label>\r\n <input\r\n type=\"password\"\r\n required={!editingUser}\r\n value={formData.password}\r\n onChange={e => setFormData(prev => ({ ...prev, password: e.target.value }))}\r\n autoComplete=\"new-password\"\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n )}\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('users.form.roles')}\r\n </label>\r\n <div className=\"space-y-2 max-h-48 overflow-y-auto p-3 border border-[var(--border-color)] rounded-lg bg-[var(--bg-secondary)]\">\r\n {roles.map(role => (\r\n <label key={role.id} className=\"flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors\">\r\n <input\r\n type=\"checkbox\"\r\n checked={formData.roleIds?.includes(role.id) || false}\r\n onChange={() => handleRoleToggle(role.id)}\r\n className=\"w-4 h-4 rounded border-[var(--border-color)] text-primary-600 focus:ring-primary-500\"\r\n />\r\n <div>\r\n <span className=\"text-[var(--text-primary)] font-medium\">{role.name}</span>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n </label>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Extension form fields slot */}\r\n <Slot\r\n name=\"users.form.fields.after\"\r\n context={{\r\n formData,\r\n onChange: (field: string, value: unknown) => {\r\n if (field.startsWith('ext.')) {\r\n const extField = field.substring(4);\r\n setFormData(prev => ({\r\n ...prev,\r\n ext: { ...((prev as unknown as Record<string, unknown>).ext as Record<string, unknown> || {}), [extField]: value }\r\n }));\r\n } else {\r\n setFormData(prev => ({ ...prev, [field]: value }));\r\n }\r\n },\r\n disabled: saving,\r\n isEditing: !!editingUser,\r\n user: editingUser,\r\n }}\r\n />\r\n\r\n <div className=\"flex justify-end gap-2 pt-4\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowModal(false)}\r\n className=\"btn btn-secondary\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"btn btn-primary disabled:opacity-50\"\r\n >\r\n {saving && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {editingUser ? t('common.save') : t('common.create')}\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["useRestrictedModuleCheck","currentTenant","hasGlobalRoles","isGlobalView","useTenant","currentModuleCode","getCurrentModule","isLoading","menu","useNavigation","RestrictedModuleBanner","t","useTranslation","isRestrictedModule","tenantName","jsxs","jsx","AlertTriangle","useDebounce","value","delay","debouncedValue","setDebouncedValue","useState","useEffect","handler","defaultFilters","UsersPage","navigate","useNavigate","searchParams","setSearchParams","useSearchParams","extensionColumns","useTableColumnExtensions","hasPermission","useAuth","canCreate","canUpdate","canDelete","initialFilters","useMemo","users","setUsers","roles","setRoles","loading","setLoading","filters","setFilters","showFilters","setShowFilters","page","setPage","totalPages","setTotalPages","totalCount","setTotalCount","showModal","setShowModal","editingUser","setEditingUser","formData","setFormData","saving","setSaving","error","setError","viewMode","setViewMode","urlFilters","urlPage","debouncedSearch","activeFilterCount","count","loadUsers","useCallback","result","adminApi","err","params","loadRoles","handleResetFilters","updateFilter","key","prev","openCreateModal","openEditModal","user","detail","r","handleSubmit","e","updateData","message","handleToggleStatus","handleDelete","handleRoleToggle","roleId","id","activeUsers","u","inactiveUsers","onlineCount","getToggleStatusButtonClass","canManage","isActive","getToggleStatusTitle","getEditButtonClass","getEditButtonTitle","getDeleteButtonClass","getDeleteButtonTitle","getMembershipSourceBadge","membershipSource","colorMap","labelMap","renderTableView","col","Loader2","Search","Avatar","Cloud","Mail","role","index","RoleBadge","Shield","StatusBadge","color","label","Users","Eye","Edit2","UserX","UserCheck","Trash2","Slot","renderCardsView","renderKanbanView","Fragment","KanbanColumn","KanbanCard","Breadcrumb","Plus","X","Filter","RotateCcw","ViewToggle","ChevronDown","ArrowUpDown","Pagination","field","extField"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UsersPage-CXC9Hvq6.js","sources":["../../src/hooks/useRestrictedModuleCheck.ts","../../src/components/ui/RestrictedModuleBanner.tsx","../../src/pages/platform/administration/users/UsersPage.tsx"],"sourcesContent":["import { useTenant } from '@/contexts/TenantContext';\r\nimport { useNavigation } from '@/contexts/NavigationContext';\r\n\r\n/**\r\n * Hook to check if Super Admin is viewing a module the current tenant cannot access.\r\n *\r\n * Logic:\r\n * - currentModuleCode: parsed from URL (always available)\r\n * - getCurrentModule(): returns the module IF it's in the tenant's filtered menu\r\n * - If currentModuleCode exists BUT getCurrentModule() returns undefined\r\n * → The module is restricted for this tenant\r\n */\r\nexport function useRestrictedModuleCheck(): {\n isRestrictedModule: boolean;\n tenantName: string | null;\n} {\r\n const { currentTenant, hasGlobalRoles, isGlobalView } = useTenant();\r\n const { currentModuleCode, getCurrentModule, isLoading, menu } = useNavigation();\r\n\r\n // Only applies when:\r\n // 1. User has global roles (Super Admin)\r\n // 2. User is in tenant context (not global view)\r\n // 3. There's a current module in the URL\r\n // 4. Menu is loaded\r\n const shouldCheck = hasGlobalRoles && !isGlobalView && currentTenant && currentModuleCode && !isLoading && menu;\r\n\r\n if (!shouldCheck) {\r\n return { isRestrictedModule: false, tenantName: null };\r\n }\r\n\r\n const moduleInMenu = getCurrentModule();\r\n\r\n return {\r\n isRestrictedModule: !moduleInMenu,\r\n tenantName: currentTenant?.name || null,\r\n };\r\n}\r\n","import type { ReactElement } from 'react';\nimport { useTranslation } from 'react-i18next';\r\nimport { AlertTriangle } from 'lucide-react';\r\nimport { useRestrictedModuleCheck } from '@/hooks/useRestrictedModuleCheck';\r\n\r\n/**\r\n * Warning banner displayed when Super Admin views a module that the current\r\n * tenant does not have access to.\r\n *\r\n * Uses amber warning styling to clearly indicate the restricted state.\r\n */\r\nexport function RestrictedModuleBanner(): ReactElement | null {\r\n const { t } = useTranslation('admin');\r\n const { isRestrictedModule, tenantName } = useRestrictedModuleCheck();\r\n\r\n if (!isRestrictedModule) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n className=\"flex items-center gap-3 px-4 py-2.5 border bg-amber-500/10 border-amber-500/20\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n {/* Warning Icon */}\r\n <div\r\n className=\"flex-shrink-0 w-8 h-8 flex items-center justify-center bg-amber-500/10\"\r\n style={{ borderRadius: 'var(--radius-card)' }}\r\n >\r\n <AlertTriangle className=\"w-4 h-4 text-amber-600\" />\r\n </div>\r\n\r\n {/* Warning Text */}\r\n <div className=\"flex-1 min-w-0\">\r\n <span className=\"font-medium text-amber-700\">\r\n {t('scope.banner.restrictedModule', 'Module restreint')}\r\n </span>\r\n <p className=\"text-xs text-amber-600/70 mt-0.5\">\r\n {t(\r\n 'scope.banner.restrictedModuleDesc',\r\n 'Le tenant \"{{tenantName}}\" n\\'a pas accès à ce module. Données affichées grâce à vos privilèges administrateur.',\r\n { tenantName }\r\n )}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect, useCallback, useMemo } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useNavigate, useSearchParams } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\ntype TFunction = ReturnType<typeof useTranslation>['t'];\r\nimport { Plus, Search, Edit2, Trash2, UserCheck, UserX, X, Loader2, Eye, Mail, Shield, Filter, Cloud, ChevronDown, ArrowUpDown, RotateCcw, Users } from 'lucide-react';\r\nimport { adminApi, type UserListDto, type RoleListDto, type CreateUserRequest, type UpdateUserRequest } from '@/services/api/adminApi';\r\nimport { ViewToggle, Avatar, StatusBadge, RoleBadge, KanbanColumn, KanbanCard, Pagination, type ViewMode } from '@/components/ui/DataView';\r\nimport { Slot, useTableColumnExtensions } from '@/extensions';\r\nimport { RestrictedModuleBanner } from '@/components/ui/RestrictedModuleBanner';\r\nimport { Breadcrumb } from '@/components/ui/Breadcrumb';\r\nimport { useTenant } from '@/contexts/TenantContext';\r\nimport { useAuth } from '@/contexts/AuthContext';\r\n\r\n// Debounce hook for search\r\nfunction useDebounce<T>(value: T, delay: number): T {\r\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\r\n useEffect(() => {\r\n const handler = setTimeout(() => setDebouncedValue(value), delay);\r\n return () => clearTimeout(handler);\r\n }, [value, delay]);\r\n return debouncedValue;\r\n}\r\n\r\n// Filter state type\r\ninterface FilterState {\r\n search: string;\r\n status: 'all' | 'active' | 'inactive';\r\n roleId: string;\r\n source: 'all' | 'entra' | 'local';\r\n userType: string;\r\n sortBy: string;\r\n sortDesc: boolean;\r\n}\r\n\r\nconst defaultFilters: FilterState = {\r\n search: '',\r\n status: 'all',\r\n roleId: '',\r\n source: 'all',\r\n userType: '',\r\n sortBy: 'lastname',\r\n sortDesc: false,\r\n};\r\n\r\nexport function UsersPage(): ReactElement {\r\n const { t } = useTranslation('admin');\r\n const navigate = useNavigate();\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n const extensionColumns = useTableColumnExtensions('users');\r\n const { currentTenant, isGlobalView } = useTenant();\r\n const { hasPermission } = useAuth();\r\n\r\n // Permission checks for action buttons\r\n const canCreate = hasPermission('administration.users.create');\r\n const canUpdate = hasPermission('administration.users.update');\r\n const canDelete = hasPermission('administration.users.delete');\r\n\r\n // Initialize filters from URL params\r\n const initialFilters: FilterState = useMemo(() => ({\r\n search: searchParams.get('search') || '',\r\n status: (searchParams.get('status') as FilterState['status']) || 'all',\r\n roleId: searchParams.get('roleId') || '',\r\n source: (searchParams.get('source') as FilterState['source']) || 'all',\r\n userType: searchParams.get('userType') || '',\r\n sortBy: searchParams.get('sortBy') || 'lastname',\r\n sortDesc: searchParams.get('sortDesc') === 'true',\r\n }), []);\r\n\r\n const [users, setUsers] = useState<UserListDto[]>([]);\r\n const [roles, setRoles] = useState<RoleListDto[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [filters, setFilters] = useState<FilterState>(initialFilters);\r\n const [showFilters, setShowFilters] = useState(false);\r\n const [page, setPage] = useState(parseInt(searchParams.get('page') || '1'));\r\n const [totalPages, setTotalPages] = useState(1);\r\n const [totalCount, setTotalCount] = useState(0);\r\n const [showModal, setShowModal] = useState(false);\r\n const [editingUser, setEditingUser] = useState<UserListDto | null>(null);\r\n const [formData, setFormData] = useState<CreateUserRequest>({\r\n email: '',\r\n password: '',\r\n firstName: '',\r\n lastName: '',\r\n roleIds: []\r\n });\r\n const [saving, setSaving] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [viewMode, setViewMode] = useState<ViewMode>('table');\r\n\r\n // Sync filters from URL when URL changes (e.g., browser back/forward navigation)\r\n useEffect(() => {\r\n const urlFilters: FilterState = {\r\n search: searchParams.get('search') || '',\r\n status: (searchParams.get('status') as FilterState['status']) || 'all',\r\n roleId: searchParams.get('roleId') || '',\r\n source: (searchParams.get('source') as FilterState['source']) || 'all',\r\n userType: searchParams.get('userType') || '',\r\n sortBy: searchParams.get('sortBy') || 'lastname',\r\n sortDesc: searchParams.get('sortDesc') === 'true',\r\n };\r\n // Only update if different to avoid loops\r\n if (JSON.stringify(urlFilters) !== JSON.stringify(filters)) {\r\n setFilters(urlFilters);\r\n }\r\n const urlPage = parseInt(searchParams.get('page') || '1');\r\n if (urlPage !== page) {\r\n setPage(urlPage);\r\n }\r\n }, [searchParams]); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n // Debounce search input\r\n const debouncedSearch = useDebounce(filters.search, 300);\r\n\r\n // Count active filters (excluding search and default sort)\r\n const activeFilterCount = useMemo(() => {\r\n let count = 0;\r\n if (filters.status !== 'all') count++;\r\n if (filters.roleId) count++;\r\n if (filters.source !== 'all') count++;\r\n if (filters.userType) count++;\r\n return count;\r\n }, [filters]);\r\n\r\n const loadUsers = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const result = await adminApi.users.getAll({\r\n page,\r\n pageSize: 20,\r\n search: debouncedSearch || undefined,\r\n isActive: filters.status === 'all' ? undefined : filters.status === 'active',\r\n entraOnly: filters.source === 'entra' ? true : undefined,\r\n roleId: filters.roleId || undefined,\r\n userType: filters.userType || undefined,\r\n sortBy: filters.sortBy || undefined,\r\n sortDesc: filters.sortDesc,\r\n });\r\n setUsers(result.items);\r\n setTotalPages(result.totalPages);\r\n setTotalCount(result.totalCount);\r\n } catch (err) {\r\n console.error('Failed to load users:', err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n // TENANT ISOLATION: Re-fetch when tenant changes (currentTenant or isGlobalView)\r\n }, [page, debouncedSearch, filters.status, filters.source, filters.roleId, filters.userType, filters.sortBy, filters.sortDesc, currentTenant?.id, isGlobalView]);\r\n\r\n // Update URL params when filters change\r\n useEffect(() => {\r\n const params = new URLSearchParams();\r\n if (filters.search) params.set('search', filters.search);\r\n if (filters.status !== 'all') params.set('status', filters.status);\r\n if (filters.roleId) params.set('roleId', filters.roleId);\r\n if (filters.source !== 'all') params.set('source', filters.source);\r\n if (filters.userType) params.set('userType', filters.userType);\r\n if (filters.sortBy !== 'lastname') params.set('sortBy', filters.sortBy);\r\n if (filters.sortDesc) params.set('sortDesc', 'true');\r\n if (page > 1) params.set('page', page.toString());\r\n setSearchParams(params, { replace: true });\r\n }, [filters, page, setSearchParams]);\r\n\r\n const loadRoles = async () => {\r\n try {\r\n const result = await adminApi.roles.getAll();\r\n setRoles(result);\r\n } catch (err) {\r\n console.error('Failed to load roles:', err);\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n loadUsers();\r\n }, [loadUsers]);\r\n\r\n useEffect(() => {\r\n loadRoles();\r\n }, []);\r\n\r\n const handleResetFilters = () => {\r\n setFilters(defaultFilters);\r\n setPage(1);\r\n };\r\n\r\n const updateFilter = <K extends keyof FilterState>(key: K, value: FilterState[K]) => {\r\n setFilters(prev => ({ ...prev, [key]: value }));\r\n setPage(1);\r\n };\r\n\r\n const openCreateModal = () => {\r\n setEditingUser(null);\r\n setFormData({ email: '', password: '', firstName: '', lastName: '', roleIds: [] });\r\n setError(null);\r\n setShowModal(true);\r\n };\r\n\r\n const openEditModal = async (user: UserListDto) => {\r\n try {\r\n const detail = await adminApi.users.getById(user.id);\r\n setEditingUser(user);\r\n setFormData({\r\n email: detail.email,\r\n password: '',\r\n firstName: detail.firstName,\r\n lastName: detail.lastName,\r\n roleIds: detail.roles.map(r => r.id)\r\n });\r\n setError(null);\r\n setShowModal(true);\r\n } catch (err) {\r\n console.error('Failed to load user details:', err);\r\n }\r\n };\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setSaving(true);\r\n setError(null);\r\n\r\n try {\r\n if (editingUser) {\r\n const updateData: UpdateUserRequest = {\r\n email: formData.email !== editingUser.email ? formData.email : undefined,\r\n firstName: formData.firstName,\r\n lastName: formData.lastName,\r\n roleIds: formData.roleIds\r\n };\r\n await adminApi.users.update(editingUser.id, updateData);\r\n } else {\r\n await adminApi.users.create(formData);\r\n }\r\n setShowModal(false);\r\n loadUsers();\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : 'An error occurred';\r\n setError(message);\r\n } finally {\r\n setSaving(false);\r\n }\r\n };\r\n\r\n const handleToggleStatus = async (user: UserListDto, e?: React.MouseEvent) => {\r\n e?.stopPropagation();\r\n try {\r\n if (user.isActive) {\r\n await adminApi.users.deactivate(user.id);\r\n } else {\r\n await adminApi.users.activate(user.id);\r\n }\r\n loadUsers();\r\n } catch (err) {\r\n console.error('Failed to toggle user status:', err);\r\n }\r\n };\r\n\r\n const handleDelete = async (user: UserListDto, e?: React.MouseEvent) => {\r\n e?.stopPropagation();\r\n if (!confirm(t('users.confirmDelete', { name: user.fullName }))) return;\r\n\r\n try {\r\n await adminApi.users.delete(user.id);\r\n loadUsers();\r\n } catch (err) {\r\n console.error('Failed to delete user:', err);\r\n }\r\n };\r\n\r\n const handleRoleToggle = (roleId: string) => {\r\n setFormData(prev => ({\r\n ...prev,\r\n roleIds: prev.roleIds?.includes(roleId)\r\n ? prev.roleIds.filter(id => id !== roleId)\r\n : [...(prev.roleIds || []), roleId]\r\n }));\r\n };\r\n\r\n // Grouper les utilisateurs par statut pour le Kanban\r\n const activeUsers = users.filter(u => u.isActive);\r\n const inactiveUsers = users.filter(u => !u.isActive);\r\n const onlineCount = Math.floor(activeUsers.length * 0.3); // Simulation\r\n\r\n const getToggleStatusButtonClass = (canManage: boolean, isActive: boolean): string => {\r\n if (!canManage) return 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]';\r\n return isActive\r\n ? 'text-[var(--text-tertiary)] hover:text-[var(--warning-text)] hover:bg-[var(--warning-bg)]'\r\n : 'text-[var(--text-tertiary)] hover:text-[var(--success-text)] hover:bg-[var(--success-bg)]';\r\n };\r\n\r\n const getToggleStatusTitle = (canManage: boolean, isActive: boolean, t: TFunction): string => {\r\n if (!canManage) return t('common.noPermission', 'Permission insuffisante');\r\n return isActive ? t('users.deactivate') : t('users.activate');\r\n };\r\n\r\n const getEditButtonClass = (canManage: boolean): string => {\r\n if (!canManage) return 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]';\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]';\r\n };\r\n\r\n const getEditButtonTitle = (canManage: boolean, t: TFunction): string => {\r\n if (!canManage) return t('common.noPermission', 'Permission insuffisante');\r\n return t('common.edit');\r\n };\r\n\r\n const getDeleteButtonClass = (canManage: boolean): string => {\r\n if (!canManage) return 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]';\r\n return 'text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]';\r\n };\r\n\r\n const getDeleteButtonTitle = (canManage: boolean, t: TFunction): string => {\r\n if (!canManage) return t('common.noPermission', 'Permission insuffisante');\r\n return t('common.delete');\r\n };\r\n\r\n const getMembershipSourceBadge = (membershipSource: string) => {\r\n const colorMap: Record<string, string> = {\r\n Direct: 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300',\r\n Group: 'bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300',\r\n Both: 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300'\r\n };\r\n const labelMap: Record<string, string> = {\r\n Direct: t('users.membershipDirect', 'Direct'),\r\n Group: t('users.membershipGroup', 'Via groupe'),\r\n Both: t('users.membershipBoth', 'Mixte')\r\n };\r\n return { color: colorMap[membershipSource] || '', label: labelMap[membershipSource] || '' };\r\n };\r\n\r\n // Render functions for each view\r\n const renderTableView = () => (\r\n <div className=\"card overflow-hidden\">\r\n <table className=\"w-full\">\r\n <thead>\r\n <tr className=\"bg-[var(--bg-secondary)]\">\r\n <th className=\"w-12 px-4 py-3\">\r\n <input type=\"checkbox\" className=\"w-4 h-4 rounded border-[var(--border-color)]\" />\r\n </th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('users.columns.name')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden md:table-cell\">{t('users.columns.email')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden lg:table-cell\">{t('users.columns.role')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider\">{t('users.columns.status')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell\">{t('users.columns.source', 'Source')}</th>\r\n <th className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell\">{t('users.columns.group', 'Groupe')}</th>\r\n {/* Extension columns headers */}\r\n {extensionColumns.map(col => (\r\n <th key={col.key} className=\"text-left px-4 py-3 text-xs font-semibold text-[var(--text-tertiary)] uppercase tracking-wider hidden xl:table-cell\" style={col.width ? { width: col.width } : undefined}>\r\n {col.label}\r\n </th>\r\n ))}\r\n <th className=\"w-32 px-4 py-3\"></th>\r\n </tr>\r\n </thead>\r\n <tbody className=\"divide-y divide-[var(--border-color)]\">\r\n {loading && (\r\n <tr>\r\n <td colSpan={8} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center gap-3\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-primary-500\" />\r\n <span className=\"text-sm text-[var(--text-secondary)]\">Chargement...</span>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && users.length === 0 && (\r\n <tr>\r\n <td colSpan={8} className=\"px-6 py-16 text-center\">\r\n <div className=\"flex flex-col items-center gap-3\">\r\n <div className=\"w-16 h-16 rounded-full bg-[var(--bg-secondary)] flex items-center justify-center\">\r\n <Search className=\"w-8 h-8 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('users.noUsers')}</span>\r\n </div>\r\n </td>\r\n </tr>\r\n )}\r\n {!loading && users.length > 0 && (\r\n users.map(user => (\r\n <tr\r\n key={user.id}\r\n className=\"group hover:bg-[var(--bg-hover)] transition-all cursor-pointer\"\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n >\r\n <td className=\"px-4 py-3\" onClick={e => e.stopPropagation()}>\r\n <input type=\"checkbox\" className=\"w-4 h-4 rounded border-[var(--border-color)]\" />\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-2.5 h-2.5 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"min-w-0\">\r\n <div className=\"flex items-center gap-2\">\r\n <p className=\"font-medium text-[var(--text-primary)] group-hover:text-primary-600 transition-colors truncate\">\r\n {user.fullName}\r\n </p>\r\n {user.entraObjectId && (\r\n <span className=\"hidden sm:inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400\">\r\n <Cloud className=\"w-2.5 h-2.5\" />\r\n AAD\r\n </span>\r\n )}\r\n </div>\r\n <p className=\"text-sm text-[var(--text-tertiary)] truncate md:hidden flex items-center gap-1\">\r\n <Mail className=\"w-3 h-3\" />\r\n {user.email}\r\n </p>\r\n </div>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden md:table-cell\">\r\n <div className=\"flex items-center gap-2 text-[var(--text-secondary)]\">\r\n <Mail className=\"w-4 h-4 text-[var(--text-tertiary)]\" />\r\n <span className=\"truncate\">{user.email}</span>\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3 hidden lg:table-cell\">\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {user.roles.length > 0 ? user.roles.map((role, index) => (\r\n <RoleBadge\r\n key={`${role}-${index}`}\r\n role={role}\r\n variant={role.toLowerCase().includes('admin') ? 'accent' : 'default'}\r\n icon={<Shield className=\"w-3 h-3\" />}\r\n />\r\n )) : (\r\n <span className=\"text-sm text-[var(--text-tertiary)] italic\">Aucun rôle</span>\r\n )}\r\n </div>\r\n </td>\r\n <td className=\"px-4 py-3\">\r\n <StatusBadge\r\n status={user.isActive ? 'active' : 'inactive'}\r\n label={user.isActive ? t('users.status.active') : t('users.status.inactive')}\r\n />\r\n </td>\r\n <td className=\"px-4 py-3 hidden xl:table-cell\">\r\n {(() => {\r\n const { color, label } = getMembershipSourceBadge(user.membershipSource);\r\n return <span className={`inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs font-medium ${color}`}>{label}</span>;\r\n })()}\r\n </td>\r\n <td className=\"px-4 py-3 hidden xl:table-cell\">\r\n {user.primaryGroupId ? (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n navigate(`/administration/groups/${user.primaryGroupId}`);\r\n }}\r\n className=\"inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs font-medium bg-[var(--bg-secondary)] hover:bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:text-primary-600 transition-colors\"\r\n >\r\n <Users className=\"w-3 h-3\" />\r\n {user.primaryGroupName}\r\n </button>\r\n ) : (\r\n <span className=\"text-[var(--text-tertiary)]\">—</span>\r\n )}\r\n </td>\r\n {/* Extension columns data */}\r\n {extensionColumns.map(col => (\r\n <td key={col.key} className=\"px-4 py-3 hidden xl:table-cell text-[var(--text-secondary)]\">\r\n {col.render(user as unknown as Record<string, unknown>, { tableId: 'users', rowIndex: users.indexOf(user) })}\r\n </td>\r\n ))}\r\n <td className=\"px-4 py-3\">\r\n <div className=\"flex items-center justify-end gap-1\" onClick={e => e.stopPropagation()}>\r\n <button\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n className=\"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all\"\r\n title={t('users.view')}\r\n >\r\n <Eye className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); openEditModal(user); }}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${!canUpdate ? 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]' : 'text-[var(--text-tertiary)] hover:text-[var(--info-text)] hover:bg-[var(--info-bg)]'}`}\r\n title={!canUpdate ? t('common.noPermission', 'Permission insuffisante') : t('common.edit')}\r\n >\r\n <Edit2 className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => handleToggleStatus(user, e)}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${getToggleStatusButtonClass(canUpdate, user.isActive)}`}\r\n title={getToggleStatusTitle(canUpdate, user.isActive, t)}\r\n >\r\n {user.isActive ? <UserX className=\"w-4 h-4\" /> : <UserCheck className=\"w-4 h-4\" />}\r\n </button>\r\n {user.userType !== 'System' && user.userType !== 'LocalAdmin' && (\r\n <button\r\n onClick={(e) => handleDelete(user, e)}\r\n disabled={!canDelete}\r\n className={`p-2 rounded-lg transition-all ${!canDelete ? 'opacity-50 cursor-not-allowed text-[var(--text-tertiary)]' : 'text-[var(--text-tertiary)] hover:text-[var(--error-text)] hover:bg-[var(--error-bg)]'}`}\r\n title={!canDelete ? t('common.noPermission', 'Permission insuffisante') : t('common.delete')}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n {/* Extension row actions */}\r\n <Slot name=\"users.table.row.actions\" context={{ user, reload: loadUsers }} />\r\n </div>\r\n </td>\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n );\r\n\r\n const renderCardsView = () => (\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\">\r\n {loading && (\r\n <div className=\"col-span-full flex flex-col items-center justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-primary-500\" />\r\n <span className=\"mt-3 text-sm text-[var(--text-secondary)]\">Chargement...</span>\r\n </div>\r\n )}\r\n {!loading && users.length === 0 && (\r\n <div className=\"col-span-full flex flex-col items-center justify-center py-16\">\r\n <div className=\"w-16 h-16 rounded-lg bg-[var(--bg-secondary)] flex items-center justify-center mb-3\">\r\n <Search className=\"w-8 h-8 text-[var(--text-tertiary)]\" />\r\n </div>\r\n <span className=\"text-[var(--text-secondary)]\">{t('users.noUsers')}</span>\r\n </div>\r\n )}\r\n {!loading && users.length > 0 && (\r\n users.map(user => (\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n key={user.id}\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(`/administration/users/${user.id}`); } }}\r\n className=\"bg-[var(--bg-card)] border-2 border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)] rounded-[var(--radius-card)] overflow-hidden transition-all hover:shadow-lg hover:border-[var(--color-accent-400)] cursor-pointer flex flex-col text-left\"\r\n >\r\n {/* Header with colored background */}\r\n <div className=\"bg-[var(--color-accent-50)] dark:bg-[var(--color-accent-900)]/20 p-4 border-b border-[var(--color-accent-200)] dark:border-[var(--color-accent-800)]\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} size=\"lg\" className=\"rounded-lg\" />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-5 h-5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-3 h-3 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div>\r\n <h3 className=\"font-semibold text-[var(--text-primary)] truncate\">{user.fullName}</h3>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate flex items-center gap-1\">\r\n <Mail className=\"w-3 h-3\" />\r\n {user.email}\r\n </p>\r\n </div>\r\n </div>\r\n {/* Status badges */}\r\n <div className=\"flex flex-col items-end gap-1\">\r\n <span className={`inline-flex items-center gap-1.5 px-2 py-0.5 text-xs rounded-full font-medium ${\r\n user.isActive\r\n ? 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400'\r\n : 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400'\r\n }`}>\r\n {user.isActive ? t('users.status.active') : t('users.status.inactive')}\r\n </span>\r\n {user.entraObjectId && (\r\n <span className=\"inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400\">\r\n <Cloud className=\"w-2.5 h-2.5\" />\r\n AAD\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n {/* Body */}\r\n <div className=\"p-4 flex flex-col flex-1\">\r\n {/* Roles */}\r\n <div className=\"flex flex-wrap gap-1 mb-3\">\r\n {user.roles.length > 0 ? user.roles.slice(0, 2).map(role => (\r\n <RoleBadge\r\n key={role}\r\n role={role}\r\n variant={role.toLowerCase().includes('admin') ? 'accent' : 'default'}\r\n icon={<Shield className=\"w-3 h-3\" />}\r\n />\r\n )) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">Aucun rôle</span>\r\n )}\r\n {user.roles.length > 2 && (\r\n <span className=\"text-xs px-2 py-0.5 rounded-md bg-[var(--bg-secondary)] text-[var(--text-muted)]\">+{user.roles.length - 2}</span>\r\n )}\r\n </div>\r\n {/* Extension card content */}\r\n <Slot name=\"users.card.content\" context={{ user }} />\r\n {/* Spacer */}\r\n <div className=\"flex-1\" />\r\n {/* Actions */}\r\n <div className=\"flex items-center justify-end gap-1 pt-3 border-t border-[var(--border-color)]\" onClick={e => e.stopPropagation()}>\r\n <button\r\n onClick={() => navigate(`/administration/users/${user.id}`)}\r\n className=\"p-2 rounded-lg text-[var(--text-tertiary)] hover:text-primary-600 hover:bg-[var(--accent-bg)] transition-all\"\r\n title={t('users.view')}\r\n >\r\n <Eye className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); openEditModal(user); }}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${getEditButtonClass(canUpdate)}`}\r\n title={getEditButtonTitle(canUpdate, t)}\r\n >\r\n <Edit2 className=\"w-4 h-4\" />\r\n </button>\r\n <button\r\n onClick={(e) => handleToggleStatus(user, e)}\r\n disabled={!canUpdate}\r\n className={`p-2 rounded-lg transition-all ${getToggleStatusButtonClass(canUpdate, user.isActive)}`}\r\n title={getToggleStatusTitle(canUpdate, user.isActive, t)}\r\n >\r\n {user.isActive ? <UserX className=\"w-4 h-4\" /> : <UserCheck className=\"w-4 h-4\" />}\r\n </button>\r\n {user.userType !== 'System' && user.userType !== 'LocalAdmin' && (\r\n <button\r\n onClick={(e) => handleDelete(user, e)}\r\n disabled={!canDelete}\r\n className={`p-2 rounded-lg transition-all ${getDeleteButtonClass(canDelete)}`}\r\n title={getDeleteButtonTitle(canDelete, t)}\r\n >\r\n <Trash2 className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n );\r\n\r\n const renderKanbanView = () => (\r\n <div className=\"flex gap-6 overflow-x-auto pb-4\">\r\n {loading ? (\r\n <div className=\"flex-1 flex flex-col items-center justify-center py-16\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-primary-500\" />\r\n <span className=\"mt-3 text-sm text-[var(--text-secondary)]\">Chargement...</span>\r\n </div>\r\n ) : (\r\n <>\r\n <KanbanColumn title=\"Actifs\" count={activeUsers.length} color=\"success\">\r\n {activeUsers.map(user => (\r\n <KanbanCard key={user.id} onClick={() => navigate(`/administration/users/${user.id}`)}>\r\n <div className=\"flex items-center gap-3 mb-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} size=\"sm\" />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-2 h-2 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"font-medium text-sm text-[var(--text-primary)] truncate\">{user.fullName}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{user.email}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-between\">\r\n {user.roles.length > 0 ? (\r\n <RoleBadge\r\n role={user.roles[0]}\r\n variant={user.roles[0].toLowerCase().includes('admin') ? 'accent' : 'default'}\r\n />\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n <span className=\"text-xs text-[var(--text-muted)]\">En ligne</span>\r\n </div>\r\n </KanbanCard>\r\n ))}\r\n </KanbanColumn>\r\n\r\n <KanbanColumn title=\"Inactifs\" count={inactiveUsers.length} color=\"error\">\r\n {inactiveUsers.map(user => (\r\n <KanbanCard key={user.id} onClick={() => navigate(`/administration/users/${user.id}`)}>\r\n <div className=\"flex items-center gap-3 mb-3\">\r\n <div className=\"relative\">\r\n <Avatar name={user.fullName} size=\"sm\" />\r\n {user.entraObjectId && (\r\n <div className=\"absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-blue-500 flex items-center justify-center ring-2 ring-[var(--bg-card)]\" title={t('users.syncedWithAad')}>\r\n <Cloud className=\"w-2 h-2 text-white\" />\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"font-medium text-sm text-[var(--text-primary)] truncate\">{user.fullName}</p>\r\n <p className=\"text-xs text-[var(--text-tertiary)] truncate\">{user.email}</p>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center justify-between\">\r\n {user.roles.length > 0 ? (\r\n <RoleBadge role={user.roles[0]} />\r\n ) : (\r\n <span className=\"text-xs text-[var(--text-muted)]\">-</span>\r\n )}\r\n <button\r\n onClick={(e) => handleToggleStatus(user, e)}\r\n disabled={!canUpdate}\r\n className={`text-xs px-2 py-1 rounded transition-opacity ${!canUpdate ? 'opacity-50 cursor-not-allowed bg-[var(--bg-secondary)] text-[var(--text-tertiary)]' : 'bg-[var(--success-bg)] text-[var(--success-text)] hover:opacity-80'}`}\r\n title={!canUpdate ? t('common.noPermission', 'Permission insuffisante') : undefined}\r\n >\r\n Réactiver\r\n </button>\r\n </div>\r\n </KanbanCard>\r\n ))}\r\n {inactiveUsers.length === 0 && (\r\n <div className=\"border border-dashed border-[var(--border-color)] rounded-lg p-6 text-center\">\r\n <UserCheck className=\"w-6 h-6 mx-auto mb-2 text-[var(--text-muted)]\" />\r\n <p className=\"text-xs text-[var(--text-muted)]\">Aucun utilisateur inactif</p>\r\n </div>\r\n )}\r\n </KanbanColumn>\r\n </>\r\n )}\r\n </div>\r\n );\r\n\r\n return (\r\n <div className=\"space-y-6\">\r\n {/* Breadcrumb */}\r\n <Breadcrumb\r\n items={[\r\n { label: t('header.title'), href: '/administration' },\r\n { label: t('users.title') }\r\n ]}\r\n />\r\n\r\n {/* Header */}\r\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-4\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">{t('users.title')}</h1>\r\n <p className=\"text-sm text-[var(--text-tertiary)] mt-1\">\r\n {totalCount} utilisateurs • {onlineCount} en ligne\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <Slot name=\"users.header.actions\" context={{ users, totalCount, reload: loadUsers }} />\r\n <button\r\n onClick={openCreateModal}\r\n disabled={!canCreate}\r\n className={`btn btn-primary ${!canCreate ? 'opacity-50 cursor-not-allowed' : ''}`}\r\n title={!canCreate ? t('common.noPermission', 'Permission insuffisante') : undefined}\r\n >\r\n <Plus className=\"w-4 h-4\" />\r\n {t('users.create')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <RestrictedModuleBanner />\r\n\r\n {/* Toolbar */}\r\n <div className=\"card p-4\">\r\n <div className=\"flex flex-col gap-4\">\r\n {/* Search row */}\r\n <div className=\"flex flex-col md:flex-row md:items-center justify-between gap-4\">\r\n {/* Search & Filter Toggle */}\r\n <div className=\"flex items-center gap-3 flex-1\">\r\n <div className=\"relative flex-1 max-w-md\">\r\n {!filters.search && (\r\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-muted)] pointer-events-none\" />\r\n )}\r\n <input\r\n type=\"text\"\r\n value={filters.search}\r\n onChange={e => updateFilter('search', e.target.value)}\r\n placeholder={t('users.filters.searchPlaceholder')}\r\n className=\"input w-full\"\r\n style={!filters.search ? { paddingLeft: '2.5rem' } : undefined}\r\n />\r\n {filters.search && (\r\n <button\r\n onClick={() => updateFilter('search', '')}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-[var(--bg-secondary)]\"\r\n >\r\n <X className=\"w-3 h-3 text-[var(--text-tertiary)]\" />\r\n </button>\r\n )}\r\n </div>\r\n <button\r\n onClick={() => setShowFilters(!showFilters)}\r\n className={`btn ${showFilters ? 'btn-primary' : 'btn-secondary'} relative`}\r\n >\r\n <Filter className=\"w-4 h-4\" />\r\n <span className=\"hidden sm:inline\">{t('users.filters.title')}</span>\r\n {activeFilterCount > 0 && (\r\n <span className=\"absolute -top-1.5 -right-1.5 w-5 h-5 rounded-full bg-[var(--color-accent-500)] text-white text-xs flex items-center justify-center\">\r\n {activeFilterCount}\r\n </span>\r\n )}\r\n </button>\r\n {activeFilterCount > 0 && (\r\n <button\r\n onClick={handleResetFilters}\r\n className=\"btn btn-ghost text-[var(--text-tertiary)] hover:text-[var(--text-primary)]\"\r\n title={t('users.filters.reset')}\r\n >\r\n <RotateCcw className=\"w-4 h-4\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* View Toggle - hidden on mobile (always cards on mobile) */}\r\n <div className=\"hidden md:block\">\r\n <ViewToggle\r\n viewMode={viewMode}\r\n onChange={setViewMode}\r\n tableLabel=\"Table\"\r\n cardsLabel=\"Cards\"\r\n kanbanLabel=\"Kanban\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Advanced Filters Panel */}\r\n {showFilters && (\r\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 pt-4 border-t border-[var(--border-color)]\">\r\n {/* Status Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.status')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.status}\r\n onChange={e => updateFilter('status', e.target.value as FilterState['status'])}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"all\">{t('users.filters.allStatuses')}</option>\r\n <option value=\"active\">{t('users.filters.activeOnly')}</option>\r\n <option value=\"inactive\">{t('users.filters.inactiveOnly')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* Role Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.role')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.roleId}\r\n onChange={e => updateFilter('roleId', e.target.value)}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"\">{t('users.filters.allRoles')}</option>\r\n {roles.map(role => (\r\n <option key={role.id} value={role.id}>{role.name}</option>\r\n ))}\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* Source Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.source')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.source}\r\n onChange={e => updateFilter('source', e.target.value as FilterState['source'])}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"all\">{t('users.filters.allSources')}</option>\r\n <option value=\"entra\">{t('users.filters.entraOnly')}</option>\r\n <option value=\"local\">{t('users.filters.localOnly')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* User Type Filter */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.userType')}\r\n </label>\r\n <div className=\"relative\">\r\n <select\r\n value={filters.userType}\r\n onChange={e => updateFilter('userType', e.target.value)}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"\">{t('users.filters.allTypes')}</option>\r\n <option value=\"User\">{t('users.filters.typeUser')}</option>\r\n <option value=\"System\">{t('users.filters.typeSystem')}</option>\r\n <option value=\"LocalAdmin\">{t('users.filters.typeLocalAdmin')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n {/* Sort By */}\r\n <div>\r\n <label className=\"block text-xs font-medium text-[var(--text-tertiary)] mb-1.5\">\r\n {t('users.filters.sortBy')}\r\n </label>\r\n <div className=\"flex gap-2\">\r\n <div className=\"relative flex-1\">\r\n <select\r\n value={filters.sortBy}\r\n onChange={e => updateFilter('sortBy', e.target.value)}\r\n className=\"input w-full appearance-none pr-8\"\r\n >\r\n <option value=\"lastname\">{t('users.filters.sortName')}</option>\r\n <option value=\"email\">{t('users.filters.sortEmail')}</option>\r\n <option value=\"lastlogin\">{t('users.filters.sortLastLogin')}</option>\r\n <option value=\"createdat\">{t('users.filters.sortCreatedAt')}</option>\r\n <option value=\"status\">{t('users.filters.sortStatus')}</option>\r\n </select>\r\n <ChevronDown className=\"absolute right-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--text-tertiary)] pointer-events-none\" />\r\n </div>\r\n <button\r\n onClick={() => updateFilter('sortDesc', !filters.sortDesc)}\r\n className={`btn ${filters.sortDesc ? 'btn-primary' : 'btn-secondary'} px-2.5`}\r\n title={filters.sortDesc ? t('users.filters.sortDesc') : t('users.filters.sortAsc')}\r\n >\r\n <ArrowUpDown className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Active filters summary */}\r\n {activeFilterCount > 0 && !showFilters && (\r\n <div className=\"flex items-center gap-2 text-sm text-[var(--text-tertiary)]\">\r\n <Filter className=\"w-4 h-4\" />\r\n <span>{t('users.filters.activeFilters', { count: activeFilterCount })}</span>\r\n <button\r\n onClick={() => setShowFilters(true)}\r\n className=\"text-[var(--color-accent-600)] hover:underline\"\r\n >\r\n {t('users.filters.title')}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Content based on view mode */}\r\n {/* Mobile: Always show cards (responsive) */}\r\n <div className=\"md:hidden\">\r\n {renderCardsView()}\r\n </div>\r\n {/* Tablet+: Show selected view mode */}\r\n <div className=\"hidden md:block\">\r\n {viewMode === 'table' && renderTableView()}\r\n {viewMode === 'cards' && renderCardsView()}\r\n {viewMode === 'kanban' && renderKanbanView()}\r\n </div>\r\n\r\n {/* Pagination (only for table and cards) */}\r\n {viewMode !== 'kanban' && (\r\n <Pagination\r\n page={page}\r\n totalPages={totalPages}\r\n totalCount={totalCount}\r\n pageSize={20}\r\n onPageChange={setPage}\r\n itemLabel=\"utilisateurs\"\r\n />\r\n )}\r\n\r\n {/* Modal */}\r\n {showModal && (\r\n <div className=\"fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50\">\r\n <div className=\"card w-full max-w-lg p-6 m-4 max-h-[90vh] overflow-y-auto\">\r\n <div className=\"flex items-center justify-between mb-6\">\r\n <h2 className=\"text-xl font-bold text-[var(--text-primary)]\">\r\n {editingUser ? t('users.edit') : t('users.create')}\r\n </h2>\r\n <button onClick={() => setShowModal(false)} className=\"btn btn-ghost p-2\">\r\n <X className=\"w-5 h-5\" />\r\n </button>\r\n </div>\r\n\r\n {error && (\r\n <div className=\"mb-4 p-3 rounded-lg bg-[var(--error-bg)] text-[var(--error-text)] text-sm border border-[var(--error-border)]\">\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit} className=\"space-y-4\">\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.form.firstName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.firstName}\r\n onChange={e => setFormData(prev => ({ ...prev, firstName: e.target.value }))}\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.form.lastName')}\r\n </label>\r\n <input\r\n type=\"text\"\r\n required\r\n value={formData.lastName}\r\n onChange={e => setFormData(prev => ({ ...prev, lastName: e.target.value }))}\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.columns.email')}\r\n </label>\r\n <input\r\n type=\"email\"\r\n required\r\n value={formData.email}\r\n onChange={e => setFormData(prev => ({ ...prev, email: e.target.value }))}\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n\r\n {!editingUser && (\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-1\">\r\n {t('users.form.password')}\r\n </label>\r\n <input\r\n type=\"password\"\r\n required={!editingUser}\r\n value={formData.password}\r\n onChange={e => setFormData(prev => ({ ...prev, password: e.target.value }))}\r\n autoComplete=\"new-password\"\r\n className=\"input w-full\"\r\n />\r\n </div>\r\n )}\r\n\r\n <div>\r\n <label className=\"block text-sm font-medium text-[var(--text-secondary)] mb-2\">\r\n {t('users.form.roles')}\r\n </label>\r\n <div className=\"space-y-2 max-h-48 overflow-y-auto p-3 border border-[var(--border-color)] rounded-lg bg-[var(--bg-secondary)]\">\r\n {roles.map(role => (\r\n <label key={role.id} className=\"flex items-center gap-3 cursor-pointer p-2 rounded-lg hover:bg-[var(--bg-hover)] transition-colors\">\r\n <input\r\n type=\"checkbox\"\r\n checked={formData.roleIds?.includes(role.id) || false}\r\n onChange={() => handleRoleToggle(role.id)}\r\n className=\"w-4 h-4 rounded border-[var(--border-color)] text-primary-600 focus:ring-primary-500\"\r\n />\r\n <div>\r\n <span className=\"text-[var(--text-primary)] font-medium\">{role.name}</span>\r\n {role.description && (\r\n <p className=\"text-xs text-[var(--text-tertiary)]\">{role.description}</p>\r\n )}\r\n </div>\r\n </label>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Extension form fields slot */}\r\n <Slot\r\n name=\"users.form.fields.after\"\r\n context={{\r\n formData,\r\n onChange: (field: string, value: unknown) => {\r\n if (field.startsWith('ext.')) {\r\n const extField = field.substring(4);\r\n setFormData(prev => ({\r\n ...prev,\r\n ext: { ...((prev as unknown as Record<string, unknown>).ext as Record<string, unknown> || {}), [extField]: value }\r\n }));\r\n } else {\r\n setFormData(prev => ({ ...prev, [field]: value }));\r\n }\r\n },\r\n disabled: saving,\r\n isEditing: !!editingUser,\r\n user: editingUser,\r\n }}\r\n />\r\n\r\n <div className=\"flex justify-end gap-2 pt-4\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowModal(false)}\r\n className=\"btn btn-secondary\"\r\n >\r\n {t('common.cancel')}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n disabled={saving}\r\n className=\"btn btn-primary disabled:opacity-50\"\r\n >\r\n {saving && <Loader2 className=\"w-4 h-4 animate-spin\" />}\r\n {editingUser ? t('common.save') : t('common.create')}\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["useRestrictedModuleCheck","currentTenant","hasGlobalRoles","isGlobalView","useTenant","currentModuleCode","getCurrentModule","isLoading","menu","useNavigation","RestrictedModuleBanner","t","useTranslation","isRestrictedModule","tenantName","jsxs","jsx","AlertTriangle","useDebounce","value","delay","debouncedValue","setDebouncedValue","useState","useEffect","handler","defaultFilters","UsersPage","navigate","useNavigate","searchParams","setSearchParams","useSearchParams","extensionColumns","useTableColumnExtensions","hasPermission","useAuth","canCreate","canUpdate","canDelete","initialFilters","useMemo","users","setUsers","roles","setRoles","loading","setLoading","filters","setFilters","showFilters","setShowFilters","page","setPage","totalPages","setTotalPages","totalCount","setTotalCount","showModal","setShowModal","editingUser","setEditingUser","formData","setFormData","saving","setSaving","error","setError","viewMode","setViewMode","urlFilters","urlPage","debouncedSearch","activeFilterCount","count","loadUsers","useCallback","result","adminApi","err","params","loadRoles","handleResetFilters","updateFilter","key","prev","openCreateModal","openEditModal","user","detail","r","handleSubmit","e","updateData","message","handleToggleStatus","handleDelete","handleRoleToggle","roleId","id","activeUsers","u","inactiveUsers","onlineCount","getToggleStatusButtonClass","canManage","isActive","getToggleStatusTitle","getEditButtonClass","getEditButtonTitle","getDeleteButtonClass","getDeleteButtonTitle","getMembershipSourceBadge","membershipSource","colorMap","labelMap","renderTableView","col","Loader2","Search","Avatar","Cloud","Mail","role","index","RoleBadge","Shield","StatusBadge","color","label","Users","Eye","Edit2","UserX","UserCheck","Trash2","Slot","renderCardsView","renderKanbanView","Fragment","KanbanColumn","KanbanCard","Breadcrumb","Plus","X","Filter","RotateCcw","ViewToggle","ChevronDown","ArrowUpDown","Pagination","field","extField"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const a=require("./index-
|
|
2
|
-
//# sourceMappingURL=accessRequestsApi-
|
|
1
|
+
"use strict";const a=require("./index-IgLVXPg8.js"),r={createRequest:async(e,s,t)=>(await a.apiClient.post(`/api/tenants/${e}/applications/${s}/request`,t)).data,getMyRequests:async()=>(await a.apiClient.get("/api/my/access-requests")).data,getRequestsByApplication:async(e,s)=>{const t=s?`?status=${s}`:"";return(await a.apiClient.get(`/api/applications/${e}/access-requests${t}`)).data},getRequestsByTenant:async(e,s)=>{const t=s?`?status=${s}`:"";return(await a.apiClient.get(`/api/tenants/${e}/access-requests${t}`)).data},approveRequest:async(e,s)=>(await a.apiClient.post(`/api/access-requests/${e}/approve`,s)).data,denyRequest:async(e,s)=>(await a.apiClient.post(`/api/access-requests/${e}/deny`,{notes:s})).data,getAllRequests:async(e,s)=>{const t=new URLSearchParams;e&&t.set("status",e),s&&t.set("tenantId",s);const n=t.toString();return(await a.apiClient.get(`/api/access-requests${n?`?${n}`:""}`)).data}};exports.accessRequestsApi=r;
|
|
2
|
+
//# sourceMappingURL=accessRequestsApi-B-4TJ5_U.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessRequestsApi-
|
|
1
|
+
{"version":3,"file":"accessRequestsApi-B-4TJ5_U.js","sources":["../../src/services/api/accessRequestsApi.ts"],"sourcesContent":["import { apiClient } from './apiClient';\r\n\r\nexport interface AccessRequest {\r\n id: string;\r\n userId: string;\r\n userEmail: string;\r\n userFullName: string;\r\n applicationId: string;\r\n applicationLabel: string;\r\n tenantId: string;\r\n tenantName: string;\r\n reason: string | null;\r\n status: 'Pending' | 'Approved' | 'Denied';\r\n requestedAt: string;\r\n processedAt: string | null;\r\n processedBy: string | null;\r\n processingNotes: string | null;\r\n}\r\n\r\nexport interface CreateAccessRequestDto {\r\n applicationId: string;\r\n reason?: string;\r\n}\r\n\r\nexport interface ProcessRequestDto {\r\n notes?: string;\r\n roleId?: string;\r\n groupId?: string;\r\n}\r\n\r\nexport const accessRequestsApi = {\r\n // User endpoints\r\n createRequest: async (tenantId: string, appId: string, data: CreateAccessRequestDto) => {\r\n const response = await apiClient.post<string>(`/api/tenants/${tenantId}/applications/${appId}/request`, data);\r\n return response.data;\r\n },\r\n\r\n getMyRequests: async () => {\r\n const response = await apiClient.get<AccessRequest[]>('/api/my/access-requests');\r\n return response.data;\r\n },\r\n\r\n // Admin endpoints\r\n getRequestsByApplication: async (appId: string, status?: string) => {\r\n const params = status ? `?status=${status}` : '';\r\n const response = await apiClient.get<AccessRequest[]>(`/api/applications/${appId}/access-requests${params}`);\r\n return response.data;\r\n },\r\n\r\n getRequestsByTenant: async (tenantId: string, status?: string) => {\r\n const params = status ? `?status=${status}` : '';\r\n const response = await apiClient.get<AccessRequest[]>(`/api/tenants/${tenantId}/access-requests${params}`);\r\n return response.data;\r\n },\r\n\r\n approveRequest: async (requestId: string, data: { roleId?: string; groupId?: string; notes?: string }) => {\r\n const response = await apiClient.post(`/api/access-requests/${requestId}/approve`, data);\r\n return response.data;\r\n },\r\n\r\n denyRequest: async (requestId: string, notes: string) => {\r\n const response = await apiClient.post(`/api/access-requests/${requestId}/deny`, { notes });\r\n return response.data;\r\n },\r\n\r\n getAllRequests: async (status?: string, tenantId?: string) => {\r\n const params = new URLSearchParams();\r\n if (status) params.set('status', status);\r\n if (tenantId) params.set('tenantId', tenantId);\r\n const qs = params.toString();\r\n const response = await apiClient.get<AccessRequest[]>(`/api/access-requests${qs ? `?${qs}` : ''}`);\r\n return response.data;\r\n },\r\n};\r\n"],"names":["accessRequestsApi","tenantId","appId","data","apiClient","status","params","requestId","notes","qs"],"mappings":"oDA8BaA,EAAoB,CAE/B,cAAe,MAAOC,EAAkBC,EAAeC,KACpC,MAAMC,YAAU,KAAa,gBAAgBH,CAAQ,iBAAiBC,CAAK,WAAYC,CAAI,GAC5F,KAGlB,cAAe,UACI,MAAMC,YAAU,IAAqB,yBAAyB,GAC/D,KAIlB,yBAA0B,MAAOF,EAAeG,IAAoB,CAClE,MAAMC,EAASD,EAAS,WAAWA,CAAM,GAAK,GAE9C,OADiB,MAAMD,EAAAA,UAAU,IAAqB,qBAAqBF,CAAK,mBAAmBI,CAAM,EAAE,GAC3F,IAClB,EAEA,oBAAqB,MAAOL,EAAkBI,IAAoB,CAChE,MAAMC,EAASD,EAAS,WAAWA,CAAM,GAAK,GAE9C,OADiB,MAAMD,EAAAA,UAAU,IAAqB,gBAAgBH,CAAQ,mBAAmBK,CAAM,EAAE,GACzF,IAClB,EAEA,eAAgB,MAAOC,EAAmBJ,KACvB,MAAMC,EAAAA,UAAU,KAAK,wBAAwBG,CAAS,WAAYJ,CAAI,GACvE,KAGlB,YAAa,MAAOI,EAAmBC,KACpB,MAAMJ,EAAAA,UAAU,KAAK,wBAAwBG,CAAS,QAAS,CAAE,MAAAC,EAAO,GACzE,KAGlB,eAAgB,MAAOH,EAAiBJ,IAAsB,CAC5D,MAAMK,EAAS,IAAI,gBACfD,GAAQC,EAAO,IAAI,SAAUD,CAAM,EACnCJ,GAAUK,EAAO,IAAI,WAAYL,CAAQ,EAC7C,MAAMQ,EAAKH,EAAO,SAAA,EAElB,OADiB,MAAMF,YAAU,IAAqB,uBAAuBK,EAAK,IAAIA,CAAE,GAAK,EAAE,EAAE,GACjF,IAClB,CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { j as a } from "./index-
|
|
1
|
+
import { j as a } from "./index-lpIzhufD.js";
|
|
2
2
|
const c = {
|
|
3
3
|
// User endpoints
|
|
4
4
|
createRequest: async (e, s, t) => (await a.post(`/api/tenants/${e}/applications/${s}/request`, t)).data,
|
|
@@ -24,4 +24,4 @@ const c = {
|
|
|
24
24
|
export {
|
|
25
25
|
c as a
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=accessRequestsApi-
|
|
27
|
+
//# sourceMappingURL=accessRequestsApi-DZSfThpd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessRequestsApi-
|
|
1
|
+
{"version":3,"file":"accessRequestsApi-DZSfThpd.js","sources":["../../src/services/api/accessRequestsApi.ts"],"sourcesContent":["import { apiClient } from './apiClient';\r\n\r\nexport interface AccessRequest {\r\n id: string;\r\n userId: string;\r\n userEmail: string;\r\n userFullName: string;\r\n applicationId: string;\r\n applicationLabel: string;\r\n tenantId: string;\r\n tenantName: string;\r\n reason: string | null;\r\n status: 'Pending' | 'Approved' | 'Denied';\r\n requestedAt: string;\r\n processedAt: string | null;\r\n processedBy: string | null;\r\n processingNotes: string | null;\r\n}\r\n\r\nexport interface CreateAccessRequestDto {\r\n applicationId: string;\r\n reason?: string;\r\n}\r\n\r\nexport interface ProcessRequestDto {\r\n notes?: string;\r\n roleId?: string;\r\n groupId?: string;\r\n}\r\n\r\nexport const accessRequestsApi = {\r\n // User endpoints\r\n createRequest: async (tenantId: string, appId: string, data: CreateAccessRequestDto) => {\r\n const response = await apiClient.post<string>(`/api/tenants/${tenantId}/applications/${appId}/request`, data);\r\n return response.data;\r\n },\r\n\r\n getMyRequests: async () => {\r\n const response = await apiClient.get<AccessRequest[]>('/api/my/access-requests');\r\n return response.data;\r\n },\r\n\r\n // Admin endpoints\r\n getRequestsByApplication: async (appId: string, status?: string) => {\r\n const params = status ? `?status=${status}` : '';\r\n const response = await apiClient.get<AccessRequest[]>(`/api/applications/${appId}/access-requests${params}`);\r\n return response.data;\r\n },\r\n\r\n getRequestsByTenant: async (tenantId: string, status?: string) => {\r\n const params = status ? `?status=${status}` : '';\r\n const response = await apiClient.get<AccessRequest[]>(`/api/tenants/${tenantId}/access-requests${params}`);\r\n return response.data;\r\n },\r\n\r\n approveRequest: async (requestId: string, data: { roleId?: string; groupId?: string; notes?: string }) => {\r\n const response = await apiClient.post(`/api/access-requests/${requestId}/approve`, data);\r\n return response.data;\r\n },\r\n\r\n denyRequest: async (requestId: string, notes: string) => {\r\n const response = await apiClient.post(`/api/access-requests/${requestId}/deny`, { notes });\r\n return response.data;\r\n },\r\n\r\n getAllRequests: async (status?: string, tenantId?: string) => {\r\n const params = new URLSearchParams();\r\n if (status) params.set('status', status);\r\n if (tenantId) params.set('tenantId', tenantId);\r\n const qs = params.toString();\r\n const response = await apiClient.get<AccessRequest[]>(`/api/access-requests${qs ? `?${qs}` : ''}`);\r\n return response.data;\r\n },\r\n};\r\n"],"names":["accessRequestsApi","tenantId","appId","data","apiClient","status","params","requestId","notes","qs"],"mappings":";AA8BO,MAAMA,IAAoB;AAAA;AAAA,EAE/B,eAAe,OAAOC,GAAkBC,GAAeC,OACpC,MAAMC,EAAU,KAAa,gBAAgBH,CAAQ,iBAAiBC,CAAK,YAAYC,CAAI,GAC5F;AAAA,EAGlB,eAAe,aACI,MAAMC,EAAU,IAAqB,yBAAyB,GAC/D;AAAA;AAAA,EAIlB,0BAA0B,OAAOF,GAAeG,MAAoB;AAClE,UAAMC,IAASD,IAAS,WAAWA,CAAM,KAAK;AAE9C,YADiB,MAAMD,EAAU,IAAqB,qBAAqBF,CAAK,mBAAmBI,CAAM,EAAE,GAC3F;AAAA,EAClB;AAAA,EAEA,qBAAqB,OAAOL,GAAkBI,MAAoB;AAChE,UAAMC,IAASD,IAAS,WAAWA,CAAM,KAAK;AAE9C,YADiB,MAAMD,EAAU,IAAqB,gBAAgBH,CAAQ,mBAAmBK,CAAM,EAAE,GACzF;AAAA,EAClB;AAAA,EAEA,gBAAgB,OAAOC,GAAmBJ,OACvB,MAAMC,EAAU,KAAK,wBAAwBG,CAAS,YAAYJ,CAAI,GACvE;AAAA,EAGlB,aAAa,OAAOI,GAAmBC,OACpB,MAAMJ,EAAU,KAAK,wBAAwBG,CAAS,SAAS,EAAE,OAAAC,GAAO,GACzE;AAAA,EAGlB,gBAAgB,OAAOH,GAAiBJ,MAAsB;AAC5D,UAAMK,IAAS,IAAI,gBAAA;AACnB,IAAID,KAAQC,EAAO,IAAI,UAAUD,CAAM,GACnCJ,KAAUK,EAAO,IAAI,YAAYL,CAAQ;AAC7C,UAAMQ,IAAKH,EAAO,SAAA;AAElB,YADiB,MAAMF,EAAU,IAAqB,uBAAuBK,IAAK,IAAIA,CAAE,KAAK,EAAE,EAAE,GACjF;AAAA,EAClB;AACF;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./index-
|
|
2
|
-
//# sourceMappingURL=aiApi-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./index-IgLVXPg8.js"),n={dashboard:{getOverview:(i=30)=>a.api.get("/api/administration/ai/dashboard/overview",{params:{days:i}}),getByProvider:(i,t)=>a.api.get("/api/administration/ai/dashboard/by-provider",{params:{startDate:i,endDate:t}}),getByModel:(i,t,e)=>a.api.get("/api/administration/ai/dashboard/by-model",{params:{startDate:i,endDate:t,providerId:e}}),getDailyCosts:(i=30,t)=>a.api.get("/api/administration/ai/dashboard/daily-costs",{params:{days:i,providerId:t}}),getRecentEvents:(i=50,t)=>a.api.get("/api/administration/ai/dashboard/recent-events",{params:{count:i,providerId:t}})},settings:{getProviders:()=>a.api.get("/api/administration/ai/settings/providers"),getProvider:i=>a.api.get(`/api/administration/ai/settings/providers/${i}`),getModels:(i,t)=>a.api.get("/api/administration/ai/settings/models",{params:{category:i,providerId:t}}),getKey:i=>a.api.get(`/api/administration/ai/settings/keys/${i}`),createKey:(i,t)=>a.api.post(`/api/administration/ai/settings/providers/${i}/keys`,t),updateKey:(i,t)=>a.api.put(`/api/administration/ai/settings/keys/${i}`,t),rotateKey:(i,t)=>a.api.post(`/api/administration/ai/settings/keys/${i}/rotate`,t),revealKey:i=>a.api.post(`/api/administration/ai/settings/keys/${i}/reveal`),activateKey:i=>a.api.post(`/api/administration/ai/settings/keys/${i}/activate`),deactivateKey:i=>a.api.post(`/api/administration/ai/settings/keys/${i}/deactivate`),deleteKey:i=>a.api.delete(`/api/administration/ai/settings/keys/${i}`)},instances:{getAll:()=>a.api.get("/api/administration/ai/instances"),getMyInstances:()=>a.api.get("/api/administration/ai/instances/my-instances"),getById:i=>a.api.get(`/api/administration/ai/instances/${i}`),generateCode:i=>a.api.get(`/api/administration/ai/instances/generate-code/${i}`),create:i=>a.api.post("/api/administration/ai/instances",i),update:(i,t)=>a.api.put(`/api/administration/ai/instances/${i}`,t),delete:i=>a.api.delete(`/api/administration/ai/instances/${i}`),setApiKey:(i,t)=>a.api.post(`/api/administration/ai/instances/${i}/api-key`,t),setAdminKey:(i,t)=>a.api.post(`/api/administration/ai/instances/${i}/admin-key`,t),toggleActive:i=>a.api.post(`/api/administration/ai/instances/${i}/toggle-active`),addTenant:(i,t)=>a.api.post(`/api/administration/ai/instances/${i}/tenants`,t),removeTenant:(i,t)=>a.api.delete(`/api/administration/ai/instances/${i}/tenants/${t}`),setAllTenants:(i,t)=>a.api.put(`/api/administration/ai/instances/${i}/all-tenants`,t),addSkill:(i,t)=>a.api.post(`/api/administration/ai/instances/${i}/skills`,t),removeSkill:(i,t)=>a.api.delete(`/api/administration/ai/instances/${i}/skills/${t}`)},skills:{getAll:i=>a.api.get("/api/administration/ai/skills",{params:i}),getById:i=>a.api.get(`/api/administration/ai/skills/${i}`),getByCode:(i,t)=>a.api.get(`/api/administration/ai/skills/by-code/${i}`,{params:{version:t}}),create:i=>a.api.post("/api/administration/ai/skills",i),update:(i,t)=>a.api.put(`/api/administration/ai/skills/${i}`,t),delete:i=>a.api.delete(`/api/administration/ai/skills/${i}`),activate:i=>a.api.post(`/api/administration/ai/skills/${i}/activate`),deprecate:i=>a.api.post(`/api/administration/ai/skills/${i}/deprecate`),clone:i=>a.api.post(`/api/administration/ai/skills/${i}/clone`),preview:(i,t)=>a.api.post(`/api/administration/ai/skills/${i}/preview`,t),execute:(i,t)=>a.api.post(`/api/administration/ai/skills/${i}/execute`,t),addBlock:(i,t)=>a.api.post(`/api/administration/ai/skills/${i}/blocks`,t),updateBlock:(i,t,e)=>a.api.put(`/api/administration/ai/skills/${i}/blocks/${t}`,e),deleteBlock:(i,t)=>a.api.delete(`/api/administration/ai/skills/${i}/blocks/${t}`),reorderBlocks:(i,t)=>a.api.put(`/api/administration/ai/skills/${i}/blocks/reorder`,t)},blockDefinitions:{getAll:i=>a.api.get("/api/administration/ai/skills/block-definitions",{params:i}),getById:i=>a.api.get(`/api/administration/ai/skills/block-definitions/${i}`),create:i=>a.api.post("/api/administration/ai/skills/block-definitions",i),update:(i,t)=>a.api.put(`/api/administration/ai/skills/block-definitions/${i}`,t),delete:i=>a.api.delete(`/api/administration/ai/skills/block-definitions/${i}`)},schemas:{getAll:i=>a.api.get("/api/administration/ai/schemas",{params:i}),getById:i=>a.api.get(`/api/administration/ai/schemas/${i}`),getByCode:(i,t)=>a.api.get(`/api/administration/ai/schemas/by-code/${i}`,{params:{version:t}}),getActiveByCode:i=>a.api.get(`/api/administration/ai/schemas/active/${i}`),create:i=>a.api.post("/api/administration/ai/schemas",i),update:(i,t)=>a.api.put(`/api/administration/ai/schemas/${i}`,t),incrementVersion:(i,t)=>a.api.post(`/api/administration/ai/schemas/${i}/increment-version`,t),activate:i=>a.api.post(`/api/administration/ai/schemas/${i}/activate`),deactivate:i=>a.api.post(`/api/administration/ai/schemas/${i}/deactivate`),delete:i=>a.api.delete(`/api/administration/ai/schemas/${i}`)},usage:{getByInstance:(i,t)=>a.api.get("/api/administration/ai/monitoring/by-instance",{params:{startDate:i,endDate:t}}),getInstanceEvents:(i,t,e,s=100)=>a.api.get(`/api/administration/ai/monitoring/instance/${i}/events`,{params:{startDate:t,endDate:e,count:s}})},agents:{getAll:()=>a.api.get("/api/administration/ai/agents"),getById:i=>a.api.get(`/api/administration/ai/agents/${i}`),create:i=>a.api.post("/api/administration/ai/agents",i),update:(i,t)=>a.api.put(`/api/administration/ai/agents/${i}`,t),delete:i=>a.api.delete(`/api/administration/ai/agents/${i}`),execute:(i,t)=>a.api.post(`/api/administration/ai/agents/${i}/execute`,t),getExecutions:i=>a.api.get(`/api/administration/ai/agents/${i}/executions`),getExecutionDetail:i=>a.api.get(`/api/administration/ai/agents/executions/${i}`)}};exports.aiApi=n;
|
|
2
|
+
//# sourceMappingURL=aiApi-B20Teu2v.js.map
|