add & configure machine: added formular integration
This commit is contained in:
parent
15a136b266
commit
97b8c7a701
@ -1,6 +1,13 @@
|
||||
import { setMachineSchema } from "@/api/machine/machine";
|
||||
import { useListClanModules } from "@/api/modules/modules";
|
||||
import { Alert, AlertTitle, FormHelperText, Typography } from "@mui/material";
|
||||
import {
|
||||
Alert,
|
||||
AlertTitle,
|
||||
Divider,
|
||||
FormHelperText,
|
||||
Input,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import Box from "@mui/material/Box";
|
||||
import Chip from "@mui/material/Chip";
|
||||
import FormControl from "@mui/material/FormControl";
|
||||
@ -8,9 +15,14 @@ import InputLabel from "@mui/material/InputLabel";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import OutlinedInput from "@mui/material/OutlinedInput";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { useEffect } from "react";
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { CreateMachineForm, FormStepContentProps } from "./interfaces";
|
||||
import {
|
||||
CreateMachineForm,
|
||||
FormHooks,
|
||||
FormStepContentProps,
|
||||
} from "./interfaces";
|
||||
|
||||
const ITEM_HEIGHT = 48;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
@ -23,51 +35,114 @@ const MenuProps = {
|
||||
},
|
||||
};
|
||||
|
||||
interface IupdateSchema {
|
||||
clanName: string;
|
||||
modules: string[];
|
||||
formHooks: FormHooks;
|
||||
setSchemaError: Dispatch<SetStateAction<null | string>>;
|
||||
}
|
||||
|
||||
const updateSchema = ({
|
||||
clanName,
|
||||
modules,
|
||||
formHooks,
|
||||
setSchemaError,
|
||||
}: IupdateSchema) => {
|
||||
formHooks.setValue("isSchemaLoading", true);
|
||||
setMachineSchema(clanName, "example_machine", {
|
||||
clanImports: modules,
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.statusText == "OK") {
|
||||
formHooks.setValue("schema", response.data.schema);
|
||||
setSchemaError(null);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
formHooks.setValue("schema", {});
|
||||
console.error({ error });
|
||||
setSchemaError(error.message);
|
||||
toast.error(`${error.message}`);
|
||||
})
|
||||
.finally(() => {
|
||||
formHooks.setValue("isSchemaLoading", false);
|
||||
});
|
||||
};
|
||||
|
||||
type ClanModulesProps = FormStepContentProps;
|
||||
|
||||
const SchemaSuccessMsg = () => (
|
||||
<Alert severity="success">
|
||||
<AlertTitle>Success</AlertTitle>
|
||||
<Typography variant="subtitle2" sx={{ mt: 2 }}>
|
||||
Machine configuration schema successfully created.
|
||||
</Typography>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
interface SchemaErrorMsgProps {
|
||||
msg: string | null;
|
||||
}
|
||||
|
||||
const SchemaErrorMsg = (props: SchemaErrorMsgProps) => (
|
||||
<Alert severity="error">
|
||||
<AlertTitle>Error</AlertTitle>
|
||||
<Typography variant="subtitle1" sx={{ mt: 2 }}>
|
||||
Machine configuration schema could not be created.
|
||||
</Typography>
|
||||
<Typography variant="subtitle2" sx={{ mt: 2 }}>
|
||||
{props.msg}
|
||||
</Typography>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
export default function ClanModules(props: ClanModulesProps) {
|
||||
const { clanName, formHooks } = props;
|
||||
const { data, isLoading } = useListClanModules(clanName);
|
||||
|
||||
const [schemaError, setSchemaError] = useState<string | null>(null);
|
||||
const selectedModules = formHooks.watch("modules");
|
||||
|
||||
useEffect(() => {
|
||||
setMachineSchema(clanName, "example_machine", {
|
||||
imports: [],
|
||||
}).then((response) => {
|
||||
if (response.statusText == "OK") {
|
||||
formHooks.setValue("schema", response.data.schema);
|
||||
}
|
||||
updateSchema({
|
||||
clanName,
|
||||
modules: formHooks.watch("modules"),
|
||||
formHooks,
|
||||
setSchemaError,
|
||||
});
|
||||
formHooks.setValue("modules", []);
|
||||
|
||||
// Only re-run if global clanName has changed
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [clanName]);
|
||||
const isSchemaLoading = formHooks.watch("isSchemaLoading");
|
||||
|
||||
const handleChange = (
|
||||
event: SelectChangeEvent<CreateMachineForm["modules"]>,
|
||||
event: SelectChangeEvent<CreateMachineForm["modules"]>
|
||||
) => {
|
||||
const {
|
||||
target: { value },
|
||||
} = event;
|
||||
const newValue = typeof value === "string" ? value.split(",") : value;
|
||||
formHooks.setValue("modules", newValue);
|
||||
setMachineSchema(clanName, "example_machine", {
|
||||
imports: newValue,
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.statusText == "OK") {
|
||||
formHooks.setValue("schema", response.data.schema);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
formHooks.setValue("schema", {});
|
||||
console.error({ error });
|
||||
toast.error(`${error.message}`);
|
||||
});
|
||||
|
||||
updateSchema({
|
||||
clanName,
|
||||
modules: newValue,
|
||||
formHooks,
|
||||
setSchemaError,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="my-4 flex w-full flex-col justify-center px-2">
|
||||
<FormControl sx={{ my: 4 }} disabled={isLoading} required>
|
||||
<InputLabel>Machine name</InputLabel>
|
||||
<Controller
|
||||
name="name"
|
||||
control={formHooks.control}
|
||||
render={({ field }) => <Input {...field} />}
|
||||
/>
|
||||
<FormHelperText>Choose a unique name for the machine.</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<Alert severity="info">
|
||||
<AlertTitle>Info</AlertTitle>
|
||||
Optionally select some modules —{" "}
|
||||
@ -106,6 +181,14 @@ export default function ClanModules(props: ClanModulesProps) {
|
||||
(Optional) Select clan modules to be added.
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
{!isSchemaLoading && <Divider flexItem sx={{ my: 4 }} />}
|
||||
{!isSchemaLoading &&
|
||||
(!schemaError ? (
|
||||
<SchemaSuccessMsg />
|
||||
) : (
|
||||
<SchemaErrorMsg msg={schemaError} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ export function CustomConfig(props: FormStepContentProps) {
|
||||
}
|
||||
return acc;
|
||||
}, {}),
|
||||
[schema],
|
||||
[schema]
|
||||
);
|
||||
|
||||
return (
|
||||
@ -110,11 +110,11 @@ function PureCustomConfig(props: PureCustomConfigProps) {
|
||||
message: "invalid config",
|
||||
});
|
||||
toast.error(
|
||||
"Configuration is invalid. Please check the highlighted fields for details.",
|
||||
"Configuration is invalid. Please check the highlighted fields for details."
|
||||
);
|
||||
} else {
|
||||
formHooks.clearErrors("config");
|
||||
toast.success("Config seems valid");
|
||||
toast.success("Configuration is valid");
|
||||
}
|
||||
};
|
||||
|
||||
@ -139,7 +139,7 @@ function PureCustomConfig(props: PureCustomConfigProps) {
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Validate
|
||||
Validate configuration
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { createMachine, setMachineConfig } from "@/api/machine/machine";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
LinearProgress,
|
||||
MobileStepper,
|
||||
Step,
|
||||
@ -11,6 +13,7 @@ import {
|
||||
} from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useAppState } from "../hooks/useAppContext";
|
||||
import ClanModules from "./clanModules";
|
||||
import { CustomConfig } from "./customConfig";
|
||||
@ -22,22 +25,19 @@ export function CreateMachineForm() {
|
||||
} = useAppState();
|
||||
const formHooks = useForm<CreateMachineForm>({
|
||||
defaultValues: {
|
||||
isSchemaLoading: false,
|
||||
name: "",
|
||||
config: {},
|
||||
modules: [],
|
||||
},
|
||||
});
|
||||
const { handleSubmit, reset } = formHooks;
|
||||
|
||||
const { handleSubmit, reset, watch } = formHooks;
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
||||
const [activeStep, setActiveStep] = useState<number>(0);
|
||||
|
||||
const steps: FormStep[] = [
|
||||
{
|
||||
id: "template",
|
||||
label: "Template",
|
||||
content: <div></div>,
|
||||
},
|
||||
{
|
||||
id: "modules",
|
||||
label: "Modules",
|
||||
@ -56,11 +56,6 @@ export function CreateMachineForm() {
|
||||
<LinearProgress />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "save",
|
||||
label: "Save",
|
||||
content: <div></div>,
|
||||
},
|
||||
];
|
||||
|
||||
const handleNext = () => {
|
||||
@ -75,14 +70,23 @@ export function CreateMachineForm() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setActiveStep(0);
|
||||
reset();
|
||||
};
|
||||
const currentStep = steps.at(activeStep);
|
||||
|
||||
async function onSubmit(data: any) {
|
||||
async function onSubmit(data: CreateMachineForm) {
|
||||
console.log({ data }, "Aggregated Data; creating machine from");
|
||||
if (clanName) {
|
||||
if (!data.name) {
|
||||
toast.error("Machine name should not be empty");
|
||||
return;
|
||||
}
|
||||
await createMachine(clanName, {
|
||||
name: data.name,
|
||||
});
|
||||
await setMachineConfig(clanName, data.name, {
|
||||
config: data.config.formData,
|
||||
clanImports: data.modules,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const BackButton = () => (
|
||||
@ -102,17 +106,21 @@ export function CreateMachineForm() {
|
||||
<Button
|
||||
disabled={
|
||||
!formHooks.formState.isValid ||
|
||||
(activeStep == 1 && !formHooks.watch("schema")?.type)
|
||||
(activeStep == 0 && !watch("schema")?.type) ||
|
||||
watch("isSchemaLoading")
|
||||
}
|
||||
onClick={handleNext}
|
||||
color="secondary"
|
||||
startIcon={
|
||||
watch("isSchemaLoading") ? <CircularProgress /> : undefined
|
||||
}
|
||||
>
|
||||
{activeStep <= steps.length - 1 && "Next"}
|
||||
</Button>
|
||||
)}
|
||||
{activeStep === steps.length - 1 && (
|
||||
<Button color="secondary" onClick={handleReset}>
|
||||
Reset
|
||||
<Button color="secondary" type="submit">
|
||||
Save
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
@ -9,6 +9,7 @@ export type CreateMachineForm = {
|
||||
config: any;
|
||||
modules: string[];
|
||||
schema: JSONSchema7;
|
||||
isSchemaLoading: boolean;
|
||||
};
|
||||
|
||||
export type FormHooks = UseFormReturn<CreateMachineForm>;
|
||||
|
Loading…
Reference in New Issue
Block a user