diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index ce299d26c8..c75cb12634 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -401,7 +401,9 @@ "history_add_label": "", "history_adding_label": "", "history_are_you_sure_delete_label": "", - "history_compare_with_this_version": "", + "history_compare_from_this_version": "", + "history_compare_to_selected_version": "", + "history_compare_to_this_version": "", "history_delete_label": "", "history_deleting_label": "", "history_download_this_version": "", 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 d031b608e5..baad57a06c 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,6 +99,7 @@ function AllHistoryList() { const faded = updatesInfo.freeHistoryLimitHit && index === visibleUpdates.length - 1 + const selectable = !faded && (selection.comparing || !selected) return ( { @@ -32,15 +30,16 @@ function LabelDropdownContent({ version={version} closeDropdown={closeDropdown} /> - {!comparing && !selected && ( - - )} + ) } diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare-items.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare-items.tsx new file mode 100644 index 0000000000..fac9d2ac51 --- /dev/null +++ b/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare-items.tsx @@ -0,0 +1,69 @@ +import { useTranslation } from 'react-i18next' +import { useHistoryContext } from '../../../../context/history-context' +import { UpdateRange } from '../../../../services/types/update' +import Compare from './compare' +import { updateRangeUnion } from '../../../../utils/range' + +type CompareItemsProps = { + updateRange: UpdateRange + selected: boolean + closeDropdown: () => void +} + +function CompareItems({ + updateRange, + selected, + closeDropdown, +}: CompareItemsProps) { + const { t } = useTranslation() + const { selection } = useHistoryContext() + const { updateRange: selRange, comparing } = selection + const notASelectionBoundary = + !!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 + + return ( + <> + {showCompareWithSelected ? ( + + ) : null} + {showCompareToThis ? ( + + ) : null} + {showCompareFromThis ? ( + + ) : null} + + ) +} + +export default CompareItems diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare.tsx index 5411cda52f..5f791447ef 100644 --- a/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare.tsx +++ b/services/web/frontend/js/features/history/components/change-list/dropdown/menu-item/compare.tsx @@ -1,56 +1,36 @@ -import { useTranslation } from 'react-i18next' import { MenuItem, MenuItemProps } from 'react-bootstrap' import Icon from '../../../../../../shared/components/icon' import { useHistoryContext } from '../../../../context/history-context' -import { computeUpdateRange } from '../../../../utils/range' import { UpdateRange } from '../../../../services/types/update' type CompareProps = { - projectId: string - updateMetaEndTimestamp: number + comparisonRange: UpdateRange + text: string closeDropdown: () => void -} & Pick +} function Compare({ - projectId, - fromV, - toV, - updateMetaEndTimestamp, + comparisonRange, + text, closeDropdown, ...props }: CompareProps) { - const { t } = useTranslation() const { setSelection } = useHistoryContext() const handleCompareVersion = (e: React.MouseEvent) => { e.stopPropagation() closeDropdown() - setSelection(prevSelection => { - const { updateRange } = prevSelection - - if (updateRange) { - const range = computeUpdateRange( - updateRange, - fromV, - toV, - updateMetaEndTimestamp - ) - - return { - updateRange: range, - comparing: true, - files: [], - } - } - - return prevSelection + setSelection({ + updateRange: comparisonRange, + comparing: true, + files: [], }) } return ( - {t('history_compare_with_this_version')} + {text} ) } diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/version-dropdown-content.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/version-dropdown-content.tsx index 72cd929f7c..673259ad5a 100644 --- a/services/web/frontend/js/features/history/components/change-list/dropdown/version-dropdown-content.tsx +++ b/services/web/frontend/js/features/history/components/change-list/dropdown/version-dropdown-content.tsx @@ -1,15 +1,15 @@ import AddLabel from './menu-item/add-label' import Download from './menu-item/download' -import Compare from './menu-item/compare' 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 - comparing: boolean closeDropdownForItem: ActiveDropdown['closeDropdownForItem'] } @@ -17,9 +17,10 @@ function VersionDropdownContent({ projectId, update, selected, - comparing, closeDropdownForItem, }: VersionDropdownContentProps) { + const updateRange = updateRangeForUpdate(update) + const closeDropdown = useCallback(() => { closeDropdownForItem(update) }, [closeDropdownForItem, update]) @@ -36,15 +37,11 @@ function VersionDropdownContent({ version={update.toV} closeDropdown={closeDropdown} /> - {!comparing && !selected && ( - - )} + ) } diff --git a/services/web/frontend/js/features/history/components/change-list/history-version.tsx b/services/web/frontend/js/features/history/components/change-list/history-version.tsx index 5d330383f8..f520768097 100644 --- a/services/web/frontend/js/features/history/components/change-list/history-version.tsx +++ b/services/web/frontend/js/features/history/components/change-list/history-version.tsx @@ -18,7 +18,7 @@ type HistoryVersionProps = { update: LoadedUpdate currentUserId: string projectId: string - comparing: boolean + selectable: boolean faded: boolean showDivider: boolean selected: boolean @@ -33,7 +33,7 @@ function HistoryVersion({ update, currentUserId, projectId, - comparing, + selectable, faded, showDivider, selected, @@ -44,7 +44,6 @@ function HistoryVersion({ closeDropdownForItem, }: HistoryVersionProps) { const orderedLabels = orderBy(update.labels, ['created_at'], ['desc']) - const selectable = !faded && (comparing || !selected) return ( <> @@ -99,7 +98,6 @@ function HistoryVersion({ > {dropdownActive ? ( {dropdownActive ? ( 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 7b16034370..3461fdb73c 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 @@ -39,7 +39,6 @@ function LabelsList() { version={version} currentUserId={currentUserId} projectId={projectId} - comparing={selection.comparing} selected={selected} selectable={!(singleVersionSelected && selected)} setSelection={setSelection} diff --git a/services/web/frontend/js/features/history/components/change-list/toggle-switch.tsx b/services/web/frontend/js/features/history/components/change-list/toggle-switch.tsx index 85c6b206f9..11597ef496 100644 --- a/services/web/frontend/js/features/history/components/change-list/toggle-switch.tsx +++ b/services/web/frontend/js/features/history/components/change-list/toggle-switch.tsx @@ -1,9 +1,12 @@ import { useTranslation } from 'react-i18next' import { useHistoryContext } from '../../context/history-context' -import { getUpdateForVersion } from '../../utils/history-details' -import { computeUpdateRange } from '../../utils/range' +import { + getUpdateForVersion, + updateRangeForUpdate, +} from '../../utils/history-details' import { isAnyVersionMatchingSelection } from '../../utils/label' import { HistoryContextValue } from '../../context/types/history-context-value' +import { updateRangeUnion } from '../../utils/range' type ToggleSwitchProps = Pick< HistoryContextValue, @@ -28,22 +31,19 @@ function ToggleSwitch({ labelsOnly, setLabelsOnly }: ToggleSwitchProps) { // in labels only mode the `fromV` is equal to `toV` value // switching to all history mode and triggering immediate comparison with // an older version would cause a bug if the computation below is skipped. - const update = selection.updateRange?.toV - ? getUpdateForVersion(selection.updateRange.toV, updatesInfo.updates) - : null - const { updateRange } = selection + const update = updateRange?.toV + ? getUpdateForVersion(updateRange.toV, updatesInfo.updates) + : null if ( updateRange && update && (update.fromV !== updateRange.fromV || update.toV !== updateRange.toV) ) { - const range = computeUpdateRange( - updateRange, - update.fromV, - update.toV, - update.meta.end_ts + const range = updateRangeUnion( + updateRangeForUpdate(update), + updateRange ) setSelection({ diff --git a/services/web/frontend/js/features/history/utils/range.ts b/services/web/frontend/js/features/history/utils/range.ts index 5cf845fdbe..b0a10bfb2d 100644 --- a/services/web/frontend/js/features/history/utils/range.ts +++ b/services/web/frontend/js/features/history/utils/range.ts @@ -1,26 +1,19 @@ import { UpdateRange } from '../services/types/update' -export const computeUpdateRange = ( - updateRange: UpdateRange, - fromV: number, - toV: number, - updateMetaEndTimestamp: number +export const updateRangeUnion = ( + updateRange1: UpdateRange, + updateRange2: UpdateRange ) => { - const fromVersion = Math.min(fromV, updateRange.fromV) - const toVersion = Math.max(toV, updateRange.toV) - const fromVTimestamp = Math.min( - updateMetaEndTimestamp, - updateRange.fromVTimestamp - ) - const toVTimestamp = Math.max( - updateMetaEndTimestamp, - updateRange.toVTimestamp - ) - return { - fromV: fromVersion, - toV: toVersion, - fromVTimestamp, - toVTimestamp, + fromV: Math.min(updateRange1.fromV, updateRange2.fromV), + toV: Math.max(updateRange1.toV, updateRange2.toV), + fromVTimestamp: Math.min( + updateRange1.fromVTimestamp, + updateRange2.fromVTimestamp + ), + toVTimestamp: Math.max( + updateRange1.toVTimestamp, + updateRange2.toVTimestamp + ), } } diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 7266a620df..69b241317f 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -682,7 +682,9 @@ "history_add_label": "Add label", "history_adding_label": "Adding label", "history_are_you_sure_delete_label": "Are you sure you want to delete the following label", - "history_compare_with_this_version": "Compare with this version", + "history_compare_from_this_version": "Compare from this version", + "history_compare_to_selected_version": "Compare to selected version", + "history_compare_to_this_version": "Compare to this version", "history_delete_label": "Delete label", "history_deleting_label": "Deleting label", "history_download_this_version": "Download this version",