Merge pull request #15444 from overleaf/td-remove-root-folder-scope-use

Remove use of root folder scope in figure modal

GitOrigin-RevId: d07247b644d312ef711f5601d3c10a3274e43416
This commit is contained in:
Tim Down 2023-10-26 11:01:27 +01:00 committed by Copybot
parent 13f246a85e
commit c34c95b46d
9 changed files with 101 additions and 66 deletions

View file

@ -6,9 +6,9 @@ import {
useState,
} from 'react'
import { File, FileOrDirectory } from '../../utils/file'
import useScopeValue from '../../../../shared/hooks/use-scope-value'
import { Alert } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { useCurrentProjectFolders } from '@/features/source-editor/hooks/use-current-project-folders'
type FileNameInputProps = Omit<
DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
@ -57,7 +57,7 @@ export const FileNameInput = ({
}: FileNameInputProps) => {
const { t } = useTranslation()
const [overlap, setOverlap] = useState<boolean>(false)
const [rootFolder] = useScopeValue<FileOrDirectory>('rootFolder')
const { rootFolder } = useCurrentProjectFolders()
const { value } = props
useEffect(() => {

View file

@ -2,7 +2,7 @@ import { useCallback } from 'react'
import { FileNameInput } from './file-name-input'
import { File } from '../../utils/file'
import { Select } from '../../../../shared/components/select'
import { useCurrentProjectFolders } from '../../hooks/useCurrentProjectFolders'
import { useCurrentProjectFolders } from '../../hooks/use-current-project-folders'
import { useTranslation } from 'react-i18next'
export const FileRelocator = ({
@ -25,7 +25,7 @@ export const FileRelocator = ({
setNameDirty: (nameDirty: boolean) => void
}) => {
const { t } = useTranslation()
const [folders, rootFile] = useCurrentProjectFolders()
const { folders, rootFile } = useCurrentProjectFolders()
const nameChanged = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {

View file

@ -14,7 +14,7 @@ import {
useProjectOutputFiles,
} from '../../../../file-tree/hooks/use-project-output-files'
import { Button } from 'react-bootstrap'
import { useCurrentProjectFolders } from '../../../hooks/useCurrentProjectFolders'
import { useCurrentProjectFolders } from '../../../hooks/use-current-project-folders'
import { File, isImageEntity } from '../../../utils/file'
import { postJSON } from '../../../../../infrastructure/fetch-json'
import { useProjectContext } from '../../../../../shared/context/project-context'
@ -39,7 +39,7 @@ export const FigureModalOtherProjectSource: FC = () => {
const [nameDirty, setNameDirty] = useState<boolean>(false)
const [name, setName] = useState<string>('')
const [folder, setFolder] = useState<File | null>(null)
const [, rootFile] = useCurrentProjectFolders()
const { rootFile } = useCurrentProjectFolders()
const [file, setFile] = useState<OutputEntity | Entity | null>(null)
const FileSelector = usingOutputFiles
? SelectFromProjectOutputFiles

View file

@ -1,13 +1,13 @@
import { FC, useMemo } from 'react'
import useScopeValue from '../../../../../shared/hooks/use-scope-value'
import { Select } from '../../../../../shared/components/select'
import { useFigureModalContext } from '../figure-modal-context'
import { FileOrDirectory, filterFiles, isImageFile } from '../../../utils/file'
import { filterFiles, isImageFile } from '../../../utils/file'
import { useTranslation } from 'react-i18next'
import { useCurrentProjectFolders } from '@/features/source-editor/hooks/use-current-project-folders'
export const FigureModalCurrentProjectSource: FC = () => {
const { t } = useTranslation()
const [rootFolder] = useScopeValue<FileOrDirectory>('rootFolder')
const { rootFolder } = useCurrentProjectFolders()
const files = useMemo(
() => filterFiles(rootFolder)?.filter(isImageFile),
[rootFolder]

View file

@ -1,6 +1,6 @@
import { FC, useCallback, useEffect, useState } from 'react'
import { useFigureModalContext } from '../figure-modal-context'
import { useCurrentProjectFolders } from '../../../hooks/useCurrentProjectFolders'
import { useCurrentProjectFolders } from '../../../hooks/use-current-project-folders'
import { File } from '../../../utils/file'
import { Dashboard, useUppy } from '@uppy/react'
import '@uppy/core/dist/style.css'
@ -33,7 +33,7 @@ export const FigureModalUploadFileSource: FC = () => {
const view = useCodeMirrorViewContext()
const { dispatch, pastedImageData } = useFigureModalContext()
const { _id: projectId } = useProjectContext()
const [, rootFolder] = useCurrentProjectFolders()
const { rootFile } = useCurrentProjectFolders()
const [folder, setFolder] = useState<File | null>(null)
const [nameDirty, setNameDirty] = useState<boolean>(false)
// Files are immutable, so this will point to a (possibly) old version of the file
@ -77,7 +77,7 @@ export const FigureModalUploadFileSource: FC = () => {
if (!uploadResult.successful) {
throw new Error('Upload failed')
}
const uploadFolder = folder ?? rootFolder
const uploadFolder = folder ?? rootFile
return uploadFolder.path === '' && uploadFolder.name === 'rootFolder'
? `${name}`
: `${uploadFolder.path ? uploadFolder.path + '/' : ''}${
@ -86,7 +86,7 @@ export const FigureModalUploadFileSource: FC = () => {
},
})
},
[dispatch, rootFolder, uppy, view]
[dispatch, rootFile, uppy, view]
)
useEffect(() => {
@ -130,7 +130,7 @@ export const FigureModalUploadFileSource: FC = () => {
xhrUpload: {
...(file as any).xhrUpload,
endpoint: `/project/${projectId}/upload?folder_id=${
(folder ?? rootFolder).id
(folder ?? rootFile).id
}`,
},
})
@ -179,7 +179,7 @@ export const FigureModalUploadFileSource: FC = () => {
}, [
uppy,
folder,
rootFolder,
rootFile,
name,
nameDirty,
dispatchUploadAction,
@ -245,7 +245,7 @@ export const FigureModalUploadFileSource: FC = () => {
name={name}
nameDisabled={!file && !nameDirty}
onFolderChanged={item =>
dispatchUploadAction(name, file, item ?? rootFolder)
dispatchUploadAction(name, file, item ?? rootFile)
}
onNameChanged={name => dispatchUploadAction(name, file, folder)}
setFolder={setFolder}

View file

@ -3,7 +3,7 @@ import { useFigureModalContext } from '../figure-modal-context'
import { postJSON } from '../../../../../infrastructure/fetch-json'
import { useProjectContext } from '../../../../../shared/context/project-context'
import { File } from '../../../utils/file'
import { useCurrentProjectFolders } from '../../../hooks/useCurrentProjectFolders'
import { useCurrentProjectFolders } from '../../../hooks/use-current-project-folders'
import { FileRelocator } from '../file-relocator'
import { useTranslation } from 'react-i18next'
import { useCodeMirrorViewContext } from '../../codemirror-editor'
@ -44,7 +44,7 @@ export const FigureModalUrlSource: FC = () => {
const [nameDirty, setNameDirty] = useState<boolean>(false)
const [name, setName] = useState<string>('')
const { _id: projectId } = useProjectContext()
const [, rootFile] = useCurrentProjectFolders()
const { rootFile } = useCurrentProjectFolders()
const [folder, setFolder] = useState<File>(rootFile)
const { dispatch, getPath } = useFigureModalContext()

View file

@ -0,0 +1,51 @@
import { useMemo } from 'react'
import { File, FileOrDirectory, filterFolders } from '../utils/file'
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import { Folder } from '../../../../../types/folder'
import { Doc } from '../../../../../types/doc'
import { FileRef } from '../../../../../types/file-ref'
function docAdapter(doc: Doc): FileOrDirectory {
return {
id: doc._id,
name: doc.name,
type: 'doc',
}
}
function fileRefAdapter(fileRef: FileRef): FileOrDirectory {
return {
id: fileRef._id,
name: fileRef.name,
type: 'file',
}
}
function folderAdapter(folder: Folder): FileOrDirectory {
return {
id: folder._id,
name: folder.name,
type: 'folder',
children: folder.docs
.map(docAdapter)
.concat(
folder.fileRefs.map(fileRefAdapter),
folder.folders.map(folderAdapter)
),
}
}
export const useCurrentProjectFolders: () => {
folders: File[] | undefined
rootFile: File
rootFolder: FileOrDirectory
} = () => {
const { fileTreeData } = useFileTreeData()
return useMemo(() => {
const rootFolder = folderAdapter(fileTreeData)
const rootFile = { ...rootFolder, path: '' }
const folders = filterFolders(rootFolder)
return { folders, rootFile, rootFolder }
}, [fileTreeData])
}

View file

@ -1,13 +0,0 @@
import { useMemo } from 'react'
import useScopeValue from '../../../shared/hooks/use-scope-value'
import { File, FileOrDirectory, filterFolders } from '../utils/file'
export const useCurrentProjectFolders: () => [
File[] | undefined,
File
] = () => {
const [rootFolder] = useScopeValue<FileOrDirectory>('rootFolder')
const rootFile = { ...rootFolder, path: '' }
const folders = useMemo(() => filterFolders(rootFolder), [rootFolder])
return [folders, rootFile]
}

View file

@ -1,45 +1,12 @@
import { docId, mockDoc } from './mock-doc'
import { Folder } from '../../../../../types/folder'
import { sleep } from '../../../helpers/sleep'
import { Folder } from '../../../../../types/folder'
export const rootFolderId = '012345678901234567890123'
export const figuresFolderId = '123456789012345678901234'
export const figureId = '234567890123456789012345'
export const mockScope = (content?: string) => {
return {
rootFolder: {
id: rootFolderId,
name: 'rootFolder',
selected: false,
children: [
{
id: docId,
name: 'test.tex',
selected: false,
type: 'doc',
},
{
id: figuresFolderId,
name: 'figures',
selected: false,
type: 'folder',
children: [
{
id: figureId,
name: 'frog.jpg',
selected: false,
type: 'file',
},
{
id: 'fake-figure-id',
name: 'unicorn.png',
selected: false,
type: 'file',
},
],
},
],
},
settings: {
fontSize: 12,
fontFamily: 'monaco',
@ -66,7 +33,37 @@ export const mockScope = (content?: string) => {
_id: 'test-project',
name: 'Test Project',
spellCheckLanguage: 'en',
rootFolder: [] as Folder[],
rootFolder: [
{
_id: rootFolderId,
name: 'rootFolder',
docs: [
{
_id: docId,
name: 'test.tex',
},
],
folders: [
{
_id: figuresFolderId,
name: 'figures',
docs: [],
folders: [],
fileRefs: [
{
_id: figureId,
name: 'frog.jpg',
},
{
_id: 'fake-figure-id',
name: 'unicorn.png',
},
],
},
],
fileRefs: [],
},
] as Folder[],
features: {
trackChanges: true,
},