diff --git a/superset-frontend/src/components/ListView/ListView.tsx b/superset-frontend/src/components/ListView/ListView.tsx index 72948d55844..e0e19c503c7 100644 --- a/superset-frontend/src/components/ListView/ListView.tsx +++ b/superset-frontend/src/components/ListView/ListView.tsx @@ -17,7 +17,6 @@ * under the License. */ import { t, styled } from '@superset-ui/core'; -import { css } from '@emotion/core'; import React, { useState } from 'react'; import { Alert } from 'react-bootstrap'; import { Empty } from 'src/common/components'; @@ -38,11 +37,7 @@ import { } from './types'; import { ListViewError, useListViewState } from './utils'; -interface ListViewStylesProps { - fullHeight: boolean; -} - -const ListViewStyles = styled.div` +const ListViewStyles = styled.div` text-align: center; .superset-list-view { @@ -53,12 +48,8 @@ const ListViewStyles = styled.div` padding-bottom: 48px; .body { - ${({ fullHeight }) => - !fullHeight && - css` - overflow: scroll; - max-height: 64vh; - `}; + overflow: scroll; + max-height: 64vh; } } @@ -211,9 +202,6 @@ export interface ListViewProps { renderCard?: (row: T & { loading: boolean }) => React.ReactNode; cardSortSelectOptions?: Array; defaultViewMode?: ViewModeType; - sticky?: boolean; - fullHeight?: boolean; - manualSortBy?: boolean; } function ListView({ @@ -233,9 +221,6 @@ function ListView({ renderCard, cardSortSelectOptions, defaultViewMode = 'card', - sticky = true, - fullHeight = false, - manualSortBy = true, }: ListViewProps) { const { getTableProps, @@ -259,10 +244,8 @@ function ListView({ initialPageSize, initialSort, initialFilters: filters, - manualSortBy, }); const filterable = Boolean(filters.length); - const withPagination = Boolean(count); if (filterable) { const columnAccessors = columns.reduce( (acc, col) => ({ ...acc, [col.accessor || col.id]: true }), @@ -283,7 +266,7 @@ function ListView({ ); return ( - +
{cardViewEnabled && ( @@ -367,7 +350,6 @@ function ListView({ rows={rows} columns={columns} loading={loading} - sticky={sticky} /> )} {!loading && rows.length === 0 && ( @@ -378,25 +360,23 @@ function ListView({
- {withPagination && ( -
- gotoPage(p - 1)} - hideFirstAndLastPageLinks - /> -
- {!loading && - t( - '%s-%s of %s', - pageSize * pageIndex + (rows.length && 1), - pageSize * pageIndex + rows.length, - count, - )} -
+
+ gotoPage(p - 1)} + hideFirstAndLastPageLinks + /> +
+ {!loading && + t( + '%s-%s of %s', + pageSize * pageIndex + (rows.length && 1), + pageSize * pageIndex + rows.length, + count, + )}
- )} +
); } diff --git a/superset-frontend/src/components/ListView/TableCollection.tsx b/superset-frontend/src/components/ListView/TableCollection.tsx index a68bcf4db04..4dbbc86bce2 100644 --- a/superset-frontend/src/components/ListView/TableCollection.tsx +++ b/superset-frontend/src/components/ListView/TableCollection.tsx @@ -30,19 +30,14 @@ interface TableCollectionProps { rows: TableInstance['rows']; columns: TableInstance['column'][]; loading: boolean; - sticky: boolean; } -interface TableProps { - sticky: boolean; -} - -const Table = styled.table` +const Table = styled.table` border-collapse: separate; th { background: ${({ theme }) => theme.colors.grayscale.light5}; - position: ${({ sticky }) => sticky && 'sticky'}; + position: sticky; top: 0; &:first-of-type { @@ -204,10 +199,9 @@ export default function TableCollection({ columns, rows, loading, - sticky, }: TableCollectionProps) { return ( - +
{headerGroups.map(headerGroup => ( diff --git a/superset-frontend/src/components/ListView/utils.ts b/superset-frontend/src/components/ListView/utils.ts index 92605d268f8..c8ecc95be5c 100644 --- a/superset-frontend/src/components/ListView/utils.ts +++ b/superset-frontend/src/components/ListView/utils.ts @@ -110,7 +110,6 @@ interface UseListViewConfig { Header: (conf: any) => React.ReactNode; Cell: (conf: any) => React.ReactNode; }; - manualSortBy: boolean; } export function useListViewState({ @@ -123,7 +122,6 @@ export function useListViewState({ initialSort = [], bulkSelectMode = false, bulkSelectColumnConfig, - manualSortBy, }: UseListViewConfig) { const [query, setQuery] = useQueryParams({ filters: JsonParam, @@ -179,9 +177,9 @@ export function useListViewState({ initialState, manualFilters: true, manualPagination: true, + manualSortBy: true, autoResetFilters: false, pageCount: Math.ceil(count / initialPageSize), - manualSortBy, }, useFilters, useSortBy, diff --git a/superset-frontend/src/visualizations/TimeTable/TimeTable.jsx b/superset-frontend/src/visualizations/TimeTable/TimeTable.jsx index d27a1e80d18..c384cb0acb3 100644 --- a/superset-frontend/src/visualizations/TimeTable/TimeTable.jsx +++ b/superset-frontend/src/visualizations/TimeTable/TimeTable.jsx @@ -20,14 +20,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import Mustache from 'mustache'; import { scaleLinear } from 'd3-scale'; +import { Table, Thead, Th, Tr, Td } from 'reactable-arc'; import { formatNumber, formatTime } from '@superset-ui/core'; import { InfoTooltipWithTrigger, MetricOption, } from '@superset-ui/chart-controls'; import moment from 'moment'; -import ListView from 'src/components/ListView'; -import { memoize } from 'lodash-es'; + import FormattedNumber from './FormattedNumber'; import SparklineCell from './SparklineCell'; import './TimeTable.less'; @@ -90,68 +90,6 @@ const defaultProps = { }; class TimeTable extends React.PureComponent { - memoizedColumns = memoize(() => [ - { accessor: 'metric', Header: 'Metric' }, - ...this.props.columnConfigs.map((columnConfig, i) => ({ - accessor: columnConfig.key, - cellProps: columnConfig.colType === 'spark' && { style: { width: '1%' } }, - Header: () => ( - <> - {columnConfig.label}{' '} - {columnConfig.tooltip && ( - - )} - - ), - sortType: (rowA, rowB, columnId) => { - const rowAVal = rowA.values[columnId].props['data-value']; - const rowBVal = rowB.values[columnId].props['data-value']; - return rowAVal - rowBVal; - }, - })), - ]); - - memoizedRows = memoize(() => { - const entries = Object.keys(this.props.data) - .sort() - .map(time => ({ ...this.props.data[time], time })); - const reversedEntries = entries.concat().reverse(); - - return this.props.rows.map(row => { - const valueField = row.label || row.metric_name; - const cellValues = this.props.columnConfigs.reduce( - (acc, columnConfig) => { - if (columnConfig.colType === 'spark') { - return { - ...acc, - [columnConfig.key]: this.renderSparklineCell( - valueField, - columnConfig, - entries, - ), - }; - } - return { - ...acc, - [columnConfig.key]: this.renderValueCell( - valueField, - columnConfig, - reversedEntries, - ), - }; - }, - {}, - ); - return { ...row, ...cellValues, metric: this.renderLeftCell(row) }; - }); - }); - - initialSort = [{ id: 'metric', desc: false }]; - renderLeftCell(row) { const { rowType, url } = this.props; const context = { metric: row }; @@ -169,9 +107,10 @@ class TimeTable extends React.PureComponent { return column.label; } + const metric = row; return ( ( -
- {formatNumber(column.d3format, sparkData[index])} +
); } @@ -260,9 +204,10 @@ class TimeTable extends React.PureComponent { const color = colorFromBounds(v, column.bounds); return ( - {errorMsg ? ( - { errorMsg } +
{errorMsg}
) : ( - +
- +
)} -
+ + ); + } + + renderRow(row, entries, reversedEntries) { + const { columnConfigs } = this.props; + const valueField = row.label || row.metric_name; + const leftCell = this.renderLeftCell(row); + + return ( +
+ + {columnConfigs.map(c => + c.colType === 'spark' + ? this.renderSparklineCell(valueField, c, entries) + : this.renderValueCell(valueField, c, reversedEntries), + )} + ); } render() { - const { className, height } = this.props; + const { + className, + height, + data, + columnConfigs, + rowType, + rows, + } = this.props; + + const entries = Object.keys(data) + .sort() + .map(time => ({ ...data[time], time })); + const reversedEntries = entries.concat().reverse(); + + const defaultSort = + rowType === 'column' && columnConfigs.length + ? { + column: columnConfigs[0].key, + direction: 'desc', + } + : false; return (
- {}} - loading={false} - sticky={false} - fullHeight - manualSortBy={false} - /> +
+ (
- {formatTime( - column.dateFormat, - moment.utc(entries[index].time).toDate(), - )} + {formatNumber(column.d3format, sparkData[index])} +
+ {formatTime( + column.dateFormat, + moment.utc(entries[index].time).toDate(), + )} +
- - )} - /> + )} + /> +
+ {leftCell} +
c.key)} + > + + + {columnConfigs.map((c, i) => ( + + ))} + + {rows.map(row => this.renderRow(row, entries, reversedEntries))} +
Metric + {c.label}{' '} + {c.tooltip && ( + + )} +
); }