diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 991fb56d52..6c72050227 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -232,6 +232,7 @@ "changing_the_position_of_your_table": "", "chat": "", "chat_error": "", + "check_logs": "", "checking_dropbox_status": "", "checking_project_github_status": "", "choose_a_custom_color": "", @@ -1115,6 +1116,7 @@ "pdf_compile_in_progress_error": "", "pdf_compile_rate_limit_hit": "", "pdf_compile_try_again": "", + "pdf_couldnt_compile": "", "pdf_in_separate_tab": "", "pdf_only_hide_editor": "", "pdf_preview_error": "", @@ -1621,6 +1623,7 @@ "thanks_for_subscribing_you_help_sl": "", "thanks_settings_updated": "", "the_add_on_will_remain_active_until": "", + "the_document_environment_contains_no_content": "", "the_following_files_already_exist_in_this_project": "", "the_following_files_and_folders_already_exist_in_this_project": "", "the_following_folder_already_exists_in_this_project": "", @@ -1633,6 +1636,7 @@ "then_x_price_per_month": "", "then_x_price_per_year": "", "there_are_lots_of_options_to_edit_and_customize_your_figures": "", + "there_is_an_unrecoverable_latex_error": "", "there_was_a_problem_restoring_the_project_please_try_again_in_a_few_moments_or_contact_us": "", "they_lose_access_to_account": "", "this_action_cannot_be_reversed": "", @@ -1645,6 +1649,7 @@ "this_is_a_new_feature": "", "this_is_the_file_that_references_pulled_from_your_reference_manager_will_be_added_to": "", "this_project_already_has_maximum_editors": "", + "this_project_contains_a_file_called_output": "", "this_project_exceeded_compile_timeout_limit_on_free_plan": "", "this_project_exceeded_editor_limit": "", "this_project_has_more_than_max_collabs": "", @@ -1893,6 +1898,7 @@ "visual_editor_is_only_available_for_tex_files": "", "want_change_to_apply_before_plan_end": "", "we_are_testing_a_new_reference_search": "", + "we_are_unable_to_generate_the_pdf_at_this_time": "", "we_are_unable_to_opt_you_into_this_experiment": "", "we_cant_find_any_sections_or_subsections_in_this_file": "", "we_do_not_share_personal_information": "", @@ -1919,6 +1925,7 @@ "what_should_we_call_you": "", "when_you_tick_the_include_caption_box": "", "why_latex": "", + "why_might_this_happen": "", "why_not_pause_instead": "", "wide": "", "will_lose_edit_access_on_date": "", diff --git a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 index 0bfc703101..b0b89fa332 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 193da5d796..7ed8321b44 100644 --- a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs +++ b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs @@ -9,6 +9,7 @@ export default /** @type {const} */ ([ 'forum', 'help', 'image', + 'info', 'integration_instructions', 'picture_as_pdf', 'rate_review', diff --git a/services/web/frontend/js/features/ide-react/context/react-context-root.tsx b/services/web/frontend/js/features/ide-react/context/react-context-root.tsx index d6483a6b3f..22b10384b4 100644 --- a/services/web/frontend/js/features/ide-react/context/react-context-root.tsx +++ b/services/web/frontend/js/features/ide-react/context/react-context-root.tsx @@ -17,6 +17,7 @@ import { OnlineUsersProvider } from '@/features/ide-react/context/online-users-c import { OutlineProvider } from '@/features/ide-react/context/outline-context' import { PermissionsProvider } from '@/features/ide-react/context/permissions-context' import { ProjectProvider } from '@/shared/context/project-context' +import { RailTabProvider } from '@/features/ide-redesign/contexts/rail-tab-context' import { ProjectSettingsProvider } from '@/features/editor-left-menu/context/project-settings-context' import { ReferencesProvider } from '@/features/ide-react/context/references-context' import { SnapshotProvider } from '@/features/ide-react/context/snapshot-context' @@ -48,6 +49,7 @@ export const ReactContextRoot: FC<{ providers?: Record }> = ({ PermissionsProvider, ProjectProvider, ProjectSettingsProvider, + RailTabProvider, ReferencesProvider, SnapshotProvider, SplitTestProvider, @@ -81,7 +83,9 @@ export const ReactContextRoot: FC<{ providers?: Record }> = ({ - {children} + + {children} + diff --git a/services/web/frontend/js/features/ide-redesign/components/pdf-compile-button.tsx b/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-compile-button.tsx similarity index 95% rename from services/web/frontend/js/features/ide-redesign/components/pdf-compile-button.tsx rename to services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-compile-button.tsx index e0fa76828b..6ca848f7a3 100644 --- a/services/web/frontend/js/features/ide-redesign/components/pdf-compile-button.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-compile-button.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next' import { memo } from 'react' -import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' +import { useDetachCompileContext as useCompileContext } from '../../../../shared/context/detach-compile-context' import OLButton from '@/features/ui/components/ol/ol-button' import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import MaterialIcon from '@/shared/components/material-icon' diff --git a/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-error-state.tsx b/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-error-state.tsx new file mode 100644 index 0000000000..329aab1ba6 --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-error-state.tsx @@ -0,0 +1,58 @@ +import OLButton from '@/features/ui/components/ol/ol-button' +import MaterialIcon from '@/shared/components/material-icon' +import { useTranslation } from 'react-i18next' +import { useRailTabContext } from '../../contexts/rail-tab-context' +import { usePdfPreviewContext } from '@/features/pdf-preview/components/pdf-preview-provider' +import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context' +import { useFeatureFlag } from '@/shared/context/split-test-context' + +function PdfErrorState() { + const { loadingError } = usePdfPreviewContext() + // TODO ide-redesign-cleanup: rename showLogs to something else and check usages + const { showLogs } = useCompileContext() + const { t } = useTranslation() + const { setSelectedTab: setSelectedRailTab } = useRailTabContext() + const newEditor = useFeatureFlag('editor-redesign') + + if (!newEditor || (!loadingError && !showLogs)) { + return null + } + + return ( +
+
+
+ +
+
+

{t('pdf_couldnt_compile')}

+

+ {t('we_are_unable_to_generate_the_pdf_at_this_time')} +

+
+ { + setSelectedRailTab('errors') + }} + > + {t('check_logs')} + +
+
+
+ + {t('why_might_this_happen')} +
+
    +
  • {t('there_is_an_unrecoverable_latex_error')}
  • +
  • {t('the_document_environment_contains_no_content')}
  • +
  • {t('this_project_contains_a_file_called_output')}
  • +
+
+
+ ) +} + +export default PdfErrorState diff --git a/services/web/frontend/js/features/ide-redesign/components/pdf-preview-hybrid-toolbar.jsx b/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-preview-hybrid-toolbar.jsx similarity index 86% rename from services/web/frontend/js/features/ide-redesign/components/pdf-preview-hybrid-toolbar.jsx rename to services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-preview-hybrid-toolbar.jsx index 771ebad313..80ca3d5031 100644 --- a/services/web/frontend/js/features/ide-redesign/components/pdf-preview-hybrid-toolbar.jsx +++ b/services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-preview-hybrid-toolbar.jsx @@ -1,7 +1,6 @@ import { memo } from 'react' import OlButtonToolbar from '@/features/ui/components/ol/ol-button-toolbar' import PdfCompileButton from './pdf-compile-button' -import PdfHybridLogsButton from '@/features/pdf-preview/components/pdf-hybrid-logs-button' import PdfHybridDownloadButton from '@/features/pdf-preview/components/pdf-hybrid-download-button' function PdfPreviewHybridToolbar() { @@ -10,7 +9,6 @@ function PdfPreviewHybridToolbar() {
-
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 8ce34509fe..4a8e3198b4 100644 --- a/services/web/frontend/js/features/ide-redesign/components/rail.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/rail.tsx @@ -1,4 +1,4 @@ -import { ReactElement, useCallback, useMemo, useState } from 'react' +import { ReactElement, useCallback, useMemo } from 'react' import { Nav, NavLink, Tab, TabContainer } from 'react-bootstrap-5' import MaterialIcon, { AvailableUnfilledIcon, @@ -6,11 +6,12 @@ import MaterialIcon, { import { Panel } from 'react-resizable-panels' import { useLayoutContext } from '@/shared/context/layout-context' import { ErrorIndicator, ErrorPane } from './errors' +import { RailTabKey, useRailTabContext } from '../contexts/rail-tab-context' import FileTreeOutlinePanel from './file-tree-outline-panel' type RailElement = { icon: AvailableUnfilledIcon - key: string + key: RailTabKey component: ReactElement indicator?: ReactElement } @@ -24,8 +25,6 @@ type RailActionButton = { type RailAction = RailActionLink | RailActionButton const RAIL_TABS: RailElement[] = [ - // NOTE: The file tree **MUST** be the first (i.e. default) tab in the list - // since the file tree is responsible for opening the initial document. { key: 'file-tree', icon: 'description', @@ -55,9 +54,8 @@ const RAIL_TABS: RailElement[] = [ ] export const RailLayout = () => { - const [selectedTab, setSelectedTab] = useState( - RAIL_TABS[0]?.key - ) + const { selectedTab, setSelectedTab } = useRailTabContext() + const { setLeftMenuShown } = useLayoutContext() const railActions: RailAction[] = useMemo( () => [ @@ -76,13 +74,16 @@ export const RailLayout = () => { mountOnEnter // Only render when necessary (so that we can lazy load tab content) unmountOnExit={false} // TODO: Should we unmount the tabs when they're not used? transition={false} - defaultActiveKey={selectedTab} - onSelect={useCallback(key => setSelectedTab(key ?? undefined), [])} + activeKey={selectedTab} + onSelect={useCallback( + key => setSelectedTab(key ?? undefined), + [setSelectedTab] + )} id="ide-rail-tabs" >
- + {newEditor ? : }
) diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss index 30b277a113..159d158394 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/all.scss @@ -26,6 +26,7 @@ @import 'editor/history'; @import 'subscription'; @import 'editor/pdf'; +@import 'editor/pdf-error-state'; @import 'editor/compile-button'; @import 'editor/publish-modal'; @import 'editor/share'; diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/pdf-error-state.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/pdf-error-state.scss new file mode 100644 index 0000000000..db4977588f --- /dev/null +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/pdf-error-state.scss @@ -0,0 +1,76 @@ +.pdf-error-state { + position: absolute; + inset: var(--toolbar-small-height) 0 0 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--spacing-06); + background-color: var(--pdf-bg); +} + +.pdf-error-state-top-section { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-06); + padding: 0 var(--spacing-09) var(--spacing-09) var(--spacing-09); +} + +.pdf-error-state-warning-icon { + background-color: var(--bg-danger-03); + color: var(--content-danger); + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 100%; + + .material-symbols { + font-size: 32px; + } +} + +.pdf-error-state-text { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-02); +} + +.pdf-error-state-label { + font-size: var(--font-size-02); + font-weight: 600; + margin-bottom: 0; +} + +.pdf-error-state-description { + color: var(--content-secondary); + font-size: var(--font-size-02); + margin-bottom: 0; +} + +.pdf-error-state-info-box { + background-color: var(--bg-light-primary); + padding: var(--spacing-06); + border: 1px solid var(--border-divider); + border-radius: var(--border-radius-base); +} + +.pdf-error-state-info-box-title { + font-size: var(--font-size-02); + font-weight: 600; + display: flex; + align-items: center; + gap: var(--spacing-02); + margin-bottom: var(--spacing-04); +} + +.pdf-error-state-info-box-text { + font-size: var(--font-size-02); + display: flex; + flex-direction: column; + gap: var(--spacing-02); + margin-bottom: 0; +} diff --git a/services/web/locales/en.json b/services/web/locales/en.json index ddd48df0f9..41b773d7e4 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -296,6 +296,7 @@ "changing_the_position_of_your_table": "Changing the position of your table", "chat": "Chat", "chat_error": "Could not load chat messages, please try again.", + "check_logs": "Check logs", "check_your_email": "Check your email", "checking": "Checking", "checking_dropbox_status": "Checking Dropbox status", @@ -1503,6 +1504,7 @@ "pdf_compile_in_progress_error": "A previous compile is still running. Please wait a minute and try compiling again.", "pdf_compile_rate_limit_hit": "Compile rate limit hit", "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_hide_editor": "PDF only <0>(hide editor)", "pdf_preview_error": "There was a problem displaying the compilation results for this project.", @@ -2133,6 +2135,7 @@ "thanks_for_subscribing_you_help_sl": "Thank you for subscribing to the __planName__ plan. It’s support from people like yourself that allows __appName__ to continue to grow and improve.", "thanks_settings_updated": "Thanks, your settings have been updated.", "the_add_on_will_remain_active_until": "The add-on will remain active until the end of the current billing period.", + "the_document_environment_contains_no_content": "The document environment contains no content. If it’s empty, please add some content and compile again.", "the_file_supplied_is_of_an_unsupported_type ": "The link to open this content on Overleaf pointed to the wrong kind of file. Valid file types are .tex documents and .zip files. If this keeps happening for links on a particular site, please report this to them.", "the_following_files_already_exist_in_this_project": "The following files already exist in this project:", "the_following_files_and_folders_already_exist_in_this_project": "The following files and folders already exist in this project:", @@ -2153,6 +2156,7 @@ "then_x_price_per_month": "Then __price__ per month", "then_x_price_per_year": "Then __price__ per year", "there_are_lots_of_options_to_edit_and_customize_your_figures": "There are lots of options to edit and customize your figures, such as wrapping text around the figure, rotating the image, or including multiple images in a single figure. You’ll need to edit the LaTeX code to do this. <0>Find out how", + "there_is_an_unrecoverable_latex_error": "There is an unrecoverable LaTeX error. If there are LaTeX errors shown below or in the raw logs, please try to fix them and compile again.", "there_was_a_problem_restoring_the_project_please_try_again_in_a_few_moments_or_contact_us": "There was a problem restoring the project. Please try again in a few moments. Contact us of the problem persists.", "there_was_an_error_opening_your_content": "There was an error creating your project", "thesis": "Thesis", @@ -2168,6 +2172,7 @@ "this_is_the_file_that_references_pulled_from_your_reference_manager_will_be_added_to": "This is the file that references pulled from your reference manager will be added to.", "this_is_your_template": "This is your template from your project", "this_project_already_has_maximum_editors": "This project already has the maximum number of editors permitted on the owner’s plan. This means you can view but not edit the project.", + "this_project_contains_a_file_called_output": "This project contains a file called output.pdf. If that file exists, please rename it and compile again.", "this_project_exceeded_compile_timeout_limit_on_free_plan": "This project exceeded the compile timeout limit on our free plan.", "this_project_exceeded_editor_limit": "This project exceeded the editor limit for your plan. All collaborators now have view-only access.", "this_project_has_more_than_max_collabs": "This project has more than the maximum number of collaborators allowed on the project owner’s Overleaf plan. This means you could lose edit access from __linkSharingDate__.", @@ -2437,6 +2442,7 @@ "want_access_to_overleaf_premium_features_through_your_university": "Want access to __appName__ premium features through your university?", "want_change_to_apply_before_plan_end": "If you wish this change to apply before the end of your current billing period, please contact us.", "we_are_testing_a_new_reference_search": "We are testing a new reference search.", + "we_are_unable_to_generate_the_pdf_at_this_time": "We are unable to generate the pdf at this time.", "we_are_unable_to_opt_you_into_this_experiment": "We are unable to opt you into this experiment at this time, please ensure your organization has allowed this feature, or try again later.", "we_cant_confirm_this_email": "We can’t confirm this email", "we_cant_find_any_sections_or_subsections_in_this_file": "We can’t find any sections or subsections in this file", @@ -2467,6 +2473,7 @@ "when_you_join_labs": "When you join Labs, you can choose which experiments you want to be part of. Once you’ve done that, you can use Overleaf as normal, but you’ll see any labs features marked with this badge:", "when_you_tick_the_include_caption_box": "When you tick the box “Include caption” the image will be inserted into your document with a placeholder caption. To edit it, you simply select the placeholder text and type to replace it with your own.", "why_latex": "Why LaTeX?", + "why_might_this_happen": "Why might this happen?", "why_not_pause_instead": "Pause instead, to pick up where you left off", "wide": "Wide", "will_lose_edit_access_on_date": "Will lose edit access on __date__",