Skip to content

Commit

Permalink
chore(meshconfig): fix form
Browse files Browse the repository at this point in the history
  • Loading branch information
selankon committed Oct 30, 2024
1 parent 3ddf980 commit 41c2947
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 104 deletions.
49 changes: 30 additions & 19 deletions plugins/lime-plugin-mesh-wide-config/src/components/FormEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Trans, t } from "@lingui/macro";
import { StateUpdater, useEffect, useState } from "preact/hooks";
import { useEffect, useState } from "preact/hooks";
import { Controller, useFormContext } from "react-hook-form";
import { v4 as uuidv4 } from "uuid";

Expand All @@ -18,37 +18,46 @@ import { IMeshWideConfig } from "plugins/lime-plugin-mesh-wide-config/src/meshCo
export const EditableField = ({
isList,
name,
setIsEditing,
}: {
isList: boolean;
name: string;
setIsEditing?: StateUpdater<boolean>;
}) => {
const { control, setValue, watch, getValues } = useFormContext();

const value = watch(name);
const [initialState] = useState(value);
// Hack to force re-render when the list changes
const [uniqueKeys, setUniqueKeys] = useState(
isList ? value.map(() => uuidv4()) : ""
isList && value?.length ? value.map(() => uuidv4()) : []
);

const syncKeysWithValues = () => {
// Ensure uniqueKeys matches the length of value array
setUniqueKeys((keys) => [
...keys,
...Array(value.length - keys.length)
.fill(null)
.map(() => uuidv4()),
]);
};

const removeListItem = (index) => {
const updatedValues = value.filter((_, i) => i !== index);
setValue(name, updatedValues); // Update form values
setUniqueKeys((keys) => keys.filter((_, i) => i !== index)); // Update keys to match the new array
setValue(name, updatedValues);
setUniqueKeys((keys) => keys.filter((_, i) => i !== index));
};

const addListItem = () => {
setValue(name, [...value, ""]); // Update form values
setUniqueKeys((keys) => [...keys, uuidv4()]); // Add a new unique key
setValue(name, [...value, ""]);
setUniqueKeys((keys) => [...keys, uuidv4()]);
};

// Ensure the list has at least one item at the start
useEffect(() => {
if (isList && value.length === 0) {
setValue(name, [""]);
setUniqueKeys([uuidv4()]); // Reset keys for new list
} else {
syncKeysWithValues(); // Sync keys with values length on every render
}
}, [isList, value, name, setValue]);

Expand All @@ -67,10 +76,7 @@ export const EditableField = ({
},
required: t`This field cannot be empty`,
}}
render={({
field: { value, ...rest },
fieldState: { error },
}) => {
render={({ field, fieldState: { error } }) => {
return (
<div
className={
Expand All @@ -80,9 +86,8 @@ export const EditableField = ({
<InputField
id={`${name}[${index}]`}
className="w-100"
value={value}
error={error?.message}
{...rest}
{...field}
/>
<EditOrDelete
onDelete={() => removeListItem(index)}
Expand Down Expand Up @@ -126,10 +131,11 @@ export const AddNewConfigSection = ({
}: {
sectionName?: string;
}) => {
const { watch, setValue } = useFormContext<IMeshWideConfig>();

const { open, onOpen, onClose } = useDisclosure();
const { showToast } = useToast();

const { watch, setValue } = useFormContext<IMeshWideConfig>();
const section = watch(sectionName);

const onSuccess = (data: AddNewSectionFormProps) => {
Expand Down Expand Up @@ -166,8 +172,13 @@ export const AddNewConfigSection = ({

export const AddElementButton = (props: ButtonProps) => {
return (
<Button color={"info"} {...props}>
<Trans>Add new section</Trans>
</Button>
<div className="flex justify-center">
<Button
{...props}
className="flex items-center justify-center w-12 h-12 rounded-full border-2 border-gray-400 text-gray-400 hover:bg-gray-100 font-bold cursor-pointer"
>
+
</Button>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,8 @@ export const OptionContainer = ({
{!isEditing && <div>{_value}</div>}
{isEditing && (
<FormProvider {...fmethods}>
<form>
<EditableField
isList={isList}
name={name}
setIsEditing={setIsEditing}
/>
<form className={"flex flex-col gap-4"}>
<EditableField isList={isList} name={name} />
<div className={"flex flex-row gap-4"}>
<Button
onClick={(e) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@ import { Collapsible } from "components/collapsible";
import { useToast } from "components/toast/toastProvider";

import { EditOrDelete } from "plugins/lime-plugin-mesh-wide-config/src/components/Components";
import {
AddElementButton,
AddNewConfigSection,
} from "plugins/lime-plugin-mesh-wide-config/src/components/FormEdit";
import { AddNewConfigSection } from "plugins/lime-plugin-mesh-wide-config/src/components/FormEdit";
import { OptionContainer } from "plugins/lime-plugin-mesh-wide-config/src/components/FormOption";
import {
AddNewSectionFormProps,
AddNewSectionModal,
DeletePropModal,
EditPropModal,
} from "plugins/lime-plugin-mesh-wide-config/src/components/modals";
Expand Down Expand Up @@ -45,35 +40,19 @@ export const FormSection = ({
};

export const SectionEditOrDelete = ({ name }) => {
const {
open: isEditOpen,
onOpen: openEdit,
onClose: onCloseEdit,
} = useDisclosure();
const {
open: isDeleteModalOpen,
onOpen: openDeleteModal,
onClose: onCloseDeleteModal,
} = useDisclosure();
const { showToast } = useToast();

const onEdit = async () => {
console.log("edit stuff");
onCloseEdit();
showToast({
text: (
<Trans>
Edited {name} - {new Date().toDateString()}
</Trans>
),
onAction: () => {
console.log("Undo action");
},
});
};
const { watch, setValue, reset } = useFormContext();

const onDelete = async () => {
console.log("delete stuff");
const form = watch();
const newForm = { ...form };
delete newForm[name];
reset(newForm);
onCloseDeleteModal();
showToast({
text: (
Expand All @@ -82,20 +61,14 @@ export const SectionEditOrDelete = ({ name }) => {
</Trans>
),
onAction: () => {
console.log("Undo action");
reset(form);
},
});
};

return (
<>
<EditOrDelete onEdit={openEdit} onDelete={openDeleteModal} />
<EditPropModal
prop={name}
isOpen={isEditOpen}
onSuccess={onEdit}
onClose={onCloseEdit}
/>
<EditOrDelete onDelete={openDeleteModal} />
<DeletePropModal
prop={name}
isOpen={isDeleteModalOpen}
Expand Down
96 changes: 54 additions & 42 deletions plugins/lime-plugin-mesh-wide-config/src/components/modals.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Trans, t } from "@lingui/macro";
import { Label } from "@tanstack/react-query-devtools/build/lib/Explorer";
import { FormProvider, useForm } from "react-hook-form";
import { Controller, FormProvider, useForm } from "react-hook-form";

import { Modal, ModalProps } from "components/Modal/Modal";
import InputField from "components/inputs/InputField";
Expand All @@ -12,7 +12,7 @@ export const DeletePropModal = ({
prop,
...rest
}: { prop: string } & Pick<ModalProps, "onDelete" | "isOpen" | "onClose">) => (
<Modal title={<Trans>Delete property</Trans>} {...rest}>
<Modal title={<Trans>Delete property</Trans>} cancelBtn {...rest}>
<div>
<Trans>
Are you sure you want to delete the <strong>{prop}</strong>{" "}
Expand Down Expand Up @@ -57,7 +57,7 @@ export const AddNewSectionModal = ({
sectionName?: string;
} & Pick<ModalProps, "isOpen" | "onClose">) => {
const fmethods = useForm<AddNewSectionFormProps>({
defaultValues: { name: "", value: "", values: [""], isList: false },
defaultValues: { name: "", value: "", values: [], isList: false },
});

const handleSuccess = (data: AddNewSectionFormProps) => {
Expand All @@ -71,6 +71,7 @@ export const AddNewSectionModal = ({
formState: { errors },
watch,
reset,
control,
} = fmethods;

let title = <Trans>Add new section</Trans>;
Expand All @@ -81,45 +82,56 @@ export const AddNewSectionModal = ({
const isList = watch("isList");

return (
<Modal
title={title}
successBtnText={<Trans>Add</Trans>}
{...rest}
onSuccess={handleSubmit(handleSuccess)}
>
<FormProvider {...fmethods}>
<InputField
id={"name"}
label={<Trans>Name</Trans>}
{...register("name", {
required: t`This field cannot be empty`,
minLength: {
value: 1,
message: t`Minimum length is 1`,
},
})}
error={errors.name?.message}
/>
{sectionName && (
<>
<div className={switchStyle.toggles}>
<input
type="checkbox"
id="enabled"
{...register("isList")}
<FormProvider {...fmethods}>
<form>
<Modal
title={title}
successBtnText={<Trans>Add</Trans>}
cancelBtn
{...rest}
onSuccess={handleSubmit(handleSuccess)}
>
<Controller
name={"name"}
control={control}
rules={{
minLength: {
value: 1,
message: t`Minimum length is 1`,
},
required: t`This field cannot be empty`,
}}
render={({ field, fieldState: { error } }) => (
<InputField
id={"name"}
label={<Trans>Value</Trans>}
className="w-100"
error={error?.message}
{...field}
/>
<label htmlFor="enabled">
<Trans>Is a list</Trans>
</label>
</div>
<Label>Value</Label>
<EditableField
name={isList ? "values" : "value"}
isList={isList}
/>
</>
)}
</FormProvider>
</Modal>
)}
/>
{sectionName && (
<>
<div className={switchStyle.toggles}>
<input
type="checkbox"
id="enabled"
{...register("isList")}
/>
<label htmlFor="enabled">
<Trans>Is a list</Trans>
</label>
</div>
<Label>Value</Label>
<EditableField
name={isList ? "values" : "value"}
isList={isList}
/>
</>
)}
</Modal>
</form>
</FormProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const EditConfigForm = ({

const formData = fMethods.watch();

console.log("formData", formData);

const onSubmit = (data) => {
console.log("Form Data:", data);
};
Expand Down
2 changes: 0 additions & 2 deletions src/components/inputs/InputField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const InputField = <TFieldValues extends FieldValues>({
id,
label,
error,
value,
...inputProps
}: {
id: Path<TFieldValues>;
Expand All @@ -25,7 +24,6 @@ const InputField = <TFieldValues extends FieldValues>({
id={id}
data-testid="password-input"
className="w-100"
value={value}
{...inputProps}
/>
{error && <p class="text-red-500 text-md mt-1">{error}</p>}
Expand Down

0 comments on commit 41c2947

Please sign in to comment.