mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
[web] Compile time warning split test (#8813)
* Implement compile time warning split test * Add i18n for compile time warning * Memoize CompileTimeWarning component * Reuse startFreeTrial() function from account-upgrade * Improve usage of react bootstrap native properties * Cleanup compile-time-warning * Move all logic into CompileTimeWarning component * Only show compile time warning to project owners * Handle compile time warning in detached mode and while switching layout GitOrigin-RevId: 4fc40acfc113f91c81a6744c14c0f8b3ef766e39
This commit is contained in:
parent
7757d8d2ad
commit
d501bc4820
9 changed files with 184 additions and 1 deletions
|
@ -949,6 +949,25 @@ const ProjectController = {
|
|||
}
|
||||
)
|
||||
},
|
||||
compileTimeWarningAssignment: [
|
||||
'user',
|
||||
(results, cb) => {
|
||||
if (results.user?.features?.compileTimeout <= 60) {
|
||||
SplitTestHandler.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'compile-time-warning',
|
||||
{},
|
||||
() => {
|
||||
// do not fail editor load if assignment fails
|
||||
cb()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
(
|
||||
err,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"also": "",
|
||||
"anyone_with_link_can_edit": "",
|
||||
"anyone_with_link_can_view": "",
|
||||
"approaching_compile_timeout_limit_upgrade_for_more_compile_time": "<0></0>",
|
||||
"are_you_still_at": "",
|
||||
"ask_proj_owner_to_upgrade_for_git_bridge": "",
|
||||
"ask_proj_owner_to_upgrade_for_longer_compiles": "",
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import { memo, useCallback, useEffect } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import * as eventTracking from '../../../infrastructure/event-tracking'
|
||||
import { useDetachCompileContext } from '../../../shared/context/detach-compile-context'
|
||||
import { startFreeTrial } from '../../../main/account-upgrade'
|
||||
|
||||
function CompileTimeWarning() {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { showCompileTimeWarning, setShowCompileTimeWarning } =
|
||||
useDetachCompileContext()
|
||||
|
||||
useEffect(() => {
|
||||
if (showCompileTimeWarning) {
|
||||
eventTracking.sendMB('compile-time-warning-displayed', {})
|
||||
}
|
||||
}, [showCompileTimeWarning])
|
||||
|
||||
const closeWarning = () => {
|
||||
eventTracking.sendMB('compile-time-warning-dismissed', {})
|
||||
setShowCompileTimeWarning(false)
|
||||
}
|
||||
|
||||
const handleUpgradeClick = useCallback(event => {
|
||||
event.preventDefault()
|
||||
startFreeTrial('compile-time-warning')
|
||||
}, [])
|
||||
|
||||
if (!showCompileTimeWarning) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="alert alert-success compile-time-warning" role="alert">
|
||||
<Button
|
||||
className="close"
|
||||
data-dismiss="alert"
|
||||
aria-label="Close"
|
||||
onClick={closeWarning}
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</Button>
|
||||
<div>
|
||||
<div className="warning-text">
|
||||
<Trans
|
||||
i18nKey="approaching_compile_timeout_limit_upgrade_for_more_compile_time"
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
components={[<strong style={{ display: 'inline-block' }} />]}
|
||||
/>
|
||||
</div>
|
||||
<div className="upgrade-prompt">
|
||||
<Button bsStyle="primary" bsSize="sm" onClick={handleUpgradeClick}>
|
||||
{t('upgrade')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(CompileTimeWarning)
|
|
@ -1,5 +1,6 @@
|
|||
import { memo, Suspense } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import CompileTimeWarning from './compile-time-warning'
|
||||
import PdfLogsViewer from './pdf-logs-viewer'
|
||||
import PdfViewer from './pdf-viewer'
|
||||
import LoadingSpinner from '../../../shared/components/loading-spinner'
|
||||
|
@ -15,6 +16,7 @@ function PdfPreviewPane() {
|
|||
return (
|
||||
<div className={classes}>
|
||||
<PdfHybridPreviewToolbar />
|
||||
<CompileTimeWarning />
|
||||
<Suspense fallback={<LoadingPreview />}>
|
||||
<div className="pdf-viewer">
|
||||
<PdfViewer />
|
||||
|
|
|
@ -48,11 +48,13 @@ export function DetachCompileProvider({ children }) {
|
|||
setHasLintingError: _setHasLintingError,
|
||||
setHighlights: _setHighlights,
|
||||
setPosition: _setPosition,
|
||||
setShowCompileTimeWarning: _setShowCompileTimeWarning,
|
||||
setShowLogs: _setShowLogs,
|
||||
toggleLogs: _toggleLogs,
|
||||
setStopOnFirstError: _setStopOnFirstError,
|
||||
setStopOnValidationError: _setStopOnValidationError,
|
||||
showLogs: _showLogs,
|
||||
showCompileTimeWarning: _showCompileTimeWarning,
|
||||
showFasterCompilesFeedbackUI: _showFasterCompilesFeedbackUI,
|
||||
stopOnFirstError: _stopOnFirstError,
|
||||
stopOnValidationError: _stopOnValidationError,
|
||||
|
@ -185,6 +187,12 @@ export function DetachCompileProvider({ children }) {
|
|||
'detacher',
|
||||
'detached'
|
||||
)
|
||||
const [showCompileTimeWarning] = useDetachStateWatcher(
|
||||
'showCompileTimeWarning',
|
||||
_showCompileTimeWarning,
|
||||
'detacher',
|
||||
'detached'
|
||||
)
|
||||
const [showLogs] = useDetachStateWatcher(
|
||||
'showLogs',
|
||||
_showLogs,
|
||||
|
@ -276,6 +284,12 @@ export function DetachCompileProvider({ children }) {
|
|||
'detacher',
|
||||
'detached'
|
||||
)
|
||||
const setShowCompileTimeWarning = useDetachAction(
|
||||
'setShowCompileTimeWarning',
|
||||
_setShowCompileTimeWarning,
|
||||
'detached',
|
||||
'detacher'
|
||||
)
|
||||
const setShowLogs = useDetachAction(
|
||||
'setShowLogs',
|
||||
_setShowLogs,
|
||||
|
@ -376,11 +390,13 @@ export function DetachCompileProvider({ children }) {
|
|||
setHasLintingError,
|
||||
setHighlights,
|
||||
setPosition,
|
||||
setShowCompileTimeWarning,
|
||||
setShowLogs,
|
||||
toggleLogs,
|
||||
setStopOnFirstError,
|
||||
setStopOnValidationError,
|
||||
showLogs,
|
||||
showCompileTimeWarning,
|
||||
showFasterCompilesFeedbackUI,
|
||||
startCompile,
|
||||
stopCompile,
|
||||
|
@ -425,10 +441,12 @@ export function DetachCompileProvider({ children }) {
|
|||
setHasLintingError,
|
||||
setHighlights,
|
||||
setPosition,
|
||||
setShowCompileTimeWarning,
|
||||
setShowLogs,
|
||||
toggleLogs,
|
||||
setStopOnFirstError,
|
||||
setStopOnValidationError,
|
||||
showCompileTimeWarning,
|
||||
showLogs,
|
||||
showFasterCompilesFeedbackUI,
|
||||
startCompile,
|
||||
|
|
|
@ -27,6 +27,9 @@ import { useIdeContext } from './ide-context'
|
|||
import { useProjectContext } from './project-context'
|
||||
import { useEditorContext } from './editor-context'
|
||||
import { buildFileList } from '../../features/pdf-preview/util/file-list'
|
||||
import { useSplitTestContext } from './split-test-context'
|
||||
|
||||
const ONE_DAY = 24 * 60 * 60 * 24 * 1000
|
||||
|
||||
export const LocalCompileContext = createContext()
|
||||
|
||||
|
@ -57,10 +60,12 @@ export const CompileContextPropTypes = {
|
|||
setHasLintingError: PropTypes.func.isRequired, // only for storybook
|
||||
setHighlights: PropTypes.func.isRequired,
|
||||
setPosition: PropTypes.func.isRequired,
|
||||
setShowCompileTimeWarning: PropTypes.func.isRequired,
|
||||
setShowLogs: PropTypes.func.isRequired,
|
||||
toggleLogs: PropTypes.func.isRequired,
|
||||
setStopOnFirstError: PropTypes.func.isRequired,
|
||||
setStopOnValidationError: PropTypes.func.isRequired,
|
||||
showCompileTimeWarning: PropTypes.bool.isRequired,
|
||||
showLogs: PropTypes.bool.isRequired,
|
||||
showFasterCompilesFeedbackUI: PropTypes.bool.isRequired,
|
||||
stopOnFirstError: PropTypes.bool.isRequired,
|
||||
|
@ -82,9 +87,21 @@ export function LocalCompileProvider({ children }) {
|
|||
|
||||
const { _id: projectId, rootDocId } = useProjectContext()
|
||||
|
||||
const { splitTestVariants } = useSplitTestContext()
|
||||
|
||||
// whether a compile is in progress
|
||||
const [compiling, setCompiling] = useState(false)
|
||||
|
||||
// whether to show the compile time warning
|
||||
const [showCompileTimeWarning, setShowCompileTimeWarning] = useState(false)
|
||||
|
||||
// the last time the compile time warning was displayed
|
||||
const [lastDisplay, setLastDisplay] = usePersistedState(
|
||||
'compile-time-warning-displayed-at',
|
||||
0,
|
||||
true
|
||||
)
|
||||
|
||||
// the log entries parsed from the compile output log
|
||||
const [logEntries, setLogEntries] = useScopeValueSetterOnly('pdf.logEntries')
|
||||
|
||||
|
@ -264,6 +281,31 @@ export function LocalCompileProvider({ children }) {
|
|||
}
|
||||
}, [compiledOnce, currentDoc, compiler])
|
||||
|
||||
useEffect(() => {
|
||||
const compileTimeWarningEnabled =
|
||||
splitTestVariants['compile-time-warning'] === 'show-upgrade-prompt'
|
||||
|
||||
if (compileTimeWarningEnabled && compiling && isProjectOwner) {
|
||||
const timeout = window.setTimeout(() => {
|
||||
if (lastDisplay && Date.now() - lastDisplay < ONE_DAY) {
|
||||
return
|
||||
}
|
||||
setShowCompileTimeWarning(true)
|
||||
setLastDisplay(Date.now())
|
||||
}, 30000)
|
||||
|
||||
return () => {
|
||||
window.clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [
|
||||
compiling,
|
||||
isProjectOwner,
|
||||
lastDisplay,
|
||||
setLastDisplay,
|
||||
splitTestVariants,
|
||||
])
|
||||
|
||||
// handle the data returned from a compile request
|
||||
// note: this should _only_ run when `data` changes,
|
||||
// the other dependencies must all be static
|
||||
|
@ -522,6 +564,8 @@ export function LocalCompileProvider({ children }) {
|
|||
setHasLintingError, // only for stories
|
||||
setHighlights,
|
||||
setPosition,
|
||||
showCompileTimeWarning,
|
||||
setShowCompileTimeWarning,
|
||||
setShowLogs,
|
||||
toggleLogs,
|
||||
setStopOnFirstError,
|
||||
|
@ -570,8 +614,10 @@ export function LocalCompileProvider({ children }) {
|
|||
setHasLintingError, // only for stories
|
||||
setHighlights,
|
||||
setPosition,
|
||||
setShowCompileTimeWarning,
|
||||
setStopOnFirstError,
|
||||
setStopOnValidationError,
|
||||
showCompileTimeWarning,
|
||||
showLogs,
|
||||
showFasterCompilesFeedbackUI,
|
||||
startCompile,
|
||||
|
|
|
@ -743,3 +743,36 @@ CodeMirror
|
|||
.editor-container {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.compile-time-warning {
|
||||
position: absolute;
|
||||
right: @margin-sm;
|
||||
top: @margin-xl;
|
||||
padding: @padding-sm;
|
||||
background-color: @ol-green;
|
||||
width: 400px;
|
||||
z-index: @zindex-popover;
|
||||
box-shadow: 5px 5px 6px rgba(0, 0, 0, 0.3);
|
||||
|
||||
.warning-text {
|
||||
max-width: 300px;
|
||||
padding-right: @alert-padding;
|
||||
display: inline-block;
|
||||
font-size: @font-size-small;
|
||||
}
|
||||
.upgrade-prompt {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
top: @margin-lg;
|
||||
right: 32px;
|
||||
}
|
||||
|
||||
button.btn {
|
||||
background-color: @ol-darker-green;
|
||||
|
||||
&.close {
|
||||
background-color: @ol-green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
@ol-green: #138a07;
|
||||
@ol-type-green: #107206;
|
||||
@ol-dark-green: #004a0e;
|
||||
@ol-darker-green: #083c03;
|
||||
@ol-blue: #3e70bb;
|
||||
@ol-dark-blue: #2857a1;
|
||||
@ol-red: #c9453e;
|
||||
|
|
|
@ -1792,5 +1792,6 @@
|
|||
"get_most_subscription_by_checking_premium_features": "Get the most out of your __appName__ subscription by checking out the list of <0>__appName__’s premium features</0>.",
|
||||
"would_you_like_to_see_a_university_subscription": "Would you like to see a university-wide __appName__ subscription at your university?",
|
||||
"student_and_faculty_support_make_difference": "Student and faculty support make a difference! We can share this information with our contacts at your university when discussing an Overleaf institutional account.",
|
||||
"show_your_support": "Show your support"
|
||||
"show_your_support": "Show your support",
|
||||
"approaching_compile_timeout_limit_upgrade_for_more_compile_time": "You are approaching your compile timeout limit. Upgrade to <strong>Overleaf Premium</strong> for <0>4x more</0> compile time."
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue