From b10b7b1f915f005733075165c10ea2ee2b96204c Mon Sep 17 00:00:00 2001 From: Jessica Lawshe <5312836+lawshe@users.noreply.github.com> Date: Wed, 8 Mar 2023 08:43:42 -0600 Subject: [PATCH] Merge pull request #12042 from overleaf/jel-change-plan [web] Change plan UI now in a modal and update the style GitOrigin-RevId: 1b501b4a972ca676cff32f531862c15c0c8f9e61 --- .../dashboard/states/active/active.tsx | 14 ++-- .../states/active/change-plan/change-plan.tsx | 40 ------------ .../change-plan/change-to-group-plan.tsx | 6 +- .../change-plan/individual-plans-table.tsx | 5 +- .../change-plan/modals/change-plan-modal.tsx | 52 +++++++++++++++ .../subscription-dashboard-context.tsx | 7 -- .../web/frontend/stylesheets/app/plans.less | 64 +++++++++++++++++++ .../frontend/stylesheets/components/card.less | 6 ++ .../stylesheets/components/tables.less | 12 +++- .../frontend/stylesheets/core/variables.less | 3 + .../frontend/stylesheets/variables/all.less | 3 + .../active/change-plan/change-plan.test.tsx | 12 +--- .../types/subscription/dashboard/modal-ids.ts | 1 + 13 files changed, 156 insertions(+), 69 deletions(-) delete mode 100644 services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-plan.tsx create mode 100644 services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-plan-modal.tsx diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx index a36542d01e..7dcc52599c 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active.tsx @@ -7,10 +7,13 @@ import { CancelSubscriptionButton } from './cancel-subscription-button' import { CancelSubscription } from './cancel-plan/cancel-subscription' import { PendingPlanChange } from './pending-plan-change' import { TrialEnding } from './trial-ending' -import { ChangePlan } from './change-plan/change-plan' import { PendingAdditionalLicenses } from './pending-additional-licenses' import { ContactSupportToChangeGroupPlan } from './contact-support-to-change-group-plan' import isInFreeTrial from '../../../../util/is-in-free-trial' +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' export function ActiveSubscription({ subscription, @@ -18,7 +21,7 @@ export function ActiveSubscription({ subscription: RecurlySubscription }) { const { t } = useTranslation() - const { recurlyLoadError, setShowChangePersonalPlan, showCancellation } = + const { recurlyLoadError, setModalIdShown, showCancellation } = useSubscriptionDashboardContext() if (showCancellation) return @@ -59,7 +62,7 @@ export function ActiveSubscription({ {' '} @@ -120,7 +123,10 @@ export function ActiveSubscription({ )} - + + + + ) } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-plan.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-plan.tsx deleted file mode 100644 index 0bb7678a49..0000000000 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-plan.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { useTranslation } from 'react-i18next' -import LoadingSpinner from '../../../../../../../shared/components/loading-spinner' -import { useSubscriptionDashboardContext } from '../../../../../context/subscription-dashboard-context' -import { ChangeToGroupPlan } from './change-to-group-plan' -import { ConfirmChangePlanModal } from './modals/confirm-change-plan-modal' -import { IndividualPlansTable } from './individual-plans-table' -import { KeepCurrentPlanModal } from './modals/keep-current-plan-modal' -import { ChangeToGroupModal } from './modals/change-to-group-modal' - -export function ChangePlan() { - const { t } = useTranslation() - const { - plans, - queryingIndividualPlansData, - recurlyLoadError, - showChangePersonalPlan, - } = useSubscriptionDashboardContext() - - if (!showChangePersonalPlan || !plans || recurlyLoadError) return null - - if (queryingIndividualPlansData) { - return ( - <> -

{t('change_plan')}

- - - ) - } else { - return ( - <> -

{t('change_plan')}

- - - - - - - ) - } -} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-to-group-plan.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-to-group-plan.tsx index 97b1ad275b..8c977efc39 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-to-group-plan.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-to-group-plan.tsx @@ -10,13 +10,13 @@ export function ChangeToGroupPlan() { } return ( - <> -

{t('looking_multiple_licenses')}

+
+

{t('looking_multiple_licenses')}

{t('reduce_costs_group_licenses')}


- +
) } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/individual-plans-table.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/individual-plans-table.tsx index b7b53bd58c..98d8c2aa36 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/individual-plans-table.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/individual-plans-table.tsx @@ -92,10 +92,9 @@ function PlansRows({ plans }: { plans: Array }) { export function IndividualPlansTable({ plans }: { plans: Array }) { const { t } = useTranslation() - const { recurlyLoadError, showChangePersonalPlan } = - useSubscriptionDashboardContext() + const { recurlyLoadError } = useSubscriptionDashboardContext() - if (!showChangePersonalPlan || !plans || recurlyLoadError) return null + if (!plans || recurlyLoadError) return null return ( diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-plan-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-plan-modal.tsx new file mode 100644 index 0000000000..7c365525f2 --- /dev/null +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-plan-modal.tsx @@ -0,0 +1,52 @@ +import { Modal } from 'react-bootstrap' +import { useTranslation } from 'react-i18next' +import { SubscriptionDashModalIds } from '../../../../../../../../../../types/subscription/dashboard/modal-ids' +import AccessibleModal from '../../../../../../../../shared/components/accessible-modal' +import LoadingSpinner from '../../../../../../../../shared/components/loading-spinner' +import { useSubscriptionDashboardContext } from '../../../../../../context/subscription-dashboard-context' +import { ChangeToGroupPlan } from '../change-to-group-plan' +import { IndividualPlansTable } from '../individual-plans-table' + +function ChangePlanOptions() { + const { plans, queryingIndividualPlansData, recurlyLoadError } = + useSubscriptionDashboardContext() + + if (!plans || recurlyLoadError) return null + + if (queryingIndividualPlansData) { + return ( + <> + + + ) + } else { + return ( + <> +
+ +
+ + + ) + } +} + +export function ChangePlanModal() { + const modalId: SubscriptionDashModalIds = 'change-plan' + const { t } = useTranslation() + const { handleCloseModal, modalIdShown } = useSubscriptionDashboardContext() + + if (modalIdShown !== modalId) return null + + return ( + + + {t('change_plan')} + + + + + + + ) +} diff --git a/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx b/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx index 7a7cff615d..f3bb0acceb 100644 --- a/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx +++ b/services/web/frontend/js/features/subscription/context/subscription-dashboard-context.tsx @@ -66,8 +66,6 @@ type SubscriptionDashboardContextValue = { setRecurlyLoadError: React.Dispatch> showCancellation: boolean setShowCancellation: React.Dispatch> - showChangePersonalPlan: boolean - setShowChangePersonalPlan: React.Dispatch> leavingGroupId?: string setLeavingGroupId: React.Dispatch> } @@ -86,7 +84,6 @@ export function SubscriptionDashboardProvider({ >() const [recurlyLoadError, setRecurlyLoadError] = useState(false) const [showCancellation, setShowCancellation] = useState(false) - const [showChangePersonalPlan, setShowChangePersonalPlan] = useState(false) const [plans, setPlans] = useState([]) const [queryingIndividualPlansData, setQueryingIndividualPlansData] = useState(true) @@ -268,8 +265,6 @@ export function SubscriptionDashboardProvider({ setRecurlyLoadError, showCancellation, setShowCancellation, - showChangePersonalPlan, - setShowChangePersonalPlan, leavingGroupId, setLeavingGroupId, }), @@ -304,8 +299,6 @@ export function SubscriptionDashboardProvider({ setRecurlyLoadError, showCancellation, setShowCancellation, - showChangePersonalPlan, - setShowChangePersonalPlan, leavingGroupId, setLeavingGroupId, ] diff --git a/services/web/frontend/stylesheets/app/plans.less b/services/web/frontend/stylesheets/app/plans.less index a7166c1126..9e01bd43f7 100644 --- a/services/web/frontend/stylesheets/app/plans.less +++ b/services/web/frontend/stylesheets/app/plans.less @@ -578,3 +578,67 @@ } } } + +/** + Subscription Dash +*/ + +#change-plan { + .modal-dialog { + &:extend(.modal-lg); + } + + table { + @media only screen and (min-width: @screen-md-min) { + th:last-child, + td:last-child { + width: 1%; // will expand to fit the content + text-align: center; + } + } + + @media only screen and (max-width: @screen-sm-max) { + display: block; + + thead { + display: none; + } + + tbody, + td, + tr { + display: inline-block; + padding-top: 0; + padding-bottom: 0; + text-align: center; + width: 100%; + } + + td:first-child { + padding-top: @padding-md; + } + td:last-child { + padding-top: @padding-sm; + padding-bottom: @padding-md; + } + + tr:first-child { + td:first-child { + padding-top: @padding-sm; + } + } + + tr { + border-bottom: 1px solid @table-border-color; + td, + th { + border: 0 !important; + } + } + + tr:last-child { + border-bottom: 0; + } + } + } +} diff --git a/services/web/frontend/stylesheets/components/card.less b/services/web/frontend/stylesheets/components/card.less index 8261dd8ca1..e6af58b6c7 100644 --- a/services/web/frontend/stylesheets/components/card.less +++ b/services/web/frontend/stylesheets/components/card.less @@ -65,3 +65,9 @@ .card-content { padding: @padding-md; } + +.card-gray { + &:extend(.card); + background-color: @neutral-10; + border-radius: @card-border-radius; +} diff --git a/services/web/frontend/stylesheets/components/tables.less b/services/web/frontend/stylesheets/components/tables.less index d88ba303c8..5b1f45c513 100755 --- a/services/web/frontend/stylesheets/components/tables.less +++ b/services/web/frontend/stylesheets/components/tables.less @@ -83,7 +83,7 @@ th { } } -// Bordered version +// Bordered versions // // Add borders all around the table and between all the columns. @@ -233,3 +233,13 @@ table { } } } + +.table-outlined-container { + border: @border-width-sm solid @table-border-color; + padding: @padding-sm @padding-sm 0 @padding-sm; + border-radius: @border-radius-base-new; + + table { + margin-bottom: 0; + } +} diff --git a/services/web/frontend/stylesheets/core/variables.less b/services/web/frontend/stylesheets/core/variables.less index a4614a79b9..5b86b9f335 100644 --- a/services/web/frontend/stylesheets/core/variables.less +++ b/services/web/frontend/stylesheets/core/variables.less @@ -165,8 +165,10 @@ @line-height-small: 1.5; @border-radius-base: 3px; +@border-radius-base-new: 4px; @border-radius-large: 5px; @border-radius-small: 2px; +@border-width-sm: 1px; @border-width-base: 3px; @border-color-base: @ol-blue-gray-2; @@ -932,6 +934,7 @@ // Cards @card-box-shadow: none; +@card-border-radius: @border-radius-base-new; // Project table @structured-list-link-color: @ol-blue; diff --git a/services/web/frontend/stylesheets/variables/all.less b/services/web/frontend/stylesheets/variables/all.less index 039aec49a4..1b326b0b3c 100644 --- a/services/web/frontend/stylesheets/variables/all.less +++ b/services/web/frontend/stylesheets/variables/all.less @@ -107,8 +107,10 @@ @line-height-small: 1.5; @border-radius-base: 3px; +@border-radius-base-new: 4px; @border-radius-large: 5px; @border-radius-small: 2px; +@border-width-sm: 1px; @border-width-base: 3px; // only used by plans and cards @border-size: 1px; @border-color-base: @neutral-60; @@ -720,6 +722,7 @@ // Cards @card-box-shadow: none; +@card-border-radius: @border-radius-base-new; // Project table @structured-list-link-color: @blue; diff --git a/services/web/test/frontend/features/subscription/components/dashboard/states/active/change-plan/change-plan.test.tsx b/services/web/test/frontend/features/subscription/components/dashboard/states/active/change-plan/change-plan.test.tsx index 13a025ab10..131a0e1990 100644 --- a/services/web/test/frontend/features/subscription/components/dashboard/states/active/change-plan/change-plan.test.tsx +++ b/services/web/test/frontend/features/subscription/components/dashboard/states/active/change-plan/change-plan.test.tsx @@ -1,7 +1,6 @@ import { expect } from 'chai' import { fireEvent, screen, waitFor, within } from '@testing-library/react' import userEvent from '@testing-library/user-event' -import { ChangePlan } from '../../../../../../../../../frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-plan' import { groupPlans, plans } from '../../../../../fixtures/plans' import { annualActiveSubscription, @@ -22,7 +21,7 @@ import { } from '../../../../../../../../../frontend/js/features/subscription/data/subscription-url' import { renderActiveSubscription } from '../../../../../helpers/render-active-subscription' -describe('', function () { +describe('', function () { let reloadStub: () => void const originalLocation = window.location const plansMetaTag = { name: 'ol-plans', value: plans } @@ -42,15 +41,6 @@ describe('', function () { }) }) - it('does not render the UI when showChangePersonalPlan is false', function () { - window.metaAttributesCache.delete('ol-plans') - const { container } = renderWithSubscriptionDashContext(, { - metaTags: [plansMetaTag], - }) - - expect(container.firstChild).to.be.null - }) - it('renders the individual plans table and group plans UI', async function () { renderActiveSubscription(annualActiveSubscription) const button = screen.getByRole('button', { name: 'Change plan' }) diff --git a/services/web/types/subscription/dashboard/modal-ids.ts b/services/web/types/subscription/dashboard/modal-ids.ts index 0c49515501..9e332657ce 100644 --- a/services/web/types/subscription/dashboard/modal-ids.ts +++ b/services/web/types/subscription/dashboard/modal-ids.ts @@ -3,3 +3,4 @@ export type SubscriptionDashModalIds = | 'change-to-group' | 'keep-current-plan' | 'leave-group' + | 'change-plan'