From e5ddc9e1f672f512d9c66831dfccec253d95a564 Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Fri, 28 Mar 2025 12:04:41 +0200 Subject: [PATCH] Merge pull request #24430 from overleaf/ii-flexible-group-licensing-tear-down-feature-flag [web] Tear down flexible group licensing feature flag GitOrigin-RevId: 181713f1f2371b51cbc4256debea59bbcf3668f3 --- .../Subscription/SubscriptionController.js | 8 - .../SubscriptionGroupController.mjs | 17 -- .../Subscription/SubscriptionRouter.mjs | 5 - .../UserMembershipController.mjs | 6 - .../subscriptions/plans/_plans_faq_tabs.pug | 112 ++++----- .../web/frontend/extracted-translations.json | 9 - .../components/group-members.tsx | 24 +- .../dashboard/group-settings-button.tsx | 6 +- .../dashboard/managed-group-subscriptions.tsx | 20 +- .../dashboard/personal-subscription.tsx | 18 +- .../dashboard/premium-features-link.tsx | 27 +-- .../states/active/active-ai-addon.tsx | 221 ------------------ services/web/locales/en.json | 9 - .../components/group-members.spec.tsx | 44 ++-- .../managed-group-subscriptions.test.tsx | 6 +- .../dashboard/personal-subscription.test.tsx | 2 +- .../dashboard/subscription-dashboard.test.tsx | 7 +- .../successful-subscription.test.tsx | 10 +- .../SubscriptionGroupControllerTests.mjs | 27 --- 19 files changed, 94 insertions(+), 484 deletions(-) delete mode 100644 services/web/frontend/js/features/subscription/components/dashboard/states/active/active-ai-addon.tsx diff --git a/services/web/app/src/Features/Subscription/SubscriptionController.js b/services/web/app/src/Features/Subscription/SubscriptionController.js index 784083fdd8..cb8a293fb4 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionController.js +++ b/services/web/app/src/Features/Subscription/SubscriptionController.js @@ -56,13 +56,6 @@ async function userSubscriptionPage(req, res) { const showGroupDiscount = groupPricingDiscount.variant === 'enabled' - const { variant: flexibleLicensingVariant } = - await SplitTestHandler.promises.getAssignment( - req, - res, - 'flexible-group-licensing' - ) - const results = await SubscriptionViewModelBuilder.promises.buildUsersSubscriptionViewModel( user, @@ -147,7 +140,6 @@ async function userSubscriptionPage(req, res) { (managedUsersResults?.[0] === true || groupSSOResults?.[0] === true) && isGroupAdmin && - flexibleLicensingVariant === 'enabled' && plan?.canUseFlexibleLicensing ) } diff --git a/services/web/app/src/Features/Subscription/SubscriptionGroupController.mjs b/services/web/app/src/Features/Subscription/SubscriptionGroupController.mjs index c9837fb7b2..14d73f91de 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionGroupController.mjs +++ b/services/web/app/src/Features/Subscription/SubscriptionGroupController.mjs @@ -8,8 +8,6 @@ import SessionManager from '../Authentication/SessionManager.js' import UserAuditLogHandler from '../User/UserAuditLogHandler.js' import { expressify } from '@overleaf/promise-utils' import Modules from '../../infrastructure/Modules.js' -import SplitTestHandler from '../SplitTests/SplitTestHandler.js' -import ErrorController from '../Errors/ErrorController.js' import UserGetter from '../User/UserGetter.js' import { Subscription } from '../../models/Subscription.js' import { isProfessionalGroupPlan } from './PlansHelper.mjs' @@ -288,20 +286,6 @@ async function submitForm(req, res) { res.sendStatus(204) } -async function flexibleLicensingSplitTest(req, res, next) { - const { variant } = await SplitTestHandler.promises.getAssignment( - req, - res, - 'flexible-group-licensing' - ) - - if (variant !== 'enabled') { - return ErrorController.notFound(req, res) - } - - next() -} - async function subscriptionUpgradePage(req, res) { try { const userId = SessionManager.getLoggedInUserId(req.session) @@ -409,7 +393,6 @@ export default { removeSelfFromGroup: expressify(removeSelfFromGroup), addSeatsToGroupSubscription: expressify(addSeatsToGroupSubscription), submitForm: expressify(submitForm), - flexibleLicensingSplitTest: expressify(flexibleLicensingSplitTest), previewAddSeatsSubscriptionChange: expressify( previewAddSeatsSubscriptionChange ), diff --git a/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs b/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs index 073ed68eae..0bb30b578e 100644 --- a/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs +++ b/services/web/app/src/Features/Subscription/SubscriptionRouter.mjs @@ -73,7 +73,6 @@ export default { '/user/subscription/group/add-users', AuthenticationController.requireLogin(), RateLimiterMiddleware.rateLimit(subscriptionRateLimiter), - SubscriptionGroupController.flexibleLicensingSplitTest, SubscriptionGroupController.addSeatsToGroupSubscription ) @@ -108,7 +107,6 @@ export default { '/user/subscription/group/upgrade-subscription', AuthenticationController.requireLogin(), RateLimiterMiddleware.rateLimit(subscriptionRateLimiter), - SubscriptionGroupController.flexibleLicensingSplitTest, SubscriptionGroupController.subscriptionUpgradePage ) @@ -123,7 +121,6 @@ export default { '/user/subscription/group/missing-billing-information', AuthenticationController.requireLogin(), RateLimiterMiddleware.rateLimit(subscriptionRateLimiter), - SubscriptionGroupController.flexibleLicensingSplitTest, SubscriptionGroupController.missingBillingInformation ) @@ -131,7 +128,6 @@ export default { '/user/subscription/group/manually-collected-subscription', AuthenticationController.requireLogin(), RateLimiterMiddleware.rateLimit(subscriptionRateLimiter), - SubscriptionGroupController.flexibleLicensingSplitTest, SubscriptionGroupController.manuallyCollectedSubscription ) @@ -139,7 +135,6 @@ export default { '/user/subscription/group/subtotal-limit-exceeded', AuthenticationController.requireLogin(), RateLimiterMiddleware.rateLimit(subscriptionRateLimiter), - SubscriptionGroupController.flexibleLicensingSplitTest, SubscriptionGroupController.subtotalLimitExceeded ) diff --git a/services/web/app/src/Features/UserMembership/UserMembershipController.mjs b/services/web/app/src/Features/UserMembership/UserMembershipController.mjs index 547b3ba854..1c8bee3f55 100644 --- a/services/web/app/src/Features/UserMembership/UserMembershipController.mjs +++ b/services/web/app/src/Features/UserMembership/UserMembershipController.mjs @@ -32,12 +32,6 @@ async function manageGroupMembers(req, res, next) { ) const ssoConfig = await SSOConfig.findById(subscription.ssoConfig).exec() - await SplitTestHandler.promises.getAssignment( - req, - res, - 'flexible-group-licensing' - ) - await SplitTestHandler.promises.getAssignment(req, res, 'bootstrap-5-groups') const plan = PlansLocator.findLocalPlanInSettings(subscription.planCode) diff --git a/services/web/app/views/subscriptions/plans/_plans_faq_tabs.pug b/services/web/app/views/subscriptions/plans/_plans_faq_tabs.pug index dcbfbb1901..7f41c4d83e 100644 --- a/services/web/app/views/subscriptions/plans/_plans_faq_tabs.pug +++ b/services/web/app/views/subscriptions/plans/_plans_faq_tabs.pug @@ -165,56 +165,15 @@ mixin overleafGroupPlans() .collapse(id="overleafGroupPlansQ3") .custom-accordion-body | The educational discount for group subscriptions is for students or faculty who are using Overleaf primarily for teaching. - if canUseFlexibleLicensing - .custom-accordion-item - button.custom-accordion-header.collapsed(type="button" data-toggle="collapse" data-target="#overleafGroupPlansQ4" aria-expanded="false" aria-controls="overleafGroupPlansQ4") - | How do I add more licenses to my group subscription, and what will it cost? - span.custom-accordion-icon - i.material-symbols.material-symbols-outlined(aria-hidden="true") keyboard_arrow_down - .collapse(id="overleafGroupPlansQ4") - .custom-accordion-body - div - | You can add up to 20 licenses using the - a.inline-green-link( - target="_blank" - href="/user/subscription" - event-tracking="plans-page-click" - event-tracking-mb="true" - event-tracking-trigger="click" - event-segmentation={ button: 'contact', location: 'faq' } - ) - span subscription management page - | accessed by going to Account > - a.inline-green-link( - target="_blank" - href="/user/subscription" - event-tracking="plans-page-click" - event-tracking-mb="true" - event-tracking-trigger="click" - event-segmentation={ button: 'contact', location: 'faq' } - ) - span Subscription - | when logged into Overleaf. The cost per license will be prorated at the current per license rate, and will end with your existing renewal date. - div.mt-2 - | If you need more than 20 licenses added to your subscription, please - a.inline-green-link( - target="_blank" - href="/for/contact-sales" - event-tracking="plans-page-click" - event-tracking-mb="true" - event-tracking-trigger="click" - event-segmentation={ button: 'contact', location: 'faq' } - ) - span contact the Sales team - | . - .custom-accordion-item - button.custom-accordion-header.collapsed(type="button" data-toggle="collapse" data-target="#overleafGroupPlansQ5" aria-expanded="false" aria-controls="overleafGroupPlansQ5") - | How do I upgrade my plan from Group Standard to Group Professional? - span.custom-accordion-icon - i.material-symbols.material-symbols-outlined(aria-hidden="true") keyboard_arrow_down - .collapse(id="overleafGroupPlansQ5") - .custom-accordion-body - | You can upgrade your plan from Group Standard to Group Professional on the + .custom-accordion-item + button.custom-accordion-header.collapsed(type="button" data-toggle="collapse" data-target="#overleafGroupPlansQ4" aria-expanded="false" aria-controls="overleafGroupPlansQ4") + | How do I add more licenses to my group subscription, and what will it cost? + span.custom-accordion-icon + i.material-symbols.material-symbols-outlined(aria-hidden="true") keyboard_arrow_down + .collapse(id="overleafGroupPlansQ4") + .custom-accordion-body + div + | You can add up to 20 licenses using the a.inline-green-link( target="_blank" href="/user/subscription" @@ -224,15 +183,44 @@ mixin overleafGroupPlans() event-segmentation={ button: 'contact', location: 'faq' } ) span subscription management page - | . - else - .custom-accordion-item - button.custom-accordion-header.collapsed(type="button" data-toggle="collapse" data-target="#overleafGroupPlansQ4" aria-expanded="false" aria-controls="overleafGroupPlansQ4") - | Can I add more users to my group subscription at a later date? - span.custom-accordion-icon - i.material-symbols.material-symbols-outlined(aria-hidden="true") keyboard_arrow_down - .collapse(id="overleafGroupPlansQ4") - .custom-accordion-body - | Yes. To add more users to your subscription you’ll need to - button.btn-link.inline-green-link(data-ol-open-contact-form-modal="general") - span #{translate("contact_us")} + | accessed by going to Account > + a.inline-green-link( + target="_blank" + href="/user/subscription" + event-tracking="plans-page-click" + event-tracking-mb="true" + event-tracking-trigger="click" + event-segmentation={ button: 'contact', location: 'faq' } + ) + span Subscription + | when logged into Overleaf. The cost per license will be prorated at the current per license rate, and will end with your existing renewal date. + div.mt-2 + | If you need more than 20 licenses added to your subscription, please + a.inline-green-link( + target="_blank" + href="/for/contact-sales" + event-tracking="plans-page-click" + event-tracking-mb="true" + event-tracking-trigger="click" + event-segmentation={ button: 'contact', location: 'faq' } + ) + span contact the Sales team + | . + .custom-accordion-item + button.custom-accordion-header.collapsed(type="button" data-toggle="collapse" data-target="#overleafGroupPlansQ5" aria-expanded="false" aria-controls="overleafGroupPlansQ5") + | How do I upgrade my plan from Group Standard to Group Professional? + span.custom-accordion-icon + i.material-symbols.material-symbols-outlined(aria-hidden="true") keyboard_arrow_down + .collapse(id="overleafGroupPlansQ5") + .custom-accordion-body + | You can upgrade your plan from Group Standard to Group Professional on the + a.inline-green-link( + target="_blank" + href="/user/subscription" + event-tracking="plans-page-click" + event-tracking-mb="true" + event-tracking-trigger="click" + event-segmentation={ button: 'contact', location: 'faq' } + ) + span subscription management page + | . diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index ed0606ab4a..e6ed0fcf4c 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -74,13 +74,11 @@ "add_files": "", "add_more_editors": "", "add_more_managers": "", - "add_more_members": "", "add_more_users": "", "add_more_users_to_my_plan": "", "add_new_email": "", "add_on": "", "add_ons": "", - "add_ons_are": "", "add_or_remove_project_from_tag": "", "add_overleaf_assist": "", "add_overleaf_assist_to_your_group_subscription": "", @@ -609,7 +607,6 @@ "get_error_assist": "", "get_exclusive_access_to_labs": "", "get_in_touch": "", - "get_most_subscription_by_checking_features": "", "get_most_subscription_discover_premium_features": "", "git": "", "git_authentication_token": "", @@ -952,7 +949,6 @@ "make_private": "", "manage_beta_program_membership": "", "manage_files_from_your_dropbox_folder": "", - "manage_group_managers": "", "manage_group_members_subtext": "", "manage_group_settings": "", "manage_group_settings_subtext": "", @@ -960,7 +956,6 @@ "manage_group_settings_subtext_managed_users": "", "manage_institution_managers": "", "manage_managers_subtext": "", - "manage_members": "", "manage_newsletter": "", "manage_publisher_managers": "", "manage_sessions": "", @@ -1326,7 +1321,6 @@ "remote_service_error": "", "remove": "", "remove_access": "", - "remove_add_on": "", "remove_email_address": "", "remove_from_group": "", "remove_link": "", @@ -1634,7 +1628,6 @@ "sure_you_want_to_leave_group": "", "switch_back_to_monthly_pay_20_more": "", "switch_compile_mode_for_faster_draft_compilation": "", - "switch_plan": "", "switch_to_editor": "", "switch_to_new_editor": "", "switch_to_old_editor": "", @@ -1892,7 +1885,6 @@ "untrash": "", "update": "", "update_account_info": "", - "update_billing_details": "", "update_dropbox_settings": "", "update_your_billing_details": "", "updates_to_project_sharing": "", @@ -2095,7 +2087,6 @@ "your_new_plan": "", "your_password_was_detected": "", "your_plan": "", - "your_plan_is": "", "your_plan_is_changing_at_term_end": "", "your_plan_is_limited_to_n_editors": "", "your_plan_is_limited_to_n_editors_plural": "", diff --git a/services/web/frontend/js/features/group-management/components/group-members.tsx b/services/web/frontend/js/features/group-management/components/group-members.tsx index 3fb36f7688..e6ab3c71b4 100644 --- a/services/web/frontend/js/features/group-management/components/group-members.tsx +++ b/services/web/frontend/js/features/group-management/components/group-members.tsx @@ -5,7 +5,6 @@ import getMeta from '../../../utils/meta' import { useGroupMembersContext } from '../context/group-members-context' import ErrorAlert from './error-alert' import MembersList from './members-table/members-list' -import { useFeatureFlag } from '@/shared/context/split-test-context' import { sendMB } from '../../../infrastructure/event-tracking' import BackButton from '@/features/group-management/components/back-button' import OLRow from '@/features/ui/components/ol/ol-row' @@ -30,17 +29,12 @@ export default function GroupMembers() { paths, } = useGroupMembersContext() const [emailString, setEmailString] = useState('') - const isFlexibleGroupLicensingFeatureFlagEnabled = useFeatureFlag( - 'flexible-group-licensing' - ) const groupId = getMeta('ol-groupId') const groupName = getMeta('ol-groupName') const groupSize = getMeta('ol-groupSize') const canUseFlexibleLicensing = getMeta('ol-canUseFlexibleLicensing') const canUseAddSeatsFeature = getMeta('ol-canUseAddSeatsFeature') - const isFlexibleGroupLicensing = - canUseFlexibleLicensing && isFlexibleGroupLicensingFeatureFlagEnabled const handleEmailsChange = useCallback( e => { @@ -59,7 +53,7 @@ export default function GroupMembers() { } const groupSizeDetails = () => { - if (isFlexibleGroupLicensing) { + if (canUseFlexibleLicensing) { return ( @@ -145,11 +139,7 @@ export default function GroupMembers() { className="add-more-members-form" data-testid="add-more-members-form" > -

- {isFlexibleGroupLicensing - ? t('invite_more_members') - : t('add_more_members')} -

+

{t('invite_more_members')}

@@ -170,19 +160,15 @@ export default function GroupMembers() { bs3Props={{ loading: inviteMemberLoading ? ( <> - {isFlexibleGroupLicensing - ? t('inviting') - : t('adding')} + {t('inviting')} … - ) : isFlexibleGroupLicensing ? ( - t('invite') ) : ( - t('add') + t('invite') ), }} > - {isFlexibleGroupLicensing ? t('invite') : t('add')} + {t('invite')} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx b/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx index 798d3faa92..dca1242b10 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx @@ -1,6 +1,5 @@ import { RowLink } from '@/features/subscription/components/dashboard/row-link' import { useTranslation } from 'react-i18next' -import { useFeatureFlag } from '@/shared/context/split-test-context' import { useLocation } from '@/shared/hooks/use-location' import MaterialIcon from '@/shared/components/material-icon' import OLTag from '@/features/ui/components/ol/ol-tag' @@ -36,13 +35,10 @@ function AvailableWithGroupProfessionalBadge() { function useGroupSettingsButton(subscription: ManagedGroupSubscription) { const { t } = useTranslation() - const isFlexibleGroupLicensing = useFeatureFlag('flexible-group-licensing') const subscriptionHasManagedUsers = subscription.features?.managedUsers === true const subscriptionHasGroupSSO = subscription.features?.groupSSO === true - const heading = isFlexibleGroupLicensing - ? t('group_settings') - : t('manage_group_settings') + const heading = t('group_settings') let groupSettingRowSubText = '' if (subscriptionHasGroupSSO && subscriptionHasManagedUsers) { diff --git a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx index c6b33d7c6b..18b43bd7da 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx @@ -8,7 +8,6 @@ import { useSubscriptionDashboardContext } from '../../context/subscription-dash import { RowLink } from './row-link' import { ManagedGroupSubscription } from '../../../../../../types/subscription/dashboard/subscription' import { bsVersion } from '@/features/utils/bootstrap-5' -import { useFeatureFlag } from '@/shared/context/split-test-context' import classnames from 'classnames' function ManagedGroupAdministrator({ @@ -91,7 +90,6 @@ function ManagedGroupAdministrator({ export default function ManagedGroupSubscriptions() { const { t } = useTranslation() const { managedGroupSubscriptions } = useSubscriptionDashboardContext() - const isFlexibleGroupLicensing = useFeatureFlag('flexible-group-licensing') if (!managedGroupSubscriptions) { return null @@ -115,21 +113,13 @@ export default function ManagedGroupSubscriptions() {
    @@ -141,11 +131,7 @@ export default function ManagedGroupSubscriptions() { )} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx b/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx index 28e5999206..7f56daf750 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription.tsx @@ -1,7 +1,5 @@ import { Trans, useTranslation } from 'react-i18next' import { RecurlySubscription } from '../../../../../../types/subscription/dashboard/subscription' -import { ActiveSubscription } from './states/active/active' -import { ActiveAiAddonSubscription } from './states/active/active-ai-addon' import { PausedSubscription } from './states/active/paused' import { ActiveSubscriptionNew } from '@/features/subscription/components/dashboard/states/active/active-new' import { CanceledSubscription } from './states/canceled' @@ -9,8 +7,6 @@ import { ExpiredSubscription } from './states/expired' import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context' import PersonalSubscriptionRecurlySyncEmail from './personal-subscription-recurly-sync-email' import OLNotification from '@/features/ui/components/ol/ol-notification' -import { isStandaloneAiPlanCode, AI_ADD_ON_CODE } from '../../data/add-on-codes' -import { useFeatureFlag } from '@/shared/context/split-test-context' function PastDueSubscriptionAlert({ subscription, @@ -44,22 +40,10 @@ function PersonalSubscriptionStates({ }) { const { t } = useTranslation() const state = subscription?.recurly.state - const isFlexibleGroupLicensing = useFeatureFlag('flexible-group-licensing') - const hasAiAddon = subscription?.addOns?.some( - addOn => addOn.addOnCode === AI_ADD_ON_CODE - ) - - const onAiStandalonePlan = isStandaloneAiPlanCode(subscription.planCode) - const planHasAi = onAiStandalonePlan || hasAiAddon - - if (state === 'active' && isFlexibleGroupLicensing) { + if (state === 'active') { // This version handles subscriptions with and without addons return - } else if (state === 'active' && planHasAi) { - return - } else if (state === 'active') { - return } else if (state === 'canceled') { return } else if (state === 'expired') { diff --git a/services/web/frontend/js/features/subscription/components/dashboard/premium-features-link.tsx b/services/web/frontend/js/features/subscription/components/dashboard/premium-features-link.tsx index 925f80e71b..068857f6c8 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/premium-features-link.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/premium-features-link.tsx @@ -1,28 +1,15 @@ import { Trans } from 'react-i18next' -import { useFeatureFlag } from '@/shared/context/split-test-context' function PremiumFeaturesLink() { - const isFlexibleGroupLicensing = useFeatureFlag('flexible-group-licensing') - return (

    - {isFlexibleGroupLicensing ? ( - , - ]} - /> - ) : ( - , - ]} - /> - )} + , + ]} + />

    ) } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-ai-addon.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-ai-addon.tsx deleted file mode 100644 index f004770989..0000000000 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-ai-addon.tsx +++ /dev/null @@ -1,221 +0,0 @@ -import { useTranslation, Trans } from 'react-i18next' -import { PriceExceptions } from '../../../shared/price-exceptions' -import { useSubscriptionDashboardContext } from '../../../../context/subscription-dashboard-context' -import { RecurlySubscription } from '../../../../../../../../types/subscription/dashboard/subscription' -import { CancelSubscription } from './cancel-plan/cancel-subscription' -import { PendingPlanChange } from './pending-plan-change' -import SubscriptionRemainder from './subscription-remainder' -import { ChangePlanModal } from './change-plan/modals/change-plan-modal' -import { ConfirmChangePlanModal } from './change-plan/modals/confirm-change-plan-modal' -import { KeepCurrentPlanModal } from './change-plan/modals/keep-current-plan-modal' -import { ChangeToGroupModal } from './change-plan/modals/change-to-group-modal' -import { CancelAiAddOnModal } from './change-plan/modals/cancel-ai-add-on-modal' -import { PendingRecurlyPlan } from '../../../../../../../../types/subscription/plan' -import { - ADD_ON_NAME, - AI_ADD_ON_CODE, - isStandaloneAiPlanCode, -} from '../../../../data/add-on-codes' -import { CancelSubscriptionButton } from './cancel-subscription-button' - -import OLButton from '@/features/ui/components/ol/ol-button' - -export function ActiveAiAddonSubscription({ - subscription, -}: { - subscription: RecurlySubscription -}) { - const { t } = useTranslation() - const { - recurlyLoadError, - showCancellation, - setModalIdShown, - memberGroupSubscriptions, - institutionMemberships, - } = useSubscriptionDashboardContext() - if (showCancellation) return - - const onStandalonePlan = isStandaloneAiPlanCode(subscription.planCode) - - let planName - if (onStandalonePlan) { - planName = 'Overleaf Free' - if (institutionMemberships && institutionMemberships.length > 0) { - planName = 'Overleaf Professional' - } - if (memberGroupSubscriptions.length > 0) { - if ( - memberGroupSubscriptions.some(s => s.planLevelName === 'Professional') - ) { - planName = 'Overleaf Professional' - } else { - planName = 'Overleaf Standard' - } - } - } else { - planName = subscription.plan.name - } - - const handlePlanChange = () => setModalIdShown('change-plan') - - const handleCancelClick = () => setModalIdShown('cancel-ai-add-on') - - return ( - <> -

    - }} - /> -

    -

    - }} - /> -

    -

    - {subscription.pendingPlan && ( - - )} -

    - {subscription.pendingPlan && - subscription.pendingPlan.name !== subscription.plan.name && ( -

    {t('want_change_to_apply_before_plan_end')}

    - )} -

    - , - // eslint-disable-next-line react/jsx-key - , - ]} - /> -

    - - {!recurlyLoadError && ( -

    - - - -

    - )} - {!recurlyLoadError && ( -

    - {onStandalonePlan ? ( - - ) : ( - - )} -

    - )} -

    - - {t('view_invoices')} - -

    -

    - - {t('update_billing_details')} - -

    - - - - - - - - ) -} - -function StandaloneAiPlanActions({ - handlePlanChange, - handleCancelClick, -}: { - handlePlanChange(): void - handleCancelClick(): void -}) { - const { t } = useTranslation() - return ( - <> - - {t('upgrade')} - - - {t('remove_add_on')} - - - ) -} - -function PlanWithAddonsActions({ - handlePlanChange, - handleCancelClick, - subscription, -}: { - handlePlanChange(): void - handleCancelClick(): void - subscription: RecurlySubscription -}) { - const { t } = useTranslation() - - const pendingPlan = subscription.pendingPlan as PendingRecurlyPlan - - const hasAiAddon = subscription.addOns?.some( - addOn => addOn.addOnCode === AI_ADD_ON_CODE - ) - - const pendingCancellation = Boolean( - hasAiAddon && - pendingPlan && - !pendingPlan.addOns?.some(addOn => addOn.add_on_code === AI_ADD_ON_CODE) - ) - return ( - <> - - {t('switch_plan')} - - - <> - {!pendingCancellation && ( - - {t('remove_add_on')} - - )} - - - - ) -} diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 2d029eccf6..a889bbde31 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -89,13 +89,11 @@ "add_files": "Add Files", "add_more_editors": "Add more editors", "add_more_managers": "Add more managers", - "add_more_members": "Add more members", "add_more_users": "Add more users", "add_more_users_to_my_plan": "Add more users to my plan", "add_new_email": "Add new email", "add_on": "Add-on", "add_ons": "Add-ons", - "add_ons_are": "Add-ons: __addOnName__", "add_or_remove_project_from_tag": "Add or remove project from tag __tagName__", "add_overleaf_assist": "Add Overleaf Assist", "add_overleaf_assist_to_your_group_subscription": "Add Overleaf Assist to your group subscription", @@ -810,7 +808,6 @@ "get_in_touch": "Get in touch", "get_in_touch_having_problems": "Get in touch with support if you’re having problems", "get_involved": "Get involved", - "get_most_subscription_by_checking_features": "Get the most out of your __appName__ subscription by checking out <0>__appName__’s features.", "get_most_subscription_discover_premium_features": "Get the most from your __appName__ subscription. <0>Discover premium features.", "get_the_best_overleaf_experience": "Get the best Overleaf experience", "get_the_most_out_headline": "Get the most out of __appName__ with features such as:", @@ -1260,7 +1257,6 @@ "make_private": "Make Private", "manage_beta_program_membership": "Manage Beta Program Membership", "manage_files_from_your_dropbox_folder": "Manage files from your Dropbox folder", - "manage_group_managers": "Manage group managers", "manage_group_members_subtext": "Add or remove members from your group subscription", "manage_group_settings": "Manage group settings", "manage_group_settings_subtext": "Configure and manage SSO and Managed Users", @@ -1268,7 +1264,6 @@ "manage_group_settings_subtext_managed_users": "Turn on Managed Users", "manage_institution_managers": "Manage institution managers", "manage_managers_subtext": "Assign or remove manager privileges", - "manage_members": "Manage members", "manage_newsletter": "Manage Your Newsletter Preferences", "manage_publisher_managers": "Manage publisher managers", "manage_sessions": "Manage Your Sessions", @@ -1761,7 +1756,6 @@ "remote_service_error": "The remote service produced an error", "remove": "Remove", "remove_access": "Remove access", - "remove_add_on": "Remove add-on", "remove_email_address": "Remove email address", "remove_from_group": "Remove from group", "remove_link": "Remove link", @@ -2133,7 +2127,6 @@ "sv": "Swedish", "switch_back_to_monthly_pay_20_more": "Switch back to monthly (20% more)", "switch_compile_mode_for_faster_draft_compilation": "Switch compile mode for faster draft compilation", - "switch_plan": "Switch plan", "switch_to_editor": "Switch to editor", "switch_to_new_editor": "Switch to new editor", "switch_to_old_editor": "Switch to old editor", @@ -2429,7 +2422,6 @@ "untrash": "Restore", "update": "Update", "update_account_info": "Update Account Info", - "update_billing_details": "Update billing details", "update_dropbox_settings": "Update Dropbox Settings", "update_your_billing_details": "Update your billing details", "updates_to_project_sharing": "Updates to project sharing", @@ -2657,7 +2649,6 @@ "your_password_has_been_successfully_changed": "Your password has been successfully changed", "your_password_was_detected": "Your password is on a <0>public list of known compromised passwords. Keep your account safe by changing your password now.", "your_plan": "Your plan", - "your_plan_is": "Your plan: __planName__", "your_plan_is_changing_at_term_end": "Your plan is changing to <0>__pendingPlanName__ at the end of the current billing period.", "your_plan_is_limited_to_n_editors": "Your plan allows __count__ collaborator with edit access and unlimited viewers.", "your_plan_is_limited_to_n_editors_plural": "Your plan allows __count__ collaborators with edit access and unlimited viewers.", diff --git a/services/web/test/frontend/features/group-management/components/group-members.spec.tsx b/services/web/test/frontend/features/group-management/components/group-members.spec.tsx index aa564d028f..bc0f5c3d69 100644 --- a/services/web/test/frontend/features/group-management/components/group-members.spec.tsx +++ b/services/web/test/frontend/features/group-management/components/group-members.spec.tsx @@ -1,7 +1,6 @@ import GroupMembers from '@/features/group-management/components/group-members' import { GroupMembersProvider } from '@/features/group-management/context/group-members-context' import { User } from '../../../../../types/group-management/user' -import { SplitTestProvider } from '@/shared/context/split-test-context' const GROUP_ID = '777fff777fff' const PATHS = { @@ -14,11 +13,9 @@ const PATHS = { describe('GroupMembers', function () { function mountGroupMembersProvider() { cy.mount( - - - - - + + + ) } @@ -49,11 +46,9 @@ describe('GroupMembers', function () { }) cy.mount( - - - - - + + + ) }) @@ -517,9 +512,6 @@ describe('GroupMembers', function () { win.metaAttributesCache.set('ol-groupId', GROUP_ID) win.metaAttributesCache.set('ol-groupName', 'My Awesome Team') win.metaAttributesCache.set('ol-groupSize', 10) - win.metaAttributesCache.set('ol-splitTestVariants', { - 'flexible-group-licensing': 'enabled', - }) win.metaAttributesCache.set('ol-canUseFlexibleLicensing', true) win.metaAttributesCache.set('ol-canUseAddSeatsFeature', true) }) @@ -534,11 +526,9 @@ describe('GroupMembers', function () { }) cy.mount( - - - - - + + + ) cy.findByTestId('group-size-details').contains( @@ -556,11 +546,9 @@ describe('GroupMembers', function () { }) cy.mount( - - - - - + + + ) cy.findByTestId('group-size-details').contains( @@ -575,11 +563,9 @@ describe('GroupMembers', function () { }) cy.mount( - - - - - + + + ) cy.findByTestId('group-size-details').within(() => { diff --git a/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx index 18ed3ea124..b4e701e5b5 100644 --- a/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx +++ b/services/web/test/frontend/features/subscription/components/dashboard/managed-group-subscriptions.test.tsx @@ -190,7 +190,7 @@ describe('', function () { }, ], }) - await screen.findAllByText('Manage group settings') + await screen.findAllByText('Group settings') await screen.findAllByText('Configure and manage SSO and Managed Users') }) @@ -207,7 +207,7 @@ describe('', function () { }, ], }) - await screen.findAllByText('Manage group settings') + await screen.findAllByText('Group settings') await screen.findAllByText('Turn on Managed Users') expect(screen.queryByText('Configure and manage SSO and Managed Users')).to .not.exist @@ -227,7 +227,7 @@ describe('', function () { }, ], }) - await screen.findAllByText('Manage group settings') + await screen.findAllByText('Group settings') await screen.findAllByText('Configure and manage SSO') expect(screen.queryByText('Turn on Managed Users')).to.not.exist expect(screen.queryByText('Configure and manage SSO and Managed Users')).to diff --git a/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx index 884f528466..6b40314688 100644 --- a/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx +++ b/services/web/test/frontend/features/subscription/components/dashboard/personal-subscription.test.tsx @@ -72,7 +72,7 @@ describe('', function () { ], }) - screen.getByText('You are currently subscribed to the', { exact: false }) + screen.getByRole('heading', { name: /billing/i }) }) it('renders the canceled dash', function () { diff --git a/services/web/test/frontend/features/subscription/components/dashboard/subscription-dashboard.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/subscription-dashboard.test.tsx index 80137a6e1f..77d377cd60 100644 --- a/services/web/test/frontend/features/subscription/components/dashboard/subscription-dashboard.test.tsx +++ b/services/web/test/frontend/features/subscription/components/dashboard/subscription-dashboard.test.tsx @@ -31,11 +31,8 @@ describe('', function () { }) }) - it('renders the "Get the most out of your" subscription text', function () { - screen.getByText( - 'Get the most out of your Overleaf subscription by checking out', - { exact: false } - ) + it('renders the "Get the most from your subscription" text', function () { + screen.getByText(/get the most from your Overleaf subscription/i) }) }) diff --git a/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx b/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx index 58828bebe3..33979e6b9e 100644 --- a/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx +++ b/services/web/test/frontend/features/subscription/components/successful-subscription/successful-subscription.test.tsx @@ -36,8 +36,8 @@ describe('successful subscription page', function () { screen.getByText( /it’s support from people like yourself that allows .* to continue to grow and improve/i ) - expect(screen.getByText(/get the most out of your/i).textContent).to.match( - /get the most out of your .* subscription by checking out .*’s features/i + expect(screen.getByText(/get the most from your/i).textContent).to.match( + /get the most from your .* subscription\. discover premium features/i ) expect( screen @@ -66,9 +66,11 @@ describe('successful subscription page', function () { ) const helpLink = screen.getByRole('link', { - name: /.*’s features/i, + name: /discover premium features/i, }) - expect(helpLink.getAttribute('href')).to.equal('/about/features-overview') + expect(helpLink.getAttribute('href')).to.equal( + '/learn/how-to/Overleaf_premium_features' + ) const backToYourProjectsLink = screen.getByRole('link', { name: /back to your projects/i, diff --git a/services/web/test/unit/src/Subscription/SubscriptionGroupControllerTests.mjs b/services/web/test/unit/src/Subscription/SubscriptionGroupControllerTests.mjs index e7ea218cc1..b3b6b66dbd 100644 --- a/services/web/test/unit/src/Subscription/SubscriptionGroupControllerTests.mjs +++ b/services/web/test/unit/src/Subscription/SubscriptionGroupControllerTests.mjs @@ -615,33 +615,6 @@ describe('SubscriptionGroupController', function () { }) }) - describe('flexibleLicensingSplitTest', function () { - it('passes when the variant is "enabled"', function (done) { - const res = sinon.stub() - const next = () => { - this.ErrorController.notFound.notCalled.should.equal(true) - done() - } - this.SplitTestHandler.promises.getAssignment.resolves({ - variant: 'enabled', - }) - this.Controller.flexibleLicensingSplitTest(this.req, res, next, done) - }) - - it('returns error page when the variant is "default"', function (done) { - const res = sinon.stub() - const next = sinon.stub() - this.ErrorController.notFound = sinon.stub().callsFake(() => { - next.notCalled.should.equal(true) - done() - }) - this.SplitTestHandler.promises.getAssignment.resolves({ - variant: 'default', - }) - this.Controller.flexibleLicensingSplitTest(this.req, res, next, done) - }) - }) - describe('subscriptionUpgradePage', function () { it('should render "subscription upgrade" page', function (done) { const olSubscription = { membersLimit: 1, teamName: 'test team' }