فهرست منبع

[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
Domagoj Kriskovic 2 سال پیش
والد
کامیت
becef5f236

+ 3 - 0
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": "",

+ 41 - 0
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 (
+    <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>
+  )
+}

+ 28 - 0
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 (
+    <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>
+  )
+}

+ 29 - 39
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)
 
-  return (
-    <Button
-      className="btn-secondary history-react-toolbar-revert-file-button"
-      bsSize="xs"
-      bsStyle={null}
-      onClick={() => revertSelectedFile(selection)}
-      disabled={isLoading}
-    >
-      {isLoading ? `${t('reverting')}…` : t('revert_file')}
-    </Button>
-  )
-}
-
-function ToolbarRevertErrorModal({
-  resetErrorBoundary,
-}: {
-  resetErrorBoundary: VoidFunction
-}) {
-  const { t } = useTranslation()
+  if (!selection.updateRange || !selection.selectedFile) {
+    return null
+  }
 
   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>
+    <>
+      <RevertFileConfirmModal
+        show={showConfirmModal}
+        timestamp={selection.updateRange.toVTimestamp}
+        onConfirm={() => {
+          setShowConfirmModal(false)
+          revertSelectedFile(selection)
+        }}
+        onHide={() => setShowConfirmModal(false)}
+      />
+      <Button
+        className="btn-secondary history-react-toolbar-revert-file-button"
+        bsSize="xs"
+        bsStyle={null}
+        onClick={() => setShowConfirmModal(true)}
+        disabled={isLoading}
+      >
+        {isLoading ? `${t('reverting')}…` : t('revert_file')}
+      </Button>
+    </>
   )
 }
 
-export default withErrorBoundary(
-  ToolbarRevertFileButton,
-  ToolbarRevertErrorModal
-)
+export default withErrorBoundary(ToolbarRevertFileButton, RevertFileErrorModal)

+ 5 - 6
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 showRestoreFileButton =
-    selection.selectedFile && isFileRemoved(selection.selectedFile)
+  const showRevertFileButton = hasRevertFile && selection.selectedFile
 
-  const showRevertFileButton =
-    hasRevertFiles &&
+  const showRestoreFileButton =
     selection.selectedFile &&
-    !isFileRemoved(selection.selectedFile)
+    isFileRemoved(selection.selectedFile) &&
+    !showRevertFileButton
 
   return (
     <div className="history-react-toolbar">

+ 8 - 7
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(

+ 2 - 0
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",