From 456d831eab8409821e5861d77df5a4db9f947d91 Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:30:06 +0200 Subject: [PATCH] Merge pull request #16188 from overleaf/ii-rp-collapse-height [web] Review panel comment container fix GitOrigin-RevId: 0577949e711046303d25ba7e724564227d4a1bc7 --- .../entries/overview-file-entries.tsx | 96 +++++++++++++ .../review-panel/hooks/use-collapse-height.ts | 26 ---- .../components/review-panel/overview-file.tsx | 96 ++----------- .../review-panel/toolbar/toggle-menu.tsx | 133 +----------------- .../toolbar/track-changes-menu.tsx | 130 +++++++++++++++++ .../stylesheets/app/editor/review-panel.less | 11 -- .../review-panel/review-panel.spec.tsx | 8 +- 7 files changed, 246 insertions(+), 254 deletions(-) create mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/entries/overview-file-entries.tsx delete mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/hooks/use-collapse-height.ts create mode 100644 services/web/frontend/js/features/source-editor/components/review-panel/toolbar/track-changes-menu.tsx diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/entries/overview-file-entries.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/entries/overview-file-entries.tsx new file mode 100644 index 0000000000..a55fbba050 --- /dev/null +++ b/services/web/frontend/js/features/source-editor/components/review-panel/entries/overview-file-entries.tsx @@ -0,0 +1,96 @@ +import { useMemo } from 'react' +import ChangeEntry from '@/features/source-editor/components/review-panel/entries/change-entry' +import AggregateChangeEntry from '@/features/source-editor/components/review-panel/entries/aggregate-change-entry' +import CommentEntry from '@/features/source-editor/components/review-panel/entries/comment-entry' +import { useReviewPanelValueContext } from '@/features/source-editor/context/review-panel/review-panel-context' +import { + ReviewPanelDocEntries, + ThreadId, +} from '../../../../../../../types/review-panel/review-panel' +import { ReviewPanelEntry } from '../../../../../../../types/review-panel/entry' +import { DocId } from '../../../../../../../types/project-settings' + +type OverviewFileEntriesProps = { + docId: DocId + docEntries: ReviewPanelDocEntries +} + +function OverviewFileEntries({ docId, docEntries }: OverviewFileEntriesProps) { + const { commentThreads, permissions, users } = useReviewPanelValueContext() + + const objectEntries = useMemo(() => { + const entries = Object.entries(docEntries) as Array< + [ThreadId, ReviewPanelEntry] + > + + const orderedEntries = entries.sort(([, entryA], [, entryB]) => { + return entryA.offset - entryB.offset + }) + + return orderedEntries + }, [docEntries]) + + return ( +
+ {objectEntries.map(([id, entry]) => { + if (entry.type === 'insert' || entry.type === 'delete') { + return ( + + ) + } + + if (entry.type === 'aggregate-change') { + return ( + + ) + } + + if (entry.type === 'comment') { + const thread = commentThreads[entry.thread_id] + if (!thread?.resolved) { + return ( + + ) + } + } + + return null + })} +
+ ) +} + +export default OverviewFileEntries diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/hooks/use-collapse-height.ts b/services/web/frontend/js/features/source-editor/components/review-panel/hooks/use-collapse-height.ts deleted file mode 100644 index 431ce8ac96..0000000000 --- a/services/web/frontend/js/features/source-editor/components/review-panel/hooks/use-collapse-height.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useEffect } from 'react' - -function useCollapseHeight( - elRef: React.MutableRefObject, - shouldCollapse: boolean -) { - useEffect(() => { - if (elRef.current) { - const neededHeight = elRef.current.scrollHeight - - if (neededHeight > 0) { - const height = shouldCollapse ? 0 : neededHeight - // This might result in a too big height if the element has css prop of - // `box-sizing` set to `content-box`. To fix that, values of props such as - // box-sizing, padding and border could be extracted from `height` to compensate. - elRef.current.style.height = `${height}px` - } else { - if (shouldCollapse) { - elRef.current.style.height = '0' - } - } - } - }, [elRef, shouldCollapse]) -} - -export default useCollapseHeight diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/overview-file.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/overview-file.tsx index 106e75dffc..5780a84246 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/overview-file.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/overview-file.tsx @@ -1,17 +1,13 @@ -import { useMemo, useRef } from 'react' +import { useMemo } from 'react' import Icon from '../../../../shared/components/icon' -import ChangeEntry from './entries/change-entry' -import AggregateChangeEntry from './entries/aggregate-change-entry' -import CommentEntry from './entries/comment-entry' import { useReviewPanelUpdaterFnsContext, useReviewPanelValueContext, } from '../../context/review-panel/review-panel-context' import classnames from 'classnames' -import { ThreadId } from '../../../../../../types/review-panel/review-panel' +import { ReviewPanelDocEntries } from '../../../../../../types/review-panel/review-panel' import { MainDocument } from '../../../../../../types/project-settings' -import { ReviewPanelEntry } from '../../../../../../types/review-panel/entry' -import useCollapseHeight from './hooks/use-collapse-height' +import OverviewFileEntries from '@/features/source-editor/components/review-panel/entries/overview-file-entries' type OverviewFileProps = { docId: MainDocument['doc']['id'] @@ -19,26 +15,13 @@ type OverviewFileProps = { } function OverviewFile({ docId, docPath }: OverviewFileProps) { - const { entries, collapsed, commentThreads, permissions, users } = - useReviewPanelValueContext() + const { entries, collapsed } = useReviewPanelValueContext() const { setCollapsed } = useReviewPanelUpdaterFnsContext() const docCollapsed = collapsed[docId] - const docEntries = useMemo( - () => (docId in entries ? entries[docId] : {}), - [docId, entries] - ) - const objectEntries = useMemo(() => { - const entries = Object.entries(docEntries) as Array< - [ThreadId, ReviewPanelEntry] - > - - const orderedEntries = entries.sort(([, entryA], [, entryB]) => { - return entryA.offset - entryB.offset - }) - - return orderedEntries - }, [docEntries]) + const docEntries = useMemo(() => { + return docId in entries ? entries[docId] : ({} as ReviewPanelDocEntries) + }, [docId, entries]) const entryCount = useMemo(() => { return Object.keys(docEntries).filter( key => key !== 'add-comment' && key !== 'bulk-actions' @@ -49,9 +32,6 @@ function OverviewFile({ docId, docPath }: OverviewFileProps) { setCollapsed({ ...collapsed, [docId]: !docCollapsed }) } - const entriesContainerRef = useRef(null) - useCollapseHeight(entriesContainerRef, docCollapsed) - return (
{entryCount > 0 && ( @@ -78,65 +58,9 @@ function OverviewFile({ docId, docPath }: OverviewFileProps) { )}
)} -
- {objectEntries.map(([id, entry]) => { - if (entry.type === 'insert' || entry.type === 'delete') { - return ( - - ) - } - - if (entry.type === 'aggregate-change') { - return ( - - ) - } - - if (entry.type === 'comment') { - const thread = commentThreads[entry.thread_id] - if (!thread?.resolved) { - return ( - - ) - } - } - - return null - })} -
+ {!docCollapsed && ( + + )} ) } diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/toggle-menu.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/toggle-menu.tsx index 31c4305002..bf04f6ca41 100644 --- a/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/toggle-menu.tsx +++ b/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/toggle-menu.tsx @@ -1,15 +1,13 @@ -import { useState, useRef } from 'react' -import { Trans, useTranslation } from 'react-i18next' -import Tooltip from '../../../../../shared/components/tooltip' +import { useState } from 'react' +import { Trans } from 'react-i18next' import Icon from '../../../../../shared/components/icon' -import TrackChangesToggle from './track-changes-toggle' +import TrackChangesMenu from '@/features/source-editor/components/review-panel/toolbar/track-changes-menu' import UpgradeTrackChangesModal from '../upgrade-track-changes-modal' import { useProjectContext } from '../../../../../shared/context/project-context' import { useReviewPanelUpdaterFnsContext, useReviewPanelValueContext, } from '../../../context/review-panel/review-panel-context' -import useCollapseHeight from '../hooks/use-collapse-height' import { send, sendMB } from '../../../../../infrastructure/event-tracking' import classnames from 'classnames' @@ -21,30 +19,12 @@ const sendAnalytics = () => { } function ToggleMenu() { - const { t } = useTranslation() const project = useProjectContext() - const { - setShouldCollapse, - toggleTrackChangesForEveryone, - toggleTrackChangesForUser, - toggleTrackChangesForGuests, - } = useReviewPanelUpdaterFnsContext() - const { - permissions, - wantTrackChanges, - shouldCollapse, - trackChangesState, - trackChangesOnForEveryone, - trackChangesOnForGuests, - trackChangesForGuestsAvailable, - formattedProjectMembers, - } = useReviewPanelValueContext() + const { setShouldCollapse } = useReviewPanelUpdaterFnsContext() + const { wantTrackChanges, shouldCollapse } = useReviewPanelValueContext() const [showModal, setShowModal] = useState(false) - const containerRef = useRef(null) - useCollapseHeight(containerRef, shouldCollapse) - const handleToggleFullTCStateCollapse = () => { if (project.features.trackChanges) { setShouldCollapse(value => !value) @@ -88,108 +68,7 @@ function ToggleMenu() { -
    -
  • - - {t('tc_everyone')} - - - - toggleTrackChangesForEveryone(!trackChangesOnForEveryone) - } - value={trackChangesOnForEveryone} - disabled={!project.features.trackChanges || !permissions.write} - /> -
  • - {Object.values(formattedProjectMembers).map(member => ( -
  • - - - {member.name} - - - - - toggleTrackChangesForUser( - !trackChangesState[member.id]?.value, - member.id - ) - } - value={Boolean(trackChangesState[member.id]?.value)} - disabled={ - trackChangesOnForEveryone || - !project.features.trackChanges || - !permissions.write - } - /> -
  • - ))} -
  • -
  • - - - {t('tc_guests')} - - - - - toggleTrackChangesForGuests(!trackChangesOnForGuests) - } - value={trackChangesOnForGuests} - disabled={ - trackChangesOnForEveryone || - !project.features.trackChanges || - !permissions.write || - !trackChangesForGuestsAvailable - } - /> -
  • -
+ {!shouldCollapse && } diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/track-changes-menu.tsx b/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/track-changes-menu.tsx new file mode 100644 index 0000000000..2d32b2cb61 --- /dev/null +++ b/services/web/frontend/js/features/source-editor/components/review-panel/toolbar/track-changes-menu.tsx @@ -0,0 +1,130 @@ +import { useTranslation } from 'react-i18next' +import Tooltip from '@/shared/components/tooltip' +import TrackChangesToggle from '@/features/source-editor/components/review-panel/toolbar/track-changes-toggle' +import { + useReviewPanelUpdaterFnsContext, + useReviewPanelValueContext, +} from '@/features/source-editor/context/review-panel/review-panel-context' +import { useProjectContext } from '@/shared/context/project-context' +import classnames from 'classnames' + +function TrackChangesMenu() { + const { t } = useTranslation() + const project = useProjectContext() + const { + toggleTrackChangesForEveryone, + toggleTrackChangesForUser, + toggleTrackChangesForGuests, + } = useReviewPanelUpdaterFnsContext() + const { + permissions, + trackChangesState, + trackChangesOnForEveryone, + trackChangesOnForGuests, + trackChangesForGuestsAvailable, + formattedProjectMembers, + } = useReviewPanelValueContext() + + return ( +
    +
  • + + {t('tc_everyone')} + + + + toggleTrackChangesForEveryone(!trackChangesOnForEveryone) + } + value={trackChangesOnForEveryone} + disabled={!project.features.trackChanges || !permissions.write} + /> +
  • + {Object.values(formattedProjectMembers).map(member => ( +
  • + + + {member.name} + + + + + toggleTrackChangesForUser( + !trackChangesState[member.id]?.value, + member.id + ) + } + value={Boolean(trackChangesState[member.id]?.value)} + disabled={ + trackChangesOnForEveryone || + !project.features.trackChanges || + !permissions.write + } + /> +
  • + ))} +
  • +
  • + + + {t('tc_guests')} + + + + + toggleTrackChangesForGuests(!trackChangesOnForGuests) + } + value={trackChangesOnForGuests} + disabled={ + trackChangesOnForEveryone || + !project.features.trackChanges || + !permissions.write || + !trackChangesForGuestsAvailable + } + /> +
  • +
+ ) +} + +export default TrackChangesMenu diff --git a/services/web/frontend/stylesheets/app/editor/review-panel.less b/services/web/frontend/stylesheets/app/editor/review-panel.less index 3e8d075b96..34d9a83e0a 100644 --- a/services/web/frontend/stylesheets/app/editor/review-panel.less +++ b/services/web/frontend/stylesheets/app/editor/review-panel.less @@ -1311,23 +1311,12 @@ button when (@is-overleaf-light = true) { height: 100%; } - .rp-overview-file { - .rp-overview-file-entries { - transition: height ease-in-out 0.15s; - } - } - .rp-nav-item { border-right: 0; border-bottom: 0; border-left: 0; background: none; } - - .rp-tc-state { - height: 0; - transition: height 150ms; - } } .rp-floating-entry { diff --git a/services/web/test/frontend/features/review-panel/review-panel.spec.tsx b/services/web/test/frontend/features/review-panel/review-panel.spec.tsx index d5b36a3f78..16e2ebf0f2 100644 --- a/services/web/test/frontend/features/review-panel/review-panel.spec.tsx +++ b/services/web/test/frontend/features/review-panel/review-panel.spec.tsx @@ -68,11 +68,11 @@ describe('', function () { it('opens/closes toggle menu', function () { cy.get('@review-panel').within(() => { - cy.findByTestId('review-panel-track-changes-menu').as('menu') - cy.get('@menu').should('have.css', 'height', '1px') + cy.findByTestId('review-panel-track-changes-menu').should('not.exist') cy.findByRole('button', { name: /track changes is/i }).click() // verify the menu is expanded - cy.get('@menu') + cy.findByTestId('review-panel-track-changes-menu') + .as('menu') .then($el => { const height = window .getComputedStyle($el[0]) @@ -81,7 +81,7 @@ describe('', function () { }) .should('be.gt', 1) cy.findByRole('button', { name: /track changes is/i }).click() - cy.get('@menu').should('have.css', 'height', '1px') + cy.get('@menu').should('not.exist') }) })