Merge pull request #13801 from overleaf/ii-review-panel-migration-upgrade-track-changes-modal

[web] Create upgrade track changes modal

GitOrigin-RevId: 704ddef862ea9a2f8ca2bf63880da6e88f783724
This commit is contained in:
ilkin-overleaf 2023-07-12 17:13:08 +03:00 committed by Copybot
parent 84bbdf9772
commit dbef201e3f
6 changed files with 156 additions and 4 deletions

View file

@ -16,6 +16,7 @@
"accept": "",
"accept_all": "",
"accept_invitation": "",
"accept_or_reject_each_changes_individually": "",
"accepted_invite": "",
"account_has_been_link_to_institution_account": "",
"account_has_past_due_invoice_change_plan_warning": "",
@ -215,6 +216,7 @@
"deleted_by_on": "",
"deleting": "",
"demonstrating_git_integration": "",
"demonstrating_track_changes_feature": "",
"department": "",
"descending": "",
"description": "",
@ -719,6 +721,7 @@
"percent_discount_for_groups": "",
"plan": "",
"plan_tooltip": "",
"please_ask_the_project_owner_to_upgrade_to_track_changes": "",
"please_change_primary_to_remove": "",
"please_check_your_inbox": "",
"please_check_your_inbox_to_confirm": "",
@ -844,6 +847,7 @@
"reverse_x_sort_order": "",
"revert_pending_plan_change": "",
"review": "",
"review_your_peers_work": "",
"revoke": "",
"revoke_invite": "",
"rich_text_is_only_available_for_tex_files": "",
@ -879,6 +883,7 @@
"search_whole_word": "",
"search_within_selection": "",
"security": "",
"see_changes_in_your_documents_live": "",
"select_a_file": "",
"select_a_file_figure_modal": "",
"select_a_payment_method": "",
@ -1053,6 +1058,7 @@
"total_per_year": "",
"total_with_subtotal_and_tax": "",
"total_words": "",
"track_any_change_in_real_time": "",
"track_changes": "",
"track_changes_for_everyone": "",
"track_changes_for_x": "",
@ -1119,6 +1125,7 @@
"upgrade_for_longer_compiles": "",
"upgrade_now": "",
"upgrade_to_get_feature": "",
"upgrade_to_track_changes": "",
"upload": "",
"upload_from_computer": "",
"upload_project": "",

View file

@ -1,15 +1,24 @@
import { useRef } from 'react'
import { useState, useRef } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import Tooltip from '../../../../../shared/components/tooltip'
import Icon from '../../../../../shared/components/icon'
import TrackChangesToggle from './track-changes-toggle'
import UpgradeTrackChangesModal from '../upgrade-track-changes-modal'
import { useProjectContext } from '../../../../../shared/context/project-context'
import {
useReviewPanelUpdaterFnsContext,
useReviewPanelValueContext,
} from '../../../context/review-panel/review-panel-context'
import classnames from 'classnames'
import useCollapseHeight from '../hooks/use-collapse-height'
import { send, sendMB } from '../../../../../infrastructure/event-tracking'
import classnames from 'classnames'
const sendAnalytics = () => {
send('subscription-funnel', 'editor-click-feature', 'real-time-track-changes')
sendMB('paywall-prompt', {
'paywall-type': 'track-changes',
})
}
function ToggleMenu() {
const { t } = useTranslation()
@ -29,9 +38,20 @@ function ToggleMenu() {
formattedProjectMembers,
} = useReviewPanelValueContext()
const [showModal, setShowModal] = useState(false)
const containerRef = useRef<HTMLUListElement | null>(null)
useCollapseHeight(containerRef, shouldCollapse)
const handleToggleFullTCStateCollapse = () => {
if (project.features.trackChanges) {
setShouldCollapse(value => !value)
} else {
sendAnalytics()
setShowModal(true)
}
}
return (
<>
<span className="review-panel-toolbar-label">
@ -43,7 +63,7 @@ function ToggleMenu() {
<button
className="review-panel-toolbar-collapse-button"
onClick={() => setShouldCollapse(value => !value)}
onClick={handleToggleFullTCStateCollapse}
>
{wantTrackChanges ? (
// eslint-disable-next-line react/jsx-key
@ -164,6 +184,8 @@ function ToggleMenu() {
/>
</li>
</ul>
<UpgradeTrackChangesModal show={showModal} setShow={setShowModal} />
</>
)
}

View file

@ -0,0 +1,105 @@
import { useTranslation } from 'react-i18next'
import { Row, Col, Button, Modal } from 'react-bootstrap'
import AccessibleModal from '../../../../shared/components/accessible-modal'
import Icon from '../../../../shared/components/icon'
import { useProjectContext } from '../../../../shared/context/project-context'
import { useUserContext } from '../../../../shared/context/user-context'
import { startFreeTrial, upgradePlan } from '../../../../main/account-upgrade'
type UpgradeTrackChangesModalProps = {
show: boolean
setShow: React.Dispatch<React.SetStateAction<boolean>>
}
function UpgradeTrackChangesModal({
show,
setShow,
}: UpgradeTrackChangesModalProps) {
const { t } = useTranslation()
const project = useProjectContext()
const user = useUserContext()
return (
<AccessibleModal show={show} onHide={() => setShow(false)}>
<Modal.Header closeButton>
<h3>{t('upgrade_to_track_changes')}</h3>
</Modal.Header>
<Modal.Body>
<div className="teaser-video-container">
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
<video className="teaser-video" autoPlay loop>
<source
src="/img/teasers/track-changes/teaser-track-changes.mp4"
type="video/mp4"
/>
<img
src="/img/teasers/track-changes/teaser-track-changes.gif"
alt={t('demonstrating_track_changes_feature')}
/>
</video>
</div>
<h4 className="teaser-title">
{t('see_changes_in_your_documents_live')}
</h4>
<p className="small">{t('refresh_page_after_starting_free_trial')}</p>
<Row>
<Col md={10} mdOffset={1}>
<ul className="list-unstyled">
{[
t('track_any_change_in_real_time'),
t('review_your_peers_work'),
t('accept_or_reject_each_changes_individually'),
].map(translation => (
<li key={translation}>
<Icon type="check" /> {translation}
</li>
))}
</ul>
</Col>
</Row>
{project.owner && (
<Row className="text-center">
{project.owner._id === user.id ? (
user.allowedFreeTrial ? (
<Button
bsStyle={null}
className="btn-primary"
onClick={() => startFreeTrial('track-changes')}
>
{t('try_it_for_free')}
</Button>
) : (
<Button
bsStyle={null}
className="btn-primary"
onClick={() => upgradePlan('project-sharing')}
>
{t('upgrade')}
</Button>
)
) : (
<p>
<strong>
{t(
'please_ask_the_project_owner_to_upgrade_to_track_changes'
)}
</strong>
</p>
)}
</Row>
)}
</Modal.Body>
<Modal.Footer>
<Button
bsStyle={null}
className="btn-secondary"
onClick={() => setShow(false)}
>
{t('close')}
</Button>
</Modal.Footer>
</AccessibleModal>
)
}
export default UpgradeTrackChangesModal

View file

@ -1,8 +1,8 @@
import { useState, useMemo, useCallback } from 'react'
import useScopeValue from '../../../../../shared/hooks/use-scope-value'
import useScopeEventEmitter from '../../../../../shared/hooks/use-scope-event-emitter'
import { ReviewPanelState } from '../types/review-panel-state'
import { sendMB } from '../../../../../infrastructure/event-tracking'
import { ReviewPanelState } from '../types/review-panel-state'
import * as ReviewPanel from '../types/review-panel-state'
import { SubView } from '../../../../../../../types/review-panel/review-panel'
import { ReviewPanelCommentEntry } from '../../../../../../../types/review-panel/entry'

View file

@ -346,6 +346,7 @@
"deleted_files": "Deleted Files",
"deleting": "Deleting",
"demonstrating_git_integration": "Demonstrating Git integration",
"demonstrating_track_changes_feature": "Demonstrating Track Changes feature",
"department": "Department",
"descending": "Descending",
"description": "Description",

View file

@ -264,4 +264,21 @@ describe('<ReviewPanel />', function () {
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('add comment', function () {})
})
describe('upgrade track changes', function () {
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('renders modal', function () {})
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('closes modal', function () {})
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('opens subscription page after clicking on `upgrade`', function () {})
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('opens subscription page after clicking on `try it for free`', function () {})
// eslint-disable-next-line mocha/no-skipped-tests
it.skip('shows `ask project owner to upgrade` message', function () {})
})
})