diff --git a/changes/change_tryit_format.md b/changes/change_tryit_format.md new file mode 100644 index 000000000..8fd331655 --- /dev/null +++ b/changes/change_tryit_format.md @@ -0,0 +1 @@ +* Allow _Try It_ for functions on _Definitions_ page to take JSON or Shesmu input diff --git a/shesmu-server-ui/src/definitions.ts b/shesmu-server-ui/src/definitions.ts index 580b7a1ff..ca5ef8c57 100644 --- a/shesmu-server-ui/src/definitions.ts +++ b/shesmu-server-ui/src/definitions.ts @@ -1,4 +1,8 @@ -import { fetchJsonWithBusyDialog, locallyStored } from "./io.js"; +import { + fetchJsonWithBusyDialog, + locallyStored, + locallyStoredString, +} from "./io.js"; import { DisplayElement, IconName, @@ -12,7 +16,7 @@ import { hr, indented, inputSearch, - inputText, + inputTextArea, italic, link, mono, @@ -29,7 +33,7 @@ import { } from "./html.js"; import { parse } from "./parser.js"; import * as valueParser from "./parser.js"; -import { commonPathPrefix, mapModel } from "./util.js"; +import { combineModels, commonPathPrefix, mapModel } from "./util.js"; export type Definition = | ActionDefintion @@ -689,12 +693,33 @@ function testFunction(func: FunctionDefinition): void { const parsers = func.parameters.map( (p) => parseDescriptor(p.type, valueParser)[0] ); - const inputs = func.parameters.map(() => inputText()); + const savedFormat = locallyStoredString("shesmu_try_it_format", "shesmu"); + const inputs = func.parameters.map(() => inputTextArea("", true)); const errors = func.parameters.map(() => pane("blank")); dialog((_close) => [ "Test function ", func.name, br(), + "Argument Format: ", + dropdown( + (format, selected) => { + if (format == "json") { + return [{ type: "icon", icon: "braces" }, "JSON"]; + } else { + return [{ type: "icon", icon: "card-text" }, "Shesmu"]; + } + }, + (format) => format == savedFormat.get(), + combineModels(), + { + synchronizer: savedFormat, + predicate: (recovered, item) => recovered == item, + extract: (x) => x, + }, + "shesmu", + "json" + ), + br(), tableFromRows( func.parameters.map((p, index) => tableRow( @@ -715,21 +740,35 @@ function testFunction(func: FunctionDefinition): void { () => { const args: any[] = []; if ( - parsers.every((parser, index) => - parse( - inputs[index].value, - parser, - (x) => { - args.push(x); + parsers.every((parser, index) => { + if (savedFormat.get() == "json") { + try { + args.push(JSON.parse(inputs[index].value)); errors[index].model.statusChanged(blank()); - }, - (message, position) => + return true; + } catch (e) { errors[index].model.statusChanged({ type: "b", - contents: `${position + 1}: ${message}`, - }) - ) - ) + contents: `${e}`, + }); + return false; + } + } else { + return parse( + inputs[index].value, + parser, + (x) => { + args.push(x); + errors[index].model.statusChanged(blank()); + }, + (message, position) => + errors[index].model.statusChanged({ + type: "b", + contents: `${position + 1}: ${message}`, + }) + ); + } + }) ) { fetchJsonWithBusyDialog( "function", diff --git a/shesmu-server-ui/src/html.ts b/shesmu-server-ui/src/html.ts index 3e52be882..32b26995b 100644 --- a/shesmu-server-ui/src/html.ts +++ b/shesmu-server-ui/src/html.ts @@ -2829,11 +2829,17 @@ export function inputText(initial?: string): InputField { /** * Create a big text input box. */ -export function inputTextArea(initial?: string): InputField { +export function inputTextArea( + initial?: string, + short?: boolean +): InputField { const input = createUiFromTag("textarea"); if (initial) { input.element.value = initial; } + if (!short) { + input.element.classList.add("tall"); + } return { ui: input, get value() { diff --git a/shesmu-server/src/main/resources/ca/on/oicr/gsi/shesmu/main.css b/shesmu-server/src/main/resources/ca/on/oicr/gsi/shesmu/main.css index c9a736cb6..f5ccd2181 100644 --- a/shesmu-server/src/main/resources/ca/on/oicr/gsi/shesmu/main.css +++ b/shesmu-server/src/main/resources/ca/on/oicr/gsi/shesmu/main.css @@ -837,6 +837,8 @@ th { textarea { width: 100%; +} +textarea.tall { height: 50vh; }