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.",