diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/constants.tsx b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/constants.tsx index 497526dc3642..e26ca851e117 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/constants.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/shared-controls/components/ColumnConfigControl/constants.tsx @@ -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', diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx index 9fc0551d157a..d0003d3d4f55 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/DataTable.tsx @@ -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'; @@ -45,8 +44,6 @@ import { PAGE_SIZE_OPTIONS } from '../consts'; export interface DataTableProps extends TableOptions { tableClassName?: string; - totals?: { value: string; className?: string }[]; - totalsHeaderSpan?: number; searchInput?: boolean | GlobalFilterProps['searchInput']; selectPageSize?: boolean | SelectPageSizeProps['selectRenderer']; pageSizeOptions?: SizeOption[]; // available page size options @@ -73,8 +70,6 @@ export default function DataTable({ tableClassName, columns, data, - totals, - totalsHeaderSpan, serverPaginationData, width: initialWidth = '100%', height: initialHeight = 300, @@ -159,6 +154,7 @@ export default function DataTable({ getTableBodyProps, prepareRow, headerGroups, + footerGroups, page, pageCount, gotoPage, @@ -198,6 +194,8 @@ export default function DataTable({ return (wrapStickyTable ? wrapStickyTable(getNoResults) : getNoResults()) as JSX.Element; } + const shouldRenderFooter = columns.some(x => !!x.Footer); + const renderTable = () => ( @@ -234,14 +232,16 @@ export default function DataTable({ )} - {totals && ( + {shouldRenderFooter && ( - - - {totals.map(item => ( - - ))} - + {footerGroups.map(footerGroup => { + const { key: footerGroupKey, ...footerGroupProps } = footerGroup.getHeaderGroupProps(); + return ( + + {footerGroup.headers.map(column => column.render('Footer', { key: column.id }))} + + ); + })} )}
{t('Totals')}{item.value}
diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/types/react-table.d.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/types/react-table.d.ts index 8301ab3e0dfc..78e9a7cc55ea 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/types/react-table.d.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/DataTable/types/react-table.d.ts @@ -19,6 +19,7 @@ import { UseSortByHooks, Renderer, HeaderProps, + TableFooterProps, } from 'react-table'; import { UseStickyState, UseStickyTableOptions, UseStickyInstanceProps } from '../hooks/useSticky'; @@ -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>; + Footer?: Renderer>; } export interface ColumnInstance diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx index 01814311f0ff..2302d6ae8d4a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/TableChart.tsx @@ -247,24 +247,28 @@ export default function TableChart( [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 => { - 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; @@ -287,7 +291,7 @@ export default function TableChart( // 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; value: DataRecordValue }) => { + Cell: ({ value }: { value: DataRecordValue }) => { const [isHtml, text] = formatColumnValue(column, value); const html = isHtml ? { __html: text } : undefined; const cellProps = { @@ -343,6 +347,15 @@ export default function TableChart( ), + Footer: totals ? ( + i === 0 ? ( + {t('Totals')} + ) : ( + + {formatColumnValue(column, totals[key])[1]} + + ) + ) : undefined, sortDescFirst: sortDesc, sortType: getSortTypeByDataType(dataType), }; @@ -357,6 +370,7 @@ export default function TableChart( showCellBars, sortDesc, toggleFilter, + totals, ], ); @@ -366,37 +380,17 @@ export default function TableChart( 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 ( columns={columns} - totals={totalsFormatted} - totalsHeaderSpan={totalsHeaderSpan} data={data} rowCount={rowCount} tableClassName="table table-striped table-condensed" pageSize={pageSize} serverPaginationData={serverPaginationData} pageSizeOptions={pageSizeOptions} + width={width} height={height} serverPagination={serverPagination} onServerPaginationChange={handleServerPaginationChange} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/i18n.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/i18n.ts index d3289cdef08d..567122def3d3 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/i18n.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/i18n.ts @@ -37,9 +37,9 @@ const translations: Partial> = { '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条记录...'], }, }; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts index 02afb02191f8..b257269edeaf 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/transformProps.ts @@ -146,6 +146,7 @@ const processColumns = memoizeOne(function processColumns(props: TableChartProps key, label, dataType, + isNumeric: dataType === GenericDataType.NUMERIC, isMetric, isPercentMetric, formatter, diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts index 279a58481bd4..80cec4edc65d 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/types.ts @@ -44,6 +44,7 @@ export interface DataColumnMeta { formatter?: TimeFormatter | NumberFormatter | CustomFormatter; isMetric?: boolean; isPercentMetric?: boolean; + isNumeric?: boolean; config?: ColumnConfig; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/utils/formatValue.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/utils/formatValue.ts index 5c37d1b464be..25e9f1165395 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/utils/formatValue.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-table/src/utils/formatValue.ts @@ -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) {