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;