import React, { useEffect, useMemo } from 'react' import { Divider, PopoverInteractionKind, Position } from '@blueprintjs/core' import { Checkbox, Container, FlexExpander, Layout, Popover, Text } from '@harnessio/uicore' import { Color, FontVariation } from '@harnessio/design-system' import ReactTimeago from 'react-timeago' import { useStrings } from 'framework/strings' import type { TypesCommit } from 'services/code' import css from '../Changes.module.scss' type CommitRangeDropdownProps = { allCommits: TypesCommit[] selectedCommits: string[] setSelectedCommits: React.Dispatch> } const sortSelectedCommits = (selectedCommits: string[], sortedCommits: string[]) => { return selectedCommits.sort((commitA, commitB) => { const commitAIdx = sortedCommits.indexOf(commitA) const commitBIdx = sortedCommits.indexOf(commitB) return commitBIdx - commitAIdx }) } function getBiggerSubarray(array: Array, index: number) { if (index >= 0 && index < array.length) { const subarray1 = array.slice(0, index) const subarray2 = array.slice(index + 1) return subarray1.length > subarray2.length ? subarray1 : subarray2 } else { return [] } } const getCommitRange = (selectedCommits: string[], allCommitsSHA: string[]) => { const sortedCommits = sortSelectedCommits(selectedCommits, allCommitsSHA) const selectedCommitRange = allCommitsSHA .slice(allCommitsSHA.indexOf(sortedCommits[sortedCommits.length - 1]), allCommitsSHA.indexOf(sortedCommits[0]) + 1) .reverse() return selectedCommitRange } const CommitRangeDropdown: React.FC = ({ allCommits, selectedCommits, setSelectedCommits }) => { const { getString } = useStrings() const allCommitsSHA = useMemo(() => allCommits.map(commit => commit.sha as string), [allCommits]) useEffect(() => { if (selectedCommits.length && allCommitsSHA.length) { setSelectedCommits(prevVal => getCommitRange(prevVal, allCommitsSHA)) } }, [allCommitsSHA, setSelectedCommits, selectedCommits.length]) const handleCheckboxClick = ( event: React.MouseEvent, selectedCommitSHA: string ) => { if (event.shiftKey) { // Select Commit setSelectedCommits(current => { if (current.includes(selectedCommitSHA)) { // If Commit is Selected, return the bigger Sub Array const sortedCommits = sortSelectedCommits(current, allCommitsSHA) const subArray = getBiggerSubarray(sortedCommits, sortedCommits.indexOf(selectedCommitSHA)) return subArray } else { // If a Non Consecutive Commit is Selected, Select the Range instead. if (current.length >= 1) { // If a All Commits are Selected, Clear the Range. if (current.length + 1 === allCommits.length) { return [] } const selectedCommitRange = getCommitRange([...current, selectedCommitSHA], allCommitsSHA) return selectedCommitRange } else { // When the First Commit is Selected. return [selectedCommitSHA] } } }) } else { // If a Single Commit is Clicked setSelectedCommits([selectedCommitSHA]) } } const areAllCommitsSelected = !selectedCommits.length return ( setSelectedCommits(selectedCommits)} content={ {getString('allCommits')}} checked={areAllCommitsSelected} onClick={() => setSelectedCommits([])} margin={{ bottom: 'small' }} /> {allCommits?.map((prCommit, index) => { const isSelected = selectedCommits.includes(prCommit.sha || '') return ( handleCheckboxClick(e, prCommit.sha as string)}> handleCheckboxClick(e, prCommit.sha as string)} /> {`${allCommits.length - index} ${prCommit.title}`} ) })} {getString('selectRange')} }> {selectedCommits.length && selectedCommits.length !== allCommitsSHA.length ? `${selectedCommits.length} ${selectedCommits.length > 1 ? getString('commits') : getString('commit')}` : getString('allCommits')} ) } export default CommitRangeDropdown