From 97789e73374301a9f114124f05c5eb8a645dcb9a Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 09:01:12 -0400
Subject: [PATCH 01/80] update Checklist, Dropdown, RangeSlider to accept
optional shorthands
---
.../src/components/Checklist.react.js | 70 ++++++++++---------
.../src/components/Dropdown.react.js | 14 ++--
.../src/components/RangeSlider.react.js | 31 ++++----
.../src/fragments/Dropdown.react.js | 8 ++-
dash/dependencies.py | 4 +-
5 files changed, 71 insertions(+), 56 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 22f3d68af5..3622cbb3e4 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -33,44 +33,43 @@ export default class Checklist extends Component {
style={style}
className={className}
>
- {options.map(option => (
-
- ))}
+ {options.map(option => {
+ option = (typeof option === "string")
+ ? {
+ label: option,
+ value: option,
+ disabled: false
+ } : option;
+ return
+ })}
);
}
}
Checklist.propTypes = {
- /**
- * The ID of this component, used to identify dash components
- * in callbacks. The ID needs to be unique across all of the
- * components in an app.
- */
- id: PropTypes.string,
-
/**
* An array of options
*/
@@ -104,6 +103,13 @@ Checklist.propTypes = {
PropTypes.oneOfType([PropTypes.string, PropTypes.number])
),
+ /**
+ * The ID of this component, used to identify dash components
+ * in callbacks. The ID needs to be unique across all of the
+ * components in an app.
+ */
+ id: PropTypes.string,
+
/**
* The class of the container (div)
*/
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 604cebfe7c..bfd1d8e32a 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -25,13 +25,6 @@ export default class Dropdown extends Component {
}
Dropdown.propTypes = {
- /**
- * The ID of this component, used to identify dash components
- * in callbacks. The ID needs to be unique across all of the
- * components in an app.
- */
- id: PropTypes.string,
-
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
@@ -82,6 +75,13 @@ Dropdown.propTypes = {
),
]),
+ /**
+ * The ID of this component, used to identify dash components
+ * in callbacks. The ID needs to be unique across all of the
+ * components in an app.
+ */
+ id: PropTypes.string,
+
/**
* height of each option. Can be increased when label lengths would wrap around
*/
diff --git a/components/dash-core-components/src/components/RangeSlider.react.js b/components/dash-core-components/src/components/RangeSlider.react.js
index 2b293044b5..418779ef48 100644
--- a/components/dash-core-components/src/components/RangeSlider.react.js
+++ b/components/dash-core-components/src/components/RangeSlider.react.js
@@ -19,6 +19,22 @@ export default class RangeSlider extends Component {
}
RangeSlider.propTypes = {
+
+ /**
+ * Minimum allowed value of the slider
+ */
+ min: PropTypes.number,
+
+ /**
+ * Maximum allowed value of the slider
+ */
+ max: PropTypes.number,
+
+ /**
+ * Value by which increments or decrements are made
+ */
+ step: PropTypes.number,
+
/**
* The ID of this component, used to identify dash components
* in callbacks. The ID needs to be unique across all of the
@@ -88,16 +104,6 @@ RangeSlider.propTypes = {
*/
included: PropTypes.bool,
- /**
- * Minimum allowed value of the slider
- */
- min: PropTypes.number,
-
- /**
- * Maximum allowed value of the slider
- */
- max: PropTypes.number,
-
/**
* pushable could be set as true to allow pushing of
* surrounding handles when moving an handle.
@@ -134,11 +140,6 @@ RangeSlider.propTypes = {
]),
}),
- /**
- * Value by which increments or decrements are made
- */
- step: PropTypes.number,
-
/**
* If true, the slider will be vertical
*/
diff --git a/components/dash-core-components/src/fragments/Dropdown.react.js b/components/dash-core-components/src/fragments/Dropdown.react.js
index 2f819b353d..45fcaad904 100644
--- a/components/dash-core-components/src/fragments/Dropdown.react.js
+++ b/components/dash-core-components/src/fragments/Dropdown.react.js
@@ -35,9 +35,15 @@ export default class Dropdown extends Component {
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.options !== this.props.options) {
+ const normalizedOptions = newProps.options.map(opt =>
+ (type(opt) === 'string') ? {
+ label: opt,
+ value: opt,
+ } : opt
+ );
this.setState({
filterOptions: createFilterOptions({
- options: newProps.options,
+ options: normalizedOptions,
tokenizer: TOKENIZER,
}),
});
diff --git a/dash/dependencies.py b/dash/dependencies.py
index 1b2cc6f7f9..82b49030aa 100644
--- a/dash/dependencies.py
+++ b/dash/dependencies.py
@@ -27,7 +27,9 @@ def to_json(self):
class DashDependency: # pylint: disable=too-few-public-methods
def __init__(self, component_id, component_property):
- self.component_id = component_id
+ self.component_id = (
+ component_id if isinstance(component_id, str) else component_id.id
+ )
self.component_property = component_property
def __str__(self):
From c4cedfef72213dbddf10f6c1b394189eb2c2d4bf Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 11:15:21 -0400
Subject: [PATCH 02/80] update Checklist, RadioItems - added inline props and
shorthand options data, update DataTable - params order changed for shorthand
support, added TODO
---
.../src/components/Checklist.react.js | 58 +++++++++------
.../src/components/RadioItems.react.js | 71 +++++++++++--------
.../src/dash-table/dash/DataTable.js | 46 ++++++------
.../src/dash-table/dash/Sanitizer.ts | 4 +-
4 files changed, 105 insertions(+), 74 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 3622cbb3e4..51cd3c41b0 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -22,6 +22,7 @@ export default class Checklist extends Component {
style,
loading_state,
value,
+ inline,
} = this.props;
return (
@@ -34,8 +35,7 @@ export default class Checklist extends Component {
className={className}
>
{options.map(option => {
- option = (typeof option === "string")
- ? {
+ option = inline ? {
label: option,
value: option,
disabled: false
@@ -74,26 +74,29 @@ Checklist.propTypes = {
* An array of options
*/
options: PropTypes.arrayOf(
- PropTypes.exact({
- /**
- * The checkbox's label
- */
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
- .isRequired,
-
- /**
- * The value of the checkbox. This value
- * corresponds to the items specified in the
- * `value` property.
- */
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
- .isRequired,
-
- /**
- * If true, this checkbox is disabled and can't be clicked on.
- */
- disabled: PropTypes.bool,
- })
+ PropTypes.oneOfType([
+ PropTypes.exact({
+ /**
+ * The checkbox's label
+ */
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * The value of the checkbox. This value
+ * corresponds to the items specified in the
+ * `value` property.
+ */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * If true, this checkbox is disabled and can't be clicked on.
+ */
+ disabled: PropTypes.bool,
+ }),
+ PropTypes.string
+ ])
),
/**
@@ -193,6 +196,16 @@ Checklist.propTypes = {
* session: window.sessionStorage, data is cleared once the browser quit.
*/
persistence_type: PropTypes.oneOf(['local', 'session', 'memory']),
+
+ /**
+ * Indicates whether given `options` are array or dictionary
+ * if True:
+ * `options` will receive: [`value1`, `value2`, `value3`, ...]
+ * which equals to [{label: `value1`, value: `value1`}, {label: `value2, value: `value2`}, ...]
+ * if False:
+ * `options` will receive: [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ inline: PropTypes.bool,
};
Checklist.defaultProps = {
@@ -204,4 +217,5 @@ Checklist.defaultProps = {
value: [],
persisted_props: ['value'],
persistence_type: 'local',
+ inline: false,
};
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 8c2ef151b1..2bef0ead14 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -23,12 +23,16 @@ export default class RadioItems extends Component {
setProps,
loading_state,
value,
+ inline
} = this.props;
let ids = {};
if (id) {
ids = {id, key: id};
}
+ const sanitizeOptions = !inline ? options
+ : options.keys().map(k => ({ label: k, value: options[k] }))
+
return (
- {options.map(option => (
+ {(inline ? sanitizeOptions(options) : options).map(option => (
);
@@ -95,7 +102,7 @@ Checklist.propTypes = {
*/
disabled: PropTypes.bool,
}),
- PropTypes.string
+ PropTypes.string,
])
),
@@ -199,10 +206,10 @@ Checklist.propTypes = {
/**
* Indicates whether given `options` are array or dictionary
- * if True:
+ * if True:
* `options` will receive: [`value1`, `value2`, `value3`, ...]
* which equals to [{label: `value1`, value: `value1`}, {label: `value2, value: `value2`}, ...]
- * if False:
+ * if False:
* `options` will receive: [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
*/
inline: PropTypes.bool,
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 63359f755a..b96b95f83d 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -58,7 +58,7 @@ Dropdown.propTypes = {
*/
title: PropTypes.string,
}),
- PropTypes.string
+ PropTypes.string,
])
),
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 2bef0ead14..fa4ae6c320 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -23,15 +23,16 @@ export default class RadioItems extends Component {
setProps,
loading_state,
value,
- inline
+ inline,
} = this.props;
let ids = {};
if (id) {
ids = {id, key: id};
}
- const sanitizeOptions = !inline ? options
- : options.keys().map(k => ({ label: k, value: options[k] }))
+ const sanitizeOptions = !inline
+ ? options
+ : options.keys().map(k => ({label: k, value: options[k]}));
return (
- (type(opt) === 'string') ? {
- label: opt,
- value: opt,
- } : opt
+ type(opt) === 'string'
+ ? {
+ label: opt,
+ value: opt,
+ }
+ : opt
);
this.setState({
filterOptions: createFilterOptions({
From 9deee7196494034ba3485f08bcfbf3078fe0b7cf Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 16:02:17 -0400
Subject: [PATCH 07/80] generating seed for component id
---
dash/development/base_component.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index 43b6dfb2ff..d1a4f67acb 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -3,6 +3,7 @@
import sys
import uuid
import random
+import hashlib
from .._utils import patch_collections_abc, stringify_id
@@ -60,6 +61,10 @@ def _check_if_has_indexable_children(item):
raise KeyError
+def generate_seed(obj, kwargs):
+ return hashlib.md5(bytes(str(obj)+ str(kwargs), "utf8")).hexdigest()
+
+
class Component(metaclass=ComponentMeta):
class _UNDEFINED:
def __repr__(self):
@@ -84,7 +89,7 @@ def __init__(self, **kwargs):
if "id" not in kwargs.keys():
rd = random.Random()
- # rd.seed(seed)
+ rd.seed(int(generate_seed(self, kwargs), 16))
kwargs["id"] = str(uuid.UUID(int=rd.getrandbits(64)))
# pylint: disable=super-init-not-called
From ab3dfaeb12fe86f6f2c7f80ee96dd3f1c496bfd2 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 16:26:24 -0400
Subject: [PATCH 08/80] lint fix in dash-table
---
components/dash-table/src/dash-table/dash/DataTable.js | 4 ++--
components/dash-table/src/dash-table/dash/Sanitizer.ts | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/components/dash-table/src/dash-table/dash/DataTable.js b/components/dash-table/src/dash-table/dash/DataTable.js
index 5faff8ef9c..86b9e75de7 100644
--- a/components/dash-table/src/dash-table/dash/DataTable.js
+++ b/components/dash-table/src/dash-table/dash/DataTable.js
@@ -123,7 +123,7 @@ export const propTypes = {
*/
data: PropTypes.arrayOf(PropTypes.object),
- /**
+ /**
* Columns describes various aspects about each individual column.
* `name` and `id` are the only required parameters.
*/
@@ -440,7 +440,7 @@ export const propTypes = {
row_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
column_id: PropTypes.string
}),
-
+
/**
* If true, headers are included when copying from the table to different
* tabs and elsewhere. Note that headers are ignored when copying from the table onto itself and
diff --git a/components/dash-table/src/dash-table/dash/Sanitizer.ts b/components/dash-table/src/dash-table/dash/Sanitizer.ts
index cda6a2c25a..c3d4e8f1a2 100644
--- a/components/dash-table/src/dash-table/dash/Sanitizer.ts
+++ b/components/dash-table/src/dash-table/dash/Sanitizer.ts
@@ -119,7 +119,7 @@ export default class Sanitizer {
props.columns,
props.editable,
props.filter_options
- )
+ )
: [];
const data = props.data ?? [];
const visibleColumns = this.getVisibleColumns(
From e986f5d8e9a7cfd07d6a714c843aeaeaa65cb3f3 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 16:31:15 -0400
Subject: [PATCH 09/80] lint fix
---
dash/development/base_component.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index d1a4f67acb..d29f339fa8 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -62,7 +62,7 @@ def _check_if_has_indexable_children(item):
def generate_seed(obj, kwargs):
- return hashlib.md5(bytes(str(obj)+ str(kwargs), "utf8")).hexdigest()
+ return hashlib.md5(bytes(str(obj) + str(kwargs), "utf8")).hexdigest()
class Component(metaclass=ComponentMeta):
From 405bf72f7f37ff8aecf76787e08e383a0fc535ca Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 17:06:21 -0400
Subject: [PATCH 10/80] remove inline props and lint fix
---
.../src/components/Checklist.react.js | 33 ++++++++-----------
.../src/components/Dropdown.react.js | 6 ++++
.../src/components/RadioItems.react.js | 25 +++++++-------
dash/development/base_component.py | 13 ++++----
4 files changed, 39 insertions(+), 38 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 3730a3eb47..48df82d696 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -22,7 +22,6 @@ export default class Checklist extends Component {
style,
loading_state,
value,
- inline,
} = this.props;
return (
@@ -35,13 +34,14 @@ export default class Checklist extends Component {
className={className}
>
{options.map(option => {
- option = inline
- ? {
- label: option,
- value: option,
- disabled: false,
- }
- : option;
+ option =
+ typeof option === 'string'
+ ? {
+ label: option,
+ value: option,
+ disabled: false,
+ }
+ : option;
return (
({label: k, value: options[k]}));
+ const sanitizeOptions =
+ typeof options === 'array'
+ ? options
+ : options.keys().map(k => ({label: k, value: options[k]}));
return (
- {(inline ? sanitizeOptions(options) : options).map(option => (
+ {sanitizeOptions(options).map(option => (
Date: Mon, 6 Sep 2021 17:41:03 -0400
Subject: [PATCH 11/80] broken eslint :grimacing:
---
.../dash-core-components/src/components/RadioItems.react.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 5ef6a9b3b1..96a2f212a7 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -30,7 +30,7 @@ export default class RadioItems extends Component {
ids = {id, key: id};
}
const sanitizeOptions =
- typeof options === 'array'
+ typeof(options) !== 'object'
? options
: options.keys().map(k => ({label: k, value: options[k]}));
From 2582056c32d36fef2e86e10bae9aa77244295d4a Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 6 Sep 2021 18:02:50 -0400
Subject: [PATCH 12/80] prettier fix
---
.../dash-core-components/src/components/RadioItems.react.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 96a2f212a7..fce9a10a9b 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -30,7 +30,7 @@ export default class RadioItems extends Component {
ids = {id, key: id};
}
const sanitizeOptions =
- typeof(options) !== 'object'
+ typeof options !== 'object'
? options
: options.keys().map(k => ({label: k, value: options[k]}));
From 82ef2b79e870281d1dd870fa8b5ae0e379d004c9 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 8 Sep 2021 07:47:17 -0400
Subject: [PATCH 13/80] set random id inside dash dependency
---
dash/dependencies.py | 15 ++++++++++++---
dash/development/base_component.py | 21 +++++++++++----------
2 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/dash/dependencies.py b/dash/dependencies.py
index 82b49030aa..deee619011 100644
--- a/dash/dependencies.py
+++ b/dash/dependencies.py
@@ -1,3 +1,4 @@
+from dash.development.base_component import Component
import json
from ._validate import validate_callback
@@ -27,9 +28,17 @@ def to_json(self):
class DashDependency: # pylint: disable=too-few-public-methods
def __init__(self, component_id, component_property):
- self.component_id = (
- component_id if isinstance(component_id, str) else component_id.id
- )
+
+ if isinstance(component_id, str):
+ self.component_id = component_id
+ elif isinstance(component_id, Component):
+ self.component_id = component_id.set_random_id()
+ else:
+ raise ValueError(
+ "The input argument to DashDependency may be a string or Component,\n"
+ f"but received value of type {type(component_id)}"
+ )
+
self.component_property = component_property
def __str__(self):
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index ffcc58e8b5..337d38cd0e 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -61,14 +61,6 @@ def _check_if_has_indexable_children(item):
raise KeyError
-def _auto_set_id(obj, **kwargs):
- if "id" not in kwargs.keys():
- rd = random.Random()
- hexdigest = hashlib.md5(bytes(str(obj) + str(kwargs), "utf8")).hexdigest()
- rd.seed(int(hexdigest, 16))
- kwargs["id"] = str(uuid.UUID(int=rd.getrandbits(64)))
-
-
class Component(metaclass=ComponentMeta):
class _UNDEFINED:
def __repr__(self):
@@ -91,8 +83,6 @@ def __str__(self):
def __init__(self, **kwargs):
import dash # pylint: disable=import-outside-toplevel, cyclic-import
- _auto_set_id(self, **kwargs)
-
# pylint: disable=super-init-not-called
for k, v in list(kwargs.items()):
# pylint: disable=no-member
@@ -176,6 +166,17 @@ def __init__(self, **kwargs):
setattr(self, k, v)
+ def set_random_id(self):
+ if not hasattr(self, "id"):
+ rd = random.Random()
+ hexdigest = hashlib.md5(
+ bytes(str(self.to_plotly_json()), "utf8")
+ ).hexdigest()
+ rd.seed(int(hexdigest, 16))
+ v = str(uuid.UUID(int=rd.getrandbits(64)))
+ self.id = v
+ return self.id
+
def to_plotly_json(self):
# Add normal properties
props = {
From 1c1faf237ed3226ffc293ef8682d7d9099b714c1 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 9 Sep 2021 10:11:43 -0400
Subject: [PATCH 14/80] lint fixes
---
dash/dependencies.py | 2 +-
dash/development/base_component.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dash/dependencies.py b/dash/dependencies.py
index deee619011..b93c1af40f 100644
--- a/dash/dependencies.py
+++ b/dash/dependencies.py
@@ -1,5 +1,5 @@
-from dash.development.base_component import Component
import json
+from dash.development.base_component import Component
from ._validate import validate_callback
from ._grouping import flatten_grouping, make_grouping_by_index
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index 337d38cd0e..5ccfb8677e 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -174,8 +174,8 @@ def set_random_id(self):
).hexdigest()
rd.seed(int(hexdigest, 16))
v = str(uuid.UUID(int=rd.getrandbits(64)))
- self.id = v
- return self.id
+ setattr(self, "id", v)
+ return getattr(self, "id")
def to_plotly_json(self):
# Add normal properties
From 38ed9bff7c43c155d80b7ce05bcf3fcaff393951 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 9 Sep 2021 13:20:53 -0400
Subject: [PATCH 15/80] bug fix
---
.../dash-core-components/src/components/RadioItems.react.js | 2 +-
dash/development/component_generator.py | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index fce9a10a9b..d86e6ab654 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -32,7 +32,7 @@ export default class RadioItems extends Component {
const sanitizeOptions =
typeof options !== 'object'
? options
- : options.keys().map(k => ({label: k, value: options[k]}));
+ : Object.entries(options).map(([label, value]) => ({label, value}));
return (
Date: Thu, 9 Sep 2021 13:44:57 -0400
Subject: [PATCH 16/80] add inline styling support
---
.../src/components/Checklist.react.js | 5 +++++
.../src/components/RadioItems.react.js | 11 +++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 48df82d696..795bf0986f 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -22,8 +22,10 @@ export default class Checklist extends Component {
style,
loading_state,
value,
+ inline,
} = this.props;
+ Object.assign(labelStyle, inline ? {display: 'inline'} : {});
return (
({label, value}));
-
+ : Object.entries(options).map(([label, value]) => ({
+ label,
+ value,
+ }));
+ Object.assign(labelStyle, inline ? {display: 'inline'} : {});
return (
Date: Thu, 9 Sep 2021 13:48:53 -0400
Subject: [PATCH 17/80] fix bugs
---
.../dash-core-components/src/components/RadioItems.react.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 4a020b2c7a..7debe566a6 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -30,7 +30,7 @@ export default class RadioItems extends Component {
if (id) {
ids = {id, key: id};
}
- const sanitizeOptions =
+ const sanitizedOptions =
typeof options !== 'object'
? options
: Object.entries(options).map(([label, value]) => ({
@@ -47,7 +47,7 @@ export default class RadioItems extends Component {
className={className}
style={style}
>
- {sanitizeOptions(options).map(option => (
+ {sanitizedOptions.map(option => (
Date: Thu, 9 Sep 2021 16:04:52 -0400
Subject: [PATCH 18/80] add column populating in dash-table
---
.../src/dash-table/components/Table/props.ts | 20 +++++++++++++++++++
.../src/dash-table/dash/Sanitizer.ts | 16 +++++++++++----
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/components/dash-table/src/dash-table/components/Table/props.ts b/components/dash-table/src/dash-table/components/Table/props.ts
index 71aef18941..93e48b6821 100644
--- a/components/dash-table/src/dash-table/components/Table/props.ts
+++ b/components/dash-table/src/dash-table/components/Table/props.ts
@@ -97,6 +97,26 @@ export interface ICellCoordinates {
column_id: ColumnId;
}
+export class Column implements IBaseColumn {
+ clearable?: boolean | boolean[] | 'first' | 'last' | undefined;
+ deletable?: boolean | boolean[] | 'first' | 'last' | undefined;
+ editable = false;
+ filter_options!: IFilterOptions;
+ hideable?: boolean | boolean[] | 'first' | 'last' | undefined;
+ renamable?: boolean | boolean[] | 'first' | 'last' | undefined;
+ selectable?: boolean | boolean[] | 'first' | 'last' | undefined;
+ sort_as_null: SortAsNull = [];
+ id!: string;
+ name: string | string[] = [];
+
+ constructor(initialValues: any) {
+ if (Object.keys(initialValues).includes('name'))
+ this.name = initialValues.name;
+ if (Object.keys(initialValues).includes('id'))
+ this.id = initialValues.id;
+ }
+}
+
export type ColumnId = string;
export type Columns = IColumn[];
export type Data = Datum[];
diff --git a/components/dash-table/src/dash-table/dash/Sanitizer.ts b/components/dash-table/src/dash-table/dash/Sanitizer.ts
index c3d4e8f1a2..7198e4bced 100644
--- a/components/dash-table/src/dash-table/dash/Sanitizer.ts
+++ b/components/dash-table/src/dash-table/dash/Sanitizer.ts
@@ -2,7 +2,6 @@ import * as R from 'ramda';
import {memoizeOne} from 'core/memoizer';
import {
- Columns,
ColumnType,
Fixed,
IColumn,
@@ -18,11 +17,13 @@ import {
FilterLogicalOperator,
SelectedCells,
FilterCase,
- IFilterOptions
+ IFilterOptions,
+ Data
} from 'dash-table/components/Table/props';
import headerRows from 'dash-table/derived/header/headerRows';
import resolveFlag from 'dash-table/derived/cell/resolveFlag';
import dataLoading from 'dash-table/derived/table/data_loading';
+import {Column, Columns} from '../components/Table/props';
const D3_DEFAULT_LOCALE: INumberLocale = {
symbol: ['$', ''],
@@ -65,6 +66,11 @@ const getFixedRows = (
(filter_action !== TableAction.None ? 1 : 0) +
data2number(fixed.data);
+const populateColumnsFromData = (data: Data) =>
+ data.length > 0
+ ? Object.keys(data[0]).map(key => new Column({name: key, id: key}))
+ : [];
+
const applyDefaultsToColumns = (
defaultLocale: INumberLocale,
defaultSort: SortAsNull,
@@ -112,6 +118,7 @@ const getVisibleColumns = (
export default class Sanitizer {
sanitize(props: PropsWithDefaults): SanitizedProps {
const locale_format = this.applyDefaultToLocale(props.locale_format);
+ const data = props.data ?? [];
const columns = props.columns
? this.applyDefaultsToColumns(
locale_format,
@@ -120,8 +127,7 @@ export default class Sanitizer {
props.editable,
props.filter_options
)
- : [];
- const data = props.data ?? [];
+ : this.populateColumnsFrom(data);
const visibleColumns = this.getVisibleColumns(
columns,
props.hidden_columns
@@ -171,6 +177,8 @@ export default class Sanitizer {
});
}
+ private readonly populateColumnsFrom = memoizeOne(populateColumnsFromData);
+
private readonly applyDefaultToLocale = memoizeOne(applyDefaultToLocale);
private readonly applyDefaultsToColumns = memoizeOne(
From e172ef89d7737d59e116dffda967a8ce61a6e316 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 9 Sep 2021 17:47:21 -0400
Subject: [PATCH 19/80] disable restricting dependency type
---
dash/dependencies.py | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/dash/dependencies.py b/dash/dependencies.py
index b93c1af40f..12cd4a59be 100644
--- a/dash/dependencies.py
+++ b/dash/dependencies.py
@@ -29,15 +29,10 @@ def to_json(self):
class DashDependency: # pylint: disable=too-few-public-methods
def __init__(self, component_id, component_property):
- if isinstance(component_id, str):
- self.component_id = component_id
- elif isinstance(component_id, Component):
+ if isinstance(component_id, Component):
self.component_id = component_id.set_random_id()
else:
- raise ValueError(
- "The input argument to DashDependency may be a string or Component,\n"
- f"but received value of type {type(component_id)}"
- )
+ self.component_id = component_id
self.component_property = component_property
From c443e676201acdb334bc7e4416060b5c97fc873c Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 9 Sep 2021 20:46:54 -0400
Subject: [PATCH 20/80] fix radio options type check
---
.../src/components/RadioItems.react.js | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 7debe566a6..53e3b089b4 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -30,13 +30,12 @@ export default class RadioItems extends Component {
if (id) {
ids = {id, key: id};
}
- const sanitizedOptions =
- typeof options !== 'object'
- ? options
- : Object.entries(options).map(([label, value]) => ({
- label,
- value,
- }));
+ const sanitizedOptions = Array.isArray(options)
+ ? options
+ : Object.entries(options).map(([label, value]) => ({
+ label,
+ value,
+ }));
Object.assign(labelStyle, inline ? {display: 'inline'} : {});
return (
Date: Thu, 9 Sep 2021 21:15:33 -0400
Subject: [PATCH 21/80] add comments to inline props
---
.../dash-core-components/src/components/Checklist.react.js | 5 +++++
.../dash-core-components/src/components/RadioItems.react.js | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 795bf0986f..28f3c7922a 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -212,6 +212,11 @@ Checklist.propTypes = {
*/
persistence_type: PropTypes.oneOf(['local', 'session', 'memory']),
+ /**
+ * Indicates whether labelStyle should be inline or not
+ * True: Automatically set { 'display': 'inline' } to labelStyle
+ * False: No additional behavior to expect
+ */
inline: PropTypes.bool,
};
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 53e3b089b4..771bc7253e 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -203,6 +203,11 @@ RadioItems.propTypes = {
*/
persistence_type: PropTypes.oneOf(['local', 'session', 'memory']),
+ /**
+ * Indicates whether labelStyle should be inline or not
+ * True: Automatically set { 'display': 'inline' } to labelStyle
+ * False: No additional behavior to expect
+ */
inline: PropTypes.bool,
};
From bd7a9e331a8050533761b8981c3951433c877d71 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 9 Sep 2021 22:21:14 -0400
Subject: [PATCH 22/80] add tests for shorthands
---
.../tests/integration/misc/test_shorthands.py | 147 ++++++++++++++++++
1 file changed, 147 insertions(+)
create mode 100644 components/dash-core-components/tests/integration/misc/test_shorthands.py
diff --git a/components/dash-core-components/tests/integration/misc/test_shorthands.py b/components/dash-core-components/tests/integration/misc/test_shorthands.py
new file mode 100644
index 0000000000..83e7aa3741
--- /dev/null
+++ b/components/dash-core-components/tests/integration/misc/test_shorthands.py
@@ -0,0 +1,147 @@
+from plotly import graph_objs
+from dash import Dash, Input, Output, dcc, html
+from selenium.webdriver.common.keys import Keys
+import dash_bootstrap_components as dbc
+import plotly.express as px
+import pandas as pd
+import dash_table as dt
+
+# DROPDOWN EXAMPLE - bar-charts
+def test_mssh001_bar_charts(dash_duo):
+ app = Dash(__name__)
+
+ df = px.data.tips()
+
+ dropdown = dcc.Dropdown(df.day.unique(), value="Sun")
+ barchart = dcc.Graph()
+ app.layout = dbc.Container([dropdown, barchart])
+
+ @app.callback(Output(barchart, "figure"), Input(dropdown, "value"))
+ def update(day):
+ return px.bar(
+ df["day"] == day, x="sex", y="total_bill", color="smoker", barmode="group"
+ )
+
+ dash_duo.start_server(app)
+ assert dash_duo.get_logs() == []
+
+
+# SLIDER EXAMPLE - line-and-scatter
+def test_mssh002_line_and_scatter(dash_duo):
+ app = Dash(__name__)
+
+ df = px.data.iris()
+
+ graph = dcc.Graph()
+ label = dbc.Label("Petal Width:")
+ slider = dcc.RangeSlider(0, 2.5)
+
+ app.layout = dbc.Container([graph, label, slider])
+
+ @app.callback(Output(graph, "figure"), Input(slider, "value"))
+ def update(slider_range):
+ low, high = slider_range
+ mask = (df["petal_width"] > low) & (df["petal_width"] < high)
+ return px.scatter(
+ df[mask],
+ x="sepal_width",
+ y="sepal_length",
+ color="species",
+ size="petal_length",
+ hover_data=["petal_width"],
+ )
+
+ dash_duo.start_server(app)
+ assert dash_duo.get_logs() == []
+
+
+# CHECKLIST EXAMPLE - line-charts
+def test_mssh003_checklist_example_line_charts(dash_duo):
+ app = Dash(__name__)
+
+ df = px.data.gapminder()
+ continents = df.continent.unique()
+
+ app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
+
+ cl = dcc.Checklist(continents, value=continents[3:], inline=True)
+ graph = dcc.Graph()
+ app.layout = dbc.Container([cl, graph])
+
+ @app.callback(Output(graph, "figure"), Input(cl, "value"))
+ def update(continents):
+ return px.line(
+ df[df.continent.isin(continents)], x="year", y="lifeExp", color="country"
+ )
+
+ dash_duo.start_server(app)
+ assert dash_duo.get_logs() == []
+
+
+# BUTTON EXAMPLE - axes
+def test_mssh004_button_axes(dash_duo):
+ app = Dash(__name__)
+
+ df = px.data.tips()
+
+ graph = dcc.Graph()
+ btn = html.Button("Rotate", n_clicks=0)
+ app.layout = dbc.Container([graph, btn])
+
+ @app.callback(Output(graph, "figure"), Input(btn, "n_clicks"))
+ def rotate_figure(n_clicks):
+ return px.histogram(df, x="sex").update_xaxes(tickangle=n_clicks * 45)
+
+ dash_duo.start_server(app)
+ assert dash_duo.get_logs() == []
+
+
+# TABLE EXAMPLE
+def test_mssh005_table_example(dash_duo):
+ app = Dash(__name__)
+
+ df = pd.read_csv("https://git.io/Juf1t")
+
+ app.layout = dbc.Container(
+ [
+ dbc.Label("Click a cell in the table:", id="out"),
+ dt.DataTable(df.to_dict("records"), id="tbl"),
+ ]
+ )
+
+ @app.callback(Output("out", "children"), Input("tbl", "active_cell"))
+ def update(active_cell):
+ return str(active_cell)
+
+ dash_duo.start_server(app)
+ assert dash_duo.get_logs() == []
+
+
+# RADIO BUTTONS - legend
+def test_mssh006_radio_buttons(dash_duo):
+ app = Dash(__name__)
+
+ # Define the figure
+ df = px.data.gapminder().query("year==2007")
+
+ graph = dcc.Graph()
+ x = dcc.RadioItems({"left": 0, "right": 1}, id="x", inline=True)
+ y = dcc.RadioItems({"top": 0, "bottom": 1}, id="y", inline=True)
+ label = dbc.Label("Legend position")
+
+ app.layout = dbc.Container([graph, label, x, y])
+
+ @app.callback(Output(graph, "figure"), [Input(x, "value"), Input(y, "value")])
+ def update(pos_x, pos_y):
+ return px.scatter(
+ df,
+ x="gdpPercap",
+ y="lifeExp",
+ color="continent",
+ size="pop",
+ size_max=45,
+ log_x=True,
+ ).update_layout(legend_x=pos_x, legend_y=pos_y)
+
+ dash_duo.start_server(app)
+ assert dash_duo.get_logs() == []
From e5335ce0ac1385bd0651a11b984675c295ba3b84 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 9 Sep 2021 22:39:11 -0400
Subject: [PATCH 23/80] remove unused imports
---
.../tests/integration/misc/test_shorthands.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/components/dash-core-components/tests/integration/misc/test_shorthands.py b/components/dash-core-components/tests/integration/misc/test_shorthands.py
index 83e7aa3741..0c528e42ea 100644
--- a/components/dash-core-components/tests/integration/misc/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/misc/test_shorthands.py
@@ -1,11 +1,10 @@
-from plotly import graph_objs
from dash import Dash, Input, Output, dcc, html
-from selenium.webdriver.common.keys import Keys
import dash_bootstrap_components as dbc
import plotly.express as px
import pandas as pd
import dash_table as dt
+
# DROPDOWN EXAMPLE - bar-charts
def test_mssh001_bar_charts(dash_duo):
app = Dash(__name__)
From 22d2020c2714f6ec12a92290bde3b03ece790d55 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 10 Sep 2021 00:10:27 -0400
Subject: [PATCH 24/80] remove tests, refactor assign
---
.../src/components/Checklist.react.js | 8 +-
.../src/components/RadioItems.react.js | 7 +-
.../tests/integration/misc/test_shorthands.py | 146 ------------------
3 files changed, 10 insertions(+), 151 deletions(-)
delete mode 100644 components/dash-core-components/tests/integration/misc/test_shorthands.py
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 28f3c7922a..bc053bcaba 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -24,8 +24,6 @@ export default class Checklist extends Component {
value,
inline,
} = this.props;
-
- Object.assign(labelStyle, inline ? {display: 'inline'} : {});
return (
{sanitizedOptions.map(option => (
diff --git a/components/dash-core-components/tests/integration/misc/test_shorthands.py b/components/dash-core-components/tests/integration/misc/test_shorthands.py
deleted file mode 100644
index 0c528e42ea..0000000000
--- a/components/dash-core-components/tests/integration/misc/test_shorthands.py
+++ /dev/null
@@ -1,146 +0,0 @@
-from dash import Dash, Input, Output, dcc, html
-import dash_bootstrap_components as dbc
-import plotly.express as px
-import pandas as pd
-import dash_table as dt
-
-
-# DROPDOWN EXAMPLE - bar-charts
-def test_mssh001_bar_charts(dash_duo):
- app = Dash(__name__)
-
- df = px.data.tips()
-
- dropdown = dcc.Dropdown(df.day.unique(), value="Sun")
- barchart = dcc.Graph()
- app.layout = dbc.Container([dropdown, barchart])
-
- @app.callback(Output(barchart, "figure"), Input(dropdown, "value"))
- def update(day):
- return px.bar(
- df["day"] == day, x="sex", y="total_bill", color="smoker", barmode="group"
- )
-
- dash_duo.start_server(app)
- assert dash_duo.get_logs() == []
-
-
-# SLIDER EXAMPLE - line-and-scatter
-def test_mssh002_line_and_scatter(dash_duo):
- app = Dash(__name__)
-
- df = px.data.iris()
-
- graph = dcc.Graph()
- label = dbc.Label("Petal Width:")
- slider = dcc.RangeSlider(0, 2.5)
-
- app.layout = dbc.Container([graph, label, slider])
-
- @app.callback(Output(graph, "figure"), Input(slider, "value"))
- def update(slider_range):
- low, high = slider_range
- mask = (df["petal_width"] > low) & (df["petal_width"] < high)
- return px.scatter(
- df[mask],
- x="sepal_width",
- y="sepal_length",
- color="species",
- size="petal_length",
- hover_data=["petal_width"],
- )
-
- dash_duo.start_server(app)
- assert dash_duo.get_logs() == []
-
-
-# CHECKLIST EXAMPLE - line-charts
-def test_mssh003_checklist_example_line_charts(dash_duo):
- app = Dash(__name__)
-
- df = px.data.gapminder()
- continents = df.continent.unique()
-
- app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
-
- cl = dcc.Checklist(continents, value=continents[3:], inline=True)
- graph = dcc.Graph()
- app.layout = dbc.Container([cl, graph])
-
- @app.callback(Output(graph, "figure"), Input(cl, "value"))
- def update(continents):
- return px.line(
- df[df.continent.isin(continents)], x="year", y="lifeExp", color="country"
- )
-
- dash_duo.start_server(app)
- assert dash_duo.get_logs() == []
-
-
-# BUTTON EXAMPLE - axes
-def test_mssh004_button_axes(dash_duo):
- app = Dash(__name__)
-
- df = px.data.tips()
-
- graph = dcc.Graph()
- btn = html.Button("Rotate", n_clicks=0)
- app.layout = dbc.Container([graph, btn])
-
- @app.callback(Output(graph, "figure"), Input(btn, "n_clicks"))
- def rotate_figure(n_clicks):
- return px.histogram(df, x="sex").update_xaxes(tickangle=n_clicks * 45)
-
- dash_duo.start_server(app)
- assert dash_duo.get_logs() == []
-
-
-# TABLE EXAMPLE
-def test_mssh005_table_example(dash_duo):
- app = Dash(__name__)
-
- df = pd.read_csv("https://git.io/Juf1t")
-
- app.layout = dbc.Container(
- [
- dbc.Label("Click a cell in the table:", id="out"),
- dt.DataTable(df.to_dict("records"), id="tbl"),
- ]
- )
-
- @app.callback(Output("out", "children"), Input("tbl", "active_cell"))
- def update(active_cell):
- return str(active_cell)
-
- dash_duo.start_server(app)
- assert dash_duo.get_logs() == []
-
-
-# RADIO BUTTONS - legend
-def test_mssh006_radio_buttons(dash_duo):
- app = Dash(__name__)
-
- # Define the figure
- df = px.data.gapminder().query("year==2007")
-
- graph = dcc.Graph()
- x = dcc.RadioItems({"left": 0, "right": 1}, id="x", inline=True)
- y = dcc.RadioItems({"top": 0, "bottom": 1}, id="y", inline=True)
- label = dbc.Label("Legend position")
-
- app.layout = dbc.Container([graph, label, x, y])
-
- @app.callback(Output(graph, "figure"), [Input(x, "value"), Input(y, "value")])
- def update(pos_x, pos_y):
- return px.scatter(
- df,
- x="gdpPercap",
- y="lifeExp",
- color="continent",
- size="pop",
- size_max=45,
- log_x=True,
- ).update_layout(legend_x=pos_x, legend_y=pos_y)
-
- dash_duo.start_server(app)
- assert dash_duo.get_logs() == []
From 7497eb218b3545633b11fbeeba5a56bc7f49880b Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 10 Sep 2021 08:34:35 -0400
Subject: [PATCH 25/80] use ramda.type instead of typeof
---
.../dash-core-components/src/components/Checklist.react.js | 4 ++--
.../dash-core-components/src/fragments/Dropdown.react.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index bc053bcaba..8464531623 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
-import {append, includes, without} from 'ramda';
+import {append, includes, type, without} from 'ramda';
import React, {Component} from 'react';
/**
@@ -35,7 +35,7 @@ export default class Checklist extends Component {
>
{options.map(option => {
option =
- typeof option === 'string'
+ type(option) === 'String'
? {
label: option,
value: option,
diff --git a/components/dash-core-components/src/fragments/Dropdown.react.js b/components/dash-core-components/src/fragments/Dropdown.react.js
index 6a2c1dac52..a9163f5405 100644
--- a/components/dash-core-components/src/fragments/Dropdown.react.js
+++ b/components/dash-core-components/src/fragments/Dropdown.react.js
@@ -36,7 +36,7 @@ export default class Dropdown extends Component {
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.options !== this.props.options) {
const normalizedOptions = newProps.options.map(opt =>
- type(opt) === 'string'
+ type(opt) === 'String'
? {
label: opt,
value: opt,
@@ -65,7 +65,7 @@ export default class Dropdown extends Component {
} = this.props;
const {filterOptions} = this.state;
let selectedValue;
- if (type(value) === 'array') {
+ if (type(value) === 'Array') {
selectedValue = value.join(DELIMETER);
} else {
selectedValue = value;
From cdd6d1889aa158fa096ee971620622db6f4794a5 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 10 Sep 2021 21:38:07 -0400
Subject: [PATCH 26/80] backup commit
---
.../src/fragments/RangeSlider.react.js | 158 ++++++++++++++++--
1 file changed, 148 insertions(+), 10 deletions(-)
diff --git a/components/dash-core-components/src/fragments/RangeSlider.react.js b/components/dash-core-components/src/fragments/RangeSlider.react.js
index a8f4e8c81d..622d748b2c 100644
--- a/components/dash-core-components/src/fragments/RangeSlider.react.js
+++ b/components/dash-core-components/src/fragments/RangeSlider.react.js
@@ -7,6 +7,140 @@ import 'rc-slider/assets/index.css';
import {propTypes, defaultProps} from '../components/RangeSlider.react';
+/**
+ * Truncate marks if they are out of Slider interval
+ */
+const truncateMarks = (min, max, marks) =>
+ pickBy((k, mark) => mark >= min && mark <= max, marks);
+
+const decimalCount = d =>
+ String(d).split('.').length > 1 ? String(d).split('.')[1].length : 0;
+const alignValue = (v, d) => ((v / d).toFixed(0) * d).toFixed(decimalCount(d));
+
+const getNearbyPows = v => [
+ Math.pow(10, Math.floor(Math.log10(v))),
+ Math.pow(10, Math.ceil(Math.log10(v))),
+];
+
+const estimateBestSteps = (minValue, maxValue, stepValue) => {
+ const desiredCountMin = 3 + 2; // including start, end
+ const desiredCountMax = 6 + 2;
+
+ const totalStepCount = (maxValue - minValue) / stepValue;
+ if (totalStepCount <= desiredCountMax) {
+ return [minValue, stepValue];
+ }
+
+ const min = minValue / stepValue;
+ const max = maxValue / stepValue;
+
+ const rangeLength = max - min;
+
+ const worstInterval = Math.max(
+ Math.ceil(rangeLength / (desiredCountMin - 1)),
+ 1
+ );
+ let interval = worstInterval;
+ const [lowerStep, higherStep] = getNearbyPows(interval);
+ const step = interval > higherStep / 2 ? higherStep : lowerStep;
+
+ const alignedMin = alignValue(min, step);
+ interval = alignValue(interval, step);
+ let bestInterval = interval,
+ expectedCount = 0;
+
+ do {
+ expectedCount = (rangeLength / interval).toFixed(0);
+
+ if (max >= alignedMin + interval * (expectedCount - 0.5)) {
+ bestInterval = interval;
+ break;
+ }
+
+ interval -= step;
+ } while (expectedCount < desiredCountMax && interval > 0);
+
+ return [
+ alignedMin * stepValue,
+ (bestInterval > 0 ? bestInterval : worstInterval) * stepValue,
+ ];
+};
+
+const autoGenerateMarks = (min, max, step = 1) => {
+ const marks = [];
+ const [start, interval] = estimateBestSteps(min, max, step);
+ let cursor = start + interval;
+
+ do {
+ marks.push(alignValue(cursor, step));
+ cursor += interval;
+ } while (cursor < max);
+
+ // do some cosmetic
+ const discardThreshold = 1.5;
+ if (
+ marks.length > 2 &&
+ max - marks[marks.length - 2] <= interval * discardThreshold
+ ) {
+ marks.pop();
+ }
+
+ const marksObject = {};
+ marks.forEach(mark => {
+ marksObject[mark] = String(mark);
+ });
+ marksObject[min] = 'Start (' + min + ')';
+ marksObject[max] = 'End (' + max + ')';
+ return marksObject;
+};
+
+/**
+ * Set marks to min and max if not defined, truncate otherwise
+ */
+const calcMarks = ({min, max, marks, step}) => {
+ console.log("Are you serious, ", marks);
+ if (!marks) {
+ return {
+ [min]: min,
+ [max]: max,
+ marks: autoGenerateMarks(min, max, step),
+ };
+ }
+
+ return truncateMarks(min, max, marks);
+};
+
+/**
+ * Calculate default step if not defined
+ */
+const calcStep = (min, max, step) => {
+ if (step !== undefined) {
+ return step;
+ }
+
+ const size = Math.abs(max - min); // interval size
+ /**
+ * Size multiplied by 10^i to get a nice step value at the end (0.1, 1, 10, 100, ...)
+ */
+ const divident = size
+ .toString()
+ .replace('.', '') // removes decimal point
+ .replace(/^(\d*?[1-9])0+$/, '$1'); // removes trailing zeros
+
+ return size / divident;
+};
+
+/**
+ * Calculate default value if not defined
+ */
+const calcValue = (min, max, value) => {
+ if (value !== undefined) {
+ return value;
+ }
+
+ return [min, max];
+};
+
export default class RangeSlider extends Component {
constructor(props) {
super(props);
@@ -14,7 +148,12 @@ export default class RangeSlider extends Component {
? createSliderWithTooltip(Range)
: Range;
this._computeStyle = computeSliderStyle();
- this.state = {value: props.value};
+
+ const {min, max, value, setProps} = props;
+ this.state = {value};
+ if (!value) {
+ setProps({value: calcValue(min, max, value)});
+ }
}
UNSAFE_componentWillReceiveProps(newProps) {
@@ -46,6 +185,10 @@ export default class RangeSlider extends Component {
updatemode,
vertical,
verticalHeight,
+ min,
+ max,
+ marks,
+ step,
} = this.props;
const value = this.state.value;
@@ -62,13 +205,6 @@ 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
- );
-
return (
node,
}}
style={{position: 'relative'}}
- value={value}
- marks={truncatedMarks}
+ value={calcValue(min, max, value)}
+ marks={calcMarks({min, max, marks, step})}
+ step={calcStep(min, max, step)}
{...omit(
[
'className',
@@ -112,6 +249,7 @@ export default class RangeSlider extends Component {
'marks',
'updatemode',
'verticalHeight',
+ 'step',
],
this.props
)}
From df24223aff503eab1cbc77c96fc54738983262dc Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 10 Sep 2021 22:43:42 -0400
Subject: [PATCH 27/80] add auto generating marks to RangeSlider & Slider
---
.../src/fragments/RangeSlider.react.js | 138 +-----------------
.../src/fragments/Slider.react.js | 16 +-
.../src/utils/computeSliderMarkers.js | 135 +++++++++++++++++
3 files changed, 144 insertions(+), 145 deletions(-)
create mode 100644 components/dash-core-components/src/utils/computeSliderMarkers.js
diff --git a/components/dash-core-components/src/fragments/RangeSlider.react.js b/components/dash-core-components/src/fragments/RangeSlider.react.js
index 622d748b2c..e26ff4fb45 100644
--- a/components/dash-core-components/src/fragments/RangeSlider.react.js
+++ b/components/dash-core-components/src/fragments/RangeSlider.react.js
@@ -1,146 +1,12 @@
import React, {Component} from 'react';
-import {assoc, omit, pickBy} from 'ramda';
+import {assoc, omit} from 'ramda';
import {Range, createSliderWithTooltip} from 'rc-slider';
import computeSliderStyle from '../utils/computeSliderStyle';
import 'rc-slider/assets/index.css';
-
+import {calcValue, calcMarks, calcStep} from '../utils/computeSliderMarkers';
import {propTypes, defaultProps} from '../components/RangeSlider.react';
-/**
- * Truncate marks if they are out of Slider interval
- */
-const truncateMarks = (min, max, marks) =>
- pickBy((k, mark) => mark >= min && mark <= max, marks);
-
-const decimalCount = d =>
- String(d).split('.').length > 1 ? String(d).split('.')[1].length : 0;
-const alignValue = (v, d) => ((v / d).toFixed(0) * d).toFixed(decimalCount(d));
-
-const getNearbyPows = v => [
- Math.pow(10, Math.floor(Math.log10(v))),
- Math.pow(10, Math.ceil(Math.log10(v))),
-];
-
-const estimateBestSteps = (minValue, maxValue, stepValue) => {
- const desiredCountMin = 3 + 2; // including start, end
- const desiredCountMax = 6 + 2;
-
- const totalStepCount = (maxValue - minValue) / stepValue;
- if (totalStepCount <= desiredCountMax) {
- return [minValue, stepValue];
- }
-
- const min = minValue / stepValue;
- const max = maxValue / stepValue;
-
- const rangeLength = max - min;
-
- const worstInterval = Math.max(
- Math.ceil(rangeLength / (desiredCountMin - 1)),
- 1
- );
- let interval = worstInterval;
- const [lowerStep, higherStep] = getNearbyPows(interval);
- const step = interval > higherStep / 2 ? higherStep : lowerStep;
-
- const alignedMin = alignValue(min, step);
- interval = alignValue(interval, step);
- let bestInterval = interval,
- expectedCount = 0;
-
- do {
- expectedCount = (rangeLength / interval).toFixed(0);
-
- if (max >= alignedMin + interval * (expectedCount - 0.5)) {
- bestInterval = interval;
- break;
- }
-
- interval -= step;
- } while (expectedCount < desiredCountMax && interval > 0);
-
- return [
- alignedMin * stepValue,
- (bestInterval > 0 ? bestInterval : worstInterval) * stepValue,
- ];
-};
-
-const autoGenerateMarks = (min, max, step = 1) => {
- const marks = [];
- const [start, interval] = estimateBestSteps(min, max, step);
- let cursor = start + interval;
-
- do {
- marks.push(alignValue(cursor, step));
- cursor += interval;
- } while (cursor < max);
-
- // do some cosmetic
- const discardThreshold = 1.5;
- if (
- marks.length > 2 &&
- max - marks[marks.length - 2] <= interval * discardThreshold
- ) {
- marks.pop();
- }
-
- const marksObject = {};
- marks.forEach(mark => {
- marksObject[mark] = String(mark);
- });
- marksObject[min] = 'Start (' + min + ')';
- marksObject[max] = 'End (' + max + ')';
- return marksObject;
-};
-
-/**
- * Set marks to min and max if not defined, truncate otherwise
- */
-const calcMarks = ({min, max, marks, step}) => {
- console.log("Are you serious, ", marks);
- if (!marks) {
- return {
- [min]: min,
- [max]: max,
- marks: autoGenerateMarks(min, max, step),
- };
- }
-
- return truncateMarks(min, max, marks);
-};
-
-/**
- * Calculate default step if not defined
- */
-const calcStep = (min, max, step) => {
- if (step !== undefined) {
- return step;
- }
-
- const size = Math.abs(max - min); // interval size
- /**
- * Size multiplied by 10^i to get a nice step value at the end (0.1, 1, 10, 100, ...)
- */
- const divident = size
- .toString()
- .replace('.', '') // removes decimal point
- .replace(/^(\d*?[1-9])0+$/, '$1'); // removes trailing zeros
-
- return size / divident;
-};
-
-/**
- * Calculate default value if not defined
- */
-const calcValue = (min, max, value) => {
- if (value !== undefined) {
- return value;
- }
-
- return [min, max];
-};
-
export default class RangeSlider extends Component {
constructor(props) {
super(props);
diff --git a/components/dash-core-components/src/fragments/Slider.react.js b/components/dash-core-components/src/fragments/Slider.react.js
index 178014e395..587761adbb 100644
--- a/components/dash-core-components/src/fragments/Slider.react.js
+++ b/components/dash-core-components/src/fragments/Slider.react.js
@@ -1,10 +1,11 @@
import React, {Component} from 'react';
import ReactSlider, {createSliderWithTooltip} from 'rc-slider';
-import {assoc, omit, pickBy} from 'ramda';
+import {assoc, omit} from 'ramda';
import computeSliderStyle from '../utils/computeSliderStyle';
import 'rc-slider/assets/index.css';
+import {calcMarks} from '../utils/computeSliderMarkers';
import {propTypes, defaultProps} from '../components/Slider.react';
/**
@@ -47,6 +48,10 @@ export default class Slider extends Component {
setProps,
tooltip,
updatemode,
+ min,
+ max,
+ marks,
+ step,
vertical,
verticalHeight,
} = this.props;
@@ -65,13 +70,6 @@ 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 (
+ pickBy((k, mark) => mark >= min && mark <= max, marks);
+
+const truncateNumber = num =>
+ parseInt(num.toString().match(/^-?\d+(?:\.\d{0,0})?/)[0], 10);
+
+const decimalCount = d =>
+ String(d).split('.').length > 1 ? String(d).split('.')[1].length : 0;
+const alignIntValue = (v, d) =>
+ d < 10
+ ? v
+ : parseInt((truncateNumber(v / d) * d).toFixed(decimalCount(d)), 10);
+const alignDecimalValue = (v, d) =>
+ d < 10
+ ? parseFloat(v.toFixed(decimalCount(d)))
+ : parseFloat(((v / d).toFixed(0) * d).toFixed(decimalCount(d)));
+
+const alignValue = (v, d) =>
+ decimalCount(d) < 1 ? alignIntValue(v, d) : alignDecimalValue(v, d);
+
+const log = v => Math.floor(Math.log10(v));
+
+const getNearByStep = v =>
+ v < 10
+ ? [v]
+ : [
+ Math.pow(10, Math.floor(Math.log10(v))),
+ Math.pow(10, Math.ceil(Math.log10(v))) / 2,
+ alignValue(v, Math.pow(10, log(v))),
+ Math.pow(10, Math.ceil(Math.log10(v))),
+ ].sort((a, b) => Math.abs(a - v) - Math.abs(b - v));
+
+const estimateBestSteps = (minValue, maxValue, stepValue) => {
+ const desiredCountMin = 2 + (maxValue / stepValue <= 10 ? 3 : 3); // including start, end
+ const desiredCountMax = 2 + (maxValue / stepValue <= 10 ? 4 : 6);
+
+ const min = minValue / stepValue;
+ const max = maxValue / stepValue;
+
+ const rangeLength = max - min;
+
+ const leastMarksInterval = Math.max(
+ Math.round(rangeLength / (desiredCountMin - 1)),
+ 1
+ );
+ const possibleValues = getNearByStep(leastMarksInterval);
+
+ const finalStep =
+ possibleValues.find(step => {
+ const expectedSteps = Math.ceil(rangeLength / step) + 1;
+ return (
+ expectedSteps >= desiredCountMin - 1 &&
+ expectedSteps <= desiredCountMax + 1
+ );
+ }) || possibleValues[0];
+ return [
+ alignValue(min, finalStep) * stepValue,
+ alignValue(finalStep * stepValue, stepValue),
+ ];
+};
+
+export const autoGenerateMarks = (min, max, step = 1) => {
+ const marks = [];
+ const [start, interval] = estimateBestSteps(min, max, step);
+ let cursor = start + interval;
+
+ do {
+ marks.push(alignValue(cursor, step));
+ cursor += interval;
+ } while (cursor < max);
+
+ // do some cosmetic
+ const discardThreshold = 1.5;
+ if (
+ marks.length >= 2 &&
+ max - marks[marks.length - 2] <= interval * discardThreshold
+ ) {
+ marks.pop();
+ }
+
+ const marksObject = {};
+ marks.forEach(mark => {
+ marksObject[mark] = String(mark);
+ });
+ marksObject[min] = `Start (${min})`;
+ marksObject[max] = `End (${max})`;
+ return marksObject;
+};
+
+/**
+ * Set marks to min and max if not defined, truncate otherwise
+ */
+export const calcMarks = ({min, max, marks, step}) => {
+ return truncateMarks(
+ min,
+ max,
+ marks ? marks : autoGenerateMarks(min, max, step)
+ );
+};
+
+/**
+ * Calculate default step if not defined
+ */
+export const calcStep = (min, max, step) => {
+ if (step !== undefined) {
+ return step;
+ }
+
+ const size = Math.abs(max - min); // interval size
+ /**
+ * Size multiplied by 10^i to get a nice step value at the end (0.1, 1, 10, 100, ...)
+ */
+ const divident = size
+ .toString()
+ .replace('.', '') // removes decimal point
+ .replace(/^(\d*?[1-9])0+$/, '$1'); // removes trailing zeros
+
+ return size / divident;
+};
+
+/**
+ * Calculate default value if not defined
+ */
+export const calcValue = (min, max, value) => {
+ if (value !== undefined) {
+ return value;
+ }
+
+ return [min, max];
+};
From 74c25af528d01f73bef93c87b3eb23f71f32a363 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 11 Sep 2021 09:26:22 -0400
Subject: [PATCH 28/80] add number support for shorthanded options - Checklist,
Dropdown
---
.../src/components/Checklist.react.js | 14 +++++++-------
.../src/components/Dropdown.react.js | 4 ++--
.../src/fragments/Dropdown.react.js | 8 ++++----
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 8464531623..8b111f0961 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -35,13 +35,13 @@ export default class Checklist extends Component {
>
{options.map(option => {
option =
- type(option) === 'String'
- ? {
- label: option,
+ type(option) === 'Object'
+ ? option
+ : {
+ label: String(option),
value: option,
disabled: false,
- }
- : option;
+ };
return (
- type(opt) === 'String'
- ? {
- label: opt,
+ type(opt) === 'Object'
+ ? opt
+ : {
+ label: String(opt),
value: opt,
}
- : opt
);
this.setState({
filterOptions: createFilterOptions({
From 4a106943129e0f90ccaaa521337d7f7c86d67fbc Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 11 Sep 2021 10:12:41 -0400
Subject: [PATCH 29/80] some refactor to get react-docgen working, slider props
re-arrange
---
.../src/components/Checklist.react.js | 13 ++++----
.../src/components/Dropdown.react.js | 13 ++++----
.../src/components/RadioItems.react.js | 15 +++++-----
.../src/components/Slider.react.js | 30 +++++++++----------
4 files changed, 34 insertions(+), 37 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 8b111f0961..f01c62f436 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -86,6 +86,12 @@ Checklist.propTypes = {
*/
options: PropTypes.arrayOf(
PropTypes.oneOfType([
+ /**
+ * We now accept the single `value` as an option value,
+ * which equals to
+ * { label: `value`, value: `value`, disabled: false }
+ */
+ PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
PropTypes.exact({
/**
* The checkbox's label
@@ -106,13 +112,6 @@ Checklist.propTypes = {
*/
disabled: PropTypes.bool,
}),
-
- /**
- * We now accept the single `value` as an option value,
- * which equals to
- * { label: `value`, value: `value`, disabled: false }
- */
- PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
])
),
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index ea755f31a4..6d4858f6ce 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -31,6 +31,12 @@ Dropdown.propTypes = {
*/
options: PropTypes.arrayOf(
PropTypes.oneOfType([
+ /**
+ * We now accept the single `value` as an option value,
+ * which equals to
+ * { label: `value`, value: `value`, disabled: false }
+ */
+ PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
PropTypes.exact({
/**
* The dropdown's label
@@ -58,13 +64,6 @@ Dropdown.propTypes = {
*/
title: PropTypes.string,
}),
-
- /**
- * We now accept the single `value` as an option value,
- * which equals to
- * { label: `value`, value: `value`, disabled: false }
- */
- PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
])
),
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 559a839724..3186104452 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -78,6 +78,13 @@ RadioItems.propTypes = {
* An array of options, or inline dictionary of options
*/
options: PropTypes.oneOfType([
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`label1`: `value1`, `label2`: `value2`, ... }
+ * which equals to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.object,
PropTypes.arrayOf(
PropTypes.exact({
/**
@@ -100,14 +107,6 @@ RadioItems.propTypes = {
disabled: PropTypes.bool,
})
),
-
- /**
- * Simpler `options` representation in dictionary format
- * {`label1`: `value1`, `label2`: `value2`, ... }
- * which equals to
- * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
- */
- PropTypes.object,
]),
/**
diff --git a/components/dash-core-components/src/components/Slider.react.js b/components/dash-core-components/src/components/Slider.react.js
index 116180dd6d..566e3e8b9f 100644
--- a/components/dash-core-components/src/components/Slider.react.js
+++ b/components/dash-core-components/src/components/Slider.react.js
@@ -18,6 +18,21 @@ export default class Slider extends Component {
}
Slider.propTypes = {
+ /**
+ * Minimum allowed value of the slider
+ */
+ min: PropTypes.number,
+
+ /**
+ * Maximum allowed value of the slider
+ */
+ max: PropTypes.number,
+
+ /**
+ * Value by which increments or decrements are made
+ */
+ step: PropTypes.number,
+
/**
* The ID of this component, used to identify dash components
* in callbacks. The ID needs to be unique across all of the
@@ -76,16 +91,6 @@ Slider.propTypes = {
*/
included: PropTypes.bool,
- /**
- * Minimum allowed value of the slider
- */
- min: PropTypes.number,
-
- /**
- * Maximum allowed value of the slider
- */
- max: PropTypes.number,
-
/**
* Configuration for tooltips describing the current slider value
*/
@@ -114,11 +119,6 @@ Slider.propTypes = {
]),
}),
- /**
- * Value by which increments or decrements are made
- */
- step: PropTypes.number,
-
/**
* If true, the slider will be vertical
*/
From 5ab661846664b3375960fa6f065e4cc6c5619dd3 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 11 Sep 2021 11:02:31 -0400
Subject: [PATCH 30/80] fix unit test - remove outdated part
---
.../tests/integration/misc/test_persistence.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/components/dash-core-components/tests/integration/misc/test_persistence.py b/components/dash-core-components/tests/integration/misc/test_persistence.py
index 8435a6a6b8..401b24d0c4 100644
--- a/components/dash-core-components/tests/integration/misc/test_persistence.py
+++ b/components/dash-core-components/tests/integration/misc/test_persistence.py
@@ -141,12 +141,12 @@ 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.25) # 5
- dash_dcc.click_at_coord_fractions(range_slider, 0.8, 0.25) # 8
+ # range_slider = dash_dcc.find_element("#rangeslider")
+ # 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.25) # 22
+ # slider = dash_dcc.find_element("#slider")
+ # dash_dcc.click_at_coord_fractions(slider, 0.2, 0.25) # 22
dash_dcc.find_element("#tabs .tab:last-child").click() # C
@@ -161,8 +161,8 @@ def make_output(*args):
[u"4️⃣", u"6️⃣"],
"yes maybe",
"r",
- [5, 8],
- 22,
+ [3, 7],
+ 25,
"C",
"knock knock\nwho's there?",
]
From d90461ed88db357d49e84097f2fab0ba11cb2585 Mon Sep 17 00:00:00 2001
From: workaholicpanda <802931+workaholicpanda@users.noreply.github.com>
Date: Sat, 11 Sep 2021 18:01:11 -0400
Subject: [PATCH 31/80] update props comment
Co-authored-by: Chris Parmer
---
.../dash-core-components/src/components/Dropdown.react.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 6d4858f6ce..3e7f9e667e 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -33,7 +33,7 @@ Dropdown.propTypes = {
PropTypes.oneOfType([
/**
* We now accept the single `value` as an option value,
- * which equals to
+ * which is equal to
* { label: `value`, value: `value`, disabled: false }
*/
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
From 63ced025e25d84e6049ba8cf7c8eff8c1e28e297 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 11 Sep 2021 19:03:02 -0400
Subject: [PATCH 32/80] fix feedback comments
---
.../src/components/Checklist.react.js | 44 +----------
.../src/components/Dropdown.react.js | 39 +---------
.../src/components/RadioItems.react.js | 41 +---------
.../src/fragments/Dropdown.react.js | 15 +---
.../src/fragments/RangeSlider.react.js | 11 +--
.../src/utils/optionTypes.js | 75 +++++++++++++++++++
dash/development/base_component.py | 9 +--
7 files changed, 94 insertions(+), 140 deletions(-)
create mode 100644 components/dash-core-components/src/utils/optionTypes.js
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index f01c62f436..8b40c98f20 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
-import {append, includes, type, without} from 'ramda';
+import {append, includes, without} from 'ramda';
import React, {Component} from 'react';
+import {optionsType, normalizedOptions} from '../utils/optionTypes';
/**
* Checklist is a component that encapsulates several checkboxes.
@@ -33,15 +34,7 @@ export default class Checklist extends Component {
style={style}
className={className}
>
- {options.map(option => {
- option =
- type(option) === 'Object'
- ? option
- : {
- label: String(option),
- value: option,
- disabled: false,
- };
+ {normalizedOptions(options).map(option => {
return (
({
- label,
- value,
- }));
return (
- {sanitizedOptions.map(option => (
+ {sanitizeOptions(options).map(option => (
- type(opt) === 'Object'
- ? opt
- : {
- label: String(opt),
- value: opt,
- }
- );
this.setState({
filterOptions: createFilterOptions({
- options: normalizedOptions,
+ options: sanitizeOptions(newProps.options),
tokenizer: TOKENIZER,
}),
});
@@ -66,7 +59,7 @@ export default class Dropdown extends Component {
const {filterOptions} = this.state;
let selectedValue;
if (type(value) === 'Array') {
- selectedValue = value.join(DELIMETER);
+ selectedValue = value.join(DELIMITER);
} else {
selectedValue = value;
}
diff --git a/components/dash-core-components/src/fragments/RangeSlider.react.js b/components/dash-core-components/src/fragments/RangeSlider.react.js
index e26ff4fb45..9695184dcc 100644
--- a/components/dash-core-components/src/fragments/RangeSlider.react.js
+++ b/components/dash-core-components/src/fragments/RangeSlider.react.js
@@ -14,12 +14,7 @@ export default class RangeSlider extends Component {
? createSliderWithTooltip(Range)
: Range;
this._computeStyle = computeSliderStyle();
-
- const {min, max, value, setProps} = props;
- this.state = {value};
- if (!value) {
- setProps({value: calcValue(min, max, value)});
- }
+ this.state = {value: props.value};
}
UNSAFE_componentWillReceiveProps(newProps) {
@@ -103,8 +98,8 @@ export default class RangeSlider extends Component {
getTooltipContainer: node => node,
}}
style={{position: 'relative'}}
- value={calcValue(min, max, value)}
- marks={calcMarks({min, max, marks, step})}
+ value={value ? value : calcValue(min, max, value)}
+ marks={marks ? marks : calcMarks({min, max, marks, step})}
step={calcStep(min, max, step)}
{...omit(
[
diff --git a/components/dash-core-components/src/utils/optionTypes.js b/components/dash-core-components/src/utils/optionTypes.js
new file mode 100644
index 0000000000..eda976840b
--- /dev/null
+++ b/components/dash-core-components/src/utils/optionTypes.js
@@ -0,0 +1,75 @@
+import PropTypes from 'prop-types';
+import {type} from 'ramda';
+
+/**
+ * An array of options {label: [string|number], value: [string|number]},
+ * an optional disabled field can be used for each option
+ */
+const defaultOptionType = PropTypes.arrayOf(
+ PropTypes.exact({
+ /**
+ * The option's label
+ */
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * The value of the option. This value
+ * corresponds to the items specified in the
+ * `value` property.
+ */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * If true, this option is disabled and cannot be selected.
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * The HTML 'title' attribute for the option. Allows for
+ * information on hover. For more information on this attribute,
+ * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title
+ */
+ title: PropTypes.string,
+ })
+);
+
+/**
+ * Array of options as string[]
+ */
+const optionArrayShorthandType = PropTypes.arrayOf(
+ PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
+);
+
+/**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+const optionObjectShorthandType = PropTypes.objectOf(
+ PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
+);
+
+export const optionsType = PropTypes.oneOfType([
+ defaultOptionType,
+ optionArrayShorthandType,
+ optionObjectShorthandType,
+]);
+
+export const sanitizeOptions = options => {
+ if (type(options) === 'Array') {
+ if (options.length > 0 && type(options[0]) === 'String') {
+ return options.map(option => ({
+ label: String(option),
+ value: option,
+ }));
+ }
+ return options;
+ }
+ return Object.entries(options).map(([value, label]) => ({
+ label,
+ value,
+ }));
+};
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index 5ccfb8677e..3ed0e2fe1e 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -168,12 +168,9 @@ def __init__(self, **kwargs):
def set_random_id(self):
if not hasattr(self, "id"):
- rd = random.Random()
- hexdigest = hashlib.md5(
- bytes(str(self.to_plotly_json()), "utf8")
- ).hexdigest()
- rd.seed(int(hexdigest, 16))
- v = str(uuid.UUID(int=rd.getrandbits(64)))
+ rd = random.Random(0)
+ rd.seed(0)
+ v = str(uuid.UUID(int=rd.randint(0, 2 ** 128)))
setattr(self, "id", v)
return getattr(self, "id")
From f990b43c5e1de13649373cec1d0b48275a70bd57 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sun, 12 Sep 2021 10:35:34 -0400
Subject: [PATCH 33/80] fix some issues in Checklist, DataTable props
---
.../src/components/Checklist.react.js | 4 ++--
.../dash-core-components/src/utils/optionTypes.js | 5 ++++-
components/dash-table/src/dash-table/dash/DataTable.js | 10 +++++++++-
3 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 8b40c98f20..20ef4984a6 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import {append, includes, without} from 'ramda';
import React, {Component} from 'react';
-import {optionsType, normalizedOptions} from '../utils/optionTypes';
+import {optionsType, sanitizeOptions} from '../utils/optionTypes';
/**
* Checklist is a component that encapsulates several checkboxes.
@@ -34,7 +34,7 @@ export default class Checklist extends Component {
style={style}
className={className}
>
- {normalizedOptions(options).map(option => {
+ {sanitizeOptions(options).map(option => {
return (
{
if (type(options) === 'Array') {
- if (options.length > 0 && type(options[0]) === 'String') {
+ if (
+ options.length > 0 &&
+ ['String', 'Number', 'Bool'].includes(type(options[0]))
+ ) {
return options.map(option => ({
label: String(option),
value: option,
diff --git a/components/dash-table/src/dash-table/dash/DataTable.js b/components/dash-table/src/dash-table/dash/DataTable.js
index 86b9e75de7..61cc68656e 100644
--- a/components/dash-table/src/dash-table/dash/DataTable.js
+++ b/components/dash-table/src/dash-table/dash/DataTable.js
@@ -121,7 +121,15 @@ export const propTypes = {
* {'column-1': 8, 'column-2': 'boston', 'column-3': 'america'}
* ]
*/
- data: PropTypes.arrayOf(PropTypes.object),
+ data: PropTypes.arrayOf(
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool
+ ])
+ )
+ ),
/**
* Columns describes various aspects about each individual column.
From f3e78938eee395eaf764f230932f604f815a719f Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sun, 12 Sep 2021 10:43:39 -0400
Subject: [PATCH 34/80] pylint fix
---
dash/development/base_component.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index 3ed0e2fe1e..2d2df1d26c 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -3,7 +3,6 @@
import sys
import uuid
import random
-import hashlib
from .._utils import patch_collections_abc, stringify_id
From 67d0836ed74960ebff9658e998f385f853355c43 Mon Sep 17 00:00:00 2001
From: workaholicpanda <802931+workaholicpanda@users.noreply.github.com>
Date: Sun, 12 Sep 2021 20:33:30 -0400
Subject: [PATCH 35/80] Apply suggestions from code review
Co-authored-by: Chris Parmer
---
.../dash-core-components/src/components/RadioItems.react.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 4b625b9f9e..e839ced184 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -45,7 +45,7 @@ export default class RadioItems extends Component {
style={Object.assign(
{},
labelStyle,
- inline ? {display: 'inline'} : {}
+ inline ? {display: 'inline-block'} : {}
)}
className={labelClassName}
key={option.value}
@@ -172,8 +172,8 @@ RadioItems.propTypes = {
/**
* Indicates whether labelStyle should be inline or not
- * True: Automatically set { 'display': 'inline' } to labelStyle
- * False: No additional behavior to expect
+ * True: Automatically set { 'display': 'inline-block' } to labelStyle
+ * False: No additional styles are passed into labelStyle.
*/
inline: PropTypes.bool,
};
From 6188289dd6ad1229dc23febf623c6e2aa57f552b Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 13 Sep 2021 09:39:39 -0400
Subject: [PATCH 36/80] copy paste ProTypes to get doc-gen working
---
.../src/components/Checklist.react.js | 61 ++++++++++++++++++-
.../src/components/Dropdown.react.js | 60 +++++++++++++++++-
.../src/components/RadioItems.react.js | 61 ++++++++++++++++++-
.../src/utils/optionTypes.js | 58 ------------------
4 files changed, 176 insertions(+), 64 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 20ef4984a6..5a7320fe5f 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import {append, includes, without} from 'ramda';
import React, {Component} from 'react';
-import {optionsType, sanitizeOptions} from '../utils/optionTypes';
+import {sanitizeOptions} from '../utils/optionTypes';
/**
* Checklist is a component that encapsulates several checkboxes.
@@ -77,7 +77,64 @@ Checklist.propTypes = {
/**
* An array of options
*/
- options: optionsType,
+ options: PropTypes.oneOfType([
+ /**
+ * An array of options {label: [string|number], value: [string|number]},
+ * an optional disabled field can be used for each option
+ */
+ PropTypes.arrayOf(
+ PropTypes.exact({
+ /**
+ * The option's label
+ */
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * The value of the option. This value
+ * corresponds to the items specified in the
+ * `value` property.
+ */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * If true, this option is disabled and cannot be selected.
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * The HTML 'title' attribute for the option. Allows for
+ * information on hover. For more information on this attribute,
+ * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title
+ */
+ title: PropTypes.string,
+ })
+ ),
+ /**
+ * Array of options - [string|number|bool]
+ */
+ PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ ]),
/**
* The currently selected value
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index c94f843f02..d7577058b7 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -1,7 +1,6 @@
import PropTypes from 'prop-types';
import React, {Component, lazy, Suspense} from 'react';
import dropdown from '../utils/LazyLoader/dropdown';
-import {optionsType} from '../utils/optionTypes';
const RealDropdown = lazy(dropdown);
@@ -30,7 +29,64 @@ Dropdown.propTypes = {
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
*/
- options: optionsType,
+ options: PropTypes.oneOfType([
+ /**
+ * An array of options {label: [string|number], value: [string|number]},
+ * an optional disabled field can be used for each option
+ */
+ PropTypes.arrayOf(
+ PropTypes.exact({
+ /**
+ * The option's label
+ */
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * The value of the option. This value
+ * corresponds to the items specified in the
+ * `value` property.
+ */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * If true, this option is disabled and cannot be selected.
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * The HTML 'title' attribute for the option. Allows for
+ * information on hover. For more information on this attribute,
+ * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title
+ */
+ title: PropTypes.string,
+ })
+ ),
+ /**
+ * Array of options - [string|number|bool]
+ */
+ PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ ]),
/**
* The value of the input. If `multi` is false (the default)
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 4b625b9f9e..44292e05f2 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import './css/react-select@1.0.0-rc.3.min.css';
-import {optionsType, sanitizeOptions} from '../utils/optionTypes';
+import {sanitizeOptions} from '../utils/optionTypes';
/**
* RadioItems is a component that encapsulates several radio item inputs.
@@ -72,7 +72,64 @@ RadioItems.propTypes = {
/**
* An array of options, or inline dictionary of options
*/
- options: optionsType,
+ options: PropTypes.oneOfType([
+ /**
+ * An array of options {label: [string|number], value: [string|number]},
+ * an optional disabled field can be used for each option
+ */
+ PropTypes.arrayOf(
+ PropTypes.exact({
+ /**
+ * The option's label
+ */
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * The value of the option. This value
+ * corresponds to the items specified in the
+ * `value` property.
+ */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ .isRequired,
+
+ /**
+ * If true, this option is disabled and cannot be selected.
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * The HTML 'title' attribute for the option. Allows for
+ * information on hover. For more information on this attribute,
+ * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title
+ */
+ title: PropTypes.string,
+ })
+ ),
+ /**
+ * Array of options - [string|number|bool]
+ */
+ PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ ]),
/**
* The ID of this component, used to identify dash components
diff --git a/components/dash-core-components/src/utils/optionTypes.js b/components/dash-core-components/src/utils/optionTypes.js
index d232404bdc..c30b70cb0f 100644
--- a/components/dash-core-components/src/utils/optionTypes.js
+++ b/components/dash-core-components/src/utils/optionTypes.js
@@ -1,63 +1,5 @@
-import PropTypes from 'prop-types';
import {type} from 'ramda';
-/**
- * An array of options {label: [string|number], value: [string|number]},
- * an optional disabled field can be used for each option
- */
-const defaultOptionType = PropTypes.arrayOf(
- PropTypes.exact({
- /**
- * The option's label
- */
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
- .isRequired,
-
- /**
- * The value of the option. This value
- * corresponds to the items specified in the
- * `value` property.
- */
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
- .isRequired,
-
- /**
- * If true, this option is disabled and cannot be selected.
- */
- disabled: PropTypes.bool,
-
- /**
- * The HTML 'title' attribute for the option. Allows for
- * information on hover. For more information on this attribute,
- * see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title
- */
- title: PropTypes.string,
- })
-);
-
-/**
- * Array of options as string[]
- */
-const optionArrayShorthandType = PropTypes.arrayOf(
- PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
-);
-
-/**
- * Simpler `options` representation in dictionary format
- * {`value1`: `label1`, `value2`: `label2`, ... }
- * which is equal to
- * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
- */
-const optionObjectShorthandType = PropTypes.objectOf(
- PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
-);
-
-export const optionsType = PropTypes.oneOfType([
- defaultOptionType,
- optionArrayShorthandType,
- optionObjectShorthandType,
-]);
-
export const sanitizeOptions = options => {
if (type(options) === 'Array') {
if (
From 1d4479d4329ea49a853779c935e9d6ba6aaf7708 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Mon, 13 Sep 2021 20:16:59 +0200
Subject: [PATCH 37/80] Test Slider and RangeSlider shorthand properties
---
.../integration/sliders/test_shorthands.py | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 components/dash-core-components/tests/integration/sliders/test_shorthands.py
diff --git a/components/dash-core-components/tests/integration/sliders/test_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
new file mode 100644
index 0000000000..afbbc388f3
--- /dev/null
+++ b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
@@ -0,0 +1,42 @@
+from multiprocessing import Lock
+from dash import Dash, Input, Output, dcc, html
+import numpy as np
+
+def test_slsh001_rangeslider_shorthand_props(dash_dcc):
+ NUMBERS = [10*N for N in np.arange(0, 2, 0.5)]
+ TEST_RANGES = []
+ LAYOUT = []
+ TEST_CASES = []
+
+ for n in NUMBERS:
+ TEST_CASES.extend([
+ [n, n * 1.5],
+ [n * 0.9, n * 1.3],
+ [n * -1, n + 0.1],
+ [n * -1.5, n + 0.1],
+ [-1 * n, 0.3 * n + 0.1],
+ [0, n + 0.1],
+ [0, n * 0.43]
+ ])
+
+ for t in TEST_CASES:
+ LAYOUT.extend([
+ html.Div(f'{t[0]} - {t[1]}'),
+ dcc.Slider(t[0], t[1]),
+
+ html.Div(f'{t[0]} - {t[1]}, {abs(t[1] - t[0]) / 5}'),
+ dcc.Slider(t[0], t[1], abs(t[1] - t[0]) / 5),
+
+ html.Div(f'{t[0]} - {t[1]}'),
+ dcc.RangeSlider(t[0], t[1]),
+
+ html.Div(f'{t[0]} - {t[1]}, {abs(t[1] - t[0]) / 5}'),
+ dcc.RangeSlider(t[0], t[1], abs(t[1] - t[0]) / 5),
+ ])
+
+ app = Dash(__name__)
+ app.layout = html.Div(LAYOUT)
+
+ dash_dcc.start_server(app)
+ dash_dcc.wait_for_element(".rc-slider")
+ dash_dcc.percy_snapshot("slsh001 - test_slsh001_rangeslider_shorthand_props", True)
From 1add4e28545a19f32ea109a63141be47b3c588c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Mon, 13 Sep 2021 20:35:35 +0200
Subject: [PATCH 38/80] Test Dropdown shorthand properties
---
.../integration/dropdown/test_shorthands.py | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 components/dash-core-components/tests/integration/dropdown/test_shorthands.py
diff --git a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
new file mode 100644
index 0000000000..527fab933c
--- /dev/null
+++ b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
@@ -0,0 +1,22 @@
+from dash import Dash, dcc
+from dash.dcc import Dropdown
+from dash.html import Div
+
+def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
+ app = Dash(__name__)
+ app.layout = Div(
+ [
+ dcc.Dropdown(['a', 'b', 'c']),
+ dcc.Dropdown(['a', 'b', 'c'], 'b'),
+ dcc.Dropdown(['a', 3, 'c']),
+ dcc.Dropdown(['a', 3, 'c'], 3),
+ dcc.Dropdown(['a', 3, 'c', True, False]),
+ dcc.Dropdown(['a', 3, 'c', True, False], False),
+ ]
+ )
+
+ dash_dcc.start_server(app)
+
+ dash_dcc.wait_for_element(".dash-dropdown")
+
+ dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
From becdba9decedf347f6877bb4186c5be83f30f3d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Mon, 13 Sep 2021 20:58:01 +0200
Subject: [PATCH 39/80] Remove unnecessary imports
---
.../tests/integration/dropdown/test_shorthands.py | 8 ++------
.../tests/integration/sliders/test_shorthands.py | 3 +--
2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
index 527fab933c..45155d5c43 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
@@ -1,10 +1,8 @@
-from dash import Dash, dcc
-from dash.dcc import Dropdown
-from dash.html import Div
+from dash import Dash, dcc, html
def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
app = Dash(__name__)
- app.layout = Div(
+ app.layout = html.Div(
[
dcc.Dropdown(['a', 'b', 'c']),
dcc.Dropdown(['a', 'b', 'c'], 'b'),
@@ -16,7 +14,5 @@ def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
)
dash_dcc.start_server(app)
-
dash_dcc.wait_for_element(".dash-dropdown")
-
dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
diff --git a/components/dash-core-components/tests/integration/sliders/test_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
index afbbc388f3..46c1e0fca2 100644
--- a/components/dash-core-components/tests/integration/sliders/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
@@ -1,5 +1,4 @@
-from multiprocessing import Lock
-from dash import Dash, Input, Output, dcc, html
+from dash import Dash, dcc, html
import numpy as np
def test_slsh001_rangeslider_shorthand_props(dash_dcc):
From 9fe2f78f2a4477fa004576bae0ca7914f0b57ca7 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 13 Sep 2021 22:57:51 +0300
Subject: [PATCH 40/80] random seed moved out to global scope, the test for
set_random_id was implemented
---
dash/development/base_component.py | 4 +--
tests/unit/development/test_base_component.py | 34 ++++++++++++++++++-
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/dash/development/base_component.py b/dash/development/base_component.py
index 2d2df1d26c..4cde39805f 100644
--- a/dash/development/base_component.py
+++ b/dash/development/base_component.py
@@ -8,6 +8,8 @@
MutableSequence = patch_collections_abc("MutableSequence")
+rd = random.Random(0)
+
# pylint: disable=no-init,too-few-public-methods
class ComponentRegistry:
@@ -167,8 +169,6 @@ def __init__(self, **kwargs):
def set_random_id(self):
if not hasattr(self, "id"):
- rd = random.Random(0)
- rd.seed(0)
v = str(uuid.UUID(int=rd.randint(0, 2 ** 128)))
setattr(self, "id", v)
return getattr(self, "id")
diff --git a/tests/unit/development/test_base_component.py b/tests/unit/development/test_base_component.py
index 7b1ed62f9a..5c46c99a1d 100644
--- a/tests/unit/development/test_base_component.py
+++ b/tests/unit/development/test_base_component.py
@@ -3,9 +3,10 @@
import plotly
import pytest
-from dash import __version__
+from dash import __version__, Dash
from dash import html
from dash.development.base_component import Component
+from dash import dcc, Input, Output
Component._prop_names = ("id", "a", "children", "style")
Component._type = "TestComponent"
@@ -473,3 +474,34 @@ def test_debc027_component_error_message():
+ "keyword argument: `asdf`\n"
+ "Allowed arguments: {}".format(", ".join(sorted(html.Div()._prop_names)))
)
+
+
+def test_set_random_id():
+ app = Dash(__name__)
+
+ input1 = dcc.Input(value="Hello")
+ input2 = dcc.Input(value="Hello")
+ output1 = html.Div()
+ output2 = html.Div()
+ output3 = html.Div(id="output-3")
+
+ app.layout = html.Div([input1, input2, output1, output2, output3])
+
+ @app.callback(Output(output1, "children"), Input(input1, "value"))
+ def update(v):
+ return f"Input 1 {v}"
+
+ @app.callback(Output(output2, "children"), Input(input2, "value"))
+ def update(v):
+ return f"Input 2 {v}"
+
+ @app.callback(
+ Output("output-3", "children"), Input(input1, "value"), Input(input2, "value")
+ )
+ def update(v1, v2):
+ return f"Output 3 - Input 1: {v1}, Input 2: {v2}"
+
+ # Verify the auto-generated IDs are stable
+ assert output1.id, "e3e70682-c209-4cac-629f-6fbed82c07cd"
+ assert output2.id, "82e2e662-f728-b4fa-4248-5e3a0a5d2f34"
+ assert output3.id, "d4713d60-c8a7-0639-eb11-67b367a9c378"
From 20d79c1d42fd6f1bb22c1c39cb97e47c55d564b4 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 13 Sep 2021 16:59:09 -0400
Subject: [PATCH 41/80] fix slider markers - respect steps given
---
.../dash-core-components/src/utils/computeSliderMarkers.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 3820e722a8..c7ca6ab396 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -64,9 +64,11 @@ const estimateBestSteps = (minValue, maxValue, stepValue) => {
];
};
-export const autoGenerateMarks = (min, max, step = 1) => {
+export const autoGenerateMarks = (min, max, step) => {
const marks = [];
- const [start, interval] = estimateBestSteps(min, max, step);
+ const [start, interval] = step
+ ? [min, step]
+ : estimateBestSteps(min, max, 1);
let cursor = start + interval;
do {
From f8bdf2683c262e7f05eedd6f06a736f7b1d28194 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 00:19:02 +0300
Subject: [PATCH 42/80] assert comparision is fixed
---
tests/unit/development/test_base_component.py | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/tests/unit/development/test_base_component.py b/tests/unit/development/test_base_component.py
index 5c46c99a1d..4a3a8fd446 100644
--- a/tests/unit/development/test_base_component.py
+++ b/tests/unit/development/test_base_component.py
@@ -502,6 +502,9 @@ def update(v1, v2):
return f"Output 3 - Input 1: {v1}, Input 2: {v2}"
# Verify the auto-generated IDs are stable
- assert output1.id, "e3e70682-c209-4cac-629f-6fbed82c07cd"
- assert output2.id, "82e2e662-f728-b4fa-4248-5e3a0a5d2f34"
- assert output3.id, "d4713d60-c8a7-0639-eb11-67b367a9c378"
+ assert output1.id == "e3e70682-c209-4cac-629f-6fbed82c07cd"
+ assert input1.id == "82e2e662-f728-b4fa-4248-5e3a0a5d2f34"
+ assert output2.id == "d4713d60-c8a7-0639-eb11-67b367a9c378"
+ assert input2.id == "23a7711a-8133-2876-37eb-dcd9e87a1613"
+ # we make sure that the if the id is set explicitly, then it is not replaced by random id
+ assert output3.id == "output-3"
From f052bbd3e9b3de6065b0cc340a597759faf99e4f Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Mon, 13 Sep 2021 22:27:41 -0400
Subject: [PATCH 43/80] fix slider issues
---
.../src/fragments/RangeSlider.react.js | 8 +++-
.../src/fragments/Slider.react.js | 4 +-
.../src/utils/computeSliderMarkers.js | 37 +++++++++++--------
3 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/components/dash-core-components/src/fragments/RangeSlider.react.js b/components/dash-core-components/src/fragments/RangeSlider.react.js
index 9695184dcc..facd97d6e4 100644
--- a/components/dash-core-components/src/fragments/RangeSlider.react.js
+++ b/components/dash-core-components/src/fragments/RangeSlider.react.js
@@ -4,7 +4,11 @@ import {Range, createSliderWithTooltip} from 'rc-slider';
import computeSliderStyle from '../utils/computeSliderStyle';
import 'rc-slider/assets/index.css';
-import {calcValue, calcMarks, calcStep} from '../utils/computeSliderMarkers';
+import {
+ calcValue,
+ sanitizeMarks,
+ calcStep,
+} from '../utils/computeSliderMarkers';
import {propTypes, defaultProps} from '../components/RangeSlider.react';
export default class RangeSlider extends Component {
@@ -99,7 +103,7 @@ export default class RangeSlider extends Component {
}}
style={{position: 'relative'}}
value={value ? value : calcValue(min, max, value)}
- marks={marks ? marks : calcMarks({min, max, marks, step})}
+ marks={sanitizeMarks({min, max, marks, step})}
step={calcStep(min, max, step)}
{...omit(
[
diff --git a/components/dash-core-components/src/fragments/Slider.react.js b/components/dash-core-components/src/fragments/Slider.react.js
index 587761adbb..8161ddf007 100644
--- a/components/dash-core-components/src/fragments/Slider.react.js
+++ b/components/dash-core-components/src/fragments/Slider.react.js
@@ -5,7 +5,7 @@ import computeSliderStyle from '../utils/computeSliderStyle';
import 'rc-slider/assets/index.css';
-import {calcMarks} from '../utils/computeSliderMarkers';
+import {sanitizeMarks} from '../utils/computeSliderMarkers';
import {propTypes, defaultProps} from '../components/Slider.react';
/**
@@ -103,7 +103,7 @@ export default class Slider extends Component {
}}
style={{position: 'relative'}}
value={value}
- marks={calcMarks({min, max, marks, step})}
+ marks={sanitizeMarks({min, max, marks, step})}
{...omit(
[
'className',
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index c7ca6ab396..c9037d645b 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -61,28 +61,32 @@ const estimateBestSteps = (minValue, maxValue, stepValue) => {
return [
alignValue(min, finalStep) * stepValue,
alignValue(finalStep * stepValue, stepValue),
+ stepValue,
];
};
export const autoGenerateMarks = (min, max, step) => {
const marks = [];
- const [start, interval] = step
- ? [min, step]
+ const [start, interval, chosenStep] = step
+ ? [min, step, step]
: estimateBestSteps(min, max, 1);
let cursor = start + interval;
- do {
- marks.push(alignValue(cursor, step));
- cursor += interval;
- } while (cursor < max);
-
- // do some cosmetic
- const discardThreshold = 1.5;
- if (
- marks.length >= 2 &&
- max - marks[marks.length - 2] <= interval * discardThreshold
- ) {
- marks.pop();
+ // make sure we don't step into infinite loop
+ if ((max - cursor) / interval > 0) {
+ do {
+ marks.push(alignValue(cursor, chosenStep));
+ cursor += interval;
+ } while (cursor < max);
+
+ // do some cosmetic
+ const discardThreshold = 1.5;
+ if (
+ marks.length >= 2 &&
+ max - marks[marks.length - 2] <= interval * discardThreshold
+ ) {
+ marks.pop();
+ }
}
const marksObject = {};
@@ -95,9 +99,10 @@ export const autoGenerateMarks = (min, max, step) => {
};
/**
- * Set marks to min and max if not defined, truncate otherwise
+ * - Auto generate marks if not given,
+ * - Then truncate marks so no out of range marks
*/
-export const calcMarks = ({min, max, marks, step}) => {
+export const sanitizeMarks = ({min, max, marks, step}) => {
return truncateMarks(
min,
max,
From 83cea43dede2cdd21ba815cabae59d4dba15568f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Tue, 14 Sep 2021 09:34:32 +0200
Subject: [PATCH 44/80] Add dropdown option sanitization to some additional
required places
---
.../dash-core-components/src/fragments/Dropdown.react.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/components/dash-core-components/src/fragments/Dropdown.react.js b/components/dash-core-components/src/fragments/Dropdown.react.js
index 97463e1c72..43dd15e006 100644
--- a/components/dash-core-components/src/fragments/Dropdown.react.js
+++ b/components/dash-core-components/src/fragments/Dropdown.react.js
@@ -28,7 +28,7 @@ export default class Dropdown extends Component {
super(props);
this.state = {
filterOptions: createFilterOptions({
- options: props.options,
+ options: sanitizeOptions(props.options),
tokenizer: TOKENIZER,
}),
};
@@ -74,7 +74,7 @@ export default class Dropdown extends Component {
>
{
if (multi) {
@@ -99,7 +99,7 @@ export default class Dropdown extends Component {
backspaceRemoves={clearable}
deleteRemoves={clearable}
inputProps={{autoComplete: 'off'}}
- {...omit(['setProps', 'value'], this.props)}
+ {...omit(['setProps', 'value', 'options'], this.props)}
/>
);
From 2ba81c6b88b3429c2de1f7a812cf8a8c789a6a7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Tue, 14 Sep 2021 10:43:28 +0200
Subject: [PATCH 45/80] Convert labels to strings when an Ojbect is passed as
options
---
components/dash-core-components/src/utils/optionTypes.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/dash-core-components/src/utils/optionTypes.js b/components/dash-core-components/src/utils/optionTypes.js
index c30b70cb0f..42f9f7d530 100644
--- a/components/dash-core-components/src/utils/optionTypes.js
+++ b/components/dash-core-components/src/utils/optionTypes.js
@@ -14,7 +14,7 @@ export const sanitizeOptions = options => {
return options;
}
return Object.entries(options).map(([value, label]) => ({
- label,
+ label: String(label),
value,
}));
};
From 780bc3265ae667497eda2826961c5d2418ee3967 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Tue, 14 Sep 2021 10:54:35 +0200
Subject: [PATCH 46/80] Add more variants to Dropdown shorthand test
---
.../integration/dropdown/test_shorthands.py | 21 +++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
index 45155d5c43..c132b7461b 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
@@ -6,13 +6,30 @@ def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
[
dcc.Dropdown(['a', 'b', 'c']),
dcc.Dropdown(['a', 'b', 'c'], 'b'),
+
dcc.Dropdown(['a', 3, 'c']),
dcc.Dropdown(['a', 3, 'c'], 3),
+
+ dcc.Dropdown(['a', True, 'c']),
+ dcc.Dropdown(['a', True, 'c'], True),
+
dcc.Dropdown(['a', 3, 'c', True, False]),
dcc.Dropdown(['a', 3, 'c', True, False], False),
+
+ dcc.Dropdown({'one': 'One', 'two': 'Two', 'three': 'Three'}),
+ dcc.Dropdown({'one': 'One', 'two': 'Two', 'three': 'Three'}, 'two'),
+
+ dcc.Dropdown({'one': 1, 'two': 2, 'three': False}),
+ dcc.Dropdown({'one': 1, 'two': 2, 'three': False}, 'three'),
+
+ dcc.Dropdown({'one': 1, 'two': True, 'three': 3}),
+ dcc.Dropdown({'one': 1, 'two': True, 'three': 3}, 'two'),
+
+ dcc.Dropdown([{'label': 'one', 'value': 1}, {'label': 'two', 'value': True}, {'label': 'three', 'value': 3}]),
+ dcc.Dropdown([{'label': 'one', 'value': 1}, {'label': 'two', 'value': True}, {'label': 'three', 'value': 3}], True),
]
)
dash_dcc.start_server(app)
- dash_dcc.wait_for_element(".dash-dropdown")
- dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
+ dash_dcc.wait_for_element('.dash-dropdown')
+ dash_dcc.percy_snapshot('ddsh001 - test_ddsh001_dropdown_shorthand_properties')
From 4d4b07e7c771f7e9fe7ea7d15a67254fdba8462a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Tue, 14 Sep 2021 11:56:26 +0200
Subject: [PATCH 47/80] Extend Slider tests
---
.../integration/sliders/test_shorthands.py | 57 ++++++++++++-------
1 file changed, 38 insertions(+), 19 deletions(-)
diff --git a/components/dash-core-components/tests/integration/sliders/test_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
index 46c1e0fca2..effe44083d 100644
--- a/components/dash-core-components/tests/integration/sliders/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
@@ -1,36 +1,55 @@
from dash import Dash, dcc, html
import numpy as np
+import math
def test_slsh001_rangeslider_shorthand_props(dash_dcc):
- NUMBERS = [10*N for N in np.arange(0, 2, 0.5)]
+ NUMBERS = [10*N for N in np.arange(1, 2, 0.5)]
TEST_RANGES = []
LAYOUT = []
TEST_CASES = []
for n in NUMBERS:
TEST_CASES.extend([
- [n, n * 1.5],
- [n * 0.9, n * 1.3],
- [n * -1, n + 0.1],
- [n * -1.5, n + 0.1],
- [-1 * n, 0.3 * n + 0.1],
- [0, n + 0.1],
- [0, n * 0.43]
+ [n, n*1.5, abs(n*1.5-n) / 5],
+ [-n, 0, n/10],
+ [-n, n, n/10],
+ [-1.5 * n, -1 * n, n/7],
])
for t in TEST_CASES:
- LAYOUT.extend([
- html.Div(f'{t[0]} - {t[1]}'),
- dcc.Slider(t[0], t[1]),
-
- html.Div(f'{t[0]} - {t[1]}, {abs(t[1] - t[0]) / 5}'),
- dcc.Slider(t[0], t[1], abs(t[1] - t[0]) / 5),
+ min, max, steps = t
+ marks = {i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(math.ceil(min), math.floor(max))}
- html.Div(f'{t[0]} - {t[1]}'),
- dcc.RangeSlider(t[0], t[1]),
-
- html.Div(f'{t[0]} - {t[1]}, {abs(t[1] - t[0]) / 5}'),
- dcc.RangeSlider(t[0], t[1], abs(t[1] - t[0]) / 5),
+ LAYOUT.extend([
+ html.Div(f'{min} - {max}'),
+ dcc.Slider(min, max),
+ dcc.RangeSlider(min, max),
+
+ html.Div(f'{min} - {max}, {steps}'),
+ dcc.Slider(min, max, steps),
+ dcc.RangeSlider(min, max, steps),
+
+ html.Div(f'{min} - {max}, {steps}, value={min + steps}'),
+ dcc.Slider(min, max, steps, value=min + steps),
+ html.Div(f'{min} - {max}, {steps}, value=[{min + steps},{min + steps * 3}]'),
+ dcc.RangeSlider(min, max, steps, value=[min + steps, min + steps * 3]),
+
+ html.Div(f'{min} - {max}, {steps}, value={min + steps}, marks={marks}'),
+ dcc.Slider(
+ min,
+ max,
+ steps,
+ value=min + steps,
+ marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)},
+ ),
+ html.Div(f'{min} - {max}, {steps},value=[{min + steps},{min + steps * 3}], marks={marks}'),
+ dcc.RangeSlider(
+ min,
+ max,
+ steps,
+ value=[min + steps, min + steps * 3],
+ marks=marks,
+ ),
])
app = Dash(__name__)
From 21b3bc6fe31f52b1fb34d0f97251d5843620e8e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Tue, 14 Sep 2021 12:12:10 +0200
Subject: [PATCH 48/80] Add test for Dropdown array value type
---
.../dropdown/test_dynamic_options.py | 24 ++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py b/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py
index fd4d00560e..30a1a8af4e 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py
@@ -1,4 +1,4 @@
-from dash import Dash, Input, Output, dcc
+from dash import Dash, Input, Output, dcc, html
from dash.exceptions import PreventUpdate
@@ -51,3 +51,25 @@ def update_options(search_value):
assert options[0].text == "Montreal"
assert dash_dcc.get_logs() == []
+
+def test_dddo002_array_value(dash_dcc):
+ dropdown_options = [
+ {"label": "New York City", "value": "New,York,City"},
+ {"label": "Montreal", "value": "Montreal"},
+ {"label": "San Francisco", "value": "San,Francisco"},
+ ]
+
+ app = Dash(__name__)
+ arrayValue = ["San", "Francisco"]
+
+ dropdown = dcc.Dropdown(
+ options=dropdown_options,
+ value=arrayValue,
+ )
+ app.layout = html.Div([dropdown])
+
+ dash_dcc.start_server(app)
+
+ dash_dcc.wait_for_text_to_equal("#react-select-2--value-item", "San Francisco")
+
+ assert dash_dcc.get_logs() == []
From a440ec6ca10137c72419186b8b125adffe8419d1 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 08:02:38 -0400
Subject: [PATCH 49/80] fix: update inline description & style
---
.../dash-core-components/src/components/Checklist.react.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 5a7320fe5f..f33492670a 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -41,7 +41,7 @@ export default class Checklist extends Component {
style={Object.assign(
{},
labelStyle,
- inline ? {display: 'inline'} : {}
+ inline ? {display: 'inline-block'} : {}
)}
className={labelClassName}
>
@@ -236,8 +236,8 @@ Checklist.propTypes = {
/**
* Indicates whether labelStyle should be inline or not
- * True: Automatically set { 'display': 'inline' } to labelStyle
- * False: No additional behavior to expect
+ * True: Automatically set { 'display': 'inline-block' } to labelStyle
+ * False: No additional styles are passed into labelStyle.
*/
inline: PropTypes.bool,
};
From 851961913e1a9044d06b3f1a8fb74477611e9a71 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 08:04:24 -0400
Subject: [PATCH 50/80] chore: pass black format
---
.../dropdown/test_dynamic_options.py | 1 +
.../integration/dropdown/test_shorthands.py | 57 ++++++------
.../integration/sliders/test_shorthands.py | 90 +++++++++++--------
3 files changed, 84 insertions(+), 64 deletions(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py b/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py
index 30a1a8af4e..85d9985579 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_dynamic_options.py
@@ -52,6 +52,7 @@ def update_options(search_value):
assert dash_dcc.get_logs() == []
+
def test_dddo002_array_value(dash_dcc):
dropdown_options = [
{"label": "New York City", "value": "New,York,City"},
diff --git a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
index c132b7461b..ba5ac691e3 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_shorthands.py
@@ -1,35 +1,42 @@
from dash import Dash, dcc, html
+
def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
app = Dash(__name__)
app.layout = html.Div(
[
- dcc.Dropdown(['a', 'b', 'c']),
- dcc.Dropdown(['a', 'b', 'c'], 'b'),
-
- dcc.Dropdown(['a', 3, 'c']),
- dcc.Dropdown(['a', 3, 'c'], 3),
-
- dcc.Dropdown(['a', True, 'c']),
- dcc.Dropdown(['a', True, 'c'], True),
-
- dcc.Dropdown(['a', 3, 'c', True, False]),
- dcc.Dropdown(['a', 3, 'c', True, False], False),
-
- dcc.Dropdown({'one': 'One', 'two': 'Two', 'three': 'Three'}),
- dcc.Dropdown({'one': 'One', 'two': 'Two', 'three': 'Three'}, 'two'),
-
- dcc.Dropdown({'one': 1, 'two': 2, 'three': False}),
- dcc.Dropdown({'one': 1, 'two': 2, 'three': False}, 'three'),
-
- dcc.Dropdown({'one': 1, 'two': True, 'three': 3}),
- dcc.Dropdown({'one': 1, 'two': True, 'three': 3}, 'two'),
-
- dcc.Dropdown([{'label': 'one', 'value': 1}, {'label': 'two', 'value': True}, {'label': 'three', 'value': 3}]),
- dcc.Dropdown([{'label': 'one', 'value': 1}, {'label': 'two', 'value': True}, {'label': 'three', 'value': 3}], True),
+ dcc.Dropdown(["a", "b", "c"]),
+ dcc.Dropdown(["a", "b", "c"], "b"),
+ dcc.Dropdown(["a", 3, "c"]),
+ dcc.Dropdown(["a", 3, "c"], 3),
+ dcc.Dropdown(["a", True, "c"]),
+ dcc.Dropdown(["a", True, "c"], True),
+ dcc.Dropdown(["a", 3, "c", True, False]),
+ dcc.Dropdown(["a", 3, "c", True, False], False),
+ dcc.Dropdown({"one": "One", "two": "Two", "three": "Three"}),
+ dcc.Dropdown({"one": "One", "two": "Two", "three": "Three"}, "two"),
+ dcc.Dropdown({"one": 1, "two": 2, "three": False}),
+ dcc.Dropdown({"one": 1, "two": 2, "three": False}, "three"),
+ dcc.Dropdown({"one": 1, "two": True, "three": 3}),
+ dcc.Dropdown({"one": 1, "two": True, "three": 3}, "two"),
+ dcc.Dropdown(
+ [
+ {"label": "one", "value": 1},
+ {"label": "two", "value": True},
+ {"label": "three", "value": 3},
+ ]
+ ),
+ dcc.Dropdown(
+ [
+ {"label": "one", "value": 1},
+ {"label": "two", "value": True},
+ {"label": "three", "value": 3},
+ ],
+ True,
+ ),
]
)
dash_dcc.start_server(app)
- dash_dcc.wait_for_element('.dash-dropdown')
- dash_dcc.percy_snapshot('ddsh001 - test_ddsh001_dropdown_shorthand_properties')
+ dash_dcc.wait_for_element(".dash-dropdown")
+ dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
diff --git a/components/dash-core-components/tests/integration/sliders/test_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
index effe44083d..73b8376063 100644
--- a/components/dash-core-components/tests/integration/sliders/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
@@ -2,55 +2,67 @@
import numpy as np
import math
+
def test_slsh001_rangeslider_shorthand_props(dash_dcc):
- NUMBERS = [10*N for N in np.arange(1, 2, 0.5)]
+ NUMBERS = [10 * N for N in np.arange(1, 2, 0.5)]
TEST_RANGES = []
LAYOUT = []
TEST_CASES = []
for n in NUMBERS:
- TEST_CASES.extend([
- [n, n*1.5, abs(n*1.5-n) / 5],
- [-n, 0, n/10],
- [-n, n, n/10],
- [-1.5 * n, -1 * n, n/7],
- ])
+ TEST_CASES.extend(
+ [
+ [n, n * 1.5, abs(n * 1.5 - n) / 5],
+ [-n, 0, n / 10],
+ [-n, n, n / 10],
+ [-1.5 * n, -1 * n, n / 7],
+ ]
+ )
for t in TEST_CASES:
min, max, steps = t
- marks = {i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(math.ceil(min), math.floor(max))}
-
- LAYOUT.extend([
- html.Div(f'{min} - {max}'),
- dcc.Slider(min, max),
- dcc.RangeSlider(min, max),
-
- html.Div(f'{min} - {max}, {steps}'),
- dcc.Slider(min, max, steps),
- dcc.RangeSlider(min, max, steps),
-
- html.Div(f'{min} - {max}, {steps}, value={min + steps}'),
- dcc.Slider(min, max, steps, value=min + steps),
- html.Div(f'{min} - {max}, {steps}, value=[{min + steps},{min + steps * 3}]'),
- dcc.RangeSlider(min, max, steps, value=[min + steps, min + steps * 3]),
+ marks = {
+ i: "Label {}".format(i) if i == 1 else str(i)
+ for i in range(math.ceil(min), math.floor(max))
+ }
- html.Div(f'{min} - {max}, {steps}, value={min + steps}, marks={marks}'),
- dcc.Slider(
- min,
- max,
- steps,
- value=min + steps,
- marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)},
- ),
- html.Div(f'{min} - {max}, {steps},value=[{min + steps},{min + steps * 3}], marks={marks}'),
- dcc.RangeSlider(
- min,
- max,
- steps,
- value=[min + steps, min + steps * 3],
- marks=marks,
- ),
- ])
+ LAYOUT.extend(
+ [
+ html.Div(f"{min} - {max}"),
+ dcc.Slider(min, max),
+ dcc.RangeSlider(min, max),
+ html.Div(f"{min} - {max}, {steps}"),
+ dcc.Slider(min, max, steps),
+ dcc.RangeSlider(min, max, steps),
+ html.Div(f"{min} - {max}, {steps}, value={min + steps}"),
+ dcc.Slider(min, max, steps, value=min + steps),
+ html.Div(
+ f"{min} - {max}, {steps}, value=[{min + steps},{min + steps * 3}]"
+ ),
+ dcc.RangeSlider(min, max, steps, value=[min + steps, min + steps * 3]),
+ html.Div(f"{min} - {max}, {steps}, value={min + steps}, marks={marks}"),
+ dcc.Slider(
+ min,
+ max,
+ steps,
+ value=min + steps,
+ marks={
+ i: "Label {}".format(i) if i == 1 else str(i)
+ for i in range(1, 6)
+ },
+ ),
+ html.Div(
+ f"{min} - {max}, {steps},value=[{min + steps},{min + steps * 3}], marks={marks}"
+ ),
+ dcc.RangeSlider(
+ min,
+ max,
+ steps,
+ value=[min + steps, min + steps * 3],
+ marks=marks,
+ ),
+ ]
+ )
app = Dash(__name__)
app.layout = html.Div(LAYOUT)
From 45cded7d5bff2983da826b82865d94903dae9aec Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 08:15:49 -0400
Subject: [PATCH 51/80] chore: react doc-gen fix & flake fix
---
.../src/components/Checklist.react.js | 46 +++++++++----------
.../src/components/Dropdown.react.js | 46 +++++++++----------
.../src/components/RadioItems.react.js | 46 +++++++++----------
.../integration/sliders/test_shorthands.py | 2 +-
4 files changed, 70 insertions(+), 70 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index f33492670a..c27fcc4fc4 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -78,6 +78,29 @@ Checklist.propTypes = {
* An array of options
*/
options: PropTypes.oneOfType([
+ /**
+ * Array of options - [string|number|bool]
+ */
+ PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
@@ -111,29 +134,6 @@ Checklist.propTypes = {
title: PropTypes.string,
})
),
- /**
- * Array of options - [string|number|bool]
- */
- PropTypes.arrayOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
- /**
- * Simpler `options` representation in dictionary format
- * {`value1`: `label1`, `value2`: `label2`, ... }
- * which is equal to
- * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
- */
- PropTypes.objectOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
]),
/**
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index d7577058b7..31afd56c98 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -30,6 +30,29 @@ Dropdown.propTypes = {
* an optional disabled field can be used for each option
*/
options: PropTypes.oneOfType([
+ /**
+ * Array of options - [string|number|bool]
+ */
+ PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
@@ -63,29 +86,6 @@ Dropdown.propTypes = {
title: PropTypes.string,
})
),
- /**
- * Array of options - [string|number|bool]
- */
- PropTypes.arrayOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
- /**
- * Simpler `options` representation in dictionary format
- * {`value1`: `label1`, `value2`: `label2`, ... }
- * which is equal to
- * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
- */
- PropTypes.objectOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
]),
/**
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 1fd4512df9..9bf873159d 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -73,6 +73,29 @@ RadioItems.propTypes = {
* An array of options, or inline dictionary of options
*/
options: PropTypes.oneOfType([
+ /**
+ * Array of options - [string|number|bool]
+ */
+ PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
+ /**
+ * Simpler `options` representation in dictionary format
+ * {`value1`: `label1`, `value2`: `label2`, ... }
+ * which is equal to
+ * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
+ */
+ PropTypes.objectOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
+ ),
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
@@ -106,29 +129,6 @@ RadioItems.propTypes = {
title: PropTypes.string,
})
),
- /**
- * Array of options - [string|number|bool]
- */
- PropTypes.arrayOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
- /**
- * Simpler `options` representation in dictionary format
- * {`value1`: `label1`, `value2`: `label2`, ... }
- * which is equal to
- * [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
- */
- PropTypes.objectOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
]),
/**
diff --git a/components/dash-core-components/tests/integration/sliders/test_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
index 73b8376063..e868f9fcad 100644
--- a/components/dash-core-components/tests/integration/sliders/test_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_shorthands.py
@@ -5,7 +5,7 @@
def test_slsh001_rangeslider_shorthand_props(dash_dcc):
NUMBERS = [10 * N for N in np.arange(1, 2, 0.5)]
- TEST_RANGES = []
+ # TEST_RANGES = []
LAYOUT = []
TEST_CASES = []
From c9224277076f064e7b49999443aacb069d7cbfb5 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 08:34:07 -0400
Subject: [PATCH 52/80] chore: rename test file names to avoid conflict
---
.../dropdown/{test_shorthands.py => test_dropdown_shorthands.py} | 0
.../sliders/{test_shorthands.py => test_sliders_shorthands.py} | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename components/dash-core-components/tests/integration/dropdown/{test_shorthands.py => test_dropdown_shorthands.py} (100%)
rename components/dash-core-components/tests/integration/sliders/{test_shorthands.py => test_sliders_shorthands.py} (100%)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
similarity index 100%
rename from components/dash-core-components/tests/integration/dropdown/test_shorthands.py
rename to components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
diff --git a/components/dash-core-components/tests/integration/sliders/test_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
similarity index 100%
rename from components/dash-core-components/tests/integration/sliders/test_shorthands.py
rename to components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
From 6727574ecd6edd0a6133cc45d074253d433ccf00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szabolcs=20Marko=CC=81?=
Date: Tue, 14 Sep 2021 15:29:25 +0200
Subject: [PATCH 53/80] Handle undefined options in Dropdown
---
.../dash-core-components/src/utils/optionTypes.js | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/components/dash-core-components/src/utils/optionTypes.js b/components/dash-core-components/src/utils/optionTypes.js
index 42f9f7d530..4af9208adc 100644
--- a/components/dash-core-components/src/utils/optionTypes.js
+++ b/components/dash-core-components/src/utils/optionTypes.js
@@ -1,6 +1,13 @@
import {type} from 'ramda';
export const sanitizeOptions = options => {
+ if (type(options) === 'Object') {
+ return Object.entries(options).map(([value, label]) => ({
+ label: String(label),
+ value,
+ }));
+ }
+
if (type(options) === 'Array') {
if (
options.length > 0 &&
@@ -13,8 +20,6 @@ export const sanitizeOptions = options => {
}
return options;
}
- return Object.entries(options).map(([value, label]) => ({
- label: String(label),
- value,
- }));
+
+ return options;
};
From 7d85f2b19fc22255352dfee4acbbb72c09904540 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 15 Sep 2021 00:22:57 +0300
Subject: [PATCH 54/80] fix: the case when truncated out input marks handled
---
.../src/utils/computeSliderMarkers.js | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index c9037d645b..0468eee112 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -103,11 +103,14 @@ export const autoGenerateMarks = (min, max, step) => {
* - Then truncate marks so no out of range marks
*/
export const sanitizeMarks = ({min, max, marks, step}) => {
- return truncateMarks(
- min,
- max,
- marks ? marks : autoGenerateMarks(min, max, step)
- );
+ const truncated_marks = (marks && marks.length > 0)
+ ? truncateMarks(min, max, marks)
+ : marks;
+
+ if (truncated_marks && truncated_marks.length > 0) {
+ return truncated_marks
+ }
+ return autoGenerateMarks(min, max, step)
};
/**
From f835c0f2aaea105343aba493bb310042cd45d5da Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 15 Sep 2021 03:23:49 +0300
Subject: [PATCH 55/80] fix: correct step calculations implemented for sliders
---
.../src/fragments/Slider.react.js | 3 +-
.../src/utils/computeSliderMarkers.js | 28 ++++++++-----------
2 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/components/dash-core-components/src/fragments/Slider.react.js b/components/dash-core-components/src/fragments/Slider.react.js
index 8161ddf007..bad3be7fca 100644
--- a/components/dash-core-components/src/fragments/Slider.react.js
+++ b/components/dash-core-components/src/fragments/Slider.react.js
@@ -5,7 +5,7 @@ import computeSliderStyle from '../utils/computeSliderStyle';
import 'rc-slider/assets/index.css';
-import {sanitizeMarks} from '../utils/computeSliderMarkers';
+import {sanitizeMarks, calcStep} from '../utils/computeSliderMarkers';
import {propTypes, defaultProps} from '../components/Slider.react';
/**
@@ -104,6 +104,7 @@ export default class Slider extends Component {
style={{position: 'relative'}}
value={value}
marks={sanitizeMarks({min, max, marks, step})}
+ step={calcStep(min, max, step)}
{...omit(
[
'className',
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 0468eee112..7dbceaba9a 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -103,34 +103,28 @@ export const autoGenerateMarks = (min, max, step) => {
* - Then truncate marks so no out of range marks
*/
export const sanitizeMarks = ({min, max, marks, step}) => {
- const truncated_marks = (marks && marks.length > 0)
- ? truncateMarks(min, max, marks)
- : marks;
+ const truncated_marks =
+ marks && marks.length > 0 ? truncateMarks(min, max, marks) : marks;
if (truncated_marks && truncated_marks.length > 0) {
- return truncated_marks
+ return truncated_marks;
}
- return autoGenerateMarks(min, max, step)
+ return autoGenerateMarks(min, max, step);
};
/**
* Calculate default step if not defined
*/
export const calcStep = (min, max, step) => {
- if (step !== undefined) {
- return step;
- }
+ if (step) return step;
- const size = Math.abs(max - min); // interval size
- /**
- * Size multiplied by 10^i to get a nice step value at the end (0.1, 1, 10, 100, ...)
- */
- const divident = size
- .toString()
- .replace('.', '') // removes decimal point
- .replace(/^(\d*?[1-9])0+$/, '$1'); // removes trailing zeros
+ const diff = max > min ? max - min : min - max;
- return size / divident;
+ const v = (Math.abs(diff) + Number.EPSILON) / 100;
+ const N = Math.floor(Math.log10(v));
+ return [1 * Math.pow(10, N), 2 * Math.pow(10, N), 5 * Math.pow(10, N)].sort(
+ (a, b) => Math.abs(a - v) - Math.abs(b - v)
+ )[0];
};
/**
From 8e5e6cf3d3e254048637a4b850881b1b04ea3d7b Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 15 Sep 2021 03:42:21 +0300
Subject: [PATCH 56/80] fix: removed Start and End prefix / suffix from labels
on Slider
---
.../src/utils/computeSliderMarkers.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 7dbceaba9a..0d928c4449 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -93,8 +93,8 @@ export const autoGenerateMarks = (min, max, step) => {
marks.forEach(mark => {
marksObject[mark] = String(mark);
});
- marksObject[min] = `Start (${min})`;
- marksObject[max] = `End (${max})`;
+ marksObject[min] = String(min);
+ marksObject[max] = String(max);
return marksObject;
};
@@ -116,13 +116,13 @@ export const sanitizeMarks = ({min, max, marks, step}) => {
* Calculate default step if not defined
*/
export const calcStep = (min, max, step) => {
- if (step) return step;
+ if (step) {return step;}
const diff = max > min ? max - min : min - max;
const v = (Math.abs(diff) + Number.EPSILON) / 100;
const N = Math.floor(Math.log10(v));
- return [1 * Math.pow(10, N), 2 * Math.pow(10, N), 5 * Math.pow(10, N)].sort(
+ return [Number(Math.pow(10, N)), 2 * Math.pow(10, N), 5 * Math.pow(10, N)].sort(
(a, b) => Math.abs(a - v) - Math.abs(b - v)
)[0];
};
From 5f569c9e6a6eae2423a06cb54937a04baedf3fa6 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 22:22:03 -0400
Subject: [PATCH 57/80] chore: add labels to dropdown tests
---
.../dropdown/test_dropdown_shorthands.py | 75 +++++++++++--------
1 file changed, 42 insertions(+), 33 deletions(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
index ba5ac691e3..da26d3aacf 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
@@ -1,41 +1,50 @@
+from dash.dcc.Dropdown import Dropdown
from dash import Dash, dcc, html
def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
app = Dash(__name__)
- app.layout = html.Div(
- [
- dcc.Dropdown(["a", "b", "c"]),
- dcc.Dropdown(["a", "b", "c"], "b"),
- dcc.Dropdown(["a", 3, "c"]),
- dcc.Dropdown(["a", 3, "c"], 3),
- dcc.Dropdown(["a", True, "c"]),
- dcc.Dropdown(["a", True, "c"], True),
- dcc.Dropdown(["a", 3, "c", True, False]),
- dcc.Dropdown(["a", 3, "c", True, False], False),
- dcc.Dropdown({"one": "One", "two": "Two", "three": "Three"}),
- dcc.Dropdown({"one": "One", "two": "Two", "three": "Three"}, "two"),
- dcc.Dropdown({"one": 1, "two": 2, "three": False}),
- dcc.Dropdown({"one": 1, "two": 2, "three": False}, "three"),
- dcc.Dropdown({"one": 1, "two": True, "three": 3}),
- dcc.Dropdown({"one": 1, "two": True, "three": 3}, "two"),
- dcc.Dropdown(
- [
- {"label": "one", "value": 1},
- {"label": "two", "value": True},
- {"label": "three", "value": 3},
- ]
- ),
- dcc.Dropdown(
- [
- {"label": "one", "value": 1},
- {"label": "two", "value": True},
- {"label": "three", "value": 3},
- ],
- True,
- ),
- ]
- )
+
+ TEST_OPTIONS_N_VALUES = [
+ (["a", "b", "c"]),
+ (["a", "b", "c"], "b"),
+ (["a", 3, "c"]),
+ (["a", 3, "c"], 3),
+ (["a", True, "c"]),
+ (["a", True, "c"], True),
+ (["a", 3, "c", True, False]),
+ (["a", 3, "c", True, False], False),
+ ({"one": "One", "two": "Two", "three": "Three"}),
+ ({"one": "One", "two": "Two", "three": "Three"}, "two"),
+ ({"one": 1, "two": 2, "three": False}),
+ ({"one": 1, "two": 2, "three": False}, "three"),
+ ({"one": 1, "two": True, "three": 3}),
+ ({"one": 1, "two": True, "three": 3}, "two"),
+ (
+ [
+ {"label": "one", "value": 1},
+ {"label": "two", "value": True},
+ {"label": "three", "value": 3},
+ ]
+ ),
+ (
+ [
+ {"label": "one", "value": 1},
+ {"label": "two", "value": True},
+ {"label": "three", "value": 3},
+ ],
+ True,
+ ),
+ ]
+
+ layout = []
+ for definition in TEST_OPTIONS_N_VALUES:
+ option, value = definition
+ layout.extend(
+ [html.Div(f"Options={option}, Value={value}"), dcc.Dropdown(option, value)]
+ )
+
+ app.layout = html.Div(layout)
dash_dcc.start_server(app)
dash_dcc.wait_for_element(".dash-dropdown")
From d6e994a2bb59411cd825c1161dddecb06aa2cd63 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 22:30:41 -0400
Subject: [PATCH 58/80] chore: lint fix
---
.../tests/integration/dropdown/test_dropdown_shorthands.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
index da26d3aacf..96a401e528 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
@@ -1,4 +1,3 @@
-from dash.dcc.Dropdown import Dropdown
from dash import Dash, dcc, html
From d47a0b27dd56ed6152372d858858ec16ae4df5bb Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 22:35:56 -0400
Subject: [PATCH 59/80] fix: dropdown options for test
---
.../dropdown/test_dropdown_shorthands.py | 40 ++++++++++---------
1 file changed, 21 insertions(+), 19 deletions(-)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
index 96a401e528..bd0fc622bd 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
@@ -5,40 +5,42 @@ def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
app = Dash(__name__)
TEST_OPTIONS_N_VALUES = [
- (["a", "b", "c"]),
- (["a", "b", "c"], "b"),
- (["a", 3, "c"]),
- (["a", 3, "c"], 3),
- (["a", True, "c"]),
- (["a", True, "c"], True),
- (["a", 3, "c", True, False]),
- (["a", 3, "c", True, False], False),
- ({"one": "One", "two": "Two", "three": "Three"}),
- ({"one": "One", "two": "Two", "three": "Three"}, "two"),
- ({"one": 1, "two": 2, "three": False}),
- ({"one": 1, "two": 2, "three": False}, "three"),
- ({"one": 1, "two": True, "three": 3}),
- ({"one": 1, "two": True, "three": 3}, "two"),
- (
+ [["a", "b", "c"]],
+ [["a", "b", "c"], "b"],
+ [["a", 3, "c"]],
+ [["a", 3, "c"], 3],
+ [["a", True, "c"]],
+ [["a", True, "c"], True],
+ [["a", 3, "c", True, False]],
+ [["a", 3, "c", True, False], False],
+ # {`value1`: `label1`, `value2`, `label2`, ...}
+ [{"one": "One", "two": "Two", "three": "Three"}],
+ [{"one": "One", "two": "Two", "three": "Three"}, "two"],
+ [{"one": 1, "two": 2, "three": False}],
+ [{"one": 1, "two": 2, "three": False}, "three"],
+ [{"one": 1, "two": True, "three": 3}],
+ [{"one": 1, "two": True, "three": 3}, "two"],
+ # original options format
+ [
[
{"label": "one", "value": 1},
{"label": "two", "value": True},
{"label": "three", "value": 3},
]
- ),
- (
+ ],
+ [
[
{"label": "one", "value": 1},
{"label": "two", "value": True},
{"label": "three", "value": 3},
],
True,
- ),
+ ],
]
layout = []
for definition in TEST_OPTIONS_N_VALUES:
- option, value = definition
+ (option, value) = definition if len(definition) > 1 else [definition[0], None]
layout.extend(
[html.Div(f"Options={option}, Value={value}"), dcc.Dropdown(option, value)]
)
From 24f6cd5c16c958d4e4f9465e437f4640daeae9db Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Tue, 14 Sep 2021 23:05:58 -0400
Subject: [PATCH 60/80] chore: prettier :sleepy:
---
.../src/utils/computeSliderMarkers.js | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 0d928c4449..1f8ff0ac15 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -116,15 +116,19 @@ export const sanitizeMarks = ({min, max, marks, step}) => {
* Calculate default step if not defined
*/
export const calcStep = (min, max, step) => {
- if (step) {return step;}
+ if (step) {
+ return step;
+ }
const diff = max > min ? max - min : min - max;
const v = (Math.abs(diff) + Number.EPSILON) / 100;
const N = Math.floor(Math.log10(v));
- return [Number(Math.pow(10, N)), 2 * Math.pow(10, N), 5 * Math.pow(10, N)].sort(
- (a, b) => Math.abs(a - v) - Math.abs(b - v)
- )[0];
+ return [
+ Number(Math.pow(10, N)),
+ 2 * Math.pow(10, N),
+ 5 * Math.pow(10, N),
+ ].sort((a, b) => Math.abs(a - v) - Math.abs(b - v))[0];
};
/**
From d022d2bd018cc2e627cf86e54c2e22863e9fff49 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 16 Sep 2021 01:51:39 +0300
Subject: [PATCH 61/80] fix: removed a test file which was causing percy tests
fail
---
.../dropdown/test_dropdown_shorthands.py | 52 -------------------
1 file changed, 52 deletions(-)
delete mode 100644 components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
deleted file mode 100644
index bd0fc622bd..0000000000
--- a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from dash import Dash, dcc, html
-
-
-def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
- app = Dash(__name__)
-
- TEST_OPTIONS_N_VALUES = [
- [["a", "b", "c"]],
- [["a", "b", "c"], "b"],
- [["a", 3, "c"]],
- [["a", 3, "c"], 3],
- [["a", True, "c"]],
- [["a", True, "c"], True],
- [["a", 3, "c", True, False]],
- [["a", 3, "c", True, False], False],
- # {`value1`: `label1`, `value2`, `label2`, ...}
- [{"one": "One", "two": "Two", "three": "Three"}],
- [{"one": "One", "two": "Two", "three": "Three"}, "two"],
- [{"one": 1, "two": 2, "three": False}],
- [{"one": 1, "two": 2, "three": False}, "three"],
- [{"one": 1, "two": True, "three": 3}],
- [{"one": 1, "two": True, "three": 3}, "two"],
- # original options format
- [
- [
- {"label": "one", "value": 1},
- {"label": "two", "value": True},
- {"label": "three", "value": 3},
- ]
- ],
- [
- [
- {"label": "one", "value": 1},
- {"label": "two", "value": True},
- {"label": "three", "value": 3},
- ],
- True,
- ],
- ]
-
- layout = []
- for definition in TEST_OPTIONS_N_VALUES:
- (option, value) = definition if len(definition) > 1 else [definition[0], None]
- layout.extend(
- [html.Div(f"Options={option}, Value={value}"), dcc.Dropdown(option, value)]
- )
-
- app.layout = html.Div(layout)
-
- dash_dcc.start_server(app)
- dash_dcc.wait_for_element(".dash-dropdown")
- dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
From 9ccdec38d9e13a6b633c35072717a2f560b900f7 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 16 Sep 2021 04:15:13 +0300
Subject: [PATCH 62/80] fix: defining emptiness of dictionary implemented
correctly, which fixes the disappearing of explicitely given marks
---
.../src/utils/computeSliderMarkers.js | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 1f8ff0ac15..cd03e0f95f 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -1,4 +1,4 @@
-import {pickBy} from 'ramda';
+import {pickBy, isEmpty} from 'ramda';
/**
* Truncate marks if they are out of Slider interval
@@ -104,9 +104,11 @@ export const autoGenerateMarks = (min, max, step) => {
*/
export const sanitizeMarks = ({min, max, marks, step}) => {
const truncated_marks =
- marks && marks.length > 0 ? truncateMarks(min, max, marks) : marks;
+ marks && isEmpty(marks) === false
+ ? truncateMarks(min, max, marks)
+ : marks;
- if (truncated_marks && truncated_marks.length > 0) {
+ if (truncated_marks && isEmpty(truncated_marks) === false) {
return truncated_marks;
}
return autoGenerateMarks(min, max, step);
From edaea38f07e8d9d1191358ab8c847315215f9007 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 15 Sep 2021 22:23:09 -0400
Subject: [PATCH 63/80] fix: omit 'step' from props
---
components/dash-core-components/src/fragments/Slider.react.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/components/dash-core-components/src/fragments/Slider.react.js b/components/dash-core-components/src/fragments/Slider.react.js
index bad3be7fca..8bdf569230 100644
--- a/components/dash-core-components/src/fragments/Slider.react.js
+++ b/components/dash-core-components/src/fragments/Slider.react.js
@@ -114,6 +114,7 @@ export default class Slider extends Component {
'drag_value',
'marks',
'verticalHeight',
+ 'step',
],
this.props
)}
From e54495e030f9dd658fda6625e4eec839f33262d7 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 15 Sep 2021 22:51:07 -0400
Subject: [PATCH 64/80] chore: update props description
---
.../dash-core-components/src/components/Checklist.react.js | 4 ++--
.../dash-core-components/src/components/Dropdown.react.js | 4 ++--
.../dash-core-components/src/components/RadioItems.react.js | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index c27fcc4fc4..9fc22080b4 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -79,7 +79,7 @@ Checklist.propTypes = {
*/
options: PropTypes.oneOfType([
/**
- * Array of options - [string|number|bool]
+ * Array of options where the label and the value are the same thing - [string|number|bool]
*/
PropTypes.arrayOf(
PropTypes.oneOfType([
@@ -89,7 +89,7 @@ Checklist.propTypes = {
])
),
/**
- * Simpler `options` representation in dictionary format
+ * Simpler `options` representation in dictionary format. The order is not guaranteed.
* {`value1`: `label1`, `value2`: `label2`, ... }
* which is equal to
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 31afd56c98..27d090b8ed 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -31,7 +31,7 @@ Dropdown.propTypes = {
*/
options: PropTypes.oneOfType([
/**
- * Array of options - [string|number|bool]
+ * Array of options where the label and the value are the same thing - [string|number|bool]
*/
PropTypes.arrayOf(
PropTypes.oneOfType([
@@ -41,7 +41,7 @@ Dropdown.propTypes = {
])
),
/**
- * Simpler `options` representation in dictionary format
+ * Simpler `options` representation in dictionary format. The order is not guaranteed.
* {`value1`: `label1`, `value2`: `label2`, ... }
* which is equal to
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 9bf873159d..43bf2d3072 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -74,7 +74,7 @@ RadioItems.propTypes = {
*/
options: PropTypes.oneOfType([
/**
- * Array of options - [string|number|bool]
+ * Array of options where the label and the value are the same thing - [string|number|bool]
*/
PropTypes.arrayOf(
PropTypes.oneOfType([
@@ -84,7 +84,7 @@ RadioItems.propTypes = {
])
),
/**
- * Simpler `options` representation in dictionary format
+ * Simpler `options` representation in dictionary format. The order is not guaranteed.
* {`value1`: `label1`, `value2`: `label2`, ... }
* which is equal to
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
From c8947e7b708353587282a67d5f97bfe684857160 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Wed, 15 Sep 2021 23:25:34 -0400
Subject: [PATCH 65/80] chore: remove unnecessary prop type checker
---
.../src/components/Checklist.react.js | 8 +-------
.../dash-core-components/src/components/Dropdown.react.js | 8 +-------
.../src/components/RadioItems.react.js | 8 +-------
3 files changed, 3 insertions(+), 21 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 9fc22080b4..59710167a0 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -94,13 +94,7 @@ Checklist.propTypes = {
* which is equal to
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
*/
- PropTypes.objectOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
+ PropTypes.object,
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 27d090b8ed..6cc2597417 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -46,13 +46,7 @@ Dropdown.propTypes = {
* which is equal to
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
*/
- PropTypes.objectOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
+ PropTypes.object,
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 43bf2d3072..87b8a155cc 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -89,13 +89,7 @@ RadioItems.propTypes = {
* which is equal to
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...]
*/
- PropTypes.objectOf(
- PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- PropTypes.bool,
- ])
- ),
+ PropTypes.object,
/**
* An array of options {label: [string|number], value: [string|number]},
* an optional disabled field can be used for each option
From 9485e50bc3a08fe3b043d13dfa158a7d771181f1 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 16 Sep 2021 19:39:43 +0300
Subject: [PATCH 66/80] fix: range slider test corrected, formatted to have
some margins
---
.../sliders/test_sliders_shorthands.py | 107 +++++++++++++-----
1 file changed, 80 insertions(+), 27 deletions(-)
diff --git a/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
index e868f9fcad..3ea1d09fc7 100644
--- a/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
@@ -28,38 +28,91 @@ def test_slsh001_rangeslider_shorthand_props(dash_dcc):
LAYOUT.extend(
[
- html.Div(f"{min} - {max}"),
- dcc.Slider(min, max),
- dcc.RangeSlider(min, max),
- html.Div(f"{min} - {max}, {steps}"),
- dcc.Slider(min, max, steps),
- dcc.RangeSlider(min, max, steps),
- html.Div(f"{min} - {max}, {steps}, value={min + steps}"),
- dcc.Slider(min, max, steps, value=min + steps),
html.Div(
- f"{min} - {max}, {steps}, value=[{min + steps},{min + steps * 3}]"
+ [
+ html.Div(
+ f"{min} - {max}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min, max),
+ ]
),
- dcc.RangeSlider(min, max, steps, value=[min + steps, min + steps * 3]),
- html.Div(f"{min} - {max}, {steps}, value={min + steps}, marks={marks}"),
- dcc.Slider(
- min,
- max,
- steps,
- value=min + steps,
- marks={
- i: "Label {}".format(i) if i == 1 else str(i)
- for i in range(1, 6)
- },
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(min, max),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}, {steps}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min, max, steps),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}, {steps}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(min, max, steps),
+ ]
),
html.Div(
- f"{min} - {max}, {steps},value=[{min + steps},{min + steps * 3}], marks={marks}"
+ [
+ html.Div(
+ f"{min} - {max}, {steps}, value={min + steps}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min, max, steps, value=min + steps),
+ ]
),
- dcc.RangeSlider(
- min,
- max,
- steps,
- value=[min + steps, min + steps * 3],
- marks=marks,
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}, {steps}, value=[{min + steps},{min + steps * 3}]",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(
+ min, max, steps, value=[min + steps, min + steps * 3]
+ ),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}, {steps}, value={min + steps}, marks={marks}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(
+ min,
+ max,
+ steps,
+ value=min + steps,
+ marks=marks,
+ ),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}, {steps},value=[{min + steps},{min + steps * 3}], marks={marks}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(
+ min,
+ max,
+ steps,
+ value=[min + steps, min + steps * 3],
+ marks=marks,
+ ),
+ ]
),
]
)
From 07edc14a8e4e4201f6e2c1778664c83acd8a2c78 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 16 Sep 2021 23:34:09 +0300
Subject: [PATCH 67/80] fix: the test_ddsh001_dropdown_shorthand_properties
test restored back and the DropDowns propTypes are fixed
---
.../src/components/Dropdown.react.js | 5 +-
.../dropdown/test_dropdown_shorthands.py | 52 +++++++++++++++++++
2 files changed, 55 insertions(+), 2 deletions(-)
create mode 100644 components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 6cc2597417..177880c504 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -64,7 +64,7 @@ Dropdown.propTypes = {
* corresponds to the items specified in the
* `value` property.
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
.isRequired,
/**
@@ -93,8 +93,9 @@ Dropdown.propTypes = {
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
+ PropTypes.bool,
PropTypes.arrayOf(
- PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
),
]),
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
new file mode 100644
index 0000000000..bd0fc622bd
--- /dev/null
+++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
@@ -0,0 +1,52 @@
+from dash import Dash, dcc, html
+
+
+def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
+ app = Dash(__name__)
+
+ TEST_OPTIONS_N_VALUES = [
+ [["a", "b", "c"]],
+ [["a", "b", "c"], "b"],
+ [["a", 3, "c"]],
+ [["a", 3, "c"], 3],
+ [["a", True, "c"]],
+ [["a", True, "c"], True],
+ [["a", 3, "c", True, False]],
+ [["a", 3, "c", True, False], False],
+ # {`value1`: `label1`, `value2`, `label2`, ...}
+ [{"one": "One", "two": "Two", "three": "Three"}],
+ [{"one": "One", "two": "Two", "three": "Three"}, "two"],
+ [{"one": 1, "two": 2, "three": False}],
+ [{"one": 1, "two": 2, "three": False}, "three"],
+ [{"one": 1, "two": True, "three": 3}],
+ [{"one": 1, "two": True, "three": 3}, "two"],
+ # original options format
+ [
+ [
+ {"label": "one", "value": 1},
+ {"label": "two", "value": True},
+ {"label": "three", "value": 3},
+ ]
+ ],
+ [
+ [
+ {"label": "one", "value": 1},
+ {"label": "two", "value": True},
+ {"label": "three", "value": 3},
+ ],
+ True,
+ ],
+ ]
+
+ layout = []
+ for definition in TEST_OPTIONS_N_VALUES:
+ (option, value) = definition if len(definition) > 1 else [definition[0], None]
+ layout.extend(
+ [html.Div(f"Options={option}, Value={value}"), dcc.Dropdown(option, value)]
+ )
+
+ app.layout = html.Div(layout)
+
+ dash_dcc.start_server(app)
+ dash_dcc.wait_for_element(".dash-dropdown")
+ dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
From ab8f4fbb234e2043330de2b2ab09204d795aa0fd Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 00:36:05 +0300
Subject: [PATCH 68/80] fix: added bool type to CheckList label/value and
RadioItem label/value
---
.../dash-core-components/src/components/Checklist.react.js | 6 +++---
.../dash-core-components/src/components/RadioItems.react.js | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 59710167a0..6690525667 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -104,7 +104,7 @@ Checklist.propTypes = {
/**
* The option's label
*/
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
.isRequired,
/**
@@ -112,7 +112,7 @@ Checklist.propTypes = {
* corresponds to the items specified in the
* `value` property.
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
.isRequired,
/**
@@ -134,7 +134,7 @@ Checklist.propTypes = {
* The currently selected value
*/
value: PropTypes.arrayOf(
- PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
),
/**
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index 87b8a155cc..b78c4d0f1f 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -99,7 +99,7 @@ RadioItems.propTypes = {
/**
* The option's label
*/
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
.isRequired,
/**
@@ -107,7 +107,7 @@ RadioItems.propTypes = {
* corresponds to the items specified in the
* `value` property.
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
.isRequired,
/**
@@ -135,7 +135,7 @@ RadioItems.propTypes = {
/**
* The currently selected value
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
/**
* The style of the container (div)
From 12e96e2efc51850df8650988379506e812c3130e Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 00:39:43 +0300
Subject: [PATCH 69/80] fix: the edited JS files are reformatted using lint
---
.../src/components/Checklist.react.js | 20 ++++++++++++++-----
.../src/components/Dropdown.react.js | 13 +++++++++---
.../src/components/RadioItems.react.js | 20 ++++++++++++++-----
3 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/components/dash-core-components/src/components/Checklist.react.js b/components/dash-core-components/src/components/Checklist.react.js
index 6690525667..fc9a207982 100644
--- a/components/dash-core-components/src/components/Checklist.react.js
+++ b/components/dash-core-components/src/components/Checklist.react.js
@@ -104,16 +104,22 @@ Checklist.propTypes = {
/**
* The option's label
*/
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
- .isRequired,
+ label: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ]).isRequired,
/**
* The value of the option. This value
* corresponds to the items specified in the
* `value` property.
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
- .isRequired,
+ value: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ]).isRequired,
/**
* If true, this option is disabled and cannot be selected.
@@ -134,7 +140,11 @@ Checklist.propTypes = {
* The currently selected value
*/
value: PropTypes.arrayOf(
- PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
),
/**
diff --git a/components/dash-core-components/src/components/Dropdown.react.js b/components/dash-core-components/src/components/Dropdown.react.js
index 177880c504..f329443b8d 100644
--- a/components/dash-core-components/src/components/Dropdown.react.js
+++ b/components/dash-core-components/src/components/Dropdown.react.js
@@ -64,8 +64,11 @@ Dropdown.propTypes = {
* corresponds to the items specified in the
* `value` property.
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
- .isRequired,
+ value: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ]).isRequired,
/**
* If true, this option is disabled and cannot be selected.
@@ -95,7 +98,11 @@ Dropdown.propTypes = {
PropTypes.number,
PropTypes.bool,
PropTypes.arrayOf(
- PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ])
),
]),
diff --git a/components/dash-core-components/src/components/RadioItems.react.js b/components/dash-core-components/src/components/RadioItems.react.js
index b78c4d0f1f..fe6d8e42c1 100644
--- a/components/dash-core-components/src/components/RadioItems.react.js
+++ b/components/dash-core-components/src/components/RadioItems.react.js
@@ -99,16 +99,22 @@ RadioItems.propTypes = {
/**
* The option's label
*/
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
- .isRequired,
+ label: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ]).isRequired,
/**
* The value of the option. This value
* corresponds to the items specified in the
* `value` property.
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
- .isRequired,
+ value: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ]).isRequired,
/**
* If true, this option is disabled and cannot be selected.
@@ -135,7 +141,11 @@ RadioItems.propTypes = {
/**
* The currently selected value
*/
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
+ value: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.bool,
+ ]),
/**
* The style of the container (div)
From e49d34b8f53bde3b58470f9feb777ec60dfede72 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 03:01:43 +0300
Subject: [PATCH 70/80] feat: implemented SI Units format for unit values of
slider
---
.../src/utils/computeSliderMarkers.js | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index cd03e0f95f..5bbd3d9bb4 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -1,4 +1,5 @@
import {pickBy, isEmpty} from 'ramda';
+import {formatPrefix} from 'd3-format';
/**
* Truncate marks if they are out of Slider interval
@@ -66,10 +67,11 @@ const estimateBestSteps = (minValue, maxValue, stepValue) => {
};
export const autoGenerateMarks = (min, max, step) => {
+ const max_min_mean = (Math.abs(max) + Math.abs(min)) / 2;
const marks = [];
const [start, interval, chosenStep] = step
? [min, step, step]
- : estimateBestSteps(min, max, 1);
+ : estimateBestSteps(min, max, calcStep(min, max, step));
let cursor = start + interval;
// make sure we don't step into infinite loop
@@ -90,11 +92,12 @@ export const autoGenerateMarks = (min, max, step) => {
}
const marksObject = {};
+ const si_formatter = formatPrefix(',.0', max_min_mean);
marks.forEach(mark => {
- marksObject[mark] = String(mark);
+ marksObject[mark] = String(si_formatter(mark));
});
- marksObject[min] = String(min);
- marksObject[max] = String(max);
+ marksObject[min] = String(si_formatter(min));
+ marksObject[max] = String(si_formatter(max));
return marksObject;
};
From 487717b3c9cb8daebefdb9fbc64f9692155fc508 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 03:10:02 +0300
Subject: [PATCH 71/80] feat: added tests to cover slider SI Units format for
unit values
---
.../sliders/test_sliders_shorthands.py | 91 +++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
index 3ea1d09fc7..4dea3537ce 100644
--- a/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
@@ -117,6 +117,97 @@ def test_slsh001_rangeslider_shorthand_props(dash_dcc):
]
)
+ n = 10
+
+ N_K = 10000
+ N_M = 10000000
+ N_mu = 0.00001
+
+ min_k = -n * N_K
+ max_k = (-n + 10) * N_K
+
+ min_M = -n * N_M
+ max_M = (n + 10) * N_M
+
+ min_mu = -n * N_mu
+ max_mu = (-n + 10) * N_mu
+
+ LAYOUT.extend(
+ [
+ html.Div(
+ [
+ html.Div(
+ f"{min_k} - {max_k}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min_k, max_k),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_k} - {max_k}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(min_k, max_k),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_M} - {max_M}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min_M, max_M),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_M} - {max_M}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(min_M, max_M),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_mu} - {max_mu}, {N_mu}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min_mu, max_mu, N_mu),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_mu} - {max_mu}, {N_mu}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(min_mu, max_mu, N_mu),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_mu} - {max_mu}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min_mu, max_mu),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"{min_mu} - {max_mu}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(min_mu, max_mu),
+ ]
+ ),
+ ]
+ )
app = Dash(__name__)
app.layout = html.Div(LAYOUT)
From 362929d7053fd0e24b38e07e2110ec36537d83bd Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Thu, 16 Sep 2021 20:25:11 -0400
Subject: [PATCH 72/80] chore: eslint fix
---
.../src/utils/computeSliderMarkers.js | 38 +++++++++----------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 5bbd3d9bb4..0729b90298 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -66,6 +66,25 @@ const estimateBestSteps = (minValue, maxValue, stepValue) => {
];
};
+/**
+ * Calculate default step if not defined
+ */
+export const calcStep = (min, max, step) => {
+ if (step) {
+ return step;
+ }
+
+ const diff = max > min ? max - min : min - max;
+
+ const v = (Math.abs(diff) + Number.EPSILON) / 100;
+ const N = Math.floor(Math.log10(v));
+ return [
+ Number(Math.pow(10, N)),
+ 2 * Math.pow(10, N),
+ 5 * Math.pow(10, N),
+ ].sort((a, b) => Math.abs(a - v) - Math.abs(b - v))[0];
+};
+
export const autoGenerateMarks = (min, max, step) => {
const max_min_mean = (Math.abs(max) + Math.abs(min)) / 2;
const marks = [];
@@ -117,25 +136,6 @@ export const sanitizeMarks = ({min, max, marks, step}) => {
return autoGenerateMarks(min, max, step);
};
-/**
- * Calculate default step if not defined
- */
-export const calcStep = (min, max, step) => {
- if (step) {
- return step;
- }
-
- const diff = max > min ? max - min : min - max;
-
- const v = (Math.abs(diff) + Number.EPSILON) / 100;
- const N = Math.floor(Math.log10(v));
- return [
- Number(Math.pow(10, N)),
- 2 * Math.pow(10, N),
- 5 * Math.pow(10, N),
- ].sort((a, b) => Math.abs(a - v) - Math.abs(b - v))[0];
-};
-
/**
* Calculate default value if not defined
*/
From 1e7011e8df80827b1838c1f775902de22ac10a83 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 20:42:42 +0300
Subject: [PATCH 73/80] fix: the test adopted to propsTypes which now accepts
bool for several components
---
tests/integration/devtools/test_props_check.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/integration/devtools/test_props_check.py b/tests/integration/devtools/test_props_check.py
index 603909158e..23211ed3dd 100644
--- a/tests/integration/devtools/test_props_check.py
+++ b/tests/integration/devtools/test_props_check.py
@@ -15,12 +15,6 @@
"component": dcc.Checklist,
"props": {"options": [{"label": "hello"}], "value": ["test"]},
},
- "invalid-nested-prop": {
- "fail": True,
- "name": "invalid nested prop",
- "component": dcc.Checklist,
- "props": {"options": [{"label": "hello", "value": True}], "value": ["test"]},
- },
"invalid-arrayOf": {
"fail": True,
"name": "invalid arrayOf",
@@ -113,6 +107,12 @@
"columns": [{"id": "id", "name": "name", "format": {"prefix": "asdf"}}]
},
},
+ "allow-nested-prop": {
+ "fail": False,
+ "name": "allow nested prop",
+ "component": dcc.Checklist,
+ "props": {"options": [{"label": "hello", "value": True}], "value": ["test"]},
+ },
"allow-null": {
"fail": False,
"name": "nested null",
From 6153bd0710542d3621f5e039b2d59945197c01a4 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 23:45:07 +0300
Subject: [PATCH 74/80] fix: slider numbers whose ten factor is less than 3 and
bigger than -3 are not formatted, so that they can have floating numebrs
---
.../src/utils/computeSliderMarkers.js | 21 ++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 0729b90298..7ab33895f7 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -85,8 +85,20 @@ export const calcStep = (min, max, step) => {
].sort((a, b) => Math.abs(a - v) - Math.abs(b - v))[0];
};
-export const autoGenerateMarks = (min, max, step) => {
+export const applyD3Format = (mark, min, max) => {
+ const mu_ten_factor = -3
+ const k_ten_factor = 3
+
+ const ten_factor = Math.log10(Math.abs(mark));
+ if (ten_factor > mu_ten_factor && ten_factor < k_ten_factor) {
+ return String(mark);
+ }
const max_min_mean = (Math.abs(max) + Math.abs(min)) / 2;
+ const si_formatter = formatPrefix(',.0', max_min_mean);
+ return String(si_formatter(mark));
+};
+
+export const autoGenerateMarks = (min, max, step) => {
const marks = [];
const [start, interval, chosenStep] = step
? [min, step, step]
@@ -111,12 +123,11 @@ export const autoGenerateMarks = (min, max, step) => {
}
const marksObject = {};
- const si_formatter = formatPrefix(',.0', max_min_mean);
marks.forEach(mark => {
- marksObject[mark] = String(si_formatter(mark));
+ marksObject[mark] = applyD3Format(mark, min, max);
});
- marksObject[min] = String(si_formatter(min));
- marksObject[max] = String(si_formatter(max));
+ marksObject[min] = applyD3Format(min, min, max);
+ marksObject[max] = applyD3Format(max, min, max);
return marksObject;
};
From a3e78b170c812c2c8495b1bddd2d15f71700e8ef Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 18 Sep 2021 01:27:11 +0300
Subject: [PATCH 75/80] fix: lint issue fixed
---
.../dash-core-components/src/utils/computeSliderMarkers.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 7ab33895f7..7c936a2d3a 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -86,8 +86,8 @@ export const calcStep = (min, max, step) => {
};
export const applyD3Format = (mark, min, max) => {
- const mu_ten_factor = -3
- const k_ten_factor = 3
+ const mu_ten_factor = -3;
+ const k_ten_factor = 3;
const ten_factor = Math.log10(Math.abs(mark));
if (ten_factor > mu_ten_factor && ten_factor < k_ten_factor) {
From 23f5e79fb2bd3ede315893e354133402e966abdf Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 23:23:23 -0400
Subject: [PATCH 76/80] fix: explicit null prevents auto generating marks in
sliders
---
.../dash-core-components/src/utils/computeSliderMarkers.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/components/dash-core-components/src/utils/computeSliderMarkers.js b/components/dash-core-components/src/utils/computeSliderMarkers.js
index 7c936a2d3a..34fca54560 100644
--- a/components/dash-core-components/src/utils/computeSliderMarkers.js
+++ b/components/dash-core-components/src/utils/computeSliderMarkers.js
@@ -133,9 +133,14 @@ export const autoGenerateMarks = (min, max, step) => {
/**
* - Auto generate marks if not given,
+ * - Not generate anything at all when explicit null is given to marks
* - Then truncate marks so no out of range marks
*/
export const sanitizeMarks = ({min, max, marks, step}) => {
+ if (marks === null) {
+ return undefined;
+ }
+
const truncated_marks =
marks && isEmpty(marks) === false
? truncateMarks(min, max, marks)
From 13e008f097b0a2f7e8c16a036e5578edd4c4de43 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 23:24:12 -0400
Subject: [PATCH 77/80] fix: add snapshot for set_auto_id dependency link and
asserts
---
.../integration/misc/test_bcdp_auto_id.py | 46 +++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 components/dash-core-components/tests/integration/misc/test_bcdp_auto_id.py
diff --git a/components/dash-core-components/tests/integration/misc/test_bcdp_auto_id.py b/components/dash-core-components/tests/integration/misc/test_bcdp_auto_id.py
new file mode 100644
index 0000000000..6fe4e441eb
--- /dev/null
+++ b/components/dash-core-components/tests/integration/misc/test_bcdp_auto_id.py
@@ -0,0 +1,46 @@
+from dash import Dash, Input, Output, dcc, html
+
+
+def test_msps002_auto_id_assert(dash_dcc):
+ app = Dash(__name__)
+
+ input1 = dcc.Input(value="Hello")
+ input2 = dcc.Input(value="Hello")
+ input3 = dcc.Input(value=3)
+ output1 = html.Div()
+ output2 = html.Div()
+ output3 = html.Div(id="output-3")
+ slider = dcc.Slider(0, 10, value=9)
+
+ app.layout = html.Div([input1, input2, output1, output2, output3, input3, slider])
+
+ @app.callback(Output(output1, "children"), Input(input1, "value"))
+ def update(v):
+ return f"Output1: Input1={v}"
+
+ @app.callback(Output(output2, "children"), Input(input2, "value"))
+ def update(v):
+ return f"Output2: Input2={v}"
+
+ @app.callback(
+ Output("output-3", "children"), Input(input1, "value"), Input(input2, "value")
+ )
+ def update(v1, v2):
+ return f"Output3: Input1={v1}, Input2={v2}"
+
+ @app.callback(Output(slider, "value"), Input(input3, "value"))
+ def update(v):
+ return v
+
+ # Verify the auto-generated IDs are stable
+ assert output1.id == "e3e70682-c209-4cac-629f-6fbed82c07cd"
+ assert input1.id == "82e2e662-f728-b4fa-4248-5e3a0a5d2f34"
+ assert output2.id == "d4713d60-c8a7-0639-eb11-67b367a9c378"
+ assert input2.id == "23a7711a-8133-2876-37eb-dcd9e87a1613"
+ # we make sure that the if the id is set explicitly, then it is not replaced by random id
+ assert output3.id == "output-3"
+
+ dash_dcc.start_server(app)
+
+ dash_dcc.wait_for_element(".rc-slider")
+ dash_dcc.percy_snapshot("component_auto_id - test_msps002_auto_id_assert", True)
From d34453fcea7f79ee4511ce220b1b1776fccdd6a2 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Fri, 17 Sep 2021 23:24:58 -0400
Subject: [PATCH 78/80] fix: test marks=None and SI units format
---
.../integration/misc/test_persistence.py | 14 +-
.../sliders/test_sliders_shorthands.py | 126 +++++++-----------
2 files changed, 52 insertions(+), 88 deletions(-)
diff --git a/components/dash-core-components/tests/integration/misc/test_persistence.py b/components/dash-core-components/tests/integration/misc/test_persistence.py
index 401b24d0c4..8435a6a6b8 100644
--- a/components/dash-core-components/tests/integration/misc/test_persistence.py
+++ b/components/dash-core-components/tests/integration/misc/test_persistence.py
@@ -141,12 +141,12 @@ 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.25) # 5
- # dash_dcc.click_at_coord_fractions(range_slider, 0.8, 0.25) # 8
+ range_slider = dash_dcc.find_element("#rangeslider")
+ 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.25) # 22
+ slider = dash_dcc.find_element("#slider")
+ dash_dcc.click_at_coord_fractions(slider, 0.2, 0.25) # 22
dash_dcc.find_element("#tabs .tab:last-child").click() # C
@@ -161,8 +161,8 @@ def make_output(*args):
[u"4️⃣", u"6️⃣"],
"yes maybe",
"r",
- [3, 7],
- 25,
+ [5, 8],
+ 22,
"C",
"knock knock\nwho's there?",
]
diff --git a/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
index 4dea3537ce..79bad9df0e 100644
--- a/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
+++ b/components/dash-core-components/tests/integration/sliders/test_sliders_shorthands.py
@@ -114,103 +114,67 @@ def test_slsh001_rangeslider_shorthand_props(dash_dcc):
),
]
),
+ html.Div(
+ [
+ html.Div(
+ f"{min} - {max}, {steps},value=[{min + steps},{min + steps * 3}], marks=None",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RangeSlider(
+ min,
+ max,
+ steps,
+ value=[min + steps, min + steps * 3],
+ marks=None,
+ ),
+ ]
+ ),
]
)
- n = 10
+ app = Dash(__name__)
+ app.layout = html.Div(LAYOUT)
- N_K = 10000
- N_M = 10000000
- N_mu = 0.00001
+ dash_dcc.start_server(app)
+ dash_dcc.wait_for_element(".rc-slider")
+ dash_dcc.percy_snapshot("slsh001 - test_slsh001_rangeslider_shorthand_props", True)
- min_k = -n * N_K
- max_k = (-n + 10) * N_K
- min_M = -n * N_M
- max_M = (n + 10) * N_M
+def test_slsh002_sliders_marks_si_unit_format(dash_dcc):
- min_mu = -n * N_mu
- max_mu = (-n + 10) * N_mu
+ LAYOUT = []
+ # Showing SI Units
LAYOUT.extend(
[
html.Div(
- [
- html.Div(
- f"{min_k} - {max_k}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.Slider(min_k, max_k),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_k} - {max_k}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.RangeSlider(min_k, max_k),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_M} - {max_M}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.Slider(min_M, max_M),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_M} - {max_M}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.RangeSlider(min_M, max_M),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_mu} - {max_mu}, {N_mu}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.Slider(min_mu, max_mu, N_mu),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_mu} - {max_mu}, {N_mu}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.RangeSlider(min_mu, max_mu, N_mu),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_mu} - {max_mu}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.Slider(min_mu, max_mu),
- ]
- ),
- html.Div(
- [
- html.Div(
- f"{min_mu} - {max_mu}",
- style={"marginBottom": 15, "marginTop": 25},
- ),
- dcc.RangeSlider(min_mu, max_mu),
- ]
+ "Testing SI units",
+ style={"marginBottom": 10, "marginTop": 30},
),
]
)
+
+ for n in range(-20, 20):
+ min = 0
+ max = pow(10, n)
+ LAYOUT.extend(
+ [
+ html.Div(
+ [
+ html.Div(
+ f"min={min}, max={max}(=10^{n})",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Slider(min, max),
+ dcc.RangeSlider(min, max),
+ ]
+ )
+ ]
+ )
+
app = Dash(__name__)
app.layout = html.Div(LAYOUT)
dash_dcc.start_server(app)
dash_dcc.wait_for_element(".rc-slider")
- dash_dcc.percy_snapshot("slsh001 - test_slsh001_rangeslider_shorthand_props", True)
+ dash_dcc.percy_snapshot("slsh002 - test_slsh002_sliders_marks_si_unit_format", True)
From bea6c4c95fed986d0772850baade607b0987442e Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 18 Sep 2021 00:06:00 -0400
Subject: [PATCH 79/80] fix: test_persistence - give step=1 to expect integer
value output, otherwise 0.1 will be auto assigned
---
.../tests/integration/misc/test_persistence.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/dash-core-components/tests/integration/misc/test_persistence.py b/components/dash-core-components/tests/integration/misc/test_persistence.py
index 8435a6a6b8..1559d57815 100644
--- a/components/dash-core-components/tests/integration/misc/test_persistence.py
+++ b/components/dash-core-components/tests/integration/misc/test_persistence.py
@@ -65,9 +65,9 @@ def test_msps001_basic_persistence(dash_dcc):
persistence=True,
),
dcc.RangeSlider(
- id="rangeslider", min=0, max=10, value=[3, 7], persistence=True
+ id="rangeslider", min=0, max=10, step=1, value=[3, 7], persistence=True
),
- dcc.Slider(id="slider", min=20, max=30, value=25, persistence=True),
+ dcc.Slider(id="slider", min=20, max=30, step=1, value=25, persistence=True),
dcc.Tabs(
id="tabs",
children=[
From edf6042159a0fdeba79fdee8a536cbc543e47ce2 Mon Sep 17 00:00:00 2001
From: workaholicpanda <>
Date: Sat, 18 Sep 2021 21:02:42 +0300
Subject: [PATCH 80/80] fix: checking RadioItems and Checklist to accept new
propTypes added in tests
---
...opdown_radioitems_checklist_shorthands.py} | 36 +++++++++++++++++--
1 file changed, 33 insertions(+), 3 deletions(-)
rename components/dash-core-components/tests/integration/dropdown/{test_dropdown_shorthands.py => test_dropdown_radioitems_checklist_shorthands.py} (54%)
diff --git a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py b/components/dash-core-components/tests/integration/dropdown/test_dropdown_radioitems_checklist_shorthands.py
similarity index 54%
rename from components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
rename to components/dash-core-components/tests/integration/dropdown/test_dropdown_radioitems_checklist_shorthands.py
index bd0fc622bd..12257072fa 100644
--- a/components/dash-core-components/tests/integration/dropdown/test_dropdown_shorthands.py
+++ b/components/dash-core-components/tests/integration/dropdown/test_dropdown_radioitems_checklist_shorthands.py
@@ -1,7 +1,7 @@
from dash import Dash, dcc, html
-def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
+def test_ddsh001_test_dropdown_radioitems_checklist_shorthands(dash_dcc):
app = Dash(__name__)
TEST_OPTIONS_N_VALUES = [
@@ -42,11 +42,41 @@ def test_ddsh001_dropdown_shorthand_properties(dash_dcc):
for definition in TEST_OPTIONS_N_VALUES:
(option, value) = definition if len(definition) > 1 else [definition[0], None]
layout.extend(
- [html.Div(f"Options={option}, Value={value}"), dcc.Dropdown(option, value)]
+ [
+ html.Div(
+ [
+ html.Div(
+ f"Options={option}, Value={value}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Dropdown(option, value),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"Options={option}, Value={value}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.RadioItems(option, value=value),
+ ]
+ ),
+ html.Div(
+ [
+ html.Div(
+ f"Options={option}, Value={value}",
+ style={"marginBottom": 15, "marginTop": 25},
+ ),
+ dcc.Checklist(option, value=[value]),
+ ]
+ ),
+ ]
)
app.layout = html.Div(layout)
dash_dcc.start_server(app)
dash_dcc.wait_for_element(".dash-dropdown")
- dash_dcc.percy_snapshot("ddsh001 - test_ddsh001_dropdown_shorthand_properties")
+ dash_dcc.percy_snapshot(
+ "ddsh001 - test_ddsh001_test_dropdown_radioitems_checklist_shorthands"
+ )