mirror of
https://github.com/overleaf/overleaf.git
synced 2024-10-17 21:05:04 -04:00
b2ef7a935f
* Add a unit test on `SubscriptionFormatters.formatPrice` * Add JSDoc to `formatPrice` Also: Name the functions before exporting: This fixes my IDE (WebStorm) navigation * Make `'USD'` the default param instead of reassigning * Create `formatCurrency` function * Use `formatCurrency` in SubscriptionFormatters * Use an `isNoCentsCurrency` logic for `CLP` `JPY` `KRW` `VND` And remove custom `CLP` logic and locale * Add `locale` param to `formatPrice` * Generate `groups.json` and `localizedPlanPricing.json` ``` bin/exec web node ./scripts/recurly/recurly_prices.js --download -o prices.json bin/exec web node ./scripts/plan-prices/plans.js -f ../../prices.json -o dir ``` * Update scripts/plan-prices/plans.js to generate numbers instead of localized amounts * Generate `groups.json` and `localizedPlanPricing.json` ``` bin/exec web node ./scripts/recurly/recurly_prices.js --download -o prices.json bin/exec web node ./scripts/plan-prices/plans.js -f ../../prices.json -o dir ``` * Remove generation of `plans.json` As /services/web/frontend/js/main/plans.js was removed in https://github.com/overleaf/internal/pull/12593 * Sort currencies in alphabetical order in scripts/plan-prices/plans.js * Generate `groups.json` and `localizedPlanPricing.json` ``` bin/exec web node ./scripts/recurly/recurly_prices.js --download -o prices.json bin/exec web node ./scripts/plan-prices/plans.js -f ../../prices.json -o dir ``` * Use `formatCurrency` in price-summary.tsx * Use `formatCurrency` in Subscription Pug files * Fix unit tests SubscriptionHelperTests.js * Remove unused `currencySymbol` * Change to `formatCurrency` in other React components * Add `CurrencyCode` JSDoc types * Duplicate `formatCurrency` into services/web/app/src/util * Wrap tests in a top-level describe block * Use `narrowSymbol` * Fix tests with `narrowSymbol` expects * Revert deletion of old `formatPrice` in SubscriptionFormatters.js * Rename `formatCurrency` -> `formatCurrencyLocalized` * Revert deletion of `CurrencySymbol` * Add split-test in SubscriptionController.js * Add split-test in SubscriptionViewModelBuilder.js * Add split-test in plans * Add split-test in subscription-dashboard-context.tsx * Add split-test in 4 more components * Update tests * Show currency and payment methods in interstitial page * Fix `–` being printed. Use `–` instead * Fix test with NOK * Storybook: Fix missing `SplitTestProvider` * Storybook: Revert "Remove unused `currencySymbol`" This reverts commit e55387d4753f97bbf8e39e0fdc3ad17312122aaa. * Replace `getSplitTestVariant` by `useSplitTestContext` * Use parameterize currencyFormat in `generateInitialLocalizedGroupPrice` * Fixup import paths of `formatCurrencyLocalized` * Replace `% 1 === 0` by `Number.isInteger` * Add comment explaining that any combinations of languages/currencies could happen * Fixup after rebase: import `useSplitTestContext` * Revert "Remove SplitTestProvider from subscription root" This reverts commit be9f378fda715b86589ab0759737581c72321d87. * Revert "Remove split test provider from some tests" This reverts commit 985522932b550cfd38fa6a4f4c3d2ebaee6ff7df. GitOrigin-RevId: 59a83cbbe0f7cc7e45f189c654e23fcf9bfa37af
171 lines
5.2 KiB
JavaScript
171 lines
5.2 KiB
JavaScript
import getMeta from '../../../utils/meta'
|
|
import { swapModal } from '../../utils/swapModal'
|
|
import * as eventTracking from '../../../infrastructure/event-tracking'
|
|
import {
|
|
createLocalizedGroupPlanPrice,
|
|
formatCurrencyDefault,
|
|
} from '../utils/group-plan-pricing'
|
|
import { getSplitTestVariant } from '@/utils/splitTestUtils'
|
|
import { formatCurrencyLocalized } from '@/shared/utils/currency'
|
|
|
|
function getFormValues() {
|
|
const modalEl = document.querySelector('[data-ol-group-plan-modal]')
|
|
const planCode = modalEl.querySelector(
|
|
'input[name="plan_code"]:checked'
|
|
).value
|
|
const size = modalEl.querySelector('#size').value
|
|
const currency = modalEl.querySelector('#currency').value
|
|
const usage = modalEl.querySelector('#usage').checked
|
|
? 'educational'
|
|
: 'enterprise'
|
|
return { planCode, size, currency, usage }
|
|
}
|
|
|
|
export function updateGroupModalPlanPricing() {
|
|
const modalEl = document.querySelector('[data-ol-group-plan-modal]')
|
|
const { planCode, size, currency, usage } = getFormValues()
|
|
|
|
const localCcyVariant = getSplitTestVariant('local-ccy-format')
|
|
|
|
const { localizedPrice, localizedPerUserPrice } =
|
|
createLocalizedGroupPlanPrice({
|
|
plan: planCode,
|
|
licenseSize: size,
|
|
currency,
|
|
usage,
|
|
formatCurrency:
|
|
localCcyVariant === 'enabled'
|
|
? formatCurrencyLocalized
|
|
: formatCurrencyDefault,
|
|
})
|
|
|
|
modalEl.querySelectorAll('[data-ol-group-plan-plan-code]').forEach(el => {
|
|
el.hidden = el.getAttribute('data-ol-group-plan-plan-code') !== planCode
|
|
})
|
|
modalEl.querySelectorAll('[data-ol-group-plan-usage]').forEach(el => {
|
|
el.hidden = el.getAttribute('data-ol-group-plan-usage') !== usage
|
|
})
|
|
modalEl.querySelector('[data-ol-group-plan-display-price]').innerText =
|
|
localizedPrice
|
|
modalEl
|
|
.querySelectorAll('[data-ol-group-plan-price-per-user]')
|
|
.forEach(el => {
|
|
el.innerText = `${localizedPerUserPrice} ${el.getAttribute(
|
|
'data-ol-group-plan-price-per-user'
|
|
)}`
|
|
})
|
|
|
|
modalEl.querySelector('[data-ol-group-plan-educational-discount]').hidden =
|
|
usage !== 'educational'
|
|
|
|
modalEl.querySelector(
|
|
'[data-ol-group-plan-educational-discount-applied]'
|
|
).hidden = size < 10
|
|
|
|
modalEl.querySelector(
|
|
'[data-ol-group-plan-educational-discount-ineligible]'
|
|
).hidden = size >= 10
|
|
}
|
|
|
|
const modalEl = $('[data-ol-group-plan-modal]')
|
|
modalEl
|
|
.on('shown.bs.modal', function () {
|
|
const path = `${window.location.pathname}${window.location.search}`
|
|
history.replaceState(null, document.title, path + '#groups')
|
|
eventTracking.sendMB('form-submitted-groups-modal-open')
|
|
})
|
|
.on('hidden.bs.modal', function () {
|
|
const path = `${window.location.pathname}${window.location.search}`
|
|
history.replaceState(null, document.title, path)
|
|
})
|
|
|
|
function showGroupPlanModal() {
|
|
modalEl.modal()
|
|
eventTracking.send(
|
|
'subscription-funnel',
|
|
'plans-page',
|
|
'group-inquiry-potential'
|
|
) // deprecated by plans-page-click
|
|
}
|
|
|
|
document
|
|
.querySelectorAll('[data-ol-group-plan-form] select')
|
|
.forEach(el => el.addEventListener('change', updateGroupModalPlanPricing))
|
|
document
|
|
.querySelectorAll('[data-ol-group-plan-form] input')
|
|
.forEach(el => el.addEventListener('change', updateGroupModalPlanPricing))
|
|
document.querySelectorAll('[data-ol-purchase-group-plan]').forEach(el =>
|
|
el.addEventListener('click', e => {
|
|
e.preventDefault()
|
|
|
|
const { planCode, size, currency, usage } = getFormValues()
|
|
const queryParams = new URLSearchParams(
|
|
Object.entries({
|
|
planCode: `group_${planCode}_${size}_${usage}`,
|
|
currency,
|
|
itm_campaign: 'groups',
|
|
})
|
|
)
|
|
const itmContent = getMeta('ol-itm_content')
|
|
if (itmContent) {
|
|
queryParams.set('itm_content', itmContent)
|
|
}
|
|
eventTracking.sendMB('groups-modal-click', {
|
|
plan: planCode,
|
|
users: size,
|
|
currency,
|
|
type: usage,
|
|
})
|
|
const url = new URL('/user/subscription/new', window.origin)
|
|
url.search = queryParams.toString()
|
|
window.location = url.toString()
|
|
})
|
|
)
|
|
|
|
document.querySelectorAll('[data-ol-open-group-plan-modal]').forEach(el => {
|
|
const location = el.getAttribute('data-ol-location')
|
|
el.addEventListener('click', function (e) {
|
|
e.preventDefault()
|
|
eventTracking.sendMB('plans-page-click', {
|
|
button: 'group',
|
|
location,
|
|
'billing-period': 'annual',
|
|
})
|
|
showGroupPlanModal()
|
|
})
|
|
})
|
|
|
|
document
|
|
.querySelectorAll('[data-ol-open-contact-form-for-more-than-50-licenses]')
|
|
.forEach(el => {
|
|
el.addEventListener('click', function (e) {
|
|
e.preventDefault()
|
|
swapModal(
|
|
'[data-ol-group-plan-modal]',
|
|
'[data-ol-contact-form-modal="general"]'
|
|
)
|
|
})
|
|
})
|
|
|
|
function updateGroupModalPlanPricingIfAvailable() {
|
|
const isGroupPlanModalAvailable = document.querySelector(
|
|
'[data-ol-group-plan-modal]'
|
|
)
|
|
|
|
if (isGroupPlanModalAvailable) {
|
|
updateGroupModalPlanPricing()
|
|
}
|
|
}
|
|
|
|
updateGroupModalPlanPricingIfAvailable()
|
|
|
|
// When using browser back buttons, we need to update the pricing plan
|
|
// after the page has fully loaded as we need to wait for the previously
|
|
// selected values to load for e.g. size.
|
|
window.addEventListener('load', () => {
|
|
updateGroupModalPlanPricingIfAvailable()
|
|
})
|
|
|
|
if (window.location.hash === '#groups') {
|
|
showGroupPlanModal()
|
|
}
|