Handle changes via JSONPatch

This commit is contained in:
josdejong 2020-05-06 13:57:55 +02:00
parent e66ff70ac4
commit 4d2eb28eb3
3 changed files with 49 additions and 46 deletions

View File

@ -1,6 +1,5 @@
<script> <script>
import JSONEditor from './JSONEditor.svelte' import JSONEditor from './JSONEditor.svelte'
import { beforeUpdate, afterUpdate } from 'svelte'
let json = { let json = {
'array': [1, 2, 3, { 'array': [1, 2, 3, {
@ -47,9 +46,6 @@
console.time('load editor') console.time('load editor')
beforeUpdate(() => console.time('render app'))
afterUpdate(() => console.timeEnd('render app'))
function handleChangeFiles (event) { function handleChangeFiles (event) {
console.log('handleChangeFiles', event.target.files) console.log('handleChangeFiles', event.target.files)

View File

@ -3,7 +3,7 @@
import { faSearch } from '@fortawesome/free-solid-svg-icons' import { faSearch } from '@fortawesome/free-solid-svg-icons'
import Node from './JSONNode.svelte' import Node from './JSONNode.svelte'
import { search } from './search' import { search } from './search'
import { beforeUpdate, afterUpdate } from 'svelte' import { immutableJSONPatch } from './utils/immutableJSONPatch'
export let json = {} export let json = {}
export let onChange = () => {} export let onChange = () => {}
@ -17,8 +17,9 @@
json = newJson json = newJson
} }
beforeUpdate(() => console.time('render JSONEditor')) function getPath () {
afterUpdate(() => console.timeEnd('render JSONEditor')) return []
}
function doSearch (json, searchText) { function doSearch (json, searchText) {
console.time('search') console.time('search')
@ -38,17 +39,18 @@
function handleChangeValue (value, key) { function handleChangeValue (value, key) {
// console.log('handleChangeValue', value, key) // console.log('handleChangeValue', value, key)
json = value // json = value
}
function handleInputTextArea (event) {
console.log('on:input')
try {
json = JSON.parse(event.target.value)
} catch (err) {
console.error(err)
}
} }
/**
* @param {JSONPatchDocument} operations
*/
function handleChange (operations) {
console.log('handleChange', operations)
// TODO: store changes in history
json = immutableJSONPatch(json, operations).json
}
</script> </script>
<div class="jsoneditor"> <div class="jsoneditor">
@ -62,6 +64,8 @@
expanded={true} expanded={true}
onChangeKey={handleChangeKey} onChangeKey={handleChangeKey}
onChangeValue={handleChangeValue} onChangeValue={handleChangeValue}
onChange={handleChange}
getParentPath={getPath}
/> />
</div> </div>
</div> </div>

View File

@ -8,14 +8,24 @@
import { updateProps } from './utils/updateProps.js' import { updateProps } from './utils/updateProps.js'
import { unescapeHTML } from './utils/stringUtils' import { unescapeHTML } from './utils/stringUtils'
import { getInnerText } from './utils/domUtils' import { getInnerText } from './utils/domUtils'
import { compileJSONPointer } from './utils/jsonPointer'
export let key = undefined export let key = undefined // only applicable for object properties
export let index = undefined // only applicable for array items
export let value export let value
export let searchResult export let searchResult
export let onChange
export let onChangeKey export let onChangeKey
export let onChangeValue
export let expanded = false export let expanded = false
export let getParentPath
function getPath () {
return key !== undefined
? getParentPath().concat(key)
: []
}
const DEFAULT_LIMIT = 100 const DEFAULT_LIMIT = 100
const escapeUnicode = false // TODO: pass via options const escapeUnicode = false // TODO: pass via options
@ -90,7 +100,17 @@
function handleKeyInput (event) { function handleKeyInput (event) {
const newKey = unescapeHTML(getInnerText(event.target)) const newKey = unescapeHTML(getInnerText(event.target))
// TODO: replace the onChangeKey callback with gobally managed JSONNode id's,
// which are kept in sync with the json itself using JSONPatch
onChangeKey(newKey, key) onChangeKey(newKey, key)
const parentPath = getParentPath()
onChange([{
op: 'move',
from: compileJSONPointer(parentPath.concat(key)),
path: compileJSONPointer(parentPath.concat(newKey))
}])
} }
function handleKeyBlur () { function handleKeyBlur () {
@ -101,7 +121,12 @@
function handleValueInput (event) { function handleValueInput (event) {
const valueText = unescapeHTML(getInnerText(event.target)) const valueText = unescapeHTML(getInnerText(event.target))
const newValue = stringConvert(valueText) // TODO: implement support for type "string" const newValue = stringConvert(valueText) // TODO: implement support for type "string"
onChangeValue(newValue, key)
onChange([{
op: 'replace',
path: compileJSONPointer(getPath()),
value: newValue
}])
} }
function handleValueBlur () { function handleValueBlur () {
@ -129,15 +154,6 @@
function handleChangeKey (newChildKey, oldChildKey) { function handleChangeKey (newChildKey, oldChildKey) {
if (type === 'object') { if (type === 'object') {
const updatedValue = {}
Object.keys(value).forEach(childKey => {
if (childKey === oldChildKey) {
updatedValue[newChildKey] = value[childKey]
} else {
updatedValue[childKey] = value[childKey]
}
})
const index = props.findIndex(item => item.key === oldChildKey) const index = props.findIndex(item => item.key === oldChildKey)
if (index !== -1) { if (index !== -1) {
// we use splice here to replace the old key with the new new one // we use splice here to replace the old key with the new new one
@ -150,21 +166,6 @@
key: newChildKey key: newChildKey
}) })
} }
onChangeValue(updatedValue, key)
}
}
function handleChangeValue (childValue, childKey) {
// FIXME: use an immutability setIn function here
if (type === 'array') {
const updatedValue = [...value]
updatedValue[childKey] = childValue
onChangeValue(updatedValue, key)
} else if (type === 'object') {
const updatedValue = { ...value }
updatedValue[childKey] = childValue
onChangeValue(updatedValue, key)
} }
} }
@ -210,7 +211,8 @@
value={item} value={item}
searchResult={searchResult ? searchResult[index] : undefined} searchResult={searchResult ? searchResult[index] : undefined}
onChangeKey={handleChangeKey} onChangeKey={handleChangeKey}
onChangeValue={handleChangeValue} onChange={onChange}
getParentPath={getPath}
/> />
{/each} {/each}
{#if limited} {#if limited}
@ -259,7 +261,8 @@
value={value[prop.key]} value={value[prop.key]}
searchResult={searchResult ? searchResult[prop.key] : undefined} searchResult={searchResult ? searchResult[prop.key] : undefined}
onChangeKey={handleChangeKey} onChangeKey={handleChangeKey}
onChangeValue={handleChangeValue} onChange={onChange}
getParentPath={getPath}
/> />
{/each} {/each}
</div> </div>