Răsfoiți Sursa

Merge pull request #8346 from overleaf/em-halt-on-error-logs-2

Stop on first error: logs pane prompts

GitOrigin-RevId: a246a7e5d302ad3104e15f7fd78344992b4e011b
Eric Mc Sween 4 ani în urmă
părinte
comite
e365a6cbaf

+ 8 - 0
services/web/frontend/extracted-translations.json

@@ -246,8 +246,10 @@
   "loading_recent_github_commits": "",
   "log_entry_description": "",
   "log_entry_maximum_entries": "",
+  "log_entry_maximum_entries_enable_stop_on_first_error": "",
   "log_entry_maximum_entries_message": "",
   "log_entry_maximum_entries_message_no_errors": "",
+  "log_entry_maximum_entries_see_full_logs": "",
   "log_entry_maximum_entries_title": "",
   "log_hint_extra_info": "",
   "log_viewer_error": "",
@@ -351,6 +353,11 @@
   "project_ownership_transfer_confirmation_2": "",
   "project_synced_with_git_repo_at": "",
   "project_synchronisation": "",
+  "project_timed_out_enable_stop_on_first_error": "",
+  "project_timed_out_fatal_error": "",
+  "project_timed_out_intro": "",
+  "project_timed_out_learn_more": "",
+  "project_timed_out_optimize_images": "",
   "project_too_large": "",
   "project_too_large_please_reduce": "",
   "project_too_much_editable_text": "",
@@ -459,6 +466,7 @@
   "this_project_is_public_read_only": "",
   "this_project_will_appear_in_your_dropbox_folder_at": "",
   "timedout": "",
+  "tip": "",
   "to_add_email_accounts_need_to_be_linked_2": "",
   "to_add_more_collaborators": "",
   "to_change_access_permissions": "",

+ 1 - 2
services/web/frontend/js/features/pdf-preview/components/pdf-logs-viewer.js

@@ -22,7 +22,6 @@ function PdfLogsViewer() {
     rawLog,
     validationIssues,
     showLogs,
-    stopOnFirstError,
     stoppedOnFirstError,
   } = useCompileContext()
 
@@ -33,7 +32,7 @@ function PdfLogsViewer() {
       <div className="logs-pane-content">
         {codeCheckFailed && <PdfCodeCheckFailedNotice />}
 
-        {stopOnFirstError && stoppedOnFirstError && <StopOnFirstErrorPrompt />}
+        {stoppedOnFirstError && <StopOnFirstErrorPrompt />}
 
         {error && <PdfPreviewError error={error} />}
 

+ 81 - 16
services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.js

@@ -1,10 +1,15 @@
 import PropTypes from 'prop-types'
 import { useTranslation, Trans } from 'react-i18next'
 import { memo } from 'react'
+import { Button } from 'react-bootstrap'
 import PdfLogEntry from './pdf-log-entry'
+import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
+import getMeta from '../../../utils/meta'
 
 function PdfPreviewError({ error }) {
   const { t } = useTranslation()
+  const { lastCompileOptions, setStopOnFirstError, startCompile } =
+    useCompileContext()
 
   switch (error) {
     case 'rendering-error':
@@ -70,22 +75,82 @@ function PdfPreviewError({ error }) {
         </ErrorLogEntry>
       )
 
-    case 'timedout':
-      return (
-        <ErrorLogEntry title={t('timedout')}>
-          {t('proj_timed_out_reason')}
-
-          <div>
-            <a
-              href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F"
-              target="_blank"
-              rel="noopener"
-            >
-              {t('learn_how_to_make_documents_compile_quickly')}
-            </a>
-          </div>
-        </ErrorLogEntry>
-      )
+    case 'timedout': {
+      const showStopOnFirstError = getMeta('ol-showStopOnFirstError')
+      if (showStopOnFirstError) {
+        return (
+          <ErrorLogEntry title={t('timedout')}>
+            <p>{t('project_timed_out_intro')}</p>
+            <ul>
+              <li>
+                <Trans
+                  i18nKey="project_timed_out_optimize_images"
+                  components={[
+                    // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
+                    <a href="https://www.overleaf.com/learn/how-to/Optimising_very_large_image_files" />,
+                  ]}
+                />
+              </li>
+              <li>
+                <Trans
+                  i18nKey="project_timed_out_fatal_error"
+                  components={[
+                    // eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key
+                    <a href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F#Fatal_compile_errors_blocking_the_compilation" />,
+                  ]}
+                />
+                {!lastCompileOptions.stopOnFirstError && (
+                  <>
+                    {' '}
+                    <Trans
+                      i18nKey="project_timed_out_enable_stop_on_first_error"
+                      components={[
+                        // eslint-disable-next-line react/jsx-key
+                        <Button
+                          bsSize="xs"
+                          bsStyle="info"
+                          onClick={() => {
+                            startCompile({ stopOnFirstError: true })
+                            setStopOnFirstError(true)
+                          }}
+                        />,
+                      ]}
+                    />
+                  </>
+                )}
+              </li>
+            </ul>
+            <p>
+              <Trans
+                i18nKey="project_timed_out_learn_more"
+                components={{
+                  link: (
+                    // eslint-disable-next-line jsx-a11y/anchor-has-content
+                    <a href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F" />
+                  ),
+                }}
+              />
+            </p>
+          </ErrorLogEntry>
+        )
+      } else {
+        return (
+          <ErrorLogEntry title={t('timedout')}>
+            {t('proj_timed_out_reason')}
+
+            <div>
+              <a
+                href="https://www.overleaf.com/learn/how-to/Why_do_I_keep_getting_the_compile_timeout_error_message%3F"
+                target="_blank"
+                rel="noopener"
+              >
+                {t('learn_how_to_make_documents_compile_quickly')}
+              </a>
+            </div>
+          </ErrorLogEntry>
+        )
+      }
+    }
 
     case 'failure':
       return (

+ 58 - 11
services/web/frontend/js/features/preview/components/preview-logs-pane-max-entries.js

@@ -1,10 +1,16 @@
 import PropTypes from 'prop-types'
 import { Trans, useTranslation } from 'react-i18next'
+import { Button } from 'react-bootstrap'
 import PreviewLogEntryHeader from './preview-log-entry-header'
 import Icon from '../../../shared/components/icon'
+import getMeta from '../../../utils/meta'
+import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
 
 function PreviewLogsPaneMaxEntries({ totalEntries, entriesShown, hasErrors }) {
   const { t } = useTranslation()
+  const showStopOnFirstError = getMeta('ol-showStopOnFirstError')
+  const { startCompile, setStopOnFirstError, stoppedOnFirstError } =
+    useCompileContext()
 
   const title = t('log_entry_maximum_entries_title', {
     total: totalEntries,
@@ -15,18 +21,59 @@ function PreviewLogsPaneMaxEntries({ totalEntries, entriesShown, hasErrors }) {
     <div className="log-entry" aria-label={t('log_entry_maximum_entries')}>
       <PreviewLogEntryHeader level="raw" headerTitle={title} />
       <div className="log-entry-content">
-        <Icon type="lightbulb-o" />
-        &nbsp;
-        {hasErrors ? (
-          <Trans
-            i18nKey="log_entry_maximum_entries_message"
-            components={[<b key="bold-1" />, <p />]} // eslint-disable-line react/jsx-key
-          />
+        {showStopOnFirstError ? (
+          hasErrors && !stoppedOnFirstError ? (
+            <>
+              <p>
+                <Icon type="lightbulb-o" />
+                &nbsp;
+                <strong>{t('tip')}: </strong>
+                <Trans
+                  i18nKey="log_entry_maximum_entries_enable_stop_on_first_error"
+                  components={{
+                    button: (
+                      <Button
+                        bsSize="xs"
+                        bsStyle="info"
+                        onClick={() => {
+                          startCompile({ stopOnFirstError: true })
+                          setStopOnFirstError(true)
+                        }}
+                      />
+                    ),
+                    'learn-more-link': (
+                      // eslint-disable-next-line jsx-a11y/anchor-has-content
+                      <a href="https://www.overleaf.com/learn/latex/Questions/Tips_and_Tricks_for_Troubleshooting_LaTeX" />
+                    ),
+                  }}
+                />
+              </p>
+              <p>{t('log_entry_maximum_entries_see_full_logs')}</p>
+            </>
+          ) : (
+            <p>
+              <Icon type="lightbulb-o" />
+              &nbsp;
+              <strong>{t('tip')}: </strong>
+              {t('log_entry_maximum_entries_see_full_logs')}
+            </p>
+          )
         ) : (
-          <Trans
-            i18nKey="log_entry_maximum_entries_message_no_errors"
-            components={[<b key="bold-1" />]}
-          />
+          <>
+            <Icon type="lightbulb-o" />
+            &nbsp;
+            {hasErrors ? (
+              <Trans
+                i18nKey="log_entry_maximum_entries_message"
+                components={[<b />, <p />]} // eslint-disable-line react/jsx-key
+              />
+            ) : (
+              <Trans
+                i18nKey="log_entry_maximum_entries_message_no_errors"
+                components={[<b />]} // eslint-disable-line react/jsx-key
+              />
+            )}
+          </>
         )}
       </div>
     </div>

+ 9 - 0
services/web/frontend/js/shared/context/detach-compile-context.js

@@ -30,6 +30,7 @@ export function DetachCompileProvider({ children }) {
     fileList: _fileList,
     hasChanges: _hasChanges,
     highlights: _highlights,
+    lastCompileOptions: _lastCompileOptions,
     logEntries: _logEntries,
     logEntryAnnotations: _logEntryAnnotations,
     pdfDownloadUrl: _pdfDownloadUrl,
@@ -113,6 +114,12 @@ export function DetachCompileProvider({ children }) {
     'detacher',
     'detached'
   )
+  const [lastCompileOptions] = useDetachStateWatcher(
+    'lastCompileOptions',
+    _lastCompileOptions,
+    'detacher',
+    'detached'
+  )
   const [logEntries] = useDetachStateWatcher(
     'logEntries',
     _logEntries,
@@ -314,6 +321,7 @@ export function DetachCompileProvider({ children }) {
       fileList,
       hasChanges,
       highlights,
+      lastCompileOptions,
       logEntryAnnotations,
       logEntries,
       pdfDownloadUrl,
@@ -357,6 +365,7 @@ export function DetachCompileProvider({ children }) {
       fileList,
       hasChanges,
       highlights,
+      lastCompileOptions,
       logEntryAnnotations,
       logEntries,
       pdfDownloadUrl,

+ 6 - 0
services/web/frontend/js/shared/context/local-compile-context.js

@@ -458,6 +458,10 @@ export function LocalCompileProvider({ children }) {
     })
   }, [clearCache, compiler])
 
+  // After a compile, the compiler sets `data.options` to the options that were
+  // used for that compile.
+  const lastCompileOptions = useMemo(() => data?.options || {}, [data])
+
   const value = useMemo(
     () => ({
       autoCompile,
@@ -471,6 +475,7 @@ export function LocalCompileProvider({ children }) {
       fileList,
       hasChanges,
       highlights,
+      lastCompileOptions,
       logEntryAnnotations,
       logEntries,
       pdfDownloadUrl,
@@ -514,6 +519,7 @@ export function LocalCompileProvider({ children }) {
       fileList,
       hasChanges,
       highlights,
+      lastCompileOptions,
       logEntries,
       logEntryAnnotations,
       position,

+ 8 - 0
services/web/locales/en.json

@@ -34,6 +34,9 @@
   "log_entry_maximum_entries_title": "__total__ log messages total. Showing the first __displayed__",
   "log_entry_maximum_entries_message": "<0>Tip</0>: Try to fix the first error and recompile. Often one error causes many later error messages.<1>If you need to see the full logs, you can still download them or view the raw logs below.</1>",
   "log_entry_maximum_entries_message_no_errors": "<0>Tip</0>: If you need to see the full logs, you can still download them or view the raw logs below.",
+  "log_entry_maximum_entries_enable_stop_on_first_error": "Try to fix the first error and recompile. Often one error causes many later error messages. You can <button>Enable “Stop on first error”</button> to focus on fixing errors. We recommend fixing errors as soon as possible; letting them accumulate may lead to hard-to-debug and fatal errors. <learn-more-link>Learn more</learn-more-link>",
+  "log_entry_maximum_entries_see_full_logs": "If you need to see the full logs, you can still download them or view the raw logs below.",
+  "tip": "Tip",
   "navigate_log_source": "Navigate to log position in source code: __location__",
   "other_output_files": "Download other output files",
   "refresh": "Refresh",
@@ -1082,6 +1085,11 @@
   "something_went_wrong_loading_pdf_viewer": "Something went wrong loading the PDF viewer. This might be caused by issues like <0>temporary network problems</0> or an <0>outdated web browser</0>. Please follow the <1>troubleshooting steps for access, loading and display problems</1>. If the issue persists, please <2>let us know</2>.",
   "timedout": "Timed out",
   "proj_timed_out_reason": "Sorry, your compile took too long to run and timed out. This may be due to a LaTeX error, or a large number of high-res images or complicated diagrams.",
+  "project_timed_out_intro": "Sorry, your compile took too long to run and timed out. The most common causes of timeouts are:",
+  "project_timed_out_optimize_images": "Large or high-resolution images are taking too long to process. You may be able to <0>optimize them</0>.",
+  "project_timed_out_fatal_error": "A <0>fatal compile error</0> may be completely blocking compilation.",
+  "project_timed_out_enable_stop_on_first_error": "<0>Enable “Stop on first error”</0> to help you find and fix errors right away.",
+  "project_timed_out_learn_more": "<0>Learn more</0> about other causes of compile timeouts and how to fix them.",
   "no_errors_good_job": "No errors, good job!",
   "compile_error": "Compile Error",
   "generic_failed_compile_message": "Sorry, your LaTeX code couldn’t compile for some reason. Please check the errors below for details, or view the raw log",