mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-02 13:49:00 +02:00
Merge pull request #24562 from overleaf/ii-bs5-group-settings-tear-down
[web] Group settings BS5 feature flag tear down GitOrigin-RevId: c83297771dfeeb0426096b3b0765d6c420356d2a
This commit is contained in:
@@ -11,7 +11,6 @@ import {
|
||||
import { SSOConfig } from '../../models/SSOConfig.js'
|
||||
import { Parser as CSVParser } from 'json2csv'
|
||||
import { expressify } from '@overleaf/promise-utils'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
|
||||
import PlansLocator from '../Subscription/PlansLocator.js'
|
||||
import RecurlyClient from '../Subscription/RecurlyClient.js'
|
||||
|
||||
@@ -31,9 +30,6 @@ async function manageGroupMembers(req, res, next) {
|
||||
entityConfig
|
||||
)
|
||||
const ssoConfig = await SSOConfig.findById(subscription.ssoConfig).exec()
|
||||
|
||||
await SplitTestHandler.promises.getAssignment(req, res, 'bootstrap-5-groups')
|
||||
|
||||
const plan = PlansLocator.findLocalPlanInSettings(subscription.planCode)
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
const isAdmin = subscription.admin_id.toString() === userId
|
||||
@@ -114,8 +110,6 @@ async function _renderManagersPage(req, res, next, template) {
|
||||
entityConfig
|
||||
)
|
||||
|
||||
await SplitTestHandler.promises.getAssignment(req, res, 'bootstrap-5-groups')
|
||||
|
||||
res.render(template, {
|
||||
name: entityName,
|
||||
users,
|
||||
|
||||
@@ -5,7 +5,6 @@ block entrypointVar
|
||||
|
||||
block vars
|
||||
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
|
||||
- bootstrap5PageSplitTest = 'bootstrap-5-groups'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
|
||||
@@ -5,7 +5,6 @@ block entrypointVar
|
||||
|
||||
block vars
|
||||
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
|
||||
- bootstrap5PageSplitTest = 'bootstrap-5-groups'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
|
||||
@@ -5,7 +5,6 @@ block entrypointVar
|
||||
|
||||
block vars
|
||||
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
|
||||
- bootstrap5PageSplitTest = 'bootstrap-5-groups'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
|
||||
@@ -5,7 +5,6 @@ block entrypointVar
|
||||
|
||||
block vars
|
||||
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
|
||||
- bootstrap5PageSplitTest = 'bootstrap-5-groups'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
|
||||
@@ -393,7 +393,6 @@
|
||||
"disable_single_sign_on": "",
|
||||
"disable_sso": "",
|
||||
"disable_stop_on_first_error": "",
|
||||
"disabling": "",
|
||||
"disconnected": "",
|
||||
"discount": "",
|
||||
"discount_of": "",
|
||||
@@ -500,7 +499,6 @@
|
||||
"enable_stop_on_first_error_under_recompile_dropdown_menu_v2": "",
|
||||
"enabled": "",
|
||||
"enables_real_time_syntax_checking_in_the_editor": "",
|
||||
"enabling": "",
|
||||
"end_of_document": "",
|
||||
"ensure_recover_account": "",
|
||||
"enter_6_digit_code": "",
|
||||
@@ -817,7 +815,6 @@
|
||||
"invite_resend_limit_hit": "",
|
||||
"invited_to_group": "",
|
||||
"invited_to_group_have_individual_subcription": "",
|
||||
"inviting": "",
|
||||
"ip_address": "",
|
||||
"is_email_affiliated": "",
|
||||
"issued_on": "",
|
||||
@@ -1817,7 +1814,6 @@
|
||||
"transfer_management_resolve_following_issues": "",
|
||||
"transfer_this_users_projects": "",
|
||||
"transfer_this_users_projects_description": "",
|
||||
"transferring": "",
|
||||
"trash": "",
|
||||
"trash_projects": "",
|
||||
"trashed": "",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import IconButton from '@/features/ui/components/bootstrap-5/icon-button'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
type BackButtonProps = {
|
||||
href: string
|
||||
@@ -9,24 +7,12 @@ type BackButtonProps = {
|
||||
|
||||
function BackButton({ href, accessibilityLabel }: BackButtonProps) {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<a href={href} className="back-btn">
|
||||
<MaterialIcon
|
||||
type="arrow_back"
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
/>
|
||||
</a>
|
||||
}
|
||||
bs5={
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
href={href}
|
||||
size="lg"
|
||||
icon="arrow_back"
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
/>
|
||||
}
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
href={href}
|
||||
size="lg"
|
||||
icon="arrow_back"
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -157,16 +157,6 @@ export default function GroupMembers() {
|
||||
variant="primary"
|
||||
onClick={onAddMembersSubmit}
|
||||
isLoading={inviteMemberLoading}
|
||||
bs3Props={{
|
||||
loading: inviteMemberLoading ? (
|
||||
<>
|
||||
{t('inviting')}
|
||||
…
|
||||
</>
|
||||
) : (
|
||||
t('invite')
|
||||
),
|
||||
}}
|
||||
>
|
||||
{t('invite')}
|
||||
</OLButton>
|
||||
@@ -177,7 +167,7 @@ export default function GroupMembers() {
|
||||
</OLRow>
|
||||
<OLRow>
|
||||
<OLCol xs={8}>
|
||||
<OLFormText bs3Props={{ className: 'help-block' }}>
|
||||
<OLFormText>
|
||||
{t('add_comma_separated_emails_help')}
|
||||
</OLFormText>
|
||||
</OLCol>
|
||||
|
||||
@@ -18,7 +18,6 @@ import OLFormText from '@/features/ui/components/ol/ol-form-text'
|
||||
import OLTable from '@/features/ui/components/ol/ol-table'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
type ManagersPaths = {
|
||||
addMember: string
|
||||
@@ -182,27 +181,12 @@ export function ManagersTable({
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="cell-checkbox">
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<input
|
||||
className="select-all"
|
||||
type="checkbox"
|
||||
autoComplete="off"
|
||||
onChange={handleSelectAllClick}
|
||||
checked={selectedUsers.length === users.length}
|
||||
aria-label={t('select_all')}
|
||||
data-testid="select-all-checkbox"
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
onChange={handleSelectAllClick}
|
||||
checked={selectedUsers.length === users.length}
|
||||
aria-label={t('select_all')}
|
||||
data-testid="select-all-checkbox"
|
||||
/>
|
||||
}
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
onChange={handleSelectAllClick}
|
||||
checked={selectedUsers.length === users.length}
|
||||
aria-label={t('select_all')}
|
||||
data-testid="select-all-checkbox"
|
||||
/>
|
||||
</th>
|
||||
<th>{t('email')}</th>
|
||||
@@ -266,14 +250,6 @@ export function ManagersTable({
|
||||
variant="primary"
|
||||
onClick={addManagers}
|
||||
isLoading={inviteUserInflightCount > 0}
|
||||
bs3Props={{
|
||||
loading:
|
||||
inviteUserInflightCount > 0 ? (
|
||||
<>{t('adding')}…</>
|
||||
) : (
|
||||
t('add')
|
||||
),
|
||||
}}
|
||||
>
|
||||
{t('add')}
|
||||
</OLButton>
|
||||
@@ -281,7 +257,7 @@ export function ManagersTable({
|
||||
</OLRow>
|
||||
<OLRow>
|
||||
<OLCol xs={8}>
|
||||
<OLFormText bs3Props={{ className: 'help-block' }}>
|
||||
<OLFormText>
|
||||
{t('add_comma_separated_emails_help')}
|
||||
</OLFormText>
|
||||
</OLCol>
|
||||
|
||||
+40
-106
@@ -1,12 +1,10 @@
|
||||
import {
|
||||
useState,
|
||||
type ComponentProps,
|
||||
useCallback,
|
||||
type Dispatch,
|
||||
type SetStateAction,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dropdown as BS3Dropdown, MenuItem } from 'react-bootstrap'
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
@@ -16,11 +14,9 @@ import {
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
import useAsync from '@/shared/hooks/use-async'
|
||||
import { type FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { GroupUserAlert } from '../../utils/types'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import DropdownListItem from '@/features/ui/components/bootstrap-5/dropdown-list-item'
|
||||
import { Spinner } from 'react-bootstrap-5'
|
||||
@@ -46,7 +42,6 @@ export default function DropdownButton({
|
||||
}: ManagedUserDropdownButtonProps) {
|
||||
const { t } = useTranslation()
|
||||
const { removeMember } = useGroupMembersContext()
|
||||
const [isOpened, setIsOpened] = useState(false)
|
||||
const {
|
||||
runAsync: runResendManagedUserInviteAsync,
|
||||
isLoading: isResendingManagedUserInvite,
|
||||
@@ -82,7 +77,6 @@ export default function DropdownButton({
|
||||
variant: 'resendManagedUserInviteSuccess',
|
||||
email: user.email,
|
||||
})
|
||||
setIsOpened(false)
|
||||
}
|
||||
} catch (err) {
|
||||
if ((err as FetchError)?.response?.status === 429) {
|
||||
@@ -96,8 +90,6 @@ export default function DropdownButton({
|
||||
email: user.email,
|
||||
})
|
||||
}
|
||||
|
||||
setIsOpened(false)
|
||||
}
|
||||
},
|
||||
[setGroupUserAlert, groupId, runResendManagedUserInviteAsync]
|
||||
@@ -115,7 +107,6 @@ export default function DropdownButton({
|
||||
variant: 'resendSSOLinkInviteSuccess',
|
||||
email: user.email,
|
||||
})
|
||||
setIsOpened(false)
|
||||
}
|
||||
} catch (err) {
|
||||
if ((err as FetchError)?.response?.status === 429) {
|
||||
@@ -129,8 +120,6 @@ export default function DropdownButton({
|
||||
email: user.email,
|
||||
})
|
||||
}
|
||||
|
||||
setIsOpened(false)
|
||||
}
|
||||
},
|
||||
[setGroupUserAlert, groupId, runResendLinkSSOInviteAsync]
|
||||
@@ -151,7 +140,6 @@ export default function DropdownButton({
|
||||
variant: 'resendGroupInviteSuccess',
|
||||
email: user.email,
|
||||
})
|
||||
setIsOpened(false)
|
||||
} catch (err) {
|
||||
if ((err as FetchError)?.response?.status === 429) {
|
||||
setGroupUserAlert({
|
||||
@@ -164,8 +152,6 @@ export default function DropdownButton({
|
||||
email: user.email,
|
||||
})
|
||||
}
|
||||
|
||||
setIsOpened(false)
|
||||
}
|
||||
},
|
||||
[setGroupUserAlert, groupId, runResendGroupInviteAsync]
|
||||
@@ -270,65 +256,29 @@ export default function DropdownButton({
|
||||
|
||||
if (buttons.length === 0) {
|
||||
buttons.push(
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<MenuItem
|
||||
key="no-actions-available"
|
||||
data-testid="no-actions-available"
|
||||
>
|
||||
<span className="text-muted">{t('no_actions')}</span>
|
||||
</MenuItem>
|
||||
}
|
||||
bs5={
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
tabIndex={-1}
|
||||
data-testid="no-actions-available"
|
||||
disabled
|
||||
>
|
||||
{t('no_actions')}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
}
|
||||
/>
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
tabIndex={-1}
|
||||
data-testid="no-actions-available"
|
||||
disabled
|
||||
>
|
||||
{t('no_actions')}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div className="managed-user-actions">
|
||||
<BS3Dropdown
|
||||
id={`managed-user-dropdown-${user.email}`}
|
||||
open={isOpened}
|
||||
onToggle={open => setIsOpened(open)}
|
||||
>
|
||||
<BS3Dropdown.Toggle
|
||||
bsStyle={null}
|
||||
className="btn btn-link action-btn"
|
||||
noCaret
|
||||
>
|
||||
<Icon type="ellipsis-v" accessibilityLabel={t('actions')} />
|
||||
</BS3Dropdown.Toggle>
|
||||
<BS3Dropdown.Menu className="dropdown-menu-right managed-user-dropdown-menu">
|
||||
{buttons}
|
||||
</BS3Dropdown.Menu>
|
||||
</BS3Dropdown>
|
||||
</div>
|
||||
}
|
||||
bs5={
|
||||
<Dropdown align="end">
|
||||
<DropdownToggle
|
||||
id={`managed-user-dropdown-${user.email}`}
|
||||
bsPrefix="dropdown-table-button-toggle"
|
||||
>
|
||||
<MaterialIcon type="more_vert" accessibilityLabel={t('actions')} />
|
||||
</DropdownToggle>
|
||||
<DropdownMenu flip={false}>{buttons}</DropdownMenu>
|
||||
</Dropdown>
|
||||
}
|
||||
/>
|
||||
<Dropdown align="end">
|
||||
<DropdownToggle
|
||||
id={`managed-user-dropdown-${user.email}`}
|
||||
bsPrefix="dropdown-table-button-toggle"
|
||||
>
|
||||
<MaterialIcon type="more_vert" accessibilityLabel={t('actions')} />
|
||||
</DropdownToggle>
|
||||
<DropdownMenu flip={false}>{buttons}</DropdownMenu>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -347,42 +297,26 @@ function MenuItemButton({
|
||||
'data-testid': dataTestId,
|
||||
}: MenuItemButtonProps) {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<li role="presentation" className={className}>
|
||||
<button
|
||||
className="managed-user-menu-item-button"
|
||||
role="menuitem"
|
||||
onClick={onClick}
|
||||
data-testid={dataTestId}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
</li>
|
||||
}
|
||||
bs5={
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
tabIndex={-1}
|
||||
onClick={onClick}
|
||||
leadingIcon={
|
||||
isLoading ? (
|
||||
<Spinner
|
||||
animation="border"
|
||||
aria-hidden="true"
|
||||
size="sm"
|
||||
role="status"
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
data-testid={dataTestId}
|
||||
variant={variant}
|
||||
>
|
||||
{children}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
}
|
||||
/>
|
||||
<DropdownListItem>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
tabIndex={-1}
|
||||
onClick={onClick}
|
||||
leadingIcon={
|
||||
isLoading ? (
|
||||
<Spinner
|
||||
animation="border"
|
||||
aria-hidden="true"
|
||||
size="sm"
|
||||
role="status"
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
data-testid={dataTestId}
|
||||
variant={variant}
|
||||
>
|
||||
{children}
|
||||
</DropdownItem>
|
||||
</DropdownListItem>
|
||||
)
|
||||
}
|
||||
|
||||
+4
-17
@@ -10,9 +10,7 @@ import SelectUserCheckbox from './select-user-checkbox'
|
||||
import getMeta from '@/utils/meta'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import OLTag from '@/features/ui/components/ol/ol-tag'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import classnames from 'classnames'
|
||||
|
||||
type ManagedUserRowProps = {
|
||||
@@ -65,21 +63,10 @@ export default function MemberRow({
|
||||
description={t('group_admin')}
|
||||
>
|
||||
<span data-testid="group-admin-symbol">
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<Icon
|
||||
type="user-circle-o"
|
||||
fw
|
||||
accessibilityLabel={t('group_admin')}
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<MaterialIcon
|
||||
type="account_circle"
|
||||
accessibilityLabel={t('group_admin')}
|
||||
className="align-middle"
|
||||
/>
|
||||
}
|
||||
<MaterialIcon
|
||||
type="account_circle"
|
||||
accessibilityLabel={t('group_admin')}
|
||||
className="align-middle"
|
||||
/>
|
||||
</span>
|
||||
</OLTooltip>
|
||||
|
||||
-10
@@ -1,5 +1,4 @@
|
||||
import { User } from '../../../../../../types/group-management/user'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { useState } from 'react'
|
||||
import useAsync from '@/shared/hooks/use-async'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -144,15 +143,6 @@ export default function OffboardManagedUserModal({
|
||||
variant="danger"
|
||||
disabled={isLoading || isSuccess || !shouldEnableDeleteUserButton}
|
||||
isLoading={isLoading}
|
||||
bs3Props={{
|
||||
loading: isLoading ? (
|
||||
<>
|
||||
<Icon type="refresh" fw spin /> {t('deleting')}…
|
||||
</>
|
||||
) : (
|
||||
t('delete_user')
|
||||
),
|
||||
}}
|
||||
>
|
||||
{t('delete_user')}
|
||||
</OLButton>
|
||||
|
||||
+6
-22
@@ -2,7 +2,6 @@ import React, { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
export default function SelectAllCheckbox() {
|
||||
const { t } = useTranslation()
|
||||
@@ -31,27 +30,12 @@ export default function SelectAllCheckbox() {
|
||||
|
||||
return (
|
||||
<th className="cell-checkbox">
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<input
|
||||
className="select-all"
|
||||
type="checkbox"
|
||||
autoComplete="off"
|
||||
onChange={handleSelectAllNonManagedClick}
|
||||
checked={selectedUsers.length === nonManagedUsers.length}
|
||||
aria-label={t('select_all')}
|
||||
data-testid="select-all-checkbox"
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
onChange={handleSelectAllNonManagedClick}
|
||||
checked={selectedUsers.length === nonManagedUsers.length}
|
||||
aria-label={t('select_all')}
|
||||
data-testid="select-all-checkbox"
|
||||
/>
|
||||
}
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
onChange={handleSelectAllNonManagedClick}
|
||||
checked={selectedUsers.length === nonManagedUsers.length}
|
||||
aria-label={t('select_all')}
|
||||
data-testid="select-all-checkbox"
|
||||
/>
|
||||
</th>
|
||||
)
|
||||
|
||||
+6
-22
@@ -3,7 +3,6 @@ import type { User } from '../../../../../../types/group-management/user'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import { useCallback } from 'react'
|
||||
import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
type ManagedUsersSelectUserCheckboxProps = {
|
||||
user: User
|
||||
@@ -43,27 +42,12 @@ export default function SelectUserCheckbox({
|
||||
<td className="cell-checkbox">
|
||||
{/* the next check will hide the `checkbox` but still show the `th` */}
|
||||
{user.enrollment?.managedBy ? null : (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<input
|
||||
className="select-item"
|
||||
type="checkbox"
|
||||
autoComplete="off"
|
||||
checked={selected}
|
||||
onChange={e => handleSelectUser(e, user)}
|
||||
aria-label={t('select_user')}
|
||||
data-testid="select-single-checkbox"
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
checked={selected}
|
||||
onChange={e => handleSelectUser(e, user)}
|
||||
aria-label={t('select_user')}
|
||||
data-testid="select-single-checkbox"
|
||||
/>
|
||||
}
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
checked={selected}
|
||||
onChange={e => handleSelectUser(e, user)}
|
||||
aria-label={t('select_user')}
|
||||
data-testid="select-single-checkbox"
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
|
||||
@@ -3,8 +3,6 @@ import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { User } from '../../../../../types/group-management/user'
|
||||
import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
type GroupMemberRowProps = {
|
||||
@@ -36,27 +34,12 @@ export default function UserRow({
|
||||
return (
|
||||
<tr key={`user-${user.email}`} className="managed-entity-row">
|
||||
<td className="cell-checkbox">
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<input
|
||||
className="select-item"
|
||||
type="checkbox"
|
||||
autoComplete="off"
|
||||
checked={selected}
|
||||
onChange={e => handleSelectUser(e, user)}
|
||||
aria-label={t('select_user')}
|
||||
data-testid="select-single-checkbox"
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
checked={selected}
|
||||
onChange={e => handleSelectUser(e, user)}
|
||||
aria-label={t('select_user')}
|
||||
data-testid="select-single-checkbox"
|
||||
/>
|
||||
}
|
||||
<OLFormCheckbox
|
||||
autoComplete="off"
|
||||
checked={selected}
|
||||
onChange={e => handleSelectUser(e, user)}
|
||||
aria-label={t('select_user')}
|
||||
data-testid="select-single-checkbox"
|
||||
/>
|
||||
</td>
|
||||
<td>{user.email}</td>
|
||||
@@ -70,36 +53,15 @@ export default function UserRow({
|
||||
</td>
|
||||
<td className="cell-accepted-invite">
|
||||
{user.invite ? (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<Icon
|
||||
type="times"
|
||||
accessibilityLabel={t('invite_not_accepted')}
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<MaterialIcon
|
||||
type="clear"
|
||||
accessibilityLabel={t('invite_not_accepted')}
|
||||
/>
|
||||
}
|
||||
<MaterialIcon
|
||||
type="clear"
|
||||
accessibilityLabel={t('invite_not_accepted')}
|
||||
/>
|
||||
) : (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<Icon
|
||||
type="check"
|
||||
className="text-success"
|
||||
accessibilityLabel={t('accepted_invite')}
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<MaterialIcon
|
||||
type="check"
|
||||
className="text-success"
|
||||
accessibilityLabel={t('accepted_invite')}
|
||||
/>
|
||||
}
|
||||
<MaterialIcon
|
||||
type="check"
|
||||
className="text-success"
|
||||
accessibilityLabel={t('accepted_invite')}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ export function GroupSettingsButtonWithAdBadge({
|
||||
<div className="heading">{heading}</div>
|
||||
<div className="subtext">{groupSettingRowSubText}</div>
|
||||
</div>
|
||||
<span className="badge-group-settings">
|
||||
<span>
|
||||
<AvailableWithGroupProfessionalBadge />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import FormText, {
|
||||
import PolymorphicComponent from '@/shared/components/polymorphic-component'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import classnames from 'classnames'
|
||||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type OLFormTextProps = FormTextProps & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
@@ -19,9 +20,14 @@ function OLFormText({ as = 'div', ...props }: OLFormTextProps) {
|
||||
...bs3Props,
|
||||
} as const satisfies React.ComponentProps<typeof PolymorphicComponent>
|
||||
|
||||
// Get all `aria-*` and `data-*` attributes
|
||||
const extraProps = getAriaAndDataProps(rest)
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<PolymorphicComponent {...bs3HelpBlockProps} as={as} />}
|
||||
bs3={
|
||||
<PolymorphicComponent {...bs3HelpBlockProps} {...extraProps} as={as} />
|
||||
}
|
||||
bs5={<FormText {...rest} as={as} />}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
/* Styles for group-subscription members view */
|
||||
|
||||
.structured-list.managed-entities-list {
|
||||
/* Override scrolling behaviour on structured-list */
|
||||
overflow: initial;
|
||||
overflow-y: initial;
|
||||
overflow-x: initial;
|
||||
}
|
||||
|
||||
.managed-entities-list {
|
||||
.security-state-invite-pending {
|
||||
color: @text-muted;
|
||||
}
|
||||
.security-state-managed {
|
||||
color: @green;
|
||||
}
|
||||
.security-state-not-managed {
|
||||
color: @red;
|
||||
}
|
||||
.managed-entity-row {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.managed-user-security {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.managed-user-actions {
|
||||
button.dropdown-toggle {
|
||||
color: @text-color;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
.managed-user-dropdown-menu {
|
||||
width: 300px;
|
||||
|
||||
li > button {
|
||||
&:hover {
|
||||
background-color: @gray-lightest;
|
||||
}
|
||||
}
|
||||
.delete-user-action {
|
||||
button {
|
||||
color: @red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.managed-user-menu-item-button {
|
||||
padding: 12px 20px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
background: inherit;
|
||||
color: @ol-blue-gray-5;
|
||||
text-align: left;
|
||||
&[disabled] {
|
||||
background-color: @gray-lighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.managed-entities-table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid @structured-list-border-color;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: (@line-height-computed / 4) @line-height-computed / 2;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
thead {
|
||||
tr:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
tr:last-child {
|
||||
border-bottom: 0 none;
|
||||
}
|
||||
tr:hover {
|
||||
background-color: #f6f7f9;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-xs) {
|
||||
.cell-checkbox {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.group-sso-active {
|
||||
.cell-email {
|
||||
width: 37%;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.cell-last-active {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.cell-security {
|
||||
width: 12%;
|
||||
}
|
||||
|
||||
.cell-managed {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.cell-dropdown {
|
||||
width: 6%;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
.cell-accepted-invite {
|
||||
width: 17%;
|
||||
}
|
||||
|
||||
&.managed-users-active {
|
||||
.cell-email {
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
&.group-sso-active {
|
||||
.cell-checkbox {
|
||||
width: 3%;
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 29%;
|
||||
}
|
||||
|
||||
.cell-last-active {
|
||||
width: 16%;
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 18%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: @screen-lg) {
|
||||
.cell-checkbox {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
&.group-sso-active .cell-email {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.cell-last-active {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.cell-security {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.cell-managed {
|
||||
width: 13%;
|
||||
}
|
||||
|
||||
.cell-dropdown {
|
||||
width: 5%;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
.cell-accepted-invite {
|
||||
width: 17%;
|
||||
}
|
||||
|
||||
&.managed-users-active {
|
||||
.cell-email {
|
||||
width: 42%;
|
||||
}
|
||||
|
||||
&.group-sso-active {
|
||||
.cell-checkbox {
|
||||
width: 3%;
|
||||
}
|
||||
|
||||
.cell-email {
|
||||
width: 36%;
|
||||
}
|
||||
|
||||
.cell-name {
|
||||
width: 18%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.managed-user-security {
|
||||
.material-symbols {
|
||||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-group-settings {
|
||||
align-self: center;
|
||||
padding: 0 16px;
|
||||
}
|
||||
@@ -91,7 +91,6 @@
|
||||
@import 'components/navs-ol.less';
|
||||
@import 'components/pagination.less';
|
||||
@import 'components/tabs.less';
|
||||
@import 'components/group-members.less';
|
||||
|
||||
// ngTagsInput
|
||||
@import 'components/tags-input.less';
|
||||
|
||||
@@ -515,7 +515,6 @@
|
||||
"disable_single_sign_on": "Disable single sign-on",
|
||||
"disable_sso": "Disable SSO",
|
||||
"disable_stop_on_first_error": "Disable “Stop on first error”",
|
||||
"disabling": "Disabling",
|
||||
"disconnected": "Disconnected",
|
||||
"discount": "Discount",
|
||||
"discount_of": "Discount of __amount__",
|
||||
@@ -649,7 +648,6 @@
|
||||
"enable_stop_on_first_error_under_recompile_dropdown_menu_v2": "Enable <0>Stop on first error</0> under the <1>Recompile</1> drop-down menu to help you find and fix errors right away.",
|
||||
"enabled": "Enabled",
|
||||
"enables_real_time_syntax_checking_in_the_editor": "Enables real-time syntax checking in the editor",
|
||||
"enabling": "Enabling",
|
||||
"end_of_document": "End of document",
|
||||
"ensure_recover_account": "This will ensure that it can be used to recover your __appName__ account in case you lose access to your primary email address.",
|
||||
"enter_6_digit_code": "Enter 6-digit code",
|
||||
@@ -1070,7 +1068,6 @@
|
||||
"invited_to_group_login_benefits": "As part of this group, you’ll have access to __appName__ premium features such as additional collaborators, greater maximum compile time, and real-time track changes.",
|
||||
"invited_to_group_register": "To accept __inviterName__’s invitation you’ll need to create an account.",
|
||||
"invited_to_group_register_benefits": "__appName__ is a collaborative online LaTeX editor, with thousands of ready-to-use templates and an array of LaTeX learning resources to help you get started.",
|
||||
"inviting": "Inviting",
|
||||
"ip_address": "IP Address",
|
||||
"is_email_affiliated": "Is your email affiliated with an institution? ",
|
||||
"is_longer_than_n_characters": "is at least __n__ characters long",
|
||||
@@ -2348,7 +2345,6 @@
|
||||
"transfer_management_resolve_following_issues": "To transfer the management of your account, you need to resolve the following issues:",
|
||||
"transfer_this_users_projects": "Transfer this user’s projects",
|
||||
"transfer_this_users_projects_description": "This user’s projects will be transferred to a new owner.",
|
||||
"transferring": "Transferring",
|
||||
"trash": "Trash",
|
||||
"trash_projects": "Trash Projects",
|
||||
"trashed": "Trashed",
|
||||
|
||||
Reference in New Issue
Block a user