Просмотр исходного кода

Merge pull request #21208 from overleaf/dp-accept-reject-all-changes

Add options to accept/reject all changes to review tooltip

GitOrigin-RevId: 1cea76926d59d0354c8abaa6ba69b7e99c02fbe0
David 1 год назад
Родитель
Сommit
1c5f5950fa

+ 1 - 1
services/web/frontend/js/features/review-panel-new/components/review-panel-add-comment.tsx

@@ -6,7 +6,7 @@ import {
 import { EditorSelection } from '@codemirror/state'
 import { useTranslation } from 'react-i18next'
 import { useThreadsActionsContext } from '../context/threads-context'
-import { removeNewCommentRangeEffect } from '@/features/source-editor/extensions/add-comment'
+import { removeNewCommentRangeEffect } from '@/features/source-editor/extensions/review-tooltip'
 import useSubmittableTextInput from '../hooks/use-submittable-text-input'
 import AutoExpandingTextArea from '@/shared/components/auto-expanding-text-area'
 import { ReviewPanelEntry } from './review-panel-entry'

+ 5 - 2
services/web/frontend/js/features/review-panel-new/components/review-panel-current-file.tsx

@@ -28,7 +28,7 @@ import { canAggregate } from '../utils/can-aggregate'
 import ReviewPanelEmptyState from './review-panel-empty-state'
 import useEventListener from '@/shared/hooks/use-event-listener'
 import { hasActiveRange } from '@/features/review-panel-new/utils/has-active-range'
-import { addCommentStateField } from '@/features/source-editor/extensions/add-comment'
+import { reviewTooltipStateField } from '@/features/source-editor/extensions/review-tooltip'
 import ReviewPanelMoreCommentsButton from './review-panel-more-comments-button'
 import useMoreCommments from '../hooks/use-more-comments'
 import { Decoration } from '@codemirror/view'
@@ -111,7 +111,10 @@ const ReviewPanelCurrentFile: FC = () => {
 
   const positionsRef = useRef<Map<string, number>>(new Map())
 
-  const addCommentRanges = state.field(addCommentStateField, false)?.ranges
+  const addCommentRanges = state.field(
+    reviewTooltipStateField,
+    false
+  )?.addCommentRanges
 
   useEffect(() => {
     if (aggregatedRanges) {

+ 50 - 3
services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx

@@ -4,6 +4,7 @@ import {
   SetStateAction,
   useCallback,
   useEffect,
+  useMemo,
   useState,
 } from 'react'
 import ReactDOM from 'react-dom'
@@ -14,14 +15,19 @@ import {
   useCodeMirrorViewContext,
 } from '@/features/source-editor/components/codemirror-context'
 import {
-  addCommentStateField,
   buildAddNewCommentRangeEffect,
-} from '@/features/source-editor/extensions/add-comment'
+  reviewTooltipStateField,
+} from '@/features/source-editor/extensions/review-tooltip'
 import { getTooltip } from '@codemirror/view'
 import useViewerPermissions from '@/shared/hooks/use-viewer-permissions'
 import usePreviousValue from '@/shared/hooks/use-previous-value'
 import { useLayoutContext } from '@/shared/context/layout-context'
 import { useReviewPanelViewActionsContext } from '../context/review-panel-view-context'
+import {
+  useRangesActionsContext,
+  useRangesContext,
+} from '../context/ranges-context'
+import { isInsertOperation } from '@/utils/operations'
 
 const ReviewTooltipMenu: FC = () => {
   const state = useCodeMirrorStateContext()
@@ -29,7 +35,7 @@ const ReviewTooltipMenu: FC = () => {
   const isViewer = useViewerPermissions()
   const [show, setShow] = useState(true)
 
-  const tooltipState = state.field(addCommentStateField, false)?.tooltip
+  const tooltipState = state.field(reviewTooltipStateField, false)?.tooltip
   const previousTooltipState = usePreviousValue(tooltipState)
 
   useEffect(() => {
@@ -62,6 +68,8 @@ const ReviewTooltipMenuContent: FC<{
   const state = useCodeMirrorStateContext()
   const { setReviewPanelOpen } = useLayoutContext()
   const { setView } = useReviewPanelViewActionsContext()
+  const ranges = useRangesContext()
+  const { acceptChanges, rejectChanges } = useRangesActionsContext()
 
   const addComment = useCallback(() => {
     setReviewPanelOpen(true)
@@ -80,6 +88,28 @@ const ReviewTooltipMenuContent: FC<{
     }
   }, [addComment])
 
+  const changeIdsInSelection = useMemo(() => {
+    return (ranges?.changes ?? [])
+      .filter(({ op }) => {
+        const opFrom = op.p
+        const opLength = isInsertOperation(op) ? op.i.length : 0
+        const opTo = opFrom + opLength
+        const selection = state.selection.main
+        return opFrom >= selection.from && opTo <= selection.to
+      })
+      .map(({ id }) => id)
+  }, [ranges, state.selection.main])
+
+  const acceptChangesHandler = useCallback(() => {
+    acceptChanges(...changeIdsInSelection)
+  }, [acceptChanges, changeIdsInSelection])
+
+  const rejectChangesHandler = useCallback(() => {
+    rejectChanges(...changeIdsInSelection)
+  }, [rejectChanges, changeIdsInSelection])
+
+  const showChangesButtons = changeIdsInSelection.length > 0
+
   return (
     <div className="review-tooltip-menu">
       <button
@@ -89,6 +119,23 @@ const ReviewTooltipMenuContent: FC<{
         <MaterialIcon type="chat" />
         {t('add_comment')}
       </button>
+      {showChangesButtons && (
+        <>
+          <div className="review-tooltip-menu-divider" />
+          <button
+            className="review-tooltip-menu-button"
+            onClick={acceptChangesHandler}
+          >
+            <MaterialIcon type="check" />
+          </button>
+          <button
+            className="review-tooltip-menu-button"
+            onClick={rejectChangesHandler}
+          >
+            <MaterialIcon type="clear" />
+          </button>
+        </>
+      )}
     </div>
   )
 }

+ 2 - 2
services/web/frontend/js/features/source-editor/extensions/index.ts

@@ -52,7 +52,7 @@ import { mathPreview } from './math-preview'
 import { isSplitTestEnabled } from '@/utils/splitTestUtils'
 import { ranges } from './ranges'
 import { trackDetachedComments } from './track-detached-comments'
-import { addComment } from './add-comment'
+import { reviewTooltip } from './review-tooltip'
 
 const moduleExtensions: Array<(options: Record<string, any>) => Extension> =
   importOverleafModules('sourceEditorExtensions').map(
@@ -138,7 +138,7 @@ export const createExtensions = (options: Record<string, any>): Extension[] => [
   trackDetachedComments(options.currentDoc),
   visual(options.visual),
   mathPreview(options.settings.mathPreview),
-  addComment(),
+  reviewTooltip(),
   toolbarPanel(),
   verticalOverflow(),
   highlightActiveLine(options.visual.visual),

+ 12 - 12
services/web/frontend/js/features/source-editor/extensions/add-comment.ts → services/web/frontend/js/features/source-editor/extensions/review-tooltip.ts

@@ -31,31 +31,31 @@ export const buildAddNewCommentRangeEffect = (range: SelectionRange) => {
   )
 }
 
-export const addComment = (): Extension => {
+export const reviewTooltip = (): Extension => {
   if (!isSplitTestEnabled('review-panel-redesign')) {
     return []
   }
 
-  return [addCommentTheme, addCommentStateField, textSelected]
+  return [reviewTooltipTheme, reviewTooltipStateField, textSelected]
 }
 
-export const addCommentStateField = StateField.define<{
+export const reviewTooltipStateField = StateField.define<{
   tooltip: Tooltip | null
-  ranges: DecorationSet
+  addCommentRanges: DecorationSet
 }>({
   create() {
-    return { tooltip: null, ranges: Decoration.none }
+    return { tooltip: null, addCommentRanges: Decoration.none }
   },
 
   update(field, tr) {
-    let { tooltip, ranges } = field
+    let { tooltip, addCommentRanges } = field
 
-    ranges = ranges.map(tr.changes)
+    addCommentRanges = addCommentRanges.map(tr.changes)
 
     for (const effect of tr.effects) {
       if (effect.is(removeNewCommentRangeEffect)) {
         const rangeToRemove = effect.value
-        ranges = ranges.update({
+        addCommentRanges = addCommentRanges.update({
           // eslint-disable-next-line no-unused-vars
           filter: (from, to, value) => {
             return value.spec.id !== rangeToRemove.spec.id
@@ -65,7 +65,7 @@ export const addCommentStateField = StateField.define<{
 
       if (effect.is(addNewCommentRangeEffect)) {
         const rangeToAdd = effect.value
-        ranges = ranges.update({
+        addCommentRanges = addCommentRanges.update({
           add: [rangeToAdd],
         })
       }
@@ -79,11 +79,11 @@ export const addCommentStateField = StateField.define<{
       }
     }
 
-    return { tooltip, ranges }
+    return { tooltip, addCommentRanges }
   },
 
   provide: field => [
-    EditorView.decorations.from(field, field => field.ranges),
+    EditorView.decorations.from(field, field => field.addCommentRanges),
     showTooltip.compute([field], state => state.field(field).tooltip),
   ],
 })
@@ -109,7 +109,7 @@ function buildTooltip(range: SelectionRange): Tooltip | null {
 /**
  * Styles for the tooltip
  */
-const addCommentTheme = EditorView.baseTheme({
+const reviewTooltipTheme = EditorView.baseTheme({
   '.review-tooltip-menu-container.cm-tooltip': {
     backgroundColor: 'transparent',
     border: 'none',

+ 7 - 0
services/web/frontend/stylesheets/app/editor/review-panel-new.less

@@ -619,10 +619,12 @@
 }
 
 .review-tooltip-menu {
+  display: flex;
   box-shadow: 0px 2px 4px 0px #1e253029;
   border: none;
   border-radius: 4px;
   padding: 4px;
+  gap: 4px;
 }
 
 .review-tooltip-menu-button {
@@ -635,6 +637,11 @@
   border-radius: @border-radius-base;
 }
 
+.review-tooltip-menu-divider {
+  width: 1px;
+  background-color: #e7e9ee;
+}
+
 .review-tooltip-add-comment-button {
   padding: 2px 8px;
 }

+ 7 - 0
services/web/frontend/stylesheets/bootstrap-5/pages/editor/review-panel-new.scss

@@ -623,10 +623,12 @@
 }
 
 .review-tooltip-menu {
+  display: flex;
   box-shadow: 0 2px 4px 0 #1e253029;
   border: none;
   border-radius: var(--border-radius-base);
   padding: var(--spacing-02);
+  gap: var(--spacing-02);
 }
 
 .review-tooltip-menu-button {
@@ -644,6 +646,11 @@
   padding: var(--spacing-01) var(--spacing-04);
 }
 
+.review-tooltip-menu-divider {
+  width: 1px;
+  background-color: #e7e9ee;
+}
+
 .review-panel-tooltip {
   pointer-events: none; // this is to prevent mouseLeave event from firing when hovering over the tooltip
 }