overleaf/services/web/frontend/js/features/file-tree/util/mutate-in-tree.js

75 lines
2.1 KiB
JavaScript
Raw Normal View History

import { findInTreeOrThrow } from './find-in-tree'
export function renameInTree(tree, id, { newName }) {
return mutateInTree(tree, id, (parent, entity, index) => {
const newParent = Object.assign([], parent)
const newEntity = {
...entity,
name: newName,
}
newParent[index] = newEntity
return newParent
})
}
export function deleteInTree(tree, id) {
return mutateInTree(tree, id, (parent, entity, index) => {
return [...parent.slice(0, index), ...parent.slice(index + 1)]
})
}
export function moveInTree(tree, entityId, toFolderId) {
const found = findInTreeOrThrow(tree, entityId)
if (found.parentFolderId === toFolderId) {
// nothing to do (the entity was probably already moved)
return tree
}
const newFileTreeData = deleteInTree(tree, entityId)
return createEntityInTree(newFileTreeData, toFolderId, {
...found.entity,
type: found.type,
})
}
export function createEntityInTree(tree, parentFolderId, newEntityData) {
const { type, ...newEntity } = newEntityData
if (!type) throw new Error('Entity has no type')
const entityType = `${type}s`
return mutateInTree(tree, parentFolderId, (parent, folder, index) => {
parent[index] = {
...folder,
[entityType]: [...folder[entityType], newEntity],
}
return parent
})
}
function mutateInTree(tree, id, mutationFunction) {
if (!id || tree._id === id) {
// covers the root folder case: it has no parent so in order to use
// mutationFunction we pass an empty array as the parent and return the
// mutated tree directly
const [newTree] = mutationFunction([], tree, 0)
return newTree
}
for (const entityType of ['docs', 'fileRefs', 'folders']) {
for (let index = 0; index < tree[entityType].length; index++) {
const entity = tree[entityType][index]
if (entity._id === id) {
return {
...tree,
[entityType]: mutationFunction(tree[entityType], entity, index),
}
}
}
}
const newFolders = tree.folders.map(folder =>
mutateInTree(folder, id, mutationFunction)
)
return { ...tree, folders: newFolders }
}