From f882756dda26ee79c6d17edfb25815c14ebb414a Mon Sep 17 00:00:00 2001 From: jos Date: Sun, 30 Oct 2016 17:31:16 +0100 Subject: [PATCH] Keep expanded state when patching data --- src/components/TreeMode.js | 67 ++++++++++++++++++++++++++++++-------- src/develop.html | 2 +- src/jsonData.js | 18 +++++----- src/typedef.js | 4 +++ 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/components/TreeMode.js b/src/components/TreeMode.js index 88e822a..1b6da9a 100644 --- a/src/components/TreeMode.js +++ b/src/components/TreeMode.js @@ -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.} path * @return {boolean} */ - static expand (path) { + static expandRoot (path) { return path.length === 0 } - /** * Callback function to expand all nodes * diff --git a/src/develop.html b/src/develop.html index 4aa1aa1..480b631 100644 --- a/src/develop.html +++ b/src/develop.html @@ -13,7 +13,7 @@