Skip to content

Commit

Permalink
4001 - Datatable use Datagrid - ButtonCopyValues (#4194)
Browse files Browse the repository at this point in the history
* 4001 - Copy values from grid

* 4001 - Move and refactor Copy logic to useCopyValues hook

* 4001 - Minor rtl fix for disabled input number
  • Loading branch information
yaguzmang authored Jan 3, 2025
1 parent 3c51c4b commit 535686f
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 72 deletions.
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
@@ -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;
}
}
}
}
2 changes: 1 addition & 1 deletion src/client/pages/Section/DataTable/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,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

0 comments on commit 535686f

Please sign in to comment.