Keep expanded state with copy/paste
This commit is contained in:
parent
9a37fe0451
commit
419bdc6307
|
@ -182,7 +182,7 @@ export function insertBefore (eson, path, values) { // TODO: find a better name
|
|||
*
|
||||
* @param {ESON} eson
|
||||
* @param {Selection} selection
|
||||
* @param {Array.<{name?: string, value: JSONType, type?: ESONType}>} values
|
||||
* @param {Array.<{name?: string, value: JSON, state: Object}>} values
|
||||
* @return {Array}
|
||||
*/
|
||||
export function replace (eson, selection, values) { // TODO: find a better name and define datastructure for values
|
||||
|
@ -197,7 +197,7 @@ export function replace (eson, selection, values) { // TODO: find a better name
|
|||
path: compileJSONPointer(rootPath.concat(minIndex + offset)),
|
||||
value: entry.value,
|
||||
meta: {
|
||||
type: entry.type
|
||||
state: entry.state
|
||||
}
|
||||
}))
|
||||
|
||||
|
@ -214,8 +214,8 @@ export function replace (eson, selection, values) { // TODO: find a better name
|
|||
path: compileJSONPointer(rootPath.concat(newProp)),
|
||||
value: entry.value,
|
||||
meta: {
|
||||
type: entry.type,
|
||||
before
|
||||
before,
|
||||
state: entry.state
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -467,18 +467,67 @@ export function pathsFromSelection (eson, selection) {
|
|||
* Get the contents of a list with paths
|
||||
* @param {ESON} data
|
||||
* @param {Path[]} paths
|
||||
* @return {Array.<{name: string, value: JSON}>}
|
||||
* @return {Array.<{name: string, value: JSON, state: Object}>}
|
||||
*/
|
||||
export function contentsFromPaths (data, paths) {
|
||||
return paths.map(path => {
|
||||
const esonValue = getIn(data, path)
|
||||
return {
|
||||
name: last(path),
|
||||
value: esonToJson(getIn(data, path))
|
||||
// FIXME: also store the type and expanded state
|
||||
value: esonToJson(esonValue),
|
||||
state: getEsonState(esonValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object with paths and state (expanded, type) of an eson object
|
||||
* @param {ESON} eson
|
||||
* @return {Object.<key, Object>} An object with compiled JSON paths as key,
|
||||
* And a META object as state
|
||||
*/
|
||||
export function getEsonState (eson) {
|
||||
let state = {}
|
||||
|
||||
transform(eson, function (eson, path) {
|
||||
let meta = {}
|
||||
if (eson[META].expanded === true) {
|
||||
meta.expanded = true
|
||||
}
|
||||
if (eson[META].type === 'string') {
|
||||
meta.type = 'string'
|
||||
}
|
||||
if (!isEmpty(meta)) {
|
||||
state[compileJSONPointer(path)] = meta
|
||||
}
|
||||
|
||||
return eson
|
||||
})
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge ESON meta data to an ESON object: expanded state, type
|
||||
* @param {ESON} data
|
||||
* @param {Object.<String, Object>} state
|
||||
* @return {ESON}
|
||||
*/
|
||||
export function applyEsonState(data, state) {
|
||||
let updatedData = data
|
||||
|
||||
for (let path in state) {
|
||||
if (state.hasOwnProperty(path)) {
|
||||
const metaPath = parseJSONPointer(path).concat(META)
|
||||
updatedData = updateIn(updatedData, metaPath, function (meta) {
|
||||
return Object.assign({}, meta, state[path])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return updatedData
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the root path of a selection: the parent node shared by both start
|
||||
* and end of the selection
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
expand, expandOne, expandPath, applyErrors, search, nextSearchResult,
|
||||
previousSearchResult,
|
||||
applySelection, pathsFromSelection,
|
||||
SELECTED, SELECTED_END
|
||||
SELECTED, SELECTED_END, getEsonState
|
||||
} from './eson'
|
||||
import 'console.table'
|
||||
import repeat from 'lodash/repeat'
|
||||
|
@ -552,6 +552,32 @@ test('pathsFromSelection (after)', () => {
|
|||
expect(pathsFromSelection(eson, selection)).toEqual([])
|
||||
})
|
||||
|
||||
test('getEsonState', () => {
|
||||
const eson = jsonToEson({
|
||||
"obj": {
|
||||
"arr": ["1",2, {"first":3,"last":4}]
|
||||
},
|
||||
"str": "hello world",
|
||||
"nill": null,
|
||||
"bool": false
|
||||
})
|
||||
|
||||
eson.obj[META].expanded = true
|
||||
eson.obj.arr[META].expanded = false
|
||||
eson.obj.arr[0][META].type = 'string'
|
||||
eson.obj.arr[2][META].expanded = true
|
||||
|
||||
const state = getEsonState(eson)
|
||||
|
||||
expect(state).toEqual({
|
||||
'/obj': { expanded: true },
|
||||
'/obj/arr/0': { type: 'string' },
|
||||
'/obj/arr/2': { expanded: true },
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: test applyEsonState
|
||||
|
||||
// helper function to print JSON in the console
|
||||
function printJSON (json, message = null) {
|
||||
if (message) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
META,
|
||||
jsonToEson, esonToJson, updatePaths,
|
||||
parseJSONPointer, compileJSONPointer,
|
||||
expandAll, pathExists, resolvePathIndex, createId
|
||||
expandAll, pathExists, resolvePathIndex, createId, applyEsonState
|
||||
} from './eson'
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,10 @@ export function patchEson (eson, patch, expand = expandAll) {
|
|||
|
||||
switch (action.op) {
|
||||
case 'add': {
|
||||
const newValue = jsonToEson(action.value, path)
|
||||
// FIXME: apply expanded state
|
||||
let newValue = jsonToEson(action.value, path)
|
||||
if (options && options.state) {
|
||||
newValue = applyEsonState(newValue, options.state)
|
||||
}
|
||||
// FIXME: apply options.type
|
||||
const result = add(updatedEson, path, newValue, options)
|
||||
updatedEson = result.data
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
import { readFileSync } from 'fs'
|
||||
import { META, jsonToEson, esonToJson } from './eson'
|
||||
import { META, jsonToEson, esonToJson, expandOne } from './eson'
|
||||
import { patchEson } from './patchEson'
|
||||
import { assertDeepEqualEson } from './utils/assertDeepEqualEson'
|
||||
|
||||
|
@ -77,6 +77,39 @@ test('jsonpatch add: append to matrix', () => {
|
|||
])
|
||||
})
|
||||
|
||||
test('jsonpatch add: pass eson state', () => {
|
||||
const json = {
|
||||
a: 2
|
||||
}
|
||||
|
||||
const patch = [
|
||||
{
|
||||
op: 'add',
|
||||
path: '/b',
|
||||
value: {c: {d: 3}},
|
||||
meta: {
|
||||
state: {
|
||||
'': { expanded: true },
|
||||
'/c/d': { expanded: true }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const data = jsonToEson(json)
|
||||
const result = patchEson(data, patch)
|
||||
const patchedData = result.data
|
||||
|
||||
let expected = jsonToEson({
|
||||
a: 2,
|
||||
b: {c: {d: 3}}
|
||||
})
|
||||
expected = expandOne(expected, ['b'], true)
|
||||
expected = expandOne(expected, ['b', 'c', 'd'], true)
|
||||
|
||||
assertDeepEqualEson(patchedData, expected)
|
||||
})
|
||||
|
||||
test('jsonpatch remove', () => {
|
||||
const json = {
|
||||
arr: [1,2,3],
|
||||
|
|
Loading…
Reference in New Issue