Implemented duplicate for multiple nodes
This commit is contained in:
parent
dd989f9a64
commit
cb354f2331
|
@ -92,37 +92,44 @@ export function changeType (data, path, type) {
|
||||||
* and object property
|
* and object property
|
||||||
*
|
*
|
||||||
* @param {ESON} data
|
* @param {ESON} data
|
||||||
* @param {Path} path
|
* @param {ESONSelection} selection
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
export function duplicate (data, path) {
|
export function duplicate (data, selection) {
|
||||||
// console.log('duplicate', path)
|
// 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)
|
if (root.type === 'Array') {
|
||||||
const parent = getIn(data, esonPath)
|
return paths.map((path, offset) => ({
|
||||||
|
|
||||||
if (parent.type === 'Array') {
|
|
||||||
const index = parseInt(path[path.length - 1]) + 1
|
|
||||||
return [{
|
|
||||||
op: 'copy',
|
op: 'copy',
|
||||||
from: compileJSONPointer(path),
|
from: compileJSONPointer(path),
|
||||||
path: compileJSONPointer(parentPath.concat(index))
|
path: compileJSONPointer(rootPath.concat(maxIndex + offset))
|
||||||
}]
|
}))
|
||||||
}
|
}
|
||||||
else { // object.type === 'Object'
|
else { // object.type === 'Object'
|
||||||
const prop = path[path.length - 1]
|
const { maxIndex } = findSelectionIndices(root, start, end)
|
||||||
const newProp = findUniqueName(prop, parent.props.map(p => p.name))
|
const nextProp = root.props && root.props[maxIndex]
|
||||||
|
const before = nextProp ? nextProp.name : null
|
||||||
|
|
||||||
return [{
|
return paths.map(path => {
|
||||||
op: 'copy',
|
const prop = last(path)
|
||||||
from: compileJSONPointer(path),
|
const newProp = findUniqueName(prop, root.props.map(p => p.name))
|
||||||
path: compileJSONPointer(parentPath.concat(newProp)),
|
|
||||||
jsoneditor: {
|
return {
|
||||||
before: findNextProp(parent, prop)
|
op: 'copy',
|
||||||
|
from: compileJSONPointer(path),
|
||||||
|
path: compileJSONPointer(rootPath.concat(newProp)),
|
||||||
|
jsoneditor: {
|
||||||
|
before
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}]
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +233,7 @@ export function insertBefore (data, path, values) { // TODO: find a better name
|
||||||
* and object property
|
* and object property
|
||||||
*
|
*
|
||||||
* @param {ESON} data
|
* @param {ESON} data
|
||||||
* @param {Selection} selection
|
* @param {ESONSelection} selection
|
||||||
* @param {Array.<{name?: string, value: JSONType, type?: ESONType}>} values
|
* @param {Array.<{name?: string, value: JSONType, type?: ESONType}>} values
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
|
@ -235,10 +242,8 @@ export function replace (data, selection, values) { // TODO: find a better name
|
||||||
const rootPath = findRootPath(selection)
|
const rootPath = findRootPath(selection)
|
||||||
const start = selection.start.path[rootPath.length]
|
const start = selection.start.path[rootPath.length]
|
||||||
const end = selection.end.path[rootPath.length]
|
const end = selection.end.path[rootPath.length]
|
||||||
console.log('rootPath', rootPath, start, end)
|
|
||||||
const root = getIn(data, toEsonPath(data, rootPath))
|
const root = getIn(data, toEsonPath(data, rootPath))
|
||||||
const { minIndex, maxIndex } = findSelectionIndices(root, start, end)
|
const { minIndex, maxIndex } = findSelectionIndices(root, start, end)
|
||||||
console.log('selection', minIndex, maxIndex)
|
|
||||||
|
|
||||||
if (root.type === 'Array') {
|
if (root.type === 'Array') {
|
||||||
const removeActions = removeAll(pathsFromSelection(data, selection))
|
const removeActions = removeAll(pathsFromSelection(data, selection))
|
||||||
|
|
|
@ -72,6 +72,7 @@ export default class TreeMode extends Component {
|
||||||
'cut': this.handleKeyDownCut,
|
'cut': this.handleKeyDownCut,
|
||||||
'copy': this.handleKeyDownCopy,
|
'copy': this.handleKeyDownCopy,
|
||||||
'paste': this.handleKeyDownPaste,
|
'paste': this.handleKeyDownPaste,
|
||||||
|
'duplicate': this.handleKeyDownDuplicate,
|
||||||
'undo': this.handleUndo,
|
'undo': this.handleUndo,
|
||||||
'redo': this.handleRedo,
|
'redo': this.handleRedo,
|
||||||
'find': this.handleFocusFind,
|
'find': this.handleFocusFind,
|
||||||
|
@ -372,11 +373,11 @@ export default class TreeMode extends Component {
|
||||||
this.focusToNext(parentPath)
|
this.focusToNext(parentPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDuplicate = (path) => {
|
handleDuplicate = () => {
|
||||||
this.handlePatch(duplicate(this.state.data, path))
|
if (this.state.selection) {
|
||||||
|
this.handlePatch(duplicate(this.state.data, this.state.selection))
|
||||||
// apply focus to the duplicated node
|
// TODO: focus to duplicated selection
|
||||||
this.focusToNext(path)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRemove = (path) => {
|
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 = () => {
|
handleCut = () => {
|
||||||
const selection = this.state.selection
|
const selection = this.state.selection
|
||||||
if (selection && selection.start && selection.end) {
|
if (selection && selection.start && selection.end) {
|
||||||
|
|
|
@ -53,42 +53,42 @@ const CREATE_TYPE = {
|
||||||
duplicate: (path, events) => h('button', {
|
duplicate: (path, events) => h('button', {
|
||||||
key: 'duplicate',
|
key: 'duplicate',
|
||||||
className: MENU_ITEM_CLASS_NAME,
|
className: MENU_ITEM_CLASS_NAME,
|
||||||
onClick: () => events.onDuplicate(path),
|
onClick: () => events.onDuplicate(),
|
||||||
title: 'Duplicate'
|
title: 'Duplicate'
|
||||||
}, 'Duplicate'),
|
}, 'Duplicate'),
|
||||||
|
|
||||||
cut: (path, events) => h('button', {
|
cut: (path, events) => h('button', {
|
||||||
key: 'cut',
|
key: 'cut',
|
||||||
className: MENU_ITEM_CLASS_NAME,
|
className: MENU_ITEM_CLASS_NAME,
|
||||||
onClick: () => events.onCut(path),
|
onClick: () => events.onCut(),
|
||||||
title: 'Cut'
|
title: 'Cut'
|
||||||
}, 'Cut'),
|
}, 'Cut'),
|
||||||
|
|
||||||
copy: (path, events) => h('button', {
|
copy: (path, events) => h('button', {
|
||||||
key: 'copy',
|
key: 'copy',
|
||||||
className: MENU_ITEM_CLASS_NAME,
|
className: MENU_ITEM_CLASS_NAME,
|
||||||
onClick: () => events.onCopy(path),
|
onClick: () => events.onCopy(),
|
||||||
title: 'Copy'
|
title: 'Copy'
|
||||||
}, 'Copy'),
|
}, 'Copy'),
|
||||||
|
|
||||||
paste: (path, events) => h('button', {
|
paste: (path, events) => h('button', {
|
||||||
key: 'paste',
|
key: 'paste',
|
||||||
className: MENU_ITEM_CLASS_NAME,
|
className: MENU_ITEM_CLASS_NAME,
|
||||||
onClick: () => events.onPaste(path),
|
onClick: () => events.onPaste(),
|
||||||
title: 'Paste'
|
title: 'Paste'
|
||||||
}, 'Paste'),
|
}, 'Paste'),
|
||||||
|
|
||||||
remove: (path, events) => h('button', {
|
remove: (path, events) => h('button', {
|
||||||
key: 'remove',
|
key: 'remove',
|
||||||
className: MENU_ITEM_CLASS_NAME,
|
className: MENU_ITEM_CLASS_NAME,
|
||||||
onClick: () => events.onRemove(null), // do not pass path: we want to remove selection
|
onClick: () => events.onRemove(),
|
||||||
title: 'Remove'
|
title: 'Remove'
|
||||||
}, 'Remove'),
|
}, 'Remove'),
|
||||||
|
|
||||||
insertStructure: (path, events) => h('button', {
|
insertStructure: (path, events) => h('button', {
|
||||||
key: 'insertStructure',
|
key: 'insertStructure',
|
||||||
className: MENU_ITEM_CLASS_NAME,
|
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'
|
title: 'Insert a new object with the same data structure as the item above'
|
||||||
}, 'Insert structure'),
|
}, 'Insert structure'),
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue