file-tree-root.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import React, { useEffect, useState } 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. const FileTreeRoot = React.memo(function FileTreeRoot({
  19. refProviders,
  20. reindexReferences,
  21. setRefProviderEnabled,
  22. setStartedFreeTrial,
  23. onSelect,
  24. onInit,
  25. isConnected,
  26. }) {
  27. const { _id: projectId } = useProjectContext(projectContextPropTypes)
  28. const { fileTreeData } = useFileTreeData()
  29. const isReady = projectId && fileTreeData
  30. const [shouldShowVisualSelection, setShouldShowVisualSelection] =
  31. useState(true)
  32. const handleFileTreeClick = () => {
  33. setShouldShowVisualSelection(false)
  34. }
  35. useEffect(() => {
  36. if (isReady) onInit()
  37. }, [isReady, onInit])
  38. if (!isReady) return null
  39. return (
  40. <FileTreeContext
  41. refProviders={refProviders}
  42. setRefProviderEnabled={setRefProviderEnabled}
  43. setStartedFreeTrial={setStartedFreeTrial}
  44. setShouldShowVisualSelection={setShouldShowVisualSelection}
  45. reindexReferences={reindexReferences}
  46. onSelect={onSelect}
  47. >
  48. {isConnected ? null : <div className="disconnected-overlay" />}
  49. <FileTreeToolbar />
  50. <FileTreeContextMenu />
  51. {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
  52. <div
  53. className="file-tree-inner"
  54. onClick={handleFileTreeClick}
  55. data-testid="file-tree-inner"
  56. >
  57. <FileTreeRootFolder
  58. shouldShowVisualSelection={shouldShowVisualSelection}
  59. />
  60. </div>
  61. <FileTreeModalDelete />
  62. <FileTreeModalCreateFile />
  63. <FileTreeModalCreateFolder />
  64. <FileTreeModalError />
  65. </FileTreeContext>
  66. )
  67. })
  68. function FileTreeRootFolder({ shouldShowVisualSelection }) {
  69. useFileTreeSocketListener()
  70. const { fileTreeData } = useFileTreeData()
  71. const { isOver, dropRef } = useDroppable(fileTreeData._id)
  72. return (
  73. <>
  74. <FileTreeDraggablePreviewLayer isOver={isOver} />
  75. <FileTreeFolderList
  76. folders={fileTreeData.folders}
  77. docs={fileTreeData.docs}
  78. files={fileTreeData.fileRefs}
  79. classes={{ root: 'file-tree-list' }}
  80. dropRef={dropRef}
  81. isOver={isOver}
  82. shouldShowVisualSelection={shouldShowVisualSelection}
  83. >
  84. <li className="bottom-buffer" />
  85. </FileTreeFolderList>
  86. </>
  87. )
  88. }
  89. FileTreeRootFolder.propTypes = {
  90. shouldShowVisualSelection: PropTypes.bool,
  91. }
  92. FileTreeRoot.propTypes = {
  93. onSelect: PropTypes.func.isRequired,
  94. onInit: PropTypes.func.isRequired,
  95. isConnected: PropTypes.bool.isRequired,
  96. setRefProviderEnabled: PropTypes.func.isRequired,
  97. setStartedFreeTrial: PropTypes.func.isRequired,
  98. reindexReferences: PropTypes.func.isRequired,
  99. refProviders: PropTypes.object.isRequired,
  100. }
  101. const projectContextPropTypes = {
  102. _id: PropTypes.string.isRequired,
  103. }
  104. export default withErrorBoundary(FileTreeRoot, FileTreeError)