file-tree-mutable.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import React, { createContext, useReducer, useContext } from 'react'
  2. import PropTypes from 'prop-types'
  3. import {
  4. renameInTree,
  5. deleteInTree,
  6. moveInTree,
  7. createEntityInTree
  8. } from '../util/mutate-in-tree'
  9. const FileTreeMutableContext = createContext()
  10. const ACTION_TYPES = {
  11. RENAME: 'RENAME',
  12. DELETE: 'DELETE',
  13. MOVE: 'MOVE',
  14. CREATE_ENTITY: 'CREATE_ENTITY'
  15. }
  16. function fileTreeMutableReducer({ fileTreeData }, action) {
  17. switch (action.type) {
  18. case ACTION_TYPES.RENAME:
  19. return {
  20. fileTreeData: renameInTree(fileTreeData, action.id, {
  21. newName: action.newName
  22. })
  23. }
  24. case ACTION_TYPES.DELETE:
  25. return {
  26. fileTreeData: deleteInTree(fileTreeData, action.id)
  27. }
  28. case ACTION_TYPES.MOVE:
  29. return {
  30. fileTreeData: moveInTree(
  31. fileTreeData,
  32. action.entityId,
  33. action.toFolderId
  34. )
  35. }
  36. case ACTION_TYPES.CREATE_ENTITY:
  37. return {
  38. fileTreeData: createEntityInTree(
  39. fileTreeData,
  40. action.parentFolderId,
  41. action.entity
  42. )
  43. }
  44. default:
  45. throw new Error(`Unknown mutable file tree action type: ${action.type}`)
  46. }
  47. }
  48. export const FileTreeMutableProvider = function({ rootFolder, children }) {
  49. const [{ fileTreeData }, dispatch] = useReducer(fileTreeMutableReducer, {
  50. fileTreeData: rootFolder[0]
  51. })
  52. return (
  53. <FileTreeMutableContext.Provider value={{ fileTreeData, dispatch }}>
  54. {children}
  55. </FileTreeMutableContext.Provider>
  56. )
  57. }
  58. FileTreeMutableProvider.propTypes = {
  59. rootFolder: PropTypes.array.isRequired,
  60. children: PropTypes.oneOfType([
  61. PropTypes.arrayOf(PropTypes.node),
  62. PropTypes.node
  63. ]).isRequired
  64. }
  65. export function useFileTreeMutable() {
  66. const { fileTreeData, dispatch } = useContext(FileTreeMutableContext)
  67. function dispatchCreateFolder(parentFolderId, entity) {
  68. entity.type = 'folder'
  69. dispatch({
  70. type: ACTION_TYPES.CREATE_ENTITY,
  71. parentFolderId,
  72. entity
  73. })
  74. }
  75. function dispatchCreateDoc(parentFolderId, entity) {
  76. entity.type = 'doc'
  77. dispatch({
  78. type: ACTION_TYPES.CREATE_ENTITY,
  79. parentFolderId,
  80. entity
  81. })
  82. }
  83. function dispatchCreateFile(parentFolderId, entity) {
  84. entity.type = 'fileRef'
  85. dispatch({
  86. type: ACTION_TYPES.CREATE_ENTITY,
  87. parentFolderId,
  88. entity
  89. })
  90. }
  91. function dispatchRename(id, newName) {
  92. dispatch({
  93. type: ACTION_TYPES.RENAME,
  94. newName,
  95. id
  96. })
  97. }
  98. function dispatchDelete(id) {
  99. dispatch({ type: ACTION_TYPES.DELETE, id })
  100. }
  101. function dispatchMove(entityId, toFolderId) {
  102. dispatch({ type: ACTION_TYPES.MOVE, entityId, toFolderId })
  103. }
  104. return {
  105. fileTreeData,
  106. dispatchRename,
  107. dispatchDelete,
  108. dispatchMove,
  109. dispatchCreateFolder,
  110. dispatchCreateDoc,
  111. dispatchCreateFile
  112. }
  113. }