diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 8cf14cc2e3..7ba5f47b3f 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -1198,6 +1198,7 @@ "professional": "", "progress_bar_percentage": "", "project_approaching_file_limit": "", + "project_failed_to_compile": "", "project_figure_modal": "", "project_files": "", "project_flagged_too_many_compiles": "", @@ -1777,6 +1778,7 @@ "tried_to_register_with_email": "", "troubleshooting_tip": "", "try_again": "", + "try_for_free": "", "try_it_for_free": "", "try_now": "", "try_premium_for_free": "", diff --git a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 index fb158e5ea1..549c7c10ab 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 1c551ebdbd..c727e77cf0 100644 --- a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs +++ b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs @@ -21,4 +21,5 @@ export default /** @type {const} */ ([ 'table_chart', 'upload_file', 'web_asset', + 'error', ]) diff --git a/services/web/frontend/js/features/pdf-preview/components/timeout-message-after-paywall-dismissal.tsx b/services/web/frontend/js/features/pdf-preview/components/timeout-message-after-paywall-dismissal.tsx new file mode 100644 index 0000000000..07ba254b55 --- /dev/null +++ b/services/web/frontend/js/features/pdf-preview/components/timeout-message-after-paywall-dismissal.tsx @@ -0,0 +1,196 @@ +import getMeta from '@/utils/meta' +import { Trans, useTranslation } from 'react-i18next' +import { memo, useCallback } from 'react' +import { useDetachCompileContext } from '@/shared/context/detach-compile-context' +import StartFreeTrialButton from '@/shared/components/start-free-trial-button' +import { useFeatureFlag } from '@/shared/context/split-test-context' +import MaterialIcon from '@/shared/components/material-icon' +import OLButton from '@/features/ui/components/ol/ol-button' +import { useStopOnFirstError } from '@/shared/hooks/use-stop-on-first-error' +import PdfLogEntry from './pdf-log-entry' + +function TimeoutMessageAfterPaywallDismissal() { + const { + startCompile, + lastCompileOptions, + setAnimateCompileDropdownArrow, + isProjectOwner, + } = useDetachCompileContext() + + const { enableStopOnFirstError } = useStopOnFirstError({ + eventSource: 'timeout-new', + }) + + const handleEnableStopOnFirstErrorClick = useCallback(() => { + enableStopOnFirstError() + startCompile({ stopOnFirstError: true }) + setAnimateCompileDropdownArrow(true) + }, [enableStopOnFirstError, startCompile, setAnimateCompileDropdownArrow]) + + return ( +
+ + {getMeta('ol-ExposedSettings').enableSubscriptions && ( + + )} +
+ ) +} + +type CompileTimeoutProps = { + isProjectOwner: boolean +} + +const CompileTimeout = memo(function CompileTimeout({ + isProjectOwner, +}: CompileTimeoutProps) { + const { t } = useTranslation() + + const hasNewPaywallCta = useFeatureFlag('paywall-cta') + + return ( + + } + formattedContent={ + getMeta('ol-ExposedSettings').enableSubscriptions && ( + <> +

+ {isProjectOwner + ? t('your_project_exceeded_compile_timeout_limit_on_free_plan') + : t('this_project_exceeded_compile_timeout_limit_on_free_plan')} +

+ + {isProjectOwner === false && ( + , + ]} + /> + )} + + {isProjectOwner && ( +
+ + {hasNewPaywallCta + ? t('get_more_compile_time') + : t('try_for_free')} + +
+ )} + + ) + } + // @ts-ignore + entryAriaLabel={t('your_compile_timed_out')} + level="error" + /> + ) +}) + +type PreventTimeoutHelpMessageProps = { + lastCompileOptions: any + handleEnableStopOnFirstErrorClick: () => void + isProjectOwner: boolean +} + +const PreventTimeoutHelpMessage = memo(function PreventTimeoutHelpMessage({ + lastCompileOptions, + handleEnableStopOnFirstErrorClick, + isProjectOwner, +}: PreventTimeoutHelpMessageProps) { + const { t } = useTranslation() + + return ( + +

{t('common_causes_of_compile_timeouts_include')}:

+
    +
  • + , + ]} + /> +
  • +
  • + , + ]} + /> + {!lastCompileOptions.stopOnFirstError && ( + <> + {' '} + , + // eslint-disable-next-line react/jsx-key + , + ]} + />{' '} + + )} +
  • +
+

+ , + ]} + /> +

+ + } + // @ts-ignore + entryAriaLabel={t('reasons_for_compile_timeouts')} + level="raw" + /> + ) +}) + +export default memo(TimeoutMessageAfterPaywallDismissal) diff --git a/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-paywall-prompt.tsx b/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-paywall-prompt.tsx index c89e9e2f3b..2a56a76774 100644 --- a/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-paywall-prompt.tsx +++ b/services/web/frontend/js/features/pdf-preview/components/timeout-upgrade-paywall-prompt.tsx @@ -1,5 +1,6 @@ import getMeta from '@/utils/meta' import { useMemo } from 'react' +import TimeoutMessageAfterPaywallDismissal from './timeout-message-after-paywall-dismissal' const studentRoles = [ 'High-school student', @@ -8,14 +9,15 @@ const studentRoles = [ 'Doctoral student (e.g. PhD, MD, EngD)', ] +// We can display TimeoutMessageAfterPaywallDismissal after the user has dismissed the paywall. That logic can be implemented in this file or somewhere else? function TimeoutUpgradePaywallPrompt() { const odcRole = getMeta('ol-odcRole') const isStudent = useMemo(() => studentRoles.includes(odcRole), [odcRole]) return (
-

Hello world from new paywall component

Current user is {!isStudent && 'not'} a student.

+
) } diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/logs.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/logs.scss index 7f792ffe2d..e296a19658 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/logs.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/logs.scss @@ -209,3 +209,58 @@ text-align: left; } } + +// As part of compile time paywall redesign, we are only migrating the necessary classes needed for the split test +// Other classes should be migrated too as a part of website redesign project later on. + +.timeout-upgrade-paywall-prompt { + display: flex; + flex-direction: column; + gap: 10px; // adding this value to match existing spacing in logs pane, there is no variable for 10px +} + +.website-redesign { + .log-entry-header { + @include heading-sm; + + font-weight: 600; + padding: var(--spacing-05) var(--spacing-06); + } + + .log-entry-content { + padding: 0; + } + + .log-entry-formatted-content { + @include body-sm; + + padding: var(--spacing-06); + color: var(--neutral-70); + + a, + .btn-inline-link { + color: var(--blue-50); + } + } + + .log-entry-cta-container { + padding-top: var(--spacing-06); + display: flex; + justify-content: flex-end; + } + + .log-entry-header-error { + background-color: var(--red-10); + + .log-entry-header-title { + @include heading-sm; + + color: var(--red-50); + } + } + + .log-entry-header-raw { + background-color: var(--neutral-60); + padding: var(--spacing-04) var(--spacing-06); + } +} diff --git a/services/web/locales/en.json b/services/web/locales/en.json index cb6de95b04..e1471471d2 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -1617,6 +1617,7 @@ "progress_bar_percentage": "Progress bar from 0 to 100%", "project": "project", "project_approaching_file_limit": "This project is approaching the file limit", + "project_failed_to_compile": "Your project failed to compile", "project_figure_modal": "Project", "project_files": "Project files", "project_flagged_too_many_compiles": "This project has been flagged for compiling too often. The limit will be lifted shortly.",