first commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
import { useConnectionContext } from '@/features/ide-react/context/connection-context'
|
||||
import OLModal, {
|
||||
OLModalBody,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
} from '@/features/ui/components/ol/ol-modal'
|
||||
|
||||
// show modal when editor is forcefully disconnected
|
||||
function ForceDisconnected() {
|
||||
const { connectionState } = useConnectionContext()
|
||||
const { t } = useTranslation()
|
||||
const [secondsUntilRefresh, setSecondsUntilRefresh] = useState(0)
|
||||
const [show, setShow] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
connectionState.forceDisconnected &&
|
||||
// out of sync has its own modal
|
||||
connectionState.error !== 'out-of-sync'
|
||||
) {
|
||||
setShow(true)
|
||||
}
|
||||
}, [connectionState.forceDisconnected, connectionState.error])
|
||||
|
||||
useEffect(() => {
|
||||
if (connectionState.forceDisconnected) {
|
||||
setSecondsUntilRefresh(connectionState.forcedDisconnectDelay)
|
||||
}
|
||||
}, [connectionState.forceDisconnected, connectionState.forcedDisconnectDelay])
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
const timer = window.setInterval(() => {
|
||||
setSecondsUntilRefresh(seconds => Math.max(0, seconds - 1))
|
||||
}, 1000)
|
||||
|
||||
return () => {
|
||||
window.clearInterval(timer)
|
||||
}
|
||||
}
|
||||
}, [show])
|
||||
|
||||
if (!show) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<OLModal
|
||||
show
|
||||
// It's not possible to hide this modal, but it's a required prop
|
||||
onHide={() => {}}
|
||||
className="lock-editor-modal"
|
||||
backdrop={false}
|
||||
keyboard={false}
|
||||
>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('please_wait')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
{t('were_performing_maintenance', { seconds: secondsUntilRefresh })}
|
||||
</OLModalBody>
|
||||
</OLModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(ForceDisconnected)
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
import OLModal, {
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
} from '@/features/ui/components/ol/ol-modal'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import { ButtonProps } from '@/features/ui/components/types/button-props'
|
||||
|
||||
export type GenericConfirmModalOwnProps = {
|
||||
title: string
|
||||
message: string
|
||||
onConfirm: () => void
|
||||
confirmLabel?: string
|
||||
primaryVariant?: ButtonProps['variant']
|
||||
}
|
||||
|
||||
type GenericConfirmModalProps = React.ComponentProps<typeof OLModal> &
|
||||
GenericConfirmModalOwnProps
|
||||
|
||||
function GenericConfirmModal({
|
||||
title,
|
||||
message,
|
||||
confirmLabel,
|
||||
primaryVariant = 'primary',
|
||||
...modalProps
|
||||
}: GenericConfirmModalProps) {
|
||||
const { t } = useTranslation()
|
||||
const handleConfirmClick = modalProps.onConfirm
|
||||
|
||||
return (
|
||||
<OLModal {...modalProps}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
<OLModalBody className="modal-generic-confirm">{message}</OLModalBody>
|
||||
|
||||
<OLModalFooter>
|
||||
<OLButton variant="secondary" onClick={() => modalProps.onHide()}>
|
||||
{t('cancel')}
|
||||
</OLButton>
|
||||
<OLButton variant={primaryVariant} onClick={handleConfirmClick}>
|
||||
{confirmLabel || t('ok')}
|
||||
</OLButton>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(GenericConfirmModal)
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
import OLModal, {
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
} from '@/features/ui/components/ol/ol-modal'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
|
||||
export type GenericMessageModalOwnProps = {
|
||||
title: string
|
||||
message: string
|
||||
}
|
||||
|
||||
type GenericMessageModalProps = React.ComponentProps<typeof OLModal> &
|
||||
GenericMessageModalOwnProps
|
||||
|
||||
function GenericMessageModal({
|
||||
title,
|
||||
message,
|
||||
...modalProps
|
||||
}: GenericMessageModalProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<OLModal {...modalProps}>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
|
||||
<OLModalBody className="modal-body-share">{message}</OLModalBody>
|
||||
|
||||
<OLModalFooter>
|
||||
<OLButton variant="secondary" onClick={() => modalProps.onHide()}>
|
||||
{t('ok')}
|
||||
</OLButton>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(GenericMessageModal)
|
||||
@@ -0,0 +1,17 @@
|
||||
import { memo } from 'react'
|
||||
import ForceDisconnected from '@/features/ide-react/components/modals/force-disconnected'
|
||||
import { UnsavedDocs } from '@/features/ide-react/components/unsaved-docs/unsaved-docs'
|
||||
import SystemMessages from '@/shared/components/system-messages'
|
||||
import { IdeRedesignSwitcherModal } from '@/features/ide-redesign/components/switcher-modal/modal'
|
||||
|
||||
export const Modals = memo(() => {
|
||||
return (
|
||||
<>
|
||||
<ForceDisconnected />
|
||||
<UnsavedDocs />
|
||||
<SystemMessages />
|
||||
<IdeRedesignSwitcherModal />
|
||||
</>
|
||||
)
|
||||
})
|
||||
Modals.displayName = 'Modals'
|
||||
@@ -0,0 +1,86 @@
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { memo, useState } from 'react'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import OLModal, {
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
} from '@/features/ui/components/ol/ol-modal'
|
||||
|
||||
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 (
|
||||
<OLModal
|
||||
show={show}
|
||||
onHide={done}
|
||||
className="out-of-sync-modal"
|
||||
backdrop={false}
|
||||
keyboard={false}
|
||||
>
|
||||
<OLModalHeader closeButton>
|
||||
<OLModalTitle>{t('out_of_sync')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody 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"
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
</OLModalBody>
|
||||
<OLModalBody>
|
||||
<OLButton
|
||||
variant="secondary"
|
||||
onClick={() => setEditorContentShown(shown => !shown)}
|
||||
>
|
||||
{editorContentShown
|
||||
? t('hide_local_file_contents')
|
||||
: t('show_local_file_contents')}
|
||||
</OLButton>
|
||||
{editorContentShown ? (
|
||||
<div className="text-preview">
|
||||
<textarea
|
||||
className="scroll-container"
|
||||
readOnly
|
||||
rows={editorContentRows}
|
||||
value={editorContent}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<OLButton variant="secondary" onClick={done}>
|
||||
{t('reload_editor')}
|
||||
</OLButton>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(OutOfSyncModal)
|
||||
Reference in New Issue
Block a user