From 592dacad39fa0b7146b33353aeca0c24606ac959 Mon Sep 17 00:00:00 2001 From: Ola Hungerford Date: Wed, 26 Feb 2025 09:50:47 -0700 Subject: [PATCH] Start adding changes to address json fields --- client/src/components/DynamicJsonForm.tsx | 54 +++++++++++++++++++---- client/src/components/JsonEditor.tsx | 42 +++++++++++++++--- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/client/src/components/DynamicJsonForm.tsx b/client/src/components/DynamicJsonForm.tsx index a15b57e..709b0d4 100644 --- a/client/src/components/DynamicJsonForm.tsx +++ b/client/src/components/DynamicJsonForm.tsx @@ -41,9 +41,6 @@ const DynamicJsonForm = ({ onChange, maxDepth = 3, }: DynamicJsonFormProps) => { - const [isJsonMode, setIsJsonMode] = useState(false); - const [jsonError, setJsonError] = useState(); - const generateDefaultValue = (propSchema: JsonSchemaType): JsonValue => { switch (propSchema.type) { case "string": @@ -69,6 +66,40 @@ const DynamicJsonForm = ({ } }; + const [isJsonMode, setIsJsonMode] = useState(false); + const [jsonError, setJsonError] = useState(); + // Add state for storing raw JSON value + const [rawJsonValue, setRawJsonValue] = useState( + JSON.stringify(value ?? generateDefaultValue(schema), null, 2) + ); + + const validateJsonBeforeSubmit = () => { + if (isJsonMode && rawJsonValue) { + try { + const parsed = JSON.parse(rawJsonValue); + onChange(parsed); + setJsonError(undefined); + return true; + } catch (err) { + setJsonError(err instanceof Error ? err.message : "Invalid JSON"); + return false; + } + } + return true; + }; + + const handleSwitchToFormMode = () => { + if (isJsonMode) { + if (validateJsonBeforeSubmit()) { + setIsJsonMode(false); + } + } else { + // Update raw JSON value when switching to JSON mode + setRawJsonValue(JSON.stringify(value ?? generateDefaultValue(schema), null, 2)); + setIsJsonMode(true); + } + }; + const renderFormFields = ( propSchema: JsonSchemaType, currentValue: JsonValue, @@ -329,7 +360,7 @@ const DynamicJsonForm = ({ @@ -337,13 +368,18 @@ const DynamicJsonForm = ({ {isJsonMode ? ( { + setRawJsonValue(newValue); try { - onChange(JSON.parse(newValue)); - setJsonError(undefined); - } catch (err) { - setJsonError(err instanceof Error ? err.message : "Invalid JSON"); + if (/^\s*[{[].*[}\]]\s*$/.test(newValue)) { + const parsed = JSON.parse(newValue); + onChange(parsed); + setJsonError(undefined); + } + } catch { + // Don't set an error during typing - that will happen when the user + // tries to save or submit the form } }} error={jsonError} diff --git a/client/src/components/JsonEditor.tsx b/client/src/components/JsonEditor.tsx index 2fb7e26..9109088 100644 --- a/client/src/components/JsonEditor.tsx +++ b/client/src/components/JsonEditor.tsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from "react"; import Editor from "react-simple-code-editor"; import Prism from "prismjs"; import "prismjs/components/prism-json"; @@ -10,34 +11,63 @@ interface JsonEditorProps { error?: string; } -const JsonEditor = ({ value, onChange, error }: JsonEditorProps) => { +const JsonEditor = ({ value, onChange, error: externalError }: JsonEditorProps) => { + const [editorContent, setEditorContent] = useState(value); + const [internalError, setInternalError] = useState(undefined); + + useEffect(() => { + setEditorContent(value); + }, [value]); + const formatJson = (json: string): string => { try { + // Handle empty arrays and objects specifically + if (json.trim() === '[]') return '[]'; + if (json.trim() === '{}') return '{}'; return JSON.stringify(JSON.parse(json), null, 2); } catch { return json; } }; + const handleEditorChange = (newContent: string) => { + setEditorContent(newContent); + setInternalError(undefined); + onChange(newContent); + }; + + const handleFormatJson = () => { + try { + const formatted = formatJson(editorContent); + setEditorContent(formatted); + onChange(formatted); + setInternalError(undefined); + } catch (err) { + setInternalError(err instanceof Error ? err.message : "Invalid JSON"); + } + }; + + const displayError = internalError || externalError; + return (
Prism.highlight(code, Prism.languages.json, "json") } @@ -51,7 +81,7 @@ const JsonEditor = ({ value, onChange, error }: JsonEditorProps) => { className="w-full" />
- {error &&

{error}

} + {displayError &&

{displayError}

}
); };