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

Commit 989d8cd

Browse files
Improve Filtering (#397)
1 parent 7a308b9 commit 989d8cd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2117
-1881
lines changed

.circleci/config.yml

Lines changed: 6 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: 2
22

33
jobs:
4-
"test-v0":
4+
"test":
55
docker:
66
- image: circleci/python:3.6.7-node-browsers
77
- image: cypress/base:10
@@ -30,67 +30,7 @@ jobs:
3030
sudo pip install --upgrade virtualenv
3131
python -m venv venv || virtualenv venv
3232
. venv/bin/activate
33-
pip install -r requirements-base.txt --quiet
34-
35-
- run:
36-
name: Install dependencies (dash)
37-
command: |
38-
git clone [email protected]:plotly/dash.git
39-
git clone [email protected]:plotly/dash-renderer.git
40-
git clone [email protected]:plotly/dash-core-components.git
41-
git clone [email protected]:plotly/dash-html-components.git
42-
. venv/bin/activate
43-
pip install -e ./dash --quiet
44-
cd dash-renderer && npm install --ignore-scripts && npm run build && pip install -e . && cd ..
45-
cd dash-core-components && npm install --ignore-scripts && npm run build && pip install -e . && cd ..
46-
cd dash-html-components && npm install --ignore-scripts && npm run build && pip install -e . && cd ..
47-
48-
- run:
49-
name: Build
50-
command: |
51-
. venv/bin/activate
52-
npm run private::build:js-test
53-
npm run private::build:py
54-
pip install -e .
55-
56-
- run:
57-
name: Run tests
58-
command: |
59-
. venv/bin/activate
60-
npm run test-v0
61-
62-
63-
"test-v1":
64-
docker:
65-
- image: circleci/python:3.6.7-node-browsers
66-
- image: cypress/base:10
67-
68-
steps:
69-
- checkout
70-
- restore_cache:
71-
key: deps1-{{ .Branch }}-{{ checksum "package-lock.json" }}-{{ checksum "package.json" }}-{{ checksum ".circleci/config.yml" }}
72-
- run:
73-
name: Install npm packages
74-
command: npm install
75-
- run:
76-
name: Cypress Install
77-
command: |
78-
$(npm bin)/cypress install
79-
80-
- save_cache:
81-
key: deps1-{{ .Branch }}-{{ checksum "package-lock.json" }}-{{ checksum "package.json" }}-{{ checksum ".circleci/config.yml" }}
82-
paths:
83-
- node_modules
84-
- /home/circleci/.cache/Cypress
85-
86-
- run:
87-
name: Install requirements
88-
command: |
89-
sudo pip install --upgrade virtualenv
90-
python -m venv venv || virtualenv venv
91-
. venv/bin/activate
92-
pip install -r requirements-base.txt --quiet
93-
pip install -r requirements-v1.txt --quiet
33+
pip install -r requirements.txt --quiet
9434
9535
- run:
9636
name: Build
@@ -104,7 +44,7 @@ jobs:
10444
name: Run tests
10545
command: |
10646
. venv/bin/activate
107-
npm run test-v1
47+
npm run test
10848
10949
11050
"visual-test":
@@ -172,7 +112,7 @@ jobs:
172112
when: always
173113

174114

175-
"python-3.6-v0":
115+
"python-3.6":
176116
docker:
177117
- image: circleci/python:3.6.7-stretch-node-browsers
178118

@@ -224,53 +164,11 @@ jobs:
224164
python -m unittest tests.dash.test_integration
225165
226166
227-
"python-3.6-v1":
228-
docker:
229-
- image: circleci/python:3.6.7-stretch-node-browsers
230-
231-
environment:
232-
PERCY_ENABLED: True
233-
PERCY_PROJECT: plotly/dash-table-python-v1
234-
235-
steps:
236-
- checkout
237-
238-
- run:
239-
name: Inject Percy Environment variables
240-
command: |
241-
echo 'export PERCY_TOKEN="$PERCY_PYTHON_TOKEN_V1"' >> $BASH_ENV
242-
243-
- run:
244-
name: Install requirements
245-
command: |
246-
sudo pip install --upgrade virtualenv
247-
python -m venv venv || virtualenv venv
248-
. venv/bin/activate
249-
pip install -r requirements-base.txt --quiet
250-
pip install -r requirements-v1.txt --quiet
251-
npm install
252-
253-
- run:
254-
name: Install test requirements
255-
command: |
256-
. venv/bin/activate
257-
npm run build
258-
pip install -e .
259-
260-
- run:
261-
name: Run integration tests
262-
command: |
263-
. venv/bin/activate
264-
python -m unittest tests.dash.test_integration
265-
266-
267167
workflows:
268168
version: 2
269169
build:
270170
jobs:
271-
- "python-3.6-v0"
272-
- "python-3.6-v1"
171+
- "python-3.6"
273172
- "node"
274-
- "test-v0"
275-
- "test-v1"
173+
- "test"
276174
- "visual-test"

.config/webpack/base.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ module.exports = (preprocessor = {}, mode = 'development') => {
4343
test: /demo[/\\]index.html?$/,
4444
loader: 'file-loader?name=index.[ext]'
4545
},
46+
{
47+
test: /\.csv$/,
48+
loader: 'raw-loader'
49+
},
4650
{
4751
test: /\.ts(x?)$/,
4852
exclude: /node_modules/,

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## [Unreleased]
6+
### Added
7+
[#397](https://github.com/plotly/dash-table/pull/397)
8+
- Improve filtering syntax and capabilities
9+
- new field syntax `{myField}`
10+
- short form by-column filter
11+
- implicit column and `eq` operator (e.g `"value"`)
12+
- implicit column (e.g `ne "value"`)
13+
- explicit form (e.g `{field} ne "value"`)
14+
- new `contains` relational operator for strings
15+
- new readonly `derived_filter_structure` prop exposing the query structure in a programmatically friendlier way
16+
17+
### Changed
18+
[#397](https://github.com/plotly/dash-table/pull/397)
19+
- Rename `filtering_settings` to `filter`
20+
521
## [3.6.0] - 2019-03-04
622
### Fixed
723
[#189](https://github.com/plotly/dash-table/issues/189)

demo/App.js

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class App extends Component {
1414
super();
1515

1616
this.state = AppState;
17+
this.state.temp_filtering = '';
1718

1819
const setProps = memoizeOne(() => {
1920
return newProps => {
@@ -33,15 +34,30 @@ class App extends Component {
3334
const mode = Environment.searchParams.get('mode');
3435

3536
if (mode === AppMode.Filtering) {
36-
return (<button
37-
className='clear-filters'
38-
onClick={() => {
39-
const tableProps = R.clone(this.state.tableProps);
40-
tableProps.filtering_settings = '';
41-
42-
this.setState({ tableProps });
43-
}}
44-
>Clear Filter</button>);
37+
return (
38+
<div>
39+
<button
40+
className='clear-filters'
41+
onClick={() => {
42+
const tableProps = R.clone(this.state.tableProps);
43+
tableProps.filter = '';
44+
45+
this.setState({ tableProps });
46+
}}
47+
>Clear Filter</button>
48+
<input
49+
style={{ width: '500px' }}
50+
value={this.state.temp_filtering}
51+
onChange={
52+
e => this.setState({ temp_filtering: e.target.value })
53+
}
54+
onBlur={e => {
55+
const tableProps = R.clone(this.state.tableProps);
56+
tableProps.filter = e.target.value;
57+
58+
this.setState({ tableProps });
59+
}} />
60+
</div>);
4561
}
4662
}
4763

demo/AppMode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function getBaseTableProps(mock: IDataMock) {
6565
max_width: '1000px',
6666
width: '1000px'
6767
},
68-
style_data_conditional: [
68+
style_cell_conditional: [
6969
{ max_width: 150, min_width: 150, width: 150 },
7070
{ if: { column_id: 'rows' }, max_width: 60, min_width: 60, width: 60 },
7171
{ if: { column_id: 'bbb' }, max_width: 200, min_width: 200, width: 200 },
@@ -150,7 +150,7 @@ function getTooltipsState() {
150150
state.tableProps.column_conditional_tooltips = [{
151151
if: {
152152
column_id: 'aaa-readonly',
153-
filter: `aaa is prime`
153+
filter: `{aaa} is prime`
154154
},
155155
type: TooltipSyntax.Markdown,
156156
value: `### Go Proverbs\nCapture three to get an eye`

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,11 @@
3030
"private::runtests:unit": "cypress run --browser chrome --spec 'tests/cypress/tests/unit/**/*'",
3131
"private::runtests:standalone": "cypress run --browser chrome --spec 'tests/cypress/tests/standalone/**/*'",
3232
"private::runtests:server": "cypress run --browser chrome --spec 'tests/cypress/tests/server/**/*'",
33-
"private::runtests-v0": "run-s private::runtests:server",
34-
"private::runtests-v1": "run-s private::runtests:python private::runtests:unit private::runtests:standalone private::runtests:server",
33+
"private::runtests": "run-s private::runtests:python private::runtests:unit private::runtests:standalone private::runtests:server",
3534
"build.watch": "webpack-dev-server --content-base dash_table --mode development",
3635
"build": "run-s private::build:js private::build:py",
3736
"lint": "run-s private::lint:*",
38-
"test-v0": "run-p --race private::host* private::runtests-v0",
39-
"test-v1": "run-p --race private::host* private::runtests-v1",
37+
"test": "run-p --race private::host* private::runtests",
4038
"test.visual": "build-storybook && percy-storybook",
4139
"test.visual-local": "build-storybook",
4240
"test.watch": "run-p --race \"private::build:js-test-watch\" --race private::host* private::opentests"
@@ -55,6 +53,7 @@
5553
"@storybook/cli": "^5.0.5",
5654
"@storybook/react": "^5.0.5",
5755
"@types/d3-format": "^1.3.1",
56+
"@types/papaparse": "^4.5.9",
5857
"@types/ramda": "^0.26.5",
5958
"@types/react": "^16.8.8",
6059
"@types/react-dom": "^16.8.3",
@@ -71,7 +70,9 @@
7170
"less-loader": "^4.1.0",
7271
"npm": "^6.9.0",
7372
"npm-run-all": "^4.1.5",
73+
"papaparse": "^4.6.3",
7474
"ramda": "^0.26.1",
75+
"raw-loader": "^2.0.0",
7576
"react": "16.8.5",
7677
"react-docgen": "^4.1.0",
7778
"react-dom": "16.8.5",

requirements-v1.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
-r requirements-base.txt
2-
-r requirements-v1.txt
2+
-r requirements-v0.txt

src/core/syntax-tree/index.ts

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,63 @@
1+
import * as R from 'ramda';
2+
13
import Logger from 'core/Logger';
2-
import lexer from 'core/syntax-tree/lexer';
3-
import syntaxer, { ISyntaxerResult } from 'core/syntax-tree/syntaxer';
4+
import lexer, { ILexerResult } from 'core/syntax-tree/lexer';
5+
import syntaxer, { ISyntaxerResult, ISyntaxTree } from 'core/syntax-tree/syntaxer';
6+
import { Lexicon } from './lexicon';
7+
8+
interface IStructure {
9+
subType?: string;
10+
type: string;
11+
value: any;
12+
13+
block?: IStructure;
14+
left?: IStructure;
15+
right?: IStructure;
16+
}
17+
18+
function toStructure(tree: ISyntaxTree): IStructure {
19+
const { block, left, lexeme, right, value } = tree;
20+
21+
const res: IStructure = {
22+
subType: lexeme.subType,
23+
type: lexeme.type,
24+
value: lexeme.present ? lexeme.present(tree) : value
25+
};
26+
27+
if (block) {
28+
res.block = toStructure(block);
29+
}
30+
31+
if (left) {
32+
res.left = toStructure(left);
33+
}
34+
35+
if (right) {
36+
res.right = toStructure(right);
37+
}
38+
39+
return res;
40+
}
441

542
export default class SyntaxTree {
6-
private result: ISyntaxerResult;
43+
protected lexerResult: ILexerResult;
44+
protected syntaxerResult: ISyntaxerResult;
745

846
get isValid() {
9-
return this.result.valid;
47+
return this.syntaxerResult.valid;
1048
}
1149

1250
private get tree() {
13-
return this.result.tree;
51+
return this.syntaxerResult.tree;
1452
}
1553

16-
constructor(private readonly query: string) {
17-
this.result = syntaxer(lexer(this.query));
54+
constructor(
55+
public readonly lexicon: Lexicon,
56+
public readonly query: string,
57+
postProcessor: (res: ILexerResult) => ILexerResult = res => res
58+
) {
59+
this.lexerResult = postProcessor(lexer(this.lexicon, this.query));
60+
this.syntaxerResult = syntaxer(this.lexerResult);
1861
}
1962

2063
evaluate = (target: any) => {
@@ -33,4 +76,18 @@ export default class SyntaxTree {
3376
filter = (targets: any[]) => {
3477
return targets.filter(this.evaluate);
3578
}
79+
80+
toQueryString() {
81+
return this.lexerResult.valid ?
82+
R.map(l => l.value, this.lexerResult.lexemes).join(' ') :
83+
'';
84+
}
85+
86+
toStructure() {
87+
if (!this.isValid || !this.syntaxerResult.tree) {
88+
return null;
89+
}
90+
91+
return toStructure(this.syntaxerResult.tree);
92+
}
3693
}

0 commit comments

Comments
 (0)