file-tree-root.jsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import React, { useEffect } from 'react'
  2. import PropTypes from 'prop-types'
  3. import withErrorBoundary from '../../../infrastructure/error-boundary'
  4. import { useProjectContext } from '../../../shared/context/project-context'
  5. import { useFileTreeData } from '../../../shared/context/file-tree-data-context'
  6. import FileTreeContext from './file-tree-context'
  7. import FileTreeDraggablePreviewLayer from './file-tree-draggable-preview-layer'
  8. import FileTreeFolderList from './file-tree-folder-list'
  9. import FileTreeToolbar from './file-tree-toolbar'
  10. import FileTreeModalDelete from './modals/file-tree-modal-delete'
  11. import FileTreeModalCreateFolder from './modals/file-tree-modal-create-folder'
  12. import FileTreeModalError from './modals/file-tree-modal-error'
  13. import FileTreeContextMenu from './file-tree-context-menu'
  14. import FileTreeError from './file-tree-error'
  15. import { useDroppable } from '../contexts/file-tree-draggable'
  16. import { useFileTreeSocketListener } from '../hooks/file-tree-socket-listener'
  17. import FileTreeModalCreateFile from './modals/file-tree-modal-create-file'
  18. import FileTreeInner from './file-tree-inner'
  19. import { useDragLayer } from 'react-dnd'
  20. import classnames from 'classnames'
  21. const FileTreeRoot = React.memo(function FileTreeRoot({
  22. refProviders,
  23. reindexReferences,
  24. setRefProviderEnabled,
  25. setStartedFreeTrial,
  26. onSelect,
  27. onInit,
  28. onDelete,
  29. isConnected,
  30. }) {
  31. const { _id: projectId } = useProjectContext(projectContextPropTypes)
  32. const { fileTreeData } = useFileTreeData()
  33. const isReady = Boolean(projectId && fileTreeData)
  34. useEffect(() => {
  35. if (isReady) onInit()
  36. }, [isReady, onInit])
  37. if (!isReady) return null
  38. return (
  39. <FileTreeContext
  40. refProviders={refProviders}
  41. setRefProviderEnabled={setRefProviderEnabled}
  42. setStartedFreeTrial={setStartedFreeTrial}
  43. reindexReferences={reindexReferences}
  44. onSelect={onSelect}
  45. >
  46. {isConnected ? null : <div className="disconnected-overlay" />}
  47. <FileTreeToolbar />
  48. <FileTreeContextMenu />
  49. <FileTreeInner>
  50. <FileTreeRootFolder onDelete={onDelete} />
  51. </FileTreeInner>
  52. <FileTreeModalDelete />
  53. <FileTreeModalCreateFile />
  54. <FileTreeModalCreateFolder />
  55. <FileTreeModalError />
  56. </FileTreeContext>
  57. )
  58. })
  59. function FileTreeRootFolder({ onDelete }) {
  60. useFileTreeSocketListener(onDelete)
  61. const { fileTreeData } = useFileTreeData()
  62. const { isOver, dropRef } = useDroppable(fileTreeData._id)
  63. const dragLayer = useDragLayer(monitor => ({
  64. isDragging: monitor.isDragging(),
  65. item: monitor.getItem(),
  66. clientOffset: monitor.getClientOffset(),
  67. }))
  68. return (
  69. <>
  70. <FileTreeDraggablePreviewLayer isOver={isOver} {...dragLayer} />
  71. <FileTreeFolderList
  72. folders={fileTreeData.folders}
  73. docs={fileTreeData.docs}
  74. files={fileTreeData.fileRefs}
  75. classes={{
  76. root: classnames('file-tree-list', {
  77. 'file-tree-dragging': dragLayer.isDragging,
  78. }),
  79. }}
  80. dropRef={dropRef}
  81. dataTestId="file-tree-list-root"
  82. />
  83. </>
  84. )
  85. }
  86. FileTreeRootFolder.propTypes = {
  87. onDelete: PropTypes.func,
  88. }
  89. FileTreeRoot.propTypes = {
  90. onSelect: PropTypes.func.isRequired,
  91. onInit: PropTypes.func.isRequired,
  92. onDelete: PropTypes.func,
  93. isConnected: PropTypes.bool.isRequired,
  94. setRefProviderEnabled: PropTypes.func.isRequired,
  95. setStartedFreeTrial: PropTypes.func.isRequired,
  96. reindexReferences: PropTypes.func.isRequired,
  97. refProviders: PropTypes.object.isRequired,
  98. }
  99. const projectContextPropTypes = {
  100. _id: PropTypes.string.isRequired,
  101. }
  102. export default withErrorBoundary(FileTreeRoot, FileTreeError)