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 {ESON} eson
|
||||||
* @param {Selection} selection
|
* @param {Selection} selection
|
||||||
* @param {Array.<{name?: string, value: JSONType, type?: ESONType}>} values
|
* @param {Array.<{name?: string, value: JSON, state: Object}>} values
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
export function replace (eson, selection, values) { // TODO: find a better name and define datastructure for values
|
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)),
|
path: compileJSONPointer(rootPath.concat(minIndex + offset)),
|
||||||
value: entry.value,
|
value: entry.value,
|
||||||
meta: {
|
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)),
|
path: compileJSONPointer(rootPath.concat(newProp)),
|
||||||
value: entry.value,
|
value: entry.value,
|
||||||
meta: {
|
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
|
* Get the contents of a list with paths
|
||||||
* @param {ESON} data
|
* @param {ESON} data
|
||||||
* @param {Path[]} paths
|
* @param {Path[]} paths
|
||||||
* @return {Array.<{name: string, value: JSON}>}
|
* @return {Array.<{name: string, value: JSON, state: Object}>}
|
||||||
*/
|
*/
|
||||||
export function contentsFromPaths (data, paths) {
|
export function contentsFromPaths (data, paths) {
|
||||||
return paths.map(path => {
|
return paths.map(path => {
|
||||||
|
const esonValue = getIn(data, path)
|
||||||
return {
|
return {
|
||||||
name: last(path),
|
name: last(path),
|
||||||
value: esonToJson(getIn(data, path))
|
value: esonToJson(esonValue),
|
||||||
// FIXME: also store the type and expanded state
|
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
|
* Find the root path of a selection: the parent node shared by both start
|
||||||
* and end of the selection
|
* and end of the selection
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
expand, expandOne, expandPath, applyErrors, search, nextSearchResult,
|
expand, expandOne, expandPath, applyErrors, search, nextSearchResult,
|
||||||
previousSearchResult,
|
previousSearchResult,
|
||||||
applySelection, pathsFromSelection,
|
applySelection, pathsFromSelection,
|
||||||
SELECTED, SELECTED_END
|
SELECTED, SELECTED_END, getEsonState
|
||||||
} from './eson'
|
} from './eson'
|
||||||
import 'console.table'
|
import 'console.table'
|
||||||
import repeat from 'lodash/repeat'
|
import repeat from 'lodash/repeat'
|
||||||
|
@ -552,6 +552,32 @@ test('pathsFromSelection (after)', () => {
|
||||||
expect(pathsFromSelection(eson, selection)).toEqual([])
|
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
|
// helper function to print JSON in the console
|
||||||
function printJSON (json, message = null) {
|
function printJSON (json, message = null) {
|
||||||
if (message) {
|
if (message) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
META,
|
META,
|
||||||
jsonToEson, esonToJson, updatePaths,
|
jsonToEson, esonToJson, updatePaths,
|
||||||
parseJSONPointer, compileJSONPointer,
|
parseJSONPointer, compileJSONPointer,
|
||||||
expandAll, pathExists, resolvePathIndex, createId
|
expandAll, pathExists, resolvePathIndex, createId, applyEsonState
|
||||||
} from './eson'
|
} from './eson'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,8 +35,10 @@ export function patchEson (eson, patch, expand = expandAll) {
|
||||||
|
|
||||||
switch (action.op) {
|
switch (action.op) {
|
||||||
case 'add': {
|
case 'add': {
|
||||||
const newValue = jsonToEson(action.value, path)
|
let newValue = jsonToEson(action.value, path)
|
||||||
// FIXME: apply expanded state
|
if (options && options.state) {
|
||||||
|
newValue = applyEsonState(newValue, options.state)
|
||||||
|
}
|
||||||
// FIXME: apply options.type
|
// FIXME: apply options.type
|
||||||
const result = add(updatedEson, path, newValue, options)
|
const result = add(updatedEson, path, newValue, options)
|
||||||
updatedEson = result.data
|
updatedEson = result.data
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
import { META, jsonToEson, esonToJson } from './eson'
|
import { META, jsonToEson, esonToJson, expandOne } from './eson'
|
||||||
import { patchEson } from './patchEson'
|
import { patchEson } from './patchEson'
|
||||||
import { assertDeepEqualEson } from './utils/assertDeepEqualEson'
|
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', () => {
|
test('jsonpatch remove', () => {
|
||||||
const json = {
|
const json = {
|
||||||
arr: [1,2,3],
|
arr: [1,2,3],
|
||||||
|
|
Loading…
Reference in New Issue