mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-29 20:11:32 +02:00
Merge pull request #13500 from overleaf/ii-review-panel-migration-nav
[web] Create review panel navigation GitOrigin-RevId: abed4171e9fd52de2f137a6cf7456791bc2ca161
This commit is contained in:
@@ -175,6 +175,7 @@
|
||||
"created": "",
|
||||
"created_at": "",
|
||||
"creating": "",
|
||||
"current_file": "",
|
||||
"current_password": "",
|
||||
"currently_seeing_only_24_hrs_history": "",
|
||||
"currently_subscribed_to_plan": "",
|
||||
@@ -655,6 +656,7 @@
|
||||
"overleaf": "",
|
||||
"overleaf_history_system": "",
|
||||
"overleaf_labs": "",
|
||||
"overview": "",
|
||||
"overwrite": "",
|
||||
"owned_by_x": "",
|
||||
"owner": "",
|
||||
|
||||
@@ -3,34 +3,42 @@ import Container from './container'
|
||||
function CurrentFileContainer() {
|
||||
return (
|
||||
<Container>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Et malesuada fames ac
|
||||
turpis egestas integer eget aliquet nibh. Et leo duis ut diam quam nulla
|
||||
porttitor massa id. Risus quis varius quam quisque id diam vel quam
|
||||
elementum. Nibh venenatis cras sed felis. Sit amet commodo nulla facilisi
|
||||
nullam vehicula ipsum a arcu. Dui ut ornare lectus sit amet est placerat
|
||||
in. Aliquam ultrices sagittis orci a. Leo a diam sollicitudin tempor id eu
|
||||
nisl nunc mi. Quis ipsum suspendisse ultrices gravida dictum fusce. Ut
|
||||
etiam sit amet nisl purus in mollis nunc sed. Rhoncus est pellentesque
|
||||
elit ullamcorper dignissim cras. Faucibus turpis in eu mi bibendum. Proin
|
||||
libero nunc consequat interdum. Ac placerat vestibulum lectus mauris
|
||||
ultrices eros in cursus turpis. Ac felis donec et odio. Nullam ac tortor
|
||||
vitae purus faucibus. Consectetur lorem donec massa sapien faucibus et
|
||||
molestie. Praesent elementum facilisis leo vel fringilla est ullamcorper
|
||||
eget nulla. Adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus
|
||||
urna. Cursus metus aliquam eleifend mi in nulla posuere sollicitudin
|
||||
aliquam. Eget nullam non nisi est sit amet facilisis magna. Donec
|
||||
adipiscing tristique risus nec feugiat in fermentum posuere. Gravida
|
||||
rutrum quisque non tellus orci ac auctor augue. Euismod in pellentesque
|
||||
massa placerat duis ultricies lacus. Pellentesque diam volutpat commodo
|
||||
sed egestas. Tempus iaculis urna id volutpat lacus laoreet. Lorem ipsum
|
||||
dolor sit amet consectetur. Tincidunt id aliquet risus feugiat in ante
|
||||
metus. Risus ultricies tristique nulla aliquet enim tortor at auctor urna.
|
||||
Purus in mollis nunc sed. In ante metus dictum at. Magna eget est lorem
|
||||
ipsum dolor sit. Fusce id velit ut tortor pretium viverra. Augue neque
|
||||
gravida in fermentum et sollicitudin ac. Et malesuada fames ac turpis.
|
||||
Felis bibendum ut tristique et egestas quis ipsum suspendisse ultrices.
|
||||
Varius vel pharetra vel turpis nunc eget.
|
||||
<div
|
||||
id="review-panel-current-file"
|
||||
role="tabpanel"
|
||||
tabIndex={0}
|
||||
aria-labelledby="review-panel-tab-current-file"
|
||||
>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Et malesuada fames
|
||||
ac turpis egestas integer eget aliquet nibh. Et leo duis ut diam quam
|
||||
nulla porttitor massa id. Risus quis varius quam quisque id diam vel
|
||||
quam elementum. Nibh venenatis cras sed felis. Sit amet commodo nulla
|
||||
facilisi nullam vehicula ipsum a arcu. Dui ut ornare lectus sit amet est
|
||||
placerat in. Aliquam ultrices sagittis orci a. Leo a diam sollicitudin
|
||||
tempor id eu nisl nunc mi. Quis ipsum suspendisse ultrices gravida
|
||||
dictum fusce. Ut etiam sit amet nisl purus in mollis nunc sed. Rhoncus
|
||||
est pellentesque elit ullamcorper dignissim cras. Faucibus turpis in eu
|
||||
mi bibendum. Proin libero nunc consequat interdum. Ac placerat
|
||||
vestibulum lectus mauris ultrices eros in cursus turpis. Ac felis donec
|
||||
et odio. Nullam ac tortor vitae purus faucibus. Consectetur lorem donec
|
||||
massa sapien faucibus et molestie. Praesent elementum facilisis leo vel
|
||||
fringilla est ullamcorper eget nulla. Adipiscing vitae proin sagittis
|
||||
nisl rhoncus mattis rhoncus urna. Cursus metus aliquam eleifend mi in
|
||||
nulla posuere sollicitudin aliquam. Eget nullam non nisi est sit amet
|
||||
facilisis magna. Donec adipiscing tristique risus nec feugiat in
|
||||
fermentum posuere. Gravida rutrum quisque non tellus orci ac auctor
|
||||
augue. Euismod in pellentesque massa placerat duis ultricies lacus.
|
||||
Pellentesque diam volutpat commodo sed egestas. Tempus iaculis urna id
|
||||
volutpat lacus laoreet. Lorem ipsum dolor sit amet consectetur.
|
||||
Tincidunt id aliquet risus feugiat in ante metus. Risus ultricies
|
||||
tristique nulla aliquet enim tortor at auctor urna. Purus in mollis nunc
|
||||
sed. In ante metus dictum at. Magna eget est lorem ipsum dolor sit.
|
||||
Fusce id velit ut tortor pretium viverra. Augue neque gravida in
|
||||
fermentum et sollicitudin ac. Et malesuada fames ac turpis. Felis
|
||||
bibendum ut tristique et egestas quis ipsum suspendisse ultrices. Varius
|
||||
vel pharetra vel turpis nunc eget.
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,49 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import classnames from 'classnames'
|
||||
import Icon from '../../../../shared/components/icon'
|
||||
import {
|
||||
useReviewPanelValueContext,
|
||||
useReviewPanelUpdaterFnsContext,
|
||||
} from '../../context/review-panel/review-panel-context'
|
||||
import { isCurrentFileView, isOverviewView } from '../../utils/sub-view'
|
||||
|
||||
function Nav() {
|
||||
const { t } = useTranslation()
|
||||
const { subView } = useReviewPanelValueContext()
|
||||
const { handleSetSubview } = useReviewPanelUpdaterFnsContext()
|
||||
|
||||
return (
|
||||
<div className="rp-nav" style={{ background: '#8eaeb6', padding: '5px' }}>
|
||||
Nav
|
||||
<div className="rp-nav" role="tablist">
|
||||
<button
|
||||
type="button"
|
||||
id="review-panel-tab-current-file"
|
||||
role="tab"
|
||||
aria-selected={isCurrentFileView(subView)}
|
||||
aria-controls="review-panel-current-file"
|
||||
tabIndex={isCurrentFileView(subView) ? 0 : -1}
|
||||
className={classnames('rp-nav-item', {
|
||||
'rp-nav-item-active': isCurrentFileView(subView),
|
||||
})}
|
||||
onClick={() => handleSetSubview('cur_file')}
|
||||
>
|
||||
<Icon type="file-text-o" />
|
||||
<span className="rp-nav-label">{t('current_file')}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="review-panel-tab-overview"
|
||||
role="tab"
|
||||
aria-selected={isOverviewView(subView)}
|
||||
aria-controls="review-panel-overview"
|
||||
tabIndex={isOverviewView(subView) ? 0 : -1}
|
||||
className={classnames('rp-nav-item', {
|
||||
'rp-nav-item-active': isOverviewView(subView),
|
||||
})}
|
||||
onClick={() => handleSetSubview('overview')}
|
||||
>
|
||||
<Icon type="list" />
|
||||
<span className="rp-nav-label">{t('overview')}</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,29 @@ import Container from './container'
|
||||
function OverviewContainer() {
|
||||
return (
|
||||
<Container>
|
||||
<em>ReviewPanelOverviewContainer</em>
|
||||
<div
|
||||
id="review-panel-overview"
|
||||
role="tabpanel"
|
||||
tabIndex={0}
|
||||
aria-labelledby="review-panel-tab-overview"
|
||||
>
|
||||
Faucibus turpis in eu mi bibendum. Proin libero nunc consequat interdum.
|
||||
Ac placerat vestibulum lectus mauris ultrices eros in cursus turpis. Ac
|
||||
felis donec et odio. Nullam ac tortor vitae purus faucibus. Consectetur
|
||||
lorem donec massa sapien faucibus et molestie. Praesent elementum
|
||||
facilisis leo vel fringilla est ullamcorper eget nulla. Adipiscing vitae
|
||||
proin sagittis nisl rhoncus mattis rhoncus urna. Cursus metus aliquam
|
||||
eleifend mi in nulla posuere sollicitudin aliquam. Eget nullam non nisi
|
||||
est sit amet facilisis magna. Donec adipiscing tristique risus nec
|
||||
feugiat in fermentum posuere. Gravida rutrum quisque non tellus orci ac
|
||||
auctor augue. Euismod in pellentesque massa placerat duis ultricies
|
||||
lacus. Pellentesque diam volutpat commodo sed egestas. Tempus iaculis
|
||||
urna id volutpat lacus laoreet. Lorem ipsum dolor sit amet consectetur.
|
||||
Tincidunt id aliquet risus feugiat in ante metus. Risus ultricies
|
||||
tristique nulla aliquet enim tortor at auctor urna. Purus in mollis nunc
|
||||
sed. In ante metus dictum at. Magna eget est lorem ipsum dolor sit.
|
||||
Fusce id velit ut tortor pretium viverra.
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from '../../context/review-panel/review-panel-context'
|
||||
import CurrentFileContainer from './current-file-container'
|
||||
import OverviewContainer from './overview-container'
|
||||
import { isCurrentFileView } from '../../utils/sub-view'
|
||||
|
||||
type ReviewPanelViewProps = {
|
||||
parentDomNode: Element
|
||||
@@ -16,7 +17,7 @@ function ReviewPanelView({ parentDomNode }: ReviewPanelViewProps) {
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
<>
|
||||
{subView === 'cur_file' ? (
|
||||
{isCurrentFileView(subView) ? (
|
||||
<CurrentFileContainer />
|
||||
) : (
|
||||
<OverviewContainer />
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useMemo, useCallback } from 'react'
|
||||
import useScopeValue from '../../../../../shared/hooks/use-scope-value'
|
||||
import { ReviewPanelState } from '../types/review-panel-state'
|
||||
import { sendMB } from '../../../../../infrastructure/event-tracking'
|
||||
import * as ReviewPanel from '../types/review-panel-state'
|
||||
import { SubView } from '../../../../../../../types/review-panel'
|
||||
|
||||
function useAngularReviewPanelState(): ReviewPanelState {
|
||||
const [subView, setSubView] = useScopeValue<ReviewPanel.Value<'subView'>>(
|
||||
@@ -50,6 +52,14 @@ function useAngularReviewPanelState(): ReviewPanelState {
|
||||
const [toggleReviewPanel] =
|
||||
useScopeValue<ReviewPanel.Value<'toggleReviewPanel'>>('toggleReviewPanel')
|
||||
|
||||
const handleSetSubview = useCallback(
|
||||
(subView: SubView) => {
|
||||
setSubView(subView)
|
||||
sendMB('rp-subview-change', { subView })
|
||||
},
|
||||
[setSubView]
|
||||
)
|
||||
|
||||
const values = useMemo<ReviewPanelState['values']>(
|
||||
() => ({
|
||||
collapsed,
|
||||
@@ -87,11 +97,11 @@ function useAngularReviewPanelState(): ReviewPanelState {
|
||||
|
||||
const updaterFns = useMemo<ReviewPanelState['updaterFns']>(
|
||||
() => ({
|
||||
setSubView,
|
||||
handleSetSubview,
|
||||
setCollapsed,
|
||||
setShouldCollapse,
|
||||
}),
|
||||
[setSubView, setCollapsed, setShouldCollapse]
|
||||
[handleSetSubview, setCollapsed, setShouldCollapse]
|
||||
)
|
||||
|
||||
return { values, updaterFns }
|
||||
|
||||
@@ -27,12 +27,10 @@ export interface ReviewPanelState {
|
||||
toggleReviewPanel: () => void
|
||||
}
|
||||
updaterFns: {
|
||||
handleSetSubview: (subView: SubView) => void
|
||||
setCollapsed: React.Dispatch<
|
||||
React.SetStateAction<ReviewPanelState['values']['collapsed']>
|
||||
>
|
||||
setSubView: React.Dispatch<
|
||||
React.SetStateAction<ReviewPanelState['values']['subView']>
|
||||
>
|
||||
setShouldCollapse: React.Dispatch<
|
||||
React.SetStateAction<ReviewPanelState['values']['shouldCollapse']>
|
||||
>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { SubView } from '../../../../../types/review-panel'
|
||||
|
||||
export const isCurrentFileView = (view: SubView) => view === 'cur_file'
|
||||
export const isOverviewView = (view: SubView) => view === 'overview'
|
||||
@@ -56,7 +56,7 @@
|
||||
}
|
||||
|
||||
.rp-collapse-arrow() {
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
transform: rotateZ(0deg);
|
||||
transition: transform 0.15s ease;
|
||||
&-on {
|
||||
@@ -1214,14 +1214,6 @@ button when (@is-overleaf-light = true) {
|
||||
box-sizing: content-box;
|
||||
flex-direction: column;
|
||||
|
||||
.review-panel-toolbar {
|
||||
& .review-panel-toolbar-collapse-button {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-toggler {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1235,6 +1227,22 @@ button when (@is-overleaf-light = true) {
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
.review-panel-toolbar-collapse-button {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.rp-nav {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.rp-state-current-file & {
|
||||
.review-panel-tools {
|
||||
display: flex;
|
||||
@@ -1246,19 +1254,9 @@ button when (@is-overleaf-light = true) {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.review-panel-toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.rp-nav {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.rp-state-overview {
|
||||
.rp-state-overview & {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
display: flex;
|
||||
@@ -1266,6 +1264,9 @@ button when (@is-overleaf-light = true) {
|
||||
}
|
||||
|
||||
.rp-nav-item {
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
border-left: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,4 +131,39 @@ describe('<ReviewPanel />', function () {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('navigation', function () {
|
||||
it('renders navigation', function () {
|
||||
cy.get('@review-panel').within(() => {
|
||||
cy.findByRole('tab', { name: /current file/i })
|
||||
cy.findByRole('tab', { name: /overview/i })
|
||||
})
|
||||
})
|
||||
|
||||
it('selects the active tab', function () {
|
||||
cy.get('@review-panel').within(() => {
|
||||
cy.findByRole('tab', { name: /current file/i }).should(
|
||||
'have.attr',
|
||||
'aria-selected',
|
||||
'true'
|
||||
)
|
||||
cy.findByRole('tab', { name: /overview/i }).should(
|
||||
'have.attr',
|
||||
'aria-selected',
|
||||
'false'
|
||||
)
|
||||
cy.findByRole('tab', { name: /overview/i }).click()
|
||||
cy.findByRole('tab', { name: /current file/i }).should(
|
||||
'have.attr',
|
||||
'aria-selected',
|
||||
'false'
|
||||
)
|
||||
cy.findByRole('tab', { name: /overview/i }).should(
|
||||
'have.attr',
|
||||
'aria-selected',
|
||||
'true'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user