From f173806ee24bc9681823e1078fce29c34dba9fe6 Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:10:35 +0200 Subject: [PATCH] Merge pull request #16065 from overleaf/ii-ide-page-prototype-review-panel-add-comment [web] React ide page add comment GitOrigin-RevId: 4c2442ccc77760d4a27268551c9dd2d73fcdba84 --- .../hooks/use-review-panel-state.ts | 72 ++++++++++++++++++- .../review-panel-context-adapter.ts | 2 - .../editor-widgets/editor-widgets.tsx | 10 +++ .../entries/add-comment-entry.tsx | 4 +- .../components/review-panel/review-panel.tsx | 1 + .../review-panel/types/review-panel-state.ts | 2 +- 6 files changed, 84 insertions(+), 7 deletions(-) diff --git a/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts b/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts index afb2b47e9d..a98a7f3a3b 100644 --- a/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts +++ b/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts @@ -6,6 +6,7 @@ import useScopeValue from '../../../../../shared/hooks/use-scope-value' import useSocketListener from '@/features/ide-react/hooks/use-socket-listener' import useAsync from '@/shared/hooks/use-async' import useAbortController from '@/shared/hooks/use-abort-controller' +import useScopeEventEmitter from '@/shared/hooks/use-scope-event-emitter' import { sendMB } from '../../../../../infrastructure/event-tracking' import { dispatchReviewPanelLayout as handleLayoutChange, @@ -130,6 +131,7 @@ function useReviewPanelState(): ReviewPanelStateReactIde { // TODO permissions to be removed from the review panel context. It currently acts just as a proxy. const { permissions } = usePermissionsContext() const { showGenericMessageModal } = useModalsContext() + const addCommentEmitter = useScopeEventEmitter('comment:start_adding') // TODO `currentDocument` and `currentDocumentId` should be get from `useEditorManagerContext()` but that makes tests fail const [currentDocument] = useScopeValue('editor.sharejs_doc') @@ -834,8 +836,6 @@ function useReviewPanelState(): ReviewPanelStateReactIde { applyTrackChangesStateToClient ) - const [submitNewComment] = - useScopeValue>('submitNewComment') const [gotoEntry] = useScopeValue>('gotoEntry') @@ -1097,6 +1097,53 @@ function useReviewPanelState(): ReviewPanelStateReactIde { [getThread, projectId, showGenericMessageModal, t, view] ) + // TODO `submitNewComment` is partially localized in the `add-comment-entry` component. + const submitNewComment = useCallback( + (content: string) => { + if (!content) { + return + } + + const entries = getDocEntries(currentDocumentId) + const addCommentEntry = entries['add-comment'] as + | ReviewPanelAddCommentEntry + | undefined + + if (!addCommentEntry) { + return + } + + const { offset, length } = addCommentEntry + const threadId = RangesTracker.generateId() + setCommentThreads(prevState => ({ + ...prevState, + [threadId]: { ...getThread(threadId), submitting: true }, + })) + + const url = `/project/${projectId}/thread/${threadId}/messages` + postJSON(url, { body: { content } }) + .then(() => { + dispatchReviewPanelEvent('comment:add', { threadId, offset, length }) + handleLayoutChange({ async: true }) + sendMB('rp-new-comment', { size: content.length }) + }) + .catch(() => { + showGenericMessageModal( + t('error_submitting_comment'), + t('comment_submit_error') + ) + }) + }, + [ + currentDocumentId, + getDocEntries, + getThread, + projectId, + showGenericMessageModal, + t, + ] + ) + const [entryHover, setEntryHover] = useState(false) const [isAddingComment, setIsAddingComment] = useState(false) const [navHeight, setNavHeight] = useState(0) @@ -1250,6 +1297,19 @@ function useReviewPanelState(): ReviewPanelStateReactIde { handleLayoutChange() } + const addNewCommentFromKbdShortcut = () => { + if (!trackChangesVisible) { + return + } + dispatchReviewPanelEvent('comment:select_line') + + if (!reviewPanelOpen) { + toggleReviewPanel() + } + handleLayoutChange({ async: true }) + addCommentEmitter() + } + const handleEditorEvents = (e: Event) => { const event = e as CustomEvent const { type, payload } = event.detail @@ -1266,6 +1326,11 @@ function useReviewPanelState(): ReviewPanelStateReactIde { break } + case 'add-new-comment': { + addNewCommentFromKbdShortcut() + break + } + case 'toggle-track-changes': { toggleTrackChangesFromKbdShortcut() break @@ -1279,9 +1344,12 @@ function useReviewPanelState(): ReviewPanelStateReactIde { window.removeEventListener('editor:event', handleEditorEvents) } }, [ + addCommentEmitter, currentDocumentId, getDocEntries, resolvedThreadIds, + reviewPanelOpen, + toggleReviewPanel, toggleTrackChangesForUser, trackChanges, trackChangesState, diff --git a/services/web/frontend/js/features/ide-react/scope-adapters/review-panel-context-adapter.ts b/services/web/frontend/js/features/ide-react/scope-adapters/review-panel-context-adapter.ts index e6b25f5e81..b5fa99d3c0 100644 --- a/services/web/frontend/js/features/ide-react/scope-adapters/review-panel-context-adapter.ts +++ b/services/web/frontend/js/features/ide-react/scope-adapters/review-panel-context-adapter.ts @@ -6,8 +6,6 @@ export default function populateReviewPanelScope(store: ReactScopeValueStore) { store.set('users', {}) store.set('reviewPanel.layoutToLeft', false) store.set('reviewPanel.rendererData.lineHeight', 0) - store.set('submitNewComment', async () => {}) store.set('gotoEntry', () => {}) - store.set('saveEdit', () => {}) store.set('addNewComment', () => {}) } diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/editor-widgets/editor-widgets.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/editor-widgets/editor-widgets.tsx index 76fc59b6f5..0894871276 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/editor-widgets/editor-widgets.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/editor-widgets/editor-widgets.tsx @@ -8,6 +8,7 @@ import { useReviewPanelUpdaterFnsContext, useReviewPanelValueContext, } from '../../../context/review-panel/review-panel-context' +import { useIdeContext } from '@/shared/context/ide-context' import { useCodeMirrorViewContext } from '../../codemirror-editor' import Modal, { useBulkActionsModal } from '../entries/bulk-actions-entry/modal' import getMeta from '../../../../../utils/meta' @@ -27,6 +28,8 @@ function EditorWidgets() { } = useBulkActionsModal() const { setIsAddingComment, handleSetSubview } = useReviewPanelUpdaterFnsContext() + const { isReactIde } = useIdeContext() + const { toggleReviewPanel } = useReviewPanelUpdaterFnsContext() const [addNewComment] = useScopeValue<(e: React.MouseEvent) => void>( 'addNewComment' @@ -47,6 +50,13 @@ function EditorWidgets() { openDocId && openDocId in entries ? entries[openDocId] : undefined const handleAddNewCommentClick = (e: React.MouseEvent) => { + if (isReactIde) { + e.preventDefault() + setIsAddingComment(true) + toggleReviewPanel() + return + } + addNewComment(e) setTimeout(() => { // Re-render the comment box in order to add autofocus every time diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/entries/add-comment-entry.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/entries/add-comment-entry.tsx index a5ee70df6f..50cb258809 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/entries/add-comment-entry.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/entries/add-comment-entry.tsx @@ -30,10 +30,10 @@ function AddCommentEntry() { handleLayoutChange({ async: true }) } - const handleSubmitNewComment = async () => { + const handleSubmitNewComment = () => { setIsSubmitting(true) try { - await submitNewComment(content) + submitNewComment(content) setIsSubmitting(false) setIsAddingComment(false) setContent('') diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/review-panel.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/review-panel.tsx index c3a1a0cb04..b984d6db43 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/review-panel.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/review-panel.tsx @@ -33,6 +33,7 @@ function ReviewPanelView({ parentDomNode }: ReviewPanelViewProps) { ) + // TODO fix DOM structure return ReactDOM.createPortal( isReactIde ? (
Promise< void | ReviewPanelDocEntries[] > - submitNewComment: (content: string) => Promise + submitNewComment: (content: string) => void setEntryHover: React.Dispatch>> setIsAddingComment: React.Dispatch< React.SetStateAction>