diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 34d8431612..8db302aedb 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -463,6 +463,7 @@ "editor_and_pdf": "", "editor_disconected_click_to_reconnect": "", "editor_limit_exceeded_in_this_project": "", + "editor_only": "", "editor_only_hide_pdf": "", "editor_settings": "", "editor_theme": "", @@ -858,6 +859,7 @@ "latex_places_figures_according_to_a_special_algorithm": "", "latex_places_tables_according_to_a_special_algorithm": "", "layout": "", + "layout_options": "", "layout_processing": "", "learn_more": "", "learn_more_about_account": "", @@ -1091,6 +1093,7 @@ "open_file": "", "open_link": "", "open_path": "", + "open_pdf_in_separate_tab": "", "open_project": "", "open_survey": "", "open_target": "", @@ -1150,6 +1153,7 @@ "pdf_compile_try_again": "", "pdf_couldnt_compile": "", "pdf_in_separate_tab": "", + "pdf_only": "", "pdf_only_hide_editor": "", "pdf_preview_error": "", "pdf_rendering_error": "", @@ -1531,6 +1535,7 @@ "sort_projects": "", "source": "", "spell_check": "", + "split_view": "", "sso": "", "sso_active": "", "sso_already_setup_good_to_go": "", diff --git a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 index bf4ba34c6b..a7c79e29a9 100644 Binary files a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 and b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 differ diff --git a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs index c727e77cf0..9c4a941859 100644 --- a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs +++ b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs @@ -18,6 +18,7 @@ export default /** @type {const} */ ([ 'rate_review', 'report', 'settings', + 'space_dashboard', 'table_chart', 'upload_file', 'web_asset', diff --git a/services/web/frontend/js/features/ide-redesign/components/main-layout.tsx b/services/web/frontend/js/features/ide-redesign/components/main-layout.tsx index 71bbbe33c3..9d847ee95e 100644 --- a/services/web/frontend/js/features/ide-redesign/components/main-layout.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/main-layout.tsx @@ -7,17 +7,26 @@ import { RailLayout } from './rail' import { Toolbar } from './toolbar/toolbar' import { HorizontalToggler } from '@/features/ide-react/components/resize/horizontal-toggler' import { useTranslation } from 'react-i18next' -import { usePdfPane } from '../hooks/use-pdf-pane' +import { usePdfPane } from '@/features/ide-react/hooks/use-pdf-pane' +import { useLayoutContext } from '@/shared/context/layout-context' +import { useState } from 'react' export default function MainLayout() { + const [resizing, setResizing] = useState(false) const { - isOpen: isPdfOpen, - setIsOpen: setIsPdfOpen, - panelRef: pdfPanelRef, - handlePaneCollapse: handlePdfPaneCollapse, - handlePaneExpand: handlePdfPaneExpand, - togglePane: togglePdfPane, + togglePdfPane, + handlePdfPaneExpand, + handlePdfPaneCollapse, + setPdfIsOpen: setIsPdfOpen, + pdfIsOpen: isPdfOpen, + pdfPanelRef, } = usePdfPane() + + const { view, pdfLayout } = useLayoutContext() + + const editorIsOpen = + view === 'editor' || view === 'file' || pdfLayout === 'sideBySide' + const { t } = useTranslation() return (
@@ -27,19 +36,32 @@ export default function MainLayout() { autoSaveId="ide-redesign-outer-layout" direction="horizontal" className={classNames('ide-redesign-inner', { - 'ide-panel-group-resizing': false, + 'ide-panel-group-resizing': resizing, })} > - +
) => void + } +>(({ onClick }, ref) => { + return ( + } + /> + ) +}) + +LayoutDropdownToggleButton.displayName = 'LayoutDropdownToggleButton' + +export default function ChangeLayoutButton() { + return ( +
+ + + + + + +
+ ) +} diff --git a/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-options.tsx b/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-options.tsx new file mode 100644 index 0000000000..3c3126e8da --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/toolbar/change-layout-options.tsx @@ -0,0 +1,175 @@ +import { + DropdownItem, + DropdownHeader, +} from '@/features/ui/components/bootstrap-5/dropdown-menu' +import { + IdeLayout, + IdeView, + useLayoutContext, +} from '@/shared/context/layout-context' +import React, { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import * as eventTracking from '../../../../infrastructure/event-tracking' +import useEventListener from '@/shared/hooks/use-event-listener' +import { DetachRole } from '@/shared/context/detach-context' +import { Spinner } from 'react-bootstrap-5' + +type LayoutOption = 'sideBySide' | 'editorOnly' | 'pdfOnly' | 'detachedPdf' + +const getActiveLayoutOption = ({ + pdfLayout, + view, + detachRole, +}: { + pdfLayout: IdeLayout + view: IdeView | null + detachRole?: DetachRole +}): LayoutOption | null => { + if (view === 'history') { + return null + } + + if (detachRole === 'detacher') { + return 'detachedPdf' + } + + if (pdfLayout === 'flat' && (view === 'editor' || view === 'file')) { + return 'editorOnly' + } + + if (pdfLayout === 'flat' && view === 'pdf') { + return 'pdfOnly' + } + + if (pdfLayout === 'sideBySide') { + return 'sideBySide' + } + + return null +} + +const LayoutDropdownItem = ({ + active, + disabled = false, + processing = false, + leadingIcon, + onClick, + children, +}: { + active: boolean + leadingIcon: string + onClick: () => void + children: React.ReactNode + processing?: boolean + disabled?: boolean +}) => { + let trailingIcon: string | React.ReactNode | null = null + if (processing) { + trailingIcon = ( +
+ {shouldDisplaySubmitButton && } diff --git a/services/web/frontend/js/features/ide-redesign/hooks/use-pdf-pane.tsx b/services/web/frontend/js/features/ide-redesign/hooks/use-pdf-pane.tsx deleted file mode 100644 index 8215af3fdd..0000000000 --- a/services/web/frontend/js/features/ide-redesign/hooks/use-pdf-pane.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useCallback, useRef, useState } from 'react' -import useCollapsiblePanel from '@/features/ide-react/hooks/use-collapsible-panel' -import { ImperativePanelHandle } from 'react-resizable-panels' - -// FIXME: This is temporary, to avoid clashing with the existing usePdfPane -// which uses the layout context. That's the correct approach. -export const usePdfPane = () => { - const [isOpen, setIsOpen] = useState(true) - const [resizing, setResizing] = useState(false) - const panelRef = useRef(null) - useCollapsiblePanel(isOpen, panelRef) - - const togglePane = useCallback(() => { - setIsOpen(value => !value) - }, []) - - const handlePaneExpand = useCallback(() => { - setIsOpen(true) - }, []) - - const handlePaneCollapse = useCallback(() => { - setIsOpen(false) - }, []) - - return { - isOpen, - setIsOpen, - panelRef, - togglePane, - handlePaneExpand, - handlePaneCollapse, - resizing, - setResizing, - } -} diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/ide.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/ide.scss index a4649f102f..8513e2fca1 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/ide.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/ide.scss @@ -45,6 +45,18 @@ $editor-toggler-bg-dark-color: color.adjust( } } +.ide-redesign-main { + .ide-panel-group-resizing { + background-color: var(--white); + + // Hide panel contents while resizing + .ide-redesign-editor-content, + .pdf { + display: none !important; + } + } +} + .global-alerts { height: 0; margin-top: var(--spacing-01); diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 5b730599d9..38af911789 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -598,6 +598,7 @@ "editor_and_pdf": "Editor & PDF", "editor_disconected_click_to_reconnect": "Editor disconnected, click anywhere to reconnect.", "editor_limit_exceeded_in_this_project": "Too many editors in this project", + "editor_only": "Editor only", "editor_only_hide_pdf": "Editor only <0>(hide PDF)", "editor_settings": "Editor settings", "editor_theme": "Editor theme", @@ -1131,6 +1132,7 @@ "latex_templates_for_journal_articles": "LaTeX templates for journal articles, academic papers, CVs and résumés, presentations, and more.", "latex_templates_sentence_case": "LaTeX templates", "layout": "Layout", + "layout_options": "Layout options", "layout_processing": "Layout processing", "ldap": "LDAP", "ldap_create_admin_instructions": "Choose an email address for the first __appName__ admin account. This should correspond to an account in the LDAP system. You will then be asked to log in with this account.", @@ -1448,6 +1450,7 @@ "open_file": "Edit file", "open_link": "Go to page", "open_path": "Open __path__", + "open_pdf_in_separate_tab": "Open PDF in separate tab", "open_project": "Open Project", "open_survey": "Open survey", "open_target": "Go to target", @@ -1537,6 +1540,7 @@ "pdf_compile_try_again": "Please wait for your other compile to finish before trying again.", "pdf_couldnt_compile": "PDF couldn’t compile", "pdf_in_separate_tab": "PDF in separate tab", + "pdf_only": "PDF only", "pdf_only_hide_editor": "PDF only <0>(hide editor)", "pdf_preview_error": "There was a problem displaying the compilation results for this project.", "pdf_rendering_error": "PDF Rendering Error", @@ -2007,6 +2011,7 @@ "sort_projects": "Sort projects", "source": "Source", "spell_check": "Spell check", + "split_view": "Split view", "sso": "SSO", "sso_account_already_linked": "Account already linked to another __appName__ user", "sso_active": "SSO active",