diff --git a/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx b/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx index baad57a06c..547f529448 100644 --- a/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx +++ b/services/web/frontend/js/features/history/components/change-list/all-history-list.tsx @@ -99,7 +99,11 @@ function AllHistoryList() { const faded = updatesInfo.freeHistoryLimitHit && index === visibleUpdates.length - 1 - const selectable = !faded && (selection.comparing || !selected) + const selectable = + !faded && + (selection.comparing || + selected === 'aboveSelected' || + selected === 'belowSelected') return ( void } @@ -18,62 +18,14 @@ function CompareItems({ }: CompareItemsProps) { const { t } = useTranslation() const { selection } = useHistoryContext() - const { updateRange: selRange, comparing } = selection - - // Comparing mode variables - const notASelectionBoundaryComparingMode = - !!selRange && - comparing && - updateRange.toV !== selRange.toV && - updateRange.fromV !== selRange.fromV - const showCompareWithSelected = !comparing && !!selRange && !selected - 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' - ) + const { updateRange: selRange } = selection + if (selRange === null) { + return null } return ( <> - {showCompareWithSelected ? ( - - } - /> - ) : null} - {showCompareFromThisComparingMode ? ( + {selected === 'belowSelected' ? ( ) : null} - {showCompareToThisComparingMode ? ( + {selected === 'aboveSelected' ? ( - {showDivider ?
: null} + {showDivider ? ( +
+
+
+ ) : null} {update.meta.first_in_day ? ( - +
+ +
) : null}
)} - {!selected ? ( + {selected !== 'selected' ? ( - + {selected !== 'withinSelected' ? ( + + ) : null} ) : null} diff --git a/services/web/frontend/js/features/history/components/change-list/label-list-item.tsx b/services/web/frontend/js/features/history/components/change-list/label-list-item.tsx index 194c54df76..54de760715 100644 --- a/services/web/frontend/js/features/history/components/change-list/label-list-item.tsx +++ b/services/web/frontend/js/features/history/components/change-list/label-list-item.tsx @@ -12,13 +12,14 @@ 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' +import { ItemSelectionState } from '../../utils/history-details' type LabelListItemProps = { version: Version labels: LoadedLabel[] currentUserId: string projectId: string - selected: boolean + selected: ItemSelectionState selectable: boolean setSelection: HistoryContextValue['setSelection'] dropdownOpen: boolean diff --git a/services/web/frontend/js/features/history/components/change-list/labels-list.tsx b/services/web/frontend/js/features/history/components/change-list/labels-list.tsx index 3461fdb73c..b2e5cc943b 100644 --- a/services/web/frontend/js/features/history/components/change-list/labels-list.tsx +++ b/services/web/frontend/js/features/history/components/change-list/labels-list.tsx @@ -1,7 +1,6 @@ import { useUserContext } from '../../../../shared/context/user-context' import { isVersionSelected } from '../../utils/history-details' import { useMemo } from 'react' -import { Version } from '../../services/types/update' import LabelListItem from './label-list-item' import useDropdownActiveItem from '../../hooks/use-dropdown-active-item' import { getVersionWithLabels } from '../../utils/label' @@ -18,18 +17,10 @@ function LabelsList() { [labels] ) - const selectedVersions = new Set( - Array.from(versionWithLabels.values(), value => value.version).filter( - version => isVersionSelected(selection, version) - ) - ) - - const singleVersionSelected = selectedVersions.size === 1 - return ( <> {versionWithLabels.map(({ version, labels }) => { - const selected = selectedVersions.has(version) + const selected = isVersionSelected(selection, version) const dropdownActive = version === activeDropdownItem.item return ( @@ -40,7 +31,7 @@ function LabelsList() { currentUserId={currentUserId} projectId={projectId} selected={selected} - selectable={!(singleVersionSelected && selected)} + selectable={selected !== 'selected'} setSelection={setSelection} dropdownOpen={activeDropdownItem.isOpened && dropdownActive} dropdownActive={dropdownActive} diff --git a/services/web/frontend/js/features/history/utils/history-details.ts b/services/web/frontend/js/features/history/utils/history-details.ts index 4ce57e78bc..46327707e6 100644 --- a/services/web/frontend/js/features/history/utils/history-details.ts +++ b/services/web/frontend/js/features/history/utils/history-details.ts @@ -37,36 +37,78 @@ export const getProjectOpDoc = (projectOp: ProjectOp) => { return '' } +export type ItemSelectionState = + | 'selectedEdge' + | 'withinSelected' + | 'aboveSelected' + | 'belowSelected' + | 'selected' + | null + export function isVersionSelected( selection: Selection, version: Version -): boolean +): ItemSelectionState // eslint-disable-next-line no-redeclare export function isVersionSelected( selection: Selection, fromV: Version, toV: Version -): boolean +): ItemSelectionState // eslint-disable-next-line no-redeclare export function isVersionSelected( selection: Selection, ...args: [Version] | [Version, Version] -): boolean { +): ItemSelectionState { if (selection.updateRange) { let [fromV, toV] = args toV = toV ?? fromV - if (selection.comparing) { - // compare mode - return ( - fromV >= selection.updateRange.fromV && toV <= selection.updateRange.toV - ) - } else { + if ( + fromV > selection.updateRange.fromV && + toV < selection.updateRange.toV + ) { + return 'withinSelected' + } + + // Condition for selectedEdge when the comparing versions are from labels list + if (fromV === toV) { + if ( + toV === selection.updateRange.fromV || + fromV === selection.updateRange.toV + ) { + return 'selectedEdge' + } + } + + // Comparing mode above selected condition + if (fromV >= selection.updateRange.toV) { + return 'aboveSelected' + } + // Comparing mode below selected condition + if (toV <= selection.updateRange.fromV) { + return 'belowSelected' + } + + if ( + fromV === selection.updateRange.fromV || + toV === selection.updateRange.toV + ) { + return 'selectedEdge' + } + } else if (toV === selection.updateRange.toV) { // single version mode - return toV === selection.updateRange.toV + return 'selected' + } else if (fromV >= selection.updateRange.toV) { + // Non-Comparing mode above selected condition + return 'aboveSelected' + } else if (toV <= selection.updateRange.fromV) { + // Non-Comparing mode below selected condition + return 'belowSelected' } } - return false + + return null } export const getUpdateForVersion = (version: number, updates: LoadedUpdate[]) => diff --git a/services/web/frontend/stylesheets/app/editor/history-react.less b/services/web/frontend/stylesheets/app/editor/history-react.less index 4042f69e89..82a8e79970 100644 --- a/services/web/frontend/stylesheets/app/editor/history-react.less +++ b/services/web/frontend/stylesheets/app/editor/history-react.less @@ -90,7 +90,6 @@ history-root { padding-top: 12px; padding-bottom: 4px; line-height: 20px; - background-color: @white; } .history-version-details { @@ -106,10 +105,34 @@ history-root { } } - &.history-version-selected, - &.history-version-selected.history-version-selectable:hover { + &.history-version-selected { background-color: @green-10; + border-left: 3px solid @green-50; } + + &.history-version-selected.history-version-selectable:hover { + background-color: fade(@green-70, 16%); + border-left: 3px solid @green-50; + } + + &.history-version-within-selected { + background-color: @neutral-10; + border-left: 3px solid @green-50; + } + + &.history-version-within-selected:hover { + background-color: fade(@neutral-90, 8%); + } + } + + .version-element-within-selected { + background-color: @neutral-10; + border-left: 3px solid @green-50; + } + + .version-element-selected { + background-color: @green-10; + border-left: 3px solid @green-50; } .history-version-metadata-time { @@ -176,8 +199,12 @@ history-root { overflow-wrap: anywhere; } + .history-version-divider-container { + padding: 6px 8px; + } + .history-version-divider { - margin: 6px 8px; + margin: 0px; border-color: @neutral-20; } @@ -384,6 +411,11 @@ history-root { padding: 0; } +.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; diff --git a/services/web/frontend/stylesheets/core/variables.less b/services/web/frontend/stylesheets/core/variables.less index aefea2d89f..f14ea5c2b2 100644 --- a/services/web/frontend/stylesheets/core/variables.less +++ b/services/web/frontend/stylesheets/core/variables.less @@ -44,6 +44,8 @@ @blueDark: #040d2d; @green: #46a546; @green-10: #ebf6ea; +@green-50: #138a07; +@green-70: #1f5919; @green-30: #8cca86; @red: #a93529; @yellow: #a1a729; diff --git a/services/web/test/frontend/features/history/components/change-list.spec.tsx b/services/web/test/frontend/features/history/components/change-list.spec.tsx index 82b17d2f87..aa4d829aa9 100644 --- a/services/web/test/frontend/features/history/components/change-list.spec.tsx +++ b/services/web/test/frontend/features/history/components/change-list.spec.tsx @@ -339,9 +339,14 @@ describe('change list', function () { cy.findByLabelText(/all history/i).click({ force: true }) cy.findAllByTestId('history-version-details').should($versions => { const [first, ...rest] = Array.from($versions) - expect(first.dataset.selected === 'true').to.be.true - expect(rest.every(version => version.dataset.selected === 'false')).to - .be.true + expect(first.dataset.selected === 'selected').to.be.true + expect( + rest.every( + version => + version.dataset.selected === 'belowSelected' || + version.dataset.selected === 'aboveSelected' + ) + ).to.be.true }) }) }) @@ -361,9 +366,11 @@ describe('change list', function () { 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') + expect(first).to.have.attr('data-selected', 'selected') rest.forEach(version => - expect(version).to.have.attr('data-selected', 'false') + // Based on the fact that we are selecting first version as we load the page + // Every other version will be belowSelected + expect(version).to.have.attr('data-selected', 'belowSelected') ) })