[web] Migrate /subscription/invites/:token to BS5 (#20640)

* [web] Wiring work for `/subscription/invites/:token` BS5 migration

* [web] Add SCSS for .enrollment-invite

* [web] Update invite_logged_out PUG file for BS5

* [web] Update `GroupInviteViews` (and children) to BS5

* [web] Update `InviteManaged` to BS5

* [web] Update Logout button

* [web] Update subtitles

This removes the `text-overflow:ellipsis`. I think it's better without it, because it can be an accessibility issue.

* [web] Add margin on inner-card

* [web] Style action buttons in InviteManaged

* [web] Add missing container around Row

This was causing the row to overflow the body.

Increased the col width to compensate.

* [web] Fixup lint

* [web] Fix `ManagedUserCannotJoin` title in BS3 (!)

I checked all the other `OLNotification`: we don't use `title` anywhere else

* [web] Put title in OLNotification content

See https://github.com/overleaf/internal/pull/20640#discussion_r1777551257

* [web] Use translations for "aria-label="Email address""

* [web] Handle OLButton `isLoading` in `bs3Props`

* [web] Remove duplicated `btn` class

* [web] Add margin-bottom to InviteManaged title and fix logout button CSS in BS3

* [web] Adjust col class in Pug file for BS3 and BS5

* [web] Revert migration to OLNotification

Revert back to `@/shared/components/notification`

* [web] Add note to remove .team-invite-name after BS5 migration

* [web] Set `btn-link-logout` in BS3 only

* [web] Update OLButton so other classNames automatically get passed to the BS3 implementation

* [web] Revert OLButton changes for BS3 classnames

Co-authored-by: Rebeka <rebeka.dekany@overleaf.com>

* [web] Update services/web/modules/group-settings/frontend/js/components/invite-managed.tsx

Co-authored-by: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com>

* [web] Use OLFormGroup `controlId`

---------

Co-authored-by: Rebeka <rebeka.dekany@overleaf.com>
Co-authored-by: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com>
GitOrigin-RevId: 64b3f79c83002a9c9585bfb8e344e80b2e8eac5c
This commit is contained in:
Antoine Clausse 2024-09-30 11:48:56 +02:00 committed by Copybot
parent 246157cf63
commit d4bf47932e
9 changed files with 98 additions and 41 deletions

View file

@ -69,6 +69,13 @@ async function viewInvite(req, res, next) {
const { invite, subscription } = const { invite, subscription } =
await TeamInvitesHandler.promises.getInvite(token) await TeamInvitesHandler.promises.getInvite(token)
await SplitTestHandler.promises.getAssignment(
req,
res,
'bootstrap-5-subscription'
)
if (!invite) { if (!invite) {
return ErrorController.notFound(req, res) return ErrorController.notFound(req, res)
} }

View file

@ -1,5 +1,9 @@
extends ../../layout-marketing extends ../../layout-marketing
block vars
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
- bootstrap5PageSplitTest = 'bootstrap-5-subscription'
block entrypointVar block entrypointVar
- entrypoint = 'pages/user/subscription/invite-managed' - entrypoint = 'pages/user/subscription/invite-managed'

View file

@ -1,9 +1,12 @@
extends ../../layout-marketing extends ../../layout-marketing
block vars
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
- bootstrap5PageSplitTest = 'bootstrap-5-subscription'
block entrypointVar block entrypointVar
- entrypoint = 'pages/user/subscription/invite' - entrypoint = 'pages/user/subscription/invite'
block append meta block append meta
meta(name="ol-hasIndividualRecurlySubscription" data-type="boolean" content=hasIndividualRecurlySubscription) meta(name="ol-hasIndividualRecurlySubscription" data-type="boolean" content=hasIndividualRecurlySubscription)
meta(name="ol-inviterName" date-type="string" content=inviterName) meta(name="ol-inviterName" date-type="string" content=inviterName)

View file

@ -1,24 +1,31 @@
extends ../../layout-marketing extends ../../layout-marketing
block vars
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
- bootstrap5PageSplitTest = 'bootstrap-5-subscription'
block content block content
- var colClass = bootstrapVersion === 5 ? 'col-lg-8 m-auto' : 'col-md-8 col-md-offset-2'
main.content.content-alt.team-invite#main-content main.content.content-alt.team-invite#main-content
.container .container
.row .row
.col-md-8.col-md-offset-2.text-center div(class=colClass)
.card .card.text-center
.page-header .card-body
h1.text-centered !{translate("invited_to_group", {inviterName: inviterName, appName: appName }, [{name: 'span', attrs: {class: 'team-invite-name'}}])} .page-header
// TODO: Remove `team-invite-name` once we fully migrated to Bootstrap 5
if (accountExists) h1.text-centered !{translate("invited_to_group", {inviterName: inviterName, appName: appName }, [{name: 'span', attrs: {class: 'team-invite-name'}}])}
div
p #{translate("invited_to_group_login_benefits", {appName: appName})}
p #{translate("invited_to_group_login", {emailAddress: emailAddress})}
p
a.btn.btn.btn-primary(href=`/login?redir=/subscription/invites/${inviteToken}`) #{translate("login_to_accept_invitation")}
else
div
p #{translate("invited_to_group_register_benefits", {appName: appName})}
p #{translate("invited_to_group_register", {inviterName: inviterName})}
p
a.btn.btn.btn-primary(href=`/register?redir=/subscription/invites/${inviteToken}`) #{translate("register_to_accept_invitation")}
if (accountExists)
div
p #{translate("invited_to_group_login_benefits", {appName: appName})}
p #{translate("invited_to_group_login", {emailAddress: emailAddress})}
p
a.btn.btn-primary(href=`/login?redir=/subscription/invites/${inviteToken}`) #{translate("login_to_accept_invitation")}
else
div
p #{translate("invited_to_group_register_benefits", {appName: appName})}
p #{translate("invited_to_group_register", {inviterName: inviterName})}
p
a.btn.btn-primary(href=`/register?redir=/subscription/invites/${inviteToken}`) #{translate("register_to_accept_invitation")}

View file

@ -7,6 +7,9 @@ import ManagedUserCannotJoin from './managed-user-cannot-join'
import Notification from '@/shared/components/notification' import Notification from '@/shared/components/notification'
import JoinGroup from './join-group' import JoinGroup from './join-group'
import AcceptedInvite from './accepted-invite' import AcceptedInvite from './accepted-invite'
import OLRow from '@/features/ui/components/ol/ol-row'
import OLCol from '@/features/ui/components/ol/ol-col'
import OLCard from '@/features/ui/components/ol/ol-card'
export type InviteViewTypes = export type InviteViewTypes =
| 'invite' | 'invite'
@ -62,16 +65,16 @@ export default function GroupInvite() {
return ( return (
<div className="container" id="main-content"> <div className="container" id="main-content">
{expired && ( {expired && (
<div className="row"> <OLRow>
<div className="col-md-8 col-md-offset-2"> <OLCol lg={{ span: 8, offset: 2 }}>
<Notification type="error" content={t('email_link_expired')} /> <Notification type="error" content={t('email_link_expired')} />
</div> </OLCol>
</div> </OLRow>
)} )}
<div className="row row-spaced"> <OLRow className="row row-spaced">
<div className="col-md-8 col-md-offset-2"> <OLCol lg={{ span: 8, offset: 2 }}>
<div className="card"> <OLCard>
<div className="page-header"> <div className="page-header">
<h1 className="text-center"> <h1 className="text-center">
<Trans <Trans
@ -87,9 +90,9 @@ export default function GroupInvite() {
</h1> </h1>
</div> </div>
<GroupInviteViews /> <GroupInviteViews />
</div> </OLCard>
</div> </OLCol>
</div> </OLRow>
</div> </div>
) )
} }

View file

@ -6,6 +6,7 @@ import getMeta from '@/utils/meta'
import { Dispatch, SetStateAction, useCallback } from 'react' import { Dispatch, SetStateAction, useCallback } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { InviteViewTypes } from './group-invite' import { InviteViewTypes } from './group-invite'
import OLButton from '@/features/ui/components/ol/ol-button'
export default function HasIndividualRecurlySubscription({ export default function HasIndividualRecurlySubscription({
setView, setView,
@ -46,23 +47,21 @@ export default function HasIndividualRecurlySubscription({
<div className="text-center"> <div className="text-center">
<p>{t('cancel_personal_subscription_first')}</p> <p>{t('cancel_personal_subscription_first')}</p>
<p> <p>
<button <OLButton
className="btn btn-secondary" variant="secondary"
disabled={isCancelling} disabled={isCancelling}
onClick={() => setView('invite')} onClick={() => setView('invite')}
> >
{t('not_now')} {t('not_now')}
</button> </OLButton>
&nbsp;&nbsp; &nbsp;&nbsp;
<button <OLButton
className="btn btn-primary" variant="primary"
disabled={isCancelling} disabled={isCancelling}
onClick={() => { onClick={() => cancelPersonalSubscription()}
cancelPersonalSubscription()
}}
> >
{t('cancel_your_subscription')} {t('cancel_your_subscription')}
</button> </OLButton>
</p> </p>
</div> </div>
</> </>

View file

@ -7,6 +7,7 @@ import useAsync from '@/shared/hooks/use-async'
import classNames from 'classnames' import classNames from 'classnames'
import { debugConsole } from '@/utils/debugging' import { debugConsole } from '@/utils/debugging'
import Notification from '@/shared/components/notification' import Notification from '@/shared/components/notification'
import OLButton from '@/features/ui/components/ol/ol-button'
export default function JoinGroup({ export default function JoinGroup({
setView, setView,
@ -58,13 +59,13 @@ export default function JoinGroup({
{t('not_now')} {t('not_now')}
</a> </a>
&nbsp;&nbsp; &nbsp;&nbsp;
<button <OLButton
className="btn btn-primary" variant="primary"
onClick={() => joinTeam()} onClick={() => joinTeam()}
disabled={isJoining} disabled={isJoining}
> >
{t('accept_invitation')} {t('accept_invitation')}
</button> </OLButton>
</p> </p>
)} )}
</div> </div>

View file

@ -12,3 +12,4 @@
@import 'editor/file-tree'; @import 'editor/file-tree';
@import 'editor/figure-modal'; @import 'editor/figure-modal';
@import 'website-redesign'; @import 'website-redesign';
@import 'group-settings';

View file

@ -0,0 +1,32 @@
.enrollment-invite {
.title {
overflow: hidden;
text-overflow: ellipsis;
font-size: var(--font-size-05);
font-weight: bold;
}
.inner-card {
background-color: var(--neutral-10);
padding: var(--spacing-06);
&.warning {
background-color: var(--yellow-10);
}
}
.list-row {
border: 0;
display: flex;
flex-direction: row;
gap: var(--spacing-05);
.icon {
margin-top: var(--spacing-01);
}
}
.icon.error {
color: var(--yellow-50);
}
}