History UI changes- Extracting compare outside dropdown menu

GitOrigin-RevId: 67f51428debefdafe2c9bb746de5da8fc0ac5385
This commit is contained in:
Davinder Singh 2023-08-17 14:30:21 +01:00 committed by Copybot
parent 28a7c13887
commit 3490f6a58e
12 changed files with 158 additions and 86 deletions

View file

@ -57,7 +57,8 @@ class TestServer {
})
this.app.get('/json/basic-auth', (req, res) => {
const expectedAuth = 'Basic ' + Buffer.from('user:pass').toString('base64')
const expectedAuth =
'Basic ' + Buffer.from('user:pass').toString('base64')
if (req.headers.authorization === expectedAuth) {
res.json({ key: 'verysecret' })
} else {

View file

@ -441,7 +441,6 @@
"history_adding_label": "",
"history_are_you_sure_delete_label": "",
"history_compare_from_this_version": "",
"history_compare_to_selected_version": "",
"history_compare_up_to_this_version": "",
"history_delete_label": "",
"history_deleting_label": "",

View file

@ -2,21 +2,16 @@ import Download from './menu-item/download'
import { Version } from '../../../services/types/update'
import { ActiveDropdown } from '../../../hooks/use-dropdown-active-item'
import { useCallback } from 'react'
import CompareItems from './menu-item/compare-items'
type LabelDropdownContentProps = {
projectId: string
version: Version
versionTimestamp: number
selected: boolean
closeDropdownForItem: ActiveDropdown['closeDropdownForItem']
}
function LabelDropdownContent({
projectId,
version,
versionTimestamp,
selected,
closeDropdownForItem,
}: LabelDropdownContentProps) {
const closeDropdown = useCallback(() => {
@ -30,16 +25,6 @@ function LabelDropdownContent({
version={version}
closeDropdown={closeDropdown}
/>
<CompareItems
updateRange={{
fromV: version,
toV: version,
fromVTimestamp: versionTimestamp,
toVTimestamp: versionTimestamp,
}}
selected={selected}
closeDropdown={closeDropdown}
/>
</>
)
}

View file

@ -19,16 +19,44 @@ function CompareItems({
const { t } = useTranslation()
const { selection } = useHistoryContext()
const { updateRange: selRange, comparing } = selection
const notASelectionBoundary =
// Comparing mode variables
const notASelectionBoundaryComparingMode =
!!selRange &&
comparing &&
updateRange.toV !== selRange.toV &&
updateRange.fromV !== selRange.fromV
const showCompareWithSelected = !comparing && !!selRange && !selected
const showCompareToThis =
notASelectionBoundary && updateRange.toV > selRange.fromV
const showCompareFromThis =
notASelectionBoundary && updateRange.fromV < selRange.toV
const showCompareToThisComparingMode =
notASelectionBoundaryComparingMode && updateRange.toV > selRange.toV
const showCompareFromThisComparingMode =
notASelectionBoundaryComparingMode && updateRange.fromV < selRange.fromV
// Normal mode variables
const notASelectionBoundaryNormalMode =
!!selRange &&
updateRange.toV !== selRange.toV &&
updateRange.fromV !== selRange.fromV
const showCompareToThisNormalMode =
notASelectionBoundaryNormalMode && updateRange.toV > selRange.toV
const showCompareFromThisNormalMode =
notASelectionBoundaryNormalMode && updateRange.fromV < selRange.fromV
let iconTypeNonSelectedVersion = ''
let toolTipDescriptionNonSelectedVersion = ''
if (showCompareToThisNormalMode) {
iconTypeNonSelectedVersion = 'align_start'
toolTipDescriptionNonSelectedVersion = t(
'history_compare_up_to_this_version'
)
}
if (showCompareFromThisNormalMode) {
iconTypeNonSelectedVersion = 'align_end'
toolTipDescriptionNonSelectedVersion = t(
'history_compare_from_this_version'
)
}
return (
<>
@ -36,10 +64,16 @@ function CompareItems({
<Compare
comparisonRange={updateRangeUnion(updateRange, selRange)}
closeDropdown={closeDropdown}
text={t('history_compare_to_selected_version')}
toolTipDescription={toolTipDescriptionNonSelectedVersion}
icon={
<MaterialIcon
type={iconTypeNonSelectedVersion}
className="material-symbols-rounded history-dropdown-icon p-1"
/>
}
/>
) : null}
{showCompareFromThis ? (
{showCompareFromThisComparingMode ? (
<Compare
comparisonRange={{
fromV: updateRange.fromV,
@ -48,11 +82,16 @@ function CompareItems({
toVTimestamp: selRange.toVTimestamp,
}}
closeDropdown={closeDropdown}
text={t('history_compare_from_this_version')}
icon={<MaterialIcon type="line_start_circle" className="fa-fw" />}
toolTipDescription={t('history_compare_from_this_version')}
icon={
<MaterialIcon
type="align_end"
className="material-symbols-rounded history-dropdown-icon p-1"
/>
}
/>
) : null}
{showCompareToThis ? (
{showCompareToThisComparingMode ? (
<Compare
comparisonRange={{
fromV: selRange.fromV,
@ -61,8 +100,13 @@ function CompareItems({
toVTimestamp: updateRange.toVTimestamp,
}}
closeDropdown={closeDropdown}
text={t('history_compare_up_to_this_version')}
icon={<MaterialIcon type="line_end_circle" className="fa-fw" />}
toolTipDescription={t('history_compare_up_to_this_version')}
icon={
<MaterialIcon
type="align_start"
className="material-symbols-rounded history-dropdown-icon p-1"
/>
}
/>
) : null}
</>

View file

@ -1,26 +1,27 @@
import { MenuItem, MenuItemProps } from 'react-bootstrap'
import Icon from '../../../../../../shared/components/icon'
import { useHistoryContext } from '../../../../context/history-context'
import { UpdateRange } from '../../../../services/types/update'
import { ReactNode } from 'react'
import Tooltip from '../../../../../../shared/components/tooltip'
import { Button } from 'react-bootstrap'
type CompareProps = {
comparisonRange: UpdateRange
text: string
icon?: ReactNode
toolTipDescription?: string
closeDropdown: () => void
}
function Compare({
comparisonRange,
text,
closeDropdown,
toolTipDescription,
icon = <Icon type="exchange" fw />,
...props
}: CompareProps) {
const { setSelection } = useHistoryContext()
const handleCompareVersion = (e: React.MouseEvent<MenuItemProps>) => {
const handleCompareVersion = (e: React.MouseEvent<Button>) => {
e.stopPropagation()
closeDropdown()
@ -33,9 +34,20 @@ function Compare({
}
return (
<MenuItem onClick={handleCompareVersion} {...props}>
{icon} {text}
</MenuItem>
<Tooltip
description={toolTipDescription}
id="compare-btn"
overlayProps={{ placement: 'left' }}
>
<Button
bsStyle="link"
className="history-compare-btn"
onClick={handleCompareVersion}
>
<span className="sr-only">{toolTipDescription}</span>
{icon}
</Button>
</Tooltip>
)
}

View file

@ -3,24 +3,18 @@ import Download from './menu-item/download'
import { LoadedUpdate } from '../../../services/types/update'
import { useCallback } from 'react'
import { ActiveDropdown } from '../../../hooks/use-dropdown-active-item'
import CompareItems from './menu-item/compare-items'
import { updateRangeForUpdate } from '../../../utils/history-details'
type VersionDropdownContentProps = {
projectId: string
update: LoadedUpdate
selected: boolean
closeDropdownForItem: ActiveDropdown['closeDropdownForItem']
}
function VersionDropdownContent({
projectId,
update,
selected,
closeDropdownForItem,
}: VersionDropdownContentProps) {
const updateRange = updateRangeForUpdate(update)
const closeDropdown = useCallback(() => {
closeDropdownForItem(update)
}, [closeDropdownForItem, update])
@ -37,11 +31,6 @@ function VersionDropdownContent({
version={update.toV}
closeDropdown={closeDropdown}
/>
<CompareItems
updateRange={updateRange}
selected={selected}
closeDropdown={closeDropdown}
/>
</>
)
}

View file

@ -10,9 +10,10 @@ import { LoadedUpdate } from '../../services/types/update'
import classNames from 'classnames'
import { updateRangeForUpdate } from '../../utils/history-details'
import { ActiveDropdown } from '../../hooks/use-dropdown-active-item'
import { memo } from 'react'
import { memo, useCallback } from 'react'
import { HistoryContextValue } from '../../context/types/history-context-value'
import VersionDropdownContent from './dropdown/version-dropdown-content'
import CompareItems from './dropdown/menu-item/compare-items'
type HistoryVersionProps = {
update: LoadedUpdate
@ -45,6 +46,12 @@ function HistoryVersion({
}: HistoryVersionProps) {
const orderedLabels = orderBy(update.labels, ['created_at'], ['desc'])
const closeDropdown = useCallback(() => {
closeDropdownForItem(update)
}, [closeDropdownForItem, update])
const updateRange = updateRangeForUpdate(update)
return (
<>
{showDivider ? <hr className="history-version-divider" /> : null}
@ -75,7 +82,6 @@ function HistoryVersion({
>
{dropdownActive ? (
<VersionDropdownContent
selected={selected}
update={update}
projectId={projectId}
closeDropdownForItem={closeDropdownForItem}
@ -83,6 +89,17 @@ function HistoryVersion({
) : null}
</HistoryDropdown>
)}
{!selected ? (
<span data-testid="compare-icon-version" className="pull-right">
<CompareItems
updateRange={updateRange}
selected={selected}
closeDropdown={closeDropdown}
/>
</span>
) : null}
<div className="history-version-main-details">
<time
className="history-version-metadata-time"

View file

@ -11,6 +11,7 @@ import { useTranslation } from 'react-i18next'
import { ActiveDropdown } from '../../hooks/use-dropdown-active-item'
import { HistoryContextValue } from '../../context/types/history-context-value'
import LabelDropdownContent from './dropdown/label-dropdown-content'
import CompareItems from './dropdown/menu-item/compare-items'
type LabelListItemProps = {
version: Version
@ -59,6 +60,9 @@ function LabelListItem({
},
[setActiveDropdownItem, version]
)
const closeDropdown = useCallback(() => {
closeDropdownForItem(version)
}, [closeDropdownForItem, version])
return (
<HistoryVersionDetails
@ -75,14 +79,24 @@ function LabelListItem({
>
{dropdownActive ? (
<LabelDropdownContent
selected={selected}
version={version}
versionTimestamp={toVTimestamp}
projectId={projectId}
closeDropdownForItem={closeDropdownForItem}
/>
) : null}
</HistoryDropdown>
<span className="pull-right">
<CompareItems
updateRange={{
fromV: version,
toV: version,
fromVTimestamp: toVTimestamp,
toVTimestamp,
}}
selected={selected}
closeDropdown={closeDropdown}
/>
</span>
<div className="history-version-main-details">
{labels.map(label => (
<div key={label.id} className="history-version-label">

View file

@ -375,6 +375,15 @@ history-root {
}
}
.history-dropdown-icon {
color: @neutral-90;
}
.history-compare-btn {
line-height: 1;
padding: 0;
}
.history-file-tree {
display: flex !important; // To work around jQuery layout's inline styles
flex-direction: column;

View file

@ -719,7 +719,6 @@
"history_adding_label": "Adding label",
"history_are_you_sure_delete_label": "Are you sure you want to delete the following label",
"history_compare_from_this_version": "Compare from this version",
"history_compare_to_selected_version": "Compare to selected version",
"history_compare_up_to_this_version": "Compare up to this version",
"history_delete_label": "Delete label",
"history_deleting_label": "Deleting label",

View file

@ -332,14 +332,10 @@ describe('change list', function () {
cy.findAllByTestId('history-version-details')
.eq(1)
.within(() => {
cy.findByRole('button', { name: /more actions/i }).click()
cy.findByRole('menu').within(() => {
cy.findByRole('menuitem', {
name: /compare to selected version/i,
}).click()
})
cy.findByRole('button', {
name: /Compare/i,
}).click()
})
cy.wait('@diff')
cy.findByLabelText(/all history/i).click({ force: true })
cy.findAllByTestId('history-version-details').should($versions => {
const [first, ...rest] = Array.from($versions)
@ -350,6 +346,40 @@ describe('change list', function () {
})
})
describe('compare mode', function () {
beforeEach(function () {
mountWithEditorProviders(<ChangeList />, scope, {
user: {
id: USER_ID,
email: USER_EMAIL,
isAdmin: true,
},
})
waitForData()
})
it('compares versions', function () {
cy.findAllByTestId('history-version-details').should($versions => {
const [first, ...rest] = Array.from($versions)
expect(first).to.have.attr('data-selected', 'true')
rest.forEach(version =>
expect(version).to.have.attr('data-selected', 'false')
)
})
cy.intercept('GET', '/project/*/filetree/diff*', {
body: { diff: [{ pathname: 'main.tex' }, { pathname: 'name.tex' }] },
}).as('compareDiff')
cy.findAllByTestId('history-version-details')
.last()
.within(() => {
cy.findByTestId('compare-icon-version').click()
})
cy.wait('@compareDiff')
})
})
describe('dropdown', function () {
beforeEach(function () {
mountWithEditorProviders(<ChangeList />, scope, {
@ -421,33 +451,6 @@ describe('change list', function () {
})
cy.wait('@download')
})
it('compares versions', function () {
cy.findAllByTestId('history-version-details').should($versions => {
const [first, ...rest] = Array.from($versions)
expect(first).to.have.attr('data-selected', 'true')
rest.forEach(version =>
expect(version).to.have.attr('data-selected', 'false')
)
})
cy.intercept('GET', '/project/*/filetree/diff*', {
body: { diff: [{ pathname: 'main.tex' }, { pathname: 'name.tex' }] },
}).as('compareDiff')
cy.findAllByTestId('history-version-details')
.last()
.within(() => {
cy.findByRole('button', { name: /more actions/i }).click()
cy.findByRole('menu').within(() => {
cy.findByRole('menuitem', {
name: /compare to selected version/i,
}).click()
})
})
cy.wait('@compareDiff')
})
})
describe('paywall', function () {