Address the schema architecture crisis
This commit is contained in:
parent
2eec03661c
commit
b555e41c0b
1 changed files with 114 additions and 40 deletions
|
|
@ -113,6 +113,8 @@ const DynamicJsonForm = ({
|
|||
currentValue: JsonValue,
|
||||
path: string[] = [],
|
||||
depth: number = 0,
|
||||
parentSchema?: JsonSchemaType,
|
||||
propertyName?: string,
|
||||
) => {
|
||||
if (
|
||||
depth >= maxDepth &&
|
||||
|
|
@ -122,7 +124,7 @@ const DynamicJsonForm = ({
|
|||
return (
|
||||
<JsonEditor
|
||||
value={JSON.stringify(
|
||||
currentValue ?? generateDefaultValue(propSchema),
|
||||
currentValue ?? generateDefaultValue(propSchema, propertyName, parentSchema),
|
||||
null,
|
||||
2,
|
||||
)}
|
||||
|
|
@ -140,6 +142,9 @@ const DynamicJsonForm = ({
|
|||
);
|
||||
}
|
||||
|
||||
// Check if this property is required in the parent schema
|
||||
const isRequired = parentSchema?.required?.includes(propertyName || "") ?? false;
|
||||
|
||||
switch (propSchema.type) {
|
||||
case "string":
|
||||
return (
|
||||
|
|
@ -148,16 +153,11 @@ const DynamicJsonForm = ({
|
|||
value={(currentValue as string) ?? ""}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
// Allow clearing non-required fields by setting undefined
|
||||
// This preserves the distinction between empty string and unset
|
||||
if (!val && !propSchema.required) {
|
||||
handleFieldChange(path, undefined);
|
||||
} else {
|
||||
handleFieldChange(path, val);
|
||||
}
|
||||
// Always allow setting string values, including empty strings
|
||||
handleFieldChange(path, val);
|
||||
}}
|
||||
placeholder={propSchema.description}
|
||||
required={propSchema.required}
|
||||
required={isRequired}
|
||||
/>
|
||||
);
|
||||
case "number":
|
||||
|
|
@ -167,9 +167,7 @@ const DynamicJsonForm = ({
|
|||
value={(currentValue as number)?.toString() ?? ""}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
// Allow clearing non-required number fields
|
||||
// This preserves the distinction between 0 and unset
|
||||
if (!val && !propSchema.required) {
|
||||
if (!val && !isRequired) {
|
||||
handleFieldChange(path, undefined);
|
||||
} else {
|
||||
const num = Number(val);
|
||||
|
|
@ -179,7 +177,7 @@ const DynamicJsonForm = ({
|
|||
}
|
||||
}}
|
||||
placeholder={propSchema.description}
|
||||
required={propSchema.required}
|
||||
required={isRequired}
|
||||
/>
|
||||
);
|
||||
case "integer":
|
||||
|
|
@ -190,9 +188,7 @@ const DynamicJsonForm = ({
|
|||
value={(currentValue as number)?.toString() ?? ""}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value;
|
||||
// Allow clearing non-required integer fields
|
||||
// This preserves the distinction between 0 and unset
|
||||
if (!val && !propSchema.required) {
|
||||
if (!val && !isRequired) {
|
||||
handleFieldChange(path, undefined);
|
||||
} else {
|
||||
const num = Number(val);
|
||||
|
|
@ -203,7 +199,7 @@ const DynamicJsonForm = ({
|
|||
}
|
||||
}}
|
||||
placeholder={propSchema.description}
|
||||
required={propSchema.required}
|
||||
required={isRequired}
|
||||
/>
|
||||
);
|
||||
case "boolean":
|
||||
|
|
@ -213,7 +209,64 @@ const DynamicJsonForm = ({
|
|||
checked={(currentValue as boolean) ?? false}
|
||||
onChange={(e) => handleFieldChange(path, e.target.checked)}
|
||||
className="w-4 h-4"
|
||||
required={propSchema.required}
|
||||
required={isRequired}
|
||||
/>
|
||||
);
|
||||
case "object":
|
||||
if (!propSchema.properties) {
|
||||
return (
|
||||
<JsonEditor
|
||||
value={JSON.stringify(currentValue ?? {}, null, 2)}
|
||||
onChange={(newValue) => {
|
||||
try {
|
||||
const parsed = JSON.parse(newValue);
|
||||
handleFieldChange(path, parsed);
|
||||
setJsonError(undefined);
|
||||
} catch (err) {
|
||||
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
|
||||
}
|
||||
}}
|
||||
error={jsonError}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-2 border rounded p-3">
|
||||
{Object.entries(propSchema.properties).map(([key, subSchema]) => (
|
||||
<div key={key}>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{key}
|
||||
{propSchema.required?.includes(key) && (
|
||||
<span className="text-red-500 ml-1">*</span>
|
||||
)}
|
||||
</label>
|
||||
{renderFormFields(
|
||||
subSchema as JsonSchemaType,
|
||||
(currentValue as Record<string, JsonValue>)?.[key],
|
||||
[...path, key],
|
||||
depth + 1,
|
||||
propSchema,
|
||||
key,
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
case "array":
|
||||
return (
|
||||
<JsonEditor
|
||||
value={JSON.stringify(currentValue ?? [], null, 2)}
|
||||
onChange={(newValue) => {
|
||||
try {
|
||||
const parsed = JSON.parse(newValue);
|
||||
handleFieldChange(path, parsed);
|
||||
setJsonError(undefined);
|
||||
} catch (err) {
|
||||
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
|
||||
}
|
||||
}}
|
||||
error={jsonError}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
|
|
|
|||
Loading…
Reference in a new issue