mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
Add email notifications settings for redesigned editor
GitOrigin-RevId: d31f13bbc668d790564618e6b4a8a83fdf2d8780
This commit is contained in:
committed by
Copybot
parent
b9224ea11d
commit
3f6e96f58e
@@ -460,6 +460,7 @@ const _ProjectController = {
|
|||||||
'writefull-asymetric-queue-size-per-model',
|
'writefull-asymetric-queue-size-per-model',
|
||||||
'pdf-dark-mode',
|
'pdf-dark-mode',
|
||||||
'editor-redesign-opt-out',
|
'editor-redesign-opt-out',
|
||||||
|
'email-notifications',
|
||||||
].filter(Boolean)
|
].filter(Boolean)
|
||||||
|
|
||||||
const getUserValues = async userId =>
|
const getUserValues = async userId =>
|
||||||
|
|||||||
@@ -131,6 +131,8 @@
|
|||||||
"all_logs": "",
|
"all_logs": "",
|
||||||
"all_premium_features": "",
|
"all_premium_features": "",
|
||||||
"all_premium_features_including": "",
|
"all_premium_features_including": "",
|
||||||
|
"all_project_activity": "",
|
||||||
|
"all_project_activity_description": "",
|
||||||
"all_projects": "",
|
"all_projects": "",
|
||||||
"all_projects_will_be_transferred_immediately": "",
|
"all_projects_will_be_transferred_immediately": "",
|
||||||
"all_these_experiments_are_available_exclusively": "",
|
"all_these_experiments_are_available_exclusively": "",
|
||||||
@@ -541,6 +543,7 @@
|
|||||||
"email_link_expired": "",
|
"email_link_expired": "",
|
||||||
"email_managed_by_group_is": "",
|
"email_managed_by_group_is": "",
|
||||||
"email_must_be_linked_to_institution": "",
|
"email_must_be_linked_to_institution": "",
|
||||||
|
"email_notifications_are_currently_in_beta": "",
|
||||||
"email_or_password_wrong_try_again": "",
|
"email_or_password_wrong_try_again": "",
|
||||||
"email_remove_by_date": "",
|
"email_remove_by_date": "",
|
||||||
"emails_and_affiliations_explanation": "",
|
"emails_and_affiliations_explanation": "",
|
||||||
@@ -1158,6 +1161,7 @@
|
|||||||
"no_pdf_error_reason_unrecoverable_error": "",
|
"no_pdf_error_reason_unrecoverable_error": "",
|
||||||
"no_pdf_error_title": "",
|
"no_pdf_error_title": "",
|
||||||
"no_preview_available": "",
|
"no_preview_available": "",
|
||||||
|
"no_project_notifications_description": "",
|
||||||
"no_projects": "",
|
"no_projects": "",
|
||||||
"no_resolved_comments": "",
|
"no_resolved_comments": "",
|
||||||
"no_search_results": "",
|
"no_search_results": "",
|
||||||
@@ -1361,6 +1365,7 @@
|
|||||||
"project_linked_to": "",
|
"project_linked_to": "",
|
||||||
"project_name": "",
|
"project_name": "",
|
||||||
"project_not_linked_to_github": "",
|
"project_not_linked_to_github": "",
|
||||||
|
"project_notifications": "",
|
||||||
"project_ownership_transfer_confirmation_1": "",
|
"project_ownership_transfer_confirmation_1": "",
|
||||||
"project_ownership_transfer_confirmation_2": "",
|
"project_ownership_transfer_confirmation_2": "",
|
||||||
"project_renamed_or_deleted": "",
|
"project_renamed_or_deleted": "",
|
||||||
@@ -1480,6 +1485,8 @@
|
|||||||
"replace_from_computer": "",
|
"replace_from_computer": "",
|
||||||
"replace_from_project_files": "",
|
"replace_from_project_files": "",
|
||||||
"replace_from_url": "",
|
"replace_from_url": "",
|
||||||
|
"replies_to_your_activity_only": "",
|
||||||
|
"replies_to_your_activity_only_description": "",
|
||||||
"reply": "",
|
"reply": "",
|
||||||
"repository_name": "",
|
"repository_name": "",
|
||||||
"repository_visibility": "",
|
"repository_visibility": "",
|
||||||
@@ -1868,6 +1875,7 @@
|
|||||||
"then_x_price_per_year": "",
|
"then_x_price_per_year": "",
|
||||||
"there_are_lots_of_options_to_edit_and_customize_your_figures": "",
|
"there_are_lots_of_options_to_edit_and_customize_your_figures": "",
|
||||||
"there_was_a_problem_restoring_the_project_please_try_again_in_a_few_moments_or_contact_us": "",
|
"there_was_a_problem_restoring_the_project_please_try_again_in_a_few_moments_or_contact_us": "",
|
||||||
|
"these_settings_might_change_in_the_future": "",
|
||||||
"they_lose_access_to_account": "",
|
"they_lose_access_to_account": "",
|
||||||
"they_will_be_removed_from_the_group": "",
|
"they_will_be_removed_from_the_group": "",
|
||||||
"they_will_continue_to_have_access_to_any_projects_shared_with_them": "",
|
"they_will_continue_to_have_access_to_any_projects_shared_with_them": "",
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -42,6 +42,7 @@ export default /** @type {const} */ ([
|
|||||||
'more_vert',
|
'more_vert',
|
||||||
'neurology',
|
'neurology',
|
||||||
'note_add',
|
'note_add',
|
||||||
|
'notifications',
|
||||||
'open_in_new',
|
'open_in_new',
|
||||||
'password',
|
'password',
|
||||||
'picture_as_pdf',
|
'picture_as_pdf',
|
||||||
|
|||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import RadioButtonSetting, { RadioOption } from '../radio-button-setting'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
type NotificationLevel = 'all' | 'replies' | 'off'
|
||||||
|
|
||||||
|
export default function ProjectNotificationsSetting() {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
// TODO: Connect to project settings context when backend support is added
|
||||||
|
const [notificationLevel, setNotificationLevel] =
|
||||||
|
useState<NotificationLevel>('all')
|
||||||
|
|
||||||
|
const options: Array<RadioOption<NotificationLevel>> = [
|
||||||
|
{
|
||||||
|
value: 'all',
|
||||||
|
label: t('all_project_activity'),
|
||||||
|
description: t('all_project_activity_description'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'replies',
|
||||||
|
label: t('replies_to_your_activity_only'),
|
||||||
|
description: t('replies_to_your_activity_only_description'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'off',
|
||||||
|
label: t('off'),
|
||||||
|
description: t('no_project_notifications_description'),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RadioButtonSetting
|
||||||
|
id="projectNotifications"
|
||||||
|
options={options}
|
||||||
|
value={notificationLevel}
|
||||||
|
onChange={setNotificationLevel}
|
||||||
|
/>
|
||||||
|
<div className="project-notifications-beta-note">
|
||||||
|
<span className="beta-note-text">
|
||||||
|
{t('email_notifications_are_currently_in_beta')}{' '}
|
||||||
|
{t('these_settings_might_change_in_the_future')}{' '}
|
||||||
|
</span>
|
||||||
|
{/* TODO: update forms link */}
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="https://forms.gle/">
|
||||||
|
{t('give_feedback')}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export type RadioOption<T extends string = string> = {
|
||||||
|
value: T
|
||||||
|
label: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RadioButtonSettingProps<T extends string = string> = {
|
||||||
|
id: string
|
||||||
|
options: Array<RadioOption<T>>
|
||||||
|
value: T | undefined
|
||||||
|
onChange: (value: T) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RadioButtonSetting<T extends string = string>({
|
||||||
|
id,
|
||||||
|
options,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
}: RadioButtonSettingProps<T>) {
|
||||||
|
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
onChange(event.target.value as T)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ide-radio-setting-options">
|
||||||
|
{options.map(option => (
|
||||||
|
<label key={`${id}-${option.value}`} className="ide-radio-option">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id={`${id}-${option.value}`}
|
||||||
|
name={id}
|
||||||
|
value={option.value}
|
||||||
|
checked={value === option.value}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="ide-radio-input"
|
||||||
|
/>
|
||||||
|
<div className="ide-radio-text">
|
||||||
|
<span className="ide-setting-title">{option.label}</span>
|
||||||
|
{option.description && (
|
||||||
|
<span className="ide-setting-description">
|
||||||
|
{option.description}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
+17
@@ -3,6 +3,9 @@ import MaterialIcon from '@/shared/components/material-icon'
|
|||||||
import { Nav, NavLink, TabContainer, TabContent } from 'react-bootstrap'
|
import { Nav, NavLink, TabContainer, TabContent } from 'react-bootstrap'
|
||||||
import { SettingsEntry } from '../../contexts/settings-modal-context'
|
import { SettingsEntry } from '../../contexts/settings-modal-context'
|
||||||
import SettingsTabPane from './settings-tab-pane'
|
import SettingsTabPane from './settings-tab-pane'
|
||||||
|
import BetaBadgeIcon from '@/shared/components/beta-badge-icon'
|
||||||
|
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
export const SettingsModalBody = ({
|
export const SettingsModalBody = ({
|
||||||
activeTab,
|
activeTab,
|
||||||
@@ -42,6 +45,8 @@ export const SettingsModalBody = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SettingsNavLink = ({ entry }: { entry: SettingsEntry }) => {
|
const SettingsNavLink = ({ entry }: { entry: SettingsEntry }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
if ('href' in entry) {
|
if ('href' in entry) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
@@ -77,6 +82,18 @@ const SettingsNavLink = ({ entry }: { entry: SettingsEntry }) => {
|
|||||||
unfilled
|
unfilled
|
||||||
/>
|
/>
|
||||||
<span>{entry.title}</span>
|
<span>{entry.title}</span>
|
||||||
|
<div className="flex-grow-1" />
|
||||||
|
{entry.key === 'project_notifications' && (
|
||||||
|
<OLTooltip
|
||||||
|
id="project-notifications-beta-badge"
|
||||||
|
description={t('email_notifications_are_currently_in_beta')}
|
||||||
|
overlayProps={{ placement: 'right', delay: 100 }}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<BetaBadgeIcon />
|
||||||
|
</span>
|
||||||
|
</OLTooltip>
|
||||||
|
)}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import NewEditorSetting from '../components/settings/editor-settings/new-editor-
|
|||||||
import DarkModePdfSetting from '../components/settings/appearance-settings/dark-mode-pdf-setting'
|
import DarkModePdfSetting from '../components/settings/appearance-settings/dark-mode-pdf-setting'
|
||||||
import { useProjectSettingsContext } from '@/features/editor-left-menu/context/project-settings-context'
|
import { useProjectSettingsContext } from '@/features/editor-left-menu/context/project-settings-context'
|
||||||
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
import { useFeatureFlag } from '@/shared/context/split-test-context'
|
||||||
|
import ProjectNotificationsSetting from '../components/settings/editor-settings/project-notifications-setting'
|
||||||
|
|
||||||
const [referenceSearchSettingModule] = importOverleafModules(
|
const [referenceSearchSettingModule] = importOverleafModules(
|
||||||
'referenceSearchSetting'
|
'referenceSearchSetting'
|
||||||
@@ -51,6 +52,7 @@ export type SettingsTab = {
|
|||||||
icon: AvailableUnfilledIcon
|
icon: AvailableUnfilledIcon
|
||||||
sections: SettingsSection[]
|
sections: SettingsSection[]
|
||||||
title: string
|
title: string
|
||||||
|
hidden?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type SettingsLink = {
|
type SettingsLink = {
|
||||||
@@ -58,6 +60,7 @@ type SettingsLink = {
|
|||||||
icon: AvailableUnfilledIcon
|
icon: AvailableUnfilledIcon
|
||||||
href: string
|
href: string
|
||||||
title: string
|
title: string
|
||||||
|
hidden?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SettingsEntry = SettingsLink | SettingsTab
|
export type SettingsEntry = SettingsLink | SettingsTab
|
||||||
@@ -85,7 +88,8 @@ export const SettingsModalProvider: FC<React.PropsWithChildren> = ({
|
|||||||
const { leftMenuShown, setLeftMenuShown } = useLayoutContext()
|
const { leftMenuShown, setLeftMenuShown } = useLayoutContext()
|
||||||
|
|
||||||
const hasDarkModePdf = useFeatureFlag('pdf-dark-mode')
|
const hasDarkModePdf = useFeatureFlag('pdf-dark-mode')
|
||||||
const settingsTabs: SettingsEntry[] = useMemo(
|
const hasEmailNotifications = useFeatureFlag('email-notifications')
|
||||||
|
const allSettingsTabs: SettingsEntry[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
key: 'editor',
|
key: 'editor',
|
||||||
@@ -229,6 +233,25 @@ export const SettingsModalProvider: FC<React.PropsWithChildren> = ({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'project_notifications',
|
||||||
|
title: t('project_notifications'),
|
||||||
|
icon: 'notifications' as const,
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
key: 'general',
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
key: 'projectNotifications',
|
||||||
|
component: <ProjectNotificationsSetting />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
hidden: !hasEmailNotifications,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
key: 'account_settings',
|
key: 'account_settings',
|
||||||
title: t('account_settings'),
|
title: t('account_settings'),
|
||||||
@@ -242,7 +265,12 @@ export const SettingsModalProvider: FC<React.PropsWithChildren> = ({
|
|||||||
href: '/user/subscription',
|
href: '/user/subscription',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[t, overallTheme, hasDarkModePdf]
|
[t, overallTheme, hasDarkModePdf, hasEmailNotifications]
|
||||||
|
)
|
||||||
|
|
||||||
|
const settingsTabs = useMemo(
|
||||||
|
() => allSettingsTabs.filter(tab => !tab.hidden),
|
||||||
|
[allSettingsTabs]
|
||||||
)
|
)
|
||||||
|
|
||||||
const settingToTabMap = useMemo(() => {
|
const settingToTabMap = useMemo(() => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.ide-settings-tab-nav.nav {
|
.ide-settings-tab-nav.nav {
|
||||||
width: 240px;
|
width: 300px;
|
||||||
border-right: var(--bs-modal-header-border-width) solid
|
border-right: var(--bs-modal-header-border-width) solid
|
||||||
var(--bs-modal-header-border-color);
|
var(--bs-modal-header-border-color);
|
||||||
padding: var(--spacing-02);
|
padding: var(--spacing-02);
|
||||||
@@ -98,3 +98,35 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-left: var(--spacing-06);
|
margin-left: var(--spacing-06);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ide-radio-setting-options {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ide-radio-option {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: var(--spacing-04);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ide-radio-input {
|
||||||
|
margin-top: var(--spacing-02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ide-radio-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-notifications-beta-note {
|
||||||
|
margin-top: var(--spacing-06);
|
||||||
|
padding: var(--spacing-04);
|
||||||
|
font-size: var(--font-size-02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.beta-note-text {
|
||||||
|
color: var(--content-secondary);
|
||||||
|
}
|
||||||
|
|||||||
@@ -157,6 +157,8 @@
|
|||||||
"all_premium_features": "All premium features",
|
"all_premium_features": "All premium features",
|
||||||
"all_premium_features_including": "All premium features, including:",
|
"all_premium_features_including": "All premium features, including:",
|
||||||
"all_prices_displayed_are_in_currency": "All prices displayed are in __recommendedCurrency__.",
|
"all_prices_displayed_are_in_currency": "All prices displayed are in __recommendedCurrency__.",
|
||||||
|
"all_project_activity": "All project activity",
|
||||||
|
"all_project_activity_description": "You’ll be notified about all comments and track changes in this project.",
|
||||||
"all_projects": "All projects",
|
"all_projects": "All projects",
|
||||||
"all_projects_will_be_transferred_immediately": "All projects will be transferred to the new owner immediately.",
|
"all_projects_will_be_transferred_immediately": "All projects will be transferred to the new owner immediately.",
|
||||||
"all_templates": "All templates",
|
"all_templates": "All templates",
|
||||||
@@ -686,6 +688,7 @@
|
|||||||
"email_link_expired": "Email link expired, please request a new one.",
|
"email_link_expired": "Email link expired, please request a new one.",
|
||||||
"email_managed_by_group_is": "The email address that will be managed by your group is <0>__email__</0>.",
|
"email_managed_by_group_is": "The email address that will be managed by your group is <0>__email__</0>.",
|
||||||
"email_must_be_linked_to_institution": "As a member of __institutionName__, this email address can only be added via single sign-on on your <0>account settings</0> page. Please add a different recovery email address.",
|
"email_must_be_linked_to_institution": "As a member of __institutionName__, this email address can only be added via single sign-on on your <0>account settings</0> page. Please add a different recovery email address.",
|
||||||
|
"email_notifications_are_currently_in_beta": "Email notifications are currently in beta.",
|
||||||
"email_or_password_wrong_try_again": "Your email or password is incorrect. Please try again.",
|
"email_or_password_wrong_try_again": "Your email or password is incorrect. Please try again.",
|
||||||
"email_or_password_wrong_try_again_or_reset": "Your email or password is incorrect. Please try again, or <0>set or reset your password</0>.",
|
"email_or_password_wrong_try_again_or_reset": "Your email or password is incorrect. Please try again, or <0>set or reset your password</0>.",
|
||||||
"email_remove_by_date": "If this is not done by __date__, it will be removed from the account.",
|
"email_remove_by_date": "If this is not done by __date__, it will be removed from the account.",
|
||||||
@@ -1498,6 +1501,7 @@
|
|||||||
"no_pdf_error_title": "No PDF",
|
"no_pdf_error_title": "No PDF",
|
||||||
"no_planned_maintenance": "There is currently no planned maintenance",
|
"no_planned_maintenance": "There is currently no planned maintenance",
|
||||||
"no_preview_available": "Sorry, no preview is available.",
|
"no_preview_available": "Sorry, no preview is available.",
|
||||||
|
"no_project_notifications_description": "You won’t be notified about this project.",
|
||||||
"no_projects": "No projects",
|
"no_projects": "No projects",
|
||||||
"no_resolved_comments": "No resolved comments",
|
"no_resolved_comments": "No resolved comments",
|
||||||
"no_search_results": "No Search Results",
|
"no_search_results": "No Search Results",
|
||||||
@@ -1776,6 +1780,7 @@
|
|||||||
"project_linked_to": "This project is linked to",
|
"project_linked_to": "This project is linked to",
|
||||||
"project_name": "Project name",
|
"project_name": "Project name",
|
||||||
"project_not_linked_to_github": "This project is not linked to a GitHub repository. You can create a repository for it in GitHub:",
|
"project_not_linked_to_github": "This project is not linked to a GitHub repository. You can create a repository for it in GitHub:",
|
||||||
|
"project_notifications": "Project notifications",
|
||||||
"project_ownership_transfer_confirmation_1": "Are you sure you want to make <0>__user__</0> the owner of <1>__project__</1>?",
|
"project_ownership_transfer_confirmation_1": "Are you sure you want to make <0>__user__</0> the owner of <1>__project__</1>?",
|
||||||
"project_ownership_transfer_confirmation_2": "This action cannot be undone. The new owner will be notified and will be able to change project access settings (including removing your own access).",
|
"project_ownership_transfer_confirmation_2": "This action cannot be undone. The new owner will be notified and will be able to change project access settings (including removing your own access).",
|
||||||
"project_renamed_or_deleted": "Project Renamed or Deleted",
|
"project_renamed_or_deleted": "Project Renamed or Deleted",
|
||||||
@@ -1914,6 +1919,8 @@
|
|||||||
"replace_from_computer": "Replace from computer",
|
"replace_from_computer": "Replace from computer",
|
||||||
"replace_from_project_files": "Replace from project files",
|
"replace_from_project_files": "Replace from project files",
|
||||||
"replace_from_url": "Replace from URL",
|
"replace_from_url": "Replace from URL",
|
||||||
|
"replies_to_your_activity_only": "Replies to your activity only",
|
||||||
|
"replies_to_your_activity_only_description": "You’ll be notified about direct replies and activity on your track changes only.",
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"repository_name": "Repository Name",
|
"repository_name": "Repository Name",
|
||||||
"repository_visibility": "Repository visibility",
|
"repository_visibility": "Repository visibility",
|
||||||
@@ -2388,6 +2395,7 @@
|
|||||||
"there_are_lots_of_options_to_edit_and_customize_your_figures": "There are lots of options to edit and customize your figures, such as wrapping text around the figure, rotating the image, or including multiple images in a single figure. You’ll need to edit the LaTeX code to do this. <0>Find out how</0>",
|
"there_are_lots_of_options_to_edit_and_customize_your_figures": "There are lots of options to edit and customize your figures, such as wrapping text around the figure, rotating the image, or including multiple images in a single figure. You’ll need to edit the LaTeX code to do this. <0>Find out how</0>",
|
||||||
"there_was_a_problem_restoring_the_project_please_try_again_in_a_few_moments_or_contact_us": "There was a problem restoring the project. Please try again in a few moments. Contact us if the problem persists.",
|
"there_was_a_problem_restoring_the_project_please_try_again_in_a_few_moments_or_contact_us": "There was a problem restoring the project. Please try again in a few moments. Contact us if the problem persists.",
|
||||||
"there_was_an_error_opening_your_content": "There was an error creating your project",
|
"there_was_an_error_opening_your_content": "There was an error creating your project",
|
||||||
|
"these_settings_might_change_in_the_future": "These settings might change in the future.",
|
||||||
"thesis": "Thesis",
|
"thesis": "Thesis",
|
||||||
"they_lose_access_to_account": "They lose all access to this Overleaf account immediately",
|
"they_lose_access_to_account": "They lose all access to this Overleaf account immediately",
|
||||||
"they_will_be_removed_from_the_group": "They will be removed from the group.",
|
"they_will_be_removed_from_the_group": "They will be removed from the group.",
|
||||||
|
|||||||
Reference in New Issue
Block a user