diff --git a/CHANGELOG.md b/CHANGELOG.md index afdc103..9099adf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to the Neo N3 Visual DevTracker extension will be documented Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. +## Unreleased + +### Changed + +- The invoke file editor now supports editing invocation files that use arrays or objects as contract parameters + ## [2.1.49] - 2021-06-21 ### Changed diff --git a/src/panel/components/contracts/ArgumentInput.tsx b/src/panel/components/contracts/ArgumentInput.tsx index ba54905..a96b7c0 100644 --- a/src/panel/components/contracts/ArgumentInput.tsx +++ b/src/panel/components/contracts/ArgumentInput.tsx @@ -4,12 +4,36 @@ import InputNonDraggable from "../InputNonDraggable"; import NeoType from "./NeoType"; type Props = { - arg?: string | number; + arg?: any; autoSuggestListId: string; isReadOnly: boolean; name: string; type?: string | number; - onUpdate: (newArgument: string | number) => void; + onUpdate: (newArgument: any) => void; +}; + +const valueToString = (value: any) => { + if (!value) { + return ""; + } else if (Array.isArray(value) || typeof value === "object") { + return JSON.stringify(value); + } else { + return `${value}`; + } +}; + +const stringToValue = (text: string) => { + if (`${parseInt(text)}` === text) { + return parseInt(text); + } else if (`${parseFloat(text)}` === text) { + return parseFloat(text); + } else { + try { + return JSON.parse(text); + } catch (e) { + return `${text}`; + } + } }; export default function ArgumentInput({ @@ -20,7 +44,7 @@ export default function ArgumentInput({ type, onUpdate, }: Props) { - const [value, setValue] = useState(`${arg || ""}`); + const [value, setValue] = useState(valueToString(arg)); const inputStyle: React.CSSProperties = { color: "var(--vscode-input-foreground)", backgroundColor: "var(--vscode-input-background)", @@ -31,15 +55,6 @@ export default function ArgumentInput({ padding: 1, marginLeft: 15, }; - const coerceType = (text: string) => { - if (`${parseInt(text)}` === text) { - return parseInt(text); - } else if (`${parseFloat(text)}` === text) { - return parseFloat(text); - } else { - return `${text}`; - } - }; return (
@@ -57,12 +72,12 @@ export default function ArgumentInput({ style={inputStyle} type="text" value={value} - onBlur={(e) => onUpdate(coerceType(e.target.value))} - onChange={(e) => setValue(e.target.value)} + onBlur={(e) => onUpdate(stringToValue(e.target.value))} + onChange={(e) => setValue(valueToString(e.target.value))} onKeyDown={(e) => { if (e.metaKey) { // User may be about to save - onUpdate(coerceType(value)); + onUpdate(stringToValue(value)); } }} /> diff --git a/src/panel/components/contracts/ArgumentsInput.tsx b/src/panel/components/contracts/ArgumentsInput.tsx index 86719b4..c912011 100644 --- a/src/panel/components/contracts/ArgumentsInput.tsx +++ b/src/panel/components/contracts/ArgumentsInput.tsx @@ -5,12 +5,12 @@ import * as neonSc from "@cityofzion/neon-core/lib/sc"; import ArgumentInput from "./ArgumentInput"; type Props = { - args: (string | number)[]; + args: any[]; autoSuggestListId: string; isReadOnly: boolean; parameterDefinitions?: neonSc.ContractParameterDefinitionJson[]; style?: React.CSSProperties; - setArguments: (newArguments: (string | number)[]) => void; + setArguments: (newArguments: any[]) => void; }; export default function ArgumentsInput({ @@ -42,7 +42,7 @@ export default function ArgumentsInput({ key={`${i}_${_}`} name={(parameterDefinitions || [])[i]?.name || `Argument #${i + 1}`} type={(parameterDefinitions || [])[i]?.type} - onUpdate={(arg: string | number) => + onUpdate={(arg) => setArguments( args .map((__, j) => (i === j ? arg : __)) @@ -59,9 +59,7 @@ export default function ArgumentsInput({ isReadOnly={isReadOnly} key={args.length} name={`Argument #${args.length + 1}`} - onUpdate={(arg: string | number) => - setArguments(arg ? [...args, arg] : [...args]) - } + onUpdate={(arg) => setArguments(arg ? [...args, arg] : [...args])} /> )}
diff --git a/src/panel/components/contracts/InvocationStep.tsx b/src/panel/components/contracts/InvocationStep.tsx index 56fdeb4..67b8976 100644 --- a/src/panel/components/contracts/InvocationStep.tsx +++ b/src/panel/components/contracts/InvocationStep.tsx @@ -12,7 +12,7 @@ type Props = { i: number; contract?: string; operation?: string; - args?: (string | number)[]; + args?: any[]; autoCompleteData: AutoCompleteData; argumentSuggestionListId: string; forceFocus?: boolean; @@ -23,11 +23,7 @@ type Props = { onDragStart: () => void; onDragEnd: () => void; onRun: () => void; - onUpdate: ( - contract?: string, - operation?: string, - args?: (string | number)[] - ) => void; + onUpdate: (contract?: string, operation?: string, args?: any[]) => void; }; export default function InvocationStep({ @@ -124,7 +120,7 @@ export default function InvocationStep({ operations.find((_) => _.name === operation)?.parameters } style={{ marginBottom: 10 }} - setArguments={(newArguments: (string | number)[]) => + setArguments={(newArguments) => onUpdate(contract, operation, newArguments) } /> diff --git a/src/shared/messages/invokeFileViewRequest.ts b/src/shared/messages/invokeFileViewRequest.ts index f0a919c..4ec31e0 100644 --- a/src/shared/messages/invokeFileViewRequest.ts +++ b/src/shared/messages/invokeFileViewRequest.ts @@ -13,7 +13,7 @@ type InvokeFileViewRequest = { i: number; contract?: string; operation?: string; - args?: (string | number)[]; + args?: any[]; }; updateJson?: string; }; diff --git a/src/shared/viewState/invokeFileViewState.ts b/src/shared/viewState/invokeFileViewState.ts index 1e2d633..17802f5 100644 --- a/src/shared/viewState/invokeFileViewState.ts +++ b/src/shared/viewState/invokeFileViewState.ts @@ -11,7 +11,7 @@ type InvokeFileViewState = { fileContents: { contract?: string; operation?: string; - args?: (string | number)[]; + args?: any[]; }[]; fileContentsJson: string; isPartOfDiffView: boolean;