You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

move-to-page.ts 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import Command from './command'
  2. import history from '../history'
  3. import { Data } from 'types'
  4. import {
  5. getDocumentBranch,
  6. getPage,
  7. getPageState,
  8. getSelectedIds,
  9. setToArray,
  10. uniqueArray,
  11. } from 'utils'
  12. import { getShapeUtils } from 'state/shape-utils'
  13. import storage from 'state/storage'
  14. export default function moveToPageCommand(data: Data, newPageId: string): void {
  15. const { currentPageId: oldPageId } = data
  16. const oldPage = getPage(data)
  17. const selectedIds = setToArray(getSelectedIds(data))
  18. const idsToMove = uniqueArray(
  19. ...selectedIds.flatMap((id) => getDocumentBranch(data, id))
  20. )
  21. const oldParentIds = Object.fromEntries(
  22. idsToMove.map((id) => [id, oldPage.shapes[id].parentId])
  23. )
  24. // const selectedParents = uniqueArray(
  25. // ...selectedIds.map((id) => getTopParentId(data, id))
  26. // )
  27. history.execute(
  28. data,
  29. new Command({
  30. name: 'move_to_page',
  31. category: 'canvas',
  32. manualSelection: true,
  33. do(data) {
  34. const fromPageId = oldPageId
  35. const toPageId = newPageId
  36. const fromPage = getPage(data, fromPageId)
  37. // Get all of the selected shapes and their descendents
  38. const shapesToMove = idsToMove.map((id) => fromPage.shapes[id])
  39. shapesToMove.forEach((shape) => {
  40. // If the shape is a parent of a group that isn't selected,
  41. // remove the shape's id from its parent's children.
  42. if (
  43. shape.parentId !== fromPageId &&
  44. !idsToMove.includes(shape.parentId)
  45. ) {
  46. const parent = fromPage.shapes[shape.parentId]
  47. getShapeUtils(parent).setProperty(
  48. parent,
  49. 'children',
  50. parent.children.filter((id) => id !== shape.id)
  51. )
  52. }
  53. // Delete the shapes from the "from" page
  54. delete fromPage.shapes[shape.id]
  55. })
  56. // Clear the current page state's selected ids
  57. getPageState(data, fromPageId).selectedIds.clear()
  58. // Save the "from" page
  59. storage.savePage(data, data.document.id, fromPageId)
  60. // Load the "to" page
  61. storage.loadPage(data, toPageId)
  62. // The page we're moving the shapes to
  63. const toPage = getPage(data, toPageId)
  64. // Add all of the selected shapes to the "from" page.
  65. shapesToMove.forEach((shape) => {
  66. toPage.shapes[shape.id] = shape
  67. })
  68. // If a shape's parent isn't in the document, re-parent to the page.
  69. shapesToMove.forEach((shape) => {
  70. if (!toPage.shapes[shape.parentId]) {
  71. getShapeUtils(shape).setProperty(shape, 'parentId', toPageId)
  72. }
  73. })
  74. // Select the selected ids on the new page
  75. getPageState(data, toPageId).selectedIds = new Set(selectedIds)
  76. // Move to the new page
  77. data.currentPageId = toPageId
  78. },
  79. undo(data) {
  80. const fromPageId = newPageId
  81. const toPageId = oldPageId
  82. const fromPage = getPage(data, fromPageId)
  83. const shapesToMove = idsToMove.map((id) => fromPage.shapes[id])
  84. shapesToMove.forEach((shape) => {
  85. if (
  86. shape.parentId !== fromPageId &&
  87. !idsToMove.includes(shape.parentId)
  88. ) {
  89. const parent = fromPage.shapes[shape.parentId]
  90. getShapeUtils(parent).setProperty(
  91. parent,
  92. 'children',
  93. parent.children.filter((id) => id !== shape.id)
  94. )
  95. }
  96. delete fromPage.shapes[shape.id]
  97. })
  98. getPageState(data, fromPageId).selectedIds.clear()
  99. storage.savePage(data, data.document.id, fromPageId)
  100. storage.loadPage(data, toPageId)
  101. const toPage = getPage(data, toPageId)
  102. shapesToMove.forEach((shape) => {
  103. toPage.shapes[shape.id] = shape
  104. // Move shapes back to their old parent
  105. const parentId = oldParentIds[shape.id]
  106. getShapeUtils(shape).setProperty(shape, 'parentId', parentId)
  107. // And add the shape back to the parent's children
  108. if (parentId !== toPageId) {
  109. const parent = toPage.shapes[parentId]
  110. getShapeUtils(parent).setProperty(parent, 'children', [
  111. ...parent.children,
  112. shape.id,
  113. ])
  114. }
  115. })
  116. getPageState(data, toPageId).selectedIds = new Set(selectedIds)
  117. data.currentPageId = toPageId
  118. },
  119. })
  120. )
  121. }