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

Ensure that components are still in the DOM when they are loading. #740

Merged
merged 28 commits into from
Apr 9, 2020
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8e181d7
Ensure that components are still in the DOM when they are loading.
Jan 22, 2020
73db3ca
Define style prop for spinners as object and not bool.
Jan 22, 2020
377004b
Fix CSS property names.
Jan 22, 2020
a09a508
Merge branch 'dev' into 674-map-uirevision
Jan 22, 2020
284c3a3
Update loading component tests.
Jan 23, 2020
a90af15
Merge branch 'dev' into 674-map-uirevision
Feb 3, 2020
ceff132
Merge branch 'dev' into 674-map-uirevision
Feb 4, 2020
6167e15
Merge branch 'dev' into 674-map-uirevision
Marc-Andre-Rivet Mar 2, 2020
bfe6d15
Fix test name.
shammamah-zz Mar 3, 2020
8dc4529
Lock circleci python versions.
shammamah-zz Mar 3, 2020
1ead9bc
Merge branch 'dev' into 674-map-uirevision
Mar 5, 2020
ef5d193
Merge branch 'dev' into 674-map-uirevision
Mar 10, 2020
1cb8da3
Update CHANGELOG.
Mar 10, 2020
49fc1ea
Merge branch 'dev' into 674-map-uirevision
alexcjohnson Apr 9, 2020
f985ece
revert python version lock on CI
alexcjohnson Apr 9, 2020
01425ff
pyest.ini - mainly to speed up test discovery with `testpaths`
alexcjohnson Apr 9, 2020
6d398a2
extend --pause option to dashdcc fixture
alexcjohnson Apr 9, 2020
aa4fce7
fix typo in test_graph_basics that somehow we didn't care about before
alexcjohnson Apr 9, 2020
600a09f
more consistent structure for Loading component
alexcjohnson Apr 9, 2020
386137e
robustify store test
alexcjohnson Apr 9, 2020
22a1975
port loading component tests to dash.testing - without fixing them
alexcjohnson Apr 9, 2020
2bfaa28
update loading component tests for new class usage
alexcjohnson Apr 9, 2020
8bf9fbf
black test_loading_component
alexcjohnson Apr 9, 2020
26c6533
test that children retain identity inside loading components
alexcjohnson Apr 9, 2020
a80f0db
Update CHANGELOG.md
alexcjohnson Apr 9, 2020
4fc809a
include computed visibility in the loading/graph test
alexcjohnson Apr 9, 2020
fb15aa9
Merge branch '674-map-uirevision' of github.com:plotly/dash-core-comp…
alexcjohnson Apr 9, 2020
2b41ea0
robustify store test_data_lifecycle
alexcjohnson Apr 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Changed
- [#740](https://github.com/plotly/dash-core-components/pull/740) Keep components that are loading in the DOM, but not visible, as opposed to removing them entirely. This will ensure that the size of the component's container does not shrink or expand when the component goes into the loading state.

### Fixed
- [#740](https://github.com/plotly/dash-core-components/pull/740) Fixed bug in which mapbox `uirevision` was not behaving when inside a `dcc.Loading` component

## [1.9.0] - 2020-04-01
### Changed
- [#766](https://github.com/plotly/dash-core-components/pull/766) Update from React 16.8.6 to 16.13.0
Expand Down
5 changes: 5 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[pytest]
testpaths = tests/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having this line cuts test discovery time locally from ~10 seconds to <1sec - particularly nice when calling pytest -k ...

I didn't pay attention to the other lines, just copied from dash

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

addopts = -rsxX -vv
log_format = %(asctime)s | %(levelname)s | %(name)s:%(lineno)d | %(message)s
log_cli_level = ERROR
67 changes: 40 additions & 27 deletions src/components/Loading.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import DefaultSpinner from '../fragments/Loading/spinners/DefaultSpinner.jsx';
import CubeSpinner from '../fragments/Loading/spinners/CubeSpinner.jsx';
import CircleSpinner from '../fragments/Loading/spinners/CircleSpinner.jsx';
import DotSpinner from '../fragments/Loading/spinners/DotSpinner.jsx';
import {type} from 'ramda';

function getSpinner(spinnerType) {
switch (spinnerType) {
Expand All @@ -22,6 +21,19 @@ function getSpinner(spinnerType) {
}
}

const hiddenContainer = {visibility: 'hidden', position: 'relative'};

const coveringSpinner = {
visibility: 'visible',
position: 'absolute',
top: '0',
height: '100%',
width: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
};

/**
* A Loading component that wraps any other component and displays a spinner until the wrapped component has rendered.
*/
Expand All @@ -37,27 +49,26 @@ export default class Loading extends Component {
type: spinnerType,
} = this.props;

if (loading_state && loading_state.is_loading) {
const Spinner = getSpinner(spinnerType);
return (
<Spinner
className={className}
style={style}
status={loading_state}
color={color}
debug={debug}
fullscreen={fullscreen}
/>
);
}

if (
type(this.props.children) !== 'Object' ||
type(this.props.children) !== 'Function'
) {
return <div className={className}>{this.props.children}</div>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this part, right? Agreed, it isn't clear to me why this was there.

}
return this.props.children;
const isLoading = loading_state && loading_state.is_loading;
const Spinner = isLoading && getSpinner(spinnerType);

return (
<div style={isLoading ? hiddenContainer : {}}>
{this.props.children}
<div style={isLoading ? coveringSpinner : {}}>
{isLoading && (
<Spinner
className={className}
style={style}
status={loading_state}
color={color}
debug={debug}
fullscreen={fullscreen}
/>
)}
</div>
</div>
);
}
}

Expand Down Expand Up @@ -85,27 +96,29 @@ Loading.propTypes = {
]),

/**
* Property that determines which spinner to show - one of 'graph', 'cube', 'circle', 'dot', or 'default'.
* Property that determines which spinner to show
* one of 'graph', 'cube', 'circle', 'dot', or 'default'.
*/
type: PropTypes.oneOf(['graph', 'cube', 'circle', 'dot', 'default']),

/**
* Boolean that determines if the loading spinner will be displayed full-screen or not
* Boolean that makes the spinner display full-screen
*/
fullscreen: PropTypes.bool,

/**
* Boolean that determines if the loading spinner will display the status.prop_name and component_name
* If true, the spinner will display the component_name and prop_name
* while loading
*/
debug: PropTypes.bool,

/**
* Additional CSS class for the root DOM node
* Additional CSS class for the spinner root DOM node
*/
className: PropTypes.string,

/**
* Additional CSS styling for the root DOM node
* Additional CSS styling for the spinner root DOM node
*/
style: PropTypes.object,

Expand Down
2 changes: 1 addition & 1 deletion src/fragments/Loading/spinners/CircleSpinner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ CircleSpinner.propTypes = {
color: PropTypes.string,
className: PropTypes.string,
fullscreen: PropTypes.bool,
style: PropTypes.bool,
style: PropTypes.object,
debug: PropTypes.bool,
};

Expand Down
2 changes: 1 addition & 1 deletion src/fragments/Loading/spinners/CubeSpinner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ CubeSpinner.propTypes = {
color: PropTypes.string,
className: PropTypes.string,
fullscreen: PropTypes.bool,
style: PropTypes.bool,
style: PropTypes.object,
debug: PropTypes.bool,
};

Expand Down
2 changes: 1 addition & 1 deletion src/fragments/Loading/spinners/DefaultSpinner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ DefaultSpinner.propTypes = {
color: PropTypes.string,
className: PropTypes.string,
fullscreen: PropTypes.bool,
style: PropTypes.bool,
style: PropTypes.object,
debug: PropTypes.bool,
};

Expand Down
2 changes: 1 addition & 1 deletion src/fragments/Loading/spinners/DotSpinner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ DotSpinner.propTypes = {
color: PropTypes.string,
className: PropTypes.string,
fullscreen: PropTypes.bool,
style: PropTypes.bool,
style: PropTypes.object,
debug: PropTypes.bool,
};

Expand Down
2 changes: 1 addition & 1 deletion src/fragments/Loading/spinners/GraphSpinner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ GraphSpinner.propTypes = {
color: PropTypes.string,
className: PropTypes.string,
fullscreen: PropTypes.bool,
style: PropTypes.bool,
style: PropTypes.object,
debug: PropTypes.bool,
};

Expand Down
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ def dash_dcc(request, dash_thread_server, tmpdir):
download_path=tmpdir.mkdir("download").strpath,
percy_assets_root=request.config.getoption("percy_assets"),
percy_finalize=request.config.getoption("nopercyfinalize"),
pause=request.config.getoption("pause"),
) as dc:
yield dc
4 changes: 2 additions & 2 deletions tests/integration/graph/test_graph_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ def selected_df_figure(selection):


@pytest.mark.DCC672
def test_grbs002_graph_wrapped_in_loading_component_does_not_fail(dash_dcc):
def test_grbs003_graph_wrapped_in_loading_component_does_not_fail(dash_dcc):
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div([
html.H1('subplot issue'),
dcc.Location(id='url', refresh=False),
dcc.Loading(id="page-content")
])

@app.callback(Output('page-content', 'children'), [Input('url', 'value')])
@app.callback(Output('page-content', 'children'), [Input('url', 'pathname')])
def render_page(url):
return [
dcc.Dropdown(
Expand Down
Loading