From 8981385becdcac013393339ec03a9ac02af80e95 Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:20:27 +0530 Subject: [PATCH 01/10] feat(frontend): created `reportErrorsAndSubmit` util function --- services/frontend/src/utils/forms.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/services/frontend/src/utils/forms.ts b/services/frontend/src/utils/forms.ts index ccff7ff..af22bf6 100644 --- a/services/frontend/src/utils/forms.ts +++ b/services/frontend/src/utils/forms.ts @@ -1,5 +1,5 @@ import lodash from "lodash"; -import { number } from "yup"; +import { toaster } from "."; export const checkArray = (array: any, name: string): T => { if (!Array.isArray(array)) { @@ -195,3 +195,22 @@ export const packArrayAsStrings = ( ) ); }; + +/** + * Formik is configured to validate fields automatically using Yup. + * The problem is Formik does not call `onSubmit` function when errors + * are present. Therefore, a work around was to call `formik.submitForm` + * after showing errors to the user. The `reportErrorsAndSubmit` utility + * function basically implements this. + */ +export const reportErrorsAndSubmit = (formik: any) => () => { + const errors = Object.entries(formik.errors); + if (errors.length > 0) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_field, message] of errors) { + toaster(message as string, "error"); + } + } else { + formik.submitForm(); + } +}; From 3bdf4d3631f5134a82acf34df786b1ebb37d0fe2 Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:20:45 +0530 Subject: [PATCH 02/10] feat(frontend): updated to show toasts in create service modal --- services/frontend/src/components/Modal/service/Create.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/frontend/src/components/Modal/service/Create.tsx b/services/frontend/src/components/Modal/service/Create.tsx index 688055d..f91a4f1 100644 --- a/services/frontend/src/components/Modal/service/Create.tsx +++ b/services/frontend/src/components/Modal/service/Create.tsx @@ -15,6 +15,8 @@ import { styled } from "@mui/joy"; import Environment from "./Environment"; import Deploy from "./Deploy"; import { classNames } from "../../../utils/styles"; +import { toaster } from "../../../utils"; +import { reportErrorsAndSubmit } from "../../../utils/forms"; interface IModalServiceProps { onHide: CallbackFunction; @@ -60,6 +62,10 @@ const ModalServiceCreate = (props: IModalServiceProps) => { onAddEndpoint(result); formik.resetForm(); onHide(); + toaster( + `Created "${values.serviceName}" service successfully`, + "success" + ); }, [onAddEndpoint, onHide] ); @@ -137,7 +143,7 @@ const ModalServiceCreate = (props: IModalServiceProps) => { From b269fb7e99ca1978061796b91123ae5bba11f5dc Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:21:34 +0530 Subject: [PATCH 03/10] feat(frontend): updated to show toasts in edit service modal --- services/frontend/src/components/Modal/service/Edit.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/frontend/src/components/Modal/service/Edit.tsx b/services/frontend/src/components/Modal/service/Edit.tsx index b42c10a..31d8f12 100644 --- a/services/frontend/src/components/Modal/service/Edit.tsx +++ b/services/frontend/src/components/Modal/service/Edit.tsx @@ -15,6 +15,8 @@ import Environment from "./Environment"; import Build from "./Build"; import Deploy from "./Deploy"; import { classNames } from "../../../utils/styles"; +import { toaster } from "../../../utils"; +import { reportErrorsAndSubmit } from "../../../utils/forms"; export interface IModalServiceProps { node: IServiceNodeItem; @@ -29,6 +31,7 @@ const ModalServiceEdit = (props: IModalServiceProps) => { const handleUpdate = (values: any) => { onUpdateEndpoint(getFinalValues(values, selectedNode)); + toaster(`Updated "${values.serviceName}" service successfully`, "success"); }; const initialValues = useMemo( @@ -112,9 +115,7 @@ const ModalServiceEdit = (props: IModalServiceProps) => { From bb9baa6bb02b352317bafe414dc77380f58fc512 Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:25:51 +0530 Subject: [PATCH 04/10] feat(frontend): updated to show success toasts for create/edit network modals --- .../frontend/src/components/Modal/network/index.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/services/frontend/src/components/Modal/network/index.tsx b/services/frontend/src/components/Modal/network/index.tsx index 4832e3c..1340842 100644 --- a/services/frontend/src/components/Modal/network/index.tsx +++ b/services/frontend/src/components/Modal/network/index.tsx @@ -1,9 +1,9 @@ import { useCallback, useState } from "react"; import { XIcon } from "@heroicons/react/outline"; import CreateNetworkModal from "./CreateNetworkModal"; -import { CallbackFunction } from "../../../types"; +import { CallbackFunction, IEditNetworkForm } from "../../../types"; import EditNetworkModal from "./EditNetworkModal"; -import { attachUUID } from "../../../utils"; +import { attachUUID, toaster } from "../../../utils"; import { getFinalValues } from "./form-utils"; import EmptyNetworks from "./EmptyNetworks"; import NetworkList from "./NetworkList"; @@ -37,7 +37,8 @@ const ModalNetwork = (props: IModalNetworkProps) => { } = props; const [selectedNetwork, setSelectedNetwork] = useState(); const [showCreate, setShowCreate] = useState(false); - const handleCreate = (values: any) => { + + const handleCreate = (values: IEditNetworkForm) => { const finalValues = getFinalValues(values); const uniqueKey = attachUUID(finalValues.key); const network = { @@ -46,12 +47,16 @@ const ModalNetwork = (props: IModalNetworkProps) => { }; onCreateNetwork(network); setSelectedNetwork(network); + + toaster(`Created "${values.entryName}" network successfully`, "success"); }; - const handleUpdate = (values: any) => { + const handleUpdate = (values: IEditNetworkForm) => { const finalValues = getFinalValues(values, selectedNetwork); onUpdateNetwork(finalValues); setSelectedNetwork(finalValues); + + toaster(`Updated "${values.entryName}" network successfully`, "success"); }; const handleRemove = useCallback( From 1672bb92106243f94f12b0a19ce9b1ce73c4e5b1 Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:26:12 +0530 Subject: [PATCH 05/10] feat(frontend): updated to show error toasts for create network modal --- .../src/components/Modal/network/CreateNetworkModal.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/frontend/src/components/Modal/network/CreateNetworkModal.tsx b/services/frontend/src/components/Modal/network/CreateNetworkModal.tsx index 4cef26e..8ccc155 100644 --- a/services/frontend/src/components/Modal/network/CreateNetworkModal.tsx +++ b/services/frontend/src/components/Modal/network/CreateNetworkModal.tsx @@ -6,6 +6,7 @@ import { CallbackFunction } from "../../../types"; import { getInitialValues, tabs, validationSchema } from "./form-utils"; import { classNames } from "../../../utils/styles"; import { Button, styled } from "@mui/joy"; +import { reportErrorsAndSubmit } from "../../../utils/forms"; interface ICreateNetworkModalProps { onCreateNetwork: CallbackFunction; @@ -69,7 +70,11 @@ const CreateNetworkModal: FunctionComponent = ( - From 59dffcdd226f7ac5efcd97a47d05107f7ab14371 Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:26:21 +0530 Subject: [PATCH 06/10] feat(frontend): updated to show error toasts for edit network modal --- .../src/components/Modal/network/EditNetworkModal.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/frontend/src/components/Modal/network/EditNetworkModal.tsx b/services/frontend/src/components/Modal/network/EditNetworkModal.tsx index aa389a1..2a32490 100644 --- a/services/frontend/src/components/Modal/network/EditNetworkModal.tsx +++ b/services/frontend/src/components/Modal/network/EditNetworkModal.tsx @@ -6,6 +6,7 @@ import { CallbackFunction } from "../../../types"; import { getInitialValues, tabs, validationSchema } from "./form-utils"; import { classNames } from "../../../utils/styles"; import { Button, styled } from "@mui/joy"; +import { reportErrorsAndSubmit } from "../../../utils/forms"; interface IEditNetworkModalProps { onUpdateNetwork: CallbackFunction; @@ -68,7 +69,11 @@ const EditNetworkModal = (props: IEditNetworkModalProps) => { - From df6d694459e68abdab236336740029cff3d9a6dc Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:30:23 +0530 Subject: [PATCH 07/10] feat(frontend): updated to show toasts in create volume modal --- .../src/components/Modal/volume/CreateVolumeModal.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/services/frontend/src/components/Modal/volume/CreateVolumeModal.tsx b/services/frontend/src/components/Modal/volume/CreateVolumeModal.tsx index abdd642..951dcc0 100644 --- a/services/frontend/src/components/Modal/volume/CreateVolumeModal.tsx +++ b/services/frontend/src/components/Modal/volume/CreateVolumeModal.tsx @@ -9,8 +9,10 @@ import { validationSchema } from "./form-utils"; import General from "./General"; -import { CallbackFunction } from "../../../types"; +import { CallbackFunction, IEditVolumeForm } from "../../../types"; import { classNames } from "../../../utils/styles"; +import { toaster } from "../../../utils"; +import { reportErrorsAndSubmit } from "../../../utils/forms"; interface ICreateVolumeModalProps { onHide: CallbackFunction; @@ -21,10 +23,12 @@ const CreateVolumeModal = (props: ICreateVolumeModalProps) => { const { onHide, onAddEndpoint } = props; const [openTab, setOpenTab] = useState("General"); - const handleCreate = useCallback((values: any, formik: any) => { + const handleCreate = useCallback((values: IEditVolumeForm, formik: any) => { onAddEndpoint(getFinalValues(values)); formik.resetForm(); onHide(); + + toaster(`Created "${values.entryName}" volume successfully`, "success"); }, []); const initialValues = useMemo(() => getInitialValues(), []); @@ -94,7 +98,7 @@ const CreateVolumeModal = (props: ICreateVolumeModalProps) => { From 2adeaaddc4b6ae2fe18a4b8ef1b2ef52559c260b Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:30:34 +0530 Subject: [PATCH 08/10] feat(frontend): updated to show toasts in edit volume modal --- .../components/Modal/volume/EditVolumeModal.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/services/frontend/src/components/Modal/volume/EditVolumeModal.tsx b/services/frontend/src/components/Modal/volume/EditVolumeModal.tsx index cc20a9f..215245c 100644 --- a/services/frontend/src/components/Modal/volume/EditVolumeModal.tsx +++ b/services/frontend/src/components/Modal/volume/EditVolumeModal.tsx @@ -2,7 +2,11 @@ import { useEffect, useMemo, useState } from "react"; import { Formik } from "formik"; import { XIcon } from "@heroicons/react/outline"; import General from "./General"; -import type { CallbackFunction, IVolumeNodeItem } from "../../../types"; +import type { + CallbackFunction, + IEditVolumeForm, + IVolumeNodeItem +} from "../../../types"; import { getFinalValues, getInitialValues, @@ -10,6 +14,8 @@ import { validationSchema } from "./form-utils"; import { classNames } from "../../../utils/styles"; +import { toaster } from "../../../utils"; +import { reportErrorsAndSubmit } from "../../../utils/forms"; interface IEditVolumeModal { node: IVolumeNodeItem; @@ -28,8 +34,10 @@ const EditVolumeModal = (props: IEditVolumeModal) => { } }, [node]); - const handleUpdate = (values: any) => { + const handleUpdate = (values: IEditVolumeForm) => { onUpdateEndpoint(getFinalValues(values, selectedNode)); + + toaster(`Updated "${values.entryName}" volume successfully`, "success"); }; const initialValues = useMemo( @@ -103,7 +111,7 @@ const EditVolumeModal = (props: IEditVolumeModal) => { From d62e548c6f9e8957d7b917435b46af5edfa436f1 Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Mon, 1 Aug 2022 16:31:32 +0530 Subject: [PATCH 09/10] feat(frontend): updated to mark fields as required in network modals --- services/frontend/src/components/Modal/network/General.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/frontend/src/components/Modal/network/General.tsx b/services/frontend/src/components/Modal/network/General.tsx index 867a53a..2ce85e3 100644 --- a/services/frontend/src/components/Modal/network/General.tsx +++ b/services/frontend/src/components/Modal/network/General.tsx @@ -11,8 +11,8 @@ const Root = styled("div")` const General = () => { return ( - - + + Date: Mon, 1 Aug 2022 16:32:43 +0530 Subject: [PATCH 10/10] feat(frontend): updated to mark `labels[i].value` as optional in network modals --- services/frontend/src/components/Modal/network/General.tsx | 2 +- services/frontend/src/components/Modal/network/form-utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/frontend/src/components/Modal/network/General.tsx b/services/frontend/src/components/Modal/network/General.tsx index 2ce85e3..df01fb9 100644 --- a/services/frontend/src/components/Modal/network/General.tsx +++ b/services/frontend/src/components/Modal/network/General.tsx @@ -26,7 +26,7 @@ const General = () => { { name: `labels[${index}].value`, placeholder: "Value", - required: true, + required: false, type: "text" } ]} diff --git a/services/frontend/src/components/Modal/network/form-utils.ts b/services/frontend/src/components/Modal/network/form-utils.ts index 7d3619d..8aad568 100644 --- a/services/frontend/src/components/Modal/network/form-utils.ts +++ b/services/frontend/src/components/Modal/network/form-utils.ts @@ -44,7 +44,7 @@ export const validationSchema = yup.object({ labels: yup.array( yup.object({ key: yup.string().required("Key is required"), - value: yup.string().required("Value is required") + value: yup.string() }) ) });