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:
co-authored by
Claude Opus 4.8
parent
67fbe17cee
commit
80fb5b0c89
@@ -660,6 +660,13 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n
|
|||||||
color: var(--danger, #e5484d);
|
color: var(--danger, #e5484d);
|
||||||
font-size: 0.82rem;
|
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 {
|
.schema-preview {
|
||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
padding: 14px 16px;
|
padding: 14px 16px;
|
||||||
|
|||||||
@@ -43,32 +43,37 @@ export default function ScenarioEditor() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPG world-state schema: edited as raw JSON, only saved when it parses to an
|
// JSON view: typing only updates the text buffer; nothing is parsed or saved
|
||||||
// object (empty text clears the RPG layer). Invalid JSON shows an inline error
|
// until the user clicks Save (so a half-typed edit doesn't spam errors).
|
||||||
// and holds off saving.
|
const onJsonText = (text) => {
|
||||||
const setSchema = (text) => {
|
|
||||||
setSchemaText(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) {
|
if (!trimmed) {
|
||||||
setSchemaError('')
|
setSchemaError('')
|
||||||
setParsedSchema(null)
|
setParsedSchema(null)
|
||||||
debounceSave('stat_schema', () => saveSchema(null))
|
saveSchema(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let parsed
|
let parsed
|
||||||
try {
|
try {
|
||||||
parsed = JSON.parse(trimmed)
|
parsed = JSON.parse(trimmed)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setSchemaError(`Invalid JSON: ${err.message}`) // keep last-good preview
|
setSchemaError(`Invalid JSON: ${err.message}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (typeof parsed !== 'object' || Array.isArray(parsed)) {
|
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
|
return
|
||||||
}
|
}
|
||||||
setSchemaError('')
|
setSchemaError('')
|
||||||
setParsedSchema(parsed)
|
setParsedSchema(parsed)
|
||||||
debounceSave('stat_schema', () => saveSchema(parsed))
|
setSchemaText(JSON.stringify(parsed, null, 2)) // normalize / pretty-print
|
||||||
|
saveSchema(parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveSchema = async (parsed) => {
|
const saveSchema = async (parsed) => {
|
||||||
@@ -230,12 +235,19 @@ export default function ScenarioEditor() {
|
|||||||
<textarea
|
<textarea
|
||||||
className="schema-editor"
|
className="schema-editor"
|
||||||
value={schemaText}
|
value={schemaText}
|
||||||
onChange={(e) => setSchema(e.target.value)}
|
onChange={(e) => onJsonText(e.target.value)}
|
||||||
rows={14}
|
rows={14}
|
||||||
spellCheck={false}
|
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}'}
|
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} />
|
<SchemaPreview schema={parsedSchema} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user