mutate-in-tree.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { findInTreeOrThrow } from './find-in-tree'
  2. export function renameInTree(tree, id, { newName }) {
  3. return mutateInTree(tree, id, (parent, entity, index) => {
  4. const newParent = Object.assign([], parent)
  5. const newEntity = {
  6. ...entity,
  7. name: newName,
  8. }
  9. newParent[index] = newEntity
  10. return newParent
  11. })
  12. }
  13. export function deleteInTree(tree, id) {
  14. return mutateInTree(tree, id, (parent, entity, index) => {
  15. return [...parent.slice(0, index), ...parent.slice(index + 1)]
  16. })
  17. }
  18. export function moveInTree(tree, entityId, toFolderId) {
  19. const found = findInTreeOrThrow(tree, entityId)
  20. if (found.parentFolderId === toFolderId) {
  21. // nothing to do (the entity was probably already moved)
  22. return tree
  23. }
  24. const newFileTreeData = deleteInTree(tree, entityId)
  25. return createEntityInTree(newFileTreeData, toFolderId, {
  26. ...found.entity,
  27. type: found.type,
  28. })
  29. }
  30. export function createEntityInTree(tree, parentFolderId, newEntityData) {
  31. const { type, ...newEntity } = newEntityData
  32. if (!type) throw new Error('Entity has no type')
  33. const entityType = `${type}s`
  34. return mutateInTree(tree, parentFolderId, (parent, folder, index) => {
  35. parent[index] = {
  36. ...folder,
  37. [entityType]: [...folder[entityType], newEntity],
  38. }
  39. return parent
  40. })
  41. }
  42. function mutateInTree(tree, id, mutationFunction) {
  43. if (!id || tree._id === id) {
  44. // covers the root folder case: it has no parent so in order to use
  45. // mutationFunction we pass an empty array as the parent and return the
  46. // mutated tree directly
  47. const [newTree] = mutationFunction([], tree, 0)
  48. return newTree
  49. }
  50. for (const entityType of ['docs', 'fileRefs', 'folders']) {
  51. for (let index = 0; index < tree[entityType].length; index++) {
  52. const entity = tree[entityType][index]
  53. if (entity._id === id) {
  54. return {
  55. ...tree,
  56. [entityType]: mutationFunction(tree[entityType], entity, index),
  57. }
  58. }
  59. }
  60. }
  61. const newFolders = tree.folders.map(folder =>
  62. mutateInTree(folder, id, mutationFunction)
  63. )
  64. return { ...tree, folders: newFolders }
  65. }