Skip to content

Commit

Permalink
3.0 to multi sort or not (#58)
Browse files Browse the repository at this point in the history
* - refactor: isolate dash component layer from component implementation
- duplicate component contract in TS

* update for build js/py

* - fix python component packaging regression
- bump version to rc6

* Fix visual tests regression

* (wip) refactor controlled table

* @types

* refactor table clipboard usage

* clean up

* rename

* pr review fixes

* fix bug in test script

* fix test

* update test script

* fix tests

* fix tests

* tests -- remove async/await syntax

* fix tests

* - remove row component
- 3 tables for fixed rows/columns and content
- update TS props

* remove test code

* fix test

* remove test / broken by Cypress.io

* cypress version

* fix cell selection test

* fix percy tests

* prevent useless cell updates once again

* styling, copy/paste, navigation regressions

* build, variables renamed

* fix next/previous regression

* fix test regressions

* table styling regression

* - fixed rows/columns regression testing + fixes
- percy tests for fixed rows/columns

* fix test?

* fix test?

* revert percy removal

* multi and single column sorting support

* basic sorting e2e test

* linting

* - add runtime logger configuration override
- fix scrolling issue in prod environment

* - fix merged cells / hidden cells w/ fixed col & rows
- additional visual tests for merged, fixed, hidden combo

* remove .only

* - fix delete / select when sorted/filtered
- additional tests for delete/select when sorted/filtered

* fix copy/paste regression

* bumping version to rc7

* fix percy tests
  • Loading branch information
Marc-Andre-Rivet committed Sep 6, 2018
1 parent 0e8321f commit c45fb00
Show file tree
Hide file tree
Showing 28 changed files with 413 additions and 160 deletions.
5 changes: 5 additions & 0 deletions packages/dash-table/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# Changelog

## RC6 - Sorting props

- Additional sorting_type prop that can take value 'multi' or 'single'
This prop defines whether the user can sort based on multiple columns or can only sort by one column at a time. The default value is 'single'.
6 changes: 3 additions & 3 deletions packages/dash-table/dash_table/bundle.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions packages/dash-table/dash_table/demo.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions packages/dash-table/dash_table/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,27 @@
"computed": false
}
},
"sorting_type": {
"type": {
"name": "enum",
"value": [
{
"value": "'single'",
"computed": false
},
{
"value": "'multi'",
"computed": false
}
]
},
"required": false,
"description": "",
"defaultValue": {
"value": "'single'",
"computed": false
}
},
"sorting_settings": {
"type": {
"name": "arrayOf",
Expand Down
2 changes: 1 addition & 1 deletion packages/dash-table/dash_table/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dash-table",
"version": "3.0.0rc6",
"version": "3.0.0rc7",
"description": "Dash table",
"main": "build/index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/dash-table/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dash-table",
"version": "3.0.0rc6",
"version": "3.0.0rc7",
"description": "Dash table",
"main": "build/index.js",
"scripts": {
Expand Down
28 changes: 0 additions & 28 deletions packages/dash-table/src/core/sorting/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as R from 'ramda';
import Logger from 'core/Logger';

export interface ISortSetting {
columnId: string | number;
Expand All @@ -14,33 +13,6 @@ export enum SortDirection {

export type SortSettings = ISortSetting[];

export function updateSettings(
settings: SortSettings,
setting: ISortSetting
): SortSettings {
Logger.trace('updateSettings', settings, setting);

settings = R.clone(settings);

if (setting.direction === SortDirection.None) {
const currentIndex = R.findIndex(s => s.columnId === setting.columnId, settings);

if (currentIndex !== -1) {
settings.splice(currentIndex, 1);
}
} else {
const currentSetting = R.find(s => s.columnId === setting.columnId, settings);

if (currentSetting) {
currentSetting.direction = setting.direction;
} else {
settings.push(setting);
}
}

return settings;
}

export default (dataframe: any[], settings: SortSettings): any[] => {
if (!settings.length) {
return dataframe;
Expand Down
31 changes: 31 additions & 0 deletions packages/dash-table/src/core/sorting/multi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as R from 'ramda';

import Logger from 'core/Logger';
import { SortSettings, ISortSetting, SortDirection } from 'core/sorting';

export default (
settings: SortSettings,
setting: ISortSetting
): SortSettings => {
Logger.trace('multi - updateSettings', settings, setting);

settings = R.clone(settings);

if (setting.direction === SortDirection.None) {
const currentIndex = R.findIndex(s => s.columnId === setting.columnId, settings);

if (currentIndex !== -1) {
settings.splice(currentIndex, 1);
}
} else {
const currentSetting = R.find(s => s.columnId === setting.columnId, settings);

if (currentSetting) {
currentSetting.direction = setting.direction;
} else {
settings.push(setting);
}
}

return settings;
};
13 changes: 13 additions & 0 deletions packages/dash-table/src/core/sorting/single.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Logger from 'core/Logger';
import { SortSettings, ISortSetting, SortDirection } from 'core/sorting';

export default (
settings: SortSettings,
setting: ISortSetting
): SortSettings => {
Logger.trace('single - updateSettings', settings, setting);

return setting.direction === SortDirection.None ?
[] :
[setting];
};
2 changes: 2 additions & 0 deletions packages/dash-table/src/dash-table/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const defaultProps = {
filtering: false,
filtering_settings: '',
sorting: false,
sorting_type: 'single',
sorting_settings: [],

virtual_dataframe: [],
Expand Down Expand Up @@ -156,6 +157,7 @@ export const propTypes = {
filtering_settings: PropTypes.string,

sorting: PropTypes.oneOf(['fe', 'be', true, false]),
sorting_type: PropTypes.oneOf(['single', 'multi']),
sorting_settings: PropTypes.arrayOf(PropTypes.shape({
columnId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
direction: PropTypes.oneOf(['asc', 'desc'])
Expand Down
3 changes: 1 addition & 2 deletions packages/dash-table/src/dash-table/components/Cell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,9 @@ export default class Cell extends Component<ICellProps, ICellState> {
}

componentWillReceiveProps(nextProps: ICellPropsWithDefaults) {
const { value } = this.props;
const { value: nextValue } = nextProps;

if (value !== nextValue) {
if (this.state.value !== nextValue) {
this.setState({
value: nextValue
});
Expand Down
35 changes: 19 additions & 16 deletions packages/dash-table/src/dash-table/components/CellFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as R from 'ramda';
import React from 'react';

import Cell from 'dash-table/components/Cell';
import { ICellFactoryOptions, SelectedCells, Dataframe } from 'dash-table/components/Table/props';
import { ICellFactoryOptions, SelectedCells } from 'dash-table/components/Table/props';
import * as actions from 'dash-table/utils/actions';

export default class CellFactory {
Expand Down Expand Up @@ -122,13 +122,11 @@ export default class CellFactory {
private handleChange = (idx: number, i: number, e: any) => {
const {
columns,
dataframe,
editable,
setProps,
virtualizer
setProps
} = this.props;

const { dataframe } = virtualizer;

const c = columns[i];

if (!editable) {
Expand Down Expand Up @@ -204,7 +202,7 @@ export default class CellFactory {
</td>);
}

public createCells(dataframe: Dataframe) {
public createCells() {
const {
active_cell,
columns,
Expand All @@ -217,18 +215,23 @@ export default class CellFactory {
is_focused,
row_deletable,
row_selectable,
selected_cell
selected_cell,
virtualizer
} = this.props;

const { dataframe, indices } = virtualizer;

const visibleColumns = columns.filter(column => !column.hidden);

const offset =
(row_deletable ? 1 : 0) +
(row_selectable ? 1 : 0);

return dataframe.map((datum, rowIndex) => {
const deleteCell = this.rowDeleteCell(rowIndex);
const selectCell = this.rowSelectCell(rowIndex);
return dataframe.map((datum, virtualIdx) => {
const realIdx = indices[virtualIdx];

const deleteCell = this.rowDeleteCell(realIdx);
const selectCell = this.rowSelectCell(realIdx);

const cells = visibleColumns.map((column, visibleIndex) => {
visibleIndex += offset;
Expand All @@ -251,20 +254,20 @@ export default class CellFactory {

return (<Cell
key={`${column.id}-${visibleIndex}`}
active={active_cell[0] === rowIndex && active_cell[1] === index + offset}
active={active_cell[0] === virtualIdx && active_cell[1] === index + offset}
classes={classes}
clearable={column.clearable}
conditionalDropdowns={conditionalDropdowns}
conditionalStyles={conditionalStyles}
datum={datum}
editable={editable}
focused={!!is_focused}
onClick={this.getEventHandler(this.handleClick, rowIndex, index)}
onDoubleClick={this.getEventHandler(this.handleDoubleClick, rowIndex, index)}
onPaste={this.getEventHandler(this.handlePaste, rowIndex, index)}
onChange={this.getEventHandler(this.handleChange, rowIndex, index)}
onClick={this.getEventHandler(this.handleClick, virtualIdx, index)}
onDoubleClick={this.getEventHandler(this.handleDoubleClick, virtualIdx, index)}
onPaste={this.getEventHandler(this.handlePaste, virtualIdx, index)}
onChange={this.getEventHandler(this.handleChange, realIdx, index)}
property={column.id}
selected={R.contains([rowIndex, index + offset], selected_cell)}
selected={R.contains([virtualIdx, index + offset], selected_cell)}
staticDropdown={staticDropdown}
staticStyle={staticStyle}
tableId={id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import HeaderCellFactory, { DEFAULT_CELL_WIDTH } from 'dash-table/components/Hea
import Logger from 'core/Logger';
import TableClipboardHelper from 'dash-table/utils/TableClipboardHelper';
import CellFactory from 'dash-table/components/CellFactory';
import { ControlledTableProps, Dataframe, Columns, RowSelection } from 'dash-table/components/Table/props';
import { ControlledTableProps, Columns, RowSelection } from 'dash-table/components/Table/props';

const sortNumerical = R.sort<number>((a, b) => a - b);

Expand Down Expand Up @@ -559,10 +559,10 @@ export default class ControlledTable extends Component<ControlledTableProps> {
null
)

getFragments = (dataframe: Dataframe, fixedColumns: number, fixedRows: number) => {
getFragments = (fixedColumns: number, fixedRows: number) => {
const cells = [
...HeaderCellFactory.createHeaders(this.props),
...this.cellFactory.createCells(dataframe)
...this.cellFactory.createCells()
];

// slice out fixed columns
Expand Down Expand Up @@ -611,12 +611,9 @@ export default class ControlledTable extends Component<ControlledTableProps> {
n_fixed_columns,
n_fixed_rows,
row_deletable,
row_selectable,
virtualizer
row_selectable
} = this.props;

const dataframe = virtualizer.dataframe;

this.applyStyle(columns, row_deletable, row_selectable);

const classes = [
Expand All @@ -625,7 +622,7 @@ export default class ControlledTable extends Component<ControlledTableProps> {
...(n_fixed_columns ? ['freeze-left'] : [])
];

const grid = this.getFragments(dataframe, n_fixed_columns, n_fixed_rows);
const grid = this.getFragments(n_fixed_columns, n_fixed_rows);

return (<div id={id}>
<div className='dash-spreadsheet-container'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import React from 'react';
import * as R from 'ramda';

import Stylesheet from 'core/Stylesheet';
import { updateSettings, SortDirection, SortSettings } from 'core/sorting';
import { SortDirection, SortSettings } from 'core/sorting';
import multiUpdateSettings from 'core/sorting/multi';
import singleUpdateSettings from 'core/sorting/single';

import * as actions from 'dash-table/utils/actions';
import { RowSelection, SetProps } from 'dash-table/components/Table/props';
import { RowSelection, SetProps, SortingType } from 'dash-table/components/Table/props';

export const DEFAULT_CELL_WIDTH = 200;

Expand All @@ -21,6 +23,7 @@ interface ICellOptions {
rowSorting: string | boolean;
setProps: SetProps;
sorting_settings: SortSettings;
sorting_type: SortingType;
virtualization: any;
}

Expand All @@ -36,6 +39,7 @@ interface IOptions {
setProps: SetProps;
sorting: string | boolean;
sorting_settings: SortSettings;
sorting_type: SortingType;
virtualization: any;
}

Expand Down Expand Up @@ -65,7 +69,7 @@ export default class HeaderFactory {

private static doSort(columnId: string | number, options: ICellOptions) {
return () => {
const { sorting_settings } = options;
const { sorting_settings, sorting_type } = options;

let direction: SortDirection;
switch (HeaderFactory.getSorting(columnId, sorting_settings)) {
Expand All @@ -81,8 +85,12 @@ export default class HeaderFactory {
break;
}

const sortingStrategy = sorting_type === 'single' ?
singleUpdateSettings :
multiUpdateSettings;

options.setProps({
sorting_settings: updateSettings(
sorting_settings: sortingStrategy(
sorting_settings,
{ columnId, direction }
)
Expand Down Expand Up @@ -267,6 +275,7 @@ export default class HeaderFactory {
row_selectable,
setProps,
sorting_settings,
sorting_type,
virtualization
} = options;

Expand All @@ -290,6 +299,7 @@ export default class HeaderFactory {
rowSorting: sorting,
setProps,
sorting_settings,
sorting_type,
virtualization
}))
]];
Expand All @@ -316,6 +326,7 @@ export default class HeaderFactory {
i + 1 !== headerDepth,
setProps,
sorting_settings,
sorting_type,
virtualization
}))
]));
Expand Down
Loading

0 comments on commit c45fb00

Please sign in to comment.