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

Commit afcab48

Browse files
Async components (#692)
1 parent 10aa10e commit afcab48

18 files changed

+753
-597
lines changed

CHANGELOG.md

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

55
## [Unreleased]
6+
### Added
7+
- [#692](https://github.com/plotly/dash-core-components/pull/692) Async DatePickerSingle, DatePickerRange, Dropdown, Markdown, Upload components
8+
69
### Updated
710
- [#693](https://github.com/plotly/dash-core-components/pull/693) Upgraded plotly.js to 1.51.1
811
- [Feature release 1.51.0](https://github.com/plotly/plotly.js/releases/tag/v1.51.0) which contains:

dash_core_components_base/__init__.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,37 @@
3939

4040
_this_module = _sys.modules[__name__]
4141

42-
_js_dist = [
42+
async_resources = [
43+
'datepicker',
44+
'dropdown',
45+
'graph',
46+
'markdown',
47+
'upload'
48+
]
49+
50+
_js_dist = []
51+
52+
_js_dist.extend([{
53+
'relative_package_path': 'async~{}.js'.format(async_resource),
54+
'external_url': (
55+
'https://unpkg.com/dash-core-components@{}'
56+
'/dash_core_components/async~{}.js'
57+
).format(__version__, async_resource),
58+
'namespace': 'dash_core_components',
59+
'async': True
60+
} for async_resource in async_resources])
61+
62+
_js_dist.extend([{
63+
'relative_package_path': 'async~{}.js.map'.format(async_resource),
64+
'external_url': (
65+
'https://unpkg.com/dash-core-components@{}'
66+
'/dash_core_components/async~{}.js.map'
67+
).format(__version__, async_resource),
68+
'namespace': 'dash_core_components',
69+
'dynamic': True
70+
} for async_resource in async_resources])
71+
72+
_js_dist.extend([
4373
{
4474
'relative_package_path': 'highlight.pack.js',
4575
'namespace': 'dash_core_components'
@@ -106,7 +136,7 @@
106136
'namespace': 'dash_core_components',
107137
'dynamic': True
108138
},
109-
]
139+
])
110140

111141
for _component in __all__:
112142
setattr(locals()[_component], '_js_dist', _js_dist)

src/components/DatePickerRange.react.js

Lines changed: 9 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import 'react-dates/initialize';
2-
import {DateRangePicker} from 'react-dates';
31
import PropTypes from 'prop-types';
4-
import React, {Component} from 'react';
5-
import uniqid from 'uniqid';
2+
import React, {Component, lazy, Suspense} from 'react';
3+
import LazyLoader from '../utils/LazyLoader';
64

7-
import convertToMoment from '../utils/convertToMoment';
5+
const RealDatePickerRange = lazy(LazyLoader.datePickerRange);
86

97
/**
108
* DatePickerRange is a tailor made component designed for selecting
@@ -18,176 +16,11 @@ import convertToMoment from '../utils/convertToMoment';
1816
* which can be found here: https://github.com/airbnb/react-dates
1917
*/
2018
export default class DatePickerRange extends Component {
21-
constructor(props) {
22-
super(props);
23-
this.propsToState = this.propsToState.bind(this);
24-
this.onDatesChange = this.onDatesChange.bind(this);
25-
this.isOutsideRange = this.isOutsideRange.bind(this);
26-
this.state = {
27-
focused: false,
28-
start_date_id: props.start_date_id || uniqid(),
29-
end_date_id: props.end_date_id || uniqid(),
30-
};
31-
}
32-
33-
propsToState(newProps) {
34-
this.setState({
35-
start_date: newProps.start_date,
36-
end_date: newProps.end_date,
37-
});
38-
}
39-
40-
componentWillReceiveProps(newProps) {
41-
this.propsToState(newProps);
42-
}
43-
44-
componentWillMount() {
45-
this.propsToState(this.props);
46-
}
47-
48-
onDatesChange({startDate: start_date, endDate: end_date}) {
49-
const {setProps, updatemode, clearable} = this.props;
50-
51-
const oldMomentDates = convertToMoment(this.state, [
52-
'start_date',
53-
'end_date',
54-
]);
55-
56-
if (start_date && !start_date.isSame(oldMomentDates.start_date)) {
57-
if (updatemode === 'singledate') {
58-
setProps({start_date: start_date.format('YYYY-MM-DD')});
59-
} else {
60-
this.setState({start_date: start_date.format('YYYY-MM-DD')});
61-
}
62-
}
63-
64-
if (end_date && !end_date.isSame(oldMomentDates.end_date)) {
65-
if (updatemode === 'singledate') {
66-
setProps({end_date: end_date.format('YYYY-MM-DD')});
67-
} else if (updatemode === 'bothdates') {
68-
setProps({
69-
start_date: this.state.start_date,
70-
end_date: end_date.format('YYYY-MM-DD'),
71-
});
72-
}
73-
}
74-
75-
if (
76-
clearable &&
77-
!start_date &&
78-
!end_date &&
79-
(oldMomentDates.start_date !== start_date ||
80-
oldMomentDates.end_date !== end_date)
81-
) {
82-
setProps({start_date: null, end_date: null});
83-
}
84-
}
85-
86-
isOutsideRange(date) {
87-
const {min_date_allowed, max_date_allowed} = this.props;
88-
89-
return (
90-
(min_date_allowed && date.isBefore(min_date_allowed)) ||
91-
(max_date_allowed && date.isAfter(max_date_allowed))
92-
);
93-
}
94-
9519
render() {
96-
const {focusedInput} = this.state;
97-
98-
const {
99-
calendar_orientation,
100-
clearable,
101-
day_size,
102-
disabled,
103-
display_format,
104-
end_date_placeholder_text,
105-
first_day_of_week,
106-
is_RTL,
107-
minimum_nights,
108-
month_format,
109-
number_of_months_shown,
110-
reopen_calendar_on_clear,
111-
show_outside_days,
112-
start_date_placeholder_text,
113-
stay_open_on_select,
114-
with_full_screen_portal,
115-
with_portal,
116-
loading_state,
117-
id,
118-
style,
119-
className,
120-
start_date_id,
121-
end_date_id,
122-
} = this.props;
123-
124-
const {initial_visible_month} = convertToMoment(this.props, [
125-
'initial_visible_month',
126-
]);
127-
128-
const {start_date, end_date} = convertToMoment(this.state, [
129-
'start_date',
130-
'end_date',
131-
]);
132-
const verticalFlag = calendar_orientation !== 'vertical';
133-
134-
const DatePickerWrapperStyles = {
135-
position: 'relative',
136-
display: 'inline-block',
137-
...style,
138-
};
139-
14020
return (
141-
<div
142-
id={id}
143-
style={DatePickerWrapperStyles}
144-
className={className}
145-
data-dash-is-loading={
146-
(loading_state && loading_state.is_loading) || undefined
147-
}
148-
>
149-
<DateRangePicker
150-
daySize={day_size}
151-
disabled={disabled}
152-
displayFormat={display_format}
153-
enableOutsideDays={show_outside_days}
154-
endDate={end_date}
155-
endDatePlaceholderText={end_date_placeholder_text}
156-
firstDayOfWeek={first_day_of_week}
157-
focusedInput={focusedInput}
158-
initialVisibleMonth={() => {
159-
if (initial_visible_month) {
160-
return initial_visible_month;
161-
} else if (end_date && focusedInput === 'endDate') {
162-
return end_date;
163-
} else if (start_date && focusedInput === 'startDate') {
164-
return start_date;
165-
}
166-
return start_date;
167-
}}
168-
isOutsideRange={this.isOutsideRange}
169-
isRTL={is_RTL}
170-
keepOpenOnDateSelect={stay_open_on_select}
171-
minimumNights={minimum_nights}
172-
monthFormat={month_format}
173-
numberOfMonths={number_of_months_shown}
174-
onDatesChange={this.onDatesChange}
175-
onFocusChange={focusedInput =>
176-
this.setState({focusedInput})
177-
}
178-
orientation={calendar_orientation}
179-
reopenPickerOnClearDates={reopen_calendar_on_clear}
180-
showClearDates={clearable}
181-
startDate={start_date}
182-
startDatePlaceholderText={start_date_placeholder_text}
183-
withFullScreenPortal={
184-
with_full_screen_portal && verticalFlag
185-
}
186-
withPortal={with_portal && verticalFlag}
187-
startDateId={start_date_id || this.state.start_date_id}
188-
endDateId={end_date_id || this.state.end_date_id}
189-
/>
190-
</div>
21+
<Suspense fallback={null}>
22+
<RealDatePickerRange {...this.props} />
23+
</Suspense>
19124
);
19225
}
19326
}
@@ -446,3 +279,6 @@ DatePickerRange.defaultProps = {
446279
persisted_props: ['start_date', 'end_date'],
447280
persistence_type: 'local',
448281
};
282+
283+
export const propTypes = DatePickerRange.propTypes;
284+
export const defaultProps = DatePickerRange.defaultProps;

src/components/DatePickerSingle.react.js

Lines changed: 9 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import 'react-dates/initialize';
2-
3-
import {SingleDatePicker} from 'react-dates';
4-
import moment from 'moment';
51
import PropTypes from 'prop-types';
6-
import React, {Component} from 'react';
2+
import React, {Component, lazy, Suspense} from 'react';
3+
import LazyLoader from '../utils/LazyLoader';
74

8-
import convertToMoment from '../utils/convertToMoment';
5+
const RealDateSingleRange = lazy(LazyLoader.datePickerSingle);
96

107
/**
118
* DatePickerSingle is a tailor made component designed for selecting
@@ -18,108 +15,12 @@ import convertToMoment from '../utils/convertToMoment';
1815
* This component is based off of Airbnb's react-dates react component
1916
* which can be found here: https://github.com/airbnb/react-dates
2017
*/
21-
2218
export default class DatePickerSingle extends Component {
23-
constructor() {
24-
super();
25-
this.isOutsideRange = this.isOutsideRange.bind(this);
26-
this.onDateChange = this.onDateChange.bind(this);
27-
this.state = {focused: false};
28-
}
29-
30-
isOutsideRange(date) {
31-
const {max_date_allowed, min_date_allowed} = convertToMoment(
32-
this.props,
33-
['max_date_allowed', 'min_date_allowed']
34-
);
35-
36-
return (
37-
(min_date_allowed && date.isBefore(min_date_allowed)) ||
38-
(max_date_allowed && date.isAfter(max_date_allowed))
39-
);
40-
}
41-
42-
onDateChange(date) {
43-
const {setProps} = this.props;
44-
const payload = {date: date ? date.format('YYYY-MM-DD') : null};
45-
setProps(payload);
46-
}
47-
4819
render() {
49-
const {focused} = this.state;
50-
51-
const {
52-
calendar_orientation,
53-
clearable,
54-
day_size,
55-
disabled,
56-
display_format,
57-
first_day_of_week,
58-
is_RTL,
59-
month_format,
60-
number_of_months_shown,
61-
placeholder,
62-
reopen_calendar_on_clear,
63-
show_outside_days,
64-
stay_open_on_select,
65-
with_full_screen_portal,
66-
with_portal,
67-
loading_state,
68-
id,
69-
style,
70-
className,
71-
} = this.props;
72-
73-
const {date, initial_visible_month} = convertToMoment(this.props, [
74-
'date',
75-
'initial_visible_month',
76-
]);
77-
78-
const verticalFlag = calendar_orientation !== 'vertical';
79-
80-
const DatePickerWrapperStyles = {
81-
position: 'relative',
82-
display: 'inline-block',
83-
...style,
84-
};
85-
8620
return (
87-
<div
88-
id={id}
89-
style={DatePickerWrapperStyles}
90-
className={className}
91-
data-dash-is-loading={
92-
(loading_state && loading_state.is_loading) || undefined
93-
}
94-
>
95-
<SingleDatePicker
96-
date={date}
97-
onDateChange={this.onDateChange}
98-
focused={focused}
99-
onFocusChange={({focused}) => this.setState({focused})}
100-
initialVisibleMonth={() =>
101-
date || initial_visible_month || moment()
102-
}
103-
isOutsideRange={this.isOutsideRange}
104-
numberOfMonths={number_of_months_shown}
105-
withPortal={with_portal && verticalFlag}
106-
withFullScreenPortal={
107-
with_full_screen_portal && verticalFlag
108-
}
109-
firstDayOfWeek={first_day_of_week}
110-
enableOutsideDays={show_outside_days}
111-
monthFormat={month_format}
112-
displayFormat={display_format}
113-
placeholder={placeholder}
114-
showClearDate={clearable}
115-
disabled={disabled}
116-
keepOpenOnDateSelect={stay_open_on_select}
117-
reopenPickerOnClearDate={reopen_calendar_on_clear}
118-
isRTL={is_RTL}
119-
orientation={calendar_orientation}
120-
daySize={day_size}
121-
/>
122-
</div>
21+
<Suspense fallback={null}>
22+
<RealDateSingleRange {...this.props} />
23+
</Suspense>
12324
);
12425
}
12526
}
@@ -335,3 +236,6 @@ DatePickerSingle.defaultProps = {
335236
persisted_props: ['date'],
336237
persistence_type: 'local',
337238
};
239+
240+
export const propTypes = DatePickerSingle.propTypes;
241+
export const defaultProps = DatePickerSingle.defaultProps;

0 commit comments

Comments
 (0)