Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Table with fixed-data-table-2
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