Skip to content

Commit

Permalink
Merge branch '4001-datatable-use-datagrid' into 4001-datatable-use-da…
Browse files Browse the repository at this point in the history
…tagrid-code-clean-up
  • Loading branch information
yaguzmang committed Jan 7, 2025
2 parents 1b7921d + a2f5774 commit 0479892
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 104 deletions.
7 changes: 7 additions & 0 deletions src/client/pages/AdminCollaborators/hooks/useFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ export const useFilters = (): Returned => {
label: '',
type: TablePaginatedFilterType.SWITCH,
},
{
defaultValue: false,
fieldName: 'invitations',
hidden: true,
label: '',
type: TablePaginatedFilterType.SWITCH,
},
{
fieldName: 'roles',
label: t('common.role'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,83 +1,18 @@
import React, { MutableRefObject, useCallback } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'

import { Table, TableNames } from 'meta/assessment'

import { useCycle } from 'client/store/assessment'
import { useUser } from 'client/store/user'
import Button from 'client/components/Buttons/Button'
import { getData } from 'client/components/ButtonTableExport/utils'

type CopyValuesProps = {
tableRef: MutableRefObject<HTMLTableElement>
table: Table
}

// tableMappings is a mapping of table names to the variables that should be copied to clipboard
const tableMappings2020: Record<string, Array<string>> = {
[TableNames.forestCharacteristics]: [
'forestCharacteristics.naturalForestArea',
'forestCharacteristics.plantationForestArea',
'forestCharacteristics.plantationForestIntroducedArea',
'forestCharacteristics.otherPlantedForestArea',
],
[TableNames.growingStockAvg]: [
'growingStock.naturallyRegeneratingForest',
'growingStock.plantedForest',
'growingStock.plantationForest',
'growingStock.otherPlantedForest',
],
}

const tableMappings2025: Record<string, Array<string>> = {
[TableNames.forestCharacteristics]: [
'fra.forestCharacteristics.naturalForestArea2025',
'fra.growingStock.plantationForest2025',
'fra.forestCharacteristics.plantationForestIntroducedArea2025',
'fra.forestCharacteristics.ofWhichOtherPlantedForest',
],
[TableNames.growingStockAvg]: [
'fra.growingStock.naturallyRegeneratingForest2025',
'fra.growingStock.plantedForest2025',
'fra.growingStock.plantationForest2025',
'fra.growingStock.otherPlantedForest2025',
],
}

const colMapping = [1990, 2000, 2010, 2015, 2020, 2025]
import { useCopyValues } from './hooks/useCopyValues'
import { CopyValuesProps } from './types'

const ButtonCopyValues: React.FC<CopyValuesProps> = (props: CopyValuesProps) => {
const { tableRef, table } = props
const cycle = useCycle()
const user = useUser()
const { t } = useTranslation()
const { onClick, showButton } = useCopyValues(props)

const tableMappings = cycle.name === '2025' ? tableMappings2025 : tableMappings2020

const showButton = Object.keys(tableMappings).includes(table.props.name)

const _onClick = useCallback(() => {
const _table = tableRef.current
if (!_table) return
const csv = getData(_table)
const include = tableMappings[table.props.name].map((variableLabel) => t(variableLabel))
// A list of indexes of the table columns that should be copied to clipboard
const correctIndexes = colMapping.map((year) => csv[1].indexOf(year.toString()))
const z = csv
.filter((row) => {
return include.some((translatedVariable) => row[0].includes(translatedVariable))
})
.map((row: string[]) => {
return row.filter((_, i) => correctIndexes.includes(i))
})

navigator.clipboard.writeText(z.map((row: Array<string>) => row.join('\t')).join('\n'))
}, [t, table.props.name, tableMappings, tableRef])

// Hide button if incorrect table or user is not logged in
if (!user || !showButton) return null
if (!showButton) return null

return <Button iconName="content_copy" label={t('tableWithOdp.copyToClipboard')} onClick={_onClick} />
return <Button iconName="content_copy" label={t('tableWithOdp.copyToClipboard')} onClick={onClick} />
}

export default ButtonCopyValues
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'

import { Objects } from 'utils/objects'

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 { CopyValuesProps } from 'client/pages/Section/DataTable/Table/ButtonCopyValues/types'

// Cycle -> Table name -> Variables to be coppied to clipboard
const tableMappings: Record<string, Record<string, Array<string>>> = {
'2020': {
[TableNames.forestCharacteristics]: [
'forestCharacteristics.naturalForestArea',
'forestCharacteristics.plantationForestArea',
'forestCharacteristics.plantationForestIntroducedArea',
'forestCharacteristics.otherPlantedForestArea',
],
[TableNames.growingStockAvg]: [
'growingStock.naturallyRegeneratingForest',
'growingStock.plantedForest',
'growingStock.plantationForest',
'growingStock.otherPlantedForest',
],
},
'2025': {
[TableNames.forestCharacteristics]: [
'fra.forestCharacteristics.naturalForestArea2025',
'fra.growingStock.plantationForest2025',
'fra.forestCharacteristics.plantationForestIntroducedArea2025',
'fra.forestCharacteristics.ofWhichOtherPlantedForest',
],
[TableNames.growingStockAvg]: [
'fra.growingStock.naturallyRegeneratingForest2025',
'fra.growingStock.plantedForest2025',
'fra.growingStock.plantationForest2025',
'fra.growingStock.otherPlantedForest2025',
],
},
}

const yearsToCopy = [1990, 2000, 2010, 2015, 2020, 2025]

type Returned = {
onClick: () => void
showButton: boolean
}

export const useCopyValues = (props: CopyValuesProps): Returned => {
const { gridRef, table } = props

const { t } = useTranslation()
const { cycleName } = useCycleRouteParams()
const user = useUser()

const cycleTableMappings = tableMappings[cycleName]

const isTableIncluded = useMemo<boolean>(
() => Object.keys(cycleTableMappings ?? {}).includes(table.props.name),
[cycleTableMappings, table.props.name]
)

const onClick = useCallback<Returned['onClick']>(() => {
if (!isTableIncluded) return

const grid = gridRef.current
if (!grid) return

const csv = getDataGridData(grid)
const variablesToCopy = cycleTableMappings[table.props.name].map((variableLabel) => t(variableLabel))
const columnIndexesToCopy = yearsToCopy.map((year) => csv[1].indexOf(year.toString()))

const z = csv.reduce((acc: Array<Array<string>>, row: Array<string>) => {
const shouldIncludeRow = variablesToCopy.some((translatedVariable) => row[0].includes(translatedVariable))
if (shouldIncludeRow) {
const filteredRow = row.filter((_, i) => columnIndexesToCopy.includes(i))
acc.push(filteredRow)
}
return acc
}, [])

navigator.clipboard.writeText(z.map((row: Array<string>) => row.join('\t')).join('\n'))
}, [cycleTableMappings, gridRef, isTableIncluded, t, table.props.name])

return {
onClick,
showButton: isTableIncluded && !Objects.isEmpty(user),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { MutableRefObject } from 'react'

import { Table } from 'meta/assessment'

export type CopyValuesProps = {
gridRef: MutableRefObject<HTMLDivElement>
table: Table
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const OdpHeaderCell: React.FC<Props> = (props) => {

if (print) {
return (
<DataCell className={className} gridColumn={gridColumn} gridRow={gridRow}>
<DataCell className={classNames(className, 'header')} gridColumn={gridColumn} gridRow={gridRow}>
{odpYear}
</DataCell>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import 'src/client/style/partials';

.table-grid__data-cell-input-number {
text-align: right;

Expand All @@ -9,3 +11,13 @@
}
}
}

@include rtl {
.table-grid__data-cell-input-number {
&.input-text {
&.disabled {
justify-content: start;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ type Props = {
firstCol?: boolean
firstHighlightCol?: boolean
highlighted?: boolean
lastCol?: boolean
lastHighlightCol?: boolean
lastRow?: boolean
row: Row
}

const CellHeader: React.FC<Props> = (props) => {
const { assessmentName, col, firstCol, firstHighlightCol, highlighted, lastHighlightCol, lastRow, row } = props
const { assessmentName, col, firstCol, firstHighlightCol, highlighted, lastCol, lastHighlightCol, lastRow, row } =
props

const { t } = useTranslation()
const cycle = useCycle()
Expand Down Expand Up @@ -56,6 +58,7 @@ const CellHeader: React.FC<Props> = (props) => {
gridRow={gridRow}
header
highlighted={highlighted}
lastCol={lastCol}
lastHighlightCol={lastHighlightCol}
lastRow={lastRow}
style={colHeaderStyle}
Expand Down Expand Up @@ -86,6 +89,7 @@ CellHeader.defaultProps = {
firstCol: false,
firstHighlightCol: false,
highlighted: false,
lastCol: false,
lastHighlightCol: false,
lastRow: false,
}
Expand Down
61 changes: 41 additions & 20 deletions src/client/pages/Section/DataTable/Table/RowData/RowData.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React from 'react'

import { ColType } from 'meta/assessment'
import { Objects } from 'utils/objects'

import { Cols, ColType } from 'meta/assessment'

import { useCycle } from 'client/store/assessment'
import { DataRow } from 'client/components/DataGrid'
import { RowProps } from 'client/pages/Section/DataTable/Table/types'

Expand All @@ -11,33 +14,51 @@ import Cell from './Cell'
import CellHeader from './CellHeader'

const RowData: React.FC<RowProps> = (props) => {
const { data, assessmentName, lastRow, sectionName, table, row, disabled } = props
const { assessmentName, data, disabled, lastRow, row, rowCount, rowIndex, sectionName, table } = props

const { cols } = row
const colHeader = [ColType.placeholder, ColType.header].includes(cols[0].props.colType) ? cols[0] : undefined
const colsData = colHeader ? cols.slice(1, cols.length) : cols
const actions = useRowActions({ colHeader, row, sectionName, table })
const highlightRange = useHighlightRange({ cols })
const cycle = useCycle()

return (
<DataRow actions={actions} highlightRange={highlightRange}>
{colHeader && <CellHeader assessmentName={assessmentName} col={colHeader} lastRow={lastRow} row={row} />}

{colsData.map((col, index) => (
<Cell
key={col.uuid}
assessmentName={assessmentName}
col={col}
data={data}
disabled={disabled}
lastCol={index === cols.length - 1}
lastRow={lastRow}
row={row}
rowIndex={Number(row.props.index)}
sectionName={sectionName}
table={table}
/>
))}
{cols.map((col, colIndex) => {
const lastCol = colIndex === cols.length - 1

const { rowSpan = 1 } = Cols.getStyle({ col, cycle })
const lastSpanningRow = rowSpan !== 1 && rowSpan + rowIndex === rowCount

if (!Objects.isEmpty(colHeader) && colIndex === 0) {
return (
<CellHeader
key={col.uuid}
assessmentName={assessmentName}
col={colHeader}
lastCol={lastCol}
lastRow={lastRow || lastSpanningRow}
row={row}
/>
)
}

return (
<Cell
key={col.uuid}
assessmentName={assessmentName}
col={col}
data={data}
disabled={disabled}
lastCol={lastCol}
lastRow={lastRow || lastSpanningRow}
row={row}
rowIndex={Number(row.props.index)}
sectionName={sectionName}
table={table}
/>
)
})}
</DataRow>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useCycle } from 'client/store/assessment'
import { DataCell, DataRow } from 'client/components/DataGrid'
import { RowProps } from 'client/pages/Section/DataTable/Table/types'

const RowNoticeMessage: React.FC<RowProps> = (props) => {
const RowNoticeMessage: React.FC<Omit<RowProps, 'rowCount' | 'rowIndex'>> = (props) => {
const { row } = props

const { t } = useTranslation()
Expand All @@ -18,7 +18,7 @@ const RowNoticeMessage: React.FC<RowProps> = (props) => {
return (
<DataRow>
{cols.map((col) => {
const message = Cols.getLabel({ cycle, col, t })
const message = Cols.getLabel({ col, cycle, t })

if (!message) return null

Expand Down
4 changes: 3 additions & 1 deletion src/client/pages/Section/DataTable/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const Table: React.FC<Props> = (props) => {
<div className="fra-table__scroll-wrapper">
<div className="fra-table__editor">
{!print && <ButtonGridExport filename={fileName} gridRef={gridRef} />}
<ButtonCopyValues table={table} tableRef={tableRef} />
<ButtonCopyValues gridRef={gridRef} table={table} />
{canClearData && <ButtonTableClear disabled={disabled} sectionName={sectionName} table={table} />}
</div>

Expand Down Expand Up @@ -99,6 +99,8 @@ const Table: React.FC<Props> = (props) => {
disabled={disabled}
lastRow={index === rowsData.length - 1}
row={row}
rowCount={rowsHeader.length + rowsData.length}
rowIndex={rowsHeader.length + index}
sectionName={sectionName}
table={table}
/>
Expand Down
2 changes: 2 additions & 0 deletions src/client/pages/Section/DataTable/Table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export type RowProps = {
disabled: boolean
lastRow?: boolean
row: Row
rowCount: number
rowIndex: number
sectionName: string
table: Table
}
Loading

0 comments on commit 0479892

Please sign in to comment.