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:
ilkin-overleaf
2025-04-01 16:30:59 +03:00
committed by Copybot
parent f1f57a74e3
commit 1337af755c
20 changed files with 91 additions and 539 deletions
@@ -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')}
&hellip;
</>
) : (
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')}&hellip;</>
) : (
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>
@@ -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>
)
}
@@ -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>
@@ -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>
@@ -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>
)
@@ -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>
@@ -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';
-4
View File
@@ -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, youll 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 youll 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 users projects",
"transfer_this_users_projects_description": "This users projects will be transferred to a new owner.",
"transferring": "Transferring",
"trash": "Trash",
"trash_projects": "Trash Projects",
"trashed": "Trashed",