From 06e6a1c3c13a0692fe35c141a7d352b5db4eab8f Mon Sep 17 00:00:00 2001 From: poomthiti Date: Wed, 18 Jan 2023 16:38:27 +0700 Subject: [PATCH 1/3] feat: validate label field in instantiate page --- CHANGELOG.md | 1 + src/lib/components/forms/ControllerInput.tsx | 3 +- src/lib/pages/instantiate/instantiate.tsx | 31 +++++++++++++++----- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ffd59ff..eb51488e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#99](https://github.com/alleslabs/celatone-frontend/pull/89) Validate label field in instantiate page - [#89](https://github.com/alleslabs/celatone-frontend/pull/89) Update feedback link - [#90](https://github.com/alleslabs/celatone-frontend/pull/90) Add update admin (`/admin`) and migrate (`/migrate`) page routes - [#91](https://github.com/alleslabs/celatone-frontend/pull/91) Add migrate shortcut to the sidebar diff --git a/src/lib/components/forms/ControllerInput.tsx b/src/lib/components/forms/ControllerInput.tsx index 05435fce5..b29b07a42 100644 --- a/src/lib/components/forms/ControllerInput.tsx +++ b/src/lib/components/forms/ControllerInput.tsx @@ -54,6 +54,7 @@ export const ControllerInput = ({ }); const isError = !!error; + const isRequired = "required" in rules; return ( ({ className={field.value.length ? "floating" : ""} bgColor={labelBgColor} > - {label} + {label} {isRequired && *} )} { "select-existing" ); const [codeId, setCodeId] = useState(""); - const [error, setError] = useState(""); + const [simulateError, setSimulateError] = useState(""); const [simulating, setSimulating] = useState(false); // ------------------------------------------// // ----------------FORM HOOKS----------------// // ------------------------------------------// - const { control, setValue, watch, handleSubmit, reset } = useForm({ + const { + control, + formState: { errors: formErrors }, + setValue, + watch, + handleSubmit, + reset, + } = useForm({ + mode: "onBlur", defaultValues: { label: "", adminAddress: "", @@ -86,8 +94,10 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const selectedAssets = watchAssets.map((asset) => asset.denom); const disableInstantiate = useMemo(() => { - return !codeId || !address || !!jsonValidate(watchInitMsg); - }, [codeId, address, watchInitMsg]); + return ( + !codeId || !address || !!jsonValidate(watchInitMsg) || !!formErrors.label + ); + }, [codeId, address, watchInitMsg, formErrors.label]); const assetOptions = useMemo( () => @@ -134,7 +144,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { if (stream) broadcast(stream); setSimulating(false); } catch (e) { - setError((e as Error).message); + setSimulateError((e as Error).message); setSimulating(false); } })(); @@ -221,14 +231,16 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { setInputState={setCodeId} /> )} -
+ { disabled={disableInstantiate} loading={simulating} /> - {error && setError("")} />} + {simulateError && ( + setSimulateError("")} + /> + )} ); }; From 5ae04fb2a3ee0ce9335e52c3ae50d7345e70dc29 Mon Sep 17 00:00:00 2001 From: poomthiti Date: Thu, 19 Jan 2023 11:36:23 +0700 Subject: [PATCH 2/3] feat: add validation to codeId field --- src/lib/pages/instantiate/instantiate.tsx | 69 +++++++++++++---------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/lib/pages/instantiate/instantiate.tsx b/src/lib/pages/instantiate/instantiate.tsx index 2feda7249..0d3975eb9 100644 --- a/src/lib/pages/instantiate/instantiate.tsx +++ b/src/lib/pages/instantiate/instantiate.tsx @@ -19,7 +19,7 @@ import { useSimulateFee, } from "lib/app-provider"; import { useInstantiateTx } from "lib/app-provider/tx/instantiate"; -import { ControllerInput, TextInput } from "lib/components/forms"; +import { ControllerInput } from "lib/components/forms"; import { AssetInput } from "lib/components/forms/AssetInput"; import JsonInput from "lib/components/json/JsonInput"; import { Stepper } from "lib/components/stepper"; @@ -62,7 +62,6 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const [method, setMethod] = useState<"select-existing" | "fill-manually">( "select-existing" ); - const [codeId, setCodeId] = useState(""); const [simulateError, setSimulateError] = useState(""); const [simulating, setSimulating] = useState(false); @@ -77,8 +76,9 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { handleSubmit, reset, } = useForm({ - mode: "onBlur", + mode: "all", defaultValues: { + codeId: "", label: "", adminAddress: "", initMsg: "", @@ -89,15 +89,22 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { control, name: "assets", }); - const watchAssets = watch("assets"); - const watchInitMsg = watch("initMsg"); + const [watchAssets, watchInitMsg, watchCodeId] = watch([ + "assets", + "initMsg", + "codeId", + ]); + const selectedAssets = watchAssets.map((asset) => asset.denom); const disableInstantiate = useMemo(() => { return ( - !codeId || !address || !!jsonValidate(watchInitMsg) || !!formErrors.label + !watchCodeId || + !address || + !!jsonValidate(watchInitMsg) || + !!formErrors.label ); - }, [codeId, address, watchInitMsg, formErrors.label]); + }, [watchCodeId, address, watchInitMsg, formErrors.label]); const assetOptions = useMemo( () => @@ -124,7 +131,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const msg = composeMsg(MsgType.INSTANTIATE, { sender: address as HumanAddr, admin: adminAddress as HumanAddr, - codeId: Long.fromString(codeId), + codeId: Long.fromString(watchCodeId), label, msg: Buffer.from(initMsg), funds, @@ -133,7 +140,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const estimatedFee = await simulate([msg]); const stream = await postInstantiateTx({ estimatedFee: estimatedFee ? fabricateFee(estimatedFee) : undefined, - codeId: Number(codeId), + codeId: Number(watchCodeId), initMsg: JSON.parse(initMsg), label, admin: adminAddress, @@ -150,7 +157,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { })(); }, [ address, - codeId, + watchCodeId, handleSubmit, fabricateFee, postInstantiateTx, @@ -163,13 +170,13 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { // --------------SIDE EFFECTS----------------// // ------------------------------------------// useEffect(() => { - if (codeIdQuery) setCodeId(codeIdQuery); + if (codeIdQuery) setValue("codeId", codeIdQuery); if (msgQuery) { const decodedMsg = decode(msgQuery); try { const msgObject = JSON.parse(decodedMsg) as InstantiateRedoMsg; - setCodeId(String(msgObject.code_id)); + setValue("codeId", String(msgObject.code_id)); reset({ label: msgObject.label, adminAddress: msgObject.admin, @@ -186,7 +193,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { // comment just to avoid eslint no-empty } } - }, [codeIdQuery, msgQuery, reset]); + }, [codeIdQuery, msgQuery, reset, setValue]); return ( <> @@ -214,24 +221,26 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { - {method === "select-existing" ? ( - setCodeId(code)} - codeId={codeId} - /> - ) : ( - - )} + {method === "select-existing" ? ( + setValue("codeId", code)} + codeId={watchCodeId} + /> + ) : ( + + )} Date: Thu, 19 Jan 2023 12:14:03 +0700 Subject: [PATCH 3/3] fix: as commented --- CHANGELOG.md | 2 +- src/lib/components/forms/ControllerInput.tsx | 10 ++++-- src/lib/pages/instantiate/instantiate.tsx | 35 ++++++++++---------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f2e8c31c..8e1e83538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features -- [#99](https://github.com/alleslabs/celatone-frontend/pull/89) Validate label field in instantiate page +- [#99](https://github.com/alleslabs/celatone-frontend/pull/99) Validate label and codeId field in instantiate page - [#97](https://github.com/alleslabs/celatone-frontend/pull/97) Change label style to always afloat - [#96](https://github.com/alleslabs/celatone-frontend/pull/96) Fix incorrect instantiated block height explorer link - [#95](https://github.com/alleslabs/celatone-frontend/pull/95) Add network to url path diff --git a/src/lib/components/forms/ControllerInput.tsx b/src/lib/components/forms/ControllerInput.tsx index 7cb7a669f..20727577b 100644 --- a/src/lib/components/forms/ControllerInput.tsx +++ b/src/lib/components/forms/ControllerInput.tsx @@ -56,10 +56,16 @@ export const ControllerInput = ({ const isError = !!error; const isRequired = "required" in rules; return ( - + {label && ( - {label} {isRequired && *} + {label} )} { const [method, setMethod] = useState<"select-existing" | "fill-manually">( "select-existing" ); - const [simulateError, setSimulateError] = useState(""); const [simulating, setSimulating] = useState(false); // ------------------------------------------// @@ -83,28 +82,27 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { adminAddress: "", initMsg: "", assets: [{ denom: "", amount: "" }], + simulateError: "", }, }); const { fields, append, remove } = useFieldArray({ control, name: "assets", }); - const [watchAssets, watchInitMsg, watchCodeId] = watch([ - "assets", - "initMsg", - "codeId", - ]); + const { + codeId, + assets: watchAssets, + initMsg: watchInitMsg, + simulateError, + } = watch(); const selectedAssets = watchAssets.map((asset) => asset.denom); const disableInstantiate = useMemo(() => { return ( - !watchCodeId || - !address || - !!jsonValidate(watchInitMsg) || - !!formErrors.label + !codeId || !address || !!jsonValidate(watchInitMsg) || !!formErrors.label ); - }, [watchCodeId, address, watchInitMsg, formErrors.label]); + }, [codeId, address, watchInitMsg, formErrors.label]); const assetOptions = useMemo( () => @@ -131,7 +129,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const msg = composeMsg(MsgType.INSTANTIATE, { sender: address as HumanAddr, admin: adminAddress as HumanAddr, - codeId: Long.fromString(watchCodeId), + codeId: Long.fromString(codeId), label, msg: Buffer.from(initMsg), funds, @@ -140,7 +138,7 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { const estimatedFee = await simulate([msg]); const stream = await postInstantiateTx({ estimatedFee: estimatedFee ? fabricateFee(estimatedFee) : undefined, - codeId: Number(watchCodeId), + codeId: Number(codeId), initMsg: JSON.parse(initMsg), label, admin: adminAddress, @@ -151,19 +149,20 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { if (stream) broadcast(stream); setSimulating(false); } catch (e) { - setSimulateError((e as Error).message); + setValue("simulateError", (e as Error).message); setSimulating(false); } })(); }, [ address, - watchCodeId, + codeId, handleSubmit, fabricateFee, postInstantiateTx, simulate, broadcast, onComplete, + setValue, ]); // ------------------------------------------// @@ -227,13 +226,13 @@ const Instantiate = ({ onComplete }: InstantiatePageProps) => { mt="16px" mb="32px" onCodeSelect={(code: string) => setValue("codeId", code)} - codeId={watchCodeId} + codeId={codeId} /> ) : ( { {simulateError && ( setSimulateError("")} + onClose={() => setValue("simulateError", "")} /> )}