Keep expanded state when patching data
This commit is contained in:
parent
3f3fef9b40
commit
f882756dda
|
@ -1,7 +1,7 @@
|
|||
import { h, Component } from 'preact'
|
||||
|
||||
import { updateIn } from '../utils/immutabilityHelpers'
|
||||
import { expand, jsonToData, dataToJson, toDataPath, patchData } from '../jsonData'
|
||||
import { updateIn, getIn } from '../utils/immutabilityHelpers'
|
||||
import { expand, jsonToData, dataToJson, toDataPath, patchData, pathExists } from '../jsonData'
|
||||
import { parseJSON } from '../utils/jsonUtils'
|
||||
import {
|
||||
duplicate, insert, append, remove, changeType, changeValue, changeProperty, sort
|
||||
|
@ -17,8 +17,7 @@ export default class TreeMode extends Component {
|
|||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
const expand = this.props.options.expand || TreeMode.expand
|
||||
const data = jsonToData(this.props.data || {}, expand, [])
|
||||
const data = jsonToData(this.props.data || {}, TreeMode.expandAll, [])
|
||||
|
||||
this.state = {
|
||||
data,
|
||||
|
@ -282,13 +281,22 @@ export default class TreeMode extends Component {
|
|||
|
||||
/**
|
||||
* Apply a JSONPatch to the current JSON document
|
||||
* @param {JSONPatch} actions JSONPatch actions
|
||||
* @param {JSONPatch} actions JSONPatch actions
|
||||
* @param {PatchOptions} [options] If no expand function is provided, the
|
||||
* expanded state will be kept as is for
|
||||
* existing paths. New paths will be fully
|
||||
* expanded.
|
||||
* @return {JSONPatchResult} Returns a JSONPatch result containing the
|
||||
* patch, a patch to revert the action, and
|
||||
* an error object which is null when successful
|
||||
*/
|
||||
patch (actions) {
|
||||
const result = patchData(this.state.data, actions)
|
||||
patch (actions, options = {}) {
|
||||
if (!Array.isArray(actions)) {
|
||||
throw new TypeError('Array with patch actions expected')
|
||||
}
|
||||
|
||||
const expand = options.expand || (path => this.expandKeepOrExpandAll(path))
|
||||
const result = patchData(this.state.data, actions, expand)
|
||||
const data = result.data
|
||||
|
||||
if (this.props.options.history != false) {
|
||||
|
@ -323,13 +331,17 @@ export default class TreeMode extends Component {
|
|||
/**
|
||||
* Set JSON object in editor
|
||||
* @param {Object | Array | string | number | boolean | null} json JSON data
|
||||
* @param {SetOptions} [options]
|
||||
* @param {SetOptions} [options] If no expand function is provided,
|
||||
* The root will be expanded and all other nodes
|
||||
* will be collapsed.
|
||||
*/
|
||||
set (json, options = {}) {
|
||||
this.setState({
|
||||
data: jsonToData(json, options.expand || TreeMode.expand, []),
|
||||
const expand = options.expand || TreeMode.expandRoot
|
||||
|
||||
// TODO: do we want to keep history when .set(json) is called?
|
||||
this.setState({
|
||||
data: jsonToData(json, expand, []),
|
||||
|
||||
// TODO: do we want to keep history when .set(json) is called? (currently we remove history)
|
||||
history: [],
|
||||
historyIndex: 0
|
||||
})
|
||||
|
@ -380,6 +392,36 @@ export default class TreeMode extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a path exists in the editor
|
||||
* @param {Path} path
|
||||
*/
|
||||
exists (path) {
|
||||
return pathExists(this.state.data, path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an Array or Object at a certain path is expanded.
|
||||
* When the node does not exist, the function throws an error
|
||||
* @param {Path} path
|
||||
* @return {boolean} Returns true when expanded, false otherwise
|
||||
*/
|
||||
isExpanded (path) {
|
||||
return getIn(this.state.data, toDataPath(this.state.data, path)).expanded
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand function which keeps the expanded state the same as the current data.
|
||||
* When the path doesn't yet exist, it will be expanded.
|
||||
* @param {Path} path
|
||||
* @return {boolean}
|
||||
*/
|
||||
expandKeepOrExpandAll (path) {
|
||||
return this.exists(path)
|
||||
? this.isExpanded(path)
|
||||
: TreeMode.expandAll(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the editor
|
||||
*/
|
||||
|
@ -395,11 +437,10 @@ export default class TreeMode extends Component {
|
|||
* @param {Array.<string>} path
|
||||
* @return {boolean}
|
||||
*/
|
||||
static expand (path) {
|
||||
static expandRoot (path) {
|
||||
return path.length === 0
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback function to expand all nodes
|
||||
*
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<style>
|
||||
#container {
|
||||
height: 300px;
|
||||
height: 500px;
|
||||
width: 100%;
|
||||
max-width : 800px;
|
||||
}
|
||||
|
|
|
@ -7,12 +7,17 @@ import { setIn, updateIn, getIn, deleteIn, insertAt } from './utils/immutability
|
|||
import { isObject } from './utils/typeUtils'
|
||||
import isEqual from 'lodash/isEqual'
|
||||
|
||||
const expandAll = function (path) {
|
||||
/**
|
||||
* Expand function which will expand all nodes
|
||||
* @param path
|
||||
* @return {boolean}
|
||||
*/
|
||||
export function expandAll (path) {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: double check whether all patch functions handle each of the
|
||||
// extra properties in .jsoneditor: `before`, `type`, `order`
|
||||
// extra properties in .jsoneditor: `before`, `type`, ...
|
||||
|
||||
/**
|
||||
* Convert a JSON object into the internally used data model
|
||||
|
@ -112,11 +117,11 @@ export function toDataPath (data, path) {
|
|||
* Apply a patch to a JSONData object
|
||||
* @param {JSONData} data
|
||||
* @param {Array} patch A JSON patch
|
||||
* @param {function(path: Path)} [expand] Optional function to determine
|
||||
* what nodes must be expanded
|
||||
* @return {{data: JSONData, revert: Array.<Object>, error: Error | null}}
|
||||
*/
|
||||
export function patchData (data, patch) {
|
||||
const expand = expandAll // TODO: customizable expand function
|
||||
|
||||
export function patchData (data, patch, expand = expandAll) {
|
||||
let updatedData = data
|
||||
let revert = []
|
||||
|
||||
|
@ -134,7 +139,6 @@ export function patchData (data, patch) {
|
|||
// insert with type 'string' or 'value'
|
||||
newValue.type = options.type
|
||||
}
|
||||
// TODO: handle options.order
|
||||
|
||||
const result = add(updatedData, action.path, newValue, options)
|
||||
updatedData = result.data
|
||||
|
@ -155,12 +159,10 @@ export function patchData (data, patch) {
|
|||
const path = parseJSONPointer(action.path)
|
||||
let newValue = jsonToData(action.value, expand, path)
|
||||
|
||||
// TODO: move setting type to jsonToData
|
||||
if (options && options.type) {
|
||||
// insert with type 'string' or 'value'
|
||||
newValue.type = options.type
|
||||
}
|
||||
// TODO: handle options.order
|
||||
|
||||
const result = replace(updatedData, path, newValue)
|
||||
updatedData = result.data
|
||||
|
|
|
@ -48,4 +48,8 @@
|
|||
* @typedef {{
|
||||
* expand: function (path: Path)?
|
||||
* }} SetOptions
|
||||
*
|
||||
* @typedef {{
|
||||
* expand: function (path: Path)?
|
||||
* }} PatchOptions
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue