Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

Commit

Permalink
Refactor table API (#446)
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc-Andre-Rivet authored Jun 7, 2019
1 parent 6d49d2d commit 1f6d4b4
Show file tree
Hide file tree
Showing 63 changed files with 1,425 additions and 1,526 deletions.
86 changes: 80 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,90 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Changed
[#446](https://github.com/plotly/dash-table/pull/446)
- Table API rework
#### NEW
- `column.sort_as_null`: Allows sorting behavior customization.
Accepts an array of string, number or booleans.

#### REMOVED
- `column.clearable`: Allows clearing the value of a dropdown cell.
Removed in favor of `dropdown_**` `clearable` nested property.
- `column.options`
Removed. Redundant with `dropdown`.
- `pagination_settings`
Replaced by two props `page_current` and `page_size`.

#### RENAMED
- `column_static_tooltip`
Renamed to `tooltip`.
- `column_conditional_tooltips`
Renamed to `tooltip_conditional`.
- `filter`
Renamed to `filter_query`.
- `sort_type`
Renamed to `sort_mode`.
- `derived_filter_structure`
Renamed to `derived_filter_query_structure`.

#### MODIFIED
- `column.deletable`: Allows column deletion.
Now accepts a boolean or an array of booleans (for multi-line headers).
For example, if there are multiple headers and you want the second header row to be deletable, this would be `[False, True]`.
- `column.editable_name`: Allows column renaming.
Renamed to `column.renamable`
Now accepts a boolean or an array of booleans (for multi-line headers).
For example, if there are multiple headers and you want the second row's header's name to be editable, this would be `[False, True]`.
- `column.id`
Now accepts `string` only -- `number` column ids can be casted to string.
- `n_fixed_columns`: Will fix columns to the left.
Renamed to `fixed_columns`
Now accepts an object { headers: boolean, data: number } instead of a number.
{ headers: true } determines the number of columns to fix automatically. For example, if the rows are selectable or deletable, { headers: true } would fix those columns automatically. If { headers: true, data: 2 }, it would fix the first two data columns in addition to the selectable and deletable if visible.
- `n_fixed_rows`: Will fix rows to the top.
Renamed to `fixed_rows`
Now accepts an object { headers: boolean, data: number } instead of a number.
{ headers: true } determines the number of rows to fix automatically (i.e. if there are multiple headers, it will fix all of them as well as the filter row).
{ headers: true, data: 2} would fix all of the header rows as well as the first 2 data rows.
- `pagination_mode`
Renamed to `page_action`.
`'fe'` is now `'native'`, `'be'` is now `'custom'`, and `false` is now '`none'`
- `column_static_dropdown`
Renamed to `dropdown`.
Now an object with each entry refering to a Column ID. Each nested prop expects.
`clearable` and `options`.
- `column_conditional_dropdowns`
Renamed to `dropdown_conditional`.
`condition` changed to the same `if` nested prop used by styles.
`dropdown` renamed to `options`.
- `dropdown_properties`
Renamed to `dropdown_data`.
Matches the `data` structure.
- `tooltips`
Renamed to `tooltip_data`.
Matches the `data` structure.
- `filtering`
Renamed to `filter_action`.
- `sorting`
Renamed to `sort_action`.
- `sorting_treat_empty_string_as_none`
Renamed to `sort_as_null`.
Now accepts an array of string, number or booleans that can be ignored during sort.
Table-level prop for the `column.sort_as_null` column nested prop.
- `style_data_conditional`
Renamed `filter` to `filter_query`.

### Added
[#456](https://github.com/plotly/dash-table/issues/456)
- Support for dash-table is now available for R users of Dash.

### Fixed
[#434](https://github.com/plotly/dash-table/issues/434)
- Fix CSS borders propeties overwrite style_* borders properties.
- Fix CSS borders properties overwrite style_* borders properties.

[#435](https://github.com/plotly/dash-table/issues/435)
- selected_cells background color is set through styling pipeline / derivations.
- selected_cells background color is set through styling pipeline / derivations.

## [3.7.0] - 2019-05-15
### Added
Expand Down Expand Up @@ -315,8 +389,8 @@ The remote URL path for the bundle was incorrect.
}

A+B = {
background_color: 'floralwhite', // from A, not overriden
color: 'black', // from B, A overriden
background_color: 'floralwhite', // from A, not overridden
color: 'black', // from B, A overridden
font_size: 22, // from B
font_type: 'monospace', // from A
width: 100 // from A
Expand Down Expand Up @@ -352,7 +426,7 @@ The remote URL path for the bundle was incorrect.
if: { column_id: string | number, header_index: number | 'odd' | 'even' },
...CSSProperties
}]
- All CSSProperties are supported in kebab-cass, camelCase and snake_case
- All CSSProperties are supported in kebab-case, camelCase and snake_case

### Changed
- Renaming 'dataframe' props to 'data'
Expand Down Expand Up @@ -637,7 +711,7 @@ Freeze Top Rows (Limitations)
Freeze Left Columns (Limitations)
- performance is highly impacted if the table is in a scrollable container as the frozen columns position has to be recalculated on each scroll event; impact is minimal up to 50-100 items and makes the table difficult to use with 250-500 items
- can't freeze rows and columns at the same time
- when using merged headers, make sure that the number of fixed columns respects the merged headers, otherwise there will be some unresolved visual bugs/artefacts
- when using merged headers, make sure that the number of fixed columns respects the merged headers, otherwise there will be some unresolved visual bugs/artifacts
- rows are assumed to all have the same height

Deletable Columns (Limitations)
Expand Down
4 changes: 2 additions & 2 deletions demo/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class App extends Component {
className='clear-filters'
onClick={() => {
const tableProps = R.clone(this.state.tableProps);
tableProps.filter = '';
tableProps.filter_query = '';

this.setState({ tableProps });
}}
Expand All @@ -53,7 +53,7 @@ class App extends Component {
}
onBlur={e => {
const tableProps = R.clone(this.state.tableProps);
tableProps.filter = e.target.value;
tableProps.filter_query = e.target.value;

this.setState({ tableProps });
}} />
Expand Down
77 changes: 36 additions & 41 deletions demo/AppMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import Environment from 'core/environment';

import { generateMockData, IDataMock, generateSpaceMockData } from './data';
import {
ContentStyle,
PropsWithDefaults,
ChangeAction,
ChangeFailure,
IVisibleColumn,
ColumnType
ColumnType,
TableAction
} from 'dash-table/components/Table/props';
import { TooltipSyntax } from 'dash-table/tooltips/props';

Expand Down Expand Up @@ -46,19 +46,19 @@ function getBaseTableProps(mock: IDataMock) {
on_change: {
action: ChangeAction.None
},
editable_name: true,
renamable: true,
deletable: true
})),
column_static_dropdown: [
{
id: 'bbb',
dropdown: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({
dropdown: {
bbb: {
clearable: true,
options: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({
label: i,
value: i
}))
}
],
pagination_mode: false,
},
page_action: TableAction.None,
style_table: {
max_height: '800px',
height: '800px',
Expand All @@ -77,24 +77,23 @@ function getBaseTableProps(mock: IDataMock) {
function getDefaultState(
generateData: Function = generateMockData
): {
filter: string,
filter_query: string,
tableProps: Partial<PropsWithDefaults>
} {
const mock = generateData(5000);

return {
filter: '',
filter_query: '',
tableProps: R.merge(getBaseTableProps(mock), {
data: mock.data,
editable: true,
sorting: true,
n_fixed_rows: 3,
n_fixed_columns: 2,
sort_action: TableAction.Native,
fixed_rows: { headers: true },
fixed_columns: { headers: true },
merge_duplicate_headers: false,
row_deletable: true,
row_selectable: 'single',
content_style: ContentStyle.Fit,
pagination_mode: 'fe'
page_action: TableAction.Native
}) as Partial<PropsWithDefaults>
};
}
Expand All @@ -113,16 +112,16 @@ function getReadonlyState() {

function getSpaceInColumn() {
const state = getDefaultState(generateSpaceMockData);
state.tableProps.filtering = true;
state.tableProps.filter_action = TableAction.Native;

return state;
}

function getFixedTooltipsState() {
const state = getTooltipsState();

state.tableProps.n_fixed_columns = 3;
state.tableProps.n_fixed_rows = 4;
state.tableProps.fixed_columns = { headers: true, data: 1 };
state.tableProps.fixed_rows = { headers: true, data: 1 };

return state;
}
Expand All @@ -132,25 +131,23 @@ function getTooltipsState() {

state.tableProps.tooltip_delay = 250;
state.tableProps.tooltip_duration = 1000;
state.tableProps.tooltips = {
ccc: [
{ type: TooltipSyntax.Markdown, value: `### Go Proverb\nThe enemy's key point is yours` },
{ type: TooltipSyntax.Markdown, value: `### Go Proverb\nPlay on the point of symmetry` },
{ type: TooltipSyntax.Markdown, value: `### Go Proverb\nSente gains nothing` },
{ type: TooltipSyntax.Text, value: `Beware of going back to patch up` },
{ type: TooltipSyntax.Text, value: `When in doubt, Tenuki` },
`People in glass houses shouldn't throw stones`
]
};
state.tableProps.column_static_tooltip = {
state.tableProps.tooltip_data = [
{ ccc: { type: TooltipSyntax.Markdown, value: `### Go Proverb\nThe enemy's key point is yours` } },
{ ccc: { type: TooltipSyntax.Markdown, value: `### Go Proverb\nPlay on the point of symmetry` } },
{ ccc: { type: TooltipSyntax.Markdown, value: `### Go Proverb\nSente gains nothing` } },
{ ccc: { type: TooltipSyntax.Text, value: `Beware of going back to patch up` } },
{ ccc: { type: TooltipSyntax.Text, value: `When in doubt, Tenuki` } },
{ ccc: `People in glass houses should not throw stones` }
];
state.tableProps.tooltip = {
ccc: { type: TooltipSyntax.Text, value: `There is death in the hane` },
ddd: { type: TooltipSyntax.Markdown, value: `Hane, Cut, Placement` },
rows: `Learn the eyestealing tesuji`
};
state.tableProps.column_conditional_tooltips = [{
state.tableProps.tooltip_conditional = [{
if: {
column_id: 'aaa-readonly',
filter: `{aaa} is prime`
filter_query: `{aaa} is prime`
},
type: TooltipSyntax.Markdown,
value: `### Go Proverbs\nCapture three to get an eye`
Expand Down Expand Up @@ -218,7 +215,7 @@ function getDateState() {

function getFilteringState() {
const state = getDefaultState();
state.tableProps.filtering = true;
state.tableProps.filter_action = TableAction.Native;

return state;
}
Expand All @@ -227,15 +224,14 @@ function getVirtualizedState() {
const mock = generateMockData(5000);

return {
filter: '',
filter_query: '',
tableProps: R.merge(getBaseTableProps(mock), {
data: mock.data,
editable: true,
sorting: true,
sort_action: TableAction.Native,
merge_duplicate_headers: false,
row_deletable: true,
row_selectable: 'single',
content_style: 'fit',
virtualization: true
})
};
Expand All @@ -245,17 +241,16 @@ function getFixedVirtualizedState() {
const mock = generateMockData(5000);

return {
filter: '',
filter_query: '',
tableProps: R.merge(getBaseTableProps(mock), {
data: mock.data,
editable: true,
sorting: true,
n_fixed_rows: 3,
n_fixed_columns: 2,
sort_action: TableAction.Native,
fixed_rows: { headers: true },
fixed_columns: { headers: true },
merge_duplicate_headers: false,
row_deletable: true,
row_selectable: 'single',
content_style: 'fit',
virtualization: true
})
};
Expand Down
7 changes: 0 additions & 7 deletions demo/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export const generateMockData = (rows: number) => unpackIntoColumnsAndData([
name: ['', 'Weather', 'Climate'],
type: ColumnType.Text,
presentation: 'dropdown',
clearable: true,
data: gendata(
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4],
rows
Expand Down Expand Up @@ -141,7 +140,6 @@ export const generateSpaceMockData = (rows: number) => unpackIntoColumnsAndData(
name: ['', 'Weather', 'Climate'],
type: ColumnType.Text,
presentation: 'dropdown',
clearable: true,
data: gendata(
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4],
rows
Expand All @@ -162,11 +160,6 @@ export const mockDataSimple = (rows: number) => unpackIntoColumnsAndData([
name: 'Climate',
type: ColumnType.Text,
presentation: 'dropdown',
options: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({
label: i,
value: i
})),
clearable: true,
data: gendata(
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4],
rows
Expand Down
12 changes: 6 additions & 6 deletions generator/cssPropertiesGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ camels.forEach(([camel]) => map.set(camel, camel));

const fs = require('fs');

var stream1 = fs.createWriteStream("src/dash-table/derived/style/py2jsCssProperties.ts");
var stream1 = fs.createWriteStream('src/dash-table/derived/style/py2jsCssProperties.ts');
stream1.once('open', () => {
stream1.write('export type StyleProperty = string | number;\n');
stream1.write('\n');
Expand All @@ -317,25 +317,25 @@ stream1.once('open', () => {
first = false;
stream1.write(` ['${key}', '${value}']`);
});
stream1.write('\n]);')
stream1.write('\n]);');

stream1.end();
});

var stream2 = fs.createWriteStream("src/dash-table/derived/style/IStyle.ts");
var stream2 = fs.createWriteStream('src/dash-table/derived/style/IStyle.ts');
stream2.once('open', () => {
stream2.write(`import { StyleProperty } from './ py2jsCssProperties';\n`);
stream2.write('\n');
stream2.write('export default interface IStyle {\n');
camels.forEach(([key]) => {
stream2.write(` ${key}: StyleProperty;\n`);
});
stream2.write('}')
stream2.write('}');

stream2.end();
});

var stream3 = fs.createWriteStream("proptypes.js");
var stream3 = fs.createWriteStream('proptypes.js');
stream3.once('open', () => {
let first = true;
map.forEach((value, key) => {
Expand All @@ -350,7 +350,7 @@ stream3.once('open', () => {
stream3.write(` ${key}: PropTypes.oneOfType([PropTypes.string, PropTypes.number])`);
}
});
stream3.write('\n')
stream3.write('\n');

stream3.end();
});
Loading

0 comments on commit 1f6d4b4

Please sign in to comment.