Skip to content
This repository was archived by the owner on Dec 10, 2021. It is now read-only.

fix(plugin-chart-table): resize and totals formatting bug #1082

Merged
merged 1 commit into from
Apr 30, 2021
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 @@ -73,9 +73,9 @@ const fractionDigits: ControlFormItemSpec<'Slider'> = {

const columnWidth: ControlFormItemSpec<'InputNumber'> = {
controlType: 'InputNumber',
label: t('Width'),
label: t('Min Width'),
description: t(
'Default column width in pixels, may still be restricted by the shortest/longest word in the column',
"Default minimal column width in pixels, actual width may still be larger than this if other columns don't need much space",
),
width: 120,
placeholder: 'auto',
Expand Down
24 changes: 12 additions & 12 deletions plugins/plugin-chart-table/src/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import {
IdType,
Row,
} from 'react-table';
import { t } from '@superset-ui/core';
import { matchSorter, rankings } from 'match-sorter';
import GlobalFilter, { GlobalFilterProps } from './components/GlobalFilter';
import SelectPageSize, { SelectPageSizeProps, SizeOption } from './components/SelectPageSize';
Expand All @@ -45,8 +44,6 @@ import { PAGE_SIZE_OPTIONS } from '../consts';

export interface DataTableProps<D extends object> extends TableOptions<D> {
tableClassName?: string;
totals?: { value: string; className?: string }[];
totalsHeaderSpan?: number;
searchInput?: boolean | GlobalFilterProps<D>['searchInput'];
selectPageSize?: boolean | SelectPageSizeProps['selectRenderer'];
pageSizeOptions?: SizeOption[]; // available page size options
Expand All @@ -73,8 +70,6 @@ export default function DataTable<D extends object>({
tableClassName,
columns,
data,
totals,
totalsHeaderSpan,
serverPaginationData,
width: initialWidth = '100%',
height: initialHeight = 300,
Expand Down Expand Up @@ -159,6 +154,7 @@ export default function DataTable<D extends object>({
getTableBodyProps,
prepareRow,
headerGroups,
footerGroups,
page,
pageCount,
gotoPage,
Expand Down Expand Up @@ -198,6 +194,8 @@ export default function DataTable<D extends object>({
return (wrapStickyTable ? wrapStickyTable(getNoResults) : getNoResults()) as JSX.Element;
}

const shouldRenderFooter = columns.some(x => !!x.Footer);

const renderTable = () => (
<table {...getTableProps({ className: tableClassName })}>
<thead>
Expand Down Expand Up @@ -234,14 +232,16 @@ export default function DataTable<D extends object>({
</tr>
)}
</tbody>
{totals && (
{shouldRenderFooter && (
<tfoot>
<tr key="totals" className="dt-totals">
<td colSpan={totalsHeaderSpan}>{t('Totals')}</td>
{totals.map(item => (
<td className={item.className}>{item.value}</td>
))}
</tr>
{footerGroups.map(footerGroup => {
const { key: footerGroupKey, ...footerGroupProps } = footerGroup.getHeaderGroupProps();
return (
<tr key={footerGroupKey || footerGroup.id} {...footerGroupProps}>
{footerGroup.headers.map(column => column.render('Footer', { key: column.id }))}
</tr>
);
})}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use react-table's built-in footer support to render totals. cc @kgabryje

</tfoot>
)}
</table>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
UseSortByHooks,
Renderer,
HeaderProps,
TableFooterProps,
} from 'react-table';

import { UseStickyState, UseStickyTableOptions, UseStickyInstanceProps } from '../hooks/useSticky';
Expand Down Expand Up @@ -64,6 +65,7 @@ declare module 'react-table' {
// must define as a new property because it's not possible to override
// the existing `Header` renderer option
Header?: Renderer<TableSortByToggleProps & HeaderProps<D>>;
Footer?: Renderer<TableFooterProps<D>>;
}

export interface ColumnInstance<D extends object>
Expand Down
60 changes: 27 additions & 33 deletions plugins/plugin-chart-table/src/TableChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -247,24 +247,28 @@ export default function TableChart<D extends DataRecord = DataRecord>(
[filters, handleChange, isActiveFilterValue],
);

const getSharedStyle = (column: DataColumnMeta): CSSProperties => {
const { isNumeric, config = {} } = column;
const textAlign = config.horizontalAlign
? config.horizontalAlign
: isNumeric
? 'right'
: 'left';
return {
textAlign,
};
};

const getColumnConfigs = useCallback(
(column: DataColumnMeta, i: number): ColumnWithLooseAccessor<D> => {
const { key, label, dataType, isMetric, config = {} } = column;
const isNumber = dataType === GenericDataType.NUMERIC;
const isFilter = !isNumber && emitFilter;
const textAlign = config.horizontalAlign
? config.horizontalAlign
: isNumber
? 'right'
: 'left';
const { key, label, isNumeric, dataType, isMetric, config = {} } = column;
const isFilter = !isNumeric && emitFilter;
const columnWidth = Number.isNaN(Number(config.columnWidth))
? config.columnWidth
: Number(config.columnWidth);

// inline style for both th and td cell
const sharedStyle: CSSProperties = {
textAlign,
};
const sharedStyle: CSSProperties = getSharedStyle(column);

const alignPositiveNegative =
config.alignPositiveNegative === undefined ? defaultAlignPN : config.alignPositiveNegative;
Expand All @@ -287,7 +291,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
// typing is incorrect in current version of `@types/react-table`
// so we ask TS not to check.
accessor: ((datum: D) => datum[key]) as never,
Cell: ({ value }: { column: ColumnInstance<D>; value: DataRecordValue }) => {
Cell: ({ value }: { value: DataRecordValue }) => {
const [isHtml, text] = formatColumnValue(column, value);
const html = isHtml ? { __html: text } : undefined;
const cellProps = {
Expand Down Expand Up @@ -343,6 +347,15 @@ export default function TableChart<D extends DataRecord = DataRecord>(
<SortIcon column={col} />
</th>
),
Footer: totals ? (
i === 0 ? (
<th>{t('Totals')}</th>
) : (
<td style={sharedStyle}>
<strong>{formatColumnValue(column, totals[key])[1]}</strong>
</td>
)
) : undefined,
sortDescFirst: sortDesc,
sortType: getSortTypeByDataType(dataType),
};
Expand All @@ -357,6 +370,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
showCellBars,
sortDesc,
toggleFilter,
totals,
],
);

Expand All @@ -366,37 +380,17 @@ export default function TableChart<D extends DataRecord = DataRecord>(
updateExternalFormData(setDataMask, pageNumber, pageSize);
};

const totalsFormatted =
totals &&
columnsMeta
.filter(column => Object.keys(totals).includes(column.key))
.reduce(
(acc: { value: string; className: string }[], column) => [
...acc,
{
value: formatColumnValue(column, totals[column.key])[1],
className: column.dataType === GenericDataType.NUMERIC ? 'dt-metric' : '',
},
],
[],
);

const totalsHeaderSpan =
totalsFormatted &&
columnsMeta.filter(column => !column.isPercentMetric).length - totalsFormatted.length;

return (
<Styles>
<DataTable<D>
columns={columns}
totals={totalsFormatted}
totalsHeaderSpan={totalsHeaderSpan}
data={data}
rowCount={rowCount}
tableClassName="table table-striped table-condensed"
pageSize={pageSize}
serverPaginationData={serverPaginationData}
pageSizeOptions={pageSizeOptions}
width={width}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

height={height}
serverPagination={serverPagination}
onServerPaginationChange={handleServerPaginationChange}
Expand Down
6 changes: 3 additions & 3 deletions plugins/plugin-chart-table/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ const translations: Partial<Record<Locale, typeof en>> = {
'Show Cell Bars': ['为指标添加条状图背景'],
'page_size.show': ['每页显示'],
'page_size.all': ['全部'],
'page_size.entries': [''],
'table.previous_page': ['以前的'],
'table.next_page': ['下一個'],
'page_size.entries': ['上一页'],
'table.previous_page': ['上一页'],
'table.next_page': ['下一页'],
'search.num_records': ['%s条记录...'],
},
};
Expand Down
1 change: 1 addition & 0 deletions plugins/plugin-chart-table/src/transformProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const processColumns = memoizeOne(function processColumns(props: TableChartProps
key,
label,
dataType,
isNumeric: dataType === GenericDataType.NUMERIC,
isMetric,
isPercentMetric,
formatter,
Expand Down
1 change: 1 addition & 0 deletions plugins/plugin-chart-table/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export interface DataColumnMeta {
formatter?: TimeFormatter | NumberFormatter | CustomFormatter;
isMetric?: boolean;
isPercentMetric?: boolean;
isNumeric?: boolean;
config?: ColumnConfig;
}

Expand Down
7 changes: 6 additions & 1 deletion plugins/plugin-chart-table/src/utils/formatValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ function formatValue(
formatter: DataColumnMeta['formatter'],
value: DataRecordValue,
): [boolean, string] {
if (value === null || typeof value === 'undefined') {
// render undefined as empty string
if (value === undefined) {
return [false, ''];
}
// render null as `N/A`
if (value === null) {
return [false, 'N/A'];
}
if (formatter) {
Expand Down