Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4001 - Datatable use Datagrid - Editable borders corrections #4230

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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])
}
Loading