mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
[web] Show confirmation modal when reverting a file (#18105)
* [web] Show confirmation modal when reverting a file * only show Revert file in ui even if deleted * format:fix * using the same message for every revert * replace "document" with "file" in confirm dialog * remove "pull-left" class * fix split test name GitOrigin-RevId: ab5937b9a0570cd1fdbe5d71eda0a16ae539dc66
This commit is contained in:
parent
373b656e75
commit
becef5f236
7 changed files with 117 additions and 53 deletions
|
@ -1049,6 +1049,7 @@
|
||||||
"resize": "",
|
"resize": "",
|
||||||
"resolve": "",
|
"resolve": "",
|
||||||
"resolved_comments": "",
|
"resolved_comments": "",
|
||||||
|
"restore": "",
|
||||||
"restore_file": "",
|
"restore_file": "",
|
||||||
"restoring": "",
|
"restoring": "",
|
||||||
"resync_completed": "",
|
"resync_completed": "",
|
||||||
|
@ -1057,6 +1058,8 @@
|
||||||
"retry_test": "",
|
"retry_test": "",
|
||||||
"reverse_x_sort_order": "",
|
"reverse_x_sort_order": "",
|
||||||
"revert_file": "",
|
"revert_file": "",
|
||||||
|
"revert_file_confirmation_message": "",
|
||||||
|
"revert_file_confirmation_title": "",
|
||||||
"revert_file_error_message": "",
|
"revert_file_error_message": "",
|
||||||
"revert_file_error_title": "",
|
"revert_file_error_title": "",
|
||||||
"revert_pending_plan_change": "",
|
"revert_pending_plan_change": "",
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { formatTime } from '@/features/utils/format-date'
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
import { Button, Modal } from 'react-bootstrap'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
type RevertFileConfirmModalProps = {
|
||||||
|
show: boolean
|
||||||
|
timestamp: number
|
||||||
|
onConfirm: () => void
|
||||||
|
onHide: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RevertFileConfirmModal({
|
||||||
|
show,
|
||||||
|
timestamp,
|
||||||
|
onConfirm,
|
||||||
|
onHide,
|
||||||
|
}: RevertFileConfirmModalProps) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const date = useMemo(() => formatTime(timestamp, 'Do MMMM'), [timestamp])
|
||||||
|
const time = useMemo(() => formatTime(timestamp, 'h:mm a'), [timestamp])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal show={show} onHide={onHide}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>{t('revert_file_confirmation_title')}</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
{t('revert_file_confirmation_message', { date, time })}
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button bsStyle={null} className="btn-secondary" onClick={onHide}>
|
||||||
|
{t('cancel')}
|
||||||
|
</Button>
|
||||||
|
<Button bsStyle={null} className="btn-primary" onClick={onConfirm}>
|
||||||
|
{t('restore')}
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Button, Modal } from 'react-bootstrap'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
export function RevertFileErrorModal({
|
||||||
|
resetErrorBoundary,
|
||||||
|
}: {
|
||||||
|
resetErrorBoundary: VoidFunction
|
||||||
|
}) {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal show onHide={resetErrorBoundary}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>{t('revert_file_error_title')}</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>{t('revert_file_error_message')}</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button
|
||||||
|
bsStyle={null}
|
||||||
|
className="btn-secondary"
|
||||||
|
onClick={resetErrorBoundary}
|
||||||
|
>
|
||||||
|
{t('close')}
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
import { Button, Modal } from 'react-bootstrap'
|
import { Button } from 'react-bootstrap'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import type { HistoryContextValue } from '../../../context/types/history-context-value'
|
import type { HistoryContextValue } from '../../../context/types/history-context-value'
|
||||||
import { useRevertSelectedFile } from '@/features/history/context/hooks/use-revert-selected-file'
|
import { useRevertSelectedFile } from '@/features/history/context/hooks/use-revert-selected-file'
|
||||||
import withErrorBoundary from '@/infrastructure/error-boundary'
|
import withErrorBoundary from '@/infrastructure/error-boundary'
|
||||||
|
import { RevertFileConfirmModal } from '../modals/revert-file-confirm-modal'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { RevertFileErrorModal } from '../modals/revert-file-error-modal'
|
||||||
|
|
||||||
type ToolbarRevertingFileButtonProps = {
|
type ToolbarRevertingFileButtonProps = {
|
||||||
selection: HistoryContextValue['selection']
|
selection: HistoryContextValue['selection']
|
||||||
|
@ -13,47 +16,34 @@ function ToolbarRevertFileButton({
|
||||||
}: ToolbarRevertingFileButtonProps) {
|
}: ToolbarRevertingFileButtonProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { revertSelectedFile, isLoading } = useRevertSelectedFile()
|
const { revertSelectedFile, isLoading } = useRevertSelectedFile()
|
||||||
|
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
||||||
|
|
||||||
|
if (!selection.updateRange || !selection.selectedFile) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<RevertFileConfirmModal
|
||||||
|
show={showConfirmModal}
|
||||||
|
timestamp={selection.updateRange.toVTimestamp}
|
||||||
|
onConfirm={() => {
|
||||||
|
setShowConfirmModal(false)
|
||||||
|
revertSelectedFile(selection)
|
||||||
|
}}
|
||||||
|
onHide={() => setShowConfirmModal(false)}
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
className="btn-secondary history-react-toolbar-revert-file-button"
|
className="btn-secondary history-react-toolbar-revert-file-button"
|
||||||
bsSize="xs"
|
bsSize="xs"
|
||||||
bsStyle={null}
|
bsStyle={null}
|
||||||
onClick={() => revertSelectedFile(selection)}
|
onClick={() => setShowConfirmModal(true)}
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
>
|
>
|
||||||
{isLoading ? `${t('reverting')}…` : t('revert_file')}
|
{isLoading ? `${t('reverting')}…` : t('revert_file')}
|
||||||
</Button>
|
</Button>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarRevertErrorModal({
|
export default withErrorBoundary(ToolbarRevertFileButton, RevertFileErrorModal)
|
||||||
resetErrorBoundary,
|
|
||||||
}: {
|
|
||||||
resetErrorBoundary: VoidFunction
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal show onHide={resetErrorBoundary}>
|
|
||||||
<Modal.Header closeButton>
|
|
||||||
<Modal.Title>{t('revert_file_error_title')}</Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body>{t('revert_file_error_message')}</Modal.Body>
|
|
||||||
<Modal.Footer>
|
|
||||||
<Button
|
|
||||||
bsStyle={null}
|
|
||||||
className="btn-secondary pull-left"
|
|
||||||
onClick={resetErrorBoundary}
|
|
||||||
>
|
|
||||||
{t('close')}
|
|
||||||
</Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withErrorBoundary(
|
|
||||||
ToolbarRevertFileButton,
|
|
||||||
ToolbarRevertErrorModal
|
|
||||||
)
|
|
||||||
|
|
|
@ -14,15 +14,14 @@ type ToolbarProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Toolbar({ diff, selection }: ToolbarProps) {
|
export default function Toolbar({ diff, selection }: ToolbarProps) {
|
||||||
const hasRevertFiles = useFeatureFlag('revert-files')
|
const hasRevertFile = useFeatureFlag('revert-file')
|
||||||
|
|
||||||
|
const showRevertFileButton = hasRevertFile && selection.selectedFile
|
||||||
|
|
||||||
const showRestoreFileButton =
|
const showRestoreFileButton =
|
||||||
selection.selectedFile && isFileRemoved(selection.selectedFile)
|
|
||||||
|
|
||||||
const showRevertFileButton =
|
|
||||||
hasRevertFiles &&
|
|
||||||
selection.selectedFile &&
|
selection.selectedFile &&
|
||||||
!isFileRemoved(selection.selectedFile)
|
isFileRemoved(selection.selectedFile) &&
|
||||||
|
!showRevertFileButton
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="history-react-toolbar">
|
<div className="history-react-toolbar">
|
||||||
|
|
|
@ -75,14 +75,15 @@ export function useRevertSelectedFile() {
|
||||||
(selection: HistoryContextValue['selection']) => {
|
(selection: HistoryContextValue['selection']) => {
|
||||||
const { selectedFile, files } = selection
|
const { selectedFile, files } = selection
|
||||||
|
|
||||||
if (
|
if (selectedFile && selectedFile.pathname) {
|
||||||
selectedFile &&
|
|
||||||
selectedFile.pathname &&
|
|
||||||
!isFileRemoved(selectedFile)
|
|
||||||
) {
|
|
||||||
const file = files.find(file => file.pathname === selectedFile.pathname)
|
const file = files.find(file => file.pathname === selectedFile.pathname)
|
||||||
const toVersion = selection.updateRange?.toV
|
|
||||||
if (file && !isFileRemoved(file) && toVersion) {
|
if (file) {
|
||||||
|
const deletedAtV = isFileRemoved(file) ? file.deletedAtV : undefined
|
||||||
|
const toVersion = deletedAtV ?? selection.updateRange?.toV
|
||||||
|
if (!toVersion) {
|
||||||
|
return
|
||||||
|
}
|
||||||
setState('reverting')
|
setState('reverting')
|
||||||
|
|
||||||
revertFile(projectId, file.pathname, toVersion).then(
|
revertFile(projectId, file.pathname, toVersion).then(
|
||||||
|
|
|
@ -1549,6 +1549,8 @@
|
||||||
"return_to_login_page": "Return to Login page",
|
"return_to_login_page": "Return to Login page",
|
||||||
"reverse_x_sort_order": "Reverse __x__ sort order",
|
"reverse_x_sort_order": "Reverse __x__ sort order",
|
||||||
"revert_file": "Revert file",
|
"revert_file": "Revert file",
|
||||||
|
"revert_file_confirmation_message": "Your current file will revert to the version from __date__ at __time__.",
|
||||||
|
"revert_file_confirmation_title": "Restore this version?",
|
||||||
"revert_file_error_message": "There was a problem reverting the file version. Please try again in a few moments. If the problem continues please contact us.",
|
"revert_file_error_message": "There was a problem reverting the file version. Please try again in a few moments. If the problem continues please contact us.",
|
||||||
"revert_file_error_title": "Revert File Error",
|
"revert_file_error_title": "Revert File Error",
|
||||||
"revert_pending_plan_change": "Revert scheduled plan change",
|
"revert_pending_plan_change": "Revert scheduled plan change",
|
||||||
|
|
Loading…
Reference in a new issue