feat: add setup wizard
This commit is contained in:
95
frontend/src/components/admin/AdminConfigTable.tsx
Normal file
95
frontend/src/components/admin/AdminConfigTable.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
import { ActionIcon, Code, Group, Skeleton, Table, Text } from "@mantine/core";
|
||||
import { useModals } from "@mantine/modals";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TbEdit, TbLock } from "react-icons/tb";
|
||||
import configService from "../../services/config.service";
|
||||
import { AdminConfig as AdminConfigType } from "../../types/config.type";
|
||||
import showUpdateConfigVariableModal from "./showUpdateConfigVariableModal";
|
||||
|
||||
const AdminConfigTable = () => {
|
||||
const modals = useModals();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const [configVariables, setConfigVariables] = useState<AdminConfigType[]>([]);
|
||||
|
||||
const getConfigVariables = () => {
|
||||
setIsLoading(true);
|
||||
configService.listForAdmin().then((configVariables) => {
|
||||
setConfigVariables(configVariables);
|
||||
setIsLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getConfigVariables();
|
||||
}, []);
|
||||
|
||||
const skeletonRows = [...Array(9)].map((c, i) => (
|
||||
<tr key={i}>
|
||||
<td>
|
||||
<Skeleton height={18} width={80} mb="sm" />
|
||||
<Skeleton height={30} />
|
||||
</td>
|
||||
<td>
|
||||
<Skeleton height={18} />
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<Group position="right">
|
||||
<Skeleton height={25} width={25} />
|
||||
</Group>
|
||||
</td>
|
||||
</tr>
|
||||
));
|
||||
|
||||
return (
|
||||
<Table verticalSpacing="sm" horizontalSpacing="xl" withBorder>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{isLoading
|
||||
? skeletonRows
|
||||
: configVariables.map((element) => (
|
||||
<tr key={element.key}>
|
||||
<td style={{ maxWidth: "200px" }}>
|
||||
<Code>{element.key}</Code> {element.secret && <TbLock />}{" "}
|
||||
<br />
|
||||
<Text size="xs" color="dimmed">
|
||||
{" "}
|
||||
{element.description}
|
||||
</Text>
|
||||
</td>
|
||||
<td>{element.value}</td>
|
||||
|
||||
<td>
|
||||
<Group position="right">
|
||||
<ActionIcon
|
||||
color="primary"
|
||||
variant="light"
|
||||
size={25}
|
||||
onClick={() =>
|
||||
showUpdateConfigVariableModal(
|
||||
modals,
|
||||
element,
|
||||
getConfigVariables
|
||||
)
|
||||
}
|
||||
>
|
||||
<TbEdit />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminConfigTable;
|
||||
@@ -0,0 +1,96 @@
|
||||
import {
|
||||
Button,
|
||||
Code,
|
||||
NumberInput,
|
||||
Select,
|
||||
Space,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { useModals } from "@mantine/modals";
|
||||
import { ModalsContextProps } from "@mantine/modals/lib/context";
|
||||
import configService from "../../services/config.service";
|
||||
import { AdminConfig } from "../../types/config.type";
|
||||
import toast from "../../utils/toast.util";
|
||||
|
||||
const showUpdateConfigVariableModal = (
|
||||
modals: ModalsContextProps,
|
||||
configVariable: AdminConfig,
|
||||
getConfigVariables: () => void
|
||||
) => {
|
||||
return modals.openModal({
|
||||
title: <Title order={5}>Update configuration variable</Title>,
|
||||
children: (
|
||||
<Body
|
||||
configVariable={configVariable}
|
||||
getConfigVariables={getConfigVariables}
|
||||
/>
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
const Body = ({
|
||||
configVariable,
|
||||
getConfigVariables,
|
||||
}: {
|
||||
configVariable: AdminConfig;
|
||||
getConfigVariables: () => void;
|
||||
}) => {
|
||||
const modals = useModals();
|
||||
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
stringValue: configVariable.value,
|
||||
numberValue: parseInt(configVariable.value),
|
||||
booleanValue: configVariable.value,
|
||||
},
|
||||
});
|
||||
return (
|
||||
<Stack align="stretch">
|
||||
<Text>
|
||||
Set <Code>{configVariable.key}</Code> to
|
||||
</Text>
|
||||
{configVariable.type == "string" && (
|
||||
<TextInput label="Value" {...form.getInputProps("stringValue")} />
|
||||
)}
|
||||
{configVariable.type == "number" && (
|
||||
<NumberInput label="Value" {...form.getInputProps("numberValue")} />
|
||||
)}
|
||||
{configVariable.type == "boolean" && (
|
||||
<Select
|
||||
data={[
|
||||
{ value: "true", label: "True" },
|
||||
{ value: "false", label: "False" },
|
||||
]}
|
||||
{...form.getInputProps("booleanValue")}
|
||||
/>
|
||||
)}
|
||||
<Space />
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const value =
|
||||
configVariable.type == "string"
|
||||
? form.values.stringValue
|
||||
: configVariable.type == "number"
|
||||
? form.values.numberValue
|
||||
: form.values.booleanValue == "true";
|
||||
|
||||
await configService
|
||||
.update(configVariable.key, value)
|
||||
.then(() => {
|
||||
getConfigVariables();
|
||||
modals.closeAll();
|
||||
})
|
||||
.catch((e) => toast.error(e.response.data.message));
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default showUpdateConfigVariableModal;
|
||||
Reference in New Issue
Block a user