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

Commit

Permalink
fix(table): fix sorting, column width calculation, and text wrapping (#…
Browse files Browse the repository at this point in the history
…253)

* fix(table): fix issues

* fix(table): fix comments
  • Loading branch information
conglei committed Nov 13, 2019
1 parent a197bb9 commit 12dd847
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import DataTable from '@airbnb/lunar/lib/components/DataTable';
import Text from '@airbnb/lunar/lib/components/Text';
import Input from '@airbnb/lunar/lib/components/Input';
import withStyles, { WithStylesProps } from '@airbnb/lunar/lib/composers/withStyles';
import { Renderers, ParentRow, ColumnMetadata } from '@airbnb/lunar/lib/components/DataTable/types';
import dompurify from 'dompurify';
import {
Renderers,
ParentRow,
ColumnMetadata,
GenericRow,
} from '@airbnb/lunar/lib/components/DataTable/types';
import { createSelector } from 'reselect';
import { TimeFormatter } from '@superset-ui/time-format';
import { NumberFormatter } from '@superset-ui/number-format';
import getRenderer, { ColumnType, Cell } from './getRenderer';

type Props = {
Expand Down Expand Up @@ -43,6 +49,8 @@ const CELL_PADDING = 32;

const MAX_COLUMN_WIDTH = 300;

const htmlTagRegex = /(<([^>]+)>)/gi;

export type TableProps = Props & Readonly<typeof defaultProps>;

type InternalTableProps = TableProps & WithStylesProps;
Expand All @@ -60,13 +68,12 @@ function getCellHash(cell: Cell) {
return `${cell.key}#${cell.value}`;
}

function getText(value: unknown) {
function getText(value: unknown, format: TimeFormatter | NumberFormatter | undefined) {
if (format) {
return format.format(value as any);
}
if (typeof value === 'string') {
const span = document.createElement('span');
const sanitizedString = dompurify.sanitize(value);
span.innerHTML = sanitizedString;

return String(span.textContent || span.innerText);
return value.replace(htmlTagRegex, '');
}

return String(value);
Expand All @@ -81,14 +88,27 @@ type columnWidthMetaDataType = {

class TableVis extends React.PureComponent<InternalTableProps, TableState> {
columnWidthSelector = createSelector(
(data: ParentRow[]) => data,
(data: { rows: ParentRow[]; columns: ColumnType[] }) => data,
data => {
const keys = data && data.length > 0 ? Object.keys(data[0].data) : [];
const { rows, columns } = data;
const keys = rows && rows.length > 0 ? Object.keys(rows[0].data) : [];
let totalWidth = 0;
const columnWidthMetaData: columnWidthMetaDataType = {};
const columnsMap: {
[key: string]: ColumnType;
} = {};

columns.forEach(column => {
columnsMap[column.key] = column;
});

keys.forEach(key => {
const maxLength = Math.max(...data.map(d => getText(d.data[key]).length), key.length);
const column = columnsMap[key];
const format = column && column.format;
const maxLength = Math.max(
...rows.map(d => getText(d.data[key], format).length),
key.length,
);
const stringWidth = maxLength * CHAR_WIDTH + CELL_PADDING;
columnWidthMetaData[key] = {
maxWidth: MAX_COLUMN_WIDTH,
Expand Down Expand Up @@ -211,6 +231,8 @@ class TableVis extends React.PureComponent<InternalTableProps, TableState> {
const dataToRender = searchKeyword === '' ? data : filteredRows;
const renderers: Renderers = {};
const columnMetadata: ColumnMetadata = {};
const convertToLowerCase = ({ data: d }: GenericRow, key: string) =>
typeof d[key] === 'string' ? (d[key] as string).toLowerCase() : d[key];

columns.forEach(column => {
renderers[column.key] = getRenderer({
Expand All @@ -229,7 +251,7 @@ class TableVis extends React.PureComponent<InternalTableProps, TableState> {
});

const keys = dataToRender && dataToRender.length > 0 ? Object.keys(dataToRender[0].data) : [];
const columnWidthInfo = this.columnWidthSelector(data);
const columnWidthInfo = this.columnWidthSelector({ columns, rows: data });

keys.forEach(key => {
columnMetadata[key] = {
Expand Down Expand Up @@ -285,6 +307,7 @@ class TableVis extends React.PureComponent<InternalTableProps, TableState> {
renderers={renderers}
height={tableHeight}
width={Math.max(columnWidthInfo.totalWidth, width)}
sortByValue={convertToLowerCase}
/>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export default function getRenderer({
const baseBoxStyle: CSSProperties = {
cursor: cursorStyle,
margin: '4px -16px',
wordBreak: 'break-all',
};

const selectedBoxStyle: CSSProperties = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,16 @@ export default [
chartType="table2"
key="bigTable"
datasource={{
columnFormats: {},
columnFormats: {
clm0: '.2s',
},
verboseMap: {},
}}
formData={{
alignPn: true,
colorPn: true,
includeSearch: true,
metrics: [],
metrics: ['clm0'],
orderDesc: true,
pageLength: 0,
percentMetrics: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default [
sum__num: 1506025,
},
{
name: 'John',
name: 'john',
sum__num: 1426074,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default {
trend: 1,
},
{
name: 'John',
name: 'john',
sum__num: 1426074,
'%sum__num': 0.12,
trend: -2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
/* eslint-disable sort-keys */

const getHTML = () => {
const randomText = Array(Math.floor(Math.random() * 20))
const randomText = Array(Math.floor(Math.random() * 50))
.fill('very')
.join(' ');
.join('_');

return `<a href="www.google.com" target="_blank">Link Test with a ${randomText} long title</a>`;
return `<a href="https://www.google.com" target="_blank">Link Test with a ${randomText} long title</a>`;
};

export default function generateData(rowCount = 30, columnCount = 20) {
const columns = Array(columnCount)
.fill(0)
.map((_, i) => `clm ${i}`);
.map((_, i) => `clm${i}`);

return Array(rowCount)
.fill(0)
Expand All @@ -24,7 +24,7 @@ export default function generateData(rowCount = 30, columnCount = 20) {
(prev, key, i) => {
const obj = prev;
// eslint-disable-next-line no-restricted-properties
obj[key] = Math.round(Math.random() * Math.pow(10, i));
obj[key] = Math.round(Math.random() * Math.pow(10, columnCount - i));

return obj;
},
Expand Down

0 comments on commit 12dd847

Please sign in to comment.