@atlashub/smartstack 3.39.0-preview.1049 → 3.40.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-DgqyaZwI.js → AgentSkillsPage-BS_W2KTh.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-DgqyaZwI.js.map → AgentSkillsPage-BS_W2KTh.js.map} +1 -1
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js → AgentSkillsPage-CmDFLnp7.js} +2 -2
- package/dist/chunks/{AgentSkillsPage-ojivq0Cu.js.map → AgentSkillsPage-CmDFLnp7.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js → AgentWorkloadPage-C8IvYfhT.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-BGGTfOLs.js.map → AgentWorkloadPage-C8IvYfhT.js.map} +1 -1
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js → AgentWorkloadPage-JXsQbwuM.js} +2 -2
- package/dist/chunks/{AgentWorkloadPage-DWsC5VoS.js.map → AgentWorkloadPage-JXsQbwuM.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js → ApiCatalogDetailPage-CYOt34Vy.js} +2 -2
- package/dist/chunks/{ApiCatalogDetailPage-7EifQOAh.js.map → ApiCatalogDetailPage-CYOt34Vy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js → ApiCatalogDetailPage-wFZDsTGy.js} +3 -3
- package/dist/chunks/{ApiCatalogDetailPage-BD7XE4xK.js.map → ApiCatalogDetailPage-wFZDsTGy.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js → ApiCatalogPage-Bdm3HNGP.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BfPoZGD3.js.map → ApiCatalogPage-Bdm3HNGP.js.map} +1 -1
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js → ApiCatalogPage-m_TWQyGv.js} +2 -2
- package/dist/chunks/{ApiCatalogPage-BOPTnk-b.js.map → ApiCatalogPage-m_TWQyGv.js.map} +1 -1
- package/dist/chunks/ApplicationDetailPage-C2BSpEoW.js +2 -0
- package/dist/chunks/{ApplicationDetailPage-CWdz0TS4.js.map → ApplicationDetailPage-C2BSpEoW.js.map} +1 -1
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js → ApplicationDetailPage-CcgDAP-J.js} +503 -501
- package/dist/chunks/{ApplicationDetailPage-CDQqViuH.js.map → ApplicationDetailPage-CcgDAP-J.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js → ApplicationsDashboardPage-CDIjziL3.js} +3 -3
- package/dist/chunks/{ApplicationsDashboardPage-ZyXm2Cd1.js.map → ApplicationsDashboardPage-CDIjziL3.js.map} +1 -1
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js → ApplicationsDashboardPage-DslDyNzJ.js} +2 -2
- package/dist/chunks/{ApplicationsDashboardPage-BH4S3qA2.js.map → ApplicationsDashboardPage-DslDyNzJ.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js → ApplicationsGridPage-BCjsQGU0.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-D0fU1_Le.js.map → ApplicationsGridPage-BCjsQGU0.js.map} +1 -1
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js → ApplicationsGridPage-CIfKiCND.js} +2 -2
- package/dist/chunks/{ApplicationsGridPage-C1WF2Htv.js.map → ApplicationsGridPage-CIfKiCND.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js → ApplicationsListPage-CT75kNcH.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-Cxvt2_WQ.js.map → ApplicationsListPage-CT75kNcH.js.map} +1 -1
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js → ApplicationsListPage-D2B4PZ5n.js} +2 -2
- package/dist/chunks/{ApplicationsListPage-B3ItaY4r.js.map → ApplicationsListPage-D2B4PZ5n.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js → ApplicationsPage-CaTBtduL.js} +2 -2
- package/dist/chunks/{ApplicationsPage-BqfNR-kc.js.map → ApplicationsPage-CaTBtduL.js.map} +1 -1
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js → ApplicationsPage-DW1LhL0U.js} +4 -4
- package/dist/chunks/{ApplicationsPage-DuxuWfrN.js.map → ApplicationsPage-DW1LhL0U.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js → AssignmentRulesPage-Bt9M0ki7.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-CR1C7V0a.js.map → AssignmentRulesPage-Bt9M0ki7.js.map} +1 -1
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js → AssignmentRulesPage-Y7xv60NY.js} +2 -2
- package/dist/chunks/{AssignmentRulesPage-C4Jouh2g.js.map → AssignmentRulesPage-Y7xv60NY.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js → AssignmentsPage-1eQGTjTi.js} +2 -2
- package/dist/chunks/{AssignmentsPage-v8QUJkE7.js.map → AssignmentsPage-1eQGTjTi.js.map} +1 -1
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js → AssignmentsPage-RURdPvfZ.js} +2 -2
- package/dist/chunks/{AssignmentsPage-CjuGAd8n.js.map → AssignmentsPage-RURdPvfZ.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js → AuthCallbackPage-8hF0jYlK.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-BxIXPUJk.js.map → AuthCallbackPage-8hF0jYlK.js.map} +1 -1
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js → AuthCallbackPage-DPL68Asu.js} +2 -2
- package/dist/chunks/{AuthCallbackPage-CuS-efzY.js.map → AuthCallbackPage-DPL68Asu.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js → ConfirmEmailPage-BKlpZkVk.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CWIqy2bT.js.map → ConfirmEmailPage-BKlpZkVk.js.map} +1 -1
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js → ConfirmEmailPage-CawSZypI.js} +2 -2
- package/dist/chunks/{ConfirmEmailPage-CkN8IfP-.js.map → ConfirmEmailPage-CawSZypI.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js → CreateSupportTicketPage-AwbMbBIH.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-Df0ow5ge.js.map → CreateSupportTicketPage-AwbMbBIH.js.map} +1 -1
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js → CreateSupportTicketPage-Dg1YW1eA.js} +2 -2
- package/dist/chunks/{CreateSupportTicketPage-CmrDfFxP.js.map → CreateSupportTicketPage-Dg1YW1eA.js.map} +1 -1
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js → DashboardPage-B4YxOF-9.js} +3 -3
- package/dist/chunks/{DashboardPage-B4Pi5P3O.js.map → DashboardPage-B4YxOF-9.js.map} +1 -1
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js → DashboardPage-BZxjinar.js} +2 -2
- package/dist/chunks/{DashboardPage-wEKZ_DWf.js.map → DashboardPage-BZxjinar.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BAqpoxCW.js → DashboardPage-Bo09y8r7.js} +3 -3
- package/dist/chunks/{DashboardPage-BAqpoxCW.js.map → DashboardPage-Bo09y8r7.js.map} +1 -1
- package/dist/chunks/{DashboardPage-BT5kFaQA.js → DashboardPage-Cq5adDjP.js} +2 -2
- package/dist/chunks/{DashboardPage-BT5kFaQA.js.map → DashboardPage-Cq5adDjP.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js → EscalationConfigPage-C8Hv5naz.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-4pF38E4N.js.map → EscalationConfigPage-C8Hv5naz.js.map} +1 -1
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js → EscalationConfigPage-DNAqMRxA.js} +2 -2
- package/dist/chunks/{EscalationConfigPage-Bcifnt_h.js.map → EscalationConfigPage-DNAqMRxA.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js → ForceChangePasswordPage-BURE_vNg.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-CBaMV_PS.js.map → ForceChangePasswordPage-BURE_vNg.js.map} +1 -1
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js → ForceChangePasswordPage-C6jDZshk.js} +2 -2
- package/dist/chunks/{ForceChangePasswordPage-ClDXluX1.js.map → ForceChangePasswordPage-C6jDZshk.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js → ForgotPasswordPage-C5HLYbz4.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage--ueWRNSO.js.map → ForgotPasswordPage-C5HLYbz4.js.map} +1 -1
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js → ForgotPasswordPage-D3ZQBtjd.js} +2 -2
- package/dist/chunks/{ForgotPasswordPage-CzpAkP5R.js.map → ForgotPasswordPage-D3ZQBtjd.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js → GroupDetailPage-CTuzp9Vp.js} +5 -5
- package/dist/chunks/{GroupDetailPage-dXNOoSXE.js.map → GroupDetailPage-CTuzp9Vp.js.map} +1 -1
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js → GroupDetailPage-NJc2zCxC.js} +2 -2
- package/dist/chunks/{GroupDetailPage-BIgBzQk0.js.map → GroupDetailPage-NJc2zCxC.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js → MyAccessRequestsPage-Cvr29Pnq.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-K2NXkdy4.js.map → MyAccessRequestsPage-Cvr29Pnq.js.map} +1 -1
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js → MyAccessRequestsPage-t6I24rHN.js} +2 -2
- package/dist/chunks/{MyAccessRequestsPage-Be8VvLhh.js.map → MyAccessRequestsPage-t6I24rHN.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js → MyTenantsPage-Dy2RZ_Ei.js} +2 -2
- package/dist/chunks/{MyTenantsPage-BXx1nPC8.js.map → MyTenantsPage-Dy2RZ_Ei.js.map} +1 -1
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js → MyTenantsPage-SvDCQ4Wt.js} +3 -3
- package/dist/chunks/{MyTenantsPage-B9ZAUeCa.js.map → MyTenantsPage-SvDCQ4Wt.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js → MyTicketsPage-C3lEBFD9.js} +2 -2
- package/dist/chunks/{MyTicketsPage-C9MSmmR5.js.map → MyTicketsPage-C3lEBFD9.js.map} +1 -1
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js → MyTicketsPage-DydDgFyz.js} +2 -2
- package/dist/chunks/{MyTicketsPage-d0PoJpnX.js.map → MyTicketsPage-DydDgFyz.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js → NavigationAppsPage-Dyv767w8.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-CJ3BjLlz.js.map → NavigationAppsPage-Dyv767w8.js.map} +1 -1
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js → NavigationAppsPage-WqSspaVo.js} +2 -2
- package/dist/chunks/{NavigationAppsPage-8t2xbddT.js.map → NavigationAppsPage-WqSspaVo.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-_62-bmuk.js → NotificationsPage-Di4I95PM.js} +2 -2
- package/dist/chunks/{NotificationsPage-_62-bmuk.js.map → NotificationsPage-Di4I95PM.js.map} +1 -1
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js → NotificationsPage-elSovpBw.js} +2 -2
- package/dist/chunks/{NotificationsPage-CLHfVUxm.js.map → NotificationsPage-elSovpBw.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js → OnboardingWizardPage-fdWdkwiT.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-Dkc22Jc4.js.map → OnboardingWizardPage-fdWdkwiT.js.map} +1 -1
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js → OnboardingWizardPage-nPLe2buQ.js} +2 -2
- package/dist/chunks/{OnboardingWizardPage-D1rzD6gR.js.map → OnboardingWizardPage-nPLe2buQ.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js → PermissionDetailPage-B8C7tWFP.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-BSvSe4SI.js.map → PermissionDetailPage-B8C7tWFP.js.map} +1 -1
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js → PermissionDetailPage-IUgUaTkE.js} +2 -2
- package/dist/chunks/{PermissionDetailPage-_HhbxzlG.js.map → PermissionDetailPage-IUgUaTkE.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js → PermissionsPage-CmX5sQf2.js} +2 -2
- package/dist/chunks/{PermissionsPage-Xb92YAHn.js.map → PermissionsPage-CmX5sQf2.js.map} +1 -1
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js → PermissionsPage-Kg0rduOM.js} +2 -2
- package/dist/chunks/{PermissionsPage-B0M4gA5m.js.map → PermissionsPage-Kg0rduOM.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js → PortalDashboardPage-CCAYuhtI.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-DTeMESj9.js.map → PortalDashboardPage-CCAYuhtI.js.map} +1 -1
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js → PortalDashboardPage-Dme1XmzN.js} +2 -2
- package/dist/chunks/{PortalDashboardPage-pt9hipR4.js.map → PortalDashboardPage-Dme1XmzN.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js → PreferencesPage-Ct6xWAFp.js} +2 -2
- package/dist/chunks/{PreferencesPage-Cy30AWIN.js.map → PreferencesPage-Ct6xWAFp.js.map} +1 -1
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js → PreferencesPage-Db2RjMpm.js} +2 -2
- package/dist/chunks/{PreferencesPage-CsHVGMgp.js.map → PreferencesPage-Db2RjMpm.js.map} +1 -1
- package/dist/chunks/{ProfilePage-6Gf7igUI.js → ProfilePage-D6Xb1ALH.js} +2 -2
- package/dist/chunks/{ProfilePage-6Gf7igUI.js.map → ProfilePage-D6Xb1ALH.js.map} +1 -1
- package/dist/chunks/{ProfilePage-BzBWkztf.js → ProfilePage-DN2s-lfp.js} +2 -2
- package/dist/chunks/{ProfilePage-BzBWkztf.js.map → ProfilePage-DN2s-lfp.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js → ReferencesManagementPage-B5mcshG1.js} +2 -2
- package/dist/chunks/{ReferencesManagementPage-DEDoHrnU.js.map → ReferencesManagementPage-B5mcshG1.js.map} +1 -1
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js → ReferencesManagementPage-DB975ktX.js} +3 -3
- package/dist/chunks/{ReferencesManagementPage-DD1QiFYr.js.map → ReferencesManagementPage-DB975ktX.js.map} +1 -1
- package/dist/chunks/{RegisterPage-asdx33fV.js → RegisterPage-ZskZrLZH.js} +2 -2
- package/dist/chunks/{RegisterPage-asdx33fV.js.map → RegisterPage-ZskZrLZH.js.map} +1 -1
- package/dist/chunks/{RegisterPage-CIPHRYkl.js → RegisterPage-b8yIPVgh.js} +2 -2
- package/dist/chunks/{RegisterPage-CIPHRYkl.js.map → RegisterPage-b8yIPVgh.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js → ResetPasswordPage-CeAvfsE-.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B4Dj24vU.js.map → ResetPasswordPage-CeAvfsE-.js.map} +1 -1
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js → ResetPasswordPage-Dzp5dCp8.js} +2 -2
- package/dist/chunks/{ResetPasswordPage-B8MWH_Vi.js.map → ResetPasswordPage-Dzp5dCp8.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-Cs6T441o.js → ResolutionModal-CRVN7gHv.js} +2 -2
- package/dist/chunks/{ResolutionModal-Cs6T441o.js.map → ResolutionModal-CRVN7gHv.js.map} +1 -1
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js → ResolutionModal-DJOw1sLT.js} +2 -2
- package/dist/chunks/{ResolutionModal-rLoFOxm9.js.map → ResolutionModal-DJOw1sLT.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js → RoleDetailPage-CLVoFVF8.js} +2 -2
- package/dist/chunks/{RoleDetailPage-Pkw0wU5g.js.map → RoleDetailPage-CLVoFVF8.js.map} +1 -1
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js → RoleDetailPage-XGnPD_8C.js} +3 -3
- package/dist/chunks/{RoleDetailPage-CNFG6j6P.js.map → RoleDetailPage-XGnPD_8C.js.map} +1 -1
- package/dist/chunks/{RolesPage-BHEkMR2O.js → RolesPage-BnAMpR2b.js} +2 -2
- package/dist/chunks/{RolesPage-BHEkMR2O.js.map → RolesPage-BnAMpR2b.js.map} +1 -1
- package/dist/chunks/{RolesPage-D35jwDJU.js → RolesPage-Czj9LMkL.js} +2 -2
- package/dist/chunks/{RolesPage-D35jwDJU.js.map → RolesPage-Czj9LMkL.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-DtonDehw.js → SlaConfigPage-HM0MpIlg.js} +2 -2
- package/dist/chunks/{SlaConfigPage-DtonDehw.js.map → SlaConfigPage-HM0MpIlg.js.map} +1 -1
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js → SlaConfigPage-ZRyAs8aY.js} +2 -2
- package/dist/chunks/{SlaConfigPage-C5Jstix-.js.map → SlaConfigPage-ZRyAs8aY.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js → SupportPermissionsPage-CxJuGgcQ.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-6pC73oCY.js.map → SupportPermissionsPage-CxJuGgcQ.js.map} +1 -1
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js → SupportPermissionsPage-DNd323OK.js} +2 -2
- package/dist/chunks/{SupportPermissionsPage-CsJKGt__.js.map → SupportPermissionsPage-DNd323OK.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js → TemplatesPage-CdwPLsHj.js} +2 -2
- package/dist/chunks/{TemplatesPage-DjmYOGEC.js.map → TemplatesPage-CdwPLsHj.js.map} +1 -1
- package/dist/chunks/{TemplatesPage-DlY91VO_.js → TemplatesPage-Co3ygZvF.js} +2 -2
- package/dist/chunks/{TemplatesPage-DlY91VO_.js.map → TemplatesPage-Co3ygZvF.js.map} +1 -1
- package/dist/chunks/{TenantCard-BHLcv2gD.js → TenantCard-CmCfIK2F.js} +2 -2
- package/dist/chunks/{TenantCard-BHLcv2gD.js.map → TenantCard-CmCfIK2F.js.map} +1 -1
- package/dist/chunks/{TenantCard-DGCKVvKI.js → TenantCard-DI66acce.js} +2 -2
- package/dist/chunks/{TenantCard-DGCKVvKI.js.map → TenantCard-DI66acce.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js → TenantScopeSelector-5NOwmFX2.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-dsSwnOWg.js.map → TenantScopeSelector-5NOwmFX2.js.map} +1 -1
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js → TenantScopeSelector-CEFgxiWt.js} +2 -2
- package/dist/chunks/{TenantScopeSelector-CU5z5PJH.js.map → TenantScopeSelector-CEFgxiWt.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js → TicketDetailPage-BhZ-mpv7.js} +2 -2
- package/dist/chunks/{TicketDetailPage-BQHMaRmq.js.map → TicketDetailPage-BhZ-mpv7.js.map} +1 -1
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js → TicketDetailPage-BxOiOG22.js} +2 -2
- package/dist/chunks/{TicketDetailPage-Bk_0uQ3B.js.map → TicketDetailPage-BxOiOG22.js.map} +1 -1
- package/dist/chunks/{TicketsPage-CufUJctx.js → TicketsPage-BiTvIcM8.js} +2 -2
- package/dist/chunks/{TicketsPage-CufUJctx.js.map → TicketsPage-BiTvIcM8.js.map} +1 -1
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js → TicketsPage-CSiinHME.js} +2 -2
- package/dist/chunks/{TicketsPage-C8QQ4SKy.js.map → TicketsPage-CSiinHME.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js → UserCreateTicketPage-B3TW1oV7.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-DoEMtJoe.js.map → UserCreateTicketPage-B3TW1oV7.js.map} +1 -1
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js → UserCreateTicketPage-BszUd_WZ.js} +2 -2
- package/dist/chunks/{UserCreateTicketPage-XxjNlR9K.js.map → UserCreateTicketPage-BszUd_WZ.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js → UserDashboardPage-C6MvatAb.js} +2 -2
- package/dist/chunks/{UserDashboardPage-fdhZwMLg.js.map → UserDashboardPage-C6MvatAb.js.map} +1 -1
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js → UserDashboardPage-Dtt9VzG_.js} +2 -2
- package/dist/chunks/{UserDashboardPage-BV1d2hMG.js.map → UserDashboardPage-Dtt9VzG_.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-C97e-Dax.js → UserDetailPage-BEEV2vlJ.js} +5 -5
- package/dist/chunks/{UserDetailPage-C97e-Dax.js.map → UserDetailPage-BEEV2vlJ.js.map} +1 -1
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js → UserDetailPage-Dw5OHheZ.js} +2 -2
- package/dist/chunks/{UserDetailPage-BcA7Vhb2.js.map → UserDetailPage-Dw5OHheZ.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js → UserTicketDetailPage-B4YkzzbR.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-BA2syxXG.js.map → UserTicketDetailPage-B4YkzzbR.js.map} +1 -1
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js → UserTicketDetailPage-DCFV-0ny.js} +2 -2
- package/dist/chunks/{UserTicketDetailPage-CXuZVAa2.js.map → UserTicketDetailPage-DCFV-0ny.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js → UsersGroupsPage-CY-l9fTp.js} +3 -3
- package/dist/chunks/{UsersGroupsPage-CPVk31Dh.js.map → UsersGroupsPage-CY-l9fTp.js.map} +1 -1
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js → UsersGroupsPage-c28vYHN9.js} +2 -2
- package/dist/chunks/{UsersGroupsPage-DS2YiUE4.js.map → UsersGroupsPage-c28vYHN9.js.map} +1 -1
- package/dist/chunks/{UsersPage-BIXWHFmG.js → UsersPage-1sLlq9QD.js} +2 -2
- package/dist/chunks/{UsersPage-BIXWHFmG.js.map → UsersPage-1sLlq9QD.js.map} +1 -1
- package/dist/chunks/{UsersPage-DS8aWUKj.js → UsersPage-Bm-uNxh0.js} +2 -2
- package/dist/chunks/{UsersPage-DS8aWUKj.js.map → UsersPage-Bm-uNxh0.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js → accessRequestsApi-CJPjyEkH.js} +2 -2
- package/dist/chunks/{accessRequestsApi-C-r0mrCH.js.map → accessRequestsApi-CJPjyEkH.js.map} +1 -1
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js → accessRequestsApi-D_pj1wl6.js} +2 -2
- package/dist/chunks/{accessRequestsApi-k3ZwhcFb.js.map → accessRequestsApi-D_pj1wl6.js.map} +1 -1
- package/dist/chunks/{aiApi-B-H-76wM.js → aiApi-ByF-oo1J.js} +2 -2
- package/dist/chunks/{aiApi-B-H-76wM.js.map → aiApi-ByF-oo1J.js.map} +1 -1
- package/dist/chunks/{aiApi-CcdrBILv.js → aiApi-Dt3fj0dU.js} +2 -2
- package/dist/chunks/{aiApi-CcdrBILv.js.map → aiApi-Dt3fj0dU.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js → applicationAnalyticsApi-BgG3SGJm.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CO3tk6Ju.js.map → applicationAnalyticsApi-BgG3SGJm.js.map} +1 -1
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js → applicationAnalyticsApi-ktD65iLO.js} +2 -2
- package/dist/chunks/{applicationAnalyticsApi-CLVdVLDu.js.map → applicationAnalyticsApi-ktD65iLO.js.map} +1 -1
- package/dist/chunks/{groupsApi-DExOJZPF.js → groupsApi-C-FLWPCO.js} +2 -2
- package/dist/chunks/{groupsApi-DExOJZPF.js.map → groupsApi-C-FLWPCO.js.map} +1 -1
- package/dist/chunks/{groupsApi-CyqyYsmi.js → groupsApi-CBI5vMLa.js} +2 -2
- package/dist/chunks/{groupsApi-CyqyYsmi.js.map → groupsApi-CBI5vMLa.js.map} +1 -1
- package/dist/chunks/{index-DtAReZI6.js → index-B727-QSU.js} +2 -2
- package/dist/chunks/{index-DtAReZI6.js.map → index-B727-QSU.js.map} +1 -1
- package/dist/chunks/{index-BlOgmQzc.js → index-B9q3vx13.js} +2 -2
- package/dist/chunks/{index-BlOgmQzc.js.map → index-B9q3vx13.js.map} +1 -1
- package/dist/chunks/{index-VSQ2prtJ.js → index-BD-REzV9.js} +2 -2
- package/dist/chunks/{index-VSQ2prtJ.js.map → index-BD-REzV9.js.map} +1 -1
- package/dist/chunks/{index-XOOiD_zY.js → index-BDRogQH_.js} +3 -3
- package/dist/chunks/{index-XOOiD_zY.js.map → index-BDRogQH_.js.map} +1 -1
- package/dist/chunks/{index-DOQyf5yZ.js → index-C-DYxdvd.js} +8 -8
- package/dist/chunks/{index-DOQyf5yZ.js.map → index-C-DYxdvd.js.map} +1 -1
- package/dist/chunks/{index-Cq80YBne.js → index-CBtjGPod.js} +105 -105
- package/dist/chunks/{index-Cq80YBne.js.map → index-CBtjGPod.js.map} +1 -1
- package/dist/chunks/{index-dlXYTPWH.js → index-CF1cvNUL.js} +4 -4
- package/dist/chunks/{index-dlXYTPWH.js.map → index-CF1cvNUL.js.map} +1 -1
- package/dist/chunks/{index-COA_xJVJ.js → index-CH0pTHy1.js} +2 -2
- package/dist/chunks/{index-COA_xJVJ.js.map → index-CH0pTHy1.js.map} +1 -1
- package/dist/chunks/{index-DjZQ6ZG_.js → index-Ca88RIuT.js} +2 -2
- package/dist/chunks/{index-DjZQ6ZG_.js.map → index-Ca88RIuT.js.map} +1 -1
- package/dist/chunks/{index-Cj-9tGpd.js → index-CkWvsvKW.js} +2 -2
- package/dist/chunks/{index-Cj-9tGpd.js.map → index-CkWvsvKW.js.map} +1 -1
- package/dist/chunks/{index-EL_ZNnMH.js → index-CzYKE5fL.js} +2 -2
- package/dist/chunks/{index-EL_ZNnMH.js.map → index-CzYKE5fL.js.map} +1 -1
- package/dist/chunks/{index-qXfYaEmV.js → index-D32ol7lq.js} +2 -2
- package/dist/chunks/{index-qXfYaEmV.js.map → index-D32ol7lq.js.map} +1 -1
- package/dist/chunks/{index-DMQQ0KyA.js → index-D7hmx9IX.js} +2 -2
- package/dist/chunks/{index-DMQQ0KyA.js.map → index-D7hmx9IX.js.map} +1 -1
- package/dist/chunks/{index-BetDcNZm.js → index-DThcQmwZ.js} +2 -2
- package/dist/chunks/{index-BetDcNZm.js.map → index-DThcQmwZ.js.map} +1 -1
- package/dist/chunks/{index-C7h5yvcP.js → index-D_3J6ziZ.js} +2 -2
- package/dist/chunks/{index-C7h5yvcP.js.map → index-D_3J6ziZ.js.map} +1 -1
- package/dist/chunks/{index-C_nDTEP5.js → index-JSjfMShT.js} +2 -2
- package/dist/chunks/{index-C_nDTEP5.js.map → index-JSjfMShT.js.map} +1 -1
- package/dist/chunks/{index-COXxU0FH.js → index-gzXJw_ow.js} +3 -3
- package/dist/chunks/{index-COXxU0FH.js.map → index-gzXJw_ow.js.map} +1 -1
- package/dist/chunks/{index-jJxtz2bs.js → index-rRAbl04H.js} +2 -2
- package/dist/chunks/{index-jJxtz2bs.js.map → index-rRAbl04H.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js → tenantIconMap-Cw-hQ9n4.js} +2 -2
- package/dist/chunks/{tenantIconMap-Ddvguo0l.js.map → tenantIconMap-Cw-hQ9n4.js.map} +1 -1
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js → tenantIconMap-DinwojNW.js} +2 -2
- package/dist/chunks/{tenantIconMap-DBa5MjIz.js.map → tenantIconMap-DinwojNW.js.map} +1 -1
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js → ticketingApi-CcWdebXv.js} +2 -2
- package/dist/chunks/{ticketingApi-Cr6QSv0g.js.map → ticketingApi-CcWdebXv.js.map} +1 -1
- package/dist/chunks/{ticketingApi-D6s75rOB.js → ticketingApi-x0BwZ1NH.js} +2 -2
- package/dist/chunks/{ticketingApi-D6s75rOB.js.map → ticketingApi-x0BwZ1NH.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js → useAccessRequests-BBTIYht3.js} +2 -2
- package/dist/chunks/{useAccessRequests-VuQT-n-P.js.map → useAccessRequests-BBTIYht3.js.map} +1 -1
- package/dist/chunks/{useAccessRequests-CanI2ypo.js → useAccessRequests-BBUj9XY9.js} +71 -71
- package/dist/chunks/{useAccessRequests-CanI2ypo.js.map → useAccessRequests-BBUj9XY9.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js → useUserAccessRequests-BKQxcOXH.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-BEVZLX_M.js.map → useUserAccessRequests-BKQxcOXH.js.map} +1 -1
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js → useUserAccessRequests-BPUPiP55.js} +2 -2
- package/dist/chunks/{useUserAccessRequests-Ba40FDLm.js.map → useUserAccessRequests-BPUPiP55.js.map} +1 -1
- package/dist/pages/platform/administration/applications/ApplicationDetailPage.d.ts.map +1 -1
- package/dist/smartstack.cjs +1 -1
- package/dist/smartstack.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/ApplicationDetailPage-CWdz0TS4.js +0 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),w=require("react"),G=require("react-i18next"),V=require("react-router-dom"),T=require("./index-XOOiD_zY.js"),a=require("lucide-react"),E={blue:"bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]",green:"bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]",yellow:"bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]",red:"bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]",neutral:"bg-[var(--bg-secondary)] text-[var(--text-primary)] border-[var(--border-color)]"};function F(s){return s.status==="NoLicense"||s.isReadOnlyMode?"red":s.isInGracePeriod||s.isInTrial&&s.trialDaysRemaining<=7||s.status==="Active"&&s.daysUntilExpiration<=30?"yellow":s.status==="Active"?"green":"red"}function B(s){if(s.isPerpetual)return"green";const t=s.isInTrial?s.trialDaysRemaining:s.daysUntilExpiration;return t<=15?"red":t<=30?"yellow":"green"}function D(s){return s?new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"}):"-"}function O(s,t){const r=F(s),n=s.isInTrial?s.trialDaysRemaining:s.daysUntilExpiration,i=B(s);return[{label:t("license.info.edition","Edition"),value:t(`license.edition.${s.edition.toLowerCase()}`,s.edition),icon:a.Shield,color:"blue"},{label:t("license.info.status","Status"),value:s.isInGracePeriod?t("license.page.gracePeriod","Grace Period"):t(`license.status.${s.status.toLowerCase()}`,s.status),icon:s.isReadOnlyMode?a.AlertTriangle:a.CheckCircle,color:r},{label:t("license.page.daysRemaining","Days remaining"),value:s.isPerpetual?"∞":n.toString(),icon:s.isPerpetual?a.Infinity:a.Clock,color:i},{label:t("license.page.maxUsers","Max Users"),value:s.limits.users>0?s.limits.users.toString():t("license.page.unlimited","Unlimited"),icon:a.Users,color:"blue"}]}function q({showTrialSuccess:s,isInGracePeriod:t,validationResult:r,gracePeriodDays:n,onTrialSuccessClose:i,onValidationResultClear:l,t:d}){return e.jsxs(e.Fragment,{children:[s&&e.jsxs("div",{className:"flex items-center gap-3 p-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg animate-in fade-in slide-in-from-top",children:[e.jsx(a.CheckCircle,{className:"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm font-medium text-green-900 dark:text-green-300",children:d("license.trial.successBanner","Your 30-day trial is activated!")})}),e.jsx("button",{onClick:i,className:"text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300",children:e.jsx(a.X,{className:"w-4 h-4"})})]}),t&&e.jsxs("div",{className:"flex items-center gap-3 p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5 text-amber-600 dark:text-amber-400 flex-shrink-0"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm font-medium text-amber-900 dark:text-amber-300",children:d("license.page.gracePeriodBanner","Your license has expired. You are in a {{days}}-day grace period. Renew to avoid service interruption.",{days:n})})})]}),r&&e.jsxs("div",{className:`flex items-center gap-3 p-4 rounded-lg border ${r.type==="success"?"bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800":r.type==="revoked"?"bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800":"bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800"}`,children:[r.type==="success"?e.jsx(a.CheckCircle,{className:"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0"}):e.jsx(a.AlertTriangle,{className:`w-5 h-5 flex-shrink-0 ${r.type==="revoked"?"text-red-600 dark:text-red-400":"text-amber-600 dark:text-amber-400"}`}),e.jsx("p",{className:`text-sm font-medium flex-1 ${r.type==="success"?"text-green-900 dark:text-green-300":r.type==="revoked"?"text-red-900 dark:text-red-300":"text-amber-900 dark:text-amber-300"}`,children:r.message}),e.jsx("button",{onClick:l,className:r.type==="success"?"text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300":r.type==="revoked"?"text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300":"text-amber-600 dark:text-amber-400 hover:text-amber-700 dark:hover:text-amber-400",children:e.jsx(a.X,{className:"w-4 h-4"})})]})]})}function K({hasAllFeatures:s,enabledFeatures:t,availableFeatures:r,t:n}){return!r||r.length===0?e.jsx("p",{className:"text-[var(--text-secondary)] text-sm italic",children:n("license.page.noFeatures","No features enabled")}):e.jsxs(e.Fragment,{children:[s&&e.jsxs("div",{className:"flex items-center gap-2 p-3 mb-4 bg-[var(--success-bg)] text-[var(--success-text)] rounded-lg border border-[var(--success-border)]",children:[e.jsx(a.CheckCircle,{className:"w-5 h-5"}),e.jsx("span",{className:"font-medium",children:n("license.page.allFeatures","All features enabled")})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-6",children:r.map(({group:i,features:l})=>e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-[var(--text-secondary)] uppercase tracking-wider mb-3",children:n(`license.group.${i}`,i)}),e.jsx("div",{className:"space-y-2",children:l.map(d=>{const m=s||t.some(c=>c.toLowerCase()===d.toLowerCase());return e.jsxs("div",{className:`flex items-center gap-2 px-3 py-2 rounded-lg border ${m?"bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]":"bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)] opacity-60"}`,children:[m?e.jsx(a.Unlock,{className:"w-4 h-4 flex-shrink-0"}):e.jsx(a.Lock,{className:"w-4 h-4 flex-shrink-0"}),e.jsx("span",{className:"text-sm font-medium",children:n(`license.module.${d}`,d)})]},d)})})]},i))}),!s&&t.length===0&&e.jsx("p",{className:"text-[var(--text-secondary)] text-sm italic mt-3",children:n("license.page.noFeatures","No features enabled")})]})}function Y(s,t){const[r,n]=w.useState(!1),[i,l]=w.useState(null),d=w.useCallback(async()=>{n(!0),l(null);try{const c=await T.api.post("/api/administration/license/validate-server");c.revoked?(l({type:"revoked",message:t("license.validationRevoked","The license has been revoked by the server.")}),await s()):c.valid?(l({type:"success",message:t("license.validationSuccess","License is valid")}),await s()):l({type:"error",message:c.error||t("license.validationError","Unable to validate the license with the server.")})}catch{l({type:"error",message:t("license.validationError","Unable to validate the license with the server.")})}finally{n(!1),setTimeout(()=>l(null),5e3)}},[t,s]),m=w.useCallback(()=>l(null),[]);return{isValidating:r,validationResult:i,handleValidate:d,clearValidationResult:m}}function W(){const{t:s}=G.useTranslation("admin"),{license:t,usage:r,isLoading:n,error:i,refreshLicense:l,isHalted:d,haltReason:m}=T.useLicense(),[c,o]=w.useState(!1),[x,b]=V.useSearchParams(),[N,v]=w.useState(!1),{isValidating:u,validationResult:$,handleValidate:S,clearValidationResult:L}=Y(l,s);if(w.useEffect(()=>{l()},[l]),w.useEffect(()=>{if(x.get("trial")==="success"){v(!0);const h=setTimeout(()=>{v(!1),x.delete("trial"),b(x,{replace:!0})},5e3);return()=>clearTimeout(h)}},[x,b]),n)return e.jsx("div",{className:"flex items-center justify-center h-64",children:e.jsx(a.Loader2,{className:"w-8 h-8 animate-spin text-[var(--text-secondary)]"})});if(i||!t)return e.jsx("div",{className:"p-6",children:e.jsxs("div",{className:"card p-6 text-center",children:[e.jsx(a.AlertTriangle,{className:"w-12 h-12 mx-auto mb-4 text-[var(--warning-text)]"}),e.jsx("h2",{className:"text-lg font-semibold mb-2",children:s("license.page.errorTitle","Unable to load license")}),e.jsx("p",{className:"text-[var(--text-secondary)] mb-4",children:i||s("license.page.errorDesc","License information is not available.")}),e.jsx("button",{onClick:()=>l(),className:"btn-primary px-4 py-2",children:s("common.retry","Retry")})]})});const P=T.hasAllLicenseFeatures(t.enabledFeatures),A=O(t,s);return e.jsxs("div",{className:"p-6 space-y-6",children:[d&&e.jsxs("div",{className:"flex items-center gap-3 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium text-red-900 dark:text-red-300",children:s("license.halted.warning","Licence suspendue")}),m&&e.jsx("p",{className:"text-sm text-red-800 dark:text-red-200 mt-1",children:m})]})]}),e.jsx(q,{showTrialSuccess:N,isInGracePeriod:t.isInGracePeriod,validationResult:$,gracePeriodDays:t.gracePeriodDays,onTrialSuccessClose:()=>v(!1),onValidationResultClear:L,t:s}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("license.page.title","License Management")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:s("license.page.subtitle","View and manage your platform license")})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(T.LicenseStatusBadge,{showDetails:!0}),e.jsxs("button",{onClick:S,disabled:u,className:"btn-secondary px-4 py-2 flex items-center gap-2",children:[u?e.jsx(a.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(a.ShieldCheck,{className:"w-4 h-4"}),u?s("license.validating","Validating..."):s("license.validate","Validate")]}),e.jsxs("button",{onClick:()=>o(!0),className:"btn-primary px-4 py-2 flex items-center gap-2",children:[e.jsx(a.Key,{className:"w-4 h-4"}),s("license.activate","Activate")]})]})]}),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:A.map(h=>e.jsxs("div",{className:`card p-4 border ${E[h.color]}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(h.icon,{className:"w-5 h-5 opacity-80"}),e.jsx("span",{className:"text-sm opacity-80",children:h.label})]}),e.jsx("div",{className:"text-2xl font-bold",children:h.value})]},h.label))}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Zap,{className:"w-5 h-5"}),s("license.info.limits","Limits")]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsx(R,{icon:a.Users,label:s("license.page.usersLimit","Users"),max:t.limits.users,current:r?.activeUsers??0,margin:10,t:s}),e.jsx(R,{icon:a.Building,label:s("license.page.tenantsLimit","Tenants (B2B)"),max:t.limits.tenants,current:r?.activeTenants??0,margin:2,t:s})]}),(()=>{const h=["users","tenants","max_instances","max_users"],C=Object.entries(t.limits.custom??{}).filter(([f])=>!h.includes(f));return C.length===0?null:e.jsxs("div",{className:"mt-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsx("h3",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:s("license.page.customLimits","Custom Limits")}),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:C.map(([f,I])=>e.jsxs("div",{className:"flex justify-between items-center py-1.5 px-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:f}),e.jsx("span",{className:"text-sm font-medium",children:I})]},f))})]})})()]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Calendar,{className:"w-5 h-5"}),s("license.page.details","License Details")]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(g,{label:s("license.info.productId","Product"),value:t.productId}),e.jsx(g,{label:s("license.info.company","Company"),value:t.companyName||"-"}),e.jsx(g,{label:s("license.info.edition","Edition"),value:s(`license.edition.${t.edition.toLowerCase()}`,t.edition)}),e.jsx(g,{label:s("license.info.status","Status"),value:s(`license.status.${t.status.toLowerCase()}`,t.status)}),e.jsx(g,{label:s("license.info.activatedAt","Activated At"),value:D(t.activatedAt)}),e.jsx(g,{label:s("license.info.expiresAt","Expires At"),value:t.isPerpetual?s("license.page.never","Never (Perpetual)"):D(t.expiresAt)})]})]}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Server,{className:"w-5 h-5"}),s("license.page.subscription","Subscription")]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(g,{label:s("license.page.licenseType","License Type"),value:t.isPerpetual?s("license.page.perpetual","Perpetual"):t.isInTrial?s("license.edition.trial","Trial"):s("license.page.subscription","Subscription")}),e.jsx(g,{label:s("license.page.maxUsers","Max Users"),value:t.limits.users>0?t.limits.users.toString():s("license.page.unlimited","Unlimited")}),e.jsx(g,{label:s("license.page.gracePeriodDays","Grace Period"),value:t.gracePeriodDays>0?s("license.page.gracePeriodValue","{{days}} days",{days:t.gracePeriodDays}):s("license.page.noGracePeriod","None")}),e.jsx(g,{label:s("license.page.renewalDate","Renewal Date"),value:D(t.renewalDate)}),e.jsx(g,{label:s("license.page.mode","Mode"),value:t.isReadOnlyMode?s("license.page.readOnly","Read-only"):t.isInTrial?s("license.edition.trial","Trial"):s("license.page.licensed","Licensed")}),t.isInGracePeriod&&e.jsx(g,{label:s("license.page.gracePeriodStatus","Grace Period Status"),value:s("license.page.inGracePeriod","Active"),highlight:"yellow"})]})]}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Monitor,{className:"w-5 h-5"}),s("license.page.machineInfo","Machine")]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("div",{className:"flex justify-between items-center mb-1",children:e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s("license.page.machineName","Machine Name")})}),e.jsx("span",{className:"text-xs font-mono text-[var(--text-primary)] break-all",children:t.machineName||"-"})]}),e.jsxs("div",{className:"py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("div",{className:"flex justify-between items-center mb-1",children:e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s("license.page.instanceId","Instance ID")})}),e.jsx("span",{className:"text-xs font-mono text-[var(--text-primary)] break-all",children:t.instanceId||"-"})]}),e.jsxs("div",{className:"py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("div",{className:"flex justify-between items-center mb-1",children:e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s("license.page.licenseId","License ID")})}),e.jsx("span",{className:"text-xs font-mono text-[var(--text-primary)] break-all",children:t.licenseServerId||"-"})]})]})]})]}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Layers,{className:"w-5 h-5"}),s("license.info.features","Features")]}),e.jsx(K,{hasAllFeatures:P,enabledFeatures:t.enabledFeatures,availableFeatures:t.availableFeatures,t:s})]}),e.jsx(T.LicenseActivationDialog,{open:c,onOpenChange:o})]})}function g({label:s,value:t,highlight:r}){const n=r==="yellow"?"text-amber-600 dark:text-amber-400 font-semibold":r==="red"?"text-red-600 dark:text-red-400 font-semibold":r==="green"?"text-green-600 dark:text-green-400 font-semibold":"text-[var(--text-primary)]";return e.jsxs("div",{className:"flex justify-between items-center py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s}),e.jsx("span",{className:`text-sm font-medium ${n}`,children:t})]})}function X(s,t){return s?"text-red-500":t?"text-amber-500":"text-blue-500"}function Z(s,t){return s?"text-red-500":t?"text-amber-500":"text-[var(--text-primary)]"}function R({icon:s,label:t,max:r,current:n,margin:i=0,t:l}){const d=r<=0,m=r,c=r+i,o=140,x=12,b=(o-x)/2,N=o/2,v=135,u=270,$=c>0?Math.min(1,n/c):0,S=c>0?m/c:1,L=i>0&&n>m&&n<=c,P=n>c;let A="#3b82f6";P?A="#ef4444":L&&(A="#f59e0b");const h="rgba(245, 158, 11, 0.25)",C=j=>{const y=j*Math.PI/180;return{x:N+b*Math.cos(y),y:N+b*Math.sin(y)}},f=j=>{if(j<=0)return"";const y=v+j,k=C(v),p=C(y),M=j>180?1:0;return`M ${k.x} ${k.y} A ${b} ${b} 0 ${M} 1 ${p.x} ${p.y}`},I=c>0?Math.round(n/m*100):0;return d?e.jsxs("div",{className:"flex flex-col items-center gap-3 py-4",children:[e.jsxs("div",{className:"relative",style:{width:o,height:o},children:[e.jsxs("svg",{width:o,height:o,children:[e.jsx("path",{d:f(u),fill:"none",stroke:"var(--bg-tertiary)",strokeWidth:x,strokeLinecap:"round"}),e.jsx("path",{d:f(u),fill:"none",stroke:"#22c55e",strokeWidth:x,strokeLinecap:"round",opacity:.5})]}),e.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[e.jsx(s,{className:"w-6 h-6 text-green-500 mb-1"}),e.jsx("span",{className:"text-lg font-bold text-green-500",children:"∞"})]})]}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)]",children:t}),e.jsx("span",{className:"text-xs text-[var(--text-secondary)]",children:l("license.page.unlimited","Unlimited")})]}):e.jsxs("div",{className:"flex flex-col items-center gap-3 py-4",children:[e.jsxs("div",{className:"relative",style:{width:o,height:o},children:[e.jsxs("svg",{width:o,height:o,children:[e.jsx("path",{d:f(u),fill:"none",stroke:"var(--bg-tertiary)",strokeWidth:x,strokeLinecap:"round"}),i>0&&(()=>{const j=u*(1-S),y=v+u*S,k=C(y),p=C(v+u),M=j>180?1:0,U=`M ${k.x} ${k.y} A ${b} ${b} 0 ${M} 1 ${p.x} ${p.y}`;return e.jsx("path",{d:U,fill:"none",stroke:h,strokeWidth:x,strokeLinecap:"round"})})(),e.jsx("path",{d:f(u*$),fill:"none",stroke:A,strokeWidth:x,strokeLinecap:"round",style:{transition:"stroke 0.3s, d 0.3s"}}),i>0&&(()=>{const j=v+u*S,y=b-x/2-2,k=b+x/2+2,p=j*Math.PI/180;return e.jsx("line",{x1:N+y*Math.cos(p),y1:N+y*Math.sin(p),x2:N+k*Math.cos(p),y2:N+k*Math.sin(p),stroke:"var(--text-secondary)",strokeWidth:2,strokeLinecap:"round"})})()]}),e.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[e.jsx(s,{className:`w-5 h-5 mb-0.5 ${X(P,L)}`}),e.jsxs("span",{className:`text-2xl font-bold ${Z(P,L)}`,children:[I,"%"]}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)]",children:[n," / ",m]})]})]}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)]",children:t}),i>0&&e.jsxs("span",{className:`text-xs ${L||P?"text-amber-600 dark:text-amber-400":"text-[var(--text-secondary)]"}`,children:["+",i," ",l("license.page.tolerance","tolerance")]})]})}exports.LicenseManagementPage=W;
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),w=require("react"),G=require("react-i18next"),V=require("react-router-dom"),T=require("./index-BDRogQH_.js"),a=require("lucide-react"),E={blue:"bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]",green:"bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]",yellow:"bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]",red:"bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]",neutral:"bg-[var(--bg-secondary)] text-[var(--text-primary)] border-[var(--border-color)]"};function F(s){return s.status==="NoLicense"||s.isReadOnlyMode?"red":s.isInGracePeriod||s.isInTrial&&s.trialDaysRemaining<=7||s.status==="Active"&&s.daysUntilExpiration<=30?"yellow":s.status==="Active"?"green":"red"}function B(s){if(s.isPerpetual)return"green";const t=s.isInTrial?s.trialDaysRemaining:s.daysUntilExpiration;return t<=15?"red":t<=30?"yellow":"green"}function D(s){return s?new Date(s).toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"}):"-"}function O(s,t){const r=F(s),n=s.isInTrial?s.trialDaysRemaining:s.daysUntilExpiration,i=B(s);return[{label:t("license.info.edition","Edition"),value:t(`license.edition.${s.edition.toLowerCase()}`,s.edition),icon:a.Shield,color:"blue"},{label:t("license.info.status","Status"),value:s.isInGracePeriod?t("license.page.gracePeriod","Grace Period"):t(`license.status.${s.status.toLowerCase()}`,s.status),icon:s.isReadOnlyMode?a.AlertTriangle:a.CheckCircle,color:r},{label:t("license.page.daysRemaining","Days remaining"),value:s.isPerpetual?"∞":n.toString(),icon:s.isPerpetual?a.Infinity:a.Clock,color:i},{label:t("license.page.maxUsers","Max Users"),value:s.limits.users>0?s.limits.users.toString():t("license.page.unlimited","Unlimited"),icon:a.Users,color:"blue"}]}function q({showTrialSuccess:s,isInGracePeriod:t,validationResult:r,gracePeriodDays:n,onTrialSuccessClose:i,onValidationResultClear:l,t:d}){return e.jsxs(e.Fragment,{children:[s&&e.jsxs("div",{className:"flex items-center gap-3 p-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg animate-in fade-in slide-in-from-top",children:[e.jsx(a.CheckCircle,{className:"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm font-medium text-green-900 dark:text-green-300",children:d("license.trial.successBanner","Your 30-day trial is activated!")})}),e.jsx("button",{onClick:i,className:"text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300",children:e.jsx(a.X,{className:"w-4 h-4"})})]}),t&&e.jsxs("div",{className:"flex items-center gap-3 p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5 text-amber-600 dark:text-amber-400 flex-shrink-0"}),e.jsx("div",{className:"flex-1",children:e.jsx("p",{className:"text-sm font-medium text-amber-900 dark:text-amber-300",children:d("license.page.gracePeriodBanner","Your license has expired. You are in a {{days}}-day grace period. Renew to avoid service interruption.",{days:n})})})]}),r&&e.jsxs("div",{className:`flex items-center gap-3 p-4 rounded-lg border ${r.type==="success"?"bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800":r.type==="revoked"?"bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800":"bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800"}`,children:[r.type==="success"?e.jsx(a.CheckCircle,{className:"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0"}):e.jsx(a.AlertTriangle,{className:`w-5 h-5 flex-shrink-0 ${r.type==="revoked"?"text-red-600 dark:text-red-400":"text-amber-600 dark:text-amber-400"}`}),e.jsx("p",{className:`text-sm font-medium flex-1 ${r.type==="success"?"text-green-900 dark:text-green-300":r.type==="revoked"?"text-red-900 dark:text-red-300":"text-amber-900 dark:text-amber-300"}`,children:r.message}),e.jsx("button",{onClick:l,className:r.type==="success"?"text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300":r.type==="revoked"?"text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300":"text-amber-600 dark:text-amber-400 hover:text-amber-700 dark:hover:text-amber-400",children:e.jsx(a.X,{className:"w-4 h-4"})})]})]})}function K({hasAllFeatures:s,enabledFeatures:t,availableFeatures:r,t:n}){return!r||r.length===0?e.jsx("p",{className:"text-[var(--text-secondary)] text-sm italic",children:n("license.page.noFeatures","No features enabled")}):e.jsxs(e.Fragment,{children:[s&&e.jsxs("div",{className:"flex items-center gap-2 p-3 mb-4 bg-[var(--success-bg)] text-[var(--success-text)] rounded-lg border border-[var(--success-border)]",children:[e.jsx(a.CheckCircle,{className:"w-5 h-5"}),e.jsx("span",{className:"font-medium",children:n("license.page.allFeatures","All features enabled")})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-6",children:r.map(({group:i,features:l})=>e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-[var(--text-secondary)] uppercase tracking-wider mb-3",children:n(`license.group.${i}`,i)}),e.jsx("div",{className:"space-y-2",children:l.map(d=>{const m=s||t.some(c=>c.toLowerCase()===d.toLowerCase());return e.jsxs("div",{className:`flex items-center gap-2 px-3 py-2 rounded-lg border ${m?"bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]":"bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)] opacity-60"}`,children:[m?e.jsx(a.Unlock,{className:"w-4 h-4 flex-shrink-0"}):e.jsx(a.Lock,{className:"w-4 h-4 flex-shrink-0"}),e.jsx("span",{className:"text-sm font-medium",children:n(`license.module.${d}`,d)})]},d)})})]},i))}),!s&&t.length===0&&e.jsx("p",{className:"text-[var(--text-secondary)] text-sm italic mt-3",children:n("license.page.noFeatures","No features enabled")})]})}function Y(s,t){const[r,n]=w.useState(!1),[i,l]=w.useState(null),d=w.useCallback(async()=>{n(!0),l(null);try{const c=await T.api.post("/api/administration/license/validate-server");c.revoked?(l({type:"revoked",message:t("license.validationRevoked","The license has been revoked by the server.")}),await s()):c.valid?(l({type:"success",message:t("license.validationSuccess","License is valid")}),await s()):l({type:"error",message:c.error||t("license.validationError","Unable to validate the license with the server.")})}catch{l({type:"error",message:t("license.validationError","Unable to validate the license with the server.")})}finally{n(!1),setTimeout(()=>l(null),5e3)}},[t,s]),m=w.useCallback(()=>l(null),[]);return{isValidating:r,validationResult:i,handleValidate:d,clearValidationResult:m}}function W(){const{t:s}=G.useTranslation("admin"),{license:t,usage:r,isLoading:n,error:i,refreshLicense:l,isHalted:d,haltReason:m}=T.useLicense(),[c,o]=w.useState(!1),[x,b]=V.useSearchParams(),[N,v]=w.useState(!1),{isValidating:u,validationResult:$,handleValidate:S,clearValidationResult:L}=Y(l,s);if(w.useEffect(()=>{l()},[l]),w.useEffect(()=>{if(x.get("trial")==="success"){v(!0);const h=setTimeout(()=>{v(!1),x.delete("trial"),b(x,{replace:!0})},5e3);return()=>clearTimeout(h)}},[x,b]),n)return e.jsx("div",{className:"flex items-center justify-center h-64",children:e.jsx(a.Loader2,{className:"w-8 h-8 animate-spin text-[var(--text-secondary)]"})});if(i||!t)return e.jsx("div",{className:"p-6",children:e.jsxs("div",{className:"card p-6 text-center",children:[e.jsx(a.AlertTriangle,{className:"w-12 h-12 mx-auto mb-4 text-[var(--warning-text)]"}),e.jsx("h2",{className:"text-lg font-semibold mb-2",children:s("license.page.errorTitle","Unable to load license")}),e.jsx("p",{className:"text-[var(--text-secondary)] mb-4",children:i||s("license.page.errorDesc","License information is not available.")}),e.jsx("button",{onClick:()=>l(),className:"btn-primary px-4 py-2",children:s("common.retry","Retry")})]})});const P=T.hasAllLicenseFeatures(t.enabledFeatures),A=O(t,s);return e.jsxs("div",{className:"p-6 space-y-6",children:[d&&e.jsxs("div",{className:"flex items-center gap-3 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg",children:[e.jsx(a.AlertTriangle,{className:"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium text-red-900 dark:text-red-300",children:s("license.halted.warning","Licence suspendue")}),m&&e.jsx("p",{className:"text-sm text-red-800 dark:text-red-200 mt-1",children:m})]})]}),e.jsx(q,{showTrialSuccess:N,isInGracePeriod:t.isInGracePeriod,validationResult:$,gracePeriodDays:t.gracePeriodDays,onTrialSuccessClose:()=>v(!1),onValidationResultClear:L,t:s}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:s("license.page.title","License Management")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:s("license.page.subtitle","View and manage your platform license")})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(T.LicenseStatusBadge,{showDetails:!0}),e.jsxs("button",{onClick:S,disabled:u,className:"btn-secondary px-4 py-2 flex items-center gap-2",children:[u?e.jsx(a.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(a.ShieldCheck,{className:"w-4 h-4"}),u?s("license.validating","Validating..."):s("license.validate","Validate")]}),e.jsxs("button",{onClick:()=>o(!0),className:"btn-primary px-4 py-2 flex items-center gap-2",children:[e.jsx(a.Key,{className:"w-4 h-4"}),s("license.activate","Activate")]})]})]}),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:A.map(h=>e.jsxs("div",{className:`card p-4 border ${E[h.color]}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(h.icon,{className:"w-5 h-5 opacity-80"}),e.jsx("span",{className:"text-sm opacity-80",children:h.label})]}),e.jsx("div",{className:"text-2xl font-bold",children:h.value})]},h.label))}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Zap,{className:"w-5 h-5"}),s("license.info.limits","Limits")]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsx(R,{icon:a.Users,label:s("license.page.usersLimit","Users"),max:t.limits.users,current:r?.activeUsers??0,margin:10,t:s}),e.jsx(R,{icon:a.Building,label:s("license.page.tenantsLimit","Tenants (B2B)"),max:t.limits.tenants,current:r?.activeTenants??0,margin:2,t:s})]}),(()=>{const h=["users","tenants","max_instances","max_users"],C=Object.entries(t.limits.custom??{}).filter(([f])=>!h.includes(f));return C.length===0?null:e.jsxs("div",{className:"mt-4 pt-4 border-t border-[var(--border-color)]",children:[e.jsx("h3",{className:"text-sm font-medium text-[var(--text-secondary)] mb-3",children:s("license.page.customLimits","Custom Limits")}),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:C.map(([f,I])=>e.jsxs("div",{className:"flex justify-between items-center py-1.5 px-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:f}),e.jsx("span",{className:"text-sm font-medium",children:I})]},f))})]})})()]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Calendar,{className:"w-5 h-5"}),s("license.page.details","License Details")]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(g,{label:s("license.info.productId","Product"),value:t.productId}),e.jsx(g,{label:s("license.info.company","Company"),value:t.companyName||"-"}),e.jsx(g,{label:s("license.info.edition","Edition"),value:s(`license.edition.${t.edition.toLowerCase()}`,t.edition)}),e.jsx(g,{label:s("license.info.status","Status"),value:s(`license.status.${t.status.toLowerCase()}`,t.status)}),e.jsx(g,{label:s("license.info.activatedAt","Activated At"),value:D(t.activatedAt)}),e.jsx(g,{label:s("license.info.expiresAt","Expires At"),value:t.isPerpetual?s("license.page.never","Never (Perpetual)"):D(t.expiresAt)})]})]}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Server,{className:"w-5 h-5"}),s("license.page.subscription","Subscription")]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(g,{label:s("license.page.licenseType","License Type"),value:t.isPerpetual?s("license.page.perpetual","Perpetual"):t.isInTrial?s("license.edition.trial","Trial"):s("license.page.subscription","Subscription")}),e.jsx(g,{label:s("license.page.maxUsers","Max Users"),value:t.limits.users>0?t.limits.users.toString():s("license.page.unlimited","Unlimited")}),e.jsx(g,{label:s("license.page.gracePeriodDays","Grace Period"),value:t.gracePeriodDays>0?s("license.page.gracePeriodValue","{{days}} days",{days:t.gracePeriodDays}):s("license.page.noGracePeriod","None")}),e.jsx(g,{label:s("license.page.renewalDate","Renewal Date"),value:D(t.renewalDate)}),e.jsx(g,{label:s("license.page.mode","Mode"),value:t.isReadOnlyMode?s("license.page.readOnly","Read-only"):t.isInTrial?s("license.edition.trial","Trial"):s("license.page.licensed","Licensed")}),t.isInGracePeriod&&e.jsx(g,{label:s("license.page.gracePeriodStatus","Grace Period Status"),value:s("license.page.inGracePeriod","Active"),highlight:"yellow"})]})]}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Monitor,{className:"w-5 h-5"}),s("license.page.machineInfo","Machine")]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("div",{className:"flex justify-between items-center mb-1",children:e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s("license.page.machineName","Machine Name")})}),e.jsx("span",{className:"text-xs font-mono text-[var(--text-primary)] break-all",children:t.machineName||"-"})]}),e.jsxs("div",{className:"py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("div",{className:"flex justify-between items-center mb-1",children:e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s("license.page.instanceId","Instance ID")})}),e.jsx("span",{className:"text-xs font-mono text-[var(--text-primary)] break-all",children:t.instanceId||"-"})]}),e.jsxs("div",{className:"py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("div",{className:"flex justify-between items-center mb-1",children:e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s("license.page.licenseId","License ID")})}),e.jsx("span",{className:"text-xs font-mono text-[var(--text-primary)] break-all",children:t.licenseServerId||"-"})]})]})]})]}),e.jsxs("div",{className:"card p-6",children:[e.jsxs("h2",{className:"text-lg font-semibold mb-4 flex items-center gap-2",children:[e.jsx(a.Layers,{className:"w-5 h-5"}),s("license.info.features","Features")]}),e.jsx(K,{hasAllFeatures:P,enabledFeatures:t.enabledFeatures,availableFeatures:t.availableFeatures,t:s})]}),e.jsx(T.LicenseActivationDialog,{open:c,onOpenChange:o})]})}function g({label:s,value:t,highlight:r}){const n=r==="yellow"?"text-amber-600 dark:text-amber-400 font-semibold":r==="red"?"text-red-600 dark:text-red-400 font-semibold":r==="green"?"text-green-600 dark:text-green-400 font-semibold":"text-[var(--text-primary)]";return e.jsxs("div",{className:"flex justify-between items-center py-2 border-b border-[var(--border-color)] last:border-b-0",children:[e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:s}),e.jsx("span",{className:`text-sm font-medium ${n}`,children:t})]})}function X(s,t){return s?"text-red-500":t?"text-amber-500":"text-blue-500"}function Z(s,t){return s?"text-red-500":t?"text-amber-500":"text-[var(--text-primary)]"}function R({icon:s,label:t,max:r,current:n,margin:i=0,t:l}){const d=r<=0,m=r,c=r+i,o=140,x=12,b=(o-x)/2,N=o/2,v=135,u=270,$=c>0?Math.min(1,n/c):0,S=c>0?m/c:1,L=i>0&&n>m&&n<=c,P=n>c;let A="#3b82f6";P?A="#ef4444":L&&(A="#f59e0b");const h="rgba(245, 158, 11, 0.25)",C=j=>{const y=j*Math.PI/180;return{x:N+b*Math.cos(y),y:N+b*Math.sin(y)}},f=j=>{if(j<=0)return"";const y=v+j,k=C(v),p=C(y),M=j>180?1:0;return`M ${k.x} ${k.y} A ${b} ${b} 0 ${M} 1 ${p.x} ${p.y}`},I=c>0?Math.round(n/m*100):0;return d?e.jsxs("div",{className:"flex flex-col items-center gap-3 py-4",children:[e.jsxs("div",{className:"relative",style:{width:o,height:o},children:[e.jsxs("svg",{width:o,height:o,children:[e.jsx("path",{d:f(u),fill:"none",stroke:"var(--bg-tertiary)",strokeWidth:x,strokeLinecap:"round"}),e.jsx("path",{d:f(u),fill:"none",stroke:"#22c55e",strokeWidth:x,strokeLinecap:"round",opacity:.5})]}),e.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[e.jsx(s,{className:"w-6 h-6 text-green-500 mb-1"}),e.jsx("span",{className:"text-lg font-bold text-green-500",children:"∞"})]})]}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)]",children:t}),e.jsx("span",{className:"text-xs text-[var(--text-secondary)]",children:l("license.page.unlimited","Unlimited")})]}):e.jsxs("div",{className:"flex flex-col items-center gap-3 py-4",children:[e.jsxs("div",{className:"relative",style:{width:o,height:o},children:[e.jsxs("svg",{width:o,height:o,children:[e.jsx("path",{d:f(u),fill:"none",stroke:"var(--bg-tertiary)",strokeWidth:x,strokeLinecap:"round"}),i>0&&(()=>{const j=u*(1-S),y=v+u*S,k=C(y),p=C(v+u),M=j>180?1:0,U=`M ${k.x} ${k.y} A ${b} ${b} 0 ${M} 1 ${p.x} ${p.y}`;return e.jsx("path",{d:U,fill:"none",stroke:h,strokeWidth:x,strokeLinecap:"round"})})(),e.jsx("path",{d:f(u*$),fill:"none",stroke:A,strokeWidth:x,strokeLinecap:"round",style:{transition:"stroke 0.3s, d 0.3s"}}),i>0&&(()=>{const j=v+u*S,y=b-x/2-2,k=b+x/2+2,p=j*Math.PI/180;return e.jsx("line",{x1:N+y*Math.cos(p),y1:N+y*Math.sin(p),x2:N+k*Math.cos(p),y2:N+k*Math.sin(p),stroke:"var(--text-secondary)",strokeWidth:2,strokeLinecap:"round"})})()]}),e.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center",children:[e.jsx(s,{className:`w-5 h-5 mb-0.5 ${X(P,L)}`}),e.jsxs("span",{className:`text-2xl font-bold ${Z(P,L)}`,children:[I,"%"]}),e.jsxs("span",{className:"text-xs text-[var(--text-secondary)]",children:[n," / ",m]})]})]}),e.jsx("span",{className:"text-sm font-medium text-[var(--text-primary)]",children:t}),i>0&&e.jsxs("span",{className:`text-xs ${L||P?"text-amber-600 dark:text-amber-400":"text-[var(--text-secondary)]"}`,children:["+",i," ",l("license.page.tolerance","tolerance")]})]})}exports.LicenseManagementPage=W;
|
|
2
|
+
//# sourceMappingURL=index-CH0pTHy1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-COA_xJVJ.js","sources":["../../src/pages/platform/administration/configuration/license/LicenseManagementPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport type { TFunction } from 'i18next';\r\nimport { useSearchParams } from 'react-router-dom';\r\nimport { useLicense } from '@/contexts/LicenseContext';\r\nimport { api } from '@/services/api/apiClient';\r\nimport { hasAllLicenseFeatures } from '@/utils/licenseUtils';\r\nimport { LicenseStatusBadge } from '@/components/license/LicenseStatusBadge';\r\nimport { LicenseActivationDialog } from '@/components/license/LicenseActivationDialog';\r\nimport type { LicenseFeatureGroup } from '@/contexts/LicenseContext';\r\nimport {\r\n Shield, Calendar, Key, Layers, Users, Building, Zap, Server,\r\n CheckCircle, Clock, AlertTriangle, Loader2, X, Infinity as InfinityIcon,\r\n Lock, Unlock, ShieldCheck, Monitor\r\n} from 'lucide-react';\r\n\r\nconst colorClasses = {\r\n blue: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n green: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n yellow: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n red: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\r\n neutral: 'bg-[var(--bg-secondary)] text-[var(--text-primary)] border-[var(--border-color)]',\r\n};\r\n\r\ninterface License {\r\n isReadOnlyMode: boolean;\r\n isInTrial: boolean;\r\n trialDaysRemaining: number;\r\n status: string;\r\n daysUntilExpiration: number;\r\n isInGracePeriod: boolean;\r\n isPerpetual: boolean;\r\n edition: string;\r\n limits: { users: number };\r\n gracePeriodDays: number;\r\n enabledFeatures: string[];\r\n}\r\n\r\nfunction getStatusColor(license: License) {\r\n if (license.status === 'NoLicense') return 'red' as const;\r\n if (license.isReadOnlyMode) return 'red' as const;\r\n if (license.isInGracePeriod) return 'yellow' as const;\r\n if (license.isInTrial && license.trialDaysRemaining <= 7) return 'yellow' as const;\r\n if (license.status === 'Active' && license.daysUntilExpiration <= 30) return 'yellow' as const;\r\n if (license.status === 'Active') return 'green' as const;\r\n return 'red' as const;\r\n}\r\n\r\nfunction getLicenseDaysColor(license: { isPerpetual: boolean; isInTrial: boolean; trialDaysRemaining: number; daysUntilExpiration: number }): 'red' | 'yellow' | 'green' | 'blue' {\r\n if (license.isPerpetual) return 'green';\r\n const daysRemaining = license.isInTrial ? license.trialDaysRemaining : license.daysUntilExpiration;\r\n if (daysRemaining <= 15) return 'red';\r\n if (daysRemaining <= 30) return 'yellow';\r\n return 'green';\r\n}\r\n\r\nfunction formatDate(dateStr: string | null): string {\r\n if (!dateStr) return '-';\r\n return new Date(dateStr).toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'long',\r\n day: 'numeric',\r\n });\r\n}\r\n\r\nfunction buildKpiCards(license: License, t: TFunction) {\r\n const statusColor = getStatusColor(license);\r\n const daysRemaining = license.isInTrial ? license.trialDaysRemaining : license.daysUntilExpiration;\r\n const daysColor = getLicenseDaysColor(license);\r\n\r\n return [\r\n {\r\n label: t('license.info.edition', 'Edition'),\r\n value: t(`license.edition.${license.edition.toLowerCase()}`, license.edition),\r\n icon: Shield,\r\n color: 'blue' as const,\r\n },\r\n {\r\n label: t('license.info.status', 'Status'),\r\n value: license.isInGracePeriod\r\n ? t('license.page.gracePeriod', 'Grace Period')\r\n : t(`license.status.${license.status.toLowerCase()}`, license.status),\r\n icon: license.isReadOnlyMode ? AlertTriangle : CheckCircle,\r\n color: statusColor,\r\n },\r\n {\r\n label: t('license.page.daysRemaining', 'Days remaining'),\r\n value: license.isPerpetual ? '\\u221E' : daysRemaining.toString(),\r\n icon: license.isPerpetual ? InfinityIcon : Clock,\r\n color: daysColor,\r\n },\r\n {\r\n label: t('license.page.maxUsers', 'Max Users'),\r\n value: license.limits.users > 0 ? license.limits.users.toString() : t('license.page.unlimited', 'Unlimited'),\r\n icon: Users,\r\n color: 'blue' as const,\r\n },\r\n ];\r\n}\r\n\r\n// Sub-component: Status Banners\r\ninterface StatusBannersProps {\r\n readonly showTrialSuccess: boolean;\r\n readonly isInGracePeriod: boolean;\r\n readonly validationResult: { type: 'success' | 'revoked' | 'error'; message: string } | null;\r\n readonly gracePeriodDays: number;\r\n readonly onTrialSuccessClose: () => void;\r\n readonly onValidationResultClear: () => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction StatusBanners({\r\n showTrialSuccess, isInGracePeriod, validationResult, gracePeriodDays,\r\n onTrialSuccessClose, onValidationResultClear, t\r\n}: StatusBannersProps) {\r\n return (\r\n <>\r\n {showTrialSuccess && (\r\n <div className=\"flex items-center gap-3 p-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg animate-in fade-in slide-in-from-top\">\r\n <CheckCircle className=\"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-green-900 dark:text-green-300\">\r\n {t('license.trial.successBanner', 'Your 30-day trial is activated!')}\r\n </p>\r\n </div>\r\n <button\r\n onClick={onTrialSuccessClose}\r\n className=\"text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {isInGracePeriod && (\r\n <div className=\"flex items-center gap-3 p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg\">\r\n <AlertTriangle className=\"w-5 h-5 text-amber-600 dark:text-amber-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-amber-900 dark:text-amber-300\">\r\n {t('license.page.gracePeriodBanner', 'Your license has expired. You are in a {{days}}-day grace period. Renew to avoid service interruption.', { days: gracePeriodDays })}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {validationResult && (\r\n <div className={`flex items-center gap-3 p-4 rounded-lg border ${\r\n validationResult.type === 'success'\r\n ? 'bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800'\r\n : validationResult.type === 'revoked'\r\n ? 'bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800'\r\n : 'bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800'\r\n }`}>\r\n {validationResult.type === 'success'\r\n ? <CheckCircle className=\"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0\" />\r\n : <AlertTriangle className={`w-5 h-5 flex-shrink-0 ${\r\n validationResult.type === 'revoked'\r\n ? 'text-red-600 dark:text-red-400'\r\n : 'text-amber-600 dark:text-amber-400'\r\n }`} />\r\n }\r\n <p className={`text-sm font-medium flex-1 ${\r\n validationResult.type === 'success'\r\n ? 'text-green-900 dark:text-green-300'\r\n : validationResult.type === 'revoked'\r\n ? 'text-red-900 dark:text-red-300'\r\n : 'text-amber-900 dark:text-amber-300'\r\n }`}>\r\n {validationResult.message}\r\n </p>\r\n <button\r\n onClick={onValidationResultClear}\r\n className={\r\n validationResult.type === 'success'\r\n ? 'text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300'\r\n : validationResult.type === 'revoked'\r\n ? 'text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300'\r\n : 'text-amber-600 dark:text-amber-400 hover:text-amber-700 dark:hover:text-amber-400'\r\n }\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n\r\n// Sub-component: Features Grid\r\ninterface FeaturesGridProps {\r\n readonly hasAllFeatures: boolean;\r\n readonly enabledFeatures: string[];\r\n readonly availableFeatures?: LicenseFeatureGroup[];\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction FeaturesGrid({ hasAllFeatures, enabledFeatures, availableFeatures, t }: FeaturesGridProps) {\r\n if (!availableFeatures || availableFeatures.length === 0) {\r\n return (\r\n <p className=\"text-[var(--text-secondary)] text-sm italic\">\r\n {t('license.page.noFeatures', 'No features enabled')}\r\n </p>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n {hasAllFeatures && (\r\n <div className=\"flex items-center gap-2 p-3 mb-4 bg-[var(--success-bg)] text-[var(--success-text)] rounded-lg border border-[var(--success-border)]\">\r\n <CheckCircle className=\"w-5 h-5\" />\r\n <span className=\"font-medium\">{t('license.page.allFeatures', 'All features enabled')}</span>\r\n </div>\r\n )}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\r\n {availableFeatures.map(({ group, features }) => (\r\n <div key={group}>\r\n <h3 className=\"text-sm font-semibold text-[var(--text-secondary)] uppercase tracking-wider mb-3\">\r\n {t(`license.group.${group}`, group)}\r\n </h3>\r\n <div className=\"space-y-2\">\r\n {features.map((code) => {\r\n const enabled = hasAllFeatures || enabledFeatures.some(\r\n f => f.toLowerCase() === code.toLowerCase()\r\n );\r\n return (\r\n <div\r\n key={code}\r\n className={`flex items-center gap-2 px-3 py-2 rounded-lg border ${\r\n enabled\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]'\r\n : 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)] opacity-60'\r\n }`}\r\n >\r\n {enabled\r\n ? <Unlock className=\"w-4 h-4 flex-shrink-0\" />\r\n : <Lock className=\"w-4 h-4 flex-shrink-0\" />\r\n }\r\n <span className=\"text-sm font-medium\">{t(`license.module.${code}`, code)}</span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n {!hasAllFeatures && enabledFeatures.length === 0 && (\r\n <p className=\"text-[var(--text-secondary)] text-sm italic mt-3\">\r\n {t('license.page.noFeatures', 'No features enabled')}\r\n </p>\r\n )}\r\n </>\r\n );\r\n}\r\n\r\nfunction useValidateLicense(refreshLicense: () => Promise<void>, t: (key: string, fallback: string, opts?: Record<string, unknown>) => string) {\r\n const [isValidating, setIsValidating] = useState(false);\r\n const [validationResult, setValidationResult] = useState<{ type: 'success' | 'revoked' | 'error'; message: string } | null>(null);\r\n\r\n const handleValidate = useCallback(async () => {\r\n setIsValidating(true);\r\n setValidationResult(null);\r\n try {\r\n const result = await api.post<{ valid: boolean; revoked: boolean; error?: string }>(\r\n '/api/administration/license/validate-server'\r\n );\r\n if (result.revoked) {\r\n setValidationResult({ type: 'revoked', message: t('license.validationRevoked', 'The license has been revoked by the server.') });\r\n await refreshLicense();\r\n } else if (result.valid) {\r\n setValidationResult({ type: 'success', message: t('license.validationSuccess', 'License is valid') });\r\n await refreshLicense();\r\n } else {\r\n setValidationResult({ type: 'error', message: result.error || t('license.validationError', 'Unable to validate the license with the server.') });\r\n }\r\n } catch {\r\n setValidationResult({ type: 'error', message: t('license.validationError', 'Unable to validate the license with the server.') });\r\n } finally {\r\n setIsValidating(false);\r\n setTimeout(() => setValidationResult(null), 5000);\r\n }\r\n }, [t, refreshLicense]);\r\n\r\n const clearValidationResult = useCallback(() => setValidationResult(null), []);\r\n\r\n return { isValidating, validationResult, handleValidate, clearValidationResult };\r\n}\r\n\r\nexport function LicenseManagementPage(): ReactElement | null {\r\n const { t } = useTranslation('admin');\r\n const { license, usage, isLoading, error, refreshLicense, isHalted, haltReason } = useLicense();\r\n const [showActivation, setShowActivation] = useState(false);\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n const [showTrialSuccess, setShowTrialSuccess] = useState(false);\r\n const { isValidating, validationResult, handleValidate, clearValidationResult } = useValidateLicense(refreshLicense, t);\r\n\r\n // Refresh license data when the page is displayed (e.g. after creating a tenant)\r\n useEffect(() => {\r\n refreshLicense();\r\n }, [refreshLicense]);\r\n\r\n useEffect(() => {\r\n if (searchParams.get('trial') === 'success') {\r\n setShowTrialSuccess(true); // eslint-disable-line react-hooks/set-state-in-effect -- conditional URL param check\r\n const timer = setTimeout(() => {\r\n setShowTrialSuccess(false);\r\n searchParams.delete('trial');\r\n setSearchParams(searchParams, { replace: true });\r\n }, 5000);\r\n return () => clearTimeout(timer);\r\n }\r\n }, [searchParams, setSearchParams]);\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--text-secondary)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (error || !license) {\r\n return (\r\n <div className=\"p-6\">\r\n <div className=\"card p-6 text-center\">\r\n <AlertTriangle className=\"w-12 h-12 mx-auto mb-4 text-[var(--warning-text)]\" />\r\n <h2 className=\"text-lg font-semibold mb-2\">{t('license.page.errorTitle', 'Unable to load license')}</h2>\r\n <p className=\"text-[var(--text-secondary)] mb-4\">{error || t('license.page.errorDesc', 'License information is not available.')}</p>\r\n <button\r\n onClick={() => refreshLicense()}\r\n className=\"btn-primary px-4 py-2\"\r\n >\r\n {t('common.retry', 'Retry')}\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n const hasAllFeatures = hasAllLicenseFeatures(license.enabledFeatures);\r\n const kpiCards = buildKpiCards(license, t);\r\n\r\n return (\r\n <div className=\"p-6 space-y-6\">\r\n {isHalted && (\r\n <div className=\"flex items-center gap-3 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-red-900 dark:text-red-300\">\r\n {t('license.halted.warning', 'Licence suspendue')}\r\n </p>\r\n {haltReason && (\r\n <p className=\"text-sm text-red-800 dark:text-red-200 mt-1\">\r\n {haltReason}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <StatusBanners\r\n showTrialSuccess={showTrialSuccess}\r\n isInGracePeriod={license.isInGracePeriod}\r\n validationResult={validationResult}\r\n gracePeriodDays={license.gracePeriodDays}\r\n onTrialSuccessClose={() => setShowTrialSuccess(false)}\r\n onValidationResultClear={clearValidationResult}\r\n t={t}\r\n />\r\n\r\n {/* Banners handled by StatusBanners component above */}\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('license.page.title', 'License Management')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)] mt-1\">\r\n {t('license.page.subtitle', 'View and manage your platform license')}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <LicenseStatusBadge showDetails />\r\n <button\r\n onClick={handleValidate}\r\n disabled={isValidating}\r\n className=\"btn-secondary px-4 py-2 flex items-center gap-2\"\r\n >\r\n {isValidating\r\n ? <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n : <ShieldCheck className=\"w-4 h-4\" />\r\n }\r\n {isValidating\r\n ? t('license.validating', 'Validating...')\r\n : t('license.validate', 'Validate')}\r\n </button>\r\n <button\r\n onClick={() => setShowActivation(true)}\r\n className=\"btn-primary px-4 py-2 flex items-center gap-2\"\r\n >\r\n <Key className=\"w-4 h-4\" />\r\n {t('license.activate', 'Activate')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* KPI Cards */}\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n {kpiCards.map((card) => (\r\n <div key={card.label} className={`card p-4 border ${colorClasses[card.color]}`}>\r\n <div className=\"flex items-center gap-2 mb-2\">\r\n <card.icon className=\"w-5 h-5 opacity-80\" />\r\n <span className=\"text-sm opacity-80\">{card.label}</span>\r\n </div>\r\n <div className=\"text-2xl font-bold\">{card.value}</div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Limits Section */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Zap className=\"w-5 h-5\" />\r\n {t('license.info.limits', 'Limits')}\r\n </h2>\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n <CircularGauge\r\n icon={Users}\r\n label={t('license.page.usersLimit', 'Users')}\r\n max={license.limits.users}\r\n current={usage?.activeUsers ?? 0}\r\n margin={10}\r\n t={t}\r\n />\r\n <CircularGauge\r\n icon={Building}\r\n label={t('license.page.tenantsLimit', 'Tenants (B2B)')}\r\n max={license.limits.tenants}\r\n current={usage?.activeTenants ?? 0}\r\n margin={2}\r\n t={t}\r\n />\r\n </div>\r\n {/* Custom limits from JWT */}\r\n {(() => {\r\n const standardKeys = ['users', 'tenants', 'max_instances', 'max_users'];\r\n const customEntries = Object.entries(license.limits.custom ?? {}).filter(\r\n ([key]) => !standardKeys.includes(key)\r\n );\r\n if (customEntries.length === 0) return null;\r\n return (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <h3 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n {t('license.page.customLimits', 'Custom Limits')}\r\n </h3>\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3\">\r\n {customEntries.map(([key, value]) => (\r\n <div key={key} className=\"flex justify-between items-center py-1.5 px-3 bg-[var(--bg-secondary)] rounded-lg\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{key}</span>\r\n <span className=\"text-sm font-medium\">{value}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n })()}\r\n </div>\r\n\r\n {/* Details + Subscription + Machine Section */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\r\n {/* License Details */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Calendar className=\"w-5 h-5\" />\r\n {t('license.page.details', 'License Details')}\r\n </h2>\r\n <div className=\"space-y-3\">\r\n <DetailRow label={t('license.info.productId', 'Product')} value={license.productId} />\r\n <DetailRow label={t('license.info.company', 'Company')} value={license.companyName || '-'} />\r\n <DetailRow\r\n label={t('license.info.edition', 'Edition')}\r\n value={t(`license.edition.${license.edition.toLowerCase()}`, license.edition)}\r\n />\r\n <DetailRow\r\n label={t('license.info.status', 'Status')}\r\n value={t(`license.status.${license.status.toLowerCase()}`, license.status)}\r\n />\r\n <DetailRow\r\n label={t('license.info.activatedAt', 'Activated At')}\r\n value={formatDate(license.activatedAt)}\r\n />\r\n <DetailRow\r\n label={t('license.info.expiresAt', 'Expires At')}\r\n value={license.isPerpetual\r\n ? t('license.page.never', 'Never (Perpetual)')\r\n : formatDate(license.expiresAt)}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Subscription Info */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Server className=\"w-5 h-5\" />\r\n {t('license.page.subscription', 'Subscription')}\r\n </h2>\r\n <div className=\"space-y-3\">\r\n <DetailRow\r\n label={t('license.page.licenseType', 'License Type')}\r\n value={license.isPerpetual\r\n ? t('license.page.perpetual', 'Perpetual')\r\n : license.isInTrial\r\n ? t('license.edition.trial', 'Trial')\r\n : t('license.page.subscription', 'Subscription')}\r\n />\r\n <DetailRow\r\n label={t('license.page.maxUsers', 'Max Users')}\r\n value={license.limits.users > 0 ? license.limits.users.toString() : t('license.page.unlimited', 'Unlimited')}\r\n />\r\n <DetailRow\r\n label={t('license.page.gracePeriodDays', 'Grace Period')}\r\n value={license.gracePeriodDays > 0\r\n ? t('license.page.gracePeriodValue', '{{days}} days', { days: license.gracePeriodDays })\r\n : t('license.page.noGracePeriod', 'None')}\r\n />\r\n <DetailRow\r\n label={t('license.page.renewalDate', 'Renewal Date')}\r\n value={formatDate(license.renewalDate)}\r\n />\r\n <DetailRow\r\n label={t('license.page.mode', 'Mode')}\r\n value={license.isReadOnlyMode\r\n ? t('license.page.readOnly', 'Read-only')\r\n : license.isInTrial\r\n ? t('license.edition.trial', 'Trial')\r\n : t('license.page.licensed', 'Licensed')}\r\n />\r\n {license.isInGracePeriod && (\r\n <DetailRow\r\n label={t('license.page.gracePeriodStatus', 'Grace Period Status')}\r\n value={t('license.page.inGracePeriod', 'Active')}\r\n highlight=\"yellow\"\r\n />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Machine Info */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Monitor className=\"w-5 h-5\" />\r\n {t('license.page.machineInfo', 'Machine')}\r\n </h2>\r\n <div className=\"space-y-3\">\r\n <div className=\"py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <div className=\"flex justify-between items-center mb-1\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{t('license.page.machineName', 'Machine Name')}</span>\r\n </div>\r\n <span className=\"text-xs font-mono text-[var(--text-primary)] break-all\">\r\n {license.machineName || '-'}\r\n </span>\r\n </div>\r\n <div className=\"py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <div className=\"flex justify-between items-center mb-1\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{t('license.page.instanceId', 'Instance ID')}</span>\r\n </div>\r\n <span className=\"text-xs font-mono text-[var(--text-primary)] break-all\">\r\n {license.instanceId || '-'}\r\n </span>\r\n </div>\r\n <div className=\"py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <div className=\"flex justify-between items-center mb-1\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{t('license.page.licenseId', 'License ID')}</span>\r\n </div>\r\n <span className=\"text-xs font-mono text-[var(--text-primary)] break-all\">\r\n {license.licenseServerId || '-'}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Layers className=\"w-5 h-5\" />\r\n {t('license.info.features', 'Features')}\r\n </h2>\r\n <FeaturesGrid\r\n hasAllFeatures={hasAllFeatures}\r\n enabledFeatures={license.enabledFeatures}\r\n availableFeatures={license.availableFeatures}\r\n t={t}\r\n />\r\n </div>\r\n\r\n <LicenseActivationDialog open={showActivation} onOpenChange={setShowActivation} />\r\n </div>\r\n );\r\n}\r\n\r\nfunction DetailRow({ label, value, highlight }: { label: string; value: string; highlight?: 'yellow' | 'red' | 'green' }) {\r\n const highlightClass = highlight === 'yellow'\r\n ? 'text-amber-600 dark:text-amber-400 font-semibold'\r\n : highlight === 'red'\r\n ? 'text-red-600 dark:text-red-400 font-semibold'\r\n : highlight === 'green'\r\n ? 'text-green-600 dark:text-green-400 font-semibold'\r\n : 'text-[var(--text-primary)]';\r\n\r\n return (\r\n <div className=\"flex justify-between items-center py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{label}</span>\r\n <span className={`text-sm font-medium ${highlightClass}`}>{value}</span>\r\n </div>\r\n );\r\n}\r\n\r\nfunction getGaugeIconColor(exceededEffective: boolean, inToleranceZone: boolean): string {\r\n if (exceededEffective) return 'text-red-500';\r\n if (inToleranceZone) return 'text-amber-500';\r\n return 'text-blue-500';\r\n}\r\n\r\nfunction getGaugeTextColor(exceededEffective: boolean, inToleranceZone: boolean): string {\r\n if (exceededEffective) return 'text-red-500';\r\n if (inToleranceZone) return 'text-amber-500';\r\n return 'text-[var(--text-primary)]';\r\n}\r\n\r\nfunction CircularGauge({ icon: Icon, label, max, current, margin = 0, t }: {\r\n icon: typeof Users;\r\n label: string;\r\n max: number;\r\n current: number;\r\n margin?: number;\r\n t: (key: string, fallback: string, opts?: Record<string, unknown>) => string;\r\n}) {\r\n const unlimited = max <= 0;\r\n // `max` is the licensed contractual limit (from JWT, e.g. 50 users).\r\n // The tolerance `margin` is ADDED on top to form the hard upper bound.\r\n // Example: licensed=50 + margin=10 → total=60.\r\n const licensedLimit = max;\r\n const total = max + margin;\r\n\r\n // SVG arc parameters\r\n const size = 140;\r\n const strokeWidth = 12;\r\n const radius = (size - strokeWidth) / 2;\r\n const center = size / 2;\r\n // Arc spans 270 degrees (from 135° to 405°)\r\n const startAngle = 135;\r\n const totalArc = 270;\r\n\r\n // Percentages\r\n const usagePercent = total > 0 ? Math.min(1, current / total) : 0;\r\n const licensedPercent = total > 0 ? licensedLimit / total : 1;\r\n\r\n // Zone detection\r\n const inToleranceZone = margin > 0 && current > licensedLimit && current <= total;\r\n const exceededEffective = current > total;\r\n\r\n // Colors\r\n let usageColor = '#3b82f6'; // blue-500\r\n if (exceededEffective) usageColor = '#ef4444'; // red-500\r\n else if (inToleranceZone) usageColor = '#f59e0b'; // amber-500\r\n\r\n const toleranceTrackColor = 'rgba(245, 158, 11, 0.25)'; // amber with opacity\r\n\r\n // Helper to compute SVG arc endpoint\r\n const polarToCartesian = (angleDeg: number) => {\r\n const rad = (angleDeg * Math.PI) / 180;\r\n return {\r\n x: center + radius * Math.cos(rad),\r\n y: center + radius * Math.sin(rad),\r\n };\r\n };\r\n\r\n // Build an arc path from startAngle spanning `sweep` degrees\r\n const describeArc = (sweep: number) => {\r\n if (sweep <= 0) return '';\r\n const endAngle = startAngle + sweep;\r\n const start = polarToCartesian(startAngle);\r\n const end = polarToCartesian(endAngle);\r\n const largeArc = sweep > 180 ? 1 : 0;\r\n return `M ${start.x} ${start.y} A ${radius} ${radius} 0 ${largeArc} 1 ${end.x} ${end.y}`;\r\n };\r\n\r\n // Percentage display\r\n const displayPercent = total > 0 ? Math.round((current / licensedLimit) * 100) : 0;\r\n\r\n if (unlimited) {\r\n return (\r\n <div className=\"flex flex-col items-center gap-3 py-4\">\r\n <div className=\"relative\" style={{ width: size, height: size }}>\r\n <svg width={size} height={size}>\r\n {/* Background track */}\r\n <path\r\n d={describeArc(totalArc)}\r\n fill=\"none\"\r\n stroke=\"var(--bg-tertiary)\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n {/* Full green arc for unlimited */}\r\n <path\r\n d={describeArc(totalArc)}\r\n fill=\"none\"\r\n stroke=\"#22c55e\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n opacity={0.5}\r\n />\r\n </svg>\r\n <div className=\"absolute inset-0 flex flex-col items-center justify-center\">\r\n <Icon className=\"w-6 h-6 text-green-500 mb-1\" />\r\n <span className=\"text-lg font-bold text-green-500\">∞</span>\r\n </div>\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{label}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)]\">{t('license.page.unlimited', 'Unlimited')}</span>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"flex flex-col items-center gap-3 py-4\">\r\n <div className=\"relative\" style={{ width: size, height: size }}>\r\n <svg width={size} height={size}>\r\n {/* Background track */}\r\n <path\r\n d={describeArc(totalArc)}\r\n fill=\"none\"\r\n stroke=\"var(--bg-tertiary)\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n {/* Tolerance zone: arc from licensed limit to effective limit */}\r\n {margin > 0 && (() => {\r\n const toleranceSweep = totalArc * (1 - licensedPercent);\r\n const toleranceStartAngle = startAngle + totalArc * licensedPercent;\r\n const tStart = polarToCartesian(toleranceStartAngle);\r\n const tEnd = polarToCartesian(startAngle + totalArc);\r\n const largeArc = toleranceSweep > 180 ? 1 : 0;\r\n const tolerancePath = `M ${tStart.x} ${tStart.y} A ${radius} ${radius} 0 ${largeArc} 1 ${tEnd.x} ${tEnd.y}`;\r\n return (\r\n <path\r\n d={tolerancePath}\r\n fill=\"none\"\r\n stroke={toleranceTrackColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })()}\r\n {/* Usage arc */}\r\n <path\r\n d={describeArc(totalArc * usagePercent)}\r\n fill=\"none\"\r\n stroke={usageColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n style={{ transition: 'stroke 0.3s, d 0.3s' }}\r\n />\r\n {/* Licensed limit tick mark */}\r\n {margin > 0 && (() => {\r\n const tickAngle = startAngle + totalArc * licensedPercent;\r\n const innerR = radius - strokeWidth / 2 - 2;\r\n const outerR = radius + strokeWidth / 2 + 2;\r\n const rad = (tickAngle * Math.PI) / 180;\r\n return (\r\n <line\r\n x1={center + innerR * Math.cos(rad)}\r\n y1={center + innerR * Math.sin(rad)}\r\n x2={center + outerR * Math.cos(rad)}\r\n y2={center + outerR * Math.sin(rad)}\r\n stroke=\"var(--text-secondary)\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })()}\r\n </svg>\r\n {/* Center content */}\r\n <div className=\"absolute inset-0 flex flex-col items-center justify-center\">\r\n <Icon className={`w-5 h-5 mb-0.5 ${getGaugeIconColor(exceededEffective, inToleranceZone)}`} />\r\n <span className={`text-2xl font-bold ${getGaugeTextColor(exceededEffective, inToleranceZone)}`}>\r\n {displayPercent}%\r\n </span>\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {current} / {licensedLimit}\r\n </span>\r\n </div>\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{label}</span>\r\n {margin > 0 && (\r\n <span className={`text-xs ${inToleranceZone || exceededEffective ? 'text-amber-600 dark:text-amber-400' : 'text-[var(--text-secondary)]'}`}>\r\n +{margin} {t('license.page.tolerance', 'tolerance')}\r\n </span>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["colorClasses","getStatusColor","license","getLicenseDaysColor","daysRemaining","formatDate","dateStr","buildKpiCards","statusColor","daysColor","Shield","AlertTriangle","CheckCircle","InfinityIcon","Clock","Users","StatusBanners","showTrialSuccess","isInGracePeriod","validationResult","gracePeriodDays","onTrialSuccessClose","onValidationResultClear","t","jsxs","Fragment","jsx","X","FeaturesGrid","hasAllFeatures","enabledFeatures","availableFeatures","group","features","code","enabled","f","Unlock","Lock","useValidateLicense","refreshLicense","isValidating","setIsValidating","useState","setValidationResult","handleValidate","useCallback","result","api","clearValidationResult","LicenseManagementPage","useTranslation","usage","isLoading","error","isHalted","haltReason","useLicense","showActivation","setShowActivation","searchParams","setSearchParams","useSearchParams","setShowTrialSuccess","useEffect","timer","Loader2","hasAllLicenseFeatures","kpiCards","LicenseStatusBadge","ShieldCheck","Key","card","Zap","CircularGauge","Building","standardKeys","customEntries","key","value","Calendar","DetailRow","Server","Monitor","Layers","LicenseActivationDialog","label","highlight","highlightClass","getGaugeIconColor","exceededEffective","inToleranceZone","getGaugeTextColor","Icon","max","current","margin","unlimited","licensedLimit","total","size","strokeWidth","radius","center","startAngle","totalArc","usagePercent","licensedPercent","usageColor","toleranceTrackColor","polarToCartesian","angleDeg","rad","describeArc","sweep","endAngle","start","end","largeArc","displayPercent","toleranceSweep","toleranceStartAngle","tStart","tEnd","tolerancePath","tickAngle","innerR","outerR"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CH0pTHy1.js","sources":["../../src/pages/platform/administration/configuration/license/LicenseManagementPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport type { ReactElement } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport type { TFunction } from 'i18next';\r\nimport { useSearchParams } from 'react-router-dom';\r\nimport { useLicense } from '@/contexts/LicenseContext';\r\nimport { api } from '@/services/api/apiClient';\r\nimport { hasAllLicenseFeatures } from '@/utils/licenseUtils';\r\nimport { LicenseStatusBadge } from '@/components/license/LicenseStatusBadge';\r\nimport { LicenseActivationDialog } from '@/components/license/LicenseActivationDialog';\r\nimport type { LicenseFeatureGroup } from '@/contexts/LicenseContext';\r\nimport {\r\n Shield, Calendar, Key, Layers, Users, Building, Zap, Server,\r\n CheckCircle, Clock, AlertTriangle, Loader2, X, Infinity as InfinityIcon,\r\n Lock, Unlock, ShieldCheck, Monitor\r\n} from 'lucide-react';\r\n\r\nconst colorClasses = {\r\n blue: 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]',\r\n green: 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]',\r\n yellow: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]',\r\n red: 'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]',\r\n neutral: 'bg-[var(--bg-secondary)] text-[var(--text-primary)] border-[var(--border-color)]',\r\n};\r\n\r\ninterface License {\r\n isReadOnlyMode: boolean;\r\n isInTrial: boolean;\r\n trialDaysRemaining: number;\r\n status: string;\r\n daysUntilExpiration: number;\r\n isInGracePeriod: boolean;\r\n isPerpetual: boolean;\r\n edition: string;\r\n limits: { users: number };\r\n gracePeriodDays: number;\r\n enabledFeatures: string[];\r\n}\r\n\r\nfunction getStatusColor(license: License) {\r\n if (license.status === 'NoLicense') return 'red' as const;\r\n if (license.isReadOnlyMode) return 'red' as const;\r\n if (license.isInGracePeriod) return 'yellow' as const;\r\n if (license.isInTrial && license.trialDaysRemaining <= 7) return 'yellow' as const;\r\n if (license.status === 'Active' && license.daysUntilExpiration <= 30) return 'yellow' as const;\r\n if (license.status === 'Active') return 'green' as const;\r\n return 'red' as const;\r\n}\r\n\r\nfunction getLicenseDaysColor(license: { isPerpetual: boolean; isInTrial: boolean; trialDaysRemaining: number; daysUntilExpiration: number }): 'red' | 'yellow' | 'green' | 'blue' {\r\n if (license.isPerpetual) return 'green';\r\n const daysRemaining = license.isInTrial ? license.trialDaysRemaining : license.daysUntilExpiration;\r\n if (daysRemaining <= 15) return 'red';\r\n if (daysRemaining <= 30) return 'yellow';\r\n return 'green';\r\n}\r\n\r\nfunction formatDate(dateStr: string | null): string {\r\n if (!dateStr) return '-';\r\n return new Date(dateStr).toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'long',\r\n day: 'numeric',\r\n });\r\n}\r\n\r\nfunction buildKpiCards(license: License, t: TFunction) {\r\n const statusColor = getStatusColor(license);\r\n const daysRemaining = license.isInTrial ? license.trialDaysRemaining : license.daysUntilExpiration;\r\n const daysColor = getLicenseDaysColor(license);\r\n\r\n return [\r\n {\r\n label: t('license.info.edition', 'Edition'),\r\n value: t(`license.edition.${license.edition.toLowerCase()}`, license.edition),\r\n icon: Shield,\r\n color: 'blue' as const,\r\n },\r\n {\r\n label: t('license.info.status', 'Status'),\r\n value: license.isInGracePeriod\r\n ? t('license.page.gracePeriod', 'Grace Period')\r\n : t(`license.status.${license.status.toLowerCase()}`, license.status),\r\n icon: license.isReadOnlyMode ? AlertTriangle : CheckCircle,\r\n color: statusColor,\r\n },\r\n {\r\n label: t('license.page.daysRemaining', 'Days remaining'),\r\n value: license.isPerpetual ? '\\u221E' : daysRemaining.toString(),\r\n icon: license.isPerpetual ? InfinityIcon : Clock,\r\n color: daysColor,\r\n },\r\n {\r\n label: t('license.page.maxUsers', 'Max Users'),\r\n value: license.limits.users > 0 ? license.limits.users.toString() : t('license.page.unlimited', 'Unlimited'),\r\n icon: Users,\r\n color: 'blue' as const,\r\n },\r\n ];\r\n}\r\n\r\n// Sub-component: Status Banners\r\ninterface StatusBannersProps {\r\n readonly showTrialSuccess: boolean;\r\n readonly isInGracePeriod: boolean;\r\n readonly validationResult: { type: 'success' | 'revoked' | 'error'; message: string } | null;\r\n readonly gracePeriodDays: number;\r\n readonly onTrialSuccessClose: () => void;\r\n readonly onValidationResultClear: () => void;\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction StatusBanners({\r\n showTrialSuccess, isInGracePeriod, validationResult, gracePeriodDays,\r\n onTrialSuccessClose, onValidationResultClear, t\r\n}: StatusBannersProps) {\r\n return (\r\n <>\r\n {showTrialSuccess && (\r\n <div className=\"flex items-center gap-3 p-4 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg animate-in fade-in slide-in-from-top\">\r\n <CheckCircle className=\"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-green-900 dark:text-green-300\">\r\n {t('license.trial.successBanner', 'Your 30-day trial is activated!')}\r\n </p>\r\n </div>\r\n <button\r\n onClick={onTrialSuccessClose}\r\n className=\"text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300\"\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n )}\r\n\r\n {isInGracePeriod && (\r\n <div className=\"flex items-center gap-3 p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg\">\r\n <AlertTriangle className=\"w-5 h-5 text-amber-600 dark:text-amber-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-amber-900 dark:text-amber-300\">\r\n {t('license.page.gracePeriodBanner', 'Your license has expired. You are in a {{days}}-day grace period. Renew to avoid service interruption.', { days: gracePeriodDays })}\r\n </p>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {validationResult && (\r\n <div className={`flex items-center gap-3 p-4 rounded-lg border ${\r\n validationResult.type === 'success'\r\n ? 'bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800'\r\n : validationResult.type === 'revoked'\r\n ? 'bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800'\r\n : 'bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800'\r\n }`}>\r\n {validationResult.type === 'success'\r\n ? <CheckCircle className=\"w-5 h-5 text-green-600 dark:text-green-400 flex-shrink-0\" />\r\n : <AlertTriangle className={`w-5 h-5 flex-shrink-0 ${\r\n validationResult.type === 'revoked'\r\n ? 'text-red-600 dark:text-red-400'\r\n : 'text-amber-600 dark:text-amber-400'\r\n }`} />\r\n }\r\n <p className={`text-sm font-medium flex-1 ${\r\n validationResult.type === 'success'\r\n ? 'text-green-900 dark:text-green-300'\r\n : validationResult.type === 'revoked'\r\n ? 'text-red-900 dark:text-red-300'\r\n : 'text-amber-900 dark:text-amber-300'\r\n }`}>\r\n {validationResult.message}\r\n </p>\r\n <button\r\n onClick={onValidationResultClear}\r\n className={\r\n validationResult.type === 'success'\r\n ? 'text-green-600 dark:text-green-400 hover:text-green-700 dark:hover:text-green-300'\r\n : validationResult.type === 'revoked'\r\n ? 'text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300'\r\n : 'text-amber-600 dark:text-amber-400 hover:text-amber-700 dark:hover:text-amber-400'\r\n }\r\n >\r\n <X className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n\r\n// Sub-component: Features Grid\r\ninterface FeaturesGridProps {\r\n readonly hasAllFeatures: boolean;\r\n readonly enabledFeatures: string[];\r\n readonly availableFeatures?: LicenseFeatureGroup[];\r\n readonly t: TFunction;\r\n}\r\n\r\nfunction FeaturesGrid({ hasAllFeatures, enabledFeatures, availableFeatures, t }: FeaturesGridProps) {\r\n if (!availableFeatures || availableFeatures.length === 0) {\r\n return (\r\n <p className=\"text-[var(--text-secondary)] text-sm italic\">\r\n {t('license.page.noFeatures', 'No features enabled')}\r\n </p>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n {hasAllFeatures && (\r\n <div className=\"flex items-center gap-2 p-3 mb-4 bg-[var(--success-bg)] text-[var(--success-text)] rounded-lg border border-[var(--success-border)]\">\r\n <CheckCircle className=\"w-5 h-5\" />\r\n <span className=\"font-medium\">{t('license.page.allFeatures', 'All features enabled')}</span>\r\n </div>\r\n )}\r\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\r\n {availableFeatures.map(({ group, features }) => (\r\n <div key={group}>\r\n <h3 className=\"text-sm font-semibold text-[var(--text-secondary)] uppercase tracking-wider mb-3\">\r\n {t(`license.group.${group}`, group)}\r\n </h3>\r\n <div className=\"space-y-2\">\r\n {features.map((code) => {\r\n const enabled = hasAllFeatures || enabledFeatures.some(\r\n f => f.toLowerCase() === code.toLowerCase()\r\n );\r\n return (\r\n <div\r\n key={code}\r\n className={`flex items-center gap-2 px-3 py-2 rounded-lg border ${\r\n enabled\r\n ? 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]'\r\n : 'bg-[var(--bg-secondary)] text-[var(--text-secondary)] border-[var(--border-color)] opacity-60'\r\n }`}\r\n >\r\n {enabled\r\n ? <Unlock className=\"w-4 h-4 flex-shrink-0\" />\r\n : <Lock className=\"w-4 h-4 flex-shrink-0\" />\r\n }\r\n <span className=\"text-sm font-medium\">{t(`license.module.${code}`, code)}</span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n {!hasAllFeatures && enabledFeatures.length === 0 && (\r\n <p className=\"text-[var(--text-secondary)] text-sm italic mt-3\">\r\n {t('license.page.noFeatures', 'No features enabled')}\r\n </p>\r\n )}\r\n </>\r\n );\r\n}\r\n\r\nfunction useValidateLicense(refreshLicense: () => Promise<void>, t: (key: string, fallback: string, opts?: Record<string, unknown>) => string) {\r\n const [isValidating, setIsValidating] = useState(false);\r\n const [validationResult, setValidationResult] = useState<{ type: 'success' | 'revoked' | 'error'; message: string } | null>(null);\r\n\r\n const handleValidate = useCallback(async () => {\r\n setIsValidating(true);\r\n setValidationResult(null);\r\n try {\r\n const result = await api.post<{ valid: boolean; revoked: boolean; error?: string }>(\r\n '/api/administration/license/validate-server'\r\n );\r\n if (result.revoked) {\r\n setValidationResult({ type: 'revoked', message: t('license.validationRevoked', 'The license has been revoked by the server.') });\r\n await refreshLicense();\r\n } else if (result.valid) {\r\n setValidationResult({ type: 'success', message: t('license.validationSuccess', 'License is valid') });\r\n await refreshLicense();\r\n } else {\r\n setValidationResult({ type: 'error', message: result.error || t('license.validationError', 'Unable to validate the license with the server.') });\r\n }\r\n } catch {\r\n setValidationResult({ type: 'error', message: t('license.validationError', 'Unable to validate the license with the server.') });\r\n } finally {\r\n setIsValidating(false);\r\n setTimeout(() => setValidationResult(null), 5000);\r\n }\r\n }, [t, refreshLicense]);\r\n\r\n const clearValidationResult = useCallback(() => setValidationResult(null), []);\r\n\r\n return { isValidating, validationResult, handleValidate, clearValidationResult };\r\n}\r\n\r\nexport function LicenseManagementPage(): ReactElement | null {\r\n const { t } = useTranslation('admin');\r\n const { license, usage, isLoading, error, refreshLicense, isHalted, haltReason } = useLicense();\r\n const [showActivation, setShowActivation] = useState(false);\r\n const [searchParams, setSearchParams] = useSearchParams();\r\n const [showTrialSuccess, setShowTrialSuccess] = useState(false);\r\n const { isValidating, validationResult, handleValidate, clearValidationResult } = useValidateLicense(refreshLicense, t);\r\n\r\n // Refresh license data when the page is displayed (e.g. after creating a tenant)\r\n useEffect(() => {\r\n refreshLicense();\r\n }, [refreshLicense]);\r\n\r\n useEffect(() => {\r\n if (searchParams.get('trial') === 'success') {\r\n setShowTrialSuccess(true); // eslint-disable-line react-hooks/set-state-in-effect -- conditional URL param check\r\n const timer = setTimeout(() => {\r\n setShowTrialSuccess(false);\r\n searchParams.delete('trial');\r\n setSearchParams(searchParams, { replace: true });\r\n }, 5000);\r\n return () => clearTimeout(timer);\r\n }\r\n }, [searchParams, setSearchParams]);\r\n\r\n if (isLoading) {\r\n return (\r\n <div className=\"flex items-center justify-center h-64\">\r\n <Loader2 className=\"w-8 h-8 animate-spin text-[var(--text-secondary)]\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (error || !license) {\r\n return (\r\n <div className=\"p-6\">\r\n <div className=\"card p-6 text-center\">\r\n <AlertTriangle className=\"w-12 h-12 mx-auto mb-4 text-[var(--warning-text)]\" />\r\n <h2 className=\"text-lg font-semibold mb-2\">{t('license.page.errorTitle', 'Unable to load license')}</h2>\r\n <p className=\"text-[var(--text-secondary)] mb-4\">{error || t('license.page.errorDesc', 'License information is not available.')}</p>\r\n <button\r\n onClick={() => refreshLicense()}\r\n className=\"btn-primary px-4 py-2\"\r\n >\r\n {t('common.retry', 'Retry')}\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n const hasAllFeatures = hasAllLicenseFeatures(license.enabledFeatures);\r\n const kpiCards = buildKpiCards(license, t);\r\n\r\n return (\r\n <div className=\"p-6 space-y-6\">\r\n {isHalted && (\r\n <div className=\"flex items-center gap-3 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg\">\r\n <AlertTriangle className=\"w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0\" />\r\n <div className=\"flex-1\">\r\n <p className=\"text-sm font-medium text-red-900 dark:text-red-300\">\r\n {t('license.halted.warning', 'Licence suspendue')}\r\n </p>\r\n {haltReason && (\r\n <p className=\"text-sm text-red-800 dark:text-red-200 mt-1\">\r\n {haltReason}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n <StatusBanners\r\n showTrialSuccess={showTrialSuccess}\r\n isInGracePeriod={license.isInGracePeriod}\r\n validationResult={validationResult}\r\n gracePeriodDays={license.gracePeriodDays}\r\n onTrialSuccessClose={() => setShowTrialSuccess(false)}\r\n onValidationResultClear={clearValidationResult}\r\n t={t}\r\n />\r\n\r\n {/* Banners handled by StatusBanners component above */}\r\n\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between\">\r\n <div>\r\n <h1 className=\"text-2xl font-bold text-[var(--text-primary)]\">\r\n {t('license.page.title', 'License Management')}\r\n </h1>\r\n <p className=\"text-[var(--text-secondary)] mt-1\">\r\n {t('license.page.subtitle', 'View and manage your platform license')}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <LicenseStatusBadge showDetails />\r\n <button\r\n onClick={handleValidate}\r\n disabled={isValidating}\r\n className=\"btn-secondary px-4 py-2 flex items-center gap-2\"\r\n >\r\n {isValidating\r\n ? <Loader2 className=\"w-4 h-4 animate-spin\" />\r\n : <ShieldCheck className=\"w-4 h-4\" />\r\n }\r\n {isValidating\r\n ? t('license.validating', 'Validating...')\r\n : t('license.validate', 'Validate')}\r\n </button>\r\n <button\r\n onClick={() => setShowActivation(true)}\r\n className=\"btn-primary px-4 py-2 flex items-center gap-2\"\r\n >\r\n <Key className=\"w-4 h-4\" />\r\n {t('license.activate', 'Activate')}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* KPI Cards */}\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4\">\r\n {kpiCards.map((card) => (\r\n <div key={card.label} className={`card p-4 border ${colorClasses[card.color]}`}>\r\n <div className=\"flex items-center gap-2 mb-2\">\r\n <card.icon className=\"w-5 h-5 opacity-80\" />\r\n <span className=\"text-sm opacity-80\">{card.label}</span>\r\n </div>\r\n <div className=\"text-2xl font-bold\">{card.value}</div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Limits Section */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Zap className=\"w-5 h-5\" />\r\n {t('license.info.limits', 'Limits')}\r\n </h2>\r\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\r\n <CircularGauge\r\n icon={Users}\r\n label={t('license.page.usersLimit', 'Users')}\r\n max={license.limits.users}\r\n current={usage?.activeUsers ?? 0}\r\n margin={10}\r\n t={t}\r\n />\r\n <CircularGauge\r\n icon={Building}\r\n label={t('license.page.tenantsLimit', 'Tenants (B2B)')}\r\n max={license.limits.tenants}\r\n current={usage?.activeTenants ?? 0}\r\n margin={2}\r\n t={t}\r\n />\r\n </div>\r\n {/* Custom limits from JWT */}\r\n {(() => {\r\n const standardKeys = ['users', 'tenants', 'max_instances', 'max_users'];\r\n const customEntries = Object.entries(license.limits.custom ?? {}).filter(\r\n ([key]) => !standardKeys.includes(key)\r\n );\r\n if (customEntries.length === 0) return null;\r\n return (\r\n <div className=\"mt-4 pt-4 border-t border-[var(--border-color)]\">\r\n <h3 className=\"text-sm font-medium text-[var(--text-secondary)] mb-3\">\r\n {t('license.page.customLimits', 'Custom Limits')}\r\n </h3>\r\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-3\">\r\n {customEntries.map(([key, value]) => (\r\n <div key={key} className=\"flex justify-between items-center py-1.5 px-3 bg-[var(--bg-secondary)] rounded-lg\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{key}</span>\r\n <span className=\"text-sm font-medium\">{value}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n })()}\r\n </div>\r\n\r\n {/* Details + Subscription + Machine Section */}\r\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\r\n {/* License Details */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Calendar className=\"w-5 h-5\" />\r\n {t('license.page.details', 'License Details')}\r\n </h2>\r\n <div className=\"space-y-3\">\r\n <DetailRow label={t('license.info.productId', 'Product')} value={license.productId} />\r\n <DetailRow label={t('license.info.company', 'Company')} value={license.companyName || '-'} />\r\n <DetailRow\r\n label={t('license.info.edition', 'Edition')}\r\n value={t(`license.edition.${license.edition.toLowerCase()}`, license.edition)}\r\n />\r\n <DetailRow\r\n label={t('license.info.status', 'Status')}\r\n value={t(`license.status.${license.status.toLowerCase()}`, license.status)}\r\n />\r\n <DetailRow\r\n label={t('license.info.activatedAt', 'Activated At')}\r\n value={formatDate(license.activatedAt)}\r\n />\r\n <DetailRow\r\n label={t('license.info.expiresAt', 'Expires At')}\r\n value={license.isPerpetual\r\n ? t('license.page.never', 'Never (Perpetual)')\r\n : formatDate(license.expiresAt)}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Subscription Info */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Server className=\"w-5 h-5\" />\r\n {t('license.page.subscription', 'Subscription')}\r\n </h2>\r\n <div className=\"space-y-3\">\r\n <DetailRow\r\n label={t('license.page.licenseType', 'License Type')}\r\n value={license.isPerpetual\r\n ? t('license.page.perpetual', 'Perpetual')\r\n : license.isInTrial\r\n ? t('license.edition.trial', 'Trial')\r\n : t('license.page.subscription', 'Subscription')}\r\n />\r\n <DetailRow\r\n label={t('license.page.maxUsers', 'Max Users')}\r\n value={license.limits.users > 0 ? license.limits.users.toString() : t('license.page.unlimited', 'Unlimited')}\r\n />\r\n <DetailRow\r\n label={t('license.page.gracePeriodDays', 'Grace Period')}\r\n value={license.gracePeriodDays > 0\r\n ? t('license.page.gracePeriodValue', '{{days}} days', { days: license.gracePeriodDays })\r\n : t('license.page.noGracePeriod', 'None')}\r\n />\r\n <DetailRow\r\n label={t('license.page.renewalDate', 'Renewal Date')}\r\n value={formatDate(license.renewalDate)}\r\n />\r\n <DetailRow\r\n label={t('license.page.mode', 'Mode')}\r\n value={license.isReadOnlyMode\r\n ? t('license.page.readOnly', 'Read-only')\r\n : license.isInTrial\r\n ? t('license.edition.trial', 'Trial')\r\n : t('license.page.licensed', 'Licensed')}\r\n />\r\n {license.isInGracePeriod && (\r\n <DetailRow\r\n label={t('license.page.gracePeriodStatus', 'Grace Period Status')}\r\n value={t('license.page.inGracePeriod', 'Active')}\r\n highlight=\"yellow\"\r\n />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Machine Info */}\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Monitor className=\"w-5 h-5\" />\r\n {t('license.page.machineInfo', 'Machine')}\r\n </h2>\r\n <div className=\"space-y-3\">\r\n <div className=\"py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <div className=\"flex justify-between items-center mb-1\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{t('license.page.machineName', 'Machine Name')}</span>\r\n </div>\r\n <span className=\"text-xs font-mono text-[var(--text-primary)] break-all\">\r\n {license.machineName || '-'}\r\n </span>\r\n </div>\r\n <div className=\"py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <div className=\"flex justify-between items-center mb-1\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{t('license.page.instanceId', 'Instance ID')}</span>\r\n </div>\r\n <span className=\"text-xs font-mono text-[var(--text-primary)] break-all\">\r\n {license.instanceId || '-'}\r\n </span>\r\n </div>\r\n <div className=\"py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <div className=\"flex justify-between items-center mb-1\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{t('license.page.licenseId', 'License ID')}</span>\r\n </div>\r\n <span className=\"text-xs font-mono text-[var(--text-primary)] break-all\">\r\n {license.licenseServerId || '-'}\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"card p-6\">\r\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\r\n <Layers className=\"w-5 h-5\" />\r\n {t('license.info.features', 'Features')}\r\n </h2>\r\n <FeaturesGrid\r\n hasAllFeatures={hasAllFeatures}\r\n enabledFeatures={license.enabledFeatures}\r\n availableFeatures={license.availableFeatures}\r\n t={t}\r\n />\r\n </div>\r\n\r\n <LicenseActivationDialog open={showActivation} onOpenChange={setShowActivation} />\r\n </div>\r\n );\r\n}\r\n\r\nfunction DetailRow({ label, value, highlight }: { label: string; value: string; highlight?: 'yellow' | 'red' | 'green' }) {\r\n const highlightClass = highlight === 'yellow'\r\n ? 'text-amber-600 dark:text-amber-400 font-semibold'\r\n : highlight === 'red'\r\n ? 'text-red-600 dark:text-red-400 font-semibold'\r\n : highlight === 'green'\r\n ? 'text-green-600 dark:text-green-400 font-semibold'\r\n : 'text-[var(--text-primary)]';\r\n\r\n return (\r\n <div className=\"flex justify-between items-center py-2 border-b border-[var(--border-color)] last:border-b-0\">\r\n <span className=\"text-sm text-[var(--text-secondary)]\">{label}</span>\r\n <span className={`text-sm font-medium ${highlightClass}`}>{value}</span>\r\n </div>\r\n );\r\n}\r\n\r\nfunction getGaugeIconColor(exceededEffective: boolean, inToleranceZone: boolean): string {\r\n if (exceededEffective) return 'text-red-500';\r\n if (inToleranceZone) return 'text-amber-500';\r\n return 'text-blue-500';\r\n}\r\n\r\nfunction getGaugeTextColor(exceededEffective: boolean, inToleranceZone: boolean): string {\r\n if (exceededEffective) return 'text-red-500';\r\n if (inToleranceZone) return 'text-amber-500';\r\n return 'text-[var(--text-primary)]';\r\n}\r\n\r\nfunction CircularGauge({ icon: Icon, label, max, current, margin = 0, t }: {\r\n icon: typeof Users;\r\n label: string;\r\n max: number;\r\n current: number;\r\n margin?: number;\r\n t: (key: string, fallback: string, opts?: Record<string, unknown>) => string;\r\n}) {\r\n const unlimited = max <= 0;\r\n // `max` is the licensed contractual limit (from JWT, e.g. 50 users).\r\n // The tolerance `margin` is ADDED on top to form the hard upper bound.\r\n // Example: licensed=50 + margin=10 → total=60.\r\n const licensedLimit = max;\r\n const total = max + margin;\r\n\r\n // SVG arc parameters\r\n const size = 140;\r\n const strokeWidth = 12;\r\n const radius = (size - strokeWidth) / 2;\r\n const center = size / 2;\r\n // Arc spans 270 degrees (from 135° to 405°)\r\n const startAngle = 135;\r\n const totalArc = 270;\r\n\r\n // Percentages\r\n const usagePercent = total > 0 ? Math.min(1, current / total) : 0;\r\n const licensedPercent = total > 0 ? licensedLimit / total : 1;\r\n\r\n // Zone detection\r\n const inToleranceZone = margin > 0 && current > licensedLimit && current <= total;\r\n const exceededEffective = current > total;\r\n\r\n // Colors\r\n let usageColor = '#3b82f6'; // blue-500\r\n if (exceededEffective) usageColor = '#ef4444'; // red-500\r\n else if (inToleranceZone) usageColor = '#f59e0b'; // amber-500\r\n\r\n const toleranceTrackColor = 'rgba(245, 158, 11, 0.25)'; // amber with opacity\r\n\r\n // Helper to compute SVG arc endpoint\r\n const polarToCartesian = (angleDeg: number) => {\r\n const rad = (angleDeg * Math.PI) / 180;\r\n return {\r\n x: center + radius * Math.cos(rad),\r\n y: center + radius * Math.sin(rad),\r\n };\r\n };\r\n\r\n // Build an arc path from startAngle spanning `sweep` degrees\r\n const describeArc = (sweep: number) => {\r\n if (sweep <= 0) return '';\r\n const endAngle = startAngle + sweep;\r\n const start = polarToCartesian(startAngle);\r\n const end = polarToCartesian(endAngle);\r\n const largeArc = sweep > 180 ? 1 : 0;\r\n return `M ${start.x} ${start.y} A ${radius} ${radius} 0 ${largeArc} 1 ${end.x} ${end.y}`;\r\n };\r\n\r\n // Percentage display\r\n const displayPercent = total > 0 ? Math.round((current / licensedLimit) * 100) : 0;\r\n\r\n if (unlimited) {\r\n return (\r\n <div className=\"flex flex-col items-center gap-3 py-4\">\r\n <div className=\"relative\" style={{ width: size, height: size }}>\r\n <svg width={size} height={size}>\r\n {/* Background track */}\r\n <path\r\n d={describeArc(totalArc)}\r\n fill=\"none\"\r\n stroke=\"var(--bg-tertiary)\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n {/* Full green arc for unlimited */}\r\n <path\r\n d={describeArc(totalArc)}\r\n fill=\"none\"\r\n stroke=\"#22c55e\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n opacity={0.5}\r\n />\r\n </svg>\r\n <div className=\"absolute inset-0 flex flex-col items-center justify-center\">\r\n <Icon className=\"w-6 h-6 text-green-500 mb-1\" />\r\n <span className=\"text-lg font-bold text-green-500\">∞</span>\r\n </div>\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{label}</span>\r\n <span className=\"text-xs text-[var(--text-secondary)]\">{t('license.page.unlimited', 'Unlimited')}</span>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"flex flex-col items-center gap-3 py-4\">\r\n <div className=\"relative\" style={{ width: size, height: size }}>\r\n <svg width={size} height={size}>\r\n {/* Background track */}\r\n <path\r\n d={describeArc(totalArc)}\r\n fill=\"none\"\r\n stroke=\"var(--bg-tertiary)\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n {/* Tolerance zone: arc from licensed limit to effective limit */}\r\n {margin > 0 && (() => {\r\n const toleranceSweep = totalArc * (1 - licensedPercent);\r\n const toleranceStartAngle = startAngle + totalArc * licensedPercent;\r\n const tStart = polarToCartesian(toleranceStartAngle);\r\n const tEnd = polarToCartesian(startAngle + totalArc);\r\n const largeArc = toleranceSweep > 180 ? 1 : 0;\r\n const tolerancePath = `M ${tStart.x} ${tStart.y} A ${radius} ${radius} 0 ${largeArc} 1 ${tEnd.x} ${tEnd.y}`;\r\n return (\r\n <path\r\n d={tolerancePath}\r\n fill=\"none\"\r\n stroke={toleranceTrackColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })()}\r\n {/* Usage arc */}\r\n <path\r\n d={describeArc(totalArc * usagePercent)}\r\n fill=\"none\"\r\n stroke={usageColor}\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n style={{ transition: 'stroke 0.3s, d 0.3s' }}\r\n />\r\n {/* Licensed limit tick mark */}\r\n {margin > 0 && (() => {\r\n const tickAngle = startAngle + totalArc * licensedPercent;\r\n const innerR = radius - strokeWidth / 2 - 2;\r\n const outerR = radius + strokeWidth / 2 + 2;\r\n const rad = (tickAngle * Math.PI) / 180;\r\n return (\r\n <line\r\n x1={center + innerR * Math.cos(rad)}\r\n y1={center + innerR * Math.sin(rad)}\r\n x2={center + outerR * Math.cos(rad)}\r\n y2={center + outerR * Math.sin(rad)}\r\n stroke=\"var(--text-secondary)\"\r\n strokeWidth={2}\r\n strokeLinecap=\"round\"\r\n />\r\n );\r\n })()}\r\n </svg>\r\n {/* Center content */}\r\n <div className=\"absolute inset-0 flex flex-col items-center justify-center\">\r\n <Icon className={`w-5 h-5 mb-0.5 ${getGaugeIconColor(exceededEffective, inToleranceZone)}`} />\r\n <span className={`text-2xl font-bold ${getGaugeTextColor(exceededEffective, inToleranceZone)}`}>\r\n {displayPercent}%\r\n </span>\r\n <span className=\"text-xs text-[var(--text-secondary)]\">\r\n {current} / {licensedLimit}\r\n </span>\r\n </div>\r\n </div>\r\n <span className=\"text-sm font-medium text-[var(--text-primary)]\">{label}</span>\r\n {margin > 0 && (\r\n <span className={`text-xs ${inToleranceZone || exceededEffective ? 'text-amber-600 dark:text-amber-400' : 'text-[var(--text-secondary)]'}`}>\r\n +{margin} {t('license.page.tolerance', 'tolerance')}\r\n </span>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["colorClasses","getStatusColor","license","getLicenseDaysColor","daysRemaining","formatDate","dateStr","buildKpiCards","statusColor","daysColor","Shield","AlertTriangle","CheckCircle","InfinityIcon","Clock","Users","StatusBanners","showTrialSuccess","isInGracePeriod","validationResult","gracePeriodDays","onTrialSuccessClose","onValidationResultClear","t","jsxs","Fragment","jsx","X","FeaturesGrid","hasAllFeatures","enabledFeatures","availableFeatures","group","features","code","enabled","f","Unlock","Lock","useValidateLicense","refreshLicense","isValidating","setIsValidating","useState","setValidationResult","handleValidate","useCallback","result","api","clearValidationResult","LicenseManagementPage","useTranslation","usage","isLoading","error","isHalted","haltReason","useLicense","showActivation","setShowActivation","searchParams","setSearchParams","useSearchParams","setShowTrialSuccess","useEffect","timer","Loader2","hasAllLicenseFeatures","kpiCards","LicenseStatusBadge","ShieldCheck","Key","card","Zap","CircularGauge","Building","standardKeys","customEntries","key","value","Calendar","DetailRow","Server","Monitor","Layers","LicenseActivationDialog","label","highlight","highlightClass","getGaugeIconColor","exceededEffective","inToleranceZone","getGaugeTextColor","Icon","max","current","margin","unlimited","licensedLimit","total","size","strokeWidth","radius","center","startAngle","totalArc","usagePercent","licensedPercent","usageColor","toleranceTrackColor","polarToCartesian","angleDeg","rad","describeArc","sweep","endAngle","start","end","largeArc","displayPercent","toleranceSweep","toleranceStartAngle","tStart","tEnd","tolerancePath","tickAngle","innerR","outerR"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),N=require("react"),K=require("react-i18next"),L=require("react-router-dom"),T=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),N=require("react"),K=require("react-i18next"),L=require("react-router-dom"),T=require("./index-BDRogQH_.js"),n=require("lucide-react"),V=[{id:"general",labelKey:"settings.tabs.general",icon:n.Settings,route:"/administration/configuration/settings/general"},{id:"file-upload",labelKey:"settings.tabs.fileUpload",icon:n.Upload,route:"/administration/configuration/settings/file-upload"},{id:"legal-file",labelKey:"settings.tabs.legalFile",icon:n.FileText,route:"/administration/configuration/settings/legal-file"}];function M(){const{t}=K.useTranslation("admin"),w=L.useNavigate(),y=L.useLocation(),[x,h]=N.useState([]),[m,u]=N.useState(!0),g=N.useCallback(async()=>{try{u(!0);const v=await T.adminApi.settings.getAll();h(v)}catch(v){console.error("Failed to load settings:",v)}finally{u(!1)}},[]);N.useEffect(()=>{g()},[g]);const k=()=>{const v=y.pathname;return V.find(p=>v.includes(p.id))?.id||"general"},S=v=>{const b=V.find(p=>p.id===v);b&&w(b.route)};return m?e.jsx("div",{className:"flex items-center justify-center min-h-[400px]",children:e.jsx(n.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-600)]"})}):e.jsxs("div",{className:"space-y-6",children:[e.jsx(T.Breadcrumb,{items:[{label:t("header.title"),href:"/administration"},{label:t("settings.title","Settings")}]}),e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-[var(--text-primary)]",children:t("settings.title")}),e.jsx("p",{className:"text-[var(--text-secondary)] mt-1",children:t("settings.subtitle")})]})}),e.jsx("div",{className:"border-b border-[var(--border-color)]",children:e.jsx("nav",{className:"-mb-px flex space-x-8","aria-label":"Tabs",children:V.map(v=>{const b=v.icon,p=k()===v.id;return e.jsxs("button",{onClick:()=>S(v.id),className:`
|
|
2
2
|
group inline-flex items-center py-4 px-1 border-b-2 font-medium text-sm transition-colors
|
|
3
3
|
${p?"border-[var(--color-accent-500)] text-[var(--color-accent-600)]":"border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:border-[var(--border-color)]"}
|
|
4
4
|
`,children:[e.jsx(b,{className:`mr-2 h-5 w-5 ${p?"text-[var(--color-accent-500)]":"text-[var(--text-tertiary)] group-hover:text-[var(--text-secondary)]"}`}),t(v.labelKey)]},v.id)})})}),e.jsx(L.Outlet,{context:{settings:x,refreshSettings:g}})]})}function U(){const{settings:t,refreshSettings:w}=L.useOutletContext(),[y,x]=N.useState({}),[h,m]=N.useState(null),[u,g]=N.useState(null),[k,S]=N.useState([]),[v,b]=N.useState(!1),p=(o,c,i)=>{x(f=>({...f,[`${o}.${c}`]:i}))},D=o=>{const c=`${o.category}.${o.key}`;return y[c]!==void 0&&y[c]!==o.value},C=o=>{const c=`${o.category}.${o.key}`;return y[c]??o.value},$=o=>`${o.category}.${o.key}`;return{settings:t,editedValues:y,saving:h,historyModal:u,history:k,loadingHistory:v,handleValueChange:p,hasChanges:D,getDisplayValue:C,getEditKey:$,handleSave:async o=>{const c=$(o),i=y[c];if(!(i===void 0||i===o.value))try{m(c),await T.adminApi.settings.update(o.category,o.key,i),x(f=>{const A={...f};return delete A[c],A}),await w()}catch(f){console.error("Failed to save setting:",f)}finally{m(null)}},handleReset:async o=>{const c=$(o);try{m(c),await T.adminApi.settings.reset(o.category,o.key),x(i=>{const f={...i};return delete f[c],f}),await w()}catch(i){console.error("Failed to reset setting:",i)}finally{m(null)}},openHistory:async(o,c)=>{g({category:o,key:c}),b(!0);try{const i=await T.adminApi.settings.getHistory(o,c);S(i)}catch(i){console.error("Failed to load history:",i)}finally{b(!1)}},closeHistory:()=>g(null)}}function R({category:t,settingKey:w,history:y,loading:x,onClose:h}){const{t:m}=K.useTranslation("admin");return e.jsx("div",{className:"fixed inset-0 z-50 overflow-y-auto",children:e.jsxs("div",{className:"flex items-center justify-center min-h-screen px-4",children:[e.jsx("button",{type:"button",className:"fixed inset-0 bg-black/50",onClick:h,"aria-label":"Close modal"}),e.jsxs("div",{className:"relative rounded-[var(--radius-card)] bg-[var(--bg-card)] shadow-xl max-w-2xl w-full p-6",children:[e.jsx("h3",{className:"text-lg font-semibold text-[var(--text-primary)] mb-4",children:m("settings.historyTitle",{key:`${t}.${w}`})}),x&&e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(n.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-600)]"})}),!x&&y.length===0&&e.jsx("p",{className:"text-center py-8 text-[var(--text-secondary)]",children:m("settings.noHistory")}),!x&&y.length>0&&e.jsx("div",{className:"space-y-3 max-h-96 overflow-y-auto",children:y.map(u=>e.jsxs("div",{className:"p-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-[var(--text-secondary)]",children:u.changedByUserName||m("settings.system")}),e.jsx("span",{className:"text-[var(--text-tertiary)]",children:new Date(u.changedAt).toLocaleString()})]}),e.jsxs("div",{className:"mt-2 text-sm",children:[e.jsx("span",{className:"text-[var(--error-text)] line-through",children:u.oldValue}),e.jsx("span",{className:"mx-2 text-[var(--text-tertiary)]",children:"→"}),e.jsx("span",{className:"text-[var(--success-text)]",children:u.newValue})]})]},u.id))}),e.jsx("div",{className:"mt-6 flex justify-end",children:e.jsx("button",{onClick:h,className:"px-4 py-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] transition-colors",children:m("common.cancel")})})]})]})})}function I(){const{t}=K.useTranslation("admin"),{settings:w,saving:y,historyModal:x,history:h,loadingHistory:m,handleValueChange:u,hasChanges:g,getDisplayValue:k,getEditKey:S,handleSave:v,handleReset:b,openHistory:p,closeHistory:D}=U(),C=w.filter(s=>s.category==="Session"),$=w.filter(s=>s.category==="General"),E=s=>s==="Database"?"bg-[var(--color-accent-500)]/10 text-[var(--color-accent-600)]":s==="AppSettings"?"bg-purple-500/10 text-purple-600 dark:text-purple-400":"bg-[var(--bg-secondary)] text-[var(--text-tertiary)]",F=(s,o,c)=>s.valueType==="Bool"?e.jsxs("label",{className:"relative inline-flex items-center cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:o==="true",onChange:i=>u(s.category,s.key,i.target.checked?"true":"false"),disabled:!s.isEditable||c,className:"sr-only peer"}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-[var(--color-accent-500)]/30 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-[var(--border-color)] after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[var(--color-accent-600)] peer-disabled:opacity-50 peer-disabled:cursor-not-allowed"})]}):s.valueType==="Int"||s.valueType==="Decimal"?e.jsx("input",{type:"number",value:o,onChange:i=>u(s.category,s.key,i.target.value),disabled:!s.isEditable||c,className:"w-24 px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-button)] bg-[var(--bg-card)] text-[var(--text-primary)] disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]"}):e.jsx("input",{type:s.isSensitive?"password":"text",value:s.isSensitive?"********":o,onChange:i=>u(s.category,s.key,i.target.value),disabled:!s.isEditable||c||s.isSensitive,className:"w-48 px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-button)] bg-[var(--bg-card)] text-[var(--text-primary)] disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]"}),a=s=>{const o=S(s),c=y===o,i=g(s),f=k(s);return e.jsxs("div",{className:"flex items-center justify-between py-4 border-b border-[var(--border-color)] last:border-0",children:[e.jsxs("div",{className:"flex-1 min-w-0 pr-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t(`settings.keys.${s.category}.${s.key}`,s.key)}),!s.isEditable&&e.jsx("span",{className:"px-2 py-0.5 text-xs bg-[var(--bg-secondary)] text-[var(--text-tertiary)] rounded",children:t("settings.readonly")}),e.jsx("span",{className:`px-2 py-0.5 text-xs rounded ${E(s.source)}`,children:s.source})]}),s.description&&e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:t(`settings.descriptions.${s.category}.${s.key}`,s.description)}),s.modifiedAt&&e.jsxs("p",{className:"text-xs text-[var(--text-tertiary)] mt-1 flex items-center gap-1",children:[e.jsx(n.Clock,{className:"w-3 h-3"}),t("settings.modifiedBy",{user:s.modifiedByUserName,date:new Date(s.modifiedAt).toLocaleString()})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[F(s,f,c),s.isEditable&&s.source==="Database"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>v(s),disabled:!i||c,className:"p-2 text-[var(--color-accent-600)] hover:bg-[var(--color-accent-500)]/10 rounded-[var(--radius-button)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",title:t("common.save"),children:c?e.jsx(n.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(n.Save,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>b(s),disabled:s.value===s.defaultValue||c,className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",title:t("settings.resetToDefault"),children:e.jsx(n.RotateCcw,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>p(s.category,s.key),className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] transition-colors",title:t("settings.viewHistory"),children:e.jsx(n.History,{className:"w-4 h-4"})})]})]})]},o)};return e.jsxs("div",{className:"space-y-6",children:[C.length>0&&e.jsxs("div",{className:"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] overflow-hidden shadow-sm",children:[e.jsx("div",{className:"px-6 py-4 bg-gradient-to-r from-[var(--color-accent-500)]/10 to-[var(--color-accent-600)]/5 border-b border-[var(--border-color)]",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-[var(--color-accent-500)]/20",children:e.jsx(n.Clock,{className:"w-5 h-5 text-[var(--color-accent-600)]"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold text-[var(--text-primary)]",children:t("settings.sections.session")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:t("settings.sections.sessionDescription")})]})]})}),e.jsx("div",{className:"px-6 py-2",children:C.map(a)})]}),$.length>0&&e.jsxs("div",{className:"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] overflow-hidden shadow-sm",children:[e.jsx("div",{className:"px-6 py-4 bg-gradient-to-r from-[var(--color-accent-500)]/10 to-[var(--color-accent-600)]/5 border-b border-[var(--border-color)]",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-[var(--color-accent-500)]/20",children:e.jsx(n.Settings,{className:"w-5 h-5 text-[var(--color-accent-600)]"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold text-[var(--text-primary)]",children:t("settings.sections.general")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:t("settings.sections.generalDescription")})]})]})}),e.jsx("div",{className:"px-6 py-2",children:$.map(a)})]}),C.length===0&&$.length===0&&e.jsx("div",{className:"text-center py-12 text-[var(--text-secondary)]",children:t("settings.noSettings")}),x&&e.jsx(R,{category:x.category,settingKey:x.key,history:h,loading:m,onClose:D})]})}function q(){const{t}=K.useTranslation("admin"),{settings:w,saving:y,historyModal:x,history:h,loadingHistory:m,handleValueChange:u,hasChanges:g,getDisplayValue:k,getEditKey:S,handleSave:v,handleReset:b,openHistory:p,closeHistory:D}=U(),C=w.filter(a=>a.category==="FileUpload"),$=a=>{try{return JSON.parse(a)}catch{return[]}},E=(a,s,o)=>a.valueType==="Int"?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"number",value:s,onChange:c=>u(a.category,a.key,c.target.value),disabled:!a.isEditable||o,className:"w-24 px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-button)] bg-[var(--bg-card)] text-[var(--text-primary)] disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]"}),a.key==="MaxFileSizeMB"&&e.jsx("span",{className:"text-sm text-[var(--text-secondary)]",children:"MB"})]}):e.jsx("input",{type:a.isSensitive?"password":"text",value:a.isSensitive?"********":s,onChange:c=>u(a.category,a.key,c.target.value),disabled:!a.isEditable||o||a.isSensitive,className:"w-48 px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-button)] bg-[var(--bg-card)] text-[var(--text-primary)] disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]"}),F=a=>{const s=S(a),o=y===s,c=g(a),i=k(a);if(a.valueType==="Json"&&a.key==="AllowedExtensions"){const f=$(i);return e.jsxs("div",{className:"py-4 border-b border-[var(--border-color)] last:border-0",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t(`settings.keys.${a.category}.${a.key}`,a.key)}),!a.isEditable&&e.jsx("span",{className:"px-2 py-0.5 text-xs bg-[var(--bg-secondary)] text-[var(--text-tertiary)] rounded",children:t("settings.readonly")}),e.jsx("span",{className:"px-2 py-0.5 text-xs bg-[var(--color-accent-500)]/10 text-[var(--color-accent-600)] rounded",children:a.source})]}),a.description&&e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:t(`settings.descriptions.${a.category}.${a.key}`,a.description)})]}),a.isEditable&&a.source==="Database"&&e.jsx("button",{onClick:()=>p(a.category,a.key),className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] transition-colors",title:t("settings.viewHistory"),children:e.jsx(n.History,{className:"w-4 h-4"})})]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:f.map(A=>e.jsx("span",{className:"px-3 py-1 bg-[var(--bg-secondary)] text-[var(--text-secondary)] rounded-full text-sm",children:A},A))})]},s)}return e.jsxs("div",{className:"flex items-center justify-between py-4 border-b border-[var(--border-color)] last:border-0",children:[e.jsxs("div",{className:"flex-1 min-w-0 pr-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t(`settings.keys.${a.category}.${a.key}`,a.key)}),!a.isEditable&&e.jsx("span",{className:"px-2 py-0.5 text-xs bg-[var(--bg-secondary)] text-[var(--text-tertiary)] rounded",children:t("settings.readonly")}),e.jsx("span",{className:`px-2 py-0.5 text-xs rounded ${a.source==="Database"?"bg-[var(--color-accent-500)]/10 text-[var(--color-accent-600)]":a.source==="AppSettings"?"bg-purple-500/10 text-purple-600 dark:text-purple-400":"bg-[var(--bg-secondary)] text-[var(--text-tertiary)]"}`,children:a.source})]}),a.description&&e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:t(`settings.descriptions.${a.category}.${a.key}`,a.description)}),a.modifiedAt&&e.jsxs("p",{className:"text-xs text-[var(--text-tertiary)] mt-1 flex items-center gap-1",children:[e.jsx(n.Clock,{className:"w-3 h-3"}),t("settings.modifiedBy",{user:a.modifiedByUserName,date:new Date(a.modifiedAt).toLocaleString()})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[E(a,i,o),a.isEditable&&a.source==="Database"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>v(a),disabled:!c||o,className:"p-2 text-[var(--color-accent-600)] hover:bg-[var(--color-accent-500)]/10 rounded-[var(--radius-button)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",title:t("common.save"),children:o?e.jsx(n.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(n.Save,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>b(a),disabled:a.value===a.defaultValue||o,className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",title:t("settings.resetToDefault"),children:e.jsx(n.RotateCcw,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>p(a.category,a.key),className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] transition-colors",title:t("settings.viewHistory"),children:e.jsx(n.History,{className:"w-4 h-4"})})]})]})]},s)};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] overflow-hidden shadow-sm",children:[e.jsx("div",{className:"px-6 py-4 bg-gradient-to-r from-[var(--color-accent-500)]/10 to-[var(--color-accent-600)]/5 border-b border-[var(--border-color)]",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-[var(--color-accent-500)]/20",children:e.jsx(n.Upload,{className:"w-5 h-5 text-[var(--color-accent-600)]"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold text-[var(--text-primary)]",children:t("settings.sections.fileUpload")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:t("settings.sections.fileUploadDescription")})]})]})}),e.jsx("div",{className:"px-6 py-2",children:C.length>0?C.map(F):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:t("settings.noSettings")})})]}),x&&e.jsx(R,{category:x.category,settingKey:x.key,history:h,loading:m,onClose:D})]})}function P(){const{t}=K.useTranslation("admin"),{settings:w,refreshSettings:y}=L.useOutletContext(),[x,h]=N.useState({}),[m,u]=N.useState(null),[g,k]=N.useState(null),[S,v]=N.useState([]),[b,p]=N.useState(!1),D=w.filter(r=>r.category==="LegalFile"),C=(r,l,d)=>{h(j=>({...j,[`${r}.${l}`]:d}))},$=r=>{const l=`${r.category}.${r.key}`;return x[l]!==void 0&&x[l]!==r.value},E=r=>{const l=`${r.category}.${r.key}`;return x[l]??r.value},F=async r=>{const l=`${r.category}.${r.key}`,d=x[l];if(!(d===void 0||d===r.value))try{u(l),await T.adminApi.settings.update(r.category,r.key,d),h(j=>{const H={...j};return delete H[l],H}),await y()}catch(j){console.error("Failed to save setting:",j)}finally{u(null)}},a=async r=>{const l=`${r.category}.${r.key}`;try{u(l),await T.adminApi.settings.reset(r.category,r.key),h(d=>{const j={...d};return delete j[l],j}),await y()}catch(d){console.error("Failed to reset setting:",d)}finally{u(null)}},s=async(r,l)=>{k({category:r,key:l}),p(!0);try{const d=await T.adminApi.settings.getHistory(r,l);v(d)}catch(d){console.error("Failed to load history:",d)}finally{p(!1)}},o=r=>{const l=Math.floor(r/365),d=r%365;return d===0?`${l} ${t("settings.years")}`:`${l} ${t("settings.years")} ${d} ${t("settings.days")}`},c=r=>!r.isEditable&&(r.key==="RetentionDays"||r.key==="EnableWorm"),i=(r,l,d,j)=>r.valueType==="Bool"?e.jsxs("label",{className:"relative inline-flex cursor-pointer",children:[e.jsx("span",{className:"sr-only",children:r.key}),e.jsx("input",{type:"checkbox",checked:l==="true",onChange:H=>j(r.category,r.key,H.target.checked?"true":"false"),disabled:!r.isEditable||d,className:"sr-only peer","aria-label":r.key}),e.jsx("div",{className:"w-11 h-6 bg-[var(--bg-tertiary)] peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-[var(--color-accent-500)]/30 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-[var(--border-color)] after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[var(--color-accent-600)] peer-disabled:opacity-50 peer-disabled:cursor-not-allowed"})]}):r.valueType==="Int"?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"number",value:l,onChange:H=>j(r.category,r.key,H.target.value),disabled:!r.isEditable||d,className:"w-24 px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-button)] bg-[var(--bg-card)] text-[var(--text-primary)] disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]"}),(r.key==="RetentionDays"||r.key==="ArchiveAfterDays")&&e.jsxs("span",{className:"text-sm text-[var(--text-secondary)]",children:["(",o(parseInt(l)||0),")"]})]}):e.jsx("input",{type:r.isSensitive?"password":"text",value:r.isSensitive?"********":l,onChange:H=>j(r.category,r.key,H.target.value),disabled:!r.isEditable||d||r.isSensitive,className:"w-48 px-3 py-2 border border-[var(--border-color)] rounded-[var(--radius-button)] bg-[var(--bg-card)] text-[var(--text-primary)] disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-[var(--color-accent-500)] focus:border-[var(--color-accent-500)]"}),f=r=>r==="Database"?"bg-[var(--color-accent-500)]/10 text-[var(--color-accent-600)]":r==="AppSettings"?"bg-purple-500/10 text-purple-600 dark:text-purple-400":"bg-[var(--bg-secondary)] text-[var(--text-tertiary)]",A=r=>{const l=`${r.category}.${r.key}`,d=m===l,j=$(r),H=E(r),B=c(r);return e.jsxs("div",{className:`flex items-center justify-between py-4 border-b border-[var(--border-color)] last:border-0 ${B?"bg-[var(--warning-bg)] -mx-6 px-6":""}`,children:[e.jsxs("div",{className:"flex-1 min-w-0 pr-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-[var(--text-primary)]",children:t(`settings.keys.${r.category}.${r.key}`,r.key)}),B&&e.jsxs("span",{className:"px-2 py-0.5 text-xs bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)] rounded flex items-center gap-1",children:[e.jsx(n.Shield,{className:"w-3 h-3"}),t("settings.legallyProtected")]}),!r.isEditable&&!B&&e.jsx("span",{className:"px-2 py-0.5 text-xs bg-[var(--bg-secondary)] text-[var(--text-tertiary)] rounded",children:t("settings.readonly")}),e.jsx("span",{className:`px-2 py-0.5 text-xs rounded ${f(r.source)}`,children:r.source})]}),r.description&&e.jsx("p",{className:"text-sm text-[var(--text-secondary)] mt-1",children:t(`settings.descriptions.${r.category}.${r.key}`,r.description)}),r.modifiedAt&&e.jsxs("p",{className:"text-xs text-[var(--text-tertiary)] mt-1 flex items-center gap-1",children:[e.jsx(n.Clock,{className:"w-3 h-3"}),t("settings.modifiedBy",{user:r.modifiedByUserName,date:new Date(r.modifiedAt).toLocaleString()})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[i(r,H,d,C),r.isEditable&&r.source==="Database"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>F(r),disabled:!j||d,className:"p-2 text-[var(--color-accent-600)] hover:bg-[var(--color-accent-500)]/10 rounded-[var(--radius-button)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",title:t("common.save"),children:d?e.jsx(n.Loader2,{className:"w-4 h-4 animate-spin"}):e.jsx(n.Save,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>a(r),disabled:r.value===r.defaultValue||d,className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors",title:t("settings.resetToDefault"),children:e.jsx(n.RotateCcw,{className:"w-4 h-4"})}),e.jsx("button",{onClick:()=>s(r.category,r.key),className:"p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] transition-colors",title:t("settings.viewHistory"),children:e.jsx(n.History,{className:"w-4 h-4"})})]})]})]},l)};return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"bg-[var(--warning-bg)] border border-[var(--warning-border)] rounded-[var(--radius-card)] p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(n.AlertTriangle,{className:"w-5 h-5 text-[var(--warning-text)] flex-shrink-0 mt-0.5"}),e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium text-[var(--warning-text)]",children:t("settings.legalWarningTitle")}),e.jsx("p",{className:"text-sm text-[var(--warning-text)] opacity-90 mt-1",children:t("settings.legalWarningDescription")})]})]})}),e.jsxs("div",{className:"rounded-[var(--radius-card)] border border-[var(--border-color)] bg-[var(--bg-card)] overflow-hidden shadow-sm",children:[e.jsx("div",{className:"px-6 py-4 bg-gradient-to-r from-amber-500/10 to-amber-600/5 border-b border-[var(--border-color)]",children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-amber-500/20",children:e.jsx(n.FileText,{className:"w-5 h-5 text-amber-600"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold text-[var(--text-primary)]",children:t("settings.sections.legalFile")}),e.jsx("p",{className:"text-sm text-[var(--text-secondary)]",children:t("settings.sections.legalFileDescription")})]})]})}),e.jsx("div",{className:"px-6 py-2",children:D.length>0?D.map(A):e.jsx("div",{className:"text-center py-8 text-[var(--text-secondary)]",children:t("settings.noSettings")})})]}),g&&e.jsx("div",{className:"fixed inset-0 z-50 overflow-y-auto",children:e.jsxs("div",{className:"flex items-center justify-center min-h-screen px-4",children:[e.jsx("button",{type:"button",className:"fixed inset-0 bg-black/50",onClick:()=>k(null),"aria-label":"Close modal"}),e.jsxs("div",{className:"relative rounded-[var(--radius-card)] bg-[var(--bg-card)] shadow-xl max-w-2xl w-full p-6",children:[e.jsx("h3",{className:"text-lg font-semibold text-[var(--text-primary)] mb-4",children:t("settings.historyTitle",{key:`${g.category}.${g.key}`})}),b&&e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(n.Loader2,{className:"w-8 h-8 animate-spin text-[var(--color-accent-600)]"})}),!b&&S.length===0&&e.jsx("p",{className:"text-center py-8 text-[var(--text-secondary)]",children:t("settings.noHistory")}),!b&&S.length>0&&e.jsx("div",{className:"space-y-3 max-h-96 overflow-y-auto",children:S.map(r=>e.jsxs("div",{className:"p-3 bg-[var(--bg-secondary)] rounded-lg",children:[e.jsxs("div",{className:"flex justify-between text-sm",children:[e.jsx("span",{className:"text-[var(--text-secondary)]",children:r.changedByUserName||t("settings.system")}),e.jsx("span",{className:"text-[var(--text-tertiary)]",children:new Date(r.changedAt).toLocaleString()})]}),e.jsxs("div",{className:"mt-2 text-sm",children:[e.jsx("span",{className:"text-[var(--error-text)] line-through",children:r.oldValue}),e.jsx("span",{className:"mx-2 text-[var(--text-tertiary)]",children:"→"}),e.jsx("span",{className:"text-[var(--success-text)]",children:r.newValue})]})]},r.id))}),e.jsx("div",{className:"mt-6 flex justify-end",children:e.jsx("button",{onClick:()=>k(null),className:"px-4 py-2 text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)] rounded-[var(--radius-button)] transition-colors",children:t("common.cancel")})})]})]})})]})}exports.FileUploadSettingsSection=q;exports.GeneralSettingsSection=I;exports.LegalFileSettingsSection=P;exports.SettingsPage=M;
|
|
5
|
-
//# sourceMappingURL=index-
|
|
5
|
+
//# sourceMappingURL=index-Ca88RIuT.js.map
|