Resolve issues where JSON fields are not being rendered in form mode
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@@ -73,25 +73,24 @@ const DynamicJsonForm = ({
|
|||||||
JSON.stringify(value ?? generateDefaultValue(schema), null, 2)
|
JSON.stringify(value ?? generateDefaultValue(schema), null, 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
const validateJsonBeforeSubmit = () => {
|
// Update rawJsonValue when value prop changes
|
||||||
if (isJsonMode && rawJsonValue) {
|
useEffect(() => {
|
||||||
try {
|
if (!isJsonMode) {
|
||||||
const parsed = JSON.parse(rawJsonValue);
|
setRawJsonValue(JSON.stringify(value ?? generateDefaultValue(schema), null, 2));
|
||||||
onChange(parsed);
|
|
||||||
setJsonError(undefined);
|
|
||||||
return true;
|
|
||||||
} catch (err) {
|
|
||||||
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}, [value, schema, isJsonMode]);
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSwitchToFormMode = () => {
|
const handleSwitchToFormMode = () => {
|
||||||
if (isJsonMode) {
|
if (isJsonMode) {
|
||||||
if (validateJsonBeforeSubmit()) {
|
// When switching to Form mode, ensure we have valid JSON
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(rawJsonValue);
|
||||||
|
// Update the parent component's state with the parsed value
|
||||||
|
onChange(parsed);
|
||||||
|
// Switch to form mode
|
||||||
setIsJsonMode(false);
|
setIsJsonMode(false);
|
||||||
|
} catch (err) {
|
||||||
|
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Update raw JSON value when switching to JSON mode
|
// Update raw JSON value when switching to JSON mode
|
||||||
@@ -160,8 +159,12 @@ const DynamicJsonForm = ({
|
|||||||
className="w-4 h-4"
|
className="w-4 h-4"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "object":
|
case "object": {
|
||||||
if (!propSchema.properties) return null;
|
// Handle case where we have a value but no schema properties
|
||||||
|
const objectValue = currentValue as JsonObject || {};
|
||||||
|
|
||||||
|
// If we have schema properties, use them to render fields
|
||||||
|
if (propSchema.properties) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 border rounded-md p-4">
|
<div className="space-y-4 border rounded-md p-4">
|
||||||
{Object.entries(propSchema.properties).map(([key, prop]) => (
|
{Object.entries(propSchema.properties).map(([key, prop]) => (
|
||||||
@@ -169,7 +172,7 @@ const DynamicJsonForm = ({
|
|||||||
<Label>{formatFieldLabel(key)}</Label>
|
<Label>{formatFieldLabel(key)}</Label>
|
||||||
{renderFormFields(
|
{renderFormFields(
|
||||||
prop,
|
prop,
|
||||||
(currentValue as JsonObject)?.[key],
|
objectValue[key],
|
||||||
[...path, key],
|
[...path, key],
|
||||||
depth + 1,
|
depth + 1,
|
||||||
)}
|
)}
|
||||||
@@ -177,6 +180,29 @@ const DynamicJsonForm = ({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
// If we have a value but no schema properties, render fields based on the value
|
||||||
|
else if (Object.keys(objectValue).length > 0) {
|
||||||
|
return (
|
||||||
|
<div className="space-y-4 border rounded-md p-4">
|
||||||
|
{Object.entries(objectValue).map(([key, value]) => (
|
||||||
|
<div key={key} className="space-y-2">
|
||||||
|
<Label>{formatFieldLabel(key)}</Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={String(value)}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleFieldChange([...path, key], e.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// If we have neither schema properties nor value, return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
case "array": {
|
case "array": {
|
||||||
const arrayValue = Array.isArray(currentValue) ? currentValue : [];
|
const arrayValue = Array.isArray(currentValue) ? currentValue : [];
|
||||||
if (!propSchema.items) return null;
|
if (!propSchema.items) return null;
|
||||||
@@ -384,8 +410,23 @@ const DynamicJsonForm = ({
|
|||||||
}}
|
}}
|
||||||
error={jsonError}
|
error={jsonError}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
// If schema type is object but value is not an object or is empty, and we have actual JSON data,
|
||||||
|
// render a simple representation of the JSON data
|
||||||
|
schema.type === "object" &&
|
||||||
|
(typeof value !== "object" || value === null || Object.keys(value).length === 0) &&
|
||||||
|
rawJsonValue &&
|
||||||
|
rawJsonValue !== "{}" ? (
|
||||||
|
<div className="space-y-4 border rounded-md p-4">
|
||||||
|
<p className="text-sm text-gray-500">Form view not available for this JSON structure. Using simplified view:</p>
|
||||||
|
<pre className="bg-gray-50 dark:bg-gray-800 dark:text-gray-100 p-4 rounded text-sm overflow-auto">
|
||||||
|
{rawJsonValue}
|
||||||
|
</pre>
|
||||||
|
<p className="text-sm text-gray-500">Use JSON mode for full editing capabilities.</p>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
renderFormFields(schema, value)
|
renderFormFields(schema, value)
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user