Skip to content

Commit

Permalink
Issue 342- Add column type support for conditionals (plotly#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc-Andre-Rivet committed Feb 11, 2019
1 parent f8d8cee commit e1af346
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 18 deletions.
13 changes: 13 additions & 0 deletions packages/dash-table/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
[#342](https://github.com/plotly/dash-core/issues/342)
- Added `column_type` condition to style `if`; allows applying styles based on the type of the column for props
- `style_cell_conditional`
- `style_data_conditional`
- `style_filter_conditional`
- `style_header_conditional`

### Fixed
[#342](https://github.com/plotly/dash-core/issues/342)
- Added already supported `filter` nested prop / condition to `style_data_conditional` props definition

## [3.4.0] - 2019-02-08
### Added
[#364](https://github.com/plotly/dash-table/pull/364)
Expand Down
6 changes: 3 additions & 3 deletions packages/dash-table/dash_table/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/dash-table/dash_table/bundle.js.map

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.

2 changes: 1 addition & 1 deletion packages/dash-table/dash_table/demo.js.map

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions packages/dash-table/dash_table/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,24 @@
}
],
"required": false
},
"column_type": {
"name": "enum",
"value": [
{
"value": "'any'",
"computed": false
},
{
"value": "'numeric'",
"computed": false
},
{
"value": "'text'",
"computed": false
}
],
"required": false
}
},
"required": false
Expand Down Expand Up @@ -1083,6 +1101,28 @@
],
"required": false
},
"column_type": {
"name": "enum",
"value": [
{
"value": "'any'",
"computed": false
},
{
"value": "'numeric'",
"computed": false
},
{
"value": "'text'",
"computed": false
}
],
"required": false
},
"filter": {
"name": "string",
"required": false
},
"row_index": {
"name": "union",
"value": [
Expand Down Expand Up @@ -1138,6 +1178,24 @@
}
],
"required": false
},
"column_type": {
"name": "enum",
"value": [
{
"value": "'any'",
"computed": false
},
{
"value": "'numeric'",
"computed": false
},
{
"value": "'text'",
"computed": false
}
],
"required": false
}
},
"required": false
Expand Down Expand Up @@ -1169,6 +1227,24 @@
],
"required": false
},
"column_type": {
"name": "enum",
"value": [
{
"value": "'any'",
"computed": false
},
{
"value": "'numeric'",
"computed": false
},
{
"value": "'text'",
"computed": false
}
],
"required": false
},
"header_index": {
"name": "union",
"value": [
Expand Down
9 changes: 7 additions & 2 deletions packages/dash-table/src/dash-table/DataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,8 @@ export const propTypes = {
style_cell_conditional: PropTypes.arrayOf(PropTypes.shape({
// .exact
if: PropTypes.shape({
column_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
column_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
column_type: PropTypes.oneOf(['any', 'numeric', 'text'])
})
})),

Expand All @@ -874,6 +875,8 @@ export const propTypes = {
// .exact
if: PropTypes.shape({
column_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
column_type: PropTypes.oneOf(['any', 'numeric', 'text']),
filter: PropTypes.string,
row_index: PropTypes.oneOfType([
PropTypes.number,
PropTypes.oneOf(['odd', 'even'])
Expand All @@ -889,7 +892,8 @@ export const propTypes = {
style_filter_conditional: PropTypes.arrayOf(PropTypes.shape({
// .exact
if: PropTypes.shape({
column_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
column_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
column_type: PropTypes.oneOf(['any', 'numeric', 'text'])
})
})),

Expand All @@ -902,6 +906,7 @@ export const propTypes = {
// .exact
if: PropTypes.shape({
column_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
column_type: PropTypes.oneOf(['any', 'numeric', 'text']),
header_index: PropTypes.oneOfType([
PropTypes.number,
PropTypes.oneOf(['odd', 'even'])
Expand Down
20 changes: 15 additions & 5 deletions packages/dash-table/src/dash-table/conditional/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnId, Datum } from 'dash-table/components/Table/props';
import { ColumnId, Datum, ColumnType } from 'dash-table/components/Table/props';
import SyntaxTree from 'core/syntax-tree';

export interface IConditionalElement {
Expand All @@ -17,10 +17,14 @@ export interface INamedElement {
column_id?: ColumnId;
}

export type ConditionalBasicFilter = INamedElement;
export type ConditionalDataCell = IConditionalElement & IIndexedRowElement & INamedElement;
export type ConditionalCell = INamedElement;
export type ConditionalHeader = IIndexedHeaderElement & INamedElement;
export interface ITypedElement {
column_type?: ColumnType;
}

export type ConditionalBasicFilter = INamedElement & ITypedElement;
export type ConditionalDataCell = IConditionalElement & IIndexedRowElement & INamedElement & ITypedElement;
export type ConditionalCell = INamedElement & ITypedElement;
export type ConditionalHeader = IIndexedHeaderElement & INamedElement & ITypedElement;

function ifAstFilter(ast: SyntaxTree, datum: Datum) {
return ast.isValid && ast.evaluate(datum);
Expand All @@ -32,6 +36,12 @@ export function ifColumnId(condition: INamedElement | undefined, columnId: Colum
condition.column_id === columnId;
}

export function ifColumnType(condition: ITypedElement | undefined, columnType?: ColumnType) {
return !condition ||
condition.column_type === undefined ||
condition.column_type === (columnType || ColumnType.Any);
}

export function ifRowIndex(condition: IIndexedRowElement | undefined, rowIndex: number) {
if (!condition ||
condition.row_index === undefined) {
Expand Down
12 changes: 9 additions & 3 deletions packages/dash-table/src/dash-table/derived/style/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import {
IIndexedHeaderElement,
IIndexedRowElement,
INamedElement,
ifColumnId
ITypedElement,
ifColumnId,
ifColumnType
} from 'dash-table/conditional';

export interface IConvertedStyle {
Expand All @@ -31,15 +33,19 @@ export interface IConvertedStyle {
matchesFilter: (datum: Datum) => boolean;
}

type GenericIf = Partial<IConditionalElement & IIndexedHeaderElement & IIndexedRowElement & INamedElement>;
type GenericIf = Partial<IConditionalElement & IIndexedHeaderElement & IIndexedRowElement & INamedElement & ITypedElement>;
type GenericStyle = Style & Partial<{ if: GenericIf }>;

function convertElement(style: GenericStyle) {
const indexFilter = style.if && (style.if.header_index || style.if.row_index);
let ast: SyntaxTree;

return {
matchesColumn: (column: IVisibleColumn) => ifColumnId(style.if, column.id),
matchesColumn: (column: IVisibleColumn) =>
!style.if || (
ifColumnId(style.if, column.id) &&
ifColumnType(style.if, column.type)
),
matchesRow: (index: number) =>
indexFilter === undefined ?
true :
Expand Down
40 changes: 40 additions & 0 deletions packages/dash-table/tests/visual/percy-storybook/Style.percy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import DataTable from 'dash-table/DataTable';
import fixtures from './fixtures';
import { ColumnType } from 'dash-table/components/Table/props';

const setProps = () => { };

// Legacy: Tests previously run in Python
const fixtureStories = storiesOf('DashTable/Fixtures', module);
fixtures.forEach(fixture => fixtureStories.add(fixture.name, () => (<DataTable {...Object.assign(fixture.props)} />)));

storiesOf('DashTable/Style type condition', module)
.add('with 1 column', () => (<DataTable
setProps={setProps}
id='table'
data={[
{ a: 1, b: 2, c: '3', d: '4', e: 5, f: 6, g: 7, h: 8 },
{ a: 11, b: 22, c: '33', d: '44', e: 55, f: 66, g: 77, h: 88 },
{ a: 111, b: 222, c: '333', d: '444', e: 555, f: 666, g: 777, h: 888 }
]}
columns={[
{ id: 'a', name: 'A', type: ColumnType.Any },
{ id: 'b', name: 'B', type: ColumnType.Any },
{ id: 'c', name: 'C', type: ColumnType.Text },
{ id: 'd', name: 'D', type: ColumnType.Text },
{ id: 'e', name: 'E', type: ColumnType.Numeric },
{ id: 'f', name: 'F', type: ColumnType.Numeric },
{ id: 'g', name: 'G' },
{ id: 'h', name: 'H' }
]}
style_data_conditional={[
{ if: { column_type: ColumnType.Any, row_index: 'even' }, background_color: 'blue', color: 'white' },
{ if: { column_type: ColumnType.Text, row_index: 'even' }, background_color: 'red', color: 'white' },
{ if: { column_type: ColumnType.Numeric, row_index: 'even' }, background_color: 'green', color: 'white' },
{ if: { column_type: ColumnType.Any }, background_color: 'blue' },
{ if: { column_type: ColumnType.Text }, background_color: 'red' },
{ if: { column_type: ColumnType.Numeric }, background_color: 'green' }
]}
/>));

0 comments on commit e1af346

Please sign in to comment.