You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2022/01/27 01:05:17 UTC
[superset] 07/12: fix: SQL Lab sorting of non-numbers (#18006)
This is an automated email from the ASF dual-hosted git repository.
elizabeth pushed a commit to branch 1.4
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 5f2553d7c3bb1a1344a6924ca814bbe7658dfcfe
Author: Erik Ritter <er...@airbnb.com>
AuthorDate: Wed Jan 12 11:09:59 2022 -0800
fix: SQL Lab sorting of non-numbers (#18006)
---
.../FilterableTable/FilterableTable.test.tsx | 59 ++++++++++++++++++++++
.../components/FilterableTable/FilterableTable.tsx | 21 +++++---
2 files changed, 74 insertions(+), 6 deletions(-)
diff --git a/superset-frontend/src/components/FilterableTable/FilterableTable.test.tsx b/superset-frontend/src/components/FilterableTable/FilterableTable.test.tsx
index 77f7f71..fad9e82 100644
--- a/superset-frontend/src/components/FilterableTable/FilterableTable.test.tsx
+++ b/superset-frontend/src/components/FilterableTable/FilterableTable.test.tsx
@@ -271,4 +271,63 @@ describe('FilterableTable sorting - RTL', () => {
expect(gridCells[9]).toHaveTextContent('3439718.0300000007');
expect(gridCells[10]).toHaveTextContent('4528047.219999993');
});
+
+ it('sorts YYYY-MM-DD properly', () => {
+ const dsProps = {
+ orderedColumnKeys: ['ds'],
+ data: [
+ { ds: '2021-01-01' },
+ { ds: '2022-01-01' },
+ { ds: '2021-01-02' },
+ { ds: '2021-01-03' },
+ { ds: '2021-12-01' },
+ { ds: '2021-10-01' },
+ { ds: '2022-01-02' },
+ ],
+ height: 500,
+ };
+ render(<FilterableTable {...dsProps} />);
+
+ const dsColumn = screen.getByRole('columnheader', { name: 'ds' });
+ const gridCells = screen.getAllByRole('gridcell');
+
+ // Original order
+ expect(gridCells[0]).toHaveTextContent('2021-01-01');
+ expect(gridCells[1]).toHaveTextContent('2022-01-01');
+ expect(gridCells[2]).toHaveTextContent('2021-01-02');
+ expect(gridCells[3]).toHaveTextContent('2021-01-03');
+ expect(gridCells[4]).toHaveTextContent('2021-12-01');
+ expect(gridCells[5]).toHaveTextContent('2021-10-01');
+ expect(gridCells[6]).toHaveTextContent('2022-01-02');
+
+ // First click to sort ascending
+ userEvent.click(dsColumn);
+ expect(gridCells[0]).toHaveTextContent('2021-01-01');
+ expect(gridCells[1]).toHaveTextContent('2021-01-02');
+ expect(gridCells[2]).toHaveTextContent('2021-01-03');
+ expect(gridCells[3]).toHaveTextContent('2021-10-01');
+ expect(gridCells[4]).toHaveTextContent('2021-12-01');
+ expect(gridCells[5]).toHaveTextContent('2022-01-01');
+ expect(gridCells[6]).toHaveTextContent('2022-01-02');
+
+ // Second click to sort descending
+ userEvent.click(dsColumn);
+ expect(gridCells[0]).toHaveTextContent('2022-01-02');
+ expect(gridCells[1]).toHaveTextContent('2022-01-01');
+ expect(gridCells[2]).toHaveTextContent('2021-12-01');
+ expect(gridCells[3]).toHaveTextContent('2021-10-01');
+ expect(gridCells[4]).toHaveTextContent('2021-01-03');
+ expect(gridCells[5]).toHaveTextContent('2021-01-02');
+ expect(gridCells[6]).toHaveTextContent('2021-01-01');
+
+ // Third click to sort ascending again
+ userEvent.click(dsColumn);
+ expect(gridCells[0]).toHaveTextContent('2021-01-01');
+ expect(gridCells[1]).toHaveTextContent('2021-01-02');
+ expect(gridCells[2]).toHaveTextContent('2021-01-03');
+ expect(gridCells[3]).toHaveTextContent('2021-10-01');
+ expect(gridCells[4]).toHaveTextContent('2021-12-01');
+ expect(gridCells[5]).toHaveTextContent('2022-01-01');
+ expect(gridCells[6]).toHaveTextContent('2022-01-02');
+ });
});
diff --git a/superset-frontend/src/components/FilterableTable/FilterableTable.tsx b/superset-frontend/src/components/FilterableTable/FilterableTable.tsx
index 96bef2d..ece8c91 100644
--- a/superset-frontend/src/components/FilterableTable/FilterableTable.tsx
+++ b/superset-frontend/src/components/FilterableTable/FilterableTable.tsx
@@ -80,6 +80,10 @@ const JSON_TREE_THEME = {
base0E: '#ae81ff',
base0F: '#cc6633',
};
+// This regex handles all possible number formats in javascript, including ints, floats,
+// exponential notation, NaN, and Infinity.
+// See https://stackoverflow.com/a/30987109 for more details
+const ONLY_NUMBER_REGEX = /^(NaN|-?((\d*\.\d+|\d+)([Ee][+-]?\d+)?|Infinity))$/;
const StyledFilterableTable = styled.div`
height: 100%;
@@ -321,16 +325,21 @@ export default class FilterableTable extends PureComponent<
);
}
- // Parse any floating numbers so they'll sort correctly
- parseFloatingNums = (value: any) => {
- const floatValue = parseFloat(value);
- return Number.isNaN(floatValue) ? value : floatValue;
+ // Parse any numbers from strings so they'll sort correctly
+ parseNumberFromString = (value: string | number | null) => {
+ if (typeof value === 'string') {
+ if (ONLY_NUMBER_REGEX.test(value)) {
+ return parseFloat(value);
+ }
+ }
+
+ return value;
};
sortResults(sortBy: string, descending: boolean) {
return (a: Datum, b: Datum) => {
- const aValue = this.parseFloatingNums(a[sortBy]);
- const bValue = this.parseFloatingNums(b[sortBy]);
+ const aValue = this.parseNumberFromString(a[sortBy]);
+ const bValue = this.parseNumberFromString(b[sortBy]);
// equal items sort equally
if (aValue === bValue) {