Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sqllab): fix query results sorting #18666

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ describe('FilterableTable sorting - RTL', () => {
expect(gridCells[1]).toHaveTextContent('Bravo');
expect(gridCells[2]).toHaveTextContent('Alpha');

// Third click to sort ascending again
// Third click to clear sorting
userEvent.click(stringColumn);
expect(gridCells[0]).toHaveTextContent('Alpha');
expect(gridCells[1]).toHaveTextContent('Bravo');
expect(gridCells[0]).toHaveTextContent('Bravo');
expect(gridCells[1]).toHaveTextContent('Alpha');
expect(gridCells[2]).toHaveTextContent('Charlie');
});

Expand Down Expand Up @@ -151,10 +151,10 @@ describe('FilterableTable sorting - RTL', () => {
expect(gridCells[1]).toHaveTextContent('10');
expect(gridCells[2]).toHaveTextContent('0');

// Third click to sort ascending again
// Third click to clear sorting
userEvent.click(integerColumn);
expect(gridCells[0]).toHaveTextContent('0');
expect(gridCells[1]).toHaveTextContent('10');
expect(gridCells[0]).toHaveTextContent('10');
expect(gridCells[1]).toHaveTextContent('0');
expect(gridCells[2]).toHaveTextContent('100');
});

Expand Down Expand Up @@ -186,10 +186,10 @@ describe('FilterableTable sorting - RTL', () => {
expect(gridCells[1]).toHaveTextContent('45.67');
expect(gridCells[2]).toHaveTextContent('1.23');

// Third click to sort ascending again
// Third click to clear sorting
userEvent.click(floatColumn);
expect(gridCells[0]).toHaveTextContent('1.23');
expect(gridCells[1]).toHaveTextContent('45.67');
expect(gridCells[0]).toHaveTextContent('45.67');
expect(gridCells[1]).toHaveTextContent('1.23');
expect(gridCells[2]).toHaveTextContent('89.0000001');
});

Expand Down Expand Up @@ -257,17 +257,17 @@ describe('FilterableTable sorting - RTL', () => {
expect(gridCells[9]).toHaveTextContent('26260.210000000003');
expect(gridCells[10]).toHaveTextContent('24078.610000000004');

// Third click to sort ascending again
// Third click to clear sorting
userEvent.click(mixedFloatColumn);
expect(gridCells[0]).toHaveTextContent('24078.610000000004');
expect(gridCells[1]).toHaveTextContent('26260.210000000003');
expect(gridCells[2]).toHaveTextContent('28550.59');
expect(gridCells[3]).toHaveTextContent('48710.92');
expect(gridCells[4]).toHaveTextContent('72212.86');
expect(gridCells[5]).toHaveTextContent('98089.08000000002');
expect(gridCells[6]).toHaveTextContent('144729.96000000002');
expect(gridCells[7]).toHaveTextContent('145776.56');
expect(gridCells[8]).toHaveTextContent('152718.97999999998');
expect(gridCells[0]).toHaveTextContent('48710.92');
expect(gridCells[1]).toHaveTextContent('145776.56');
expect(gridCells[2]).toHaveTextContent('72212.86');
expect(gridCells[3]).toHaveTextContent('144729.96000000002');
expect(gridCells[4]).toHaveTextContent('26260.210000000003');
expect(gridCells[5]).toHaveTextContent('152718.97999999998');
expect(gridCells[6]).toHaveTextContent('28550.59');
expect(gridCells[7]).toHaveTextContent('24078.610000000004');
expect(gridCells[8]).toHaveTextContent('98089.08000000002');
expect(gridCells[9]).toHaveTextContent('3439718.0300000007');
expect(gridCells[10]).toHaveTextContent('4528047.219999993');
});
Expand Down Expand Up @@ -320,14 +320,14 @@ describe('FilterableTable sorting - RTL', () => {
expect(gridCells[5]).toHaveTextContent('2021-01-02');
expect(gridCells[6]).toHaveTextContent('2021-01-01');

// Third click to sort ascending again
// Third click to clear sorting
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[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('2022-01-01');
expect(gridCells[5]).toHaveTextContent('2021-10-01');
expect(gridCells[6]).toHaveTextContent('2022-01-02');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ interface FilterableTableProps {

interface FilterableTableState {
sortBy?: string;
sortDirection: SortDirectionType;
sortDirection?: SortDirectionType;
Copy link
Member

Choose a reason for hiding this comment

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

why is this optional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's because of the third unsorted state that I added. Before it was being set with an initial value of "DESC" but it would be unsorted because sortBy starts as undefined. On the first click it would be set to "ASC" and sortBy gets set to that columns name. So now I have it set as undefined/optional initially and then clicking will set it to "ASC" then "DESC" then back to undefined.

I don't really like using undefined like that and I prefer to use null but the in the react-virtualized typing for SortIndicator and Table they have sortDirection set as optional. So if i used null I would have to do a fallback to undefined anyways because of their typing

fitted: boolean;
displayedList: Datum[];
}

export default class FilterableTable extends PureComponent<
Expand Down Expand Up @@ -175,8 +176,8 @@ export default class FilterableTable extends PureComponent<
this.totalTableHeight = props.height;

this.state = {
sortDirection: SortDirection.ASC,
fitted: false,
displayedList: [...this.list],
Copy link
Member

Choose a reason for hiding this comment

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

is this the entirety of the data?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be all of it. The data gets formatted and set to the list variable in the constructor

constructor(props: FilterableTableProps) {
    super(props);
    this.list = this.formatTableData(props.data);

That's all the data that needs to be sorted from what I can tell. Lemme know if you think I missed something though

};

this.container = React.createRef();
Expand All @@ -191,7 +192,7 @@ export default class FilterableTable extends PureComponent<
}

getWidthsForColumns() {
const PADDING = 40; // accounts for cell padding and width of sorting icon
const PADDING = 50; // accounts for cell padding and width of sorting icon
const widthsByColumnKey = {};
const cellContent = ([] as string[]).concat(
...this.props.orderedColumnKeys.map(key => {
Expand Down Expand Up @@ -295,7 +296,31 @@ export default class FilterableTable extends PureComponent<
sortBy: string;
sortDirection: SortDirectionType;
}) {
this.setState({ sortBy, sortDirection });
let updatedState: FilterableTableState;

const shouldClearSort =
this.state.sortDirection === SortDirection.DESC &&
this.state.sortBy === sortBy;

if (shouldClearSort) {
updatedState = {
...this.state,
sortBy: undefined,
sortDirection: undefined,
displayedList: [...this.list],
};
} else {
updatedState = {
...this.state,
sortBy,
sortDirection,
displayedList: [...this.list].sort(
this.sortResults(sortBy, sortDirection === SortDirection.DESC),
),
};
}

this.setState(updatedState);
}

fitTableToWidthIfNeeded() {
Expand Down Expand Up @@ -362,6 +387,17 @@ export default class FilterableTable extends PureComponent<
};
}

sortGrid = (label: string) => {
this.sort({
sortBy: label,
sortDirection:
this.state.sortDirection === SortDirection.DESC ||
this.state.sortBy !== label
? SortDirection.ASC
: SortDirection.DESC,
});
};

renderTableHeader({
dataKey,
label,
Expand Down Expand Up @@ -425,8 +461,14 @@ export default class FilterableTable extends PureComponent<
: style.top,
}}
className={`${className} grid-cell grid-header-cell`}
role="columnheader"
tabIndex={columnIndex}
onClick={() => this.sortGrid(label)}
>
<div>{label}</div>
{label}
{this.state.sortBy === label && (
<SortIndicator sortDirection={this.state.sortDirection} />
)}
</div>
</Tooltip>
);
Expand All @@ -444,7 +486,7 @@ export default class FilterableTable extends PureComponent<
style: React.CSSProperties;
}) {
const columnKey = this.props.orderedColumnKeys[columnIndex];
const cellData = this.list[rowIndex][columnKey];
const cellData = this.state.displayedList[rowIndex][columnKey];
const cellText = this.getCellContent({ cellData, columnKey });
const content =
cellData === null ? <i className="text-muted">{cellText}</i> : cellText;
Expand Down Expand Up @@ -563,19 +605,13 @@ export default class FilterableTable extends PureComponent<
rowHeight,
} = this.props;

let sortedAndFilteredList = this.list;
let sortedAndFilteredList = this.state.displayedList;
// filter list
if (filterText) {
sortedAndFilteredList = this.list.filter((row: Datum) =>
sortedAndFilteredList = sortedAndFilteredList.filter((row: Datum) =>
this.hasMatch(filterText, row),
);
}
// sort list
if (sortBy) {
sortedAndFilteredList = sortedAndFilteredList.sort(
this.sortResults(sortBy, sortDirection === SortDirection.DESC),
);
}

let { height } = this.props;
let totalTableHeight = height;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@

.grid-header-cell {
font-weight: @font-weight-bold;
cursor: pointer;
}

.ReactVirtualized__Table__headerColumn:last-of-type,
Expand Down