mirror of
https://github.com/overleaf/overleaf.git
synced 2025-12-05 01:10:29 +00:00
Compare commits
12 Commits
8b33fc86ab
...
f0f7899de4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0f7899de4 | ||
|
|
5fe9d3d6e9 | ||
|
|
7488c80b36 | ||
|
|
360c7c1d33 | ||
|
|
67f105edcf | ||
|
|
9e3aba0b6f | ||
|
|
414fc3cdb3 | ||
|
|
56c1d38d47 | ||
|
|
1d36f42159 | ||
|
|
1b5887d97f | ||
|
|
2bf48b3774 | ||
|
|
19b38340ac |
1
package-lock.json
generated
1
package-lock.json
generated
@@ -52496,6 +52496,7 @@
|
||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||
"@contentful/rich-text-types": "^16.0.2",
|
||||
"@google-cloud/bigquery": "^6.0.1",
|
||||
"@google-cloud/storage": "^6.10.1",
|
||||
"@node-oauth/oauth2-server": "^5.1.0",
|
||||
"@node-saml/passport-saml": "^5.1.0",
|
||||
"@overleaf/access-token-encryptor": "*",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"scripts": {
|
||||
"format": "prettier --list-different $PWD/'**/*.js'",
|
||||
"format:fix": "prettier --write $PWD/'**/*.js'",
|
||||
"format:jenkins": "prettier --list-different $PWD/'**/Jenkinsfile'",
|
||||
"format:jenkins:fix": "prettier --write $PWD/'**/Jenkinsfile'",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"postinstall": "patch-package"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"scripts": {
|
||||
"cypress:open": "cypress open --e2e --browser chrome",
|
||||
"cypress:run": "cypress run --e2e --browser chrome",
|
||||
"format": "prettier --list-different $PWD/'**/{*.{js,mjs,ts,tsx,json},Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.{js,mjs,ts,tsx,json},Jenkinsfile}'"
|
||||
"format": "prettier --list-different $PWD/'**/*.{js,mjs,ts,tsx,json}'",
|
||||
"format:fix": "prettier --write $PWD/'**/*.{js,mjs,ts,tsx,json}'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@isomorphic-git/lightning-fs": "^4.6.0",
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js",
|
||||
"test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP",
|
||||
"nodemon": "node --watch app.js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP",
|
||||
"nodemon": "node --watch app.js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP",
|
||||
"nodemon": "node --watch app.js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"nodemon": "node --watch app.js",
|
||||
"benchmark:apply": "node benchmarks/apply",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"start": "node app.js",
|
||||
"nodemon": "node --watch app.js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js",
|
||||
"test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js",
|
||||
"lint:fix": "eslint --fix .",
|
||||
|
||||
@@ -62,8 +62,8 @@
|
||||
"start": "node app.js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP",
|
||||
"test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP",
|
||||
"test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js",
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"test:unit:_run": "vitest --config ./vitest.config.unit.cjs",
|
||||
"test:unit": "npm run test:unit:_run",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit",
|
||||
"nodemon": "node --watch app.js"
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"test:acceptance:_run": "mocha --loader=esmock --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js",
|
||||
"test:unit:_run": "mocha --loader=esmock --recursive --reporter spec --exit $@ test/unit/js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP",
|
||||
"nodemon": "node --watch app.js",
|
||||
"lint": "eslint --max-warnings 0 --format unix .",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts,Jenkinsfile}'",
|
||||
"format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'",
|
||||
"format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"types:check": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -136,7 +136,11 @@ const RestoreManager = {
|
||||
|
||||
const snapshotFile = projectSnapshotAtVersion.getFile(pathname)
|
||||
if (!snapshotFile) {
|
||||
throw new OError('file not found in snapshot', { pathname })
|
||||
throw new OError('file not found in snapshot', {
|
||||
projectId,
|
||||
version,
|
||||
pathname,
|
||||
})
|
||||
}
|
||||
|
||||
let hadDeletedRootFile = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
meta(name="ol-project_id" content=project_id)
|
||||
meta(name="ol-projectName" content=projectName)
|
||||
meta(name="ol-projectOwnerHasPremiumOnPageLoad" content=projectOwnerHasPremiumOnPageLoad)
|
||||
meta(name="ol-projectOwnerHasPremiumOnPageLoad" data-type="boolean" content=projectOwnerHasPremiumOnPageLoad)
|
||||
meta(name="ol-userSettings" data-type="json" content=userSettings)
|
||||
meta(name="ol-user" data-type="json" content=user)
|
||||
meta(name="ol-labsExperiments" data-type="json" content=labsExperiments)
|
||||
|
||||
@@ -1239,7 +1239,9 @@
|
||||
"payment_error_3ds_failed": "",
|
||||
"payment_error_generic": "",
|
||||
"payment_error_intermittent_error": "",
|
||||
"payment_error_invalid_payment_method": "",
|
||||
"payment_error_update_payment_method": "",
|
||||
"payment_error_update_payment_method_checkout": "",
|
||||
"payment_provider_unreachable_error": "",
|
||||
"payment_summary": "",
|
||||
"pdf": "",
|
||||
@@ -1779,6 +1781,7 @@
|
||||
"sync_with_a_github_repository": "",
|
||||
"synctex_error_recompile_and_try_again": "",
|
||||
"synctex_failed": "",
|
||||
"syntax_checks": "",
|
||||
"syntax_validation": "",
|
||||
"tab_connecting": "",
|
||||
"tab_no_longer_connected": "",
|
||||
|
||||
@@ -89,7 +89,7 @@ export default function CloneProjectModalContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('copy_project')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { memo, useCallback, useState } from 'react'
|
||||
import CloneProjectModalContent from './clone-project-modal-content'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
import { ClonedProject } from '../../../../../types/project/dashboard/api'
|
||||
import { Tag } from '../../../../../app/src/Features/Tags/types'
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ export default function DictionaryModalContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('edit_dictionary')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import DictionaryModalContent from './dictionary-modal-content'
|
||||
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
|
||||
type DictionaryModalProps = {
|
||||
show?: boolean
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
|
||||
import FileTreeCreateFormProvider from '../../contexts/file-tree-create-form'
|
||||
import FileTreeModalCreateFileBody from '../file-tree-create/file-tree-modal-create-file-body'
|
||||
import FileTreeModalCreateFileFooter from '../file-tree-create/file-tree-modal-create-file-footer'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -22,7 +23,7 @@ export default function FileTreeModalCreateFile() {
|
||||
return (
|
||||
<FileTreeCreateFormProvider>
|
||||
<OLModal size="lg" onHide={cancel} show>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('add_files')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import { useRefWithAutoFocus } from '../../../../shared/hooks/use-ref-with-auto-
|
||||
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
|
||||
import { DuplicateFilenameError } from '../../errors'
|
||||
import { isCleanFilename } from '../../util/safe-path'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
DuplicateFilenameError,
|
||||
DuplicateFilenameMoveError,
|
||||
} from '../../errors'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import { FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useTranslation, Trans } from 'react-i18next'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import { FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -8,7 +8,8 @@ import NotificationScrolledTo from '@/shared/components/notification-scrolled-to
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { GroupUserAlert } from '../../utils/types'
|
||||
import { useGroupMembersContext } from '../../context/group-members-context'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useEffect, useState } from 'react'
|
||||
import OLForm from '@/shared/components/ol/ol-form'
|
||||
import OLFormGroup from '@/shared/components/ol/ol-form-group'
|
||||
import ModalError from './modal-error'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { forwardRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { formatTime } from '@/features/utils/format-date'
|
||||
import { useMemo } from 'react'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -28,7 +29,7 @@ export function RestoreFileConfirmModal({
|
||||
|
||||
return (
|
||||
<OLModal show={show} onHide={onHide}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('restore_file_confirmation_title')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -16,7 +17,7 @@ export function RestoreFileErrorModal({
|
||||
|
||||
return (
|
||||
<OLModal show onHide={resetErrorBoundary}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('restore_file_error_title')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>{t('restore_file_error_message')}</OLModalBody>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -16,7 +17,7 @@ export function RestoreProjectErrorModal({
|
||||
|
||||
return (
|
||||
<OLModal show onHide={resetErrorBoundary}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{t('an_error_occured_while_restoring_project')}
|
||||
</OLModalTitle>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import HotkeysModalBottomText from './hotkeys-modal-bottom-text'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -29,7 +30,7 @@ export default function HotkeysModal({
|
||||
|
||||
return (
|
||||
<OLModal size="lg" onHide={handleHide} show={show} animation={animation}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('hotkeys')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
import { useConnectionContext } from '@/features/ide-react/context/connection-context'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
@@ -55,7 +56,7 @@ function ForceDisconnected() {
|
||||
backdrop={false}
|
||||
keyboard={false}
|
||||
>
|
||||
<OLModalHeader>
|
||||
<OLModalHeader closeButton={false}>
|
||||
<OLModalTitle>{t('please_wait')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -32,7 +33,7 @@ function GenericConfirmModal({
|
||||
|
||||
return (
|
||||
<OLModal {...modalProps}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -25,7 +26,7 @@ function GenericMessageModal({
|
||||
|
||||
return (
|
||||
<OLModal {...modalProps}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ import { Trans, useTranslation } from 'react-i18next'
|
||||
import { memo, useState } from 'react'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -36,7 +37,7 @@ function OutOfSyncModal({ editorContent, show, onHide }: OutOfSyncModalProps) {
|
||||
backdrop={false}
|
||||
keyboard={false}
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('out_of_sync')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody className="modal-body-share">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
@@ -37,7 +38,7 @@ const SettingsModal = () => {
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('settings')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody className="ide-settings-modal-body">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useIdeRedesignSwitcherContext } from '@/features/ide-react/context/ide-redesign-switcher-context'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -50,7 +51,7 @@ export const IdeRedesignIntroModal: FC = () => {
|
||||
onHide={dismissTutorial}
|
||||
className="ide-redesign-switcher-modal"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{t('the_new_overleaf_editor_try_now_in_beta')}
|
||||
</OLModalTitle>
|
||||
@@ -99,7 +100,7 @@ export const IdeRedesignSwitcherModal = () => {
|
||||
onHide={onHide}
|
||||
className="ide-redesign-switcher-modal"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{enabled
|
||||
? t('beta_program_the_new_overleaf_editor')
|
||||
|
||||
@@ -165,7 +165,7 @@ function PdfCompileButton() {
|
||||
</DropdownItem>
|
||||
</li>
|
||||
<DropdownDivider />
|
||||
<DropdownHeader>Syntax Checks</DropdownHeader>
|
||||
<DropdownHeader>{t('syntax_checks')}</DropdownHeader>
|
||||
<li role="none">
|
||||
<DropdownItem
|
||||
as="button"
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import HumanReadableLogs from '../../../ide/human-readable-logs/HumanReadableLogs'
|
||||
import BibLogParser from '../../../ide/log-parser/bib-log-parser'
|
||||
import BibLogParser, {
|
||||
BibLogEntry,
|
||||
} from '../../../ide/log-parser/bib-log-parser'
|
||||
import { enablePdfCaching } from './pdf-caching-flags'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { dirname, findEntityByPath } from '@/features/file-tree/util/path'
|
||||
import '@/utils/readable-stream-async-iterator-polyfill'
|
||||
import { EDITOR_SESSION_ID } from '@/features/pdf-preview/util/metrics'
|
||||
import { LogEntry } from './types'
|
||||
import { CompileResponseData, PDFFile } from '@ol-types/compile'
|
||||
import { LatexLogEntry } from '@/ide/log-parser/latex-log-parser'
|
||||
import { Annotation } from '@ol-types/annotation'
|
||||
import { Folder } from '@ol-types/folder'
|
||||
|
||||
// Warnings that may disappear after a second LaTeX pass
|
||||
const TRANSIENT_WARNING_REGEX = /^(Reference|Citation).+undefined on input line/
|
||||
@@ -12,7 +19,11 @@ const TRANSIENT_WARNING_REGEX = /^(Reference|Citation).+undefined on input line/
|
||||
const MAX_LOG_SIZE = 1024 * 1024 // 1MB
|
||||
const MAX_BIB_LOG_SIZE_PER_FILE = MAX_LOG_SIZE
|
||||
|
||||
export function handleOutputFiles(outputFiles, projectId, data) {
|
||||
export function handleOutputFiles(
|
||||
outputFiles: Map<string, PDFFile>,
|
||||
projectId: string,
|
||||
data: CompileResponseData
|
||||
): PDFFile | null {
|
||||
const outputFile = outputFiles.get('output.pdf')
|
||||
if (!outputFile) return null
|
||||
|
||||
@@ -34,10 +45,7 @@ export function handleOutputFiles(outputFiles, projectId, data) {
|
||||
params.set('enable_pdf_caching', 'true')
|
||||
}
|
||||
|
||||
outputFile.pdfUrl = `${buildURL(
|
||||
outputFile,
|
||||
data.pdfDownloadDomain
|
||||
)}?${params}`
|
||||
outputFile.pdfUrl = `${buildURL(outputFile, data.pdfDownloadDomain)}?${params}`
|
||||
|
||||
if (data.fromCache) {
|
||||
outputFile.pdfDownloadUrl = outputFile.downloadURL
|
||||
@@ -53,33 +61,58 @@ export function handleOutputFiles(outputFiles, projectId, data) {
|
||||
|
||||
let nextEntryId = 1
|
||||
|
||||
function generateEntryKey() {
|
||||
function generateEntryKey(): string {
|
||||
return 'compile-log-entry-' + nextEntryId++
|
||||
}
|
||||
|
||||
export const handleLogFiles = async (outputFiles, data, signal) => {
|
||||
const result = {
|
||||
type LogResult = {
|
||||
log: string | null
|
||||
logEntries: {
|
||||
errors: LogEntry[]
|
||||
warnings: LogEntry[]
|
||||
typesetting: LogEntry[]
|
||||
all: LogEntry[]
|
||||
}
|
||||
}
|
||||
export async function handleLogFiles(
|
||||
outputFiles: Map<string, PDFFile>,
|
||||
data: CompileResponseData,
|
||||
signal: AbortSignal
|
||||
): Promise<LogResult> {
|
||||
const result: LogResult = {
|
||||
log: null,
|
||||
logEntries: {
|
||||
all: [],
|
||||
errors: [],
|
||||
warnings: [],
|
||||
typesetting: [],
|
||||
},
|
||||
}
|
||||
|
||||
function accumulateResults(newEntries, type) {
|
||||
for (const key in result.logEntries) {
|
||||
function accumulateResults(
|
||||
newEntries: {
|
||||
errors?: (LatexLogEntry | BibLogEntry)[]
|
||||
warnings?: (LatexLogEntry | BibLogEntry)[]
|
||||
typesetting?: (LatexLogEntry | BibLogEntry)[]
|
||||
all?: (LatexLogEntry | BibLogEntry)[]
|
||||
},
|
||||
type?: string
|
||||
) {
|
||||
for (const key of Object.keys(result.logEntries) as Array<
|
||||
keyof typeof result.logEntries
|
||||
>) {
|
||||
if (newEntries[key]) {
|
||||
for (const entry of newEntries[key]) {
|
||||
if (type) {
|
||||
entry.type = newEntries.type
|
||||
// Type casting as we are mutating LatexLogEntry | BibLogEntry into a LogEntry
|
||||
;(entry as LogEntry).type = type
|
||||
}
|
||||
if (entry.file) {
|
||||
entry.file = normalizeFilePath(entry.file)
|
||||
}
|
||||
entry.key = generateEntryKey()
|
||||
;(entry as LogEntry).key = generateEntryKey()
|
||||
}
|
||||
result.logEntries[key].push(...newEntries[key])
|
||||
result.logEntries[key].push(...(newEntries[key] as LogEntry[]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +144,7 @@ export const handleLogFiles = async (outputFiles, data, signal) => {
|
||||
}
|
||||
}
|
||||
|
||||
const blgFiles = []
|
||||
const blgFiles: PDFFile[] = []
|
||||
|
||||
for (const [filename, file] of outputFiles) {
|
||||
if (filename.endsWith('.blg')) {
|
||||
@@ -143,15 +176,15 @@ export const handleLogFiles = async (outputFiles, data, signal) => {
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('../../../../../types/annotation').Annotation} Annotation
|
||||
* @returns {Record<string, Annotation[]>}
|
||||
*/
|
||||
export function buildLogEntryAnnotations(entries, fileTreeData, rootDocId) {
|
||||
const rootDocDirname = dirname(fileTreeData, rootDocId)
|
||||
export function buildLogEntryAnnotations(
|
||||
entries: LogEntry[],
|
||||
fileTreeData: Folder,
|
||||
rootDocId?: string | null
|
||||
): Record<string, Annotation[]> {
|
||||
const rootDocDirname = rootDocId ? dirname(fileTreeData, rootDocId) : null
|
||||
|
||||
const logEntryAnnotations = {}
|
||||
const seenLine = {}
|
||||
const logEntryAnnotations: Record<string, Annotation[]> = {}
|
||||
const seenLine: Record<number, boolean> = {}
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.file) {
|
||||
@@ -164,12 +197,12 @@ export function buildLogEntryAnnotations(entries, fileTreeData, rootDocId) {
|
||||
logEntryAnnotations[entity._id] = []
|
||||
}
|
||||
|
||||
const annotation = {
|
||||
const annotation: Annotation = {
|
||||
id: entry.key,
|
||||
entryIndex: logEntryAnnotations[entity._id].length, // used for maintaining the order of items on the same line
|
||||
row: entry.line - 1,
|
||||
row: (entry.line || 1) - 1,
|
||||
type: entry.level === 'error' ? 'error' : 'warning',
|
||||
text: entry.message,
|
||||
text: entry.message ?? '',
|
||||
source: 'compile', // NOTE: this is used in Ace for filtering the annotations
|
||||
ruleId: entry.ruleId,
|
||||
command: entry.command,
|
||||
@@ -177,9 +210,9 @@ export function buildLogEntryAnnotations(entries, fileTreeData, rootDocId) {
|
||||
|
||||
// set firstOnLine for the first non-typesetting annotation on a line
|
||||
if (entry.level !== 'typesetting') {
|
||||
if (!seenLine[entry.line]) {
|
||||
if (!seenLine[entry.line || 0]) {
|
||||
annotation.firstOnLine = true
|
||||
seenLine[entry.line] = true
|
||||
seenLine[entry.line || 0] = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,8 +224,10 @@ export function buildLogEntryAnnotations(entries, fileTreeData, rootDocId) {
|
||||
return logEntryAnnotations
|
||||
}
|
||||
|
||||
export const buildRuleCounts = (entries = []) => {
|
||||
const counts = {}
|
||||
export const buildRuleCounts = (
|
||||
entries: LogEntry[] = []
|
||||
): Record<string, number> => {
|
||||
const counts: Record<string, number> = {}
|
||||
for (const entry of entries) {
|
||||
const key = `${entry.level}_${entry.ruleId}`
|
||||
counts[key] = counts[key] ? counts[key] + 1 : 1
|
||||
@@ -200,16 +235,17 @@ export const buildRuleCounts = (entries = []) => {
|
||||
return counts
|
||||
}
|
||||
|
||||
export const buildRuleDeltas = (ruleCounts, previousRuleCounts) => {
|
||||
const counts = {}
|
||||
export const buildRuleDeltas = (
|
||||
ruleCounts: Record<string, number>,
|
||||
previousRuleCounts: Record<string, number>
|
||||
): Record<string, number> => {
|
||||
const counts: Record<string, number> = {}
|
||||
|
||||
// keys that are defined in the current log entries
|
||||
for (const [key, value] of Object.entries(ruleCounts)) {
|
||||
const previousValue = previousRuleCounts[key] ?? 0
|
||||
counts[`delta_${key}`] = value - previousValue
|
||||
}
|
||||
|
||||
// keys that are no longer defined in the current log entries
|
||||
for (const [key, value] of Object.entries(previousRuleCounts)) {
|
||||
if (!(key in ruleCounts)) {
|
||||
counts[key] = 0
|
||||
@@ -220,7 +256,7 @@ export const buildRuleDeltas = (ruleCounts, previousRuleCounts) => {
|
||||
return counts
|
||||
}
|
||||
|
||||
function buildURL(file, pdfDownloadDomain) {
|
||||
function buildURL(file: PDFFile, pdfDownloadDomain?: string): string {
|
||||
if (file.build && pdfDownloadDomain) {
|
||||
// Downloads from the compiles domain must include a build id.
|
||||
// The build id is used implicitly for access control.
|
||||
@@ -230,13 +266,15 @@ function buildURL(file, pdfDownloadDomain) {
|
||||
return `${window.origin}${file.url}`
|
||||
}
|
||||
|
||||
function normalizeFilePath(path, rootDocDirname) {
|
||||
function normalizeFilePath(
|
||||
path: string,
|
||||
rootDocDirname?: string | null
|
||||
): string {
|
||||
path = path.replace(/\/\//g, '/')
|
||||
path = path.replace(
|
||||
/^.*\/compiles\/[0-9a-f]{24}(-[0-9a-f]{24})?\/(\.\/)?/,
|
||||
''
|
||||
)
|
||||
|
||||
path = path.replace(/^\/compile\//, '')
|
||||
|
||||
if (rootDocDirname) {
|
||||
@@ -246,11 +284,15 @@ function normalizeFilePath(path, rootDocDirname) {
|
||||
return path
|
||||
}
|
||||
|
||||
function isTransientWarning(warning) {
|
||||
return TRANSIENT_WARNING_REGEX.test(warning.message)
|
||||
function isTransientWarning(warning: LatexLogEntry): boolean {
|
||||
return TRANSIENT_WARNING_REGEX.test(warning.message || '')
|
||||
}
|
||||
|
||||
async function fetchFileWithSizeLimit(url, signal, maxSize) {
|
||||
async function fetchFileWithSizeLimit(
|
||||
url: string,
|
||||
signal: AbortSignal,
|
||||
maxSize: number
|
||||
): Promise<string> {
|
||||
let result = ''
|
||||
try {
|
||||
const abortController = new AbortController()
|
||||
@@ -267,11 +309,13 @@ async function fetchFileWithSizeLimit(url, signal, maxSize) {
|
||||
throw new Error('Failed to fetch log file')
|
||||
}
|
||||
|
||||
const reader = response.body.pipeThrough(new TextDecoderStream())
|
||||
for await (const chunk of reader) {
|
||||
result += chunk
|
||||
if (result.length > maxSize) {
|
||||
abortController.abort()
|
||||
const reader = response.body?.pipeThrough(new TextDecoderStream())
|
||||
if (reader) {
|
||||
for await (const chunk of reader) {
|
||||
result += chunk
|
||||
if (result.length > maxSize) {
|
||||
abortController.abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -14,6 +14,7 @@ export type LogEntry = {
|
||||
type?: string
|
||||
messageComponent?: React.ReactNode
|
||||
contentDetails?: string[]
|
||||
command?: string
|
||||
}
|
||||
|
||||
export type ErrorLevel =
|
||||
|
||||
@@ -9,7 +9,8 @@ import { createTag } from '../../util/api'
|
||||
import { MAX_TAG_LENGTH } from '../../util/tag'
|
||||
import { ColorPicker } from '../color-picker/color-picker'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -80,7 +81,7 @@ export default function CreateTagModal({
|
||||
|
||||
return (
|
||||
<OLModal show animation onHide={onClose} id={id} backdrop="static">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('create_new_tag')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import { Tag } from '../../../../../../app/src/Features/Tags/types'
|
||||
import useAsync from '../../../../shared/hooks/use-async'
|
||||
import { deleteTag } from '../../util/api'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -46,7 +47,7 @@ export default function DeleteTagModal({
|
||||
|
||||
return (
|
||||
<OLModal show animation onHide={onClose} id={id} backdrop="static">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('delete_tag')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import { editTag } from '../../util/api'
|
||||
import { getTagColor, MAX_TAG_LENGTH } from '../../util/tag'
|
||||
import { ColorPicker } from '../color-picker/color-picker'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -88,7 +89,7 @@ export function EditTagModal({ id, tag, onEdit, onClose }: EditTagModalProps) {
|
||||
|
||||
return (
|
||||
<OLModal show animation onHide={onClose} id={id} backdrop="static">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('edit_tag')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import { Tag } from '../../../../../../app/src/Features/Tags/types'
|
||||
import { getTagColor } from '../../util/tag'
|
||||
import { ColorPicker } from '../color-picker/color-picker'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -89,7 +90,7 @@ export function ManageTagModal({
|
||||
|
||||
return (
|
||||
<OLModal show animation onHide={onClose} id={id} backdrop="static">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('edit_tag')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import * as eventTracking from '../../../../infrastructure/event-tracking'
|
||||
import { isSmallDevice } from '../../../../infrastructure/event-tracking'
|
||||
import Notification from '@/shared/components/notification'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -79,7 +80,7 @@ function ProjectsActionModal({
|
||||
id="action-project-modal"
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -16,7 +16,8 @@ import { getUserFacingMessage } from '../../../../infrastructure/fetch-json'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { isSmallDevice } from '../../../../infrastructure/event-tracking'
|
||||
import Notification from '@/shared/components/notification'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -104,7 +105,7 @@ function RenameProjectModal({
|
||||
id="rename-project-modal"
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('rename_project')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import ModalContentNewProjectForm from './modal-content-new-project-form'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
|
||||
type BlankProjectModalProps = {
|
||||
onHide: () => void
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
import ModalContentNewProjectForm from './modal-content-new-project-form'
|
||||
|
||||
type ExampleProjectModalProps = {
|
||||
|
||||
@@ -74,7 +74,7 @@ function ModalContentNewProjectForm({ onCancel, template = 'none' }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('new_project')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -94,7 +95,7 @@ function UploadProjectModal({ onHide, openProject }: UploadProjectModalProps) {
|
||||
id="upload-project-modal"
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle as="h3">{t('upload_zipped_project')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -2,7 +2,8 @@ import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import bannerImage from '../../../images/brl-banner.png'
|
||||
import usePersistedState from '../../../../../shared/hooks/use-persisted-state'
|
||||
import * as eventTracking from '../../../../../infrastructure/event-tracking'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -90,7 +91,7 @@ export default function BRLBanner() {
|
||||
|
||||
return (
|
||||
<OLModal show={showModal} onHide={handleHide}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('latam_discount_modal_title')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import bannerImage from '../../../images/inr-banner.png'
|
||||
import usePersistedState from '../../../../../shared/hooks/use-persisted-state'
|
||||
import * as eventTracking from '../../../../../infrastructure/event-tracking'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -88,7 +89,7 @@ export default function INRBanner() {
|
||||
|
||||
return (
|
||||
<OLModal show={showModal} onHide={handleHide} backdrop="static">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('inr_discount_modal_title')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -5,7 +5,8 @@ import clpBannerImage from '../../../images/clp-banner.png'
|
||||
import penBannerImage from '../../../images/pen-banner.png'
|
||||
import usePersistedState from '../../../../../shared/hooks/use-persisted-state'
|
||||
import * as eventTracking from '../../../../../infrastructure/event-tracking'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -133,7 +134,7 @@ export default function LATAMBanner() {
|
||||
|
||||
return (
|
||||
<OLModal show={showModal} onHide={handleHide} backdrop="static">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('latam_discount_modal_title')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -8,7 +8,8 @@ import { postJSON } from '../../../../../../infrastructure/fetch-json'
|
||||
import { isSmallDevice } from '../../../../../../infrastructure/event-tracking'
|
||||
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -120,7 +121,7 @@ function CompileErrorModal({
|
||||
return (
|
||||
<>
|
||||
<OLModal show onHide={handleClose}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{project.name}: {t('pdf_unavailable_for_download')}
|
||||
</OLModalTitle>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { FC, memo } from 'react'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -5,7 +5,8 @@ import teaserVideo from '../images/teaser-track-changes.mp4'
|
||||
import teaserImage from '../images/teaser-track-changes.gif'
|
||||
import { startFreeTrial, upgradePlan } from '@/main/account-upgrade'
|
||||
import { memo } from 'react'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -31,7 +32,7 @@ function UpgradeTrackChangesModal({
|
||||
|
||||
return (
|
||||
<OLModal show={show} onHide={() => setShow(false)}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('upgrade_to_review')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody className="upgrade-track-changes-modal">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { MergeAndOverride } from '../../../../../../../../types/utils'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -32,7 +33,7 @@ function ConfirmationModal({
|
||||
|
||||
return (
|
||||
<OLModal show={show} onHide={onHide}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('confirm_primary_email_change')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody className="pb-0">
|
||||
|
||||
@@ -4,7 +4,8 @@ import { FetchError, postJSON } from '@/infrastructure/fetch-json'
|
||||
import useAsync from '../../../../shared/hooks/use-async'
|
||||
import { UserEmailData } from '../../../../../../types/user-email'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -56,7 +57,7 @@ function ResendConfirmationCodeModal({
|
||||
id="action-project-modal"
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('confirm_your_email')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ function LeaveModalContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('delete_account')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import LeaveModalContent from './modal-content'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
|
||||
type LeaveModalProps = {
|
||||
isOpen: boolean
|
||||
|
||||
@@ -4,7 +4,8 @@ import OLBadge from '@/shared/components/ol/ol-badge'
|
||||
import getMeta from '../../../../utils/meta'
|
||||
import { sendMB } from '../../../../infrastructure/event-tracking'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -208,7 +209,7 @@ function UnlinkConfirmationModal({
|
||||
|
||||
return (
|
||||
<OLModal show={show} onHide={handleHide}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ import GoogleLogo from '../../../../shared/svgs/google-logo'
|
||||
import OrcidLogo from '../../../../shared/svgs/orcid-logo'
|
||||
import LinkingStatus from './status'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -168,7 +169,7 @@ function UnlinkConfirmModal({
|
||||
|
||||
return (
|
||||
<OLModal show={show} onHide={handleHide}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{t('unlink_provider_account_title', { provider: title })}
|
||||
</OLModalTitle>
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function EditorOverLimitModalContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('do_you_need_edit_access')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useProjectContext } from '@/shared/context/project-context'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
|
||||
const EditorOverLimitModal = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { lazy, Suspense } from 'react'
|
||||
import { FullSizeLoadingSpinner } from '@/shared/components/loading-spinner'
|
||||
import ClickableElementEnhancer from '@/shared/components/clickable-element-enhancer'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -43,7 +44,7 @@ export default function ShareProjectModalContent({
|
||||
|
||||
return (
|
||||
<OLModal show={show} onHide={cancel} animation={animation}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('share_project')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ import { Trans, useTranslation } from 'react-i18next'
|
||||
import { transferProjectOwnership } from '../utils/api'
|
||||
import { useProjectContext } from '@/shared/context/project-context'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -45,7 +46,7 @@ export default function TransferOwnershipModal({
|
||||
|
||||
return (
|
||||
<OLModal show onHide={cancel}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('change_project_owner')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function ViewOnlyAccessModalContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('view_only_access')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useProjectContext } from '@/shared/context/project-context'
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context'
|
||||
import { sendMB } from '@/infrastructure/event-tracking'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
|
||||
const ViewOnlyAccessModal = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -273,7 +274,7 @@ const FigureModalContent = () => {
|
||||
}
|
||||
return (
|
||||
<OLModal onHide={hide} className="figure-modal" show>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{helpShown
|
||||
? t('help')
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
DropdownToggle,
|
||||
} from '@/shared/components/dropdown/dropdown-menu'
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -19,7 +20,7 @@ export const TableGeneratorHelpModal = () => {
|
||||
onHide={hideHelp}
|
||||
className="table-generator-help-modal"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('help')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -16,7 +16,8 @@ import { setColumnWidth } from '../commands'
|
||||
import { UNITS, WidthSelection, WidthUnit } from './column-width'
|
||||
import { useCodeMirrorViewContext } from '../../../codemirror-context'
|
||||
import { CopyToClipboard } from '@/shared/components/copy-to-clipboard'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -137,7 +138,7 @@ const ColumnWidthModalBody = () => {
|
||||
onHide={closeColumnWidthModal}
|
||||
className="table-generator-width-modal"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('set_column_width')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -13,21 +13,19 @@ import { memo } from 'react'
|
||||
import OLListGroupItem from '@/shared/components/ol/ol-list-group-item'
|
||||
import sparkleWhite from '@/shared/svgs/sparkle-small-white.svg'
|
||||
import sparkle from '@/shared/svgs/ai-sparkle-text.svg'
|
||||
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
|
||||
|
||||
export const MathDropdown = memo(function MathDropdown() {
|
||||
const { t } = useTranslation()
|
||||
const view = useCodeMirrorViewContext()
|
||||
const { writefullInstance } = useEditorContext()
|
||||
|
||||
const wfRebrandEnabled = isSplitTestEnabled('overleaf-assist-bundle')
|
||||
return (
|
||||
<ToolbarButtonMenu
|
||||
id="toolbar-math"
|
||||
label={t('toolbar_insert_math')}
|
||||
icon={<MaterialIcon type="calculate" />}
|
||||
>
|
||||
{wfRebrandEnabled && writefullInstance && (
|
||||
{writefullInstance && (
|
||||
<>
|
||||
<DropdownHeader className="ol-cm-toolbar-header mx-2">
|
||||
{t('toolbar_insert_math_lowercase')}
|
||||
|
||||
@@ -12,7 +12,6 @@ import { MathDropdown } from './math-dropdown'
|
||||
import { TableDropdown } from './table-dropdown'
|
||||
import { LegacyTableDropdown } from './table-inserter-dropdown-legacy'
|
||||
import { withinFormattingCommand } from '@/features/source-editor/utils/tree-operations/formatting'
|
||||
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
|
||||
import { isMac } from '@/shared/utils/os'
|
||||
import { useProjectContext } from '@/shared/context/project-context'
|
||||
import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
|
||||
@@ -42,8 +41,6 @@ export const ToolbarItems: FC<{
|
||||
const symbolPaletteAvailable = getMeta('ol-symbolPaletteAvailable')
|
||||
const showGroup = (group: string) => !overflowed || overflowed.has(group)
|
||||
|
||||
const wfRebrandEnabled = isSplitTestEnabled('overleaf-assist-bundle')
|
||||
|
||||
return (
|
||||
<>
|
||||
{showGroup('group-history') && (
|
||||
@@ -155,11 +152,7 @@ export const ToolbarItems: FC<{
|
||||
icon="book_5"
|
||||
/>
|
||||
<InsertFigureDropdown />
|
||||
{wfRebrandEnabled && writefullInstance ? (
|
||||
<TableDropdown />
|
||||
) : (
|
||||
<LegacyTableDropdown />
|
||||
)}
|
||||
{writefullInstance ? <TableDropdown /> : <LegacyTableDropdown />}
|
||||
</div>
|
||||
)}
|
||||
{showGroup('group-list') && (
|
||||
|
||||
@@ -297,7 +297,7 @@ function useCodeMirrorScope(view: EditorView) {
|
||||
// which editor keybindings are active ('default' | 'vim' | 'emacs')
|
||||
ol_editor_keybindings: settingsRef.current.mode,
|
||||
// whether Writefull is present ('extension' | 'integration' | 'none')
|
||||
ol_extensions_writefull: window.writefull?.type ?? 'none',
|
||||
ol_extensions_writefull: window.writefull ? 'integration' : 'none',
|
||||
// whether Grammarly is present
|
||||
ol_extensions_grammarly: grammarlyExtensionPresent(),
|
||||
},
|
||||
|
||||
@@ -4,7 +4,8 @@ import { deleteJSON } from '../../../../infrastructure/fetch-json'
|
||||
import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context'
|
||||
import { useLocation } from '../../../../shared/hooks/use-location'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useSubscriptionDashboardContext } from '../../context/subscription-dash
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { postJSON } from '@/infrastructure/fetch-json'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalHeader,
|
||||
} from '@/shared/components/ol/ol-modal'
|
||||
@@ -88,7 +89,7 @@ export default function PauseSubscriptionModal() {
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalBody>
|
||||
<OLModalHeader closeButton style={{ border: 0 }} />
|
||||
<OLModalHeader style={{ border: 0 }} />
|
||||
<img
|
||||
src={PauseDuck}
|
||||
alt="Need to duck out for a while?"
|
||||
|
||||
@@ -4,7 +4,8 @@ import { SubscriptionDashModalIds } from '../../../../../../../../../../types/su
|
||||
import { postJSON } from '../../../../../../../../infrastructure/fetch-json'
|
||||
import { useSubscriptionDashboardContext } from '../../../../../../context/subscription-dashboard-context'
|
||||
import { useLocation } from '../../../../../../../../shared/hooks/use-location'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -4,7 +4,8 @@ import LoadingSpinner from '../../../../../../../../shared/components/loading-sp
|
||||
import { useSubscriptionDashboardContext } from '../../../../../../context/subscription-dashboard-context'
|
||||
import { ChangeToGroupPlan } from '../change-to-group-plan'
|
||||
import { IndividualPlansTable } from '../individual-plans-table'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
@@ -43,7 +44,7 @@ export function ChangePlanModal() {
|
||||
|
||||
return (
|
||||
<OLModal id={modalId} show animation onHide={handleCloseModal} size="lg">
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('change_plan')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ import GenericErrorAlert from '../../../../generic-error-alert'
|
||||
import { subscriptionUpdateUrl } from '../../../../../../data/subscription-url'
|
||||
import { getRecurlyGroupPlanCode } from '../../../../../../util/recurly-group-plan-code'
|
||||
import { useLocation } from '../../../../../../../../shared/hooks/use-location'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -175,7 +176,7 @@ export function ChangeToGroupModal() {
|
||||
onHide={handleCloseModal}
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle className="lh-sm">
|
||||
{t('customize_your_group_subscription')}
|
||||
{showGroupDiscount && (
|
||||
|
||||
@@ -9,7 +9,8 @@ import getMeta from '../../../../../../../../utils/meta'
|
||||
import { useSubscriptionDashboardContext } from '../../../../../../context/subscription-dashboard-context'
|
||||
import { subscriptionUpdateUrl } from '../../../../../../data/subscription-url'
|
||||
import { useLocation } from '../../../../../../../../shared/hooks/use-location'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -5,7 +5,8 @@ import { postJSON } from '../../../../../../../../infrastructure/fetch-json'
|
||||
import { useSubscriptionDashboardContext } from '../../../../../../context/subscription-dashboard-context'
|
||||
import { cancelPendingSubscriptionChangeUrl } from '../../../../../../data/subscription-url'
|
||||
import { useLocation } from '../../../../../../../../shared/hooks/use-location'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SubscriptionDashModalIds } from '../../../../../../../../../../types/subscription/dashboard/modal-ids'
|
||||
import { useSubscriptionDashboardContext } from '../../../../../../context/subscription-dashboard-context'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -2,7 +2,8 @@ import { useState } from 'react'
|
||||
import { SubscriptionDashModalIds } from '../../../../../../../../types/subscription/dashboard/modal-ids'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { useSubscriptionDashboardContext } from '@/features/subscription/context/subscription-dashboard-context'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import OLButton from '@/shared/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
import {
|
||||
OLModal,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
@@ -28,7 +29,7 @@ function LeaveProjectModal({
|
||||
id="action-project-modal"
|
||||
backdrop="static"
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('leave_project')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function WordCountModalContent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>
|
||||
{t('word_count_lower')}{' '}
|
||||
<SplitTestBadge
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { memo } from 'react'
|
||||
import WordCountModalContent from './word-count-modal-content'
|
||||
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
||||
import OLModal from '@/shared/components/ol/ol-modal'
|
||||
import { OLModal } from '@/shared/components/ol/ol-modal'
|
||||
|
||||
const WordCountModal = memo(function WordCountModal({
|
||||
show,
|
||||
|
||||
@@ -151,60 +151,6 @@ const en = {
|
||||
'errors.error-hit-limit-freemium.heading': 'You’re on fire!',
|
||||
'errors.error-hit-limit-freemium.body':
|
||||
'You’ve hit your Writefull quota. Upgrade now for unlimited language suggestions and LaTeX support, and early access to upcoming features like TikZ generation.',
|
||||
'checkout.need-more-info': "Need more info? We're here to help.",
|
||||
'checkout.free-plan-question': 'What’s included in the Free plan?',
|
||||
'checkout.free-plan-answer':
|
||||
"The Free plan offers a limited number of language edits a day, restricted use of the writing features (to paraphrase, change style, explain or summarize, and more), and limited access to TeXGPT and the LaTeX generation options. You're notified when you've hit your daily limit. Please note that limits might change daily so that we can maintain certain levels of quality of service.",
|
||||
'checkout.premium-plan-question':
|
||||
'Do I get different language edits if I upgrade to Premium?',
|
||||
'checkout.premium-plan-answer':
|
||||
'Both the Free and Premium plans let you choose the language model that revises your text: Writefull’s model, which is ideal for research writing in English, or GPT, which works with any language or text type. With the Free plan, you get a limited number of edits each day, but Premium gives you unlimited access. Plus, when you upgrade to Premium, you can add custom prompts to GPT, giving you more control over how your text is revised.',
|
||||
'checkout.custom-prompt-question':
|
||||
"What does the 'custom prompt for GPT language edits' mean?",
|
||||
'checkout.custom-prompt-answer':
|
||||
'With this feature, you can give the GPT model specific instructions on how to revise your text. For example, you can ask it to keep certain terms unchanged, make your writing more assertive, or focus only on essential language corrections. It’s a great way to tailor the edits to your needs! This option is available with the Premium plan.',
|
||||
'checkout.supercomplete-question': "What is the 'Supercomplete' feature?",
|
||||
'checkout.supercomplete-answer':
|
||||
"The 'Supercomplete' feature makes your writing even more efficient by completing your sentences and LaTeX code when prompted. This is a fully Premium feature.",
|
||||
'checkout.upcoming-features-question':
|
||||
'What other features are likely to come?',
|
||||
'checkout.upcoming-features-answer':
|
||||
'We have a long list of upcoming features! Two of these are translation and diagram generation using TikZ.',
|
||||
'checkout.overleaf-subscription-question':
|
||||
'I already pay for Overleaf. Do I still need Writefull Premium?',
|
||||
'checkout.overleaf-subscription-answer':
|
||||
'Yes, Writefull and Overleaf have integrated, but are two separate services with their own subscriptions.',
|
||||
'checkout.group-discounts-question': 'Do you offer group discounts?',
|
||||
'checkout.group-discounts-answer':
|
||||
'We do! Go here to calculate pricing depending on your group size. Select a plan and invite others to join.',
|
||||
'checkout.fair-usage-policy': '* Fair usage policy applies.',
|
||||
'checkout.still-have-questions': 'Do you still have questions?',
|
||||
'checkout.contact-us': 'Contact Us',
|
||||
'checkout.monthly': 'Monthly',
|
||||
'checkout.yearly': 'Yearly',
|
||||
'checkout.free': 'FREE',
|
||||
'checkout.basic-access': 'Basic access to Writefull',
|
||||
'checkout.features': 'Features:',
|
||||
'checkout.limited-language-edits': 'Limited language edits',
|
||||
'checkout.limited-writing-features': 'Limited usage of writing features',
|
||||
'checkout.limited-texgpt': 'Limited usage of TeXGPT',
|
||||
'checkout.custom-prompt': 'Custom prompt for GPT language edits',
|
||||
'checkout.supercomplete': 'Supercomplete',
|
||||
'checkout.supercomplete-coming': 'Supercomplete (coming soon)',
|
||||
'checkout.priority-access': 'Priority access to new Writefull features',
|
||||
'checkout.premium': 'WRITEFULL PREMIUM',
|
||||
'checkout.all-unlocked': 'All of Writefull unlocked',
|
||||
'checkout.unlimited-language-edits': 'Unlimited language edits*',
|
||||
'checkout.unlimited-writing-features':
|
||||
'Unlimited usage of writing features*',
|
||||
'checkout.unlimited-texgpt': 'Unlimited usage of TeXGPT',
|
||||
'checkout.redirecting': 'Redirecting...',
|
||||
'checkout.select-plan': 'Select Writefull plan',
|
||||
'checkout.looking-for': 'Looking for',
|
||||
'checkout.group-licenses': 'group licenses',
|
||||
'checkout.per-month': 'Per month',
|
||||
'checkout.your-current-plan': 'Your current plan',
|
||||
'checkout.billed-as-one-payment-of': 'billed as one payment of',
|
||||
'toolbar.abstract-generator.name': 'Abstract Generator',
|
||||
'toolbar.title-generator.name': 'Title Generator',
|
||||
'toolbar.create-table.name': 'Create tables',
|
||||
@@ -554,64 +500,6 @@ const es = {
|
||||
'errors.error-hit-limit-freemium.heading': 'Estás que ardes',
|
||||
'errors.error-hit-limit-freemium.body':
|
||||
'Has agotado tu cuota de Writefull. Actualiza ahora para obtener sugerencias de lenguaje ilimitadas y soporte en LaTeX, y acceso anticipado a las próximas funciones de generación como TikZ.',
|
||||
'checkout.need-more-info':
|
||||
'¿Necesitas más información? Estamos aquí para ayudar.',
|
||||
'checkout.free-plan-question': '¿Qué incluye el plan gratuito?',
|
||||
'checkout.free-plan-answer':
|
||||
'El plan gratuito ofrece un número limitado de ediciones de lenguaje al día, uso restringido de las funciones de escritura (para parafrasear, cambiar el estilo, explicar o resumir, y más), y acceso limitado a TeXGPT y las opciones de generación de LaTeX. Se te notificará cuando hayas alcanzado tu límite diario. Ten en cuenta que los límites pueden cambiar diariamente para que podamos mantener ciertos niveles de calidad de servicio.',
|
||||
'checkout.premium-plan-question':
|
||||
'¿Obtengo diferentes sugerencias de lenguaje si actualizo a Premium?',
|
||||
'checkout.premium-plan-answer':
|
||||
'Tanto los planes gratuitos como los Premium te permiten elegir el modelo de lenguaje que revisa tu texto: el modelo de Writefull, que es ideal para la escritura de investigación en inglés, o GPT, que funciona con cualquier idioma o tipo de texto. Con el plan gratuito, obtienes un número limitado de sugerencias, pero Premium te da acceso ilimitado. Además, cuando actualizas a Premium, puedes agregar prompts personalizados a GPT, dándote más control sobre cómo se revisa tu texto.',
|
||||
'checkout.custom-prompt-question':
|
||||
"¿Qué significa el 'prompt personalizado para ediciones de lenguaje GPT'?",
|
||||
'checkout.custom-prompt-answer':
|
||||
'Con esta función, puedes dar al modelo GPT instrucciones específicas sobre cómo revisar tu texto. Por ejemplo, puedes pedirle que mantenga ciertos términos sin cambios, que haga tu escritura más asertiva, o que se enfoque solo en correcciones esenciales del lenguaje. ¡Es una excelente manera de adaptar las sugerencias a tus necesidades! Esta opción está disponible con el plan Premium.',
|
||||
'checkout.supercomplete-question': "¿Qué es la función 'Supercomplete'?",
|
||||
'checkout.supercomplete-answer':
|
||||
"La función 'Supercomplete' hace que tu escritura sea aún más eficiente al completar tus oraciones y código LaTeX cuando se le solicita. Esta es una función completamente Premium.",
|
||||
'checkout.upcoming-features-question':
|
||||
'¿Qué otras funciones es probable que vengan?',
|
||||
'checkout.upcoming-features-answer':
|
||||
'¡Tenemos una larga lista de funciones próximas! Dos de estas son la traducción y la generación de diagramas usando TikZ.',
|
||||
'checkout.overleaf-subscription-question':
|
||||
'Ya pago por Overleaf. ¿Aún necesito Writefull Premium?',
|
||||
'checkout.overleaf-subscription-answer':
|
||||
'Sí, Writefull y Overleaf se han integrado, pero son dos servicios separados con sus propias suscripciones.',
|
||||
'checkout.group-discounts-question': '¿Ofrecen descuentos para grupos?',
|
||||
'checkout.group-discounts-answer':
|
||||
'¡Sí! Ve aquí para calcular el precio dependiendo del tamaño de tu grupo. Selecciona un plan e invita a otros a unirse.',
|
||||
'checkout.fair-usage-policy': '* Se aplica la política de uso justo.',
|
||||
'checkout.still-have-questions': '¿Aún tienes preguntas?',
|
||||
'checkout.contact-us': 'Contáctanos',
|
||||
'checkout.monthly': 'Mensual',
|
||||
'checkout.yearly': 'Anual',
|
||||
'checkout.free': 'GRATIS',
|
||||
'checkout.basic-access': 'Acceso básico a Writefull',
|
||||
'checkout.features': 'Características:',
|
||||
'checkout.limited-language-edits': 'Ediciones de lenguaje limitadas',
|
||||
'checkout.limited-writing-features':
|
||||
'Uso limitado de funciones de escritura',
|
||||
'checkout.limited-texgpt': 'Uso limitado de TeXGPT',
|
||||
'checkout.custom-prompt':
|
||||
'Prompt personalizado para sugerencias de lenguaje GPT',
|
||||
'checkout.supercomplete': 'Supercomplete',
|
||||
'checkout.supercomplete-coming': 'Supercomplete (pronto)',
|
||||
'checkout.priority-access':
|
||||
'Acceso prioritario a nuevas funciones de Writefull',
|
||||
'checkout.premium': 'WRITEFULL PREMIUM',
|
||||
'checkout.all-unlocked': 'Todo Writefull desbloqueado',
|
||||
'checkout.unlimited-language-edits': 'Sugerencias de lenguaje ilimitadas*',
|
||||
'checkout.unlimited-writing-features':
|
||||
'Uso ilimitado de funciones de escritura*',
|
||||
'checkout.unlimited-texgpt': 'Uso ilimitado de TeXGPT',
|
||||
'checkout.redirecting': 'Redirigiendo...',
|
||||
'checkout.select-plan': 'Seleccionar plan de Writefull',
|
||||
'checkout.looking-for': 'Buscando',
|
||||
'checkout.group-licenses': 'licencias grupales',
|
||||
'checkout.per-month': 'Por mes',
|
||||
'checkout.your-current-plan': 'Tu plan actual',
|
||||
'checkout.billed-as-one-payment-of': 'facturado como un solo pago de',
|
||||
'toolbar.abstract-generator.name': 'Generar Abstract',
|
||||
'toolbar.title-generator.name': 'Generar Título',
|
||||
'toolbar.create-table.name': 'Crear tablas',
|
||||
|
||||
@@ -64,7 +64,7 @@ const parserReducer = function (maxErrors: number | null) {
|
||||
}
|
||||
}
|
||||
|
||||
type BibLogEntry = {
|
||||
export type BibLogEntry = {
|
||||
file: string
|
||||
level: string
|
||||
message: string
|
||||
|
||||
@@ -19,7 +19,7 @@ export type LatexParserOptions = {
|
||||
ignoreDuplicates?: boolean
|
||||
}
|
||||
|
||||
type LatexLogEntry = {
|
||||
export type LatexLogEntry = {
|
||||
line: string | number | null
|
||||
file: string | undefined
|
||||
level: 'error' | 'warning' | 'typesetting'
|
||||
|
||||
@@ -12,12 +12,24 @@ type OLModalProps = ModalProps & {
|
||||
onHide: () => void
|
||||
}
|
||||
|
||||
export default function OLModal({ children, ...props }: OLModalProps) {
|
||||
type OLModalHeaderProps = ModalHeaderProps & {
|
||||
closeButton?: boolean
|
||||
}
|
||||
|
||||
export function OLModal({ children, ...props }: OLModalProps) {
|
||||
return <Modal {...props}>{children}</Modal>
|
||||
}
|
||||
|
||||
export function OLModalHeader({ children, ...props }: ModalHeaderProps) {
|
||||
return <Modal.Header {...props}>{children}</Modal.Header>
|
||||
export function OLModalHeader({
|
||||
children,
|
||||
closeButton = true,
|
||||
...props
|
||||
}: OLModalHeaderProps) {
|
||||
return (
|
||||
<Modal.Header closeButton={closeButton} {...props}>
|
||||
{children}
|
||||
</Modal.Header>
|
||||
)
|
||||
}
|
||||
|
||||
export function OLModalTitle({ children, ...props }: ModalTitleProps) {
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
buildRuleDeltas,
|
||||
handleLogFiles,
|
||||
handleOutputFiles,
|
||||
} from '../../features/pdf-preview/util/output-files'
|
||||
} from '@/features/pdf-preview/util/output-files'
|
||||
import { useProjectContext } from './project-context'
|
||||
import { useEditorContext } from './editor-context'
|
||||
import { buildFileList } from '../../features/pdf-preview/util/file-list'
|
||||
@@ -81,7 +81,7 @@ export type CompileContext = {
|
||||
logEntryAnnotations?: Record<string, Annotation[]>
|
||||
outputFilesArchive?: string
|
||||
pdfDownloadUrl?: string
|
||||
pdfFile?: PdfFile
|
||||
pdfFile?: PdfFile | null
|
||||
pdfUrl?: string
|
||||
pdfViewer?: string
|
||||
position?: PdfScrollPosition
|
||||
@@ -167,7 +167,7 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
const { pdfViewer, syntaxValidation } = userSettings
|
||||
|
||||
// low level details for metrics
|
||||
const [pdfFile, setPdfFile] = useState<PdfFile | undefined>()
|
||||
const [pdfFile, setPdfFile] = useState<PdfFile | null | undefined>()
|
||||
|
||||
// the project is considered to be "uncompiled" if a doc has changed, or finished saving, since the last compile started.
|
||||
const [uncompiled, setUncompiled] = useState(false)
|
||||
@@ -296,7 +296,7 @@ export const LocalCompileProvider: FC<React.PropsWithChildren> = ({
|
||||
}, [compiling])
|
||||
|
||||
const _buildLogEntryAnnotations = useCallback(
|
||||
(entries: any) =>
|
||||
(entries: LogEntry[]) =>
|
||||
buildLogEntryAnnotations(entries, fileTreeData, lastCompileRootDocId),
|
||||
[fileTreeData, lastCompileRootDocId]
|
||||
)
|
||||
|
||||
@@ -5,33 +5,11 @@ export interface WritefullEvents {
|
||||
}
|
||||
'writefull-received-suggestions': { numberOfSuggestions: number }
|
||||
'writefull-register-as-auto-account': { email: string }
|
||||
'writefull-shared-analytics': { eventName: string; segmentation: object }
|
||||
'writefull-ai-assist-show-paywall': { origin?: string }
|
||||
}
|
||||
|
||||
type InsertPosition = {
|
||||
parentSelector: string
|
||||
insertBeforeSelector?: string
|
||||
}
|
||||
|
||||
export interface WritefullAPI {
|
||||
init({
|
||||
toolbarPosition,
|
||||
iconPosition,
|
||||
hasAgreedToTOS,
|
||||
overleafUserId,
|
||||
overleafLabels,
|
||||
}: {
|
||||
toolbarPosition: InsertPosition
|
||||
iconPosition: InsertPosition
|
||||
hasAgreedToTOS: boolean
|
||||
overleafUserId: string
|
||||
overleafLabels: {
|
||||
autoImport: boolean
|
||||
autoCreatedAccount: boolean
|
||||
splitTests: Record<string, boolean>
|
||||
}
|
||||
}): Promise<void>
|
||||
init(): Promise<void>
|
||||
addEventListener<eventName extends keyof WritefullEvents>(
|
||||
name: eventName,
|
||||
callback: (detail: WritefullEvents[eventName]) => void
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import LoadingSpinner, {
|
||||
FullSizeLoadingSpinner,
|
||||
} from '@/shared/components/loading-spinner'
|
||||
|
||||
type Story = StoryObj<typeof LoadingSpinner>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
loadingText: 'Loading content...',
|
||||
},
|
||||
}
|
||||
|
||||
export const WithDelay: Story = {
|
||||
args: {
|
||||
delay: 500,
|
||||
loadingText: 'This will appear after a 500ms delay...',
|
||||
},
|
||||
}
|
||||
|
||||
export const FullSize: StoryObj<typeof FullSizeLoadingSpinner> = {
|
||||
render: args => <FullSizeLoadingSpinner {...args} />,
|
||||
args: {
|
||||
loadingText: 'Loading entire section...',
|
||||
size: 'sm',
|
||||
},
|
||||
}
|
||||
|
||||
const meta: Meta<typeof LoadingSpinner> = {
|
||||
title: 'Shared / Components / Loading Spinner',
|
||||
component: LoadingSpinner,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
argTypes: {
|
||||
delay: {
|
||||
control: 'select',
|
||||
options: [0, 500],
|
||||
},
|
||||
size: {
|
||||
control: 'radio',
|
||||
options: ['lg', 'sm'],
|
||||
},
|
||||
},
|
||||
args: {
|
||||
size: 'sm',
|
||||
delay: 0,
|
||||
},
|
||||
render: args => <LoadingSpinner {...args} />,
|
||||
}
|
||||
|
||||
export default meta
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
|
||||
import OLModal, {
|
||||
import { figmaDesignUrl } from './../../../.storybook/utils/figma-design-url'
|
||||
import {
|
||||
OLModal,
|
||||
OLModalHeader,
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
@@ -99,7 +100,7 @@ const meta: Meta<typeof OLModal> = {
|
||||
},
|
||||
render: ({ title, children, footer, ...args }) => (
|
||||
<OLModal {...args}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>{children}</OLModalBody>
|
||||
|
||||
@@ -1624,7 +1624,9 @@
|
||||
"payment_error_3ds_failed": "We couldn’t complete your payment because authentication wasn’t successful. Please try again or choose a different payment method. If the problem continues please <0>contact us</0>.",
|
||||
"payment_error_generic": "Sorry, something went wrong. Please try again. If the problem continues please <0>contact us</0>.",
|
||||
"payment_error_intermittent_error": "We were unable to process your payment. Please try again later or <0>contact us</0> for assistance.",
|
||||
"payment_error_invalid_payment_method": "We couldn’t process your payment because your payment details appear to be invalid. Please check the information you entered and try again. If the problem continues, please try a different payment method or <0>contact us</0>.",
|
||||
"payment_error_update_payment_method": "Your payment was declined. Please <0>update your billing information</0> and try again.",
|
||||
"payment_error_update_payment_method_checkout": "Your payment was declined. Please update your billing information and try again.",
|
||||
"payment_method_accepted": "__paymentMethod__ accepted",
|
||||
"payment_provider_unreachable_error": "Sorry, there was an error talking to our payment provider. Please try again in a few moments.\nIf you are using any ad or script blocking extensions in your browser, you may need to temporarily disable them.",
|
||||
"payment_summary": "Payment summary",
|
||||
@@ -2274,6 +2276,7 @@
|
||||
"sync_with_a_github_repository": "Sync with a GitHub repository.",
|
||||
"synctex_error_recompile_and_try_again": "That didn’t work. Recompile and try again.",
|
||||
"synctex_failed": "Couldn’t find the corresponding source file",
|
||||
"syntax_checks": "Syntax checks",
|
||||
"syntax_validation": "Code check",
|
||||
"tab_connecting": "Connecting with the editor",
|
||||
"tab_no_longer_connected": "This tab is no longer connected with the editor",
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||
"@contentful/rich-text-types": "^16.0.2",
|
||||
"@google-cloud/bigquery": "^6.0.1",
|
||||
"@google-cloud/storage": "^6.10.1",
|
||||
"@node-oauth/oauth2-server": "^5.1.0",
|
||||
"@node-saml/passport-saml": "^5.1.0",
|
||||
"@overleaf/access-token-encryptor": "*",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user