From 709f46cfbc3f41e58d9577e286b6b1961bfadbb1 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 7 Nov 2019 12:25:10 -0500 Subject: [PATCH 01/23] Omit marks that are outside of range specified by min and max. --- src/components/RangeSlider.react.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 6d90b77a6..15f99b07d 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -58,6 +58,14 @@ export default class RangeSlider extends Component { tipProps = tooltip; } + const omittedMarks = Object.keys(this.props.marks).filter(value => { + return value < this.props.min || value > this.props.max; + }); + const truncatedMarks = omit( + omittedMarks.map(mark => parseInt(mark, 10)), + this.props.marks + ); + return (
From 480511f3deff33ec5d088d436dbd6640fd422d6d Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 7 Nov 2019 12:44:02 -0500 Subject: [PATCH 02/23] Handle case in which marks prop is not defined. --- src/components/RangeSlider.react.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 15f99b07d..35a7b9c4d 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -58,9 +58,12 @@ export default class RangeSlider extends Component { tipProps = tooltip; } - const omittedMarks = Object.keys(this.props.marks).filter(value => { - return value < this.props.min || value > this.props.max; - }); + const omittedMarks = this.props.marks + ? Object.keys(this.props.marks).filter(value => { + return value < this.props.min || value > this.props.max; + }) + : []; + const truncatedMarks = omit( omittedMarks.map(mark => parseInt(mark, 10)), this.props.marks From 01324bf6d708b32990c11fa182d521c63ec95094 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Fri, 8 Nov 2019 14:34:25 -0500 Subject: [PATCH 03/23] Add test for out-of-range numbers. --- tests/integration/sliders/test_sliders.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/integration/sliders/test_sliders.py b/tests/integration/sliders/test_sliders.py index 15f5610d0..73ced90a9 100644 --- a/tests/integration/sliders/test_sliders.py +++ b/tests/integration/sliders/test_sliders.py @@ -58,3 +58,19 @@ def update_output(rng): dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-15") dash_dcc.click_at_coord_fractions(slider, 0.5, 0.5) dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-10") + + +def test_slsl003_out_of_range_marks_rangeslider(dash_dcc): + + app = dash.Dash(__name__) + app.layout = html.Div([ + dcc.RangeSlider( + min=0, + max=5, + marks={i: 'Label {}'.format(i) for i in range(10)} + ) + ]) + + dash_dcc.start_server(app) + + assert len(dash_dcc.find_elements('span.rc-slider-mark-text')) == 6 From 5cb8509f16a469abbeba54ed0a0918461c19e36a Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Mon, 11 Nov 2019 16:02:56 -0500 Subject: [PATCH 04/23] Use pickBy. --- src/components/RangeSlider.react.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 35a7b9c4d..72c4431c0 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {assoc, omit} from 'ramda'; +import {assoc, omit, pickBy} from 'ramda'; import {Range, createSliderWithTooltip} from 'rc-slider'; /** @@ -58,16 +58,12 @@ export default class RangeSlider extends Component { tipProps = tooltip; } - const omittedMarks = this.props.marks - ? Object.keys(this.props.marks).filter(value => { - return value < this.props.min || value > this.props.max; - }) - : []; - - const truncatedMarks = omit( - omittedMarks.map(mark => parseInt(mark, 10)), - this.props.marks - ); + const truncatedMarks = this.props.marks + ? pickBy( + (k, mark) => mark >= this.props.min && mark <= this.props.max, + this.props.marks + ) + : this.props.marks; return (
Date: Mon, 11 Nov 2019 16:06:02 -0500 Subject: [PATCH 05/23] Add mark at point below minimum value. --- tests/integration/sliders/test_sliders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/sliders/test_sliders.py b/tests/integration/sliders/test_sliders.py index 73ced90a9..363e212f2 100644 --- a/tests/integration/sliders/test_sliders.py +++ b/tests/integration/sliders/test_sliders.py @@ -67,7 +67,7 @@ def test_slsl003_out_of_range_marks_rangeslider(dash_dcc): dcc.RangeSlider( min=0, max=5, - marks={i: 'Label {}'.format(i) for i in range(10)} + marks={i: 'Label {}'.format(i) for i in range(-1, 10)} ) ]) From 396756ebec479aa18146de37e66928de5e0ed805 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Mon, 11 Nov 2019 16:33:53 -0500 Subject: [PATCH 06/23] Also omit out-of-range marks for slider. --- src/components/Slider.react.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index f587596bc..4810afa7b 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import ReactSlider, {createSliderWithTooltip} from 'rc-slider'; import PropTypes from 'prop-types'; -import {assoc, omit} from 'ramda'; +import {assoc, omit, pickBy} from 'ramda'; import './css/rc-slider@6.1.2.css'; /** @@ -58,6 +58,13 @@ export default class Slider extends Component { tipProps = tooltip; } + const truncatedMarks = this.props.marks + ? pickBy( + (k, mark) => mark >= this.props.min && mark <= this.props.max, + this.props.marks + ) + : this.props.marks; + return (
From 4bdaf7110c7c06c66405e1afb374c2a8ec1cf970 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Mon, 11 Nov 2019 16:34:11 -0500 Subject: [PATCH 07/23] Add test for slider. --- tests/integration/sliders/test_sliders.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/integration/sliders/test_sliders.py b/tests/integration/sliders/test_sliders.py index 363e212f2..3e7f4ae30 100644 --- a/tests/integration/sliders/test_sliders.py +++ b/tests/integration/sliders/test_sliders.py @@ -60,7 +60,23 @@ def update_output(rng): dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-10") -def test_slsl003_out_of_range_marks_rangeslider(dash_dcc): +def test_slsl003_out_of_range_marks_slider(dash_dcc): + + app = dash.Dash(__name__) + app.layout = html.Div([ + dcc.Slider( + min=0, + max=5, + marks={i: 'Label {}'.format(i) for i in range(-1, 10)} + ) + ]) + + dash_dcc.start_server(app) + + assert len(dash_dcc.find_elements('span.rc-slider-mark-text')) == 6 + + +def test_slsl004_out_of_range_marks_rangeslider(dash_dcc): app = dash.Dash(__name__) app.layout = html.Div([ From 1f5d15d544eac20e072d2c5c86a4a350d4f54078 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 12 Nov 2019 12:48:14 -0500 Subject: [PATCH 08/23] Add padding to Slider and RangeSlider containers. --- src/components/RangeSlider.react.js | 6 +++++- src/components/Slider.react.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 72c4431c0..249f20b7a 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -72,7 +72,11 @@ export default class RangeSlider extends Component { (loading_state && loading_state.is_loading) || undefined } className={className} - style={vertical ? {height: '100%'} : {}} + style={Object.assign( + {}, + {padding: '25px'}, + vertical ? {height: '100%'} : {} + )} > { diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 4810afa7b..4dfa72543 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -72,7 +72,11 @@ export default class Slider extends Component { (loading_state && loading_state.is_loading) || undefined } className={className} - style={vertical ? {height: '100%'} : {}} + style={Object.assign( + {}, + {padding: '25px'}, + vertical ? {height: '100%'} : {} + )} > { From a93fa427e502764b778c3994d70e84e5fce3ca32 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 12 Nov 2019 13:56:33 -0500 Subject: [PATCH 09/23] Update test for persistence. With the new padding values, the '0' selection is no longer at the very edge of the container div. --- .../calendar/#test_date_picker_range.py# | 79 +++++++++++++++++++ tests/integration/misc/test_persistence.py | 4 +- 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tests/integration/calendar/#test_date_picker_range.py# diff --git a/tests/integration/calendar/#test_date_picker_range.py# b/tests/integration/calendar/#test_date_picker_range.py# new file mode 100644 index 000000000..71dc504cc --- /dev/null +++ b/tests/integration/calendar/#test_date_picker_range.py# @@ -0,0 +1,79 @@ +from datetime import datetime + +import dash +import dash_html_components as html +import dash_core_components as dcc + + +def test_dtpr001_initial_month_provided(dash_dcc): + app = dash.Dash(__name__) + app.layout = html.Div([ + dcc.DatePickerRange( + id="dps-initial-month", + min_date_allowed=datetime(2010, 1, 1), + max_date_allowed=datetime(2099, 12, 31), + initial_visible_month=datetime(2019, 10, 28) + ) + ]) + + dash_dcc.start_server(app) + + date_picker_start = dash_dcc.find_element( + '#dps-initial-month .DateInput_input.DateInput_input_1[placeholder="Start Date"]' + ) + date_picker_start.click() + + dash_dcc.wait_for_text_to_equal( + '#dps-initial-month .CalendarMonth.CalendarMonth_1[data-visible=true] strong', + 'October 2019', + 1 + ) + + +def test_dtpr002_no_initial_month_min_date(dash_dcc): + app = dash.Dash(__name__) + app.layout = html.Div([ + dcc.DatePickerRange( + id="dps-initial-month", + min_date_allowed=datetime(2010, 1, 1), + max_date_allowed=datetime(2099, 12, 31) + ) + ]) + + dash_dcc.start_server(app) + + date_picker_start = dash_dcc.find_element( + '#dps-initial-month .DateInput_input.DateInput_input_1[placeholder="Start Date"]' + ) + date_picker_start.click() + + dash_dcc.wait_for_text_to_equal( + '#dps-initial-month .CalendarMonth.CalendarMonth_1[data-visible=true] strong', + 'January 2010' + ) + + +def test_dtpr003_no_initial_month_no_min_date_start_date(dash_dcc): + app = dash.Dash(__name__) + app.layout = html.Div([ + dcc.DatePickerRange( + id="dps-initial-month", + start_date=datetime(2019, 8, 13), + max_date_allowed=datetime(2099, 12, 31) + ) + ]) + + dash_dcc.start_server(app) + + date_picker_start = dash_dcc.find_element( + '#dps-initial-month .DateInput_input.DateInput_input_1[placeholder="Start Date"]' + ) + date_picker_start.click() + + dash_dcc.wait_for_text_to_equal( + '#dps-initial-month .CalendarMonth.CalendarMonth_1[data-visible=true] strong', + 'August 2019' + ) + + +def test_dtpr004_vertical_ \ No newline at end of file diff --git a/tests/integration/misc/test_persistence.py b/tests/integration/misc/test_persistence.py index 71b656bfb..ce07145da 100644 --- a/tests/integration/misc/test_persistence.py +++ b/tests/integration/misc/test_persistence.py @@ -147,8 +147,8 @@ def make_output(*args): dash_dcc.find_element("#radioitems label:first-child input").click() # red range_slider = dash_dcc.find_element("#rangeslider") - dash_dcc.click_at_coord_fractions(range_slider, 0.01, 0.5) # 0 dash_dcc.click_at_coord_fractions(range_slider, 0.5, 0.5) # 5 + dash_dcc.click_at_coord_fractions(range_slider, 0.8, 0.5) # 8 slider = dash_dcc.find_element("#slider") dash_dcc.click_at_coord_fractions(slider, 0.2, 0.5) # 22 @@ -166,7 +166,7 @@ def make_output(*args): [u"4️⃣", u"6️⃣"], "yes maybe", "r", - [0, 5], + [5, 8], 22, "C", "knock knock\nwho's there?", From fdd296b3012d079819b6ff2d7e2684222b3b9bae Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Wed, 13 Nov 2019 13:13:02 -0500 Subject: [PATCH 10/23] Change test for always visible rangeslider. --- tests/integration/sliders/test_sliders.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/sliders/test_sliders.py b/tests/integration/sliders/test_sliders.py index 3e7f4ae30..db74024ee 100644 --- a/tests/integration/sliders/test_sliders.py +++ b/tests/integration/sliders/test_sliders.py @@ -54,10 +54,10 @@ def update_output(rng): dash_dcc.wait_for_text_to_equal("#out", "You have selected 5-15") slider = dash_dcc.find_element("#rangeslider") - dash_dcc.click_at_coord_fractions(slider, 0.1, 0.5) - dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-15") + dash_dcc.click_at_coord_fractions(slider, 0.05, 0.5) + dash_dcc.wait_for_text_to_equal("#out", "You have selected 1-15") dash_dcc.click_at_coord_fractions(slider, 0.5, 0.5) - dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-10") + dash_dcc.wait_for_text_to_equal("#out", "You have selected 1-10") def test_slsl003_out_of_range_marks_slider(dash_dcc): From ad838fc0b9279dd9cd98604a8f968799f4134621 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 11:39:29 -0500 Subject: [PATCH 11/23] Only add top padding if there are always-visible tooltips on the top. --- src/components/RangeSlider.react.js | 11 ++++++++++- src/components/Slider.react.js | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 249f20b7a..b6c8bdf20 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {assoc, omit, pickBy} from 'ramda'; +import {assoc, omit, contains, pickBy} from 'ramda'; import {Range, createSliderWithTooltip} from 'rc-slider'; /** @@ -75,6 +75,15 @@ export default class RangeSlider extends Component { style={Object.assign( {}, {padding: '25px'}, + !tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, [ + 'top', + 'topLeft', + 'topRight', + ]) + ? {paddingTop: '0px'} + : {}, vertical ? {height: '100%'} : {} )} > diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 4dfa72543..e7f278e27 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import ReactSlider, {createSliderWithTooltip} from 'rc-slider'; import PropTypes from 'prop-types'; -import {assoc, omit, pickBy} from 'ramda'; +import {assoc, omit, pickBy, contains} from 'ramda'; import './css/rc-slider@6.1.2.css'; /** @@ -75,6 +75,15 @@ export default class Slider extends Component { style={Object.assign( {}, {padding: '25px'}, + !tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, [ + 'top', + 'topLeft', + 'topRight', + ]) + ? {paddingTop: '0px'} + : {}, vertical ? {height: '100%'} : {} )} > From c8070d4fd8b8668936eb522af988d409aae5bdd3 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 11:59:21 -0500 Subject: [PATCH 12/23] Preserve whitespace in marks. --- src/components/css/rc-slider@6.1.2.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/css/rc-slider@6.1.2.css b/src/components/css/rc-slider@6.1.2.css index 5e0b07cc7..a2bb4c911 100644 --- a/src/components/css/rc-slider@6.1.2.css +++ b/src/components/css/rc-slider@6.1.2.css @@ -56,6 +56,7 @@ text-align: center; cursor: pointer; color: #999; + white-space: pre; } .rc-slider-mark-text-active { color: #666; From 9e2ee6b2dadb9bfbeb5aa2241afaec89fc72bc6e Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 13:00:27 -0500 Subject: [PATCH 13/23] Add optional verticalHeight prop for vertical sliders. --- src/components/RangeSlider.react.js | 55 +++++++++++++++++++++-------- src/components/Slider.react.js | 55 +++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index b6c8bdf20..166aee01f 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {assoc, omit, contains, pickBy} from 'ramda'; +import {assoc, omit, contains, pickBy, merge} from 'ramda'; import {Range, createSliderWithTooltip} from 'rc-slider'; /** @@ -42,6 +42,7 @@ export default class RangeSlider extends Component { tooltip, updatemode, vertical, + verticalHeight, } = this.props; const value = this.state.value; @@ -65,6 +66,36 @@ export default class RangeSlider extends Component { ) : this.props.marks; + let style = { + padding: '25px', + }; + + if ( + !vertical && + (!tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, ['top', 'topLeft', 'topRight'])) + ) { + style = merge(style, {paddingTop: '0px'}); + } + + if ( + vertical && + (!tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, [ + 'left', + 'topRight', + 'bottomRight', + ])) + ) { + style = merge(style, {paddingLeft: '0px'}); + } + + if (vertical) { + style = merge(style, {height: verticalHeight + 'px'}); + } + return (
{ @@ -110,6 +128,7 @@ export default class RangeSlider extends Component { 'setProps', 'marks', 'updatemode', + 'verticalHeight', ], this.props )} @@ -240,6 +259,11 @@ RangeSlider.propTypes = { */ vertical: PropTypes.bool, + /** + * The height, in px, of the slider if it is vertical. + */ + verticalHeight: PropTypes.number, + /** * Determines when the component should update * its value. If `mouseup`, then the slider @@ -308,4 +332,5 @@ RangeSlider.defaultProps = { updatemode: 'mouseup', persisted_props: ['value'], persistence_type: 'local', + verticalHeight: 400, }; diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index e7f278e27..7b5369ba6 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import ReactSlider, {createSliderWithTooltip} from 'rc-slider'; import PropTypes from 'prop-types'; -import {assoc, omit, pickBy, contains} from 'ramda'; +import {assoc, omit, pickBy, contains, merge} from 'ramda'; import './css/rc-slider@6.1.2.css'; /** @@ -42,6 +42,7 @@ export default class Slider extends Component { tooltip, updatemode, vertical, + verticalHeight, } = this.props; const value = this.state.value; @@ -65,6 +66,36 @@ export default class Slider extends Component { ) : this.props.marks; + let style = { + padding: '25px', + }; + + if ( + !vertical && + (!tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, ['top', 'topLeft', 'topRight'])) + ) { + style = merge(style, {paddingTop: '0px'}); + } + + if ( + vertical && + (!tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, [ + 'left', + 'topRight', + 'bottomRight', + ])) + ) { + style = merge(style, {paddingLeft: '0px'}); + } + + if (vertical) { + style = merge(style, {height: verticalHeight + 'px'}); + } + return (
{ @@ -110,6 +128,7 @@ export default class Slider extends Component { 'updatemode', 'value', 'marks', + 'verticalHeight', ], this.props )} @@ -221,6 +240,11 @@ Slider.propTypes = { */ vertical: PropTypes.bool, + /** + * The height, in px, of the slider if it is vertical. + */ + verticalHeight: PropTypes.number, + /** * Determines when the component should update * its value. If `mouseup`, then the slider @@ -289,4 +313,5 @@ Slider.defaultProps = { updatemode: 'mouseup', persisted_props: ['value'], persistence_type: 'local', + verticalHeight: 400, }; From 4d03221fdb204722edbee37633c5a3e16fac28d5 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 13:00:45 -0500 Subject: [PATCH 14/23] Update slider stylesheet. --- src/components/css/rc-slider@6.1.2.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/css/rc-slider@6.1.2.css b/src/components/css/rc-slider@6.1.2.css index a2bb4c911..027431320 100644 --- a/src/components/css/rc-slider@6.1.2.css +++ b/src/components/css/rc-slider@6.1.2.css @@ -57,6 +57,7 @@ cursor: pointer; color: #999; white-space: pre; + width: fit-content; } .rc-slider-mark-text-active { color: #666; From bbb4fea121af67782632109fb146475a7515d3af Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 14:22:49 -0500 Subject: [PATCH 15/23] Update coordinates to reflect new padding. --- tests/integration/sliders/test_sliders.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/sliders/test_sliders.py b/tests/integration/sliders/test_sliders.py index db74024ee..f7f5d060c 100644 --- a/tests/integration/sliders/test_sliders.py +++ b/tests/integration/sliders/test_sliders.py @@ -26,9 +26,9 @@ def update_output(value): dash_dcc.wait_for_text_to_equal("#out", "You have selected 5") slider = dash_dcc.find_element("#slider") - dash_dcc.click_at_coord_fractions(slider, 0.5, 0.5) + dash_dcc.click_at_coord_fractions(slider, 0.5, 0.25) dash_dcc.wait_for_text_to_equal("#out", "You have selected 10") - dash_dcc.click_at_coord_fractions(slider, 0.75, 0.5) + dash_dcc.click_at_coord_fractions(slider, 0.75, 0.25) dash_dcc.wait_for_text_to_equal("#out", "You have selected 15") @@ -54,9 +54,9 @@ def update_output(rng): dash_dcc.wait_for_text_to_equal("#out", "You have selected 5-15") slider = dash_dcc.find_element("#rangeslider") - dash_dcc.click_at_coord_fractions(slider, 0.05, 0.5) + dash_dcc.click_at_coord_fractions(slider, 0.05, 0.25) dash_dcc.wait_for_text_to_equal("#out", "You have selected 1-15") - dash_dcc.click_at_coord_fractions(slider, 0.5, 0.5) + dash_dcc.click_at_coord_fractions(slider, 0.5, 0.25) dash_dcc.wait_for_text_to_equal("#out", "You have selected 1-10") From a0aad561f191068e263bf86e84c16c51c765aaa3 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 15:00:27 -0500 Subject: [PATCH 16/23] Remove file. --- .../calendar/#test_date_picker_range.py# | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 tests/integration/calendar/#test_date_picker_range.py# diff --git a/tests/integration/calendar/#test_date_picker_range.py# b/tests/integration/calendar/#test_date_picker_range.py# deleted file mode 100644 index 71dc504cc..000000000 --- a/tests/integration/calendar/#test_date_picker_range.py# +++ /dev/null @@ -1,79 +0,0 @@ -from datetime import datetime - -import dash -import dash_html_components as html -import dash_core_components as dcc - - -def test_dtpr001_initial_month_provided(dash_dcc): - app = dash.Dash(__name__) - app.layout = html.Div([ - dcc.DatePickerRange( - id="dps-initial-month", - min_date_allowed=datetime(2010, 1, 1), - max_date_allowed=datetime(2099, 12, 31), - initial_visible_month=datetime(2019, 10, 28) - ) - ]) - - dash_dcc.start_server(app) - - date_picker_start = dash_dcc.find_element( - '#dps-initial-month .DateInput_input.DateInput_input_1[placeholder="Start Date"]' - ) - date_picker_start.click() - - dash_dcc.wait_for_text_to_equal( - '#dps-initial-month .CalendarMonth.CalendarMonth_1[data-visible=true] strong', - 'October 2019', - 1 - ) - - -def test_dtpr002_no_initial_month_min_date(dash_dcc): - app = dash.Dash(__name__) - app.layout = html.Div([ - dcc.DatePickerRange( - id="dps-initial-month", - min_date_allowed=datetime(2010, 1, 1), - max_date_allowed=datetime(2099, 12, 31) - ) - ]) - - dash_dcc.start_server(app) - - date_picker_start = dash_dcc.find_element( - '#dps-initial-month .DateInput_input.DateInput_input_1[placeholder="Start Date"]' - ) - date_picker_start.click() - - dash_dcc.wait_for_text_to_equal( - '#dps-initial-month .CalendarMonth.CalendarMonth_1[data-visible=true] strong', - 'January 2010' - ) - - -def test_dtpr003_no_initial_month_no_min_date_start_date(dash_dcc): - app = dash.Dash(__name__) - app.layout = html.Div([ - dcc.DatePickerRange( - id="dps-initial-month", - start_date=datetime(2019, 8, 13), - max_date_allowed=datetime(2099, 12, 31) - ) - ]) - - dash_dcc.start_server(app) - - date_picker_start = dash_dcc.find_element( - '#dps-initial-month .DateInput_input.DateInput_input_1[placeholder="Start Date"]' - ) - date_picker_start.click() - - dash_dcc.wait_for_text_to_equal( - '#dps-initial-month .CalendarMonth.CalendarMonth_1[data-visible=true] strong', - 'August 2019' - ) - - -def test_dtpr004_vertical_ \ No newline at end of file From 1261f90e4ecb893d374dd78127cd8626ca288274 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 15:00:50 -0500 Subject: [PATCH 17/23] Use fixed-width slider for rangeslider test. --- tests/integration/sliders/test_sliders.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/sliders/test_sliders.py b/tests/integration/sliders/test_sliders.py index f7f5d060c..449af2b95 100644 --- a/tests/integration/sliders/test_sliders.py +++ b/tests/integration/sliders/test_sliders.py @@ -34,7 +34,7 @@ def update_output(value): def test_slsl002_always_visible_rangeslider(dash_dcc): app = dash.Dash(__name__) - app.layout = html.Div([ + app.layout = html.Div(style={'width': '400px'}, children=[ dcc.RangeSlider( id="rangeslider", min=0, @@ -54,10 +54,10 @@ def update_output(rng): dash_dcc.wait_for_text_to_equal("#out", "You have selected 5-15") slider = dash_dcc.find_element("#rangeslider") - dash_dcc.click_at_coord_fractions(slider, 0.05, 0.25) - dash_dcc.wait_for_text_to_equal("#out", "You have selected 1-15") + dash_dcc.click_at_coord_fractions(slider, 0.15, 0.25) + dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-15") dash_dcc.click_at_coord_fractions(slider, 0.5, 0.25) - dash_dcc.wait_for_text_to_equal("#out", "You have selected 1-10") + dash_dcc.wait_for_text_to_equal("#out", "You have selected 2-10") def test_slsl003_out_of_range_marks_slider(dash_dcc): From b7dee1ab7830531fa2d1f918b8accbd88cea60cb Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Thu, 14 Nov 2019 15:18:47 -0500 Subject: [PATCH 18/23] Fix persistence test. --- tests/integration/misc/test_persistence.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/misc/test_persistence.py b/tests/integration/misc/test_persistence.py index ce07145da..c2a6291f7 100644 --- a/tests/integration/misc/test_persistence.py +++ b/tests/integration/misc/test_persistence.py @@ -147,11 +147,11 @@ def make_output(*args): dash_dcc.find_element("#radioitems label:first-child input").click() # red range_slider = dash_dcc.find_element("#rangeslider") - dash_dcc.click_at_coord_fractions(range_slider, 0.5, 0.5) # 5 - dash_dcc.click_at_coord_fractions(range_slider, 0.8, 0.5) # 8 + dash_dcc.click_at_coord_fractions(range_slider, 0.5, 0.25) # 5 + dash_dcc.click_at_coord_fractions(range_slider, 0.8, 0.25) # 8 slider = dash_dcc.find_element("#slider") - dash_dcc.click_at_coord_fractions(slider, 0.2, 0.5) # 22 + dash_dcc.click_at_coord_fractions(slider, 0.2, 0.25) # 22 dash_dcc.find_element("#tabs .tab:last-child").click() # C From edc2784d41bf0ee6ccc79ddc2e7aa6edac76aa4f Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 19 Nov 2019 10:38:01 -0500 Subject: [PATCH 19/23] Memoize computation of style and move function to utils. --- src/components/RangeSlider.react.js | 48 ++++++----------------------- src/components/Slider.react.js | 36 +++------------------- src/utils/computeSliderStyle.js | 37 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 70 deletions(-) create mode 100644 src/utils/computeSliderStyle.js diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 166aee01f..600cd3ca6 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -1,7 +1,8 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {assoc, omit, contains, pickBy, merge} from 'ramda'; +import {assoc, omit, contains, pickBy} from 'ramda'; import {Range, createSliderWithTooltip} from 'rc-slider'; +import computeSliderStyle from '../utils/computeSliderStyle'; /** * A double slider with two handles. @@ -14,6 +15,7 @@ export default class RangeSlider extends Component { this.DashSlider = props.tooltip ? createSliderWithTooltip(Range) : Range; + this._computeStyle = computeSliderStyle(); } propsToState(newProps) { @@ -59,42 +61,12 @@ export default class RangeSlider extends Component { tipProps = tooltip; } - const truncatedMarks = this.props.marks - ? pickBy( - (k, mark) => mark >= this.props.min && mark <= this.props.max, - this.props.marks - ) - : this.props.marks; - - let style = { - padding: '25px', - }; - - if ( - !vertical && - (!tooltip || - !tooltip.always_visible || - !contains(tooltip.placement, ['top', 'topLeft', 'topRight'])) - ) { - style = merge(style, {paddingTop: '0px'}); - } - - if ( - vertical && - (!tooltip || - !tooltip.always_visible || - !contains(tooltip.placement, [ - 'left', - 'topRight', - 'bottomRight', - ])) - ) { - style = merge(style, {paddingLeft: '0px'}); - } - - if (vertical) { - style = merge(style, {height: verticalHeight + 'px'}); - } + const truncatedMarks = + this.props.marks && + pickBy( + (k, mark) => mark >= this.props.min && mark <= this.props.max, + this.props.marks + ); return (
{ diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 7b5369ba6..e550597bd 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -1,8 +1,9 @@ import React, {Component} from 'react'; import ReactSlider, {createSliderWithTooltip} from 'rc-slider'; import PropTypes from 'prop-types'; -import {assoc, omit, pickBy, contains, merge} from 'ramda'; +import {assoc, omit, pickBy, contains} from 'ramda'; import './css/rc-slider@6.1.2.css'; +import computeSliderStyle from '../utils/computeSliderStyle'; /** * A slider component with a single handle. @@ -14,6 +15,7 @@ export default class Slider extends Component { this.DashSlider = props.tooltip ? createSliderWithTooltip(ReactSlider) : ReactSlider; + this._computeStyle = computeSliderStyle(); } propsToState(newProps) { @@ -66,36 +68,6 @@ export default class Slider extends Component { ) : this.props.marks; - let style = { - padding: '25px', - }; - - if ( - !vertical && - (!tooltip || - !tooltip.always_visible || - !contains(tooltip.placement, ['top', 'topLeft', 'topRight'])) - ) { - style = merge(style, {paddingTop: '0px'}); - } - - if ( - vertical && - (!tooltip || - !tooltip.always_visible || - !contains(tooltip.placement, [ - 'left', - 'topRight', - 'bottomRight', - ])) - ) { - style = merge(style, {paddingLeft: '0px'}); - } - - if (vertical) { - style = merge(style, {height: verticalHeight + 'px'}); - } - return (
{ diff --git a/src/utils/computeSliderStyle.js b/src/utils/computeSliderStyle.js new file mode 100644 index 000000000..f6db3d36f --- /dev/null +++ b/src/utils/computeSliderStyle.js @@ -0,0 +1,37 @@ +import {merge, memoizeWith, identity, contains} from 'ramda'; + +export default (vertical, verticalHeight, tooltip) => { + return memoizeWith(identity, (vertical, verticalHeight, tooltip) => { + let style = { + padding: '25px', + }; + + if ( + !vertical && + (!tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, ['top', 'topLeft', 'topRight'])) + ) { + style = merge(style, {paddingTop: '0px'}); + } + + if ( + vertical && + (!tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, [ + 'left', + 'topRight', + 'bottomRight', + ])) + ) { + style = merge(style, {paddingLeft: '0px'}); + } + + if (vertical) { + style = merge(style, {height: verticalHeight + 'px'}); + } + + return style; + }); +}; From df14f7dc319db21656e161d70848f928804b9302 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 19 Nov 2019 10:43:21 -0500 Subject: [PATCH 20/23] Simplify style code. --- src/utils/computeSliderStyle.js | 34 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/utils/computeSliderStyle.js b/src/utils/computeSliderStyle.js index f6db3d36f..1164fea15 100644 --- a/src/utils/computeSliderStyle.js +++ b/src/utils/computeSliderStyle.js @@ -6,30 +6,28 @@ export default (vertical, verticalHeight, tooltip) => { padding: '25px', }; - if ( - !vertical && - (!tooltip || - !tooltip.always_visible || - !contains(tooltip.placement, ['top', 'topLeft', 'topRight'])) - ) { - style = merge(style, {paddingTop: '0px'}); - } + if (vertical) { + style = merge(style, {height: verticalHeight + 'px'}); - if ( - vertical && - (!tooltip || + if ( + !tooltip || !tooltip.always_visible || !contains(tooltip.placement, [ 'left', 'topRight', 'bottomRight', - ])) - ) { - style = merge(style, {paddingLeft: '0px'}); - } - - if (vertical) { - style = merge(style, {height: verticalHeight + 'px'}); + ]) + ) { + style = merge(style, {paddingLeft: '0px'}); + } + } else { + if ( + !tooltip || + !tooltip.always_visible || + !contains(tooltip.placement, ['top', 'topLeft', 'topRight']) + ) { + style = merge(style, {paddingTop: '0px'}); + } } return style; From b9a8fcf5359090fdd837dc66c1d1a576ccf69e43 Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 19 Nov 2019 10:45:46 -0500 Subject: [PATCH 21/23] Fix eslint errors. --- src/components/RangeSlider.react.js | 2 +- src/components/Slider.react.js | 2 +- src/utils/computeSliderStyle.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/RangeSlider.react.js b/src/components/RangeSlider.react.js index 600cd3ca6..f06973f3b 100644 --- a/src/components/RangeSlider.react.js +++ b/src/components/RangeSlider.react.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {assoc, omit, contains, pickBy} from 'ramda'; +import {assoc, omit, pickBy} from 'ramda'; import {Range, createSliderWithTooltip} from 'rc-slider'; import computeSliderStyle from '../utils/computeSliderStyle'; diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index e550597bd..d2a09cea1 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import ReactSlider, {createSliderWithTooltip} from 'rc-slider'; import PropTypes from 'prop-types'; -import {assoc, omit, pickBy, contains} from 'ramda'; +import {assoc, omit, pickBy} from 'ramda'; import './css/rc-slider@6.1.2.css'; import computeSliderStyle from '../utils/computeSliderStyle'; diff --git a/src/utils/computeSliderStyle.js b/src/utils/computeSliderStyle.js index 1164fea15..936958adc 100644 --- a/src/utils/computeSliderStyle.js +++ b/src/utils/computeSliderStyle.js @@ -1,6 +1,6 @@ import {merge, memoizeWith, identity, contains} from 'ramda'; -export default (vertical, verticalHeight, tooltip) => { +export default () => { return memoizeWith(identity, (vertical, verticalHeight, tooltip) => { let style = { padding: '25px', From 3e32f28ea0dde469f51b0db26546e565e4060f1d Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 19 Nov 2019 11:48:00 -0500 Subject: [PATCH 22/23] Modify style object directly. --- src/utils/computeSliderStyle.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utils/computeSliderStyle.js b/src/utils/computeSliderStyle.js index 936958adc..5d6531311 100644 --- a/src/utils/computeSliderStyle.js +++ b/src/utils/computeSliderStyle.js @@ -1,13 +1,13 @@ -import {merge, memoizeWith, identity, contains} from 'ramda'; +import {memoizeWith, identity, contains} from 'ramda'; export default () => { return memoizeWith(identity, (vertical, verticalHeight, tooltip) => { - let style = { + const style = { padding: '25px', }; if (vertical) { - style = merge(style, {height: verticalHeight + 'px'}); + style.height = verticalHeight + 'px'; if ( !tooltip || @@ -18,7 +18,7 @@ export default () => { 'bottomRight', ]) ) { - style = merge(style, {paddingLeft: '0px'}); + style.paddingLeft = '0px'; } } else { if ( @@ -26,7 +26,7 @@ export default () => { !tooltip.always_visible || !contains(tooltip.placement, ['top', 'topLeft', 'topRight']) ) { - style = merge(style, {paddingTop: '0px'}); + style.paddingTop = '0px'; } } From 473e86a2d4ff0d99450bbae636cbe566cf1b2d4e Mon Sep 17 00:00:00 2001 From: Shammamah Hossain Date: Tue, 19 Nov 2019 12:32:40 -0500 Subject: [PATCH 23/23] Update CHANGELOG. --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99aa64a2d..fd0944dc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Changed +- [#695](https://github.com/plotly/dash-core-components/pull/695) Improvements to Slider and RangeSlider + - Marks outside of the range specified by `min` and `max` are now omitted when the slider renders. + - Padding is now dependent on the orientation (vertical or horizontal), and whether or not tooltips are always displayed. + - The whitespace is now preserved for `marks` labels. + +### Added +- [#695](https://github.com/plotly/dash-core-components/pull/695) Added new property `verticalHeight` to Slider and RangeSlider, to allow the user to specify the height (in px) of vertical sliders. This defaults to `400`. + ## [1.5.1] - 2019-11-14 ### Fixed - [#696](https://github.com/plotly/dash-core-components/pull/696) Fix IE11 compatibility issues and ES5 compatibility and validation