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 (