From 39e262a0304848bbf9923f4c8ff8e5f0999f0dbd Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Wed, 21 Sep 2016 12:57:00 -0700 Subject: [PATCH 1/2] [FilterBox] dashboard date range filtering --- caravel/assets/.eslintignore | 13 +-- caravel/assets/javascripts/modules/caravel.js | 2 +- caravel/assets/package.json | 16 ++-- caravel/assets/visualizations/filter_box.css | 3 + caravel/assets/visualizations/filter_box.jsx | 87 ++++++++++++++----- caravel/forms.py | 5 ++ caravel/viz.py | 45 ++++++---- 7 files changed, 119 insertions(+), 52 deletions(-) diff --git a/caravel/assets/.eslintignore b/caravel/assets/.eslintignore index f9657ae67c1..7b1f78cba3c 100644 --- a/caravel/assets/.eslintignore +++ b/caravel/assets/.eslintignore @@ -1,7 +1,10 @@ -node_modules/* -vendor/* +**/*{.,-}min.js +**/*.sh +coverage/** dist/* -stylesheets/* +images/* +node_modules/* +node_modules*/* spec/* -coverage/** -**/*{.,-}min.js +stylesheets/* +vendor/* diff --git a/caravel/assets/javascripts/modules/caravel.js b/caravel/assets/javascripts/modules/caravel.js index c39877e162b..f6e7e577778 100644 --- a/caravel/assets/javascripts/modules/caravel.js +++ b/caravel/assets/javascripts/modules/caravel.js @@ -58,7 +58,7 @@ const px = function () { const containerId = data.token + '_con'; const selector = '#' + containerId; const container = $(selector); - const sliceId = data.sliceId; + const sliceId = data.slice_id; let dttm = 0; const stopwatch = function () { dttm += 10; diff --git a/caravel/assets/package.json b/caravel/assets/package.json index be99cc569b3..24f238dd9d0 100644 --- a/caravel/assets/package.json +++ b/caravel/assets/package.json @@ -12,8 +12,7 @@ "cover": "babel-node ./node_modules/.bin/istanbul cover _mocha -- --require spec/helpers/browser.js --recursive spec/**/*_spec.*", "dev": "NODE_ENV=dev webpack -d --watch --colors --progress", "prod": "NODE_ENV=production webpack -p --colors --progress", - "lint": "npm run --silent lint:js", - "lint:js": "eslint --ignore-path=.eslintignore --ext .js,.jsx ." + "lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx ." }, "repository": { "type": "git", @@ -39,6 +38,7 @@ "dependencies": { "autobind-decorator": "^1.3.3", "babel-cli": "^6.14.0", + "babel-preset-es2015": "^6.14.0", "bootstrap": "^3.3.6", "bootstrap-datepicker": "^1.6.0", "brace": "^0.7.0", @@ -62,11 +62,11 @@ "moments": "0.0.2", "mustache": "^2.2.1", "nvd3": "1.8.4", - "react": "^15.2.1", + "react": "^15.3.2", "react-ace": "^3.4.1", "react-bootstrap": "^0.30.3", "react-bootstrap-table": "^2.3.8", - "react-dom": "^0.14.8", + "react-dom": "^15.3.2", "react-draggable": "^2.1.2", "react-grid-layout": "^0.13.1", "react-map-gl": "^1.0.0-beta-10", @@ -89,8 +89,7 @@ "babel": "^6.3.26", "babel-core": "^6.10.4", "babel-loader": "^6.2.4", - "babel-preset-airbnb": "^1.1.1", - "babel-preset-es2015": "^6.9.0", + "babel-preset-airbnb": "^2.0.0", "babel-preset-react": "^6.11.1", "chai": "^3.5.0", "codeclimate-test-reporter": "^0.3.3", @@ -99,7 +98,7 @@ "eslint": "^2.13.1", "eslint-config-airbnb": "^9.0.1", "eslint-plugin-import": "^1.11.1", - "eslint-plugin-jsx-a11y": "^2.0.1", + "eslint-plugin-jsx-a11y": "^1.2.0", "eslint-plugin-react": "^5.2.2", "exports-loader": "^0.6.3", "istanbul": "^1.0.0-alpha", @@ -110,8 +109,7 @@ "less": "^2.6.1", "less-loader": "^2.2.2", "mocha": "^2.4.5", - "react-addons-test-utils": "^0.14.8", - "react-dom": "^0.14.8", + "react-addons-test-utils": "^15.3.2", "style-loader": "^0.13.0", "transform-loader": "^0.2.3", "url-loader": "^0.5.7", diff --git a/caravel/assets/visualizations/filter_box.css b/caravel/assets/visualizations/filter_box.css index 43b193032eb..388c13d550e 100644 --- a/caravel/assets/visualizations/filter_box.css +++ b/caravel/assets/visualizations/filter_box.css @@ -27,3 +27,6 @@ ul.select2-results div.filter_box{ .filter_box:hover { z-index: 1000; } +.m-b-5 { + margin-bottom: 5px; +} diff --git a/caravel/assets/visualizations/filter_box.jsx b/caravel/assets/visualizations/filter_box.jsx index ca56ebb523e..322a1b309a1 100644 --- a/caravel/assets/visualizations/filter_box.jsx +++ b/caravel/assets/visualizations/filter_box.jsx @@ -10,6 +10,29 @@ import '../stylesheets/react-select/select.less'; import './filter_box.css'; +const TIME_CHOICES = [ + '1 hour ago', + '12 hours ago', + '1 day ago', + '7 days ago', + '28 days ago', + '90 days ago', + '1 year ago', +]; + +const propTypes = { + origSelectedValues: React.PropTypes.object, + filtersChoices: React.PropTypes.object, + onChange: React.PropTypes.func, + showDateFilter: React.PropTypes.bool, +}; + +const defaultProps = { + origSelectedValues: {}, + onChange: () => {}, + showDateFilter: false, +}; + class FilterBox extends React.Component { constructor(props) { super(props); @@ -17,7 +40,42 @@ class FilterBox extends React.Component { selectedValues: props.origSelectedValues, }; } + changeFilter(filter, options) { + let vals = null; + if (options) { + if (Array.isArray(options)) { + vals = options.map((opt) => opt.value); + } else { + vals = options.value; + } + } + const selectedValues = Object.assign({}, this.state.selectedValues); + selectedValues[filter] = vals; + this.setState({ selectedValues }); + this.props.onChange(filter, vals); + } render() { + let dateFilter; + if (this.props.showDateFilter) { + dateFilter = ['__from', '__to'].map((field) => { + const val = this.state.selectedValues[field]; + const choices = TIME_CHOICES.slice(); + if (!choices.includes(val)) { + choices.push(val); + } + const options = choices.map((s) => ({ value: s, label: s })); + return ( +
+ {field.replace('__', '')} + +
+ ); + }); + } const filters = Object.keys(this.props.filtersChoices).map((filter) => { const data = this.props.filtersChoices[filter]; const maxes = {}; @@ -25,7 +83,7 @@ class FilterBox extends React.Component { return d.metric; }); return ( -
+
{filter}