Merge pull request #23182 from overleaf/dp-pdf-error-state

Add pdf error state for new ide

GitOrigin-RevId: 35fe07744996375db9cb3b860bdc128b509ee438
This commit is contained in:
David
2025-01-29 11:41:47 +00:00
committed by Copybot
parent 069624029a
commit f523358d08
13 changed files with 222 additions and 16 deletions

View File

@@ -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": "",

View File

@@ -9,6 +9,7 @@ export default /** @type {const} */ ([
'forum',
'help',
'image',
'info',
'integration_instructions',
'picture_as_pdf',
'rate_review',

View File

@@ -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<string, FC> }> = ({
PermissionsProvider,
ProjectProvider,
ProjectSettingsProvider,
RailTabProvider,
ReferencesProvider,
SnapshotProvider,
SplitTestProvider,
@@ -81,7 +83,9 @@ export const ReactContextRoot: FC<{ providers?: Record<string, FC> }> = ({
<Providers.OnlineUsersProvider>
<Providers.MetadataProvider>
<Providers.OutlineProvider>
{children}
<Providers.RailTabProvider>
{children}
</Providers.RailTabProvider>
</Providers.OutlineProvider>
</Providers.MetadataProvider>
</Providers.OnlineUsersProvider>

View File

@@ -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'

View File

@@ -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 (
<div className="pdf-error-state">
<div className="pdf-error-state-top-section">
<div className="pdf-error-state-warning-icon">
<MaterialIcon type="warning" />
</div>
<div className="pdf-error-state-text">
<p className="pdf-error-state-label">{t('pdf_couldnt_compile')}</p>
<p className="pdf-error-state-description">
{t('we_are_unable_to_generate_the_pdf_at_this_time')}
</p>
</div>
<OLButton
variant="secondary"
size="sm"
onClick={() => {
setSelectedRailTab('errors')
}}
>
{t('check_logs')}
</OLButton>
</div>
<div className="pdf-error-state-info-box">
<div className="pdf-error-state-info-box-title">
<MaterialIcon type="info" unfilled />
{t('why_might_this_happen')}
</div>
<ul className="pdf-error-state-info-box-text">
<li>{t('there_is_an_unrecoverable_latex_error')}</li>
<li>{t('the_document_environment_contains_no_content')}</li>
<li>{t('this_project_contains_a_file_called_output')}</li>
</ul>
</div>
</div>
)
}
export default PdfErrorState

View File

@@ -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() {
<OlButtonToolbar className="toolbar toolbar-pdf toolbar-pdf-hybrid">
<div className="toolbar-pdf-left">
<PdfCompileButton />
<PdfHybridLogsButton />
<PdfHybridDownloadButton />
</div>
<div className="toolbar-pdf-right">

View File

@@ -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<string | undefined>(
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"
>
<div className="ide-rail">
<Nav
defaultActiveKey={RAIL_TABS[0]?.key}
activeKey={selectedTab}
className="d-flex flex-column ide-rail-tabs-nav"
>
{RAIL_TABS.map(({ icon, key, indicator }) => (

View File

@@ -0,0 +1,52 @@
import {
createContext,
Dispatch,
FC,
SetStateAction,
useContext,
useMemo,
useState,
} from 'react'
export type RailTabKey =
| 'file-tree'
| 'integrations'
| 'review-panel'
| 'chat'
| 'errors'
const RailTabContext = createContext<
| {
selectedTab: RailTabKey
setSelectedTab: Dispatch<SetStateAction<RailTabKey>>
}
| undefined
>(undefined)
export const RailTabProvider: FC = ({ children }) => {
// NOTE: The file tree **MUST** be the first tab to be opened
// since it is responsible for opening the initial document.
const [selectedTab, setSelectedTab] = useState<RailTabKey>('file-tree')
const value = useMemo(
() => ({
selectedTab,
setSelectedTab,
}),
[selectedTab, setSelectedTab]
)
return (
<RailTabContext.Provider value={value}>{children}</RailTabContext.Provider>
)
}
export const useRailTabContext = () => {
const context = useContext(RailTabContext)
if (!context) {
throw new Error(
'useRailTabContext is only available inside RailTabProvider'
)
}
return context
}

View File

@@ -10,7 +10,8 @@ import CompileTimeWarningUpgradePrompt from './compile-time-warning-upgrade-prom
import { PdfPreviewProvider } from './pdf-preview-provider'
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
import { useFeatureFlag } from '@/shared/context/split-test-context'
import PdfPreviewHybridToolbarNew from '@/features/ide-redesign/components/pdf-preview-hybrid-toolbar'
import PdfPreviewHybridToolbarNew from '@/features/ide-redesign/components/pdf-preview/pdf-preview-hybrid-toolbar'
import PdfErrorState from '@/features/ide-redesign/components/pdf-preview/pdf-error-state'
const pdfPreviewPromotions = importOverleafModules('pdfPreviewPromotions') as {
import: { default: ElementType }
@@ -45,7 +46,7 @@ function PdfPreviewPane() {
<PdfViewer />
</div>
</Suspense>
<PdfLogsViewer />
{newEditor ? <PdfErrorState /> : <PdfLogsViewer />}
</PdfPreviewProvider>
</div>
)

View File

@@ -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';

View File

@@ -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;
}

View File

@@ -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 couldnt compile",
"pdf_in_separate_tab": "PDF in separate tab",
"pdf_only_hide_editor": "PDF only <0>(hide editor)</0>",
"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. Its 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 its 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. Youll need to edit the LaTeX code to do this. <0>Find out how</0>",
"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 owners 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 owners 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 cant confirm this email",
"we_cant_find_any_sections_or_subsections_in_this_file": "We cant 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 youve done that, you can use Overleaf as normal, but youll 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__",