Skip to content

Commit

Permalink
4001 - Datatable use Datagrid - Editable borders corrections (#4230)
Browse files Browse the repository at this point in the history
* 4001 - Move grid utils to DataGrid

* 4001 - Correct cell border rendering when adjacent cells are non-editable

* 4001 - Rename vars to lastEditableRow and lastEditableCol

* 4001 - Put editable border scss vars together
  • Loading branch information
yaguzmang authored Jan 21, 2025
1 parent ea2d8f4 commit 970364e
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { CSVLink } from 'react-csv'
import { useIsDataLocked } from 'client/store/ui/dataLock'
import { useIsPrintRoute } from 'client/hooks/useIsRoute'
import { ButtonProps, useButtonClassName } from 'client/components/Buttons/Button'
import { getDataGridData } from 'client/components/DataGrid/utils'
import Icon from 'client/components/Icon'

import { useFilename } from './hooks/useFilename'
import * as Utils from './utils'

type Props = Pick<ButtonProps, 'size'> & {
disabled?: boolean
Expand Down Expand Up @@ -35,7 +35,7 @@ const ButtonGridExport: React.FC<Props> = (props) => {
data={data}
filename={`${filename}.csv`}
onClick={(_, done) => {
setData(Utils.getDataGridData(gridRef.current))
setData(getDataGridData(gridRef.current))
done()
}}
target="_blank"
Expand Down
7 changes: 5 additions & 2 deletions src/client/components/DataGrid/DataCell/DataCell.scss
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@ $highlight-top-bottom: inset 0 1px $ui-accent, inset 0 -1px $ui-accent;
border-left: $border-editable;
border-top: $border-editable;

&.lastCol {
&.lastCol,
&.lastEditableCol {
border-right: $border-editable;
}

&.lastEditableRow,
&.lastRow {
border-bottom: $border-editable;
}
Expand Down Expand Up @@ -156,7 +158,8 @@ $highlight-top-bottom: inset 0 1px $ui-accent, inset 0 -1px $ui-accent;
border-left: unset;
border-right: $border-editable;

&.lastCol {
&.lastCol,
&.lastEditableCol {
border-left: $border-editable;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,25 @@ const _getCellSpans = (props: {
return { colSpan, rowSpan }
}

type DataRow = Array<string | null>
type TableData = Array<DataRow>
type DataRow<T> = Array<T | null>
type GridData<T extends Element | string> = Array<DataRow<T>>

export const getDataGridData = (grid: HTMLDivElement): TableData => {
export const getDataGridElementMatrix = (grid: HTMLDivElement): GridData<Element> => {
if (!grid) {
return []
}
const gridStyle = getComputedStyle(grid)
const columnCount = gridStyle.getPropertyValue('grid-template-columns').split(' ').length
const rowCount = gridStyle.getPropertyValue('grid-template-rows').split(' ').length

const data: TableData = Array.from({ length: rowCount }, () => new Array(columnCount).fill(null))
const elementMatrix: GridData<Element> = Array.from({ length: rowCount }, () => new Array(columnCount).fill(null))

const cells = Array.from(grid.children)

const findNextAvailablePosition = (): { row: number; col: number } | null => {
for (let row = 0; row < data.length; row += 1) {
for (let col = 0; col < data[row].length; col += 1) {
if (Objects.isNil(data[row][col])) {
for (let row = 0; row < elementMatrix.length; row += 1) {
for (let col = 0; col < elementMatrix[row].length; col += 1) {
if (Objects.isNil(elementMatrix[row][col])) {
return { col, row }
}
}
Expand All @@ -95,31 +95,57 @@ export const getDataGridData = (grid: HTMLDivElement): TableData => {
if (Objects.isNil(nextAvailablePosition)) return
const { col, row } = nextAvailablePosition

const isNoticeMessage = cell.classList.contains('table-grid__notice-message-cell')

let cellContent = _getElementText(cell as HTMLElement)
const spaceFreeContent = cellContent.replace(/\s/g, '')
cellContent =
Number.isNaN(Number.parseFloat(spaceFreeContent)) || Number.isNaN(Number(spaceFreeContent))
? cellContent
: spaceFreeContent

const { rowSpan, colSpan } = _getCellSpans({ cell, columnCount, rowCount })

for (let r = row; r < row + rowSpan && r < rowCount; r += 1) {
for (let c = col; c < col + colSpan && c < columnCount; c += 1) {
// Place notice message only in the first cell of the row
if (isNoticeMessage) {
if (r === row && c === col) {
data[r][c] = cellContent
} else {
data[r][c] = ''
}
elementMatrix[r][c] = cell
}
}
})

return elementMatrix
}

export const getDataGridData = (grid: HTMLDivElement): GridData<string> => {
if (!grid) {
return []
}
const elementMatrix = getDataGridElementMatrix(grid)

const rowCount = elementMatrix.length
const columnCount = elementMatrix[0]?.length || 0
const data: GridData<string> = Array.from({ length: rowCount }, () => new Array(columnCount).fill(null))

elementMatrix.forEach((row, rowIndex) => {
let noticeMessageAdded = false

row.forEach((cell, colIndex) => {
if (Objects.isEmpty(cell)) {
data[rowIndex][colIndex] = ''
return
}

const isNoticeMessage = cell.classList.contains('table-grid__notice-message-cell')

let cellContent = _getElementText(cell as HTMLElement)
const spaceFreeContent = cellContent.replace(/\s/g, '')
cellContent =
Number.isNaN(Number.parseFloat(spaceFreeContent)) || Number.isNaN(Number(spaceFreeContent))
? cellContent
: spaceFreeContent

if (isNoticeMessage) {
if (!noticeMessageAdded) {
data[rowIndex][colIndex] = cellContent
noticeMessageAdded = true
} else {
data[r][c] = cellContent
data[rowIndex][colIndex] = ''
}
} else {
data[rowIndex][colIndex] = cellContent
}
}
})
})

return data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { TableNames } from 'meta/assessment'

import { useUser } from 'client/store/user'
import { useCycleRouteParams } from 'client/hooks/useRouteParams'
import { getDataGridData } from 'client/components/DataGrid/ButtonGridExport/utils'
import { getDataGridData } from 'client/components/DataGrid/utils'
import { CopyValuesProps } from 'client/pages/Section/DataTable/Table/ButtonCopyValues/types'

// Cycle -> Table name -> Variables to be coppied to clipboard
Expand Down
2 changes: 2 additions & 0 deletions src/client/pages/Section/DataTable/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import GridHeadCell from 'client/pages/Section/DataTable/Table/GridHeadCell'
import RowData from 'client/pages/Section/DataTable/Table/RowData'
import RowNoticeMessage from 'client/pages/Section/DataTable/Table/RowNoticeMessage'

import { useCellBorderCorrection } from './hooks/useCellBorderCorrection'
import { useGridTemplateColumns } from './hooks/useGridTemplateColumns'
import { useParsedTable } from './hooks/useParsedTable'
import DataValidations from './DataValidations'
Expand Down Expand Up @@ -46,6 +47,7 @@ const Table: React.FC<Props> = (props) => {
})

const gridTemplateColumns = useGridTemplateColumns({ headers, table })
useCellBorderCorrection({ disabled, gridRef, rowsData, rowsHeader })

const canViewReview = useCanViewReview(sectionName)
const withActions = withReview && canViewReview
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { MutableRefObject, useEffect } from 'react'

import { Objects } from 'utils/objects'

import { Row } from 'meta/assessment'

import { getDataGridElementMatrix } from 'client/components/DataGrid/utils'

type Props = {
disabled: boolean
gridRef: MutableRefObject<HTMLDivElement>
rowsData: Array<Row>
rowsHeader: Array<Row>
}

export const useCellBorderCorrection = (props: Props) => {
const { disabled, gridRef, rowsData, rowsHeader } = props

useEffect(() => {
if (!gridRef?.current) return

if (disabled) return

const dataGridElementMatrix = getDataGridElementMatrix(gridRef.current)

dataGridElementMatrix.forEach((row, rowIndex) => {
row.forEach((cell, colIndex) => {
if (Objects.isEmpty(cell)) return

const isEditable = cell.classList.contains('editable')

if (!isEditable) return

const rightCell = row[colIndex + 1]
const bottomCell = dataGridElementMatrix[rowIndex + 1]?.[colIndex]

if (!Objects.isEmpty(rightCell) && !rightCell.classList.contains('editable')) {
if (!rightCell.classList.contains('actions')) {
cell.classList.add('lastEditableCol')
}
}

if (!Objects.isEmpty(bottomCell) && !bottomCell.classList.contains('editable')) {
if (!bottomCell.classList.contains('actions')) {
cell.classList.add('lastEditableRow')
}
}
})
})
}, [disabled, gridRef, rowsData.length, rowsHeader.length])
}

0 comments on commit 970364e

Please sign in to comment.