mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-27 02:51:57 +02:00
Cleanup Bootstrap 3 code in the Account settings page (#24058)
* Remove the Bootstrap 5 version utilities * Remove Account settings LESS stylesheet and unused styles * Prefer using the OLFormText wrapper component instead of FormText * Remove the Bootstrap 3 version stories * Replace Font Awesome icons to Material icons * Fix the heading hierarchy * Cleanup unused translation * Restore ellipsis to the text of two loading spinners * Add loading button tests back and add some button loading labels --------- Co-authored-by: Tim Down <158919+timdown@users.noreply.github.com> GitOrigin-RevId: 283a9167c8c78bf0fe5062840ded6917dcd6263b
This commit is contained in:
@@ -87,6 +87,7 @@ function ReconfirmAffiliation({
|
||||
className="btn-inline-link"
|
||||
disabled={isLoading}
|
||||
isLoading={isLoading}
|
||||
loadingLabel={t('sending') + '…'}
|
||||
>
|
||||
{t('resend_confirmation_email')}
|
||||
</OLButton>
|
||||
|
||||
@@ -12,7 +12,7 @@ import OLNotification from '@/features/ui/components/ol/ol-notification'
|
||||
import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
|
||||
import OLFormLabel from '@/features/ui/components/ol/ol-form-label'
|
||||
import OLFormControl from '@/features/ui/components/ol/ol-form-control'
|
||||
import FormText from '@/features/ui/components/bootstrap-5/form/form-text'
|
||||
import OLFormText from '@/features/ui/components/ol/ol-form-text'
|
||||
|
||||
function AccountInfoSection() {
|
||||
const { t } = useTranslation()
|
||||
@@ -127,9 +127,7 @@ function AccountInfoSection() {
|
||||
form="account-info-form"
|
||||
disabled={!isFormValid}
|
||||
isLoading={isLoading}
|
||||
bs3Props={{
|
||||
loading: isLoading ? `${t('saving')}…` : t('update'),
|
||||
}}
|
||||
loadingLabel={t('saving') + '…'}
|
||||
>
|
||||
{t('update')}
|
||||
</OLButton>
|
||||
@@ -196,7 +194,7 @@ function ReadOrWriteFormGroup({
|
||||
onInvalid={handleInvalid}
|
||||
/>
|
||||
{validationMessage && (
|
||||
<FormText type="error">{validationMessage}</FormText>
|
||||
<OLFormText type="error">{validationMessage}</OLFormText>
|
||||
)}
|
||||
</OLFormGroup>
|
||||
)
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
import EmailsHeader from './emails/header'
|
||||
import EmailsRow from './emails/row'
|
||||
import AddEmail from './emails/add-email'
|
||||
import Icon from '../../../shared/components/icon'
|
||||
import OLNotification from '@/features/ui/components/ol/ol-notification'
|
||||
import OLSpinner from '@/features/ui/components/ol/ol-spinner'
|
||||
import { LeaversSurveyAlert } from './leavers-survey-alert'
|
||||
|
||||
function EmailsSectionContent() {
|
||||
@@ -28,7 +28,7 @@ function EmailsSectionContent() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<h3>{t('emails_and_affiliations_title')}</h3>
|
||||
<h2 className="h3">{t('emails_and_affiliations_title')}</h2>
|
||||
<p className="small">{t('emails_and_affiliations_explanation')}</p>
|
||||
<p className="small">
|
||||
<Trans
|
||||
@@ -49,7 +49,7 @@ function EmailsSectionContent() {
|
||||
{isInitializing ? (
|
||||
<div className="affiliations-table-row-highlighted">
|
||||
<div className="affiliations-table-cell text-center">
|
||||
<Icon type="refresh" fw spin /> {t('loading')}...
|
||||
<OLSpinner size="sm" /> {t('loading')}...
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -68,10 +68,6 @@ function EmailsSectionContent() {
|
||||
<OLNotification
|
||||
type="error"
|
||||
content={t('error_performing_request')}
|
||||
bs3Props={{
|
||||
icon: <Icon type="exclamation-triangle" fw />,
|
||||
className: 'text-center',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -7,7 +7,6 @@ import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import OLIconButton, {
|
||||
OLIconButtonProps,
|
||||
} from '@/features/ui/components/ol/ol-icon-button'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
type DeleteButtonProps = Pick<
|
||||
@@ -26,8 +25,7 @@ function DeleteButton({ disabled, isLoading, onClick }: DeleteButtonProps) {
|
||||
size="sm"
|
||||
onClick={onClick}
|
||||
accessibilityLabel={t('remove') || ''}
|
||||
icon={bsVersion({ bs5: 'delete', bs3: 'trash' })}
|
||||
bs3Props={{ fw: true }}
|
||||
icon="delete"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import getMeta from '../../../../utils/meta'
|
||||
import { ReCaptcha2 } from '../../../../shared/components/recaptcha-2'
|
||||
import { useRecaptcha } from '../../../../shared/hooks/use-recaptcha'
|
||||
import OLCol from '@/features/ui/components/ol/ol-col'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import { ConfirmEmailForm } from '@/features/settings/components/emails/confirm-email-form'
|
||||
|
||||
function AddEmail() {
|
||||
@@ -153,10 +152,7 @@ function AddEmail() {
|
||||
|
||||
const InputComponent = (
|
||||
<>
|
||||
<label
|
||||
htmlFor="affiliations-email"
|
||||
className={bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })}
|
||||
>
|
||||
<label htmlFor="affiliations-email" className="visually-hidden">
|
||||
{t('email')}
|
||||
</label>
|
||||
<Input
|
||||
|
||||
@@ -3,10 +3,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useCombobox } from 'downshift'
|
||||
import classnames from 'classnames'
|
||||
import countries, { CountryCode } from '../../../data/countries-list'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import OLFormControl from '@/features/ui/components/ol/ol-form-control'
|
||||
import { DropdownItem } from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
type CountryInputProps = {
|
||||
setValue: React.Dispatch<React.SetStateAction<CountryCode | null>>
|
||||
@@ -51,26 +49,10 @@ function Downshift({ setValue, inputRef }: CountryInputProps) {
|
||||
const shouldOpen = isOpen && inputItems.length
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
'dropdown',
|
||||
bsVersion({
|
||||
bs5: 'd-block',
|
||||
bs3: classnames('ui-select-container ui-select-bootstrap', {
|
||||
open: shouldOpen,
|
||||
}),
|
||||
})
|
||||
)}
|
||||
>
|
||||
<div
|
||||
{...getComboboxProps()}
|
||||
className={bsVersion({ bs3: 'ui-select-toggle' })}
|
||||
>
|
||||
<div className={classnames('dropdown', 'd-block')}>
|
||||
<div {...getComboboxProps()}>
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-for */}
|
||||
<label
|
||||
{...getLabelProps()}
|
||||
className={bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })}
|
||||
>
|
||||
<label {...getLabelProps()} className="visually-hidden">
|
||||
{t('country')}
|
||||
</label>
|
||||
<OLFormControl
|
||||
@@ -91,52 +73,30 @@ function Downshift({ setValue, inputRef }: CountryInputProps) {
|
||||
</div>
|
||||
<ul
|
||||
{...getMenuProps()}
|
||||
className={classnames(
|
||||
'dropdown-menu',
|
||||
bsVersion({
|
||||
bs5: classnames('select-dropdown-menu', { show: shouldOpen }),
|
||||
bs3: 'ui-select-choices ui-select-choices-content ui-select-dropdown',
|
||||
})
|
||||
)}
|
||||
className={classnames('dropdown-menu', 'select-dropdown-menu', {
|
||||
show: shouldOpen,
|
||||
})}
|
||||
>
|
||||
{inputItems.map((item, index) => (
|
||||
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
||||
<li
|
||||
className={bsVersion({ bs3: 'ui-select-choices-group' })}
|
||||
key={`${item.name}-${index}`}
|
||||
{...getItemProps({ item, index })}
|
||||
aria-selected={selectedItem?.name === item.name}
|
||||
>
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div
|
||||
className={classnames('ui-select-choices-row', {
|
||||
active: selectedItem?.name === item.name,
|
||||
'ui-select-choices-row--highlighted':
|
||||
highlightedIndex === index,
|
||||
})}
|
||||
>
|
||||
<span className="ui-select-choices-row-inner">
|
||||
<span>{item.name}</span>
|
||||
</span>
|
||||
</div>
|
||||
<DropdownItem
|
||||
as="span"
|
||||
role={undefined}
|
||||
className={classnames({
|
||||
active: selectedItem?.name === item.name,
|
||||
'dropdown-item-highlighted': highlightedIndex === index,
|
||||
})}
|
||||
trailingIcon={
|
||||
selectedItem?.name === item.name ? 'check' : undefined
|
||||
}
|
||||
bs5={
|
||||
<DropdownItem
|
||||
as="span"
|
||||
role={undefined}
|
||||
className={classnames({
|
||||
active: selectedItem?.name === item.name,
|
||||
'dropdown-item-highlighted': highlightedIndex === index,
|
||||
})}
|
||||
trailingIcon={
|
||||
selectedItem?.name === item.name ? 'check' : undefined
|
||||
}
|
||||
>
|
||||
{item.name}
|
||||
</DropdownItem>
|
||||
}
|
||||
/>
|
||||
>
|
||||
{item.name}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import Icon from '../../../../../shared/components/icon'
|
||||
import { UseAsyncReturnType } from '../../../../../shared/hooks/use-async'
|
||||
import { getUserFacingMessage } from '../../../../../infrastructure/fetch-json'
|
||||
import OLRow from '@/features/ui/components/ol/ol-row'
|
||||
@@ -18,10 +17,6 @@ function Layout({ isError, error, children }: LayoutProps) {
|
||||
<OLNotification
|
||||
type="error"
|
||||
content={getUserFacingMessage(error) ?? ''}
|
||||
bs3Props={{
|
||||
icon: <Icon type="exclamation-triangle" fw />,
|
||||
className: 'text-center',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -217,16 +217,7 @@ export function ConfirmEmailForm({
|
||||
disabled={isResending}
|
||||
type="submit"
|
||||
isLoading={isConfirming}
|
||||
bs3Props={{
|
||||
loading: isConfirming ? (
|
||||
<>
|
||||
{t('confirming')}
|
||||
<span>…</span>
|
||||
</>
|
||||
) : (
|
||||
t('confirm')
|
||||
),
|
||||
}}
|
||||
loadingLabel={t('confirming')}
|
||||
>
|
||||
{t('confirm')}
|
||||
</OLButton>
|
||||
@@ -235,16 +226,7 @@ export function ConfirmEmailForm({
|
||||
disabled={isConfirming}
|
||||
onClick={resendHandler}
|
||||
isLoading={isResending}
|
||||
bs3Props={{
|
||||
loading: isResending ? (
|
||||
<>
|
||||
{t('resending_confirmation_code')}
|
||||
<span>…</span>
|
||||
</>
|
||||
) : (
|
||||
t('resend_confirmation_code')
|
||||
),
|
||||
}}
|
||||
loadingLabel={t('resending_confirmation_code')}
|
||||
>
|
||||
{t('resend_confirmation_code')}
|
||||
</OLButton>
|
||||
|
||||
@@ -2,10 +2,8 @@ import { useState, useEffect, forwardRef } from 'react'
|
||||
import { useCombobox } from 'downshift'
|
||||
import classnames from 'classnames'
|
||||
import { escapeRegExp } from 'lodash'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import OLFormControl from '@/features/ui/components/ol/ol-form-control'
|
||||
import { DropdownItem } from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import OLFormLabel from '@/features/ui/components/ol/ol-form-label'
|
||||
|
||||
type DownshiftInputProps = {
|
||||
@@ -83,26 +81,12 @@ function Downshift({
|
||||
const shouldOpen = isOpen && inputItems.length
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
'dropdown',
|
||||
bsVersion({
|
||||
bs5: 'd-block',
|
||||
bs3: classnames('ui-select-container ui-select-bootstrap', {
|
||||
open: shouldOpen,
|
||||
}),
|
||||
})
|
||||
)}
|
||||
>
|
||||
<div className={classnames('dropdown', 'd-block')}>
|
||||
<div {...getComboboxProps()}>
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-for */}
|
||||
<OLFormLabel
|
||||
{...getLabelProps()}
|
||||
className={
|
||||
showLabel
|
||||
? ''
|
||||
: bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })
|
||||
}
|
||||
className={showLabel ? '' : 'visually-hidden'}
|
||||
>
|
||||
{label}
|
||||
</OLFormLabel>
|
||||
@@ -124,62 +108,35 @@ function Downshift({
|
||||
</div>
|
||||
<ul
|
||||
{...getMenuProps()}
|
||||
className={classnames(
|
||||
'dropdown-menu',
|
||||
bsVersion({
|
||||
bs5: classnames('select-dropdown-menu', { show: shouldOpen }),
|
||||
bs3: 'ui-select-choices ui-select-choices-content ui-select-dropdown',
|
||||
})
|
||||
)}
|
||||
className={classnames('dropdown-menu', 'select-dropdown-menu', {
|
||||
show: shouldOpen,
|
||||
})}
|
||||
>
|
||||
{showSuggestedText && inputItems.length && (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<li className="ui-select-title">{itemsTitle}</li>}
|
||||
bs5={
|
||||
<li>
|
||||
<DropdownItem as="span" role={undefined} disabled>
|
||||
{itemsTitle}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
}
|
||||
/>
|
||||
<li>
|
||||
<DropdownItem as="span" role={undefined} disabled>
|
||||
{itemsTitle}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
)}
|
||||
{inputItems.map((item, index) => (
|
||||
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
||||
<li
|
||||
className={bsVersion({ bs3: 'ui-select-choices-group' })}
|
||||
key={`${item}${index}`}
|
||||
{...getItemProps({ item, index })}
|
||||
aria-selected={selectedItem === item}
|
||||
>
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div
|
||||
className={classnames('ui-select-choices-row', {
|
||||
active: selectedItem === item,
|
||||
'ui-select-choices-row--highlighted':
|
||||
highlightedIndex === index,
|
||||
})}
|
||||
>
|
||||
<span className="ui-select-choices-row-inner">
|
||||
<span>{highlightMatchedCharacters(item, inputValue)}</span>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
bs5={
|
||||
<DropdownItem
|
||||
as="span"
|
||||
role={undefined}
|
||||
className={classnames({
|
||||
active: selectedItem === item,
|
||||
'dropdown-item-highlighted': highlightedIndex === index,
|
||||
})}
|
||||
trailingIcon={selectedItem === item ? 'check' : undefined}
|
||||
>
|
||||
{highlightMatchedCharacters(item, inputValue)}
|
||||
</DropdownItem>
|
||||
}
|
||||
/>
|
||||
<DropdownItem
|
||||
as="span"
|
||||
role={undefined}
|
||||
className={classnames({
|
||||
active: selectedItem === item,
|
||||
'dropdown-item-highlighted': highlightedIndex === index,
|
||||
})}
|
||||
trailingIcon={selectedItem === item ? 'check' : undefined}
|
||||
>
|
||||
{highlightMatchedCharacters(item, inputValue)}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -2,8 +2,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import { UserEmailData } from '../../../../../../types/user-email'
|
||||
import { ssoAvailableForInstitution } from '../../utils/sso'
|
||||
import OLBadge from '@/features/ui/components/ol/ol-badge'
|
||||
import { isBootstrap5 } from '@/features/utils/bootstrap-5'
|
||||
import classnames from 'classnames'
|
||||
import ResendConfirmationCodeModal from '@/features/settings/components/emails/resend-confirmation-code-modal'
|
||||
|
||||
type EmailProps = {
|
||||
@@ -37,7 +35,7 @@ function Email({ userEmailData }: EmailProps) {
|
||||
</div>
|
||||
)}
|
||||
{hasBadges && (
|
||||
<div className={classnames({ small: !isBootstrap5() })}>
|
||||
<div>
|
||||
{isPrimary && (
|
||||
<>
|
||||
<OLBadge bg="info">Primary</OLBadge>{' '}
|
||||
|
||||
@@ -3,7 +3,6 @@ import EmailCell from './cell'
|
||||
import OLCol from '@/features/ui/components/ol/ol-col'
|
||||
import OLRow from '@/features/ui/components/ol/ol-row'
|
||||
import classnames from 'classnames'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
|
||||
function Header() {
|
||||
const { t } = useTranslation()
|
||||
@@ -11,41 +10,19 @@ function Header() {
|
||||
return (
|
||||
<>
|
||||
<OLRow>
|
||||
<OLCol
|
||||
lg={4}
|
||||
className={bsVersion({
|
||||
bs5: 'd-none d-sm-block',
|
||||
bs3: 'hidden-xs',
|
||||
})}
|
||||
>
|
||||
<OLCol lg={4} className="d-none d-sm-block">
|
||||
<EmailCell>
|
||||
<strong>{t('email')}</strong>
|
||||
</EmailCell>
|
||||
</OLCol>
|
||||
<OLCol
|
||||
lg={8}
|
||||
className={bsVersion({
|
||||
bs5: 'd-none d-sm-block',
|
||||
bs3: 'hidden-xs',
|
||||
})}
|
||||
>
|
||||
<OLCol lg={8} className="d-none d-sm-block">
|
||||
<EmailCell>
|
||||
<strong>{t('institution_and_role')}</strong>
|
||||
</EmailCell>
|
||||
</OLCol>
|
||||
</OLRow>
|
||||
<div
|
||||
className={classnames(
|
||||
bsVersion({ bs5: 'd-none d-sm-block', bs3: 'hidden-xs' }),
|
||||
'horizontal-divider'
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
className={classnames(
|
||||
bsVersion({ bs5: 'd-none d-sm-block', bs3: 'hidden-xs' }),
|
||||
'horizontal-divider'
|
||||
)}
|
||||
/>
|
||||
<div className={classnames('d-none d-sm-block', 'horizontal-divider')} />
|
||||
<div className={classnames('d-none d-sm-block', 'horizontal-divider')} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -146,11 +146,6 @@ function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
|
||||
disabled={!role || !department}
|
||||
isLoading={isLoading}
|
||||
loadingLabel={t('saving')}
|
||||
bs3Props={{
|
||||
loading: isLoading
|
||||
? `${t('saving')}…`
|
||||
: t('save_or_cancel-save'),
|
||||
}}
|
||||
>
|
||||
{t('save_or_cancel-save')}
|
||||
</OLButton>
|
||||
|
||||
@@ -6,8 +6,6 @@ import ReconfirmationInfoPromptText from './reconfirmation-info/reconfirmation-i
|
||||
import OLRow from '@/features/ui/components/ol/ol-row'
|
||||
import OLCol from '@/features/ui/components/ol/ol-col'
|
||||
import OLNotification from '@/features/ui/components/ol/ol-notification'
|
||||
import { isBootstrap5 } from '@/features/utils/bootstrap-5'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { useUserEmailsContext } from '@/features/settings/context/user-email-context'
|
||||
import { FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
@@ -16,14 +14,13 @@ import { Trans, useTranslation } from 'react-i18next'
|
||||
import useAsync from '@/shared/hooks/use-async'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import classnames from 'classnames'
|
||||
import LoadingSpinner from '@/shared/components/loading-spinner'
|
||||
|
||||
type ReconfirmationInfoProps = {
|
||||
userEmailData: UserEmailData
|
||||
}
|
||||
|
||||
function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
|
||||
const reconfirmationRemoveEmail = getMeta('ol-reconfirmationRemoveEmail')
|
||||
const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML')
|
||||
|
||||
const { t } = useTranslation()
|
||||
@@ -86,7 +83,6 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
|
||||
institution={userEmailData.affiliation.institution}
|
||||
/>
|
||||
}
|
||||
bs3Props={{ className: 'settings-reconfirm-info small' }}
|
||||
/>
|
||||
</OLCol>
|
||||
</OLRow>
|
||||
@@ -97,88 +93,11 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
|
||||
return (
|
||||
<OLRow>
|
||||
<OLCol lg={12}>
|
||||
{isBootstrap5() ? (
|
||||
<OLNotification
|
||||
type="info"
|
||||
content={
|
||||
<>
|
||||
{hasSent ? (
|
||||
<Trans
|
||||
i18nKey="please_check_your_inbox_to_confirm"
|
||||
values={{
|
||||
institutionName:
|
||||
userEmailData.affiliation.institution.name,
|
||||
}}
|
||||
shouldUnescape
|
||||
tOptions={{ interpolation: { escapeValue: true } }}
|
||||
components={
|
||||
/* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
|
||||
[<strong />]
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<ReconfirmationInfoPromptText
|
||||
institutionName={
|
||||
userEmailData.affiliation.institution.name
|
||||
}
|
||||
primary={userEmailData.default}
|
||||
/>
|
||||
)}
|
||||
<br />
|
||||
{isError && (
|
||||
<div className="text-danger">
|
||||
{rateLimited
|
||||
? t('too_many_requests')
|
||||
: t('generic_something_went_wrong')}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
action={
|
||||
hasSent ? (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Icon type="refresh" spin fw /> {t('sending')}...
|
||||
</>
|
||||
) : (
|
||||
<OLButton
|
||||
variant="link"
|
||||
disabled={state.isLoading}
|
||||
onClick={handleRequestReconfirmation}
|
||||
className="btn-inline-link"
|
||||
>
|
||||
{t('resend_confirmation_email')}
|
||||
</OLButton>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<OLButton
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
isLoading={isLoading}
|
||||
onClick={handleRequestReconfirmation}
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Icon type="refresh" spin fw /> {t('sending')}...
|
||||
</>
|
||||
) : (
|
||||
t('confirm_affiliation')
|
||||
)}
|
||||
</OLButton>
|
||||
)
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={classnames('settings-reconfirm-info', 'small', {
|
||||
'alert alert-info':
|
||||
reconfirmationRemoveEmail === userEmailData.email,
|
||||
})}
|
||||
>
|
||||
{hasSent ? (
|
||||
<div>
|
||||
<OLNotification
|
||||
type="info"
|
||||
content={
|
||||
<>
|
||||
{hasSent ? (
|
||||
<Trans
|
||||
i18nKey="please_check_your_inbox_to_confirm"
|
||||
values={{
|
||||
@@ -191,10 +110,29 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
|
||||
/* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
|
||||
[<strong />]
|
||||
}
|
||||
/>{' '}
|
||||
/>
|
||||
) : (
|
||||
<ReconfirmationInfoPromptText
|
||||
institutionName={userEmailData.affiliation.institution.name}
|
||||
primary={userEmailData.default}
|
||||
/>
|
||||
)}
|
||||
<br />
|
||||
{isError && (
|
||||
<div className="text-danger">
|
||||
{rateLimited
|
||||
? t('too_many_requests')
|
||||
: t('generic_something_went_wrong')}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
action={
|
||||
hasSent ? (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Icon type="refresh" spin fw /> {t('sending')}...
|
||||
<LoadingSpinner loadingText={`${t('sending')}…`} />
|
||||
</>
|
||||
) : (
|
||||
<OLButton
|
||||
@@ -206,55 +144,25 @@ function ReconfirmationInfo({ userEmailData }: ReconfirmationInfoProps) {
|
||||
{t('resend_confirmation_email')}
|
||||
</OLButton>
|
||||
)}
|
||||
<br />
|
||||
{isError && (
|
||||
<div className="text-danger">
|
||||
{rateLimited
|
||||
? t('too_many_requests')
|
||||
: t('generic_something_went_wrong')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
<ReconfirmationInfoPromptText
|
||||
institutionName={
|
||||
userEmailData.affiliation.institution.name
|
||||
}
|
||||
primary={userEmailData.default}
|
||||
icon={
|
||||
<Icon type="warning" className="me-1 icon-warning" />
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="setting-reconfirm-info-right">
|
||||
<OLButton
|
||||
variant="secondary"
|
||||
disabled={state.isLoading || isPending}
|
||||
onClick={handleRequestReconfirmation}
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Icon type="refresh" spin fw /> {t('sending')}...
|
||||
</>
|
||||
) : (
|
||||
t('confirm_affiliation')
|
||||
)}
|
||||
</OLButton>
|
||||
<br />
|
||||
{isError && (
|
||||
<div className="text-danger">
|
||||
{rateLimited
|
||||
? t('too_many_requests')
|
||||
: t('generic_something_went_wrong')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
) : (
|
||||
<OLButton
|
||||
variant="secondary"
|
||||
disabled={isPending}
|
||||
isLoading={isLoading}
|
||||
onClick={handleRequestReconfirmation}
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<LoadingSpinner loadingText={`${t('sending')}…`} />
|
||||
</>
|
||||
) : (
|
||||
t('confirm_affiliation')
|
||||
)}
|
||||
</OLButton>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</OLCol>
|
||||
</OLRow>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import Icon from '../../../../shared/components/icon'
|
||||
import getMeta from '../../../../utils/meta'
|
||||
import OLNotification from '@/features/ui/components/ol/ol-notification'
|
||||
|
||||
@@ -35,15 +34,6 @@ export function SSOAlert() {
|
||||
}
|
||||
isDismissible
|
||||
onDismiss={handleErrorClosed}
|
||||
bs3Props={{
|
||||
icon: (
|
||||
<Icon
|
||||
type="exclamation-triangle"
|
||||
accessibilityLabel={t('generic_something_went_wrong')}
|
||||
/>
|
||||
),
|
||||
className: 'mb-0 text-center',
|
||||
}}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
@@ -83,9 +73,6 @@ export function SSOAlert() {
|
||||
}
|
||||
isDismissible
|
||||
onDismiss={handleInfoClosed}
|
||||
bs3Props={{
|
||||
className: 'mb-0 text-center',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{!warningClosed && institutionEmailNonCanonical && (
|
||||
@@ -102,16 +89,6 @@ export function SSOAlert() {
|
||||
}
|
||||
isDismissible
|
||||
onDismiss={handleWarningClosed}
|
||||
bs3Props={{
|
||||
icon: (
|
||||
<Icon
|
||||
type="exclamation-triangle"
|
||||
accessibilityLabel={t('generic_something_went_wrong')}
|
||||
fw
|
||||
/>
|
||||
),
|
||||
className: 'text-center',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -17,13 +17,7 @@ function LeaveModal({ isOpen, handleClose }: LeaveModalProps) {
|
||||
}, [handleClose, inFlight])
|
||||
|
||||
return (
|
||||
<OLModal
|
||||
animation
|
||||
show={isOpen}
|
||||
onHide={handleHide}
|
||||
id="leave-modal"
|
||||
bs3Props={{ backdrop: 'static' }}
|
||||
>
|
||||
<OLModal animation show={isOpen} onHide={handleHide} id="leave-modal">
|
||||
<LeaveModalContent
|
||||
handleHide={handleHide}
|
||||
inFlight={inFlight}
|
||||
|
||||
@@ -204,9 +204,6 @@ function PasswordForm() {
|
||||
disabled={!isFormValid}
|
||||
isLoading={isLoading}
|
||||
loadingLabel={`${t('saving')}…`}
|
||||
bs3Props={{
|
||||
loading: isLoading ? `${t('saving')}…` : t('change'),
|
||||
}}
|
||||
>
|
||||
{t('change')}
|
||||
</OLButton>
|
||||
|
||||
@@ -3,7 +3,6 @@ import AccountInfoSection from '../../js/features/settings/components/account-in
|
||||
import { setDefaultMeta, defaultSetupMocks } from './helpers/account-info'
|
||||
import { UserProvider } from '../../js/shared/context/user-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Success = args => {
|
||||
setDefaultMeta()
|
||||
@@ -56,7 +55,4 @@ export const Error = args => {
|
||||
export default {
|
||||
title: 'Account Settings / Account Info',
|
||||
component: AccountInfoSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import useFetchMock from './../hooks/use-fetch-mock'
|
||||
import Input from '../../js/features/settings/components/emails/add-email/input'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const EmailInput = (args: any) => {
|
||||
useFetchMock(fetchMock =>
|
||||
@@ -27,6 +26,5 @@ export default {
|
||||
component: Input,
|
||||
argTypes: {
|
||||
onChange: { action: 'change' },
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import BetaProgramSection from '../../js/features/settings/components/beta-program-section'
|
||||
import { UserProvider } from '../../js/shared/context/user-context'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const SectionNotEnrolled = args => {
|
||||
window.metaAttributesCache.set('ol-user', { betaProgram: false })
|
||||
@@ -25,7 +24,4 @@ export const SectionEnrolled = args => {
|
||||
export default {
|
||||
title: 'Account Settings / Beta Program',
|
||||
component: BetaProgramSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
errorsMocks,
|
||||
emailLimitSetupMocks,
|
||||
} from './helpers/emails'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const EmailsList = args => {
|
||||
useFetchMock(defaultSetupMocks)
|
||||
@@ -41,7 +40,4 @@ export const NetworkErrors = args => {
|
||||
export default {
|
||||
title: 'Account Settings / Emails and Affiliations',
|
||||
component: EmailsSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import useFetchMock from '../hooks/use-fetch-mock'
|
||||
import LeaveModal from '../../js/features/settings/components/leave/modal'
|
||||
import LeaveSection from '../../js/features/settings/components/leave-section'
|
||||
import { setDefaultMeta, defaultSetupMocks } from './helpers/leave'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Section = args => {
|
||||
useFetchMock(defaultSetupMocks)
|
||||
@@ -68,6 +67,5 @@ export default {
|
||||
},
|
||||
argTypes: {
|
||||
handleClose: { action: 'handleClose' },
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import EmailsSection from '../../js/features/settings/components/emails-section'
|
||||
import { UserEmailsProvider } from '../../js/features/settings/context/user-email-context'
|
||||
import { LeaversSurveyAlert } from '../../js/features/settings/components/leavers-survey-alert'
|
||||
import localStorage from '@/infrastructure/local-storage'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const SurveyAlert = () => {
|
||||
localStorage.setItem(
|
||||
@@ -19,7 +18,4 @@ export const SurveyAlert = () => {
|
||||
export default {
|
||||
title: 'Account Settings / Survey Alerts',
|
||||
component: EmailsSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { SSOProvider } from '../../js/features/settings/context/sso-context'
|
||||
import { ScopeDecorator } from '../decorators/scope'
|
||||
import { useEffect } from 'react'
|
||||
import { useMeta } from '../hooks/use-meta'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
const MOCK_DELAY = 1000
|
||||
|
||||
@@ -94,7 +93,4 @@ export default {
|
||||
title: 'Account Settings / Linking',
|
||||
component: LinkingSection,
|
||||
decorators: [ScopeDecorator],
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import NewsletterSection from '../../js/features/settings/components/newsletter-section'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Section = args => {
|
||||
return <NewsletterSection {...args} />
|
||||
@@ -8,7 +7,4 @@ export const Section = args => {
|
||||
export default {
|
||||
title: 'Account Settings / Newsletter',
|
||||
component: NewsletterSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
import { UserProvider } from '../../js/shared/context/user-context'
|
||||
import { ScopeDecorator } from '../decorators/scope'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Overleaf = args => {
|
||||
setDefaultLeaveMeta()
|
||||
@@ -79,7 +78,4 @@ export default {
|
||||
title: 'Account Settings / Full Page',
|
||||
component: SettingsPageRoot,
|
||||
decorators: [ScopeDecorator],
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import useFetchMock from '../hooks/use-fetch-mock'
|
||||
import PasswordSection from '../../js/features/settings/components/password-section'
|
||||
import { setDefaultMeta, defaultSetupMocks } from './helpers/password'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Success = args => {
|
||||
setDefaultMeta()
|
||||
@@ -47,7 +46,4 @@ export const Error = args => {
|
||||
export default {
|
||||
title: 'Account Settings / Password',
|
||||
component: PasswordSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import SessionsSection from '../../js/features/settings/components/sessions-section'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Section = args => {
|
||||
return <SessionsSection {...args} />
|
||||
@@ -8,7 +7,4 @@ export const Section = args => {
|
||||
export default {
|
||||
title: 'Account Settings / Sessions',
|
||||
component: SessionsSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import EmailsSection from '../../js/features/settings/components/emails-section'
|
||||
import { SSOAlert } from '../../js/features/settings/components/emails/sso-alert'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const Info = () => {
|
||||
window.metaAttributesCache.set('ol-institutionLinked', {
|
||||
@@ -54,7 +53,4 @@ export const ErrorWithTryAgain = () => {
|
||||
export default {
|
||||
title: 'Account Settings / SSO Alerts',
|
||||
component: EmailsSection,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
.account-settings {
|
||||
.alert {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#delete-account-modal {
|
||||
.alert {
|
||||
margin-top: 25px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.confirmation-checkbox-wrapper {
|
||||
padding-top: 8px;
|
||||
input {
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.affiliations-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
.affiliations-table-cell {
|
||||
padding: 0.5rem;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.affiliations-table-cell-tabbed {
|
||||
margin: @margin-sm 0 0 @margin-md;
|
||||
padding-left: @margin-sm;
|
||||
border-left: 2px solid @table-border-color; // don't migrate this line of style
|
||||
}
|
||||
.affiliations-table-row-highlighted {
|
||||
background-color: tint(@content-alt-bg-color, 6%);
|
||||
}
|
||||
.affiliations-table-email {
|
||||
width: 40%;
|
||||
}
|
||||
.affiliations-table-institution {
|
||||
width: 40%;
|
||||
}
|
||||
.affiliations-table-inline-actions {
|
||||
padding: 0 !important;
|
||||
text-align: right;
|
||||
word-wrap: break-word;
|
||||
button {
|
||||
margin: @table-cell-padding 0;
|
||||
}
|
||||
}
|
||||
.affiliations-table-inline-action {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.affiliations-table-inline-action-disabled-wrapper {
|
||||
display: inline-block;
|
||||
}
|
||||
.affiliations-table-highlighted-row {
|
||||
background-color: tint(@content-alt-bg-color, 6%);
|
||||
}
|
||||
.affiliations-table-error-row {
|
||||
background-color: @alert-danger-bg;
|
||||
color: @alert-danger-text;
|
||||
.btn {
|
||||
margin-top: @table-cell-padding;
|
||||
.button-variant(
|
||||
@btn-danger-color; darken(@btn-danger-bg, 8%) ; @btn-danger-border
|
||||
);
|
||||
}
|
||||
.small {
|
||||
color: @alert-danger-text;
|
||||
}
|
||||
}
|
||||
.affiliations-table-info-row {
|
||||
background-color: @alert-info-bg;
|
||||
color: @alert-info-text;
|
||||
.small {
|
||||
color: @alert-info-text;
|
||||
}
|
||||
}
|
||||
.affiliations-table-warning-row {
|
||||
background-color: @alert-warning-bg;
|
||||
color: @alert-warning-text;
|
||||
.small {
|
||||
color: @alert-warning-text;
|
||||
}
|
||||
}
|
||||
tbody > tr.affiliations-table-saml-row > td:not(.with-border) {
|
||||
border: 0;
|
||||
}
|
||||
tbody > tr.affiliations-table-info-row > td {
|
||||
border: 0;
|
||||
}
|
||||
tbody > tr.affiliations-table-warning-row > td {
|
||||
border: 0;
|
||||
}
|
||||
.affiliations-form-group {
|
||||
margin-top: @table-cell-padding;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
.affiliation-change-container,
|
||||
.affiliation-change-actions {
|
||||
margin-top: @table-cell-padding;
|
||||
}
|
||||
|
||||
.affiliations-table-label {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.btn-link-accounts {
|
||||
margin-bottom: (@line-height-computed / 2) - @table-cell-padding;
|
||||
}
|
||||
|
||||
.settings-widget-status-icon,
|
||||
.dropbox-sync-icon {
|
||||
position: relative;
|
||||
font-size: 1.3em;
|
||||
line-height: 1.3em;
|
||||
vertical-align: top;
|
||||
&.status-error,
|
||||
&.dropbox-sync-icon-error {
|
||||
color: @alert-danger-bg;
|
||||
}
|
||||
&.status-success,
|
||||
&.dropbox-sync-icon-success {
|
||||
color: @alert-success-bg;
|
||||
}
|
||||
&.status-pending,
|
||||
&.dropbox-sync-icon-updating {
|
||||
color: @alert-info-bg;
|
||||
&::after {
|
||||
content: '\f021';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
margin-left: -20%;
|
||||
font-size: 60%;
|
||||
color: #fff;
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-widgets-container {
|
||||
border: 1px solid @gray-lighter;
|
||||
|
||||
hr {
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-widget-container {
|
||||
display: grid;
|
||||
grid-template-columns: 40px 1fr auto;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-right: 20px;
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.dual-logo {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.description-container {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
> h4 {
|
||||
margin: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
.settings-widget-container {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
.title-row {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Should not be migrated to BS5
|
||||
.settings-reconfirm-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 0px auto @margin-sm auto !important;
|
||||
padding: @padding-md;
|
||||
&:not(.alert-info) {
|
||||
background-color: @ol-blue-gray-0;
|
||||
.fa-warning {
|
||||
color: @brand-warning;
|
||||
}
|
||||
}
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-right: @margin-md;
|
||||
}
|
||||
}
|
||||
|
||||
// Should not be migrated to BS5
|
||||
.setting-reconfirm-info-right {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Prevents icon from large account linking sections, such as the git bridge,
|
||||
// from rendering in the center of the widget, anchoring it to the top
|
||||
.linking-icon-fixed-position {
|
||||
align-self: start;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
// overrides the default `Col` padding, as the inner `affiliations-table-cell` has its own padding, and
|
||||
// the content length of the git-bridge token table is pretty much fixed (tokens and dates)
|
||||
.linking-git-bridge-table-cell {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.linking-git-bridge-revoke-button {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.security-row {
|
||||
.line-header > b {
|
||||
color: @ol-blue-gray-6;
|
||||
}
|
||||
|
||||
line-height: 24px;
|
||||
color: @ol-blue-gray-4;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 6px 0;
|
||||
|
||||
.icon {
|
||||
color: @ol-blue-gray-6;
|
||||
display: flex;
|
||||
flex: 1 1 7%;
|
||||
padding: 0 16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 1 1 93%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: @font-size-small;
|
||||
border-radius: 4px;
|
||||
padding: 2px 4px;
|
||||
margin-top: 4px;
|
||||
margin-left: 8px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.status-label-configured {
|
||||
background-color: @ol-green;
|
||||
color: @neutral-10;
|
||||
}
|
||||
|
||||
&.status-label-ready {
|
||||
background-color: @neutral-20;
|
||||
color: @neutral-90;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,6 @@
|
||||
background-color: var(--bg-light-secondary);
|
||||
}
|
||||
|
||||
.affiliations-table-inline-action {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.affiliation-change-container {
|
||||
margin-top: var(--spacing-04);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@
|
||||
|
||||
// Overleaf app classes
|
||||
@import 'app/base.less';
|
||||
@import 'app/account-settings.less';
|
||||
@import 'app/beta-program.less';
|
||||
@import 'app/about-page.less';
|
||||
@import 'app/project-list.less';
|
||||
|
||||
@@ -875,7 +875,7 @@ describe('<UserNotifications />', function () {
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', { name: /resend confirmation email/i })
|
||||
)
|
||||
await waitForElementToBeRemoved(() => screen.getByText('Loading'))
|
||||
await waitForElementToBeRemoved(() => screen.getByText('Sending…'))
|
||||
expect(sendReconfirmationMock.calls()).to.have.lengthOf(2)
|
||||
})
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('<AccountInfoSection />', function () {
|
||||
name: 'Update',
|
||||
})
|
||||
)
|
||||
await screen.findByRole('button', { name: 'Loading' })
|
||||
await screen.findByRole('button', { name: /saving/i })
|
||||
|
||||
finishUpdateCall(200)
|
||||
await screen.findByRole('button', {
|
||||
|
||||
@@ -69,7 +69,7 @@ async function confirmCodeForEmail(email: string) {
|
||||
})
|
||||
fireEvent.click(submitCodeBtn)
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByRole('button', { name: /Loading/i })
|
||||
screen.getByRole('button', { name: /confirming/i })
|
||||
)
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ describe('<EmailsSection />', function () {
|
||||
)
|
||||
|
||||
await confirmCodeForEmail(userEmailData.email)
|
||||
screen.getByText(userEmailData.email)
|
||||
await screen.findByText(userEmailData.email)
|
||||
})
|
||||
|
||||
it('fails to add add new email address', async function () {
|
||||
@@ -381,8 +381,8 @@ describe('<EmailsSection />', function () {
|
||||
|
||||
await confirmCodeForEmail(userEmailData.email)
|
||||
|
||||
screen.getByText(userEmailData.affiliation.role!, { exact: false })
|
||||
screen.getByText(customDepartment, { exact: false })
|
||||
await screen.findByText(userEmailData.affiliation.role!, { exact: false })
|
||||
await screen.findByText(customDepartment, { exact: false })
|
||||
})
|
||||
|
||||
it('autocompletes institution name', async function () {
|
||||
@@ -528,10 +528,12 @@ describe('<EmailsSection />', function () {
|
||||
department: userEmailData.affiliation?.department,
|
||||
})
|
||||
|
||||
screen.getByText(userEmailData.email)
|
||||
screen.getByText(newUniversity)
|
||||
screen.getByText(userEmailData.affiliation.role!, { exact: false })
|
||||
screen.getByText(userEmailData.affiliation.department!, { exact: false })
|
||||
await screen.findByText(userEmailData.email)
|
||||
await screen.findByText(newUniversity)
|
||||
await screen.findByText(userEmailData.affiliation.role!, { exact: false })
|
||||
await screen.findByText(userEmailData.affiliation.department!, {
|
||||
exact: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('shows country, university, role and department fields based on whether `change` was clicked or not', async function () {
|
||||
|
||||
@@ -195,7 +195,7 @@ describe('user role and institution', function () {
|
||||
screen.getByRole('button', { name: /saving/i })
|
||||
)
|
||||
|
||||
screen.getByText(roleValue, { exact: false })
|
||||
screen.getByText(departmentValue, { exact: false })
|
||||
await screen.findByText(roleValue, { exact: false })
|
||||
await screen.findByText(departmentValue, { exact: false })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -161,7 +161,7 @@ describe('<ReconfirmationInfo/>', function () {
|
||||
// commented out as it's already gone by this point
|
||||
// await screen.findByText(/Sending/)
|
||||
expect(fetchMock.called()).to.be.true
|
||||
await waitForElementToBeRemoved(() => screen.getByText(/Sending/))
|
||||
await waitForElementToBeRemoved(() => screen.getByText('Sending…'))
|
||||
await screen.findByRole('button', {
|
||||
name: 'Resend confirmation email',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user