iterative/vscode-dvc

View on GitHub
webview/src/plots/components/comparisonTable/ComparisonTableHead.tsx

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import React, { createRef, useEffect } from 'react'
import { Revision } from 'dvc/src/plots/webview/contract'
import { useSelector } from 'react-redux'
import styles from './styles.module.scss'
import { ComparisonTableHeader } from './ComparisonTableHeader'
import { PlotsState } from '../../store'

export type ComparisonTableColumn = Revision

const POSITION_ADJUSTMENTS = 51 - 4 // 4 is equal to the gap in the comparison table and 51 is the height of the section header

const setHeaderTop = (head: HTMLTableSectionElement, top: number) => {
  for (const header of head.firstChild?.childNodes || []) {
    ;(header as HTMLTableCellElement).style.top = `${top}px`
  }
}
interface ComparisonTableHeadProps {
  columns: ComparisonTableColumn[]
  pinnedColumn: string
  setColumnsOrder: (columns: string[]) => void
  setPinnedColumn: (column: string) => void
}

export const ComparisonTableHead: React.FC<ComparisonTableHeadProps> = ({
  columns,
  pinnedColumn,
  setColumnsOrder,
  setPinnedColumn
}) => {
  const ribbonHeight = useSelector((state: PlotsState) => state.ribbon.height)
  const headRef = createRef<HTMLTableSectionElement>()

  useEffect(() => {
    const adjustedRibbonHeight = ribbonHeight + POSITION_ADJUSTMENTS
    const calculateTop = () => {
      if (headRef.current) {
        const headerPosition = headRef.current.getBoundingClientRect().top
        const top =
          headerPosition - POSITION_ADJUSTMENTS < 0
            ? adjustedRibbonHeight - headerPosition
            : 0
        setHeaderTop(headRef.current, top)
      }
    }

    window.addEventListener('scroll', calculateTop)

    return () => {
      window.removeEventListener('scroll', calculateTop)
    }
  }, [ribbonHeight, headRef])

  const items = columns.map(
    ({ label, id, displayColor, description, commit }) => {
      return (
        <ComparisonTableHeader
          key={id}
          pinnedColumn={pinnedColumn}
          onClicked={() => setPinnedColumn(id)}
          displayColor={displayColor}
          id={id}
          order={columns.map(col => col.id)}
          setOrder={setColumnsOrder}
        >
          {label}
          {!commit && description && (
            <span className={styles.experimentName}>{description}</span>
          )}
        </ComparisonTableHeader>
      )
    }
  )

  return (
    <thead data-testid="comparison-table-head" ref={headRef}>
      <tr>{items}</tr>
    </thead>
  )
}