mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Implement Back to School 2023 banners and modal (#14363)
* Implement Back to School 2023 banners and modal * Only show WritefullPromoBanner if not showing BackToSchoolModal GitOrigin-RevId: 3bd2ea48fa6d66f112cc26662a61be05cf7daafd
This commit is contained in:
parent
3f7b84cb40
commit
43c92642c6
15 changed files with 311 additions and 3 deletions
|
@ -452,6 +452,7 @@ async function projectListPage(req, res, next) {
|
||||||
showInrGeoBanner,
|
showInrGeoBanner,
|
||||||
inrGeoBannerVariant,
|
inrGeoBannerVariant,
|
||||||
inrGeoBannerSplitTestName,
|
inrGeoBannerSplitTestName,
|
||||||
|
showBackToSchoolModal: Boolean(usersBestSubscription?.type === 'free'),
|
||||||
projectDashboardReact: true, // used in navbar
|
projectDashboardReact: true, // used in navbar
|
||||||
welcomePageRedesignVariant: welcomePageRedesignAssignment.variant,
|
welcomePageRedesignVariant: welcomePageRedesignAssignment.variant,
|
||||||
groupSubscriptionsPendingEnrollment:
|
groupSubscriptionsPendingEnrollment:
|
||||||
|
|
|
@ -130,6 +130,16 @@ async function plansPage(req, res) {
|
||||||
plansPageViewSegmentation[inrGeoBannerSplitTestName] = inrGeoBannerVariant
|
plansPageViewSegmentation[inrGeoBannerSplitTestName] = inrGeoBannerVariant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let showBackToSchoolBanner
|
||||||
|
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||||
|
if (userId) {
|
||||||
|
const usersBestSubscription =
|
||||||
|
await SubscriptionViewModelBuilder.promises.getBestSubscription({
|
||||||
|
_id: userId,
|
||||||
|
})
|
||||||
|
showBackToSchoolBanner = usersBestSubscription?.type === 'free'
|
||||||
|
}
|
||||||
|
|
||||||
AnalyticsManager.recordEventForSession(
|
AnalyticsManager.recordEventForSession(
|
||||||
req.session,
|
req.session,
|
||||||
'plans-page-view',
|
'plans-page-view',
|
||||||
|
@ -152,6 +162,7 @@ async function plansPage(req, res) {
|
||||||
initialLocalizedGroupPrice:
|
initialLocalizedGroupPrice:
|
||||||
SubscriptionHelper.generateInitialLocalizedGroupPrice(currency),
|
SubscriptionHelper.generateInitialLocalizedGroupPrice(currency),
|
||||||
showInrGeoBanner,
|
showInrGeoBanner,
|
||||||
|
showBackToSchoolBanner,
|
||||||
annualTrialsAssignment: annualTrialsAssignment?.variant,
|
annualTrialsAssignment: annualTrialsAssignment?.variant,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ block append meta
|
||||||
meta(name="ol-inrGeoBannerSplitTestName" data-type="string" content=inrGeoBannerSplitTestName)
|
meta(name="ol-inrGeoBannerSplitTestName" data-type="string" content=inrGeoBannerSplitTestName)
|
||||||
meta(name="ol-showLATAMBanner" data-type="boolean" content=showLATAMBanner)
|
meta(name="ol-showLATAMBanner" data-type="boolean" content=showLATAMBanner)
|
||||||
meta(name="ol-recommendedCurrency" data-type="string" content=recommendedCurrency)
|
meta(name="ol-recommendedCurrency" data-type="string" content=recommendedCurrency)
|
||||||
|
meta(name="ol-showBackToSchoolModal" data-type="boolean" content=showBackToSchoolModal)
|
||||||
meta(name="ol-welcomePageRedesignVariant" data-type="string" content=welcomePageRedesignVariant)
|
meta(name="ol-welcomePageRedesignVariant" data-type="string" content=welcomePageRedesignVariant)
|
||||||
meta(name="ol-groupSubscriptionsPendingEnrollment" data-type="json" content=groupSubscriptionsPendingEnrollment)
|
meta(name="ol-groupSubscriptionsPendingEnrollment" data-type="json" content=groupSubscriptionsPendingEnrollment)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,31 @@ block append meta
|
||||||
|
|
||||||
block content
|
block content
|
||||||
main.content.content-alt#main-content
|
main.content.content-alt#main-content
|
||||||
|
.container
|
||||||
|
.user-notifications
|
||||||
|
ul.list-unstyled(ng-cloak)
|
||||||
|
li.notification-entry
|
||||||
|
div.alert.alert-back-to-school(
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-prompt"
|
||||||
|
event-tracking-trigger="load"
|
||||||
|
event-segmentation='{"location": "interstitial-page-banner", "name": "bts2023", "content": "banner"}'
|
||||||
|
)
|
||||||
|
.notification-body
|
||||||
|
| 🎉
|
||||||
|
p
|
||||||
|
strong #{translate("back_to_school_banner_bargain_with_x_percent_off_in_school_or_not", {x: '15'})}
|
||||||
|
br
|
||||||
|
| #{translate("back_to_school_banner_hurry_offer_ends_sep_30")}
|
||||||
|
.notification-action
|
||||||
|
a.btn.btn-sm.btn-default-outline(
|
||||||
|
href="/about/back-to-school-promo-2023"
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-click"
|
||||||
|
event-tracking-trigger="click"
|
||||||
|
event-segmentation='{"location": "interstitial-page-banner", "name": "bts2023", "content": "banner", "type": "click"}'
|
||||||
|
) #{translate('claim_discounts')}
|
||||||
|
|
||||||
.content-page
|
.content-page
|
||||||
.plans
|
.plans
|
||||||
.container
|
.container
|
||||||
|
|
|
@ -14,6 +14,31 @@ block append meta
|
||||||
|
|
||||||
block content
|
block content
|
||||||
main.content.content-alt#main-content
|
main.content.content-alt#main-content
|
||||||
|
.container
|
||||||
|
.user-notifications
|
||||||
|
ul.list-unstyled(ng-cloak)
|
||||||
|
li.notification-entry
|
||||||
|
div.alert.alert-back-to-school(
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-prompt"
|
||||||
|
event-tracking-trigger="load"
|
||||||
|
event-segmentation='{"location": "interstitial-page-banner", "name": "bts2023", "content": "banner"}'
|
||||||
|
)
|
||||||
|
.notification-body
|
||||||
|
| 🎉
|
||||||
|
p
|
||||||
|
strong #{translate("back_to_school_banner_bargain_with_x_percent_off_in_school_or_not", {x: '15'})}
|
||||||
|
br
|
||||||
|
| #{translate("back_to_school_banner_hurry_offer_ends_sep_30")}
|
||||||
|
.notification-action
|
||||||
|
a.btn.btn-sm.btn-default-outline(
|
||||||
|
href="/about/back-to-school-promo-2023"
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-click"
|
||||||
|
event-tracking-trigger="click"
|
||||||
|
event-segmentation='{"location": "interstitial-page-banner", "name": "bts2023", "content": "banner", "type": "click"}'
|
||||||
|
) #{translate('claim_discounts')}
|
||||||
|
|
||||||
.content-page
|
.content-page
|
||||||
.plans
|
.plans
|
||||||
.container
|
.container
|
||||||
|
|
|
@ -14,6 +14,31 @@ block append meta
|
||||||
|
|
||||||
block content
|
block content
|
||||||
main.content.content-alt#main-content
|
main.content.content-alt#main-content
|
||||||
|
.container
|
||||||
|
.user-notifications
|
||||||
|
ul.list-unstyled(ng-cloak)
|
||||||
|
li.notification-entry
|
||||||
|
div.alert.alert-back-to-school(
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-prompt"
|
||||||
|
event-tracking-trigger="load"
|
||||||
|
event-segmentation='{"location": "interstitial-page-banner", "name": "bts2023", "content": "banner"}'
|
||||||
|
)
|
||||||
|
.notification-body
|
||||||
|
| 🎉
|
||||||
|
p
|
||||||
|
strong #{translate("back_to_school_banner_bargain_with_x_percent_off_in_school_or_not", {x: '15'})}
|
||||||
|
br
|
||||||
|
| #{translate("back_to_school_banner_hurry_offer_ends_sep_30")}
|
||||||
|
.notification-action
|
||||||
|
a.btn.btn-sm.btn-default-outline(
|
||||||
|
href="/about/back-to-school-promo-2023"
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-click"
|
||||||
|
event-tracking-trigger="click"
|
||||||
|
event-segmentation='{"location": "interstitial-page-banner", "name": "bts2023", "content": "banner", "type": "click"}'
|
||||||
|
) #{translate('claim_discounts')}
|
||||||
|
|
||||||
.content-page
|
.content-page
|
||||||
.plans
|
.plans
|
||||||
.container
|
.container
|
||||||
|
|
|
@ -12,12 +12,40 @@ block append meta
|
||||||
|
|
||||||
block content
|
block content
|
||||||
main.content.content-alt#main-content
|
main.content.content-alt#main-content
|
||||||
|
if showBackToSchoolBanner
|
||||||
|
.container(
|
||||||
|
)
|
||||||
|
.user-notifications
|
||||||
|
ul.list-unstyled(ng-cloak)
|
||||||
|
li.notification-entry
|
||||||
|
div.alert.alert-back-to-school(
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-prompt"
|
||||||
|
event-tracking-trigger="load"
|
||||||
|
event-segmentation='{"location": "plans-page-banner", "name": "bts2023", "content": "banner"}'
|
||||||
|
)
|
||||||
|
.notification-body
|
||||||
|
| 🎉
|
||||||
|
p
|
||||||
|
strong #{translate("back_to_school_banner_bargain_with_x_percent_off_in_school_or_not", {x: '15'})}
|
||||||
|
br
|
||||||
|
| #{translate("back_to_school_banner_hurry_offer_ends_sep_30")}
|
||||||
|
.notification-action
|
||||||
|
a.btn.btn-sm.btn-default-outline(
|
||||||
|
href="/about/back-to-school-promo-2023"
|
||||||
|
event-tracking-mb="true"
|
||||||
|
event-tracking="promo-click"
|
||||||
|
event-tracking-trigger="click"
|
||||||
|
event-segmentation='{"location": "plans-page-banner", "name": "bts2023", "content": "banner", "type": "click"}'
|
||||||
|
) #{translate('claim_discounts')}
|
||||||
|
|
||||||
.content-page
|
.content-page
|
||||||
.plans
|
.plans
|
||||||
.container(ng-cloak)
|
.container(ng-cloak)
|
||||||
if showInrGeoBanner
|
if showInrGeoBanner
|
||||||
div.alert.alert-success.text-centered !{translate("inr_discount_offer_plans_page_banner", {flag: '🇮🇳'})}
|
div.alert.alert-success.text-centered !{translate("inr_discount_offer_plans_page_banner", {flag: '🇮🇳'})}
|
||||||
|
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-12
|
.col-md-12
|
||||||
.page-header.centered.plans-header.text-centered.top-page-header
|
.page-header.centered.plans-header.text-centered.top-page-header
|
||||||
|
|
|
@ -86,6 +86,9 @@
|
||||||
"autocomplete": "",
|
"autocomplete": "",
|
||||||
"autocomplete_references": "",
|
"autocomplete_references": "",
|
||||||
"back": "",
|
"back": "",
|
||||||
|
"back_to_school_modal_bargain_with_x_percent_off": "",
|
||||||
|
"back_to_school_modal_offer_ends_sep_30": "",
|
||||||
|
"back_to_school_modal_offers_from_writefull_and_papers": "",
|
||||||
"back_to_subscription": "",
|
"back_to_subscription": "",
|
||||||
"back_to_your_projects": "",
|
"back_to_your_projects": "",
|
||||||
"beta_program_already_participating": "",
|
"beta_program_already_participating": "",
|
||||||
|
@ -139,6 +142,7 @@
|
||||||
"checking_project_github_status": "",
|
"checking_project_github_status": "",
|
||||||
"choose_a_custom_color": "",
|
"choose_a_custom_color": "",
|
||||||
"choose_from_group_members": "",
|
"choose_from_group_members": "",
|
||||||
|
"claim_discounts": "",
|
||||||
"clear_cached_files": "",
|
"clear_cached_files": "",
|
||||||
"clear_search": "",
|
"clear_search": "",
|
||||||
"click_here_to_view_sl_in_lng": "",
|
"click_here_to_view_sl_in_lng": "",
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import usePersistedState from '../../../../../shared/hooks/use-persisted-state'
|
||||||
|
import * as eventTracking from '../../../../../infrastructure/event-tracking'
|
||||||
|
import { Modal, Button } from 'react-bootstrap'
|
||||||
|
import AccessibleModal from '../../../../../shared/components/accessible-modal'
|
||||||
|
|
||||||
|
export default function BackToSchoolModal() {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [dismissedUntil, setDismissedUntil] = usePersistedState<
|
||||||
|
Date | undefined
|
||||||
|
>(`has_dismissed_back_to_school_modal_until`)
|
||||||
|
const viewEventSent = useRef<boolean>(false)
|
||||||
|
|
||||||
|
const [showModal, setShowModal] = useState(true)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dismissedUntil && new Date(dismissedUntil) > new Date()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!viewEventSent.current) {
|
||||||
|
eventTracking.sendMB('promo-prompt', {
|
||||||
|
name: 'bts2023',
|
||||||
|
location: 'dashboard-modal',
|
||||||
|
content: 'modal',
|
||||||
|
})
|
||||||
|
viewEventSent.current = true
|
||||||
|
}
|
||||||
|
}, [dismissedUntil])
|
||||||
|
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
eventTracking.sendMB('promo-click', {
|
||||||
|
name: 'bts2023',
|
||||||
|
location: 'dashboard-modal',
|
||||||
|
content: 'modal',
|
||||||
|
type: 'click',
|
||||||
|
})
|
||||||
|
|
||||||
|
setShowModal(false)
|
||||||
|
|
||||||
|
window.open('/about/back-to-school-promo-2023')
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const bannerDismissed = useCallback(() => {
|
||||||
|
eventTracking.sendMB('promo-dismiss', {
|
||||||
|
name: 'bts2023',
|
||||||
|
location: 'dashboard-modal',
|
||||||
|
content: 'modal',
|
||||||
|
})
|
||||||
|
const until = new Date()
|
||||||
|
until.setDate(until.getDate() + 14) // 14 days
|
||||||
|
setDismissedUntil(until)
|
||||||
|
}, [setDismissedUntil])
|
||||||
|
|
||||||
|
const handleHide = useCallback(() => {
|
||||||
|
setShowModal(false)
|
||||||
|
bannerDismissed()
|
||||||
|
}, [bannerDismissed])
|
||||||
|
|
||||||
|
const handleMaybeLater = useCallback(() => {
|
||||||
|
eventTracking.sendMB('promo-click', {
|
||||||
|
name: 'bts2023',
|
||||||
|
location: 'dashboard-modal',
|
||||||
|
content: 'modal',
|
||||||
|
type: 'pause',
|
||||||
|
})
|
||||||
|
setShowModal(false)
|
||||||
|
const until = new Date()
|
||||||
|
until.setDate(until.getDate() + 1) // 1 day
|
||||||
|
setDismissedUntil(until)
|
||||||
|
}, [setDismissedUntil])
|
||||||
|
|
||||||
|
if (dismissedUntil && new Date(dismissedUntil) > new Date()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AccessibleModal show={showModal} onHide={handleHide}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>
|
||||||
|
{t('back_to_school_modal_bargain_with_x_percent_off', { x: '15' })}
|
||||||
|
</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body className="modal-body-share">
|
||||||
|
<p>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
src="/img/subscriptions/back-to-school-modal.png"
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<p>{t('back_to_school_modal_offers_from_writefull_and_papers')}</p>
|
||||||
|
<p>
|
||||||
|
<strong>{t('back_to_school_modal_offer_ends_sep_30')}</strong>
|
||||||
|
</p>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button bsStyle="default" onClick={handleMaybeLater}>
|
||||||
|
{t('maybe_later')}
|
||||||
|
</Button>
|
||||||
|
<Button type="button" bsStyle="primary" onClick={handleClick}>
|
||||||
|
{t('claim_discounts')}
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</AccessibleModal>
|
||||||
|
)
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import INRBanner from './ads/inr-banner'
|
||||||
import LATAMBanner from './ads/latam-banner'
|
import LATAMBanner from './ads/latam-banner'
|
||||||
import getMeta from '../../../../utils/meta'
|
import getMeta from '../../../../utils/meta'
|
||||||
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
||||||
|
import BackToSchoolModal from './ads/back-to-school-modal'
|
||||||
|
|
||||||
type Subscription = {
|
type Subscription = {
|
||||||
groupId: string
|
groupId: string
|
||||||
|
@ -28,8 +29,12 @@ function UserNotifications() {
|
||||||
'ol-groupSubscriptionsPendingEnrollment',
|
'ol-groupSubscriptionsPendingEnrollment',
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
const showBackToSchoolModal = getMeta('ol-showBackToSchoolModal', false)
|
||||||
|
|
||||||
const showInrGeoBanner = getMeta('ol-showInrGeoBanner', false)
|
const showInrGeoBanner = getMeta('ol-showInrGeoBanner', false)
|
||||||
const inrGeoBannerVariant = getMeta('ol-inrGeoBannerVariant', 'default')
|
const inrGeoBannerVariant = showBackToSchoolModal
|
||||||
|
? 'default' // This test should be disabled to prevent double modals, but sanity check to be safe
|
||||||
|
: getMeta('ol-inrGeoBannerVariant', 'default')
|
||||||
const inrGeoBannerSplitTestName = getMeta(
|
const inrGeoBannerSplitTestName = getMeta(
|
||||||
'ol-inrGeoBannerSplitTestName',
|
'ol-inrGeoBannerSplitTestName',
|
||||||
'unassigned'
|
'unassigned'
|
||||||
|
@ -61,7 +66,11 @@ function UserNotifications() {
|
||||||
) : (
|
) : (
|
||||||
<GroupsAndEnterpriseBanner />
|
<GroupsAndEnterpriseBanner />
|
||||||
)}
|
)}
|
||||||
<WritefullPromoBanner />
|
{showBackToSchoolModal ? (
|
||||||
|
<BackToSchoolModal />
|
||||||
|
) : (
|
||||||
|
<WritefullPromoBanner />
|
||||||
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-top: @header-height;
|
padding-top: 0px; // temporarily change from @header-height to 0px for back to school banner changes
|
||||||
h1,
|
h1,
|
||||||
p,
|
p,
|
||||||
label {
|
label {
|
||||||
|
@ -331,6 +331,41 @@
|
||||||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.back-to-school {
|
||||||
|
.back-to-school-banner {
|
||||||
|
background: @blue-10;
|
||||||
|
padding: 0px 16px 0px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid @blue-20;
|
||||||
|
color: @neutral-90;
|
||||||
|
.banner-row {
|
||||||
|
height: 56px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.claim-my-discount {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navbar-default {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: @screen-sm-max) {
|
@media only screen and (max-width: @screen-sm-max) {
|
||||||
.doc-history-example {
|
.doc-history-example {
|
||||||
margin-bottom: @margin-md;
|
margin-bottom: @margin-md;
|
||||||
|
|
|
@ -84,6 +84,32 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Back to school promo
|
||||||
|
*/
|
||||||
|
|
||||||
|
.alert-back-to-school {
|
||||||
|
.alert-variant(@green-10; #BBDBB8; @neutral-90);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #bbdbb8;
|
||||||
|
box-shadow: none !important;
|
||||||
|
|
||||||
|
.notification-body {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-default-outline {
|
||||||
|
border: 1px solid @neutral-60;
|
||||||
|
background: white;
|
||||||
|
font-size: 16px;
|
||||||
|
color: @neutral-90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-default-outline:active {
|
||||||
|
background: @neutral-40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Plans Test
|
Plans Test
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -138,6 +138,12 @@
|
||||||
"back_to_account_settings": "Back to account settings",
|
"back_to_account_settings": "Back to account settings",
|
||||||
"back_to_editor": "Back to the editor",
|
"back_to_editor": "Back to the editor",
|
||||||
"back_to_log_in": "Back to log in",
|
"back_to_log_in": "Back to log in",
|
||||||
|
"back_to_school_banner_bargain_with_x_percent_off_in_school_or_not": "Grab a back-to-school bargain with __x__% off all individual Overleaf subscriptions (whether you’re in school or not!)",
|
||||||
|
"back_to_school_banner_hurry_offer_ends_sep_30": "Hurry! Offer ends September 30.",
|
||||||
|
"back_to_school_homepage_bargain_with_x_percent_off": "Grab a back-to-school bargain with 15% off all individual Overleaf subscriptions",
|
||||||
|
"back_to_school_modal_bargain_with_x_percent_off": "Everyone can grab a back-to-school bargain this fall with __x__% off an Overleaf subscription",
|
||||||
|
"back_to_school_modal_offer_ends_sep_30": "Offer ends September 30.",
|
||||||
|
"back_to_school_modal_offers_from_writefull_and_papers": "And with offers from Writefull and Papers too, you’ll have the tools you need to write smarter this year.",
|
||||||
"back_to_subscription": "Back to Subscription",
|
"back_to_subscription": "Back to Subscription",
|
||||||
"back_to_your_projects": "Back to your projects",
|
"back_to_your_projects": "Back to your projects",
|
||||||
"become_an_advisor": "Become an __appName__ advisor",
|
"become_an_advisor": "Become an __appName__ advisor",
|
||||||
|
@ -229,6 +235,8 @@
|
||||||
"choose_from_group_members": "Choose from Group Members",
|
"choose_from_group_members": "Choose from Group Members",
|
||||||
"choose_your_plan": "Choose your plan",
|
"choose_your_plan": "Choose your plan",
|
||||||
"city": "City",
|
"city": "City",
|
||||||
|
"claim_discounts": "Claim discounts",
|
||||||
|
"claim_my_discount": "Claim my discount",
|
||||||
"clear_cached_files": "Clear cached files",
|
"clear_cached_files": "Clear cached files",
|
||||||
"clear_search": "clear search",
|
"clear_search": "clear search",
|
||||||
"clear_sessions": "Clear Sessions",
|
"clear_sessions": "Clear Sessions",
|
||||||
|
|
BIN
services/web/public/img/subscriptions/back-to-school-modal.png
Normal file
BIN
services/web/public/img/subscriptions/back-to-school-modal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
|
@ -78,6 +78,7 @@ describe('SubscriptionController', function () {
|
||||||
buildPlansList: sinon.stub(),
|
buildPlansList: sinon.stub(),
|
||||||
promises: {
|
promises: {
|
||||||
buildUsersSubscriptionViewModel: sinon.stub().resolves({}),
|
buildUsersSubscriptionViewModel: sinon.stub().resolves({}),
|
||||||
|
getBestSubscription: sinon.stub().resolves({}),
|
||||||
},
|
},
|
||||||
buildPlansListForSubscriptionDash: sinon
|
buildPlansListForSubscriptionDash: sinon
|
||||||
.stub()
|
.stub()
|
||||||
|
|
Loading…
Reference in a new issue