From 1c5f5950fa53cbb23182ea52ee445b6b3c964d7b Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:14:16 +0100 Subject: [PATCH] Merge pull request #21208 from overleaf/dp-accept-reject-all-changes Add options to accept/reject all changes to review tooltip GitOrigin-RevId: 1cea76926d59d0354c8abaa6ba69b7e99c02fbe0 --- .../components/review-panel-add-comment.tsx | 2 +- .../components/review-panel-current-file.tsx | 7 ++- .../components/review-tooltip-menu.tsx | 53 +++++++++++++++++-- .../source-editor/extensions/index.ts | 4 +- .../{add-comment.ts => review-tooltip.ts} | 24 ++++----- .../app/editor/review-panel-new.less | 7 +++ .../pages/editor/review-panel-new.scss | 7 +++ 7 files changed, 84 insertions(+), 20 deletions(-) rename services/web/frontend/js/features/source-editor/extensions/{add-comment.ts => review-tooltip.ts} (80%) diff --git a/services/web/frontend/js/features/review-panel-new/components/review-panel-add-comment.tsx b/services/web/frontend/js/features/review-panel-new/components/review-panel-add-comment.tsx index ebafb0cfc4..c147284eb7 100644 --- a/services/web/frontend/js/features/review-panel-new/components/review-panel-add-comment.tsx +++ b/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' diff --git a/services/web/frontend/js/features/review-panel-new/components/review-panel-current-file.tsx b/services/web/frontend/js/features/review-panel-new/components/review-panel-current-file.tsx index 16378ffc6f..7b136cddb0 100644 --- a/services/web/frontend/js/features/review-panel-new/components/review-panel-current-file.tsx +++ b/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>(new Map()) - const addCommentRanges = state.field(addCommentStateField, false)?.ranges + const addCommentRanges = state.field( + reviewTooltipStateField, + false + )?.addCommentRanges useEffect(() => { if (aggregatedRanges) { diff --git a/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx b/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx index ce34a6f74d..7c2bde4997 100644 --- a/services/web/frontend/js/features/review-panel-new/components/review-tooltip-menu.tsx +++ b/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 (
+ {showChangesButtons && ( + <> +
+ + + + )}
) } diff --git a/services/web/frontend/js/features/source-editor/extensions/index.ts b/services/web/frontend/js/features/source-editor/extensions/index.ts index d8d21d649a..96179a7b6e 100644 --- a/services/web/frontend/js/features/source-editor/extensions/index.ts +++ b/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) => Extension> = importOverleafModules('sourceEditorExtensions').map( @@ -138,7 +138,7 @@ export const createExtensions = (options: Record): Extension[] => [ trackDetachedComments(options.currentDoc), visual(options.visual), mathPreview(options.settings.mathPreview), - addComment(), + reviewTooltip(), toolbarPanel(), verticalOverflow(), highlightActiveLine(options.visual.visual), diff --git a/services/web/frontend/js/features/source-editor/extensions/add-comment.ts b/services/web/frontend/js/features/source-editor/extensions/review-tooltip.ts similarity index 80% rename from services/web/frontend/js/features/source-editor/extensions/add-comment.ts rename to services/web/frontend/js/features/source-editor/extensions/review-tooltip.ts index 0d297e9491..0c7d917b68 100644 --- a/services/web/frontend/js/features/source-editor/extensions/add-comment.ts +++ b/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', diff --git a/services/web/frontend/stylesheets/app/editor/review-panel-new.less b/services/web/frontend/stylesheets/app/editor/review-panel-new.less index b3a3578b4d..bda2faa6cc 100644 --- a/services/web/frontend/stylesheets/app/editor/review-panel-new.less +++ b/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; } diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/review-panel-new.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/editor/review-panel-new.scss index fed7ead1fe..01ed159417 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/editor/review-panel-new.scss +++ b/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 }