Created
May 18, 2020 06:32
-
-
Save Anenth/24c6caa871cba47eb05fbf71db30b838 to your computer and use it in GitHub Desktop.
Table with fixed-data-table-2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from 'react'; | |
import ClassNames from 'classnames'; | |
import { Table as FixedTable, Column } from 'fixed-data-table-2'; | |
import '!!style-loader!css-loader!fixed-data-table-2/dist/fixed-data-table-base.css'; | |
import { get } from 'lodash'; | |
import { ellipseString } from '../../helpers/BaseUtils'; | |
import { HTML_ICON, Icon, ICON_SIZES } from '../Icons/Icons'; | |
import { Text, TEXT_SIZE } from '../Text/Text'; | |
import { Tooltip } from '../Tooltip/Tooltip'; | |
import { Row, Space } from '../Grid/Grid'; | |
import styles from './table.css'; | |
import { fromNowForTooltip, humanizeDate } from '../../utils/DateUtils'; | |
type TableDateType = {}; | |
type TableColumnType = { | |
title: string; | |
columnKey: string; | |
HeaderComponent: React.ReactNode; | |
CellComponent: React.ReactNode; | |
hidden?: boolean; | |
isFixed?: boolean; | |
sortable?: boolean; | |
// Space | |
width?: number; | |
vcenter?: boolean; | |
horizontalSpacing?: boolean; | |
verticalSpacing?: boolean; | |
}; | |
type TableProps = { | |
data: Array<TableDateType>; | |
columns: Array<TableColumnType>; | |
changeSort?: () => {}; | |
currentSorting?: {}; | |
width?: number; | |
height?: number; | |
}; | |
const ROW_HEIGHT = 40; | |
const HEADER_HEIGHT = 48; | |
export function OldTable(props: TableProps) { | |
const { | |
height = 500, | |
width = '100%', | |
data, | |
columns, | |
currentSorting = { columns: 0, order: 'asc' }, | |
changeSort, | |
} = props; | |
const [columnWidths, updateColumnWidth] = useState(getDefaultColumnWidths(columns)); | |
function onColumnResizeEndCallback(newColumnWidth, columnKey) { | |
updateColumnWidth({ | |
...columnWidths, | |
[columnKey]: newColumnWidth, | |
}); | |
} | |
return ( | |
<FixedTable | |
className={styles.table} | |
rowHeight={ROW_HEIGHT} | |
headerHeight={HEADER_HEIGHT} | |
rowsCount={data.length} | |
width={width} | |
height={height} | |
touchScrollEnabled | |
onColumnResizeEndCallback={onColumnResizeEndCallback}> | |
{renderColumns({ | |
data, | |
columns, | |
// @ts-ignore | |
currentSorting, | |
changeSort, | |
columnWidths, | |
})} | |
</FixedTable> | |
); | |
} | |
OldTable.defaultProps = {}; | |
export function renderColumns({ | |
data: dataRows, | |
columns: columnsData, | |
currentSorting = { column: 0, order: 'asc' }, | |
columnWidths, | |
}) { | |
return columnsData.map(({ HeaderComponent, CellComponent, columnKey, ...column }) => { | |
if (column.hidden) { | |
return null; | |
} | |
if (!HeaderComponent) { | |
console.error(`no HeaderComponent passed for column ${columnKey}`); | |
return null; | |
} | |
if (!CellComponent) { | |
console.error(`no CellComponent passed for column ${columnKey}`); | |
return null; | |
} | |
return ( | |
<Column | |
key={columnKey} | |
fixed={column.isFixed} | |
header={ | |
<TableCell | |
cellHeight="md" | |
vcenter={column.vcenter} | |
horizontalSpacing={column.horizontalSpacing} | |
isActiveSortingCol={currentSorting.column === columnKey} | |
sortingOrder={currentSorting.order} | |
clickable={column.sortable} | |
rightAligned={column.rightAligned}> | |
<HeaderComponent name={column.title} icon_name={column.icon_name} /> | |
</TableCell> | |
} | |
cell={({ rowIndex }) => ( | |
<TableCell | |
isActiveSortingCol={false} | |
sortingOrder="asc" | |
rightAligned={column.rightAligned} | |
cellHeight={column.cellHeight} | |
horizontalSpacing={column.horizontalSpacing}> | |
<CellComponent | |
rowIndex={rowIndex} | |
rows={dataRows} | |
relatedColumnKeys={column.related_column_keys} | |
additional_meta_data={column.additional_meta_data} | |
columnKey={columnKey} | |
/> | |
</TableCell> | |
)} | |
width={columnWidths[columnKey] || 150} | |
/> | |
); | |
}); | |
} | |
type TableCellProps = { | |
children: React.ReactNode; | |
rightAligned: boolean; | |
vcenter?: boolean; | |
clickable?: boolean; | |
isActiveSortingCol: boolean; | |
sortingOrder: string; | |
cellHeight: 'md' | 'lg'; | |
horizontalSpacing: 2 | 4; | |
}; | |
export function TableCell(props: TableCellProps) { | |
const { | |
children, | |
rightAligned, | |
vcenter = true, | |
horizontalSpacing = 2, | |
clickable, | |
isActiveSortingCol, | |
sortingOrder, | |
cellHeight, | |
} = props; | |
const classes = ClassNames(styles.table__cell, styles[`table__cell--height-${cellHeight}`], { | |
[styles['table__cell--right-aligned']]: rightAligned, | |
[styles['table__cell--clickable']]: !!clickable, | |
}); | |
// const clickHandler = e => { | |
// e.currentTarget.contains(e.target) && onClick && onClick(); // handle cases where dropdown clicks bubble up | |
// }; | |
return ( | |
<Row vcenter={vcenter} className={classes}> | |
<Space size={horizontalSpacing}> | |
<Row vcenter> | |
<Space size={2} /> | |
{children} | |
<Space size={1} /> | |
{isActiveSortingCol && ( | |
<Icon size={ICON_SIZES.SM} name={sortingOrder === 'asc' ? 'arrow_up' : 'arrow_down'} /> | |
)} | |
</Row> | |
</Space> | |
</Row> | |
); | |
} | |
export function PlainTextHeader(props: { name: string }) { | |
return <Text muted>{props.name}</Text>; | |
} | |
type ElipsisedPlainTextHeaderProps = { | |
name: string; | |
maxLength: number; | |
}; | |
export function ElipsisedPlainTextHeader(props: ElipsisedPlainTextHeaderProps) { | |
const { name, maxLength } = props; | |
return ( | |
<Tooltip message={name}> | |
<Text size={TEXT_SIZE.SIZE_5} muted> | |
{ellipseString(name, maxLength)} | |
</Text> | |
</Tooltip> | |
); | |
} | |
type TextCellSimpleType = { | |
rows: Array<{}>; | |
rowIndex: number; | |
relatedColumnKeys: Array<string>; | |
columnKey: string; | |
}; | |
export function TextCellSimple(props: TextCellSimpleType) { | |
const { rows, rowIndex, relatedColumnKeys, columnKey } = props; | |
const cellText = getContentForCell(rows, rowIndex, columnKey); | |
const zeroTextContent = HTML_ICON.DASH_SMALL; | |
if (relatedColumnKeys) { | |
const tooltip = get(rows[rowIndex], relatedColumnKeys[0], '0'); | |
return ( | |
<Tooltip message={tooltip}> | |
<Text ellipsis muted={!cellText}> | |
{cellText || zeroTextContent} | |
</Text> | |
</Tooltip> | |
); | |
} | |
return ( | |
<Text ellipsis muted={!cellText}> | |
{cellText || zeroTextContent} | |
</Text> | |
); | |
} | |
type TextCellDateType = { | |
rows: Array<{}>; | |
rowIndex: number; | |
columnKey: string; | |
}; | |
export function TextCellDate(props: TextCellDateType) { | |
const { rows, rowIndex, columnKey } = props; | |
const date = getContentForCell(rows, rowIndex, columnKey); | |
const tooltip = fromNowForTooltip(date); | |
const humanizedDate = humanizeDate(date); | |
return ( | |
<Tooltip message={tooltip}> | |
<Text ellipsis>{humanizedDate}</Text> | |
</Tooltip> | |
); | |
} | |
type TableHeaderWithIconProps = { | |
icon_name: string; | |
name: string; | |
size: TEXT_SIZE; | |
}; | |
export function TableHeaderWithIcon(props: TableHeaderWithIconProps) { | |
return ( | |
<Text ellipsis={false} size={props.size}> | |
{props.name} | |
<Icon name={props.icon_name} /> | |
</Text> | |
); | |
} | |
function getDefaultColumnWidths(columns: Array<TableColumnType>): { [columnKey: string]: number } { | |
return columns.reduce((result, column) => { | |
return { | |
...result, | |
[column.columnKey]: column.width || 150, | |
}; | |
}, {}); | |
} | |
function getContentForCell(rows, rowIndex, columnKey) { | |
return get(rows[rowIndex], columnKey, '0'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment