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

Merge pull request #13487 from overleaf/ii-review-panel-migration-create-panel-toggler

[web] Create review panel toggler

GitOrigin-RevId: f50422b99dbd8bbc2f1fbf323419ee13403c9ba6
ilkin-overleaf 3 лет назад
Родитель
Сommit
15f4e2e5cc

+ 2 - 0
services/web/frontend/js/features/source-editor/components/review-panel/container.tsx

@@ -1,3 +1,4 @@
+import Toggler from './toggler'
 import Toolbar from './toolbar/toolbar'
 import Nav from './nav'
 import classnames from 'classnames'
@@ -17,6 +18,7 @@ function Container({ children, classNames, ...rest }: ContainerProps) {
       {...rest}
       data-testid="review-panel"
     >
+      <Toggler />
       <Toolbar />
       {children}
       <Nav />

+ 5 - 3
services/web/frontend/js/features/source-editor/components/review-panel/nav.tsx

@@ -1,7 +1,9 @@
-export type SubView = 'cur_file' | 'overview'
-
 function Nav() {
-  return <div style={{ background: '#bbb', padding: '10px' }}>Nav</div>
+  return (
+    <div className="rp-nav" style={{ background: '#8eaeb6', padding: '5px' }}>
+      Nav
+    </div>
+  )
 }
 
 export default Nav

+ 25 - 0
services/web/frontend/js/features/source-editor/components/review-panel/toggler.tsx

@@ -0,0 +1,25 @@
+import { useTranslation } from 'react-i18next'
+import { useReviewPanelValueContext } from '../../context/review-panel/review-panel-context'
+
+function Toggler() {
+  const { t } = useTranslation()
+  const { toggleReviewPanel } = useReviewPanelValueContext()
+
+  const handleTogglerClick = (event: React.MouseEvent<HTMLButtonElement>) => {
+    const target = event.target as HTMLButtonElement
+    target.blur()
+    toggleReviewPanel()
+  }
+
+  return (
+    <button
+      type="button"
+      className="review-panel-toggler"
+      onClick={handleTogglerClick}
+    >
+      <span className="sr-only">{t('hotkey_toggle_review_panel')}</span>
+    </button>
+  )
+}
+
+export default Toggler

+ 5 - 0
services/web/frontend/js/features/source-editor/context/review-panel/hooks/use-angular-review-panel-state.ts

@@ -47,6 +47,9 @@ function useAngularReviewPanelState(): ReviewPanelState {
     ReviewPanel.Value<'formattedProjectMembers'>
   >('reviewPanel.formattedProjectMembers')
 
+  const [toggleReviewPanel] =
+    useScopeValue<ReviewPanel.Value<'toggleReviewPanel'>>('toggleReviewPanel')
+
   const values = useMemo<ReviewPanelState['values']>(
     () => ({
       collapsed,
@@ -62,6 +65,7 @@ function useAngularReviewPanelState(): ReviewPanelState {
       trackChangesOnForGuests,
       trackChangesForGuestsAvailable,
       formattedProjectMembers,
+      toggleReviewPanel,
     }),
     [
       collapsed,
@@ -77,6 +81,7 @@ function useAngularReviewPanelState(): ReviewPanelState {
       trackChangesOnForGuests,
       trackChangesForGuestsAvailable,
       formattedProjectMembers,
+      toggleReviewPanel,
     ]
   )
 

+ 5 - 2
services/web/frontend/js/features/source-editor/context/review-panel/types/review-panel-state.ts

@@ -1,5 +1,7 @@
-import { SubView } from '../../../components/review-panel/nav'
-import { ReviewPanelPermissions } from '../../../../../../../types/review-panel'
+import {
+  SubView,
+  ReviewPanelPermissions,
+} from '../../../../../../../types/review-panel'
 
 export interface ReviewPanelState {
   values: {
@@ -22,6 +24,7 @@ export interface ReviewPanelState {
         name: string
       }
     >
+    toggleReviewPanel: () => void
   }
   updaterFns: {
     setCollapsed: React.Dispatch<

+ 14 - 13
services/web/frontend/stylesheets/app/editor/review-panel.less

@@ -1222,6 +1222,19 @@ button when (@is-overleaf-light = true) {
     }
   }
 
+  .review-panel-toggler {
+    display: flex;
+    flex-direction: column;
+    padding: 0;
+    border: 0;
+
+    &:after {
+      position: sticky;
+      top: 50%;
+      bottom: 50%;
+    }
+  }
+
   .rp-state-current-file & {
     .review-panel-tools {
       display: flex;
@@ -1243,25 +1256,13 @@ button when (@is-overleaf-light = true) {
       position: sticky;
       bottom: 0;
     }
-
-    .review-panel-toggler {
-      position: sticky;
-      top: 0;
-    }
   }
 
-  .rp-state-overview & {
+  .rp-state-overview {
     position: sticky;
     top: 0;
     display: flex;
     flex-direction: column;
-
-    .review-panel-toggler {
-      position: absolute;
-      top: 0;
-      bottom: 0;
-      left: 0;
-    }
   }
 
   .rp-nav-item {

+ 20 - 7
services/web/test/frontend/features/review-panel/review-panel.spec.tsx

@@ -22,15 +22,11 @@ describe('<ReviewPanel />', function () {
     const scope = mockScope('')
     scope.editor.showVisual = true
 
-    // Making a shallow copy, otherwise cannot spy on an object declared outside the test file
-    const newScope = { ...scope }
-    cy.spy(newScope, 'toggleTrackChangesForEveryone').as(
-      'toggleTrackChangesForEveryone'
-    )
+    cy.wrap(scope).as('scope')
 
     cy.mount(
       <Container className="rp-size-expanded">
-        <EditorProviders scope={newScope}>
+        <EditorProviders scope={scope}>
           <CodeMirrorEditor />
         </EditorProviders>
       </Container>
@@ -90,7 +86,9 @@ describe('<ReviewPanel />', function () {
           cy.findByLabelText(/track changes for everyone/i).click({
             force: true,
           })
-          cy.get('@toggleTrackChangesForEveryone').should('be.calledOnce')
+          cy.get('@scope')
+            .its('toggleTrackChangesForEveryone')
+            .should('be.calledOnce')
         })
       })
 
@@ -118,4 +116,19 @@ describe('<ReviewPanel />', function () {
       })
     })
   })
+
+  describe('toggler', function () {
+    it('renders toggler button', function () {
+      cy.get('@review-panel').within(() => {
+        cy.findByRole('button', { name: /toggle review panel/i })
+      })
+    })
+
+    it('calls the toggler function on click', function () {
+      cy.get('@review-panel').within(() => {
+        cy.findByRole('button', { name: /toggle review panel/i }).click()
+        cy.get('@scope').its('toggleReviewPanel').should('be.calledOnce')
+      })
+    })
+  })
 })

+ 2 - 1
services/web/test/frontend/features/source-editor/helpers/mock-scope.ts

@@ -82,7 +82,8 @@ export const mockScope = (content?: string) => {
     ui: {
       reviewPanelOpen: true,
     },
-    toggleTrackChangesForEveryone() {},
+    toggleReviewPanel: cy.stub(),
+    toggleTrackChangesForEveryone: cy.stub(),
     onlineUserCursorHighlights: {},
     permissionsLevel: 'owner',
     $on: cy.stub(),

+ 2 - 0
services/web/types/review-panel.ts

@@ -1,3 +1,5 @@
+export type SubView = 'cur_file' | 'overview'
+
 export interface ReviewPanelPermissions {
   read: boolean
   write: boolean