Merge pull request #15592 from overleaf/td-ide-page-more-modals

React IDE page: add out-of-sync modal and project deleted modal

GitOrigin-RevId: 6081a40c3009e8ebc5b3f9752c4059af3d52966d
This commit is contained in:
Tim Down
2023-11-07 09:04:44 +00:00
committed by Copybot
parent ecf7befe88
commit c3afce73c1
13 changed files with 257 additions and 25 deletions
@@ -21,7 +21,7 @@ export function Alerts() {
return (
<div className="global-alerts">
{connectionState.forceDisconnected ? (
<Alert bsStyle="warning" className="small">
<Alert bsStyle="danger" className="small">
<strong>{t('disconnected')}</strong>
</Alert>
) : null}
@@ -10,6 +10,7 @@ import EditorNavigationToolbar from '@/features/ide-react/components/editor-navi
import ChatPane from '@/features/chat/components/chat-pane'
import { useLayoutEventTracking } from '@/features/ide-react/hooks/use-layout-event-tracking'
import useSocketListeners from '@/features/ide-react/hooks/use-socket-listeners'
import { useModalsContext } from '@/features/ide-react/context/modals-context'
import { useOpenFile } from '@/features/ide-react/hooks/use-open-file'
// This is filled with placeholder content while the real content is migrated
@@ -25,7 +26,19 @@ export default function IdePage() {
useOpenFile()
const [leftColumnDefaultSize, setLeftColumnDefaultSize] = useState(20)
const { registerUserActivity } = useConnectionContext()
const { connectionState, registerUserActivity } = useConnectionContext()
const { showLockEditorMessageModal } = useModalsContext()
// Show modal when editor is forcefully disconnected
useEffect(() => {
if (connectionState.forceDisconnected) {
showLockEditorMessageModal(connectionState.forcedDisconnectDelay)
}
}, [
connectionState.forceDisconnected,
connectionState.forcedDisconnectDelay,
showLockEditorMessageModal,
])
// Inform the connection manager when the user is active
const listener = useCallback(
@@ -0,0 +1,48 @@
import { useTranslation } from 'react-i18next'
import { Modal } from 'react-bootstrap'
import AccessibleModal from '@/shared/components/accessible-modal'
import { useEffect, useState } from 'react'
export type LockEditorMessageModalProps = {
delay: number // In seconds
show: boolean
}
function LockEditorMessageModal({ delay, show }: LockEditorMessageModalProps) {
const { t } = useTranslation()
const [secondsUntilRefresh, setSecondsUntilRefresh] = useState(0)
useEffect(() => {
if (show) {
setSecondsUntilRefresh(delay)
const timer = window.setInterval(() => {
setSecondsUntilRefresh(seconds => Math.max(0, seconds - 1))
}, 1000)
return () => {
window.clearInterval(timer)
}
}
}, [show, delay])
return (
<AccessibleModal
show={show}
// It's not possible to hide this modal, but it's a required prop
onHide={() => {}}
className="lock-editor-modal"
backdrop={false}
keyboard={false}
>
<Modal.Header>
<Modal.Title>{t('please_wait')}</Modal.Title>
</Modal.Header>
<Modal.Body>
{t('were_performing_maintenance', { seconds: secondsUntilRefresh })}
</Modal.Body>
</AccessibleModal>
)
}
export default LockEditorMessageModal
@@ -0,0 +1,81 @@
import { Trans, useTranslation } from 'react-i18next'
import { Button, Modal } from 'react-bootstrap'
import AccessibleModal from '@/shared/components/accessible-modal'
import { useState } from 'react'
import { useLocation } from '@/shared/hooks/use-location'
export type OutOfSyncModalProps = {
editorContent: string
show: boolean
onHide: () => void
}
function OutOfSyncModal({ editorContent, show, onHide }: OutOfSyncModalProps) {
const { t } = useTranslation()
const location = useLocation()
const [editorContentShown, setEditorContentShown] = useState(false)
const editorContentRows = (editorContent.match(/\n/g)?.length || 0) + 1
// Reload the page to avoid staying in an inconsistent state.
// https://github.com/overleaf/issues/issues/3694
function done() {
onHide()
location.reload()
}
return (
<AccessibleModal
show={show}
onHide={done}
className="out-of-sync-modal"
backdrop={false}
keyboard={false}
>
<Modal.Header closeButton>
<Modal.Title>{t('out_of_sync')}</Modal.Title>
</Modal.Header>
<Modal.Body className="modal-body-share">
<Trans
i18nKey="out_of_sync_detail"
components={[
// eslint-disable-next-line react/jsx-key
<br />,
// eslint-disable-next-line jsx-a11y/anchor-has-content,react/jsx-key
<a
target="_blank"
rel="noopener noreferrer"
href="/learn/Kb/Editor_out_of_sync_problems"
/>,
]}
/>
</Modal.Body>
<Modal.Body>
<Button
bsStyle="info"
onClick={() => setEditorContentShown(shown => !shown)}
>
{editorContentShown
? t('hide_local_file_contents')
: t('show_local_file_contents')}
</Button>
{editorContentShown ? (
<div className="text-preview">
<textarea
className="scroll-container"
readOnly
rows={editorContentRows}
value={editorContent}
/>
</div>
) : null}
</Modal.Body>
<Modal.Footer>
<Button bsStyle="info" onClick={done}>
{t('reload_editor')}
</Button>
</Modal.Footer>
</AccessibleModal>
)
}
export default OutOfSyncModal