Skip to content

Commit fe069dc

Browse files
committed
enhance metric form UI
1 parent 7af5f45 commit fe069dc

6 files changed

Lines changed: 116 additions & 38 deletions

File tree

internal/webui/src/containers/MetricFormDialog/MetricFormDialog.consts.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,16 @@ export const getMetricInitialValues = (data?: MetricGridRow): MetricFormValues =
1414
Gauges: convertGauges(data?.Metric.Gauges ?? [""]),
1515
InitSQL: data?.Metric.InitSQL ?? "",
1616
IsInstanceLevel: data?.Metric.IsInstanceLevel ?? false,
17-
SQLs: yaml.stringify(data?.Metric.SQLs) ?? "",
17+
SQLs: (data?.Metric.SQLs) ?? "",
1818
};
1919
};
2020

2121
export const createMetricRequest = (values: MetricFormValues): MetricRequestBody => {
22-
const sqls: Record<number, string> = {};
23-
yaml.parse(values.SQLs, (key, value) => {
24-
if (key) {
25-
const version = Number(key);
26-
if (Number.isNaN(version)) {
27-
throw new Error("Version is not a valid number");
28-
}
29-
sqls[Number(key)] = String(value);
30-
}
31-
});
22+
const formattedSQLs = values.SQLs.reduce((acc, current) => {
23+
// Key = Version, Value = SQL
24+
acc[current.Version] = current.SQL;
25+
return acc;
26+
}, {} as Record<string, string>);
3227

3328
return {
3429
Name: values.Name,
@@ -39,7 +34,7 @@ export const createMetricRequest = (values: MetricFormValues): MetricRequestBody
3934
Gauges: values.Gauges?.split("\n"),
4035
InitSQL: values.InitSQL,
4136
IsInstanceLevel: values.IsInstanceLevel,
42-
SQLs: sqls,
37+
SQLs: formattedSQLs,
4338
},
4439
};
4540
};

internal/webui/src/containers/MetricFormDialog/MetricFormDialog.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,17 @@ export const MetricFormDialog = () => {
2020

2121
useEffect(() => {
2222
const initialValues = getMetricInitialValues(data);
23-
reset(initialValues);
23+
// Convert SQLs object to array format for the form
24+
const formattedValues = {
25+
...initialValues,
26+
SQLs: initialValues?.SQLs && !Array.isArray(initialValues.SQLs)
27+
? Object.entries(initialValues.SQLs).map(([key, value]) => ({
28+
Version: key,
29+
SQL: value as string
30+
}))
31+
: []
32+
};
33+
reset(formattedValues);
2434
}, [data, open, reset]);
2535

2636
const submitTitle = useMemo(

internal/webui/src/containers/MetricFormDialog/components/MetricForm/MetricForm.consts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ export const metricFormValuesValidationSchema = Yup.object({
1414
Gauges: Yup.string().optional().nullable(),
1515
InitSQL: Yup.string().optional().nullable(),
1616
IsInstanceLevel: Yup.bool().required(),
17-
SQLs: Yup.string().trim().required("SQLs is required"),
17+
SQLs: Yup.array().of(Yup.object().shape({Version: Yup.string().required("Version is required"),SQL: Yup.string().required("SQL value is required"),})),
1818
});

internal/webui/src/containers/MetricFormDialog/components/MetricForm/MetricForm.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type MetricFormSettings = {
1616
};
1717

1818
type MetricFormSQL = {
19-
SQLs: string;
19+
SQLs: Record<string, string>;
2020
};
2121

2222
export type MetricFormValues = MetricFormGeneral & MetricFormSettings & MetricFormSQL;
Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { FormControl, FormHelperText, InputLabel, OutlinedInput } from "@mui/material";
2-
import { useFormContext } from "react-hook-form";
2+
import { Controller, useFieldArray, useFormContext } from "react-hook-form";
33
import { useFormStyles } from "styles/form";
44
import { MetricFormValues } from "../MetricForm.types";
5+
import { Button, FormControl, FormHelperText, IconButton, InputLabel, OutlinedInput } from "@mui/material";
6+
import DeleteIcon from "@mui/icons-material/Delete";
7+
import { Autocomplete } from "components/Autocomplete/Autocomplete";
8+
import { useMemo } from "react";
59

610
export const MetricFormStepSQL = () => {
7-
const { register, formState: { errors } } = useFormContext<MetricFormValues>();
11+
const { control, register, formState: { errors } , clearErrors} = useFormContext<MetricFormValues>();
812
const { classes, cx } = useFormStyles();
13+
const SqlFields = useFieldArray({ control, name: "SQLs" });
914

1015
const hasError = (field: keyof MetricFormValues) => !!errors[field];
1116

@@ -16,31 +21,91 @@ export const MetricFormStepSQL = () => {
1621
}
1722
return undefined;
1823
};
24+
const handleSqlAppend = () => {
25+
SqlFields.append({ Version: "", SQL: "" });
26+
clearErrors("PresetMetrics");
27+
};
28+
29+
const VersionOptions = useMemo(() => [
30+
"15",
31+
"14",
32+
"13",
33+
"12",
34+
"11",
35+
"10",
36+
].map((key) => ({ label: key })),
37+
[]
38+
);
39+
40+
const getArrayError = (
41+
index: number,
42+
field: "Version" | "SQL"
43+
) => errors.SQLs?.[index]?.[field]?.message;
1944

2045
return (
2146
<div className={classes.form}>
22-
<FormControl
23-
className={cx(classes.formControlInput, classes.widthFull)}
24-
error={hasError("SQLs")}
25-
variant="outlined"
26-
>
27-
<InputLabel htmlFor="SQLs">SQLs</InputLabel>
28-
<OutlinedInput
29-
{...register("SQLs")}
30-
id="SQLs"
31-
label="SQLs"
32-
aria-describedby="SQLs-error"
33-
multiline
34-
rows={15}
35-
inputProps={{
36-
style: {
37-
font: "revert",
38-
fontSize: "0.7rem",
39-
}
40-
}}
41-
/>
47+
{SqlFields.fields.map(({ id }, index) => (
48+
<div className={classes.row} key={id}>
49+
<FormControl
50+
className={cx(classes.formControlInput, classes.widthQuarter)}
51+
variant="outlined"
52+
error={!!getArrayError(index, "Version")}
53+
>
54+
<Controller
55+
name={`SQLs.${index}.Version`}
56+
control={control}
57+
render={({ field }) => (
58+
<Autocomplete
59+
{...field}
60+
id={`SQLs.${index}.Version`}
61+
label="Version"
62+
options={VersionOptions}
63+
freeSolo
64+
value={field.value}
65+
onInputChange={(_, value) => field.onChange(value)}
66+
// TDDO: Restrict input to numbers and dots only, but allow free solo for custom versions
67+
68+
/>
69+
)}
70+
/>
71+
<FormHelperText>{getArrayError(index, "Version")}</FormHelperText>
72+
</FormControl>
73+
<FormControl
74+
className={cx(classes.formControlInput, classes.widthThreeQuarter)}
75+
variant="outlined"
76+
error={hasError("SQLs")}
77+
>
78+
<InputLabel htmlFor={`SQLs.${index}.SQL`}>SQL</InputLabel>
79+
<OutlinedInput
80+
{...register(`SQLs.${index}.SQL`)}
81+
id={`SQLs.${index}.SQL`}
82+
label="SQL"
83+
multiline
84+
minRows={3}
85+
maxRows={12}
86+
endAdornment={
87+
<IconButton
88+
key={`SQLs.${index}.Delete`}
89+
title="Delete SQL"
90+
onClick={() => SqlFields.remove(index)}
91+
>
92+
<DeleteIcon />
93+
</IconButton>
94+
}
95+
/>
96+
<FormHelperText>{getArrayError(index, "SQL")}</FormHelperText>
97+
</FormControl>
98+
</div>
99+
))}
100+
<div className={cx(classes.row, classes.addButton)}>
101+
<Button
102+
variant="contained"
103+
onClick={handleSqlAppend}
104+
>
105+
Add SQLs
106+
</Button>
107+
</div>
42108
<FormHelperText id="SQLs-error">{getError("SQLs")}</FormHelperText>
43-
</FormControl>
44109
</div>
45110
);
46111
};

internal/webui/src/styles/form.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ export const useFormStyles = makeStyles()(
5757
maxWidth: "100%",
5858
width: "100%",
5959
},
60+
widthQuarter: {
61+
flex: "0 0 20%",
62+
maxWidth: "25%",
63+
},
64+
widthThreeQuarter: {
65+
flex: "0 0 75%",
66+
maxWidth: "75%",
67+
},
6068
hidden: {
6169
display: "none",
6270
}

0 commit comments

Comments
 (0)