@alepha/ui 0.18.2 → 0.19.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/admin/{AdminApiKeys-BJhIwfD6.js → AdminApiKeys-Bt1PjO6o.js} +3 -4
- package/dist/admin/{AdminApiKeys-BJhIwfD6.js.map → AdminApiKeys-Bt1PjO6o.js.map} +1 -1
- package/dist/admin/{AdminAudits-DzD_4cDt.js → AdminAudits-C7c1CN4c.js} +3 -4
- package/dist/admin/{AdminAudits-DzD_4cDt.js.map → AdminAudits-C7c1CN4c.js.map} +1 -1
- package/dist/admin/{AdminDashboard-C92tIc6x.js → AdminDashboard-C3RXpTp6.js} +3 -4
- package/dist/admin/{AdminDashboard-C92tIc6x.js.map → AdminDashboard-C3RXpTp6.js.map} +1 -1
- package/dist/admin/{AdminFiles-DLpfhBkf.js → AdminFiles-31ivR6Wq.js} +3 -4
- package/dist/admin/{AdminFiles-DLpfhBkf.js.map → AdminFiles-31ivR6Wq.js.map} +1 -1
- package/dist/admin/{AdminJobDashboard-KIOkeMgE.js → AdminJobDashboard-BABLe7hL.js} +73 -25
- package/dist/admin/AdminJobDashboard-BABLe7hL.js.map +1 -0
- package/dist/admin/{AdminJobExecutions-D0Yo_PU0.js → AdminJobExecutions-D-G8RIlr.js} +3 -4
- package/dist/admin/{AdminJobExecutions-D0Yo_PU0.js.map → AdminJobExecutions-D-G8RIlr.js.map} +1 -1
- package/dist/admin/{AdminJobRegistry-PFajqaGK.js → AdminJobRegistry-oIS3K9NX.js} +3 -4
- package/dist/admin/{AdminJobRegistry-PFajqaGK.js.map → AdminJobRegistry-oIS3K9NX.js.map} +1 -1
- package/dist/admin/{AdminLayout-B1DXZHDn.js → AdminLayout-BmZ9mtXh.js} +8 -25
- package/dist/admin/AdminLayout-BmZ9mtXh.js.map +1 -0
- package/dist/admin/AdminNotifications-DHdzksww.js +541 -0
- package/dist/admin/AdminNotifications-DHdzksww.js.map +1 -0
- package/dist/admin/{AdminParameters-BspPeqp_.js → AdminParameters-CyZQSXnN.js} +118 -112
- package/dist/admin/AdminParameters-CyZQSXnN.js.map +1 -0
- package/dist/admin/{AdminSessions-BnH5CZQl.js → AdminSessions--xwELDSO.js} +3 -4
- package/dist/admin/{AdminSessions-BnH5CZQl.js.map → AdminSessions--xwELDSO.js.map} +1 -1
- package/dist/admin/{AdminUserLayout-DUbC6-BI.js → AdminUserLayout-DvBTG5gd.js} +82 -115
- package/dist/admin/AdminUserLayout-DvBTG5gd.js.map +1 -0
- package/dist/admin/{AdminUserProfile-DuTUnjdG.js → AdminUserProfile-CzsPBl6Z.js} +7 -6
- package/dist/admin/AdminUserProfile-CzsPBl6Z.js.map +1 -0
- package/dist/admin/{AdminUserSessions-DvZdAGpL.js → AdminUserSessions-C-aUnhVN.js} +3 -4
- package/dist/admin/{AdminUserSessions-DvZdAGpL.js.map → AdminUserSessions-C-aUnhVN.js.map} +1 -1
- package/dist/admin/{AdminUsers-CR9z0g_5.js → AdminUsers-BYwei5sj.js} +4 -4
- package/dist/admin/AdminUsers-BYwei5sj.js.map +1 -0
- package/dist/admin/{AuthLayout-DsUfp9RG.js → AuthLayout-CkPGLJku.js} +3 -4
- package/dist/admin/{AuthLayout-DsUfp9RG.js.map → AuthLayout-CkPGLJku.js.map} +1 -1
- package/dist/{demo/IconGoogle-CSQLPYwX.js → admin/IconGoogle-8Nkx6yax.js} +2 -4
- package/dist/admin/{IconGoogle-Ch1m3Uzl.js.map → IconGoogle-8Nkx6yax.js.map} +1 -1
- package/dist/admin/Login-DSBqNsZc.js +274 -0
- package/dist/admin/Login-DSBqNsZc.js.map +1 -0
- package/dist/admin/{Profile-B2EcIDB9.js → Profile-CDRjJo0P.js} +31 -29
- package/dist/admin/Profile-CDRjJo0P.js.map +1 -0
- package/dist/admin/{Register-Z3fxRbUF.js → Register-4QGFOnfh.js} +201 -146
- package/dist/admin/Register-4QGFOnfh.js.map +1 -0
- package/dist/admin/{ResetPassword-_Y1qTTKh.js → ResetPassword-Gxc9L_mY.js} +9 -10
- package/dist/admin/ResetPassword-Gxc9L_mY.js.map +1 -0
- package/dist/admin/{VerifyEmail-Bg22bwcC.js → VerifyEmail-D7G5NnaN.js} +25 -11
- package/dist/admin/VerifyEmail-D7G5NnaN.js.map +1 -0
- package/dist/admin/adminUserAtom-DCi4wf-v.js +11 -0
- package/dist/admin/adminUserAtom-DCi4wf-v.js.map +1 -0
- package/dist/admin/{core-BVO_TQxb.js → core-D1AbU50V.js} +662 -570
- package/dist/admin/core-D1AbU50V.js.map +1 -0
- package/dist/admin/index.d.ts +141 -53
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +67 -49
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/{demo/AuthLayout-DN-ClJQk.js → auth/AuthLayout-CfRKcTqP.js} +3 -4
- package/dist/auth/{AuthLayout-C161NeF6.js.map → AuthLayout-CfRKcTqP.js.map} +1 -1
- package/dist/{admin/IconGoogle-Ch1m3Uzl.js → auth/IconGoogle-8Nkx6yax.js} +2 -4
- package/dist/auth/{IconGoogle-Ch1m3Uzl.js.map → IconGoogle-8Nkx6yax.js.map} +1 -1
- package/dist/auth/Login-DJyweoPS.js +274 -0
- package/dist/auth/Login-DJyweoPS.js.map +1 -0
- package/dist/auth/{Profile-BMpXJ0oi.js → Profile-Cy93pNTw.js} +31 -29
- package/dist/auth/Profile-Cy93pNTw.js.map +1 -0
- package/dist/auth/{Register-2gx8qll-.js → Register-CSqzzitW.js} +201 -146
- package/dist/auth/Register-CSqzzitW.js.map +1 -0
- package/dist/{demo/ResetPassword-CAPj8MO3.js → auth/ResetPassword-B61QPlQi.js} +9 -10
- package/dist/auth/ResetPassword-B61QPlQi.js.map +1 -0
- package/dist/{demo/VerifyEmail-DFmdCdYs.js → auth/VerifyEmail-CqBJ11id.js} +25 -11
- package/dist/auth/VerifyEmail-CqBJ11id.js.map +1 -0
- package/dist/auth/{core-DyfeVr5c.js → core-C6D3pazL.js} +403 -343
- package/dist/auth/core-C6D3pazL.js.map +1 -0
- package/dist/auth/index.d.ts +93 -54
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +30 -31
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/core/index.d.ts +123 -62
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +878 -776
- package/dist/core/index.js.map +1 -1
- package/dist/{auth/AuthLayout-C161NeF6.js → demo/AuthLayout-Dq5tSLSc.js} +3 -4
- package/dist/demo/{AuthLayout-DN-ClJQk.js.map → AuthLayout-Dq5tSLSc.js.map} +1 -1
- package/dist/demo/DemoButton-_Ws2w-J0.js +181 -0
- package/dist/demo/DemoButton-_Ws2w-J0.js.map +1 -0
- package/dist/demo/DemoControlSelect-ChP4ZOpQ.js +304 -0
- package/dist/demo/DemoControlSelect-ChP4ZOpQ.js.map +1 -0
- package/dist/demo/DemoDataTable-Hwf_UUni.js +361 -0
- package/dist/demo/DemoDataTable-Hwf_UUni.js.map +1 -0
- package/dist/demo/{DemoDialog-DW8QEvD1.js → DemoDialog-B01OMVRd.js} +3 -4
- package/dist/demo/{DemoDialog-DW8QEvD1.js.map → DemoDialog-B01OMVRd.js.map} +1 -1
- package/dist/demo/{DemoFlex-CAhLUanT.js → DemoFlex-870PEl0V.js} +4 -5
- package/dist/demo/{DemoFlex-CAhLUanT.js.map → DemoFlex-870PEl0V.js.map} +1 -1
- package/dist/demo/{DemoHeading-yIFmNjHB.js → DemoHeading-C1YR27fz.js} +4 -5
- package/dist/demo/{DemoHeading-yIFmNjHB.js.map → DemoHeading-C1YR27fz.js.map} +1 -1
- package/dist/demo/{DemoHome-BSGuBHus.js → DemoHome-DRbL2eGf.js} +4 -5
- package/dist/demo/{DemoHome-BSGuBHus.js.map → DemoHome-DRbL2eGf.js.map} +1 -1
- package/dist/demo/{DemoJsonViewer-DsA2IpgV.js → DemoJsonViewer-DoABiqBW.js} +4 -5
- package/dist/demo/{DemoJsonViewer-DsA2IpgV.js.map → DemoJsonViewer-DoABiqBW.js.map} +1 -1
- package/dist/demo/{DemoLayout-Cy6xjn6P.js → DemoLayout-CN_PDCX2.js} +16 -8
- package/dist/demo/DemoLayout-CN_PDCX2.js.map +1 -0
- package/dist/demo/{DemoLogin-vqxgTu4P.js → DemoLogin-B5x-ug3Q.js} +51 -35
- package/dist/demo/DemoLogin-B5x-ug3Q.js.map +1 -0
- package/dist/demo/{DemoRegister-YHPvPg77.js → DemoRegister-Q6sg2xuV.js} +51 -53
- package/dist/demo/DemoRegister-Q6sg2xuV.js.map +1 -0
- package/dist/demo/{DemoResetPassword-mOW18Zlm.js → DemoResetPassword-DrqZfmEw.js} +14 -19
- package/dist/demo/DemoResetPassword-DrqZfmEw.js.map +1 -0
- package/dist/demo/{DemoSidebar-od7aLjP_.js → DemoSidebar-CfKS6w1o.js} +4 -5
- package/dist/demo/{DemoSidebar-od7aLjP_.js.map → DemoSidebar-CfKS6w1o.js.map} +1 -1
- package/dist/demo/{DemoText-DU3JeRS0.js → DemoText-pT6Gi5b5.js} +4 -5
- package/dist/demo/{DemoText-DU3JeRS0.js.map → DemoText-pT6Gi5b5.js.map} +1 -1
- package/dist/demo/{DemoToast-CUJEiPRa.js → DemoToast-I13NBzQQ.js} +3 -4
- package/dist/demo/{DemoToast-CUJEiPRa.js.map → DemoToast-I13NBzQQ.js.map} +1 -1
- package/dist/demo/{DemoTypeForm-C1dNkahD.js → DemoTypeForm-BqzcrtvN.js} +9 -6
- package/dist/demo/DemoTypeForm-BqzcrtvN.js.map +1 -0
- package/dist/demo/DemoVerifyEmail-HwD8xfQw.js +33 -0
- package/dist/demo/DemoVerifyEmail-HwD8xfQw.js.map +1 -0
- package/dist/{auth/IconGoogle-Ch1m3Uzl.js → demo/IconGoogle-CwQy4G9y.js} +2 -4
- package/dist/demo/{IconGoogle-CSQLPYwX.js.map → IconGoogle-CwQy4G9y.js.map} +1 -1
- package/dist/demo/Login-CqG1iJbn.js +274 -0
- package/dist/demo/Login-CqG1iJbn.js.map +1 -0
- package/dist/demo/{Profile-BE_Y3co2.js → Profile-C0ojJCaG.js} +31 -29
- package/dist/demo/Profile-C0ojJCaG.js.map +1 -0
- package/dist/demo/{Register-fXHmBpr3.js → Register-KKZwr_lL.js} +201 -146
- package/dist/demo/Register-KKZwr_lL.js.map +1 -0
- package/dist/{auth/ResetPassword-DBxt9hKk.js → demo/ResetPassword-DMrLFEtr.js} +9 -10
- package/dist/demo/ResetPassword-DMrLFEtr.js.map +1 -0
- package/dist/demo/{Showcase-BtEU0pY9.js → Showcase-D49Wud2v.js} +65 -68
- package/dist/demo/Showcase-D49Wud2v.js.map +1 -0
- package/dist/{auth/VerifyEmail-Z80Ubajk.js → demo/VerifyEmail-BFCAFz6T.js} +25 -11
- package/dist/demo/VerifyEmail-BFCAFz6T.js.map +1 -0
- package/dist/demo/{auth-Djd7SKiw.js → auth-D9qTZzCa.js} +18 -35
- package/dist/demo/{auth-Djd7SKiw.js.map → auth-D9qTZzCa.js.map} +1 -1
- package/dist/demo/{core-B7LNjM78.js → core-DRtQklr3.js} +752 -647
- package/dist/demo/core-DRtQklr3.js.map +1 -0
- package/dist/demo/index.d.ts +1 -0
- package/dist/demo/index.d.ts.map +1 -1
- package/dist/demo/index.js +25 -22
- package/dist/demo/index.js.map +1 -1
- package/dist/demo/rolldown-runtime-CiIaOW0V.js +13 -0
- package/package.json +19 -19
- package/src/admin/AdminRouter.tsx +42 -2
- package/src/admin/atoms/adminUserAtom.ts +7 -0
- package/src/admin/components/AdminLayout.tsx +2 -14
- package/src/admin/components/jobs/AdminJobDashboard.tsx +51 -20
- package/src/admin/components/notifications/AdminNotifications.tsx +519 -0
- package/src/admin/components/parameters/ParameterDetails.tsx +12 -270
- package/src/admin/components/parameters/ParameterDetailsConfigForm.tsx +238 -0
- package/src/admin/components/parameters/ParameterDetailsLoading.tsx +24 -0
- package/src/admin/components/parameters/ParameterHistory.tsx +10 -11
- package/src/admin/components/parameters/ParameterTree.tsx +28 -184
- package/src/admin/components/parameters/ParameterTreeNode.tsx +151 -0
- package/src/admin/components/shared/AdminResourceHeader.tsx +2 -25
- package/src/admin/components/shared/AdminResourceHeaderMenuItem.tsx +37 -0
- package/src/admin/components/shared/AdminResourceTabs.tsx +2 -26
- package/src/admin/components/shared/AdminResourceTabsItem.tsx +36 -0
- package/src/admin/components/users/AdminUserLayout.tsx +84 -127
- package/src/admin/components/users/AdminUserProfile.tsx +5 -2
- package/src/admin/components/users/AdminUsers.tsx +1 -1
- package/src/auth/components/Login.tsx +188 -121
- package/src/auth/components/Profile.tsx +1 -22
- package/src/auth/components/ProfileField.tsx +39 -0
- package/src/auth/components/Register.tsx +215 -158
- package/src/auth/components/ResetPassword.tsx +7 -11
- package/src/auth/components/VerifyEmail.tsx +35 -10
- package/src/auth/components/buttons/UserButton.tsx +19 -21
- package/src/auth/index.ts +1 -0
- package/src/core/components/Flex.tsx +34 -0
- package/src/core/components/buttons/ActionButton.tsx +105 -78
- package/src/core/components/data/DetailDrawer.tsx +102 -96
- package/src/core/components/data/DetailList.tsx +2 -1
- package/src/core/components/dialogs/PromptDialog.tsx +1 -1
- package/src/core/components/layout/Breadcrumb.tsx +4 -7
- package/src/core/components/layout/DashboardShell.tsx +18 -4
- package/src/core/components/layout/Sidebar.tsx +16 -241
- package/src/core/components/layout/SidebarCollapsedItem.tsx +91 -0
- package/src/core/components/layout/SidebarItem.tsx +146 -0
- package/src/core/components/layout/index.ts +3 -1
- package/src/core/form/components/Control.tsx +31 -29
- package/src/core/form/components/ControlArray.tsx +13 -39
- package/src/core/form/components/ControlDate.tsx +10 -21
- package/src/core/form/components/ControlNumber.tsx +4 -33
- package/src/core/form/components/ControlQueryBuilder.tsx +12 -175
- package/src/core/form/components/ControlQueryBuilderHelp.tsx +165 -0
- package/src/core/form/components/ControlSelect.browser.spec.tsx +343 -0
- package/src/core/form/components/ControlSelect.tsx +294 -92
- package/src/core/form/components/TypeForm.browser.spec.tsx +3 -3
- package/src/core/form/components/TypeForm.tsx +5 -2
- package/src/core/form/index.ts +8 -1
- package/src/core/form/utils/parseInput.ts +7 -3
- package/src/core/index.ts +3 -1
- package/src/core/json/components/JsonViewer.tsx +103 -319
- package/src/core/json/components/JsonViewerCopyButton.tsx +46 -0
- package/src/core/json/components/JsonViewerRowNode.tsx +120 -0
- package/src/core/json/components/JsonViewerShared.ts +76 -0
- package/src/core/services/DialogService.tsx +2 -2
- package/src/core/styles.css +13 -2
- package/src/core/table/components/ColumnPicker.tsx +3 -3
- package/src/core/table/components/DataTable.tsx +88 -29
- package/src/core/table/components/DataTableFilters.tsx +6 -11
- package/src/core/table/components/DataTablePagination.tsx +9 -3
- package/src/core/table/components/DataTableToolbar.tsx +7 -3
- package/src/core/table/components/FilterPicker.tsx +3 -3
- package/src/core/table/interfaces/types.ts +29 -0
- package/src/core/utils/icons.tsx +2 -2
- package/src/demo/DemoRouter.ts +8 -1
- package/src/demo/components/DemoLayout.tsx +12 -2
- package/src/demo/components/auth/DemoLogin.tsx +35 -28
- package/src/demo/components/auth/DemoRegister.tsx +35 -49
- package/src/demo/components/auth/DemoResetPassword.tsx +5 -9
- package/src/demo/components/auth/DemoVerifyEmail.tsx +7 -6
- package/src/demo/components/core/DemoButton.tsx +123 -103
- package/src/demo/components/core/DemoControlSelect.tsx +325 -0
- package/src/demo/components/core/DemoDataTable.tsx +255 -237
- package/src/demo/components/core/DemoTypeForm.tsx +7 -2
- package/src/demo/components/shared/MacWindow.tsx +5 -11
- package/src/demo/components/shared/Showcase.tsx +28 -42
- package/dist/admin/AdminJobDashboard-KIOkeMgE.js.map +0 -1
- package/dist/admin/AdminLayout-B1DXZHDn.js.map +0 -1
- package/dist/admin/AdminParameters-BspPeqp_.js.map +0 -1
- package/dist/admin/AdminUserLayout-DUbC6-BI.js.map +0 -1
- package/dist/admin/AdminUserProfile-DuTUnjdG.js.map +0 -1
- package/dist/admin/AdminUsers-CR9z0g_5.js.map +0 -1
- package/dist/admin/Login-DHbYJKwg.js +0 -219
- package/dist/admin/Login-DHbYJKwg.js.map +0 -1
- package/dist/admin/Profile-B2EcIDB9.js.map +0 -1
- package/dist/admin/Register-Z3fxRbUF.js.map +0 -1
- package/dist/admin/ResetPassword-_Y1qTTKh.js.map +0 -1
- package/dist/admin/VerifyEmail-Bg22bwcC.js.map +0 -1
- package/dist/admin/core-BVO_TQxb.js.map +0 -1
- package/dist/admin/rolldown-runtime-CjeV3_4I.js +0 -18
- package/dist/auth/Login-C7jIqf00.js +0 -219
- package/dist/auth/Login-C7jIqf00.js.map +0 -1
- package/dist/auth/Profile-BMpXJ0oi.js.map +0 -1
- package/dist/auth/Register-2gx8qll-.js.map +0 -1
- package/dist/auth/ResetPassword-DBxt9hKk.js.map +0 -1
- package/dist/auth/VerifyEmail-Z80Ubajk.js.map +0 -1
- package/dist/auth/core-DyfeVr5c.js.map +0 -1
- package/dist/auth/rolldown-runtime-CjeV3_4I.js +0 -18
- package/dist/demo/DemoButton-CGUyR9eM.js +0 -178
- package/dist/demo/DemoButton-CGUyR9eM.js.map +0 -1
- package/dist/demo/DemoDataTable-QFG-xXSx.js +0 -358
- package/dist/demo/DemoDataTable-QFG-xXSx.js.map +0 -1
- package/dist/demo/DemoLayout-Cy6xjn6P.js.map +0 -1
- package/dist/demo/DemoLogin-vqxgTu4P.js.map +0 -1
- package/dist/demo/DemoRegister-YHPvPg77.js.map +0 -1
- package/dist/demo/DemoResetPassword-mOW18Zlm.js.map +0 -1
- package/dist/demo/DemoTypeForm-C1dNkahD.js.map +0 -1
- package/dist/demo/DemoVerifyEmail-D9EcXZ38.js +0 -30
- package/dist/demo/DemoVerifyEmail-D9EcXZ38.js.map +0 -1
- package/dist/demo/Login-CoYf_P_F.js +0 -219
- package/dist/demo/Login-CoYf_P_F.js.map +0 -1
- package/dist/demo/Profile-BE_Y3co2.js.map +0 -1
- package/dist/demo/Register-fXHmBpr3.js.map +0 -1
- package/dist/demo/ResetPassword-CAPj8MO3.js.map +0 -1
- package/dist/demo/Showcase-BtEU0pY9.js.map +0 -1
- package/dist/demo/VerifyEmail-DFmdCdYs.js.map +0 -1
- package/dist/demo/core-B7LNjM78.js.map +0 -1
- package/dist/demo/rolldown-runtime-CjeV3_4I.js +0 -18
- package/src/demo/styles.css +0 -0
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { jsonSchemaToTypeBox, type TObject, t } from "alepha";
|
|
5
|
-
import { useForm } from "alepha/react/form";
|
|
6
|
-
import { useI18n } from "alepha/react/i18n";
|
|
7
|
-
import { useMemo } from "react";
|
|
8
|
-
import { formatJson, type ParameterValue } from "./types.ts";
|
|
1
|
+
import ParameterDetailsConfigForm from "./ParameterDetailsConfigForm.tsx";
|
|
2
|
+
import ParameterDetailsLoading from "./ParameterDetailsLoading.tsx";
|
|
3
|
+
import type { ParameterValue } from "./types.ts";
|
|
9
4
|
|
|
10
|
-
|
|
5
|
+
interface Props {
|
|
11
6
|
selectedConfig: string | null;
|
|
12
7
|
configValue: ParameterValue | null;
|
|
13
8
|
loading: boolean;
|
|
@@ -15,277 +10,24 @@ export interface ParameterDetailsProps {
|
|
|
15
10
|
onSave: (values: Record<string, unknown>) => Promise<void>;
|
|
16
11
|
}
|
|
17
12
|
|
|
18
|
-
/**
|
|
19
|
-
* Loading state.
|
|
20
|
-
*/
|
|
21
|
-
const LoadingState = () => (
|
|
22
|
-
<Flex
|
|
23
|
-
flex={1}
|
|
24
|
-
h="100%"
|
|
25
|
-
p="md"
|
|
26
|
-
style={{
|
|
27
|
-
overflow: "hidden",
|
|
28
|
-
minWidth: 0,
|
|
29
|
-
display: "flex",
|
|
30
|
-
}}
|
|
31
|
-
>
|
|
32
|
-
<Flex flex={1} justify="center" align="center" h="100%">
|
|
33
|
-
<Loader size="sm" />
|
|
34
|
-
</Flex>
|
|
35
|
-
</Flex>
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
interface ConfigFormProps {
|
|
39
|
-
selectedConfig: string;
|
|
40
|
-
configValue: ParameterValue | null;
|
|
41
|
-
saving: boolean;
|
|
42
|
-
onSave: (values: Record<string, unknown>) => Promise<void>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The actual form component - only rendered when a config is selected.
|
|
47
|
-
*/
|
|
48
|
-
const ConfigForm = ({
|
|
49
|
-
selectedConfig,
|
|
50
|
-
configValue,
|
|
51
|
-
saving,
|
|
52
|
-
onSave,
|
|
53
|
-
}: ConfigFormProps) => {
|
|
54
|
-
const { l } = useI18n();
|
|
55
|
-
|
|
56
|
-
// Get the current value to display (from saved version or default)
|
|
57
|
-
const currentContent = useMemo(() => {
|
|
58
|
-
if (configValue?.current?.content) {
|
|
59
|
-
return configValue.current.content;
|
|
60
|
-
}
|
|
61
|
-
if (configValue?.currentValue !== undefined) {
|
|
62
|
-
return configValue.currentValue;
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
}, [configValue]);
|
|
66
|
-
|
|
67
|
-
// Convert JSON Schema from API to TypeBox schema
|
|
68
|
-
const schemaForForm = useMemo(() => {
|
|
69
|
-
if (!configValue?.schema) {
|
|
70
|
-
return t.object({});
|
|
71
|
-
}
|
|
72
|
-
try {
|
|
73
|
-
return jsonSchemaToTypeBox(configValue.schema) as TObject;
|
|
74
|
-
} catch {
|
|
75
|
-
return t.object({});
|
|
76
|
-
}
|
|
77
|
-
}, [configValue?.schema]);
|
|
78
|
-
|
|
79
|
-
const form = useForm(
|
|
80
|
-
{
|
|
81
|
-
schema: schemaForForm,
|
|
82
|
-
initialValues: (currentContent ?? {}) as Record<string, unknown>,
|
|
83
|
-
handler: async (values) => {
|
|
84
|
-
await onSave(values as Record<string, unknown>);
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
[selectedConfig, schemaForForm, currentContent],
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// Check if we have a valid schema with properties
|
|
91
|
-
const hasValidSchema = useMemo(() => {
|
|
92
|
-
const schema = configValue?.schema;
|
|
93
|
-
return (
|
|
94
|
-
schema &&
|
|
95
|
-
typeof schema === "object" &&
|
|
96
|
-
"properties" in schema &&
|
|
97
|
-
Object.keys(schema.properties as object).length > 0
|
|
98
|
-
);
|
|
99
|
-
}, [configValue?.schema]);
|
|
100
|
-
|
|
101
|
-
// Count the number of fields to determine column layout
|
|
102
|
-
const fieldCount = useMemo(() => {
|
|
103
|
-
const schema = configValue?.schema;
|
|
104
|
-
if (
|
|
105
|
-
schema &&
|
|
106
|
-
typeof schema === "object" &&
|
|
107
|
-
"properties" in schema &&
|
|
108
|
-
schema.properties
|
|
109
|
-
) {
|
|
110
|
-
return Object.keys(schema.properties as object).length;
|
|
111
|
-
}
|
|
112
|
-
return 0;
|
|
113
|
-
}, [configValue?.schema]);
|
|
114
|
-
|
|
115
|
-
// Determine optimal column count based on field count
|
|
116
|
-
const columns = useMemo(() => {
|
|
117
|
-
if (fieldCount <= 2) return 1;
|
|
118
|
-
if (fieldCount <= 6) return 2;
|
|
119
|
-
return 3;
|
|
120
|
-
}, [fieldCount]);
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<Flex
|
|
124
|
-
flex={1}
|
|
125
|
-
h="100%"
|
|
126
|
-
style={{
|
|
127
|
-
overflow: "hidden",
|
|
128
|
-
minWidth: 0,
|
|
129
|
-
display: "flex",
|
|
130
|
-
}}
|
|
131
|
-
>
|
|
132
|
-
<Flex direction="column" h="100%" w="100%" style={{ minHeight: 0 }}>
|
|
133
|
-
{/* Content */}
|
|
134
|
-
<Flex
|
|
135
|
-
flex={1}
|
|
136
|
-
p="md"
|
|
137
|
-
className="overflow-auto"
|
|
138
|
-
style={{ minHeight: 0 }}
|
|
139
|
-
>
|
|
140
|
-
{currentContent !== null ? (
|
|
141
|
-
<Flex direction="column" gap="lg">
|
|
142
|
-
{/* Form or JSON view */}
|
|
143
|
-
<Flex>
|
|
144
|
-
{hasValidSchema ? (
|
|
145
|
-
<TypeForm
|
|
146
|
-
form={form}
|
|
147
|
-
columns={columns}
|
|
148
|
-
skipSubmitButton
|
|
149
|
-
fill={false}
|
|
150
|
-
/>
|
|
151
|
-
) : (
|
|
152
|
-
<Flex>
|
|
153
|
-
<Text size="xs" c="dimmed" mb={4}>
|
|
154
|
-
Current Value
|
|
155
|
-
</Text>
|
|
156
|
-
<Code block style={{ whiteSpace: "pre-wrap" }}>
|
|
157
|
-
{formatJson(currentContent)}
|
|
158
|
-
</Code>
|
|
159
|
-
</Flex>
|
|
160
|
-
)}
|
|
161
|
-
</Flex>
|
|
162
|
-
|
|
163
|
-
{/* Metadata */}
|
|
164
|
-
{configValue?.current?.changeDescription && (
|
|
165
|
-
<Flex>
|
|
166
|
-
<Text size="xs" c="dimmed" mb={4}>
|
|
167
|
-
Change Description
|
|
168
|
-
</Text>
|
|
169
|
-
<Text size="sm">{configValue.current.changeDescription}</Text>
|
|
170
|
-
</Flex>
|
|
171
|
-
)}
|
|
172
|
-
|
|
173
|
-
{configValue?.current && (
|
|
174
|
-
<Flex gap="xl">
|
|
175
|
-
<Flex>
|
|
176
|
-
<Text size="xs" c="dimmed" mb={2}>
|
|
177
|
-
Updated
|
|
178
|
-
</Text>
|
|
179
|
-
<Text size="sm">
|
|
180
|
-
{l(configValue.current.updatedAt, { date: "fromNow" })}
|
|
181
|
-
</Text>
|
|
182
|
-
</Flex>
|
|
183
|
-
{configValue.current.creatorName && (
|
|
184
|
-
<Flex>
|
|
185
|
-
<Text size="xs" c="dimmed" mb={2}>
|
|
186
|
-
Updated By
|
|
187
|
-
</Text>
|
|
188
|
-
<Text size="sm">{configValue.current.creatorName}</Text>
|
|
189
|
-
</Flex>
|
|
190
|
-
)}
|
|
191
|
-
</Flex>
|
|
192
|
-
)}
|
|
193
|
-
|
|
194
|
-
{!configValue?.current &&
|
|
195
|
-
configValue?.currentValue !== undefined && (
|
|
196
|
-
<Text size="xs" c="dimmed">
|
|
197
|
-
This configuration is using its default value. No versions
|
|
198
|
-
have been saved to the database yet.
|
|
199
|
-
</Text>
|
|
200
|
-
)}
|
|
201
|
-
|
|
202
|
-
{/* Scheduled update preview */}
|
|
203
|
-
{configValue?.next && (
|
|
204
|
-
<Card withBorder p="sm" bg="var(--mantine-color-blue-light)">
|
|
205
|
-
<Flex direction="column" gap="xs">
|
|
206
|
-
<Flex gap="xs">
|
|
207
|
-
<IconClock
|
|
208
|
-
size={14}
|
|
209
|
-
color="var(--mantine-color-blue-6)"
|
|
210
|
-
/>
|
|
211
|
-
<Text size="xs" fw={500} c="blue">
|
|
212
|
-
Scheduled Update (v{configValue.next.version})
|
|
213
|
-
</Text>
|
|
214
|
-
</Flex>
|
|
215
|
-
<Text size="xs" c="dimmed">
|
|
216
|
-
Activates{" "}
|
|
217
|
-
{l(configValue.next.activationDate, {
|
|
218
|
-
date: "fromNow",
|
|
219
|
-
})}
|
|
220
|
-
</Text>
|
|
221
|
-
<Code block style={{ whiteSpace: "pre-wrap" }} fz="xs">
|
|
222
|
-
{formatJson(configValue.next.content)}
|
|
223
|
-
</Code>
|
|
224
|
-
</Flex>
|
|
225
|
-
</Card>
|
|
226
|
-
)}
|
|
227
|
-
</Flex>
|
|
228
|
-
) : (
|
|
229
|
-
<Flex justify="center" align="center" h={200}>
|
|
230
|
-
<Text c="dimmed" size="sm">
|
|
231
|
-
No current value
|
|
232
|
-
</Text>
|
|
233
|
-
</Flex>
|
|
234
|
-
)}
|
|
235
|
-
</Flex>
|
|
236
|
-
|
|
237
|
-
{/* Footer with actions */}
|
|
238
|
-
{hasValidSchema && currentContent !== null && (
|
|
239
|
-
<Flex
|
|
240
|
-
p="md"
|
|
241
|
-
style={{
|
|
242
|
-
flexShrink: 0,
|
|
243
|
-
borderTop: "1px solid var(--mantine-color-default-border)",
|
|
244
|
-
}}
|
|
245
|
-
>
|
|
246
|
-
<Flex justify="flex-end" gap="sm">
|
|
247
|
-
<ActionButton
|
|
248
|
-
variant="subtle"
|
|
249
|
-
onClick={() => form.reset({} as any)}
|
|
250
|
-
disabled={saving}
|
|
251
|
-
>
|
|
252
|
-
Reset
|
|
253
|
-
</ActionButton>
|
|
254
|
-
<ActionButton intent="primary" form={form} loading={saving}>
|
|
255
|
-
Save Changes
|
|
256
|
-
</ActionButton>
|
|
257
|
-
</Flex>
|
|
258
|
-
</Flex>
|
|
259
|
-
)}
|
|
260
|
-
</Flex>
|
|
261
|
-
</Flex>
|
|
262
|
-
);
|
|
263
|
-
};
|
|
264
|
-
|
|
265
13
|
/**
|
|
266
14
|
* Parameter details panel.
|
|
267
15
|
* Shows loading state or the config form.
|
|
268
16
|
* Note: Empty state is handled by parent (AdminParameters).
|
|
269
17
|
*/
|
|
270
|
-
const ParameterDetails = ({
|
|
271
|
-
selectedConfig,
|
|
272
|
-
configValue,
|
|
273
|
-
loading,
|
|
274
|
-
saving,
|
|
275
|
-
onSave,
|
|
276
|
-
}: ParameterDetailsProps) => {
|
|
18
|
+
const ParameterDetails = (props: Props) => {
|
|
277
19
|
// Loading state
|
|
278
|
-
if (loading) {
|
|
279
|
-
return <
|
|
20
|
+
if (props.loading) {
|
|
21
|
+
return <ParameterDetailsLoading />;
|
|
280
22
|
}
|
|
281
23
|
|
|
282
24
|
// Config form (selectedConfig is guaranteed to be non-null by parent)
|
|
283
25
|
return (
|
|
284
|
-
<
|
|
285
|
-
selectedConfig={selectedConfig!}
|
|
286
|
-
configValue={configValue}
|
|
287
|
-
saving={saving}
|
|
288
|
-
onSave={onSave}
|
|
26
|
+
<ParameterDetailsConfigForm
|
|
27
|
+
selectedConfig={props.selectedConfig!}
|
|
28
|
+
configValue={props.configValue}
|
|
29
|
+
saving={props.saving}
|
|
30
|
+
onSave={props.onSave}
|
|
289
31
|
/>
|
|
290
32
|
);
|
|
291
33
|
};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { ActionButton, Flex, Text, TypeForm } from "@alepha/ui";
|
|
2
|
+
import { Card, Code } from "@mantine/core";
|
|
3
|
+
import { IconClock } from "@tabler/icons-react";
|
|
4
|
+
import { jsonSchemaToTypeBox, type TObject, t } from "alepha";
|
|
5
|
+
import { useForm } from "alepha/react/form";
|
|
6
|
+
import { useI18n } from "alepha/react/i18n";
|
|
7
|
+
import { useMemo } from "react";
|
|
8
|
+
import { formatJson, type ParameterValue } from "./types.ts";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
selectedConfig: string;
|
|
12
|
+
configValue: ParameterValue | null;
|
|
13
|
+
saving: boolean;
|
|
14
|
+
onSave: (values: Record<string, unknown>) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The actual form component - only rendered when a config is selected.
|
|
19
|
+
*/
|
|
20
|
+
const ParameterDetailsConfigForm = (props: Props) => {
|
|
21
|
+
const { l } = useI18n();
|
|
22
|
+
|
|
23
|
+
// Get the current value to display (from saved version or default)
|
|
24
|
+
const currentContent = useMemo(() => {
|
|
25
|
+
if (props.configValue?.current?.content) {
|
|
26
|
+
return props.configValue.current.content;
|
|
27
|
+
}
|
|
28
|
+
if (props.configValue?.currentValue !== undefined) {
|
|
29
|
+
return props.configValue.currentValue;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}, [props.configValue]);
|
|
33
|
+
|
|
34
|
+
// Convert JSON Schema from API to TypeBox schema
|
|
35
|
+
const schemaForForm = useMemo(() => {
|
|
36
|
+
if (!props.configValue?.schema) {
|
|
37
|
+
return t.object({});
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
return jsonSchemaToTypeBox(props.configValue.schema) as TObject;
|
|
41
|
+
} catch {
|
|
42
|
+
return t.object({});
|
|
43
|
+
}
|
|
44
|
+
}, [props.configValue?.schema]);
|
|
45
|
+
|
|
46
|
+
const form = useForm(
|
|
47
|
+
{
|
|
48
|
+
schema: schemaForForm,
|
|
49
|
+
initialValues: (currentContent ?? {}) as Record<string, unknown>,
|
|
50
|
+
handler: async (values) => {
|
|
51
|
+
await props.onSave(values as Record<string, unknown>);
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
[props.selectedConfig, schemaForForm, currentContent],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Check if we have a valid schema with properties
|
|
58
|
+
const hasValidSchema = useMemo(() => {
|
|
59
|
+
const schema = props.configValue?.schema;
|
|
60
|
+
return (
|
|
61
|
+
schema &&
|
|
62
|
+
typeof schema === "object" &&
|
|
63
|
+
"properties" in schema &&
|
|
64
|
+
Object.keys(schema.properties as object).length > 0
|
|
65
|
+
);
|
|
66
|
+
}, [props.configValue?.schema]);
|
|
67
|
+
|
|
68
|
+
// Count the number of fields to determine column layout
|
|
69
|
+
const fieldCount = useMemo(() => {
|
|
70
|
+
const schema = props.configValue?.schema;
|
|
71
|
+
if (
|
|
72
|
+
schema &&
|
|
73
|
+
typeof schema === "object" &&
|
|
74
|
+
"properties" in schema &&
|
|
75
|
+
schema.properties
|
|
76
|
+
) {
|
|
77
|
+
return Object.keys(schema.properties as object).length;
|
|
78
|
+
}
|
|
79
|
+
return 0;
|
|
80
|
+
}, [props.configValue?.schema]);
|
|
81
|
+
|
|
82
|
+
// Determine optimal column count based on field count
|
|
83
|
+
const columns = useMemo(() => {
|
|
84
|
+
if (fieldCount <= 2) return 1;
|
|
85
|
+
if (fieldCount <= 6) return 2;
|
|
86
|
+
return 3;
|
|
87
|
+
}, [fieldCount]);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<Flex
|
|
91
|
+
flex={1}
|
|
92
|
+
h="100%"
|
|
93
|
+
style={{
|
|
94
|
+
overflow: "hidden",
|
|
95
|
+
minWidth: 0,
|
|
96
|
+
display: "flex",
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<Flex direction="column" h="100%" w="100%" style={{ minHeight: 0 }}>
|
|
100
|
+
{/* Content */}
|
|
101
|
+
<Flex
|
|
102
|
+
flex={1}
|
|
103
|
+
p="md"
|
|
104
|
+
className="overflow-auto"
|
|
105
|
+
style={{ minHeight: 0 }}
|
|
106
|
+
>
|
|
107
|
+
{currentContent !== null ? (
|
|
108
|
+
<Flex direction="column" gap="lg">
|
|
109
|
+
{/* Form or JSON view */}
|
|
110
|
+
<Flex>
|
|
111
|
+
{hasValidSchema ? (
|
|
112
|
+
<TypeForm
|
|
113
|
+
form={form}
|
|
114
|
+
columns={columns}
|
|
115
|
+
skipSubmitButton
|
|
116
|
+
fill={false}
|
|
117
|
+
/>
|
|
118
|
+
) : (
|
|
119
|
+
<Flex>
|
|
120
|
+
<Text size="xs" c="dimmed" mb={4}>
|
|
121
|
+
Current Value
|
|
122
|
+
</Text>
|
|
123
|
+
<Code block style={{ whiteSpace: "pre-wrap" }}>
|
|
124
|
+
{formatJson(currentContent)}
|
|
125
|
+
</Code>
|
|
126
|
+
</Flex>
|
|
127
|
+
)}
|
|
128
|
+
</Flex>
|
|
129
|
+
|
|
130
|
+
{/* Metadata */}
|
|
131
|
+
{props.configValue?.current?.changeDescription && (
|
|
132
|
+
<Flex>
|
|
133
|
+
<Text size="xs" c="dimmed" mb={4}>
|
|
134
|
+
Change Description
|
|
135
|
+
</Text>
|
|
136
|
+
<Text size="sm">
|
|
137
|
+
{props.configValue.current.changeDescription}
|
|
138
|
+
</Text>
|
|
139
|
+
</Flex>
|
|
140
|
+
)}
|
|
141
|
+
|
|
142
|
+
{props.configValue?.current && (
|
|
143
|
+
<Flex gap="xl">
|
|
144
|
+
<Flex>
|
|
145
|
+
<Text size="xs" c="dimmed" mb={2}>
|
|
146
|
+
Updated
|
|
147
|
+
</Text>
|
|
148
|
+
<Text size="sm">
|
|
149
|
+
{l(props.configValue.current.updatedAt, {
|
|
150
|
+
date: "fromNow",
|
|
151
|
+
})}
|
|
152
|
+
</Text>
|
|
153
|
+
</Flex>
|
|
154
|
+
{props.configValue.current.creatorName && (
|
|
155
|
+
<Flex>
|
|
156
|
+
<Text size="xs" c="dimmed" mb={2}>
|
|
157
|
+
Updated By
|
|
158
|
+
</Text>
|
|
159
|
+
<Text size="sm">
|
|
160
|
+
{props.configValue.current.creatorName}
|
|
161
|
+
</Text>
|
|
162
|
+
</Flex>
|
|
163
|
+
)}
|
|
164
|
+
</Flex>
|
|
165
|
+
)}
|
|
166
|
+
|
|
167
|
+
{!props.configValue?.current &&
|
|
168
|
+
props.configValue?.currentValue !== undefined && (
|
|
169
|
+
<Text size="xs" c="dimmed">
|
|
170
|
+
This configuration is using its default value. No versions
|
|
171
|
+
have been saved to the database yet.
|
|
172
|
+
</Text>
|
|
173
|
+
)}
|
|
174
|
+
|
|
175
|
+
{/* Scheduled update preview */}
|
|
176
|
+
{props.configValue?.next && (
|
|
177
|
+
<Card withBorder p="sm" bg="var(--mantine-color-blue-light)">
|
|
178
|
+
<Flex direction="column" gap="xs">
|
|
179
|
+
<Flex gap="xs">
|
|
180
|
+
<IconClock
|
|
181
|
+
size={14}
|
|
182
|
+
color="var(--mantine-color-blue-6)"
|
|
183
|
+
/>
|
|
184
|
+
<Text size="xs" fw={500} c="blue">
|
|
185
|
+
Scheduled Update (v{props.configValue.next.version})
|
|
186
|
+
</Text>
|
|
187
|
+
</Flex>
|
|
188
|
+
<Text size="xs" c="dimmed">
|
|
189
|
+
Activates{" "}
|
|
190
|
+
{l(props.configValue.next.activationDate, {
|
|
191
|
+
date: "fromNow",
|
|
192
|
+
})}
|
|
193
|
+
</Text>
|
|
194
|
+
<Code block style={{ whiteSpace: "pre-wrap" }} fz="xs">
|
|
195
|
+
{formatJson(props.configValue.next.content)}
|
|
196
|
+
</Code>
|
|
197
|
+
</Flex>
|
|
198
|
+
</Card>
|
|
199
|
+
)}
|
|
200
|
+
</Flex>
|
|
201
|
+
) : (
|
|
202
|
+
<Flex justify="center" align="center" h={200}>
|
|
203
|
+
<Text c="dimmed" size="sm">
|
|
204
|
+
No current value
|
|
205
|
+
</Text>
|
|
206
|
+
</Flex>
|
|
207
|
+
)}
|
|
208
|
+
</Flex>
|
|
209
|
+
|
|
210
|
+
{/* Footer with actions */}
|
|
211
|
+
{hasValidSchema && currentContent !== null && (
|
|
212
|
+
<Flex
|
|
213
|
+
p="md"
|
|
214
|
+
style={{
|
|
215
|
+
flexShrink: 0,
|
|
216
|
+
borderTop: "1px solid var(--mantine-color-default-border)",
|
|
217
|
+
}}
|
|
218
|
+
>
|
|
219
|
+
<Flex justify="flex-end" gap="sm">
|
|
220
|
+
<ActionButton
|
|
221
|
+
variant="subtle"
|
|
222
|
+
onClick={() => form.reset({} as any)}
|
|
223
|
+
disabled={props.saving}
|
|
224
|
+
>
|
|
225
|
+
Reset
|
|
226
|
+
</ActionButton>
|
|
227
|
+
<ActionButton intent="primary" form={form} loading={props.saving}>
|
|
228
|
+
Save Changes
|
|
229
|
+
</ActionButton>
|
|
230
|
+
</Flex>
|
|
231
|
+
</Flex>
|
|
232
|
+
)}
|
|
233
|
+
</Flex>
|
|
234
|
+
</Flex>
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export default ParameterDetailsConfigForm;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Flex } from "@alepha/ui";
|
|
2
|
+
import { Loader } from "@mantine/core";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Loading state for the parameter details panel.
|
|
6
|
+
*/
|
|
7
|
+
const ParameterDetailsLoading = () => (
|
|
8
|
+
<Flex
|
|
9
|
+
flex={1}
|
|
10
|
+
h="100%"
|
|
11
|
+
p="md"
|
|
12
|
+
style={{
|
|
13
|
+
overflow: "hidden",
|
|
14
|
+
minWidth: 0,
|
|
15
|
+
display: "flex",
|
|
16
|
+
}}
|
|
17
|
+
>
|
|
18
|
+
<Flex flex={1} justify="center" align="center" h="100%">
|
|
19
|
+
<Loader size="sm" />
|
|
20
|
+
</Flex>
|
|
21
|
+
</Flex>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export default ParameterDetailsLoading;
|
|
@@ -5,22 +5,21 @@ import type { ParameterResponse } from "alepha/api/parameters";
|
|
|
5
5
|
import { useI18n } from "alepha/react/i18n";
|
|
6
6
|
import { getStatusColor } from "./types.ts";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
interface Props {
|
|
9
9
|
selectedConfig: string | null;
|
|
10
10
|
history: ParameterResponse[];
|
|
11
11
|
loading: boolean;
|
|
12
12
|
onRollback: (version: number) => void;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}: ParameterHistoryProps) => {
|
|
15
|
+
/**
|
|
16
|
+
* Parameter version history timeline panel.
|
|
17
|
+
*/
|
|
18
|
+
const ParameterHistory = (props: Props) => {
|
|
20
19
|
const { l } = useI18n();
|
|
21
20
|
|
|
22
21
|
const renderContent = () => {
|
|
23
|
-
if (loading) {
|
|
22
|
+
if (props.loading) {
|
|
24
23
|
return (
|
|
25
24
|
<Flex flex={1} justify="center" align="center">
|
|
26
25
|
<Loader size="sm" />
|
|
@@ -28,7 +27,7 @@ const ParameterHistory = ({
|
|
|
28
27
|
);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
if (history.length === 0) {
|
|
30
|
+
if (props.history.length === 0) {
|
|
32
31
|
return (
|
|
33
32
|
<Flex flex={1} justify="center" align="center">
|
|
34
33
|
<Text c="dimmed" size="xs">
|
|
@@ -41,11 +40,11 @@ const ParameterHistory = ({
|
|
|
41
40
|
return (
|
|
42
41
|
<ScrollArea flex={1} offsetScrollbars>
|
|
43
42
|
<Timeline
|
|
44
|
-
active={history.findIndex((h) => h.status === "current")}
|
|
43
|
+
active={props.history.findIndex((h) => h.status === "current")}
|
|
45
44
|
bulletSize={24}
|
|
46
45
|
lineWidth={2}
|
|
47
46
|
>
|
|
48
|
-
{history.map((version) => (
|
|
47
|
+
{props.history.map((version) => (
|
|
49
48
|
<Timeline.Item
|
|
50
49
|
key={version.id}
|
|
51
50
|
bullet={
|
|
@@ -91,7 +90,7 @@ const ParameterHistory = ({
|
|
|
91
90
|
<ActionButton
|
|
92
91
|
size="compact-xs"
|
|
93
92
|
variant="subtle"
|
|
94
|
-
onClick={() => onRollback(version.version)}
|
|
93
|
+
onClick={() => props.onRollback(version.version)}
|
|
95
94
|
>
|
|
96
95
|
Rollback to this version
|
|
97
96
|
</ActionButton>
|