diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 1e46f737ea..4a0b614fa3 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -1049,6 +1049,7 @@ "resize": "", "resolve": "", "resolved_comments": "", + "restore": "", "restore_file": "", "restoring": "", "resync_completed": "", @@ -1057,6 +1058,8 @@ "retry_test": "", "reverse_x_sort_order": "", "revert_file": "", + "revert_file_confirmation_message": "", + "revert_file_confirmation_title": "", "revert_file_error_message": "", "revert_file_error_title": "", "revert_pending_plan_change": "", diff --git a/services/web/frontend/js/features/history/components/diff-view/modals/revert-file-confirm-modal.tsx b/services/web/frontend/js/features/history/components/diff-view/modals/revert-file-confirm-modal.tsx new file mode 100644 index 0000000000..778e9d02b8 --- /dev/null +++ b/services/web/frontend/js/features/history/components/diff-view/modals/revert-file-confirm-modal.tsx @@ -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 ( + + + {t('revert_file_confirmation_title')} + + + {t('revert_file_confirmation_message', { date, time })} + + + + + + + ) +} diff --git a/services/web/frontend/js/features/history/components/diff-view/modals/revert-file-error-modal.tsx b/services/web/frontend/js/features/history/components/diff-view/modals/revert-file-error-modal.tsx new file mode 100644 index 0000000000..1fc7b24a38 --- /dev/null +++ b/services/web/frontend/js/features/history/components/diff-view/modals/revert-file-error-modal.tsx @@ -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 ( + + + {t('revert_file_error_title')} + + {t('revert_file_error_message')} + + + + + ) +} diff --git a/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-revert-file-button.tsx b/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-revert-file-button.tsx index 39a542b5ce..78fbd91430 100644 --- a/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-revert-file-button.tsx +++ b/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-revert-file-button.tsx @@ -1,8 +1,11 @@ -import { Button, Modal } from 'react-bootstrap' +import { Button } from 'react-bootstrap' import { useTranslation } from 'react-i18next' import type { HistoryContextValue } from '../../../context/types/history-context-value' import { useRevertSelectedFile } from '@/features/history/context/hooks/use-revert-selected-file' 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 = { selection: HistoryContextValue['selection'] @@ -13,47 +16,34 @@ function ToolbarRevertFileButton({ }: ToolbarRevertingFileButtonProps) { const { t } = useTranslation() const { revertSelectedFile, isLoading } = useRevertSelectedFile() + const [showConfirmModal, setShowConfirmModal] = useState(false) + + if (!selection.updateRange || !selection.selectedFile) { + return null + } return ( - + <> + { + setShowConfirmModal(false) + revertSelectedFile(selection) + }} + onHide={() => setShowConfirmModal(false)} + /> + + ) } -function ToolbarRevertErrorModal({ - resetErrorBoundary, -}: { - resetErrorBoundary: VoidFunction -}) { - const { t } = useTranslation() - - return ( - - - {t('revert_file_error_title')} - - {t('revert_file_error_message')} - - - - - ) -} - -export default withErrorBoundary( - ToolbarRevertFileButton, - ToolbarRevertErrorModal -) +export default withErrorBoundary(ToolbarRevertFileButton, RevertFileErrorModal) diff --git a/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar.tsx b/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar.tsx index 261608b863..92cbbe565e 100644 --- a/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar.tsx +++ b/services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar.tsx @@ -14,15 +14,14 @@ type 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 = - selection.selectedFile && isFileRemoved(selection.selectedFile) - - const showRevertFileButton = - hasRevertFiles && selection.selectedFile && - !isFileRemoved(selection.selectedFile) + isFileRemoved(selection.selectedFile) && + !showRevertFileButton return (
diff --git a/services/web/frontend/js/features/history/context/hooks/use-revert-selected-file.ts b/services/web/frontend/js/features/history/context/hooks/use-revert-selected-file.ts index d6bd2d5992..545819a14f 100644 --- a/services/web/frontend/js/features/history/context/hooks/use-revert-selected-file.ts +++ b/services/web/frontend/js/features/history/context/hooks/use-revert-selected-file.ts @@ -75,14 +75,15 @@ export function useRevertSelectedFile() { (selection: HistoryContextValue['selection']) => { const { selectedFile, files } = selection - if ( - selectedFile && - selectedFile.pathname && - !isFileRemoved(selectedFile) - ) { + if (selectedFile && 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') revertFile(projectId, file.pathname, toVersion).then( diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 3bdca2e0d5..fa9fb173b6 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -1549,6 +1549,8 @@ "return_to_login_page": "Return to Login page", "reverse_x_sort_order": "Reverse __x__ sort order", "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_title": "Revert File Error", "revert_pending_plan_change": "Revert scheduled plan change",