From f0a80a832271c3f28d525fcb385ed79249427dd9 Mon Sep 17 00:00:00 2001 From: Eric Mc Sween Date: Mon, 13 Jun 2022 08:08:38 -0400 Subject: [PATCH] Merge pull request #8361 from overleaf/em-halt-on-error-events Analytics events for "Stop on first error" GitOrigin-RevId: cbdb054cdf031f0364390c36cc1c1865169f2cd4 --- .../components/pdf-compile-button.js | 8 +- .../components/pdf-preview-error.js | 170 +++++++++--------- .../components/stop-on-first-error-prompt.js | 22 ++- .../preview-logs-pane-max-entries.js | 18 +- .../shared/context/local-compile-context.js | 6 +- .../shared/hooks/use-stop-on-first-error.js | 34 ++++ 6 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 services/web/frontend/js/shared/hooks/use-stop-on-first-error.js diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js b/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js index a521977af6..4b2f6a9f90 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-compile-button.js @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next' import { memo } from 'react' import classnames from 'classnames' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' +import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error' import PdfCompileButtonInner from './pdf-compile-button-inner' import getMeta from '../../../utils/meta' @@ -16,7 +17,6 @@ function PdfCompileButton() { hasChanges, setAutoCompile, setDraft, - setStopOnFirstError, setStopOnValidationError, stopOnFirstError, stopOnValidationError, @@ -24,6 +24,8 @@ function PdfCompileButton() { stopCompile, recompileFromScratch, } = useCompileContext() + const { enableStopOnFirstError, disableStopOnFirstError } = + useStopOnFirstError({ eventSource: 'dropdown' }) const { t } = useTranslation() const showStopOnFirstError = getMeta('ol-showStopOnFirstError') @@ -90,14 +92,14 @@ function PdfCompileButton() { )} {showStopOnFirstError && ( - setStopOnFirstError(true)}> + {t('stop_on_first_error')} )} {showStopOnFirstError && ( - setStopOnFirstError(false)}> + {t('try_to_compile_despite_errors')} diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.js b/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.js index 78d119ea26..c0fee73644 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-preview-error.js @@ -1,15 +1,14 @@ import PropTypes from 'prop-types' import { useTranslation, Trans } from 'react-i18next' -import { memo } from 'react' +import { memo, useCallback } from 'react' import { Button } from 'react-bootstrap' import PdfLogEntry from './pdf-log-entry' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' +import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error' import getMeta from '../../../utils/meta' function PdfPreviewError({ error }) { const { t } = useTranslation() - const { lastCompileOptions, setStopOnFirstError, startCompile } = - useCompileContext() switch (error) { case 'rendering-error': @@ -75,82 +74,8 @@ function PdfPreviewError({ error }) { ) - case 'timedout': { - const showStopOnFirstError = getMeta('ol-showStopOnFirstError') - if (showStopOnFirstError) { - return ( - -

{t('project_timed_out_intro')}

-
    -
  • - , - ]} - /> -
  • -
  • - , - ]} - /> - {!lastCompileOptions.stopOnFirstError && ( - <> - {' '} - { - startCompile({ stopOnFirstError: true }) - setStopOnFirstError(true) - }} - />, - ]} - /> - - )} -
  • -
-

- - ), - }} - /> -

-
- ) - } else { - return ( - - {t('proj_timed_out_reason')} - -
- - {t('learn_how_to_make_documents_compile_quickly')} - -
-
- ) - } - } + case 'timedout': + return case 'failure': return ( @@ -233,8 +158,93 @@ function ErrorLogEntry({ title, children }) { /> ) } - ErrorLogEntry.propTypes = { title: PropTypes.string.isRequired, children: PropTypes.any.isRequired, } + +function TimedOutLogEntry() { + const { t } = useTranslation() + const { enableStopOnFirstError } = useStopOnFirstError({ + eventSource: 'timeout', + }) + const { startCompile, lastCompileOptions } = useCompileContext() + const showStopOnFirstError = getMeta('ol-showStopOnFirstError') + + const handleEnableStopOnFirstErrorClick = useCallback(() => { + enableStopOnFirstError() + startCompile({ stopOnFirstError: true }) + }, [enableStopOnFirstError, startCompile]) + + if (showStopOnFirstError) { + return ( + +

{t('project_timed_out_intro')}

+
    +
  • + , + ]} + /> +
  • +
  • + , + ]} + /> + {!lastCompileOptions.stopOnFirstError && ( + <> + {' '} + , + ]} + /> + + )} +
  • +
+

+ + ), + }} + /> +

+
+ ) + } else { + return ( + + {t('proj_timed_out_reason')} + + + + ) + } +} +TimedOutLogEntry.propTypes = {} diff --git a/services/web/frontend/js/features/pdf-preview/components/stop-on-first-error-prompt.js b/services/web/frontend/js/features/pdf-preview/components/stop-on-first-error-prompt.js index 090f027ed8..68a7bf6f81 100644 --- a/services/web/frontend/js/features/pdf-preview/components/stop-on-first-error-prompt.js +++ b/services/web/frontend/js/features/pdf-preview/components/stop-on-first-error-prompt.js @@ -1,11 +1,22 @@ +import { useCallback } from 'react' import { useTranslation, Trans } from 'react-i18next' import { Button } from 'react-bootstrap' import PdfLogEntry from './pdf-log-entry' import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context' +import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error' export default function StopOnFirstErrorPrompt() { const { t } = useTranslation() - const { setStopOnFirstError, startCompile } = useCompileContext() + const { startCompile } = useCompileContext() + const { disableStopOnFirstError } = useStopOnFirstError({ + eventSource: 'logs-pane', + }) + + const handleDisableButtonClick = useCallback(() => { + disableStopOnFirstError() + startCompile({ stopOnFirstError: false }) + }, [disableStopOnFirstError, startCompile]) + return ( ]} />{' '} - diff --git a/services/web/frontend/js/features/preview/components/preview-logs-pane-max-entries.js b/services/web/frontend/js/features/preview/components/preview-logs-pane-max-entries.js index 386c62728b..3963e40096 100644 --- a/services/web/frontend/js/features/preview/components/preview-logs-pane-max-entries.js +++ b/services/web/frontend/js/features/preview/components/preview-logs-pane-max-entries.js @@ -1,3 +1,4 @@ +import { useCallback } from 'react' import PropTypes from 'prop-types' import { Trans, useTranslation } from 'react-i18next' import { Button } from 'react-bootstrap' @@ -5,18 +6,26 @@ 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' +import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error' function PreviewLogsPaneMaxEntries({ totalEntries, entriesShown, hasErrors }) { const { t } = useTranslation() const showStopOnFirstError = getMeta('ol-showStopOnFirstError') - const { startCompile, setStopOnFirstError, stoppedOnFirstError } = - useCompileContext() + const { startCompile, stoppedOnFirstError } = useCompileContext() + const { enableStopOnFirstError } = useStopOnFirstError({ + eventSource: 'too-many-logs', + }) const title = t('log_entry_maximum_entries_title', { total: totalEntries, displayed: entriesShown, }) + const handleEnableStopOnFirstErrorClick = useCallback(() => { + enableStopOnFirstError() + startCompile({ stopOnFirstError: true }) + }, [enableStopOnFirstError, startCompile]) + return (
@@ -35,10 +44,7 @@ function PreviewLogsPaneMaxEntries({ totalEntries, entriesShown, hasErrors }) {