Add explicit Save button to the schema JSON editor

The JSON view no longer parses/saves on every keystroke — you type freely
and click "Save JSON" to apply. Invalid JSON (or a non-object) shows the
parse error inline instead of auto-rejecting; valid JSON is pretty-printed,
applied to the form/preview, and saved. The form editor still auto-saves.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parththakkar106
2026-07-21 16:01:42 +05:30
co-authored by Claude Opus 4.8
parent 67fbe17cee
commit 80fb5b0c89
2 changed files with 30 additions and 11 deletions
+7
View File
@@ -660,6 +660,13 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n
color: var(--danger, #e5484d);
font-size: 0.82rem;
}
.schema-json-actions {
display: flex;
align-items: center;
gap: 12px;
margin-top: 8px;
}
.schema-json-actions .schema-error { margin-top: 0; }
.schema-preview {
margin-top: 14px;
padding: 14px 16px;
+23 -11
View File
@@ -43,32 +43,37 @@ export default function ScenarioEditor() {
})
}
// RPG world-state schema: edited as raw JSON, only saved when it parses to an
// object (empty text clears the RPG layer). Invalid JSON shows an inline error
// and holds off saving.
const setSchema = (text) => {
// JSON view: typing only updates the text buffer; nothing is parsed or saved
// until the user clicks Save (so a half-typed edit doesn't spam errors).
const onJsonText = (text) => {
setSchemaText(text)
const trimmed = text.trim()
if (schemaError) setSchemaError('')
}
// Parse the JSON box on demand: apply + save if valid, else show the error.
const commitJson = () => {
const trimmed = schemaText.trim()
if (!trimmed) {
setSchemaError('')
setParsedSchema(null)
debounceSave('stat_schema', () => saveSchema(null))
saveSchema(null)
return
}
let parsed
try {
parsed = JSON.parse(trimmed)
} catch (err) {
setSchemaError(`Invalid JSON: ${err.message}`) // keep last-good preview
setSchemaError(`Invalid JSON: ${err.message}`)
return
}
if (typeof parsed !== 'object' || Array.isArray(parsed)) {
setSchemaError('The schema must be a JSON object.')
setSchemaError('The schema must be a JSON object (e.g. { "player": { … } }).')
return
}
setSchemaError('')
setParsedSchema(parsed)
debounceSave('stat_schema', () => saveSchema(parsed))
setSchemaText(JSON.stringify(parsed, null, 2)) // normalize / pretty-print
saveSchema(parsed)
}
const saveSchema = async (parsed) => {
@@ -230,12 +235,19 @@ export default function ScenarioEditor() {
<textarea
className="schema-editor"
value={schemaText}
onChange={(e) => setSchema(e.target.value)}
onChange={(e) => onJsonText(e.target.value)}
rows={14}
spellCheck={false}
placeholder={'{\n "player": { "hp": { "min": 0, "max": 100, "initial": 100 } },\n "npcs": {\n "gwen": { "name": "Gwen", "keys": "Gwen, ranger", "desc": "...",\n "stats": { "trust": { "min": -100, "max": 100, "initial": 20 } } }\n },\n "flags": { "has_key": { "desc": "...", "initial": false } },\n "milestones": { "goal": { "desc": "..." } }\n}'}
/>
{schemaError && <div className="schema-error">⚠ {schemaError}</div>}
<div className="schema-json-actions">
<button type="button" className="primary" onClick={commitJson}>Save JSON</button>
{schemaError
? <span className="schema-error">⚠ {schemaError}</span>
: <span className="dim" style={{ fontSize: '0.8rem' }}>
Edits apply when you click Save.
</span>}
</div>
<SchemaPreview schema={parsedSchema} />
</>
)}