From 8acbafcb05dffcf226fe615e717c61c2858a0054 Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:02:30 +0000 Subject: [PATCH] Merge pull request #22979 from overleaf/dp-file-tree-in-editor Add file tree to editor GitOrigin-RevId: 493ecf88d632bed92c6b2b5ae2e5c0b7eef968cc --- ...alSymbolsRoundedUnfilledPartialSlice.woff2 | Bin 3120 -> 3596 bytes .../material-symbols/unfilled-symbols.mjs | 3 + .../file-tree/components/file-tree-doc.tsx | 56 +--------- .../components/file-tree-folder-icons.tsx | 77 +++++++++++++ .../components/file-tree-folder-list.tsx | 58 +++++----- .../file-tree/components/file-tree-folder.tsx | 55 ++-------- .../file-tree/components/file-tree-icon.tsx | 81 ++++++++++++++ .../file-tree/util/icon-type-from-name.ts | 20 ++++ .../features/ide-redesign/components/rail.tsx | 18 ++-- .../bootstrap-5/pages/editor/file-tree.scss | 101 +++++++++++++++++- .../bootstrap-5/pages/editor/toolbar.scss | 1 + .../components/file-tree-root.spec.tsx | 2 +- 12 files changed, 333 insertions(+), 139 deletions(-) create mode 100644 services/web/frontend/js/features/file-tree/components/file-tree-folder-icons.tsx create mode 100644 services/web/frontend/js/features/file-tree/components/file-tree-icon.tsx diff --git a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 index 68ddbc999db5c6183cfc0521ce266eb957104d1c..0bfc703101a2f380e803e1d424809784d94923e8 100644 GIT binary patch literal 3596 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 S>#KFoepyT|y`ZcG0000|!_IsF literal 3120 zcmV-04A1j-Pew8T0RR9101Pky4gdfE02d$t01Mav0RR9100000000000000000000 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 { - const { t } = useTranslation() - - const className = classnames('file-tree-icon', { - 'linked-file-icon': isLinkedFile, - }) - - return ( - <> -   - - - {isLinkedFile && ( - - )} - - } - bs5={ - <> - - {isLinkedFile && ( - - )} - - } - /> - - ) -} - export default FileTreeDoc diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-folder-icons.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-folder-icons.tsx new file mode 100644 index 0000000000..9ee8f7229f --- /dev/null +++ b/services/web/frontend/js/features/file-tree/components/file-tree-folder-icons.tsx @@ -0,0 +1,77 @@ +import { useTranslation } from 'react-i18next' +import Icon from '../../../shared/components/icon' +import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' +import MaterialIcon from '@/shared/components/material-icon' +import { useFeatureFlag } from '@/shared/context/split-test-context' + +function FileTreeFolderIcons({ + expanded, + onExpandCollapseClick, +}: { + expanded: boolean + onExpandCollapseClick: () => void +}) { + const { t } = useTranslation() + + const newEditor = useFeatureFlag('editor-redesign') + + if (newEditor) { + return ( + <> + + + ) + } + + return ( + + + + + } + bs5={ + <> + + + + } + /> + ) +} + +export default FileTreeFolderIcons diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.tsx index 7641ad906c..1706554960 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.tsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-folder-list.tsx @@ -32,39 +32,47 @@ function FileTreeFolderList({ return (
    - {folders.sort(compareFunction).map(folder => { - return ( - - ) - })} - {docsAndFiles.sort(compareFunction).map(doc => { - if ('isFile' in doc) { +
    + {folders.sort(compareFunction).map(folder => { return ( - ) - } + })} + {docsAndFiles.sort(compareFunction).map(doc => { + if ('isFile' in doc) { + return ( + + ) + } - return - })} - {children} + return + })} + {children} +
) } diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-folder.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-folder.tsx index abcb6474cd..5ad8481349 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-folder.tsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-folder.tsx @@ -1,8 +1,6 @@ import { useEffect } from 'react' -import { useTranslation } from 'react-i18next' import classNames from 'classnames' -import Icon from '../../../shared/components/icon' import { useFileTreeSelectable, useSelectableEntity, @@ -12,11 +10,10 @@ import { useDroppable } from '../contexts/file-tree-draggable' import FileTreeItemInner from './file-tree-item/file-tree-item-inner' import FileTreeFolderList from './file-tree-folder-list' import usePersistedState from '../../../shared/hooks/use-persisted-state' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import MaterialIcon from '@/shared/components/material-icon' import { Folder } from '../../../../../types/folder' import { Doc } from '../../../../../types/doc' import { FileRef } from '../../../../../types/file-ref' +import FileTreeFolderIcons from './file-tree-folder-icons' function FileTreeFolder({ name, @@ -31,8 +28,6 @@ function FileTreeFolder({ docs: Doc[] files: FileRef[] }) { - const { t } = useTranslation() - const { isSelected, props: selectableEntityProps } = useSelectableEntity( id, 'folder' @@ -58,47 +53,6 @@ function FileTreeFolder({ const { isOver: isOverRoot, dropRef: dropRefRoot } = useDroppable(id) const { isOver: isOverList, dropRef: dropRefList } = useDroppable(id) - const icons = ( - - - - - } - bs5={ - <> - - - - } - /> - ) - return ( <>
  • + } />
  • {expanded ? ( diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-icon.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-icon.tsx new file mode 100644 index 0000000000..d9e78e6675 --- /dev/null +++ b/services/web/frontend/js/features/file-tree/components/file-tree-icon.tsx @@ -0,0 +1,81 @@ +import { useTranslation } from 'react-i18next' +import Icon from '../../../shared/components/icon' +import iconTypeFromName, { + newEditorIconTypeFromName, +} from '../util/icon-type-from-name' +import classnames from 'classnames' +import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' +import MaterialIcon from '@/shared/components/material-icon' +import { useFeatureFlag } from '@/shared/context/split-test-context' + +function FileTreeIcon({ + isLinkedFile, + name, +}: { + name: string + isLinkedFile?: boolean +}) { + const { t } = useTranslation() + + const className = classnames('file-tree-icon', { + 'linked-file-icon': isLinkedFile, + }) + + const newEditor = useFeatureFlag('editor-redesign') + + if (newEditor) { + return ( + <> + + {isLinkedFile && ( + + )} + + ) + } + + return ( + <> +   + + + {isLinkedFile && ( + + )} + + } + bs5={ + <> + + {isLinkedFile && ( + + )} + + } + /> + + ) +} + +export default FileTreeIcon diff --git a/services/web/frontend/js/features/file-tree/util/icon-type-from-name.ts b/services/web/frontend/js/features/file-tree/util/icon-type-from-name.ts index 68eb393fec..1df52b8f70 100644 --- a/services/web/frontend/js/features/file-tree/util/icon-type-from-name.ts +++ b/services/web/frontend/js/features/file-tree/util/icon-type-from-name.ts @@ -1,4 +1,24 @@ import { isBootstrap5 } from '@/features/utils/bootstrap-5' +import { AvailableUnfilledIcon } from '@/shared/components/material-icon' + +// TODO ide-redesign-cleanup: Make this the default export and remove the legacy version +export const newEditorIconTypeFromName = ( + name: string +): AvailableUnfilledIcon => { + let ext = name.split('.').pop() + ext = ext ? ext.toLowerCase() : ext + + if (ext && ['png', 'pdf', 'jpg', 'jpeg', 'gif'].includes(ext)) { + return 'image' + } else if (ext && ['csv', 'xls', 'xlsx'].includes(ext)) { + return 'table_chart' + } else if (ext && ['py', 'r'].includes(ext)) { + return 'code' + } else if (ext && ['bib'].includes(ext)) { + return 'book_5' + } + return 'description' +} export default function iconTypeFromName(name: string): string { let ext = name.split('.').pop() diff --git a/services/web/frontend/js/features/ide-redesign/components/rail.tsx b/services/web/frontend/js/features/ide-redesign/components/rail.tsx index e9d21af972..a5ffa47089 100644 --- a/services/web/frontend/js/features/ide-redesign/components/rail.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/rail.tsx @@ -5,6 +5,7 @@ import MaterialIcon, { } from '@/shared/components/material-icon' import { Panel } from 'react-resizable-panels' import { useLayoutContext } from '@/shared/context/layout-context' +import { FileTree } from '@/features/ide-react/components/file-tree' type RailElement = { icon: AvailableUnfilledIcon @@ -26,7 +27,12 @@ const RAIL_TABS: RailElement[] = [ { key: 'file-tree', icon: 'description', - component: <>File tree, + component: ( + <> + {/* TODO: add panel for file outline */} + + + ), }, { key: 'integrations', @@ -127,11 +133,11 @@ const RailTab = ({ }) => { return ( - + {active ? ( + + ) : ( + + )} ) } diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/file-tree.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/file-tree.scss index efff19c941..5368b69dc8 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/file-tree.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/file-tree.scss @@ -5,8 +5,11 @@ --file-tree-bg: var(--bg-dark-tertiary); --file-tree-item-selected-color: var(--content-primary-dark); --file-tree-item-dragging-bg: #{rgb($bg-dark-secondary, 0.9)}; + --file-tree-item-dragging-color: var(--content-primary-dark); --file-tree-item-dragging-preview-bg: #{rgb($bg-accent-01, 0.6)}; + --file-tree-item-dragging-preview-colour: var(--content-primary-dark); --file-tree-line-height: 2.05; + --file-tree-icon-colour: var(--content-disabled); } @include theme('light') { @@ -15,6 +18,96 @@ --file-tree-bg: var(--bg-light-primary); --file-tree-item-selected-color: var(--bg-light-primary); --file-tree-item-dragging-bg: #{rgb($bg-light-tertiary, 0.9)}; + --file-tree-item-dragging-color: var(--content-secondary); + --file-tree-item-dragging-preview-colour: var(--bg-light-primary); +} + +// TODO ide-redesign-cleanup: Replace the existing styling with these overrides. +.ide-redesign-main { + --file-tree-item-hover-bg: var(--bg-light-secondary); + --file-tree-item-selected-bg: var(--bg-dark-primary); + --file-tree-item-selected-color: var(--white); + --file-tree-item-color: var(--content-primary); + --file-tree-bg: var(--white); + --file-tree-icon-colour: var(--content-primary); + --file-tree-item-dragging-bg: #{rgb($bg-dark-primary, 0.9)}; + --file-tree-item-dragging-color: var(--white); + --file-tree-item-dragging-preview-bg: #{rgb($bg-light-secondary, 0.6)}; + --file-tree-item-dragging-preview-colour: #{rgb($content-primary, 0.6)}; + + .file-tree { + background-color: var(--file-tree-bg); + } + + .file-tree ul.file-tree-list { + margin: var(--spacing-02); + } + + .file-tree-folder-list { + border-left: 1px solid + color-mix(in srgb, var(--border-primary) 24%, transparent); + margin-left: 14px !important; + + &.file-tree-list { + border-left: none; + margin-left: var(--spacing-02) !important; + + > .file-tree-folder-list-inner { + margin-left: 0; + } + } + } + + .file-tree-folder-list-inner { + margin-left: 10px; + display: flex; + flex-direction: column; + gap: var(--spacing-02); + } + + .item-name-button, + .folder-expand-collapse-button { + display: flex; + align-items: center; + height: 20px !important; + } + + .file-tree ul.file-tree-list li .material-symbols.file-tree-expand-icon { + margin-left: 0; + } + + .file-tree ul.file-tree-list li .material-symbols.file-tree-icon { + margin-left: 0; + margin-right: 0; + } + + // TODO ide-redesign-cleanup: Remove the !important overrides once + // we have replaced the default styling + .linked-file-highlight { + background-color: var(--file-tree-bg) !important; + color: var(--file-tree-icon-colour) !important; + left: 14px !important; + } + + .entity-name { + color: var(--file-tree-item-color); + border-radius: var(--border-radius-base); + padding: var(--spacing-02); + + // TODO ide-redesign-cleanup: This is here to override the fake-full-width-bg + // mixin. We can just remove that mixin when we clean this up. + &::before { + content: none !important; + } + } + + .item-name-button { + margin-left: var(--spacing-02); + } + + .dnd-draggable-preview-item { + border-radius: var(--border-radius-base); + } } .ide-react-file-tree-panel { @@ -214,7 +307,7 @@ } .material-symbols { - color: var(--content-disabled); + color: var(--file-tree-icon-colour); &.file-tree-icon { margin-right: var(--spacing-02); @@ -252,7 +345,7 @@ width: 24px; padding: var(--spacing-03); font-size: var(--font-size-03); - color: var(--content-disabled); + color: var(--file-tree-icon-colour); } .file-tree-dropdown-toggle { @@ -410,7 +503,7 @@ @include fake-full-width-bg(var(--file-tree-item-dragging-bg)); - color: var(--file-tree-item-color); + color: var(--file-tree-item-dragging-color); .material-symbols { color: var(--content-disabled) !important; @@ -447,7 +540,7 @@ } .dnd-draggable-preview-item { - color: var(--file-tree-item-selected-color); + color: var(--file-tree-item-dragging-preview-colour); background-color: var(--file-tree-item-dragging-preview-bg); width: 75%; padding-left: var(--spacing-08); diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar.scss index 464ad52df0..e7f0c5baf9 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/toolbar.scss @@ -51,6 +51,7 @@ --toolbar-btn-hover-bg-color: var(--neutral-80); --toolbar-btn-hover-color: var(--white); --editor-toolbar-bg: var(--white); + --toolbar-filetree-bg-color: var(--white); .toolbar { border-bottom: none; diff --git a/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx b/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx index b26dca9a49..4c2680a072 100644 --- a/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx +++ b/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx @@ -372,7 +372,7 @@ describe('', function () { cy.findByRole('treeitem', { name: 'abcdef.tex' }).then($itemEl => { cy.findByTestId('file-tree-list-root').then($rootEl => { - expect($itemEl.get(0).parentNode).to.equal($rootEl.get(0)) + expect($itemEl.get(0).parentNode?.parentNode).to.equal($rootEl.get(0)) }) }) })