151 lines
4.3 KiB
TypeScript
151 lines
4.3 KiB
TypeScript
import Command from './command'
|
|
import history from '../history'
|
|
import { Data } from 'types'
|
|
import { uniqueArray } from 'utils'
|
|
import tld from 'utils/tld'
|
|
import { getShapeUtils } from 'state/shape-utils'
|
|
import storage from 'state/storage'
|
|
|
|
export default function moveToPageCommand(data: Data, newPageId: string): void {
|
|
const { currentPageId: oldPageId } = data
|
|
const oldPage = tld.getPage(data)
|
|
const selectedIds = [...tld.getSelectedIds(data)]
|
|
|
|
const idsToMove = uniqueArray(
|
|
...selectedIds.flatMap((id) => tld.getDocumentBranch(data, id))
|
|
)
|
|
|
|
const oldParentIds = Object.fromEntries(
|
|
idsToMove.map((id) => [id, oldPage.shapes[id].parentId])
|
|
)
|
|
|
|
// const selectedParents = uniqueArray(
|
|
// ...selectedIds.map((id) => getTopParentId(data, id))
|
|
// )
|
|
|
|
history.execute(
|
|
data,
|
|
new Command({
|
|
name: 'move_to_page',
|
|
category: 'canvas',
|
|
manualSelection: true,
|
|
do(data) {
|
|
const fromPageId = oldPageId
|
|
const toPageId = newPageId
|
|
|
|
const fromPage = tld.getPage(data)
|
|
|
|
// Get all of the selected shapes and their descendents
|
|
const shapesToMove = idsToMove.map((id) => fromPage.shapes[id])
|
|
|
|
shapesToMove.forEach((shape) => {
|
|
// If the shape is a parent of a group that isn't selected,
|
|
// remove the shape's id from its parent's children.
|
|
if (
|
|
shape.parentId !== fromPageId &&
|
|
!idsToMove.includes(shape.parentId)
|
|
) {
|
|
const parent = fromPage.shapes[shape.parentId]
|
|
|
|
getShapeUtils(parent).setProperty(
|
|
parent,
|
|
'children',
|
|
parent.children.filter((id) => id !== shape.id)
|
|
)
|
|
}
|
|
|
|
// Delete the shapes from the "from" page
|
|
delete fromPage.shapes[shape.id]
|
|
})
|
|
|
|
// Clear the current page state's selected ids
|
|
tld.setSelectedIds(data, [])
|
|
|
|
// Save the "from" page
|
|
storage.savePage(data, data.document.id, fromPageId)
|
|
|
|
// Load the "to" page
|
|
storage.loadPage(data, toPageId)
|
|
|
|
// The page we're moving the shapes to
|
|
const toPage = tld.getPage(data)
|
|
|
|
// Add all of the selected shapes to the "from" page.
|
|
shapesToMove.forEach((shape) => {
|
|
toPage.shapes[shape.id] = shape
|
|
})
|
|
|
|
// If a shape's parent isn't in the document, re-parent to the page.
|
|
shapesToMove.forEach((shape) => {
|
|
if (!toPage.shapes[shape.parentId]) {
|
|
getShapeUtils(shape).setProperty(shape, 'parentId', toPageId)
|
|
}
|
|
})
|
|
|
|
// Select the selected ids on the new page
|
|
tld.setSelectedIds(data, [...selectedIds])
|
|
|
|
// Move to the new page
|
|
data.currentPageId = toPageId
|
|
|
|
tld.setZoomCSS(tld.getPageState(data).camera.zoom)
|
|
},
|
|
undo(data) {
|
|
const fromPageId = newPageId
|
|
const toPageId = oldPageId
|
|
|
|
const fromPage = tld.getPage(data)
|
|
|
|
const shapesToMove = idsToMove.map((id) => fromPage.shapes[id])
|
|
|
|
shapesToMove.forEach((shape) => {
|
|
if (
|
|
shape.parentId !== fromPageId &&
|
|
!idsToMove.includes(shape.parentId)
|
|
) {
|
|
const parent = fromPage.shapes[shape.parentId]
|
|
|
|
getShapeUtils(parent).setProperty(
|
|
parent,
|
|
'children',
|
|
parent.children.filter((id) => id !== shape.id)
|
|
)
|
|
}
|
|
|
|
delete fromPage.shapes[shape.id]
|
|
})
|
|
|
|
tld.setSelectedIds(data, [])
|
|
|
|
storage.savePage(data, data.document.id, fromPageId)
|
|
|
|
storage.loadPage(data, toPageId)
|
|
|
|
const toPage = tld.getPage(data)
|
|
|
|
shapesToMove.forEach((shape) => {
|
|
toPage.shapes[shape.id] = shape
|
|
|
|
// Move shapes back to their old parent
|
|
const parentId = oldParentIds[shape.id]
|
|
getShapeUtils(shape).setProperty(shape, 'parentId', parentId)
|
|
|
|
// And add the shape back to the parent's children
|
|
if (parentId !== toPageId) {
|
|
const parent = toPage.shapes[parentId]
|
|
getShapeUtils(parent).setProperty(parent, 'children', [
|
|
...parent.children,
|
|
shape.id,
|
|
])
|
|
}
|
|
})
|
|
|
|
tld.setSelectedIds(data, [...selectedIds])
|
|
|
|
data.currentPageId = toPageId
|
|
|
|
tld.setZoomCSS(tld.getPageState(data).camera.zoom)
|
|
},
|
|
})
|
|
)
|
|
}
|