diff --git a/services/web/app/src/Features/UserMembership/UserMembershipController.mjs b/services/web/app/src/Features/UserMembership/UserMembershipController.mjs index 1c8bee3f55..aaa8fa5812 100644 --- a/services/web/app/src/Features/UserMembership/UserMembershipController.mjs +++ b/services/web/app/src/Features/UserMembership/UserMembershipController.mjs @@ -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, diff --git a/services/web/app/views/user_membership/group-managers-react.pug b/services/web/app/views/user_membership/group-managers-react.pug index 143e2218d8..ed2f3454db 100644 --- a/services/web/app/views/user_membership/group-managers-react.pug +++ b/services/web/app/views/user_membership/group-managers-react.pug @@ -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) diff --git a/services/web/app/views/user_membership/group-members-react.pug b/services/web/app/views/user_membership/group-members-react.pug index 5a3b4f45f2..b146d0d143 100644 --- a/services/web/app/views/user_membership/group-members-react.pug +++ b/services/web/app/views/user_membership/group-members-react.pug @@ -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) diff --git a/services/web/app/views/user_membership/institution-managers-react.pug b/services/web/app/views/user_membership/institution-managers-react.pug index 99307f69a9..dfe59364dc 100644 --- a/services/web/app/views/user_membership/institution-managers-react.pug +++ b/services/web/app/views/user_membership/institution-managers-react.pug @@ -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) diff --git a/services/web/app/views/user_membership/publisher-managers-react.pug b/services/web/app/views/user_membership/publisher-managers-react.pug index 7f965add73..84bcbea80c 100644 --- a/services/web/app/views/user_membership/publisher-managers-react.pug +++ b/services/web/app/views/user_membership/publisher-managers-react.pug @@ -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) diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 0a8b92009a..058e8e77bf 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -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": "", diff --git a/services/web/frontend/js/features/group-management/components/back-button.tsx b/services/web/frontend/js/features/group-management/components/back-button.tsx index 5efac75366..2846fc7bc3 100644 --- a/services/web/frontend/js/features/group-management/components/back-button.tsx +++ b/services/web/frontend/js/features/group-management/components/back-button.tsx @@ -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 ( - - - - } - bs5={ - - } + ) } diff --git a/services/web/frontend/js/features/group-management/components/group-members.tsx b/services/web/frontend/js/features/group-management/components/group-members.tsx index ff14586882..2faeea9cc0 100644 --- a/services/web/frontend/js/features/group-management/components/group-members.tsx +++ b/services/web/frontend/js/features/group-management/components/group-members.tsx @@ -157,16 +157,6 @@ export default function GroupMembers() { variant="primary" onClick={onAddMembersSubmit} isLoading={inviteMemberLoading} - bs3Props={{ - loading: inviteMemberLoading ? ( - <> - {t('inviting')} - … - - ) : ( - t('invite') - ), - }} > {t('invite')} @@ -177,7 +167,7 @@ export default function GroupMembers() { - + {t('add_comma_separated_emails_help')} diff --git a/services/web/frontend/js/features/group-management/components/managers-table.tsx b/services/web/frontend/js/features/group-management/components/managers-table.tsx index d19fedce69..5efe2ffbb9 100644 --- a/services/web/frontend/js/features/group-management/components/managers-table.tsx +++ b/services/web/frontend/js/features/group-management/components/managers-table.tsx @@ -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({ - - } - bs5={ - - } + {t('email')} @@ -266,14 +250,6 @@ export function ManagersTable({ variant="primary" onClick={addManagers} isLoading={inviteUserInflightCount > 0} - bs3Props={{ - loading: - inviteUserInflightCount > 0 ? ( - <>{t('adding')}… - ) : ( - t('add') - ), - }} > {t('add')} @@ -281,7 +257,7 @@ export function ManagersTable({ - + {t('add_comma_separated_emails_help')} diff --git a/services/web/frontend/js/features/group-management/components/members-table/dropdown-button.tsx b/services/web/frontend/js/features/group-management/components/members-table/dropdown-button.tsx index 284e31a860..691a4b3636 100644 --- a/services/web/frontend/js/features/group-management/components/members-table/dropdown-button.tsx +++ b/services/web/frontend/js/features/group-management/components/members-table/dropdown-button.tsx @@ -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( - - {t('no_actions')} - - } - bs5={ - - - {t('no_actions')} - - - } - /> + + + {t('no_actions')} + + ) } return ( - - setIsOpened(open)} - > - - - - - {buttons} - - - - } - bs5={ - - - - - {buttons} - - } - /> + + + + + {buttons} + ) } @@ -347,42 +297,26 @@ function MenuItemButton({ 'data-testid': dataTestId, }: MenuItemButtonProps) { return ( - - - - } - bs5={ - - - - } - /> + + + ) } diff --git a/services/web/frontend/js/features/group-management/components/members-table/member-row.tsx b/services/web/frontend/js/features/group-management/components/members-table/member-row.tsx index 8fec350a3b..2398cbbf9d 100644 --- a/services/web/frontend/js/features/group-management/components/members-table/member-row.tsx +++ b/services/web/frontend/js/features/group-management/components/members-table/member-row.tsx @@ -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')} > - - } - bs5={ - - } + diff --git a/services/web/frontend/js/features/group-management/components/members-table/offboard-managed-user-modal.tsx b/services/web/frontend/js/features/group-management/components/members-table/offboard-managed-user-modal.tsx index 3f1165c046..4edf771d55 100644 --- a/services/web/frontend/js/features/group-management/components/members-table/offboard-managed-user-modal.tsx +++ b/services/web/frontend/js/features/group-management/components/members-table/offboard-managed-user-modal.tsx @@ -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 ? ( - <> - {t('deleting')}… - - ) : ( - t('delete_user') - ), - }} > {t('delete_user')} diff --git a/services/web/frontend/js/features/group-management/components/members-table/select-all-checkbox.tsx b/services/web/frontend/js/features/group-management/components/members-table/select-all-checkbox.tsx index 9286ce1a2e..17aaa2d983 100644 --- a/services/web/frontend/js/features/group-management/components/members-table/select-all-checkbox.tsx +++ b/services/web/frontend/js/features/group-management/components/members-table/select-all-checkbox.tsx @@ -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 ( - - } - bs5={ - - } + ) diff --git a/services/web/frontend/js/features/group-management/components/members-table/select-user-checkbox.tsx b/services/web/frontend/js/features/group-management/components/members-table/select-user-checkbox.tsx index fb83bc872f..a2d32810bc 100644 --- a/services/web/frontend/js/features/group-management/components/members-table/select-user-checkbox.tsx +++ b/services/web/frontend/js/features/group-management/components/members-table/select-user-checkbox.tsx @@ -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({ {/* the next check will hide the `checkbox` but still show the `th` */} {user.enrollment?.managedBy ? null : ( - handleSelectUser(e, user)} - aria-label={t('select_user')} - data-testid="select-single-checkbox" - /> - } - bs5={ - handleSelectUser(e, user)} - aria-label={t('select_user')} - data-testid="select-single-checkbox" - /> - } + handleSelectUser(e, user)} + aria-label={t('select_user')} + data-testid="select-single-checkbox" /> )} diff --git a/services/web/frontend/js/features/group-management/components/user-row.tsx b/services/web/frontend/js/features/group-management/components/user-row.tsx index 013dee1499..895cc69f04 100644 --- a/services/web/frontend/js/features/group-management/components/user-row.tsx +++ b/services/web/frontend/js/features/group-management/components/user-row.tsx @@ -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 ( - handleSelectUser(e, user)} - aria-label={t('select_user')} - data-testid="select-single-checkbox" - /> - } - bs5={ - handleSelectUser(e, user)} - aria-label={t('select_user')} - data-testid="select-single-checkbox" - /> - } + handleSelectUser(e, user)} + aria-label={t('select_user')} + data-testid="select-single-checkbox" /> {user.email} @@ -70,36 +53,15 @@ export default function UserRow({ {user.invite ? ( - - } - bs5={ - - } + ) : ( - - } - bs5={ - - } + )} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx b/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx index dca1242b10..7430e8cca7 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/group-settings-button.tsx @@ -92,7 +92,7 @@ export function GroupSettingsButtonWithAdBadge({
{heading}
{groupSettingRowSubText}
- + diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx index d3673d2d21..d465eb4050 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx @@ -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 @@ -19,9 +20,14 @@ function OLFormText({ as = 'div', ...props }: OLFormTextProps) { ...bs3Props, } as const satisfies React.ComponentProps + // Get all `aria-*` and `data-*` attributes + const extraProps = getAriaAndDataProps(rest) + return ( } + bs3={ + + } bs5={} /> ) diff --git a/services/web/frontend/stylesheets/components/group-members.less b/services/web/frontend/stylesheets/components/group-members.less deleted file mode 100644 index a164d42032..0000000000 --- a/services/web/frontend/stylesheets/components/group-members.less +++ /dev/null @@ -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; -} diff --git a/services/web/frontend/stylesheets/main-style.less b/services/web/frontend/stylesheets/main-style.less index 5a9906dbd2..696da82176 100644 --- a/services/web/frontend/stylesheets/main-style.less +++ b/services/web/frontend/stylesheets/main-style.less @@ -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'; diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 3285a3412f..1e5a89c93b 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -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 under the <1>Recompile 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",