Implemented duplicate for multiple nodes

This commit is contained in:
jos 2017-11-08 15:41:40 +01:00
parent dd989f9a64
commit cb354f2331
3 changed files with 51 additions and 34 deletions

View File

@ -92,37 +92,44 @@ export function changeType (data, path, type) {
* and object property
*
* @param {ESON} data
* @param {Path} path
* @param {ESONSelection} selection
* @return {Array}
*/
export function duplicate (data, path) {
export function duplicate (data, selection) {
// console.log('duplicate', path)
const parentPath = path.slice(0, path.length - 1)
const rootPath = findRootPath(selection)
const start = selection.start.path[rootPath.length]
const end = selection.end.path[rootPath.length]
const root = getIn(data, toEsonPath(data, rootPath))
const { maxIndex } = findSelectionIndices(root, start, end)
const paths = pathsFromSelection(data, selection)
const esonPath = toEsonPath(data, parentPath)
const parent = getIn(data, esonPath)
if (parent.type === 'Array') {
const index = parseInt(path[path.length - 1]) + 1
return [{
if (root.type === 'Array') {
return paths.map((path, offset) => ({
op: 'copy',
from: compileJSONPointer(path),
path: compileJSONPointer(parentPath.concat(index))
}]
path: compileJSONPointer(rootPath.concat(maxIndex + offset))
}))
}
else { // object.type === 'Object'
const prop = path[path.length - 1]
const newProp = findUniqueName(prop, parent.props.map(p => p.name))
const { maxIndex } = findSelectionIndices(root, start, end)
const nextProp = root.props && root.props[maxIndex]
const before = nextProp ? nextProp.name : null
return [{
return paths.map(path => {
const prop = last(path)
const newProp = findUniqueName(prop, root.props.map(p => p.name))
return {
op: 'copy',
from: compileJSONPointer(path),
path: compileJSONPointer(parentPath.concat(newProp)),
path: compileJSONPointer(rootPath.concat(newProp)),
jsoneditor: {
before: findNextProp(parent, prop)
before
}
}]
}
})
}
}
@ -226,7 +233,7 @@ export function insertBefore (data, path, values) { // TODO: find a better name
* and object property
*
* @param {ESON} data
* @param {Selection} selection
* @param {ESONSelection} selection
* @param {Array.<{name?: string, value: JSONType, type?: ESONType}>} values
* @return {Array}
*/
@ -235,10 +242,8 @@ export function replace (data, selection, values) { // TODO: find a better name
const rootPath = findRootPath(selection)
const start = selection.start.path[rootPath.length]
const end = selection.end.path[rootPath.length]
console.log('rootPath', rootPath, start, end)
const root = getIn(data, toEsonPath(data, rootPath))
const { minIndex, maxIndex } = findSelectionIndices(root, start, end)
console.log('selection', minIndex, maxIndex)
if (root.type === 'Array') {
const removeActions = removeAll(pathsFromSelection(data, selection))

View File

@ -72,6 +72,7 @@ export default class TreeMode extends Component {
'cut': this.handleKeyDownCut,
'copy': this.handleKeyDownCopy,
'paste': this.handleKeyDownPaste,
'duplicate': this.handleKeyDownDuplicate,
'undo': this.handleUndo,
'redo': this.handleRedo,
'find': this.handleFocusFind,
@ -372,11 +373,11 @@ export default class TreeMode extends Component {
this.focusToNext(parentPath)
}
handleDuplicate = (path) => {
this.handlePatch(duplicate(this.state.data, path))
// apply focus to the duplicated node
this.focusToNext(path)
handleDuplicate = () => {
if (this.state.selection) {
this.handlePatch(duplicate(this.state.data, this.state.selection))
// TODO: focus to duplicated selection
}
}
handleRemove = (path) => {
@ -455,6 +456,17 @@ export default class TreeMode extends Component {
}
}
handleKeyDownDuplicate = (event) => {
const path = this.findDataPathFromElement(event.target)
if (path) {
const selection = { start: {path}, end: {path} }
this.handlePatch(duplicate(this.state.data, selection))
// apply focus to the duplicated node
this.focusToNext(path)
}
}
handleCut = () => {
const selection = this.state.selection
if (selection && selection.start && selection.end) {

View File

@ -53,42 +53,42 @@ const CREATE_TYPE = {
duplicate: (path, events) => h('button', {
key: 'duplicate',
className: MENU_ITEM_CLASS_NAME,
onClick: () => events.onDuplicate(path),
onClick: () => events.onDuplicate(),
title: 'Duplicate'
}, 'Duplicate'),
cut: (path, events) => h('button', {
key: 'cut',
className: MENU_ITEM_CLASS_NAME,
onClick: () => events.onCut(path),
onClick: () => events.onCut(),
title: 'Cut'
}, 'Cut'),
copy: (path, events) => h('button', {
key: 'copy',
className: MENU_ITEM_CLASS_NAME,
onClick: () => events.onCopy(path),
onClick: () => events.onCopy(),
title: 'Copy'
}, 'Copy'),
paste: (path, events) => h('button', {
key: 'paste',
className: MENU_ITEM_CLASS_NAME,
onClick: () => events.onPaste(path),
onClick: () => events.onPaste(),
title: 'Paste'
}, 'Paste'),
remove: (path, events) => h('button', {
key: 'remove',
className: MENU_ITEM_CLASS_NAME,
onClick: () => events.onRemove(null), // do not pass path: we want to remove selection
onClick: () => events.onRemove(),
title: 'Remove'
}, 'Remove'),
insertStructure: (path, events) => h('button', {
key: 'insertStructure',
className: MENU_ITEM_CLASS_NAME,
onClick: () => events.onInsertStructure(path),
onClick: () => events.onInsertStructure(),
title: 'Insert a new object with the same data structure as the item above'
}, 'Insert structure'),