-
Notifications
You must be signed in to change notification settings - Fork 33
Loading states api #93
Changes from 23 commits
762b0ba
1fb8376
5940bb4
5bf3d30
a571882
1777a94
1af20c9
4ddc4b7
02e992a
6acc394
3264f4b
a51dcf9
d38fec9
96aebf4
72b579d
8d5e4af
95ed504
e1917bf
cfe4c40
6c34ac9
2153923
e48348b
48e0dd4
4b43a54
8f1cc81
05955ea
807d6bc
bf97e2b
99ef59a
cd4a507
c9f28d2
08c4646
622e912
91e0a25
75592f7
b7f3770
8c0771b
a2220fb
461d515
a0ed549
f692a8d
a1a4531
e1fb848
8fb0bda
8751dd4
94b9259
0850d4b
763c5bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,171 @@ | ||
from dash import Dash | ||
# -*- coding: utf-8 -*- | ||
import dash | ||
import dash_html_components as html | ||
import dash_core_components as dcc | ||
import plotly.graph_objs as go | ||
import time | ||
|
||
app = Dash(__name__) | ||
app.scripts.config.serve_locally=True | ||
app.layout = html.Div([ | ||
dcc.Input(id='my-input', value='initial-input'), | ||
html.Div(id='my-output') | ||
]) | ||
from dash.dependencies import Input, Output, State | ||
|
||
external_stylesheets = ["https://unpkg.com/[email protected]/css/tachyons.min.css"] | ||
|
||
@app.callback( | ||
dash.dependencies.Output('my-output', 'children'), | ||
[dash.dependencies.Input('my-input', 'value')] | ||
) | ||
def update(value): | ||
return 'Output: {}'.format(value) | ||
app = dash.Dash(__name__, external_stylesheets=external_stylesheets) | ||
|
||
card_style = { | ||
"box-shadow": "0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.3)" | ||
} | ||
|
||
if __name__ == '__main__': | ||
card_style_greyed = { | ||
"box-shadow": "0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.3)", | ||
"backgroundColor": "#e0e0e0", | ||
} | ||
|
||
app.scripts.config.serve_locally = True | ||
|
||
app.layout = dcc.Loading(children=[html.Div( | ||
className="sans-serif", | ||
children=[ | ||
html.Div( | ||
[ | ||
html.H1( | ||
className="tc f1 hot-pink mv6", children=["Dash Loading States API"] | ||
) | ||
] | ||
), | ||
html.Div( | ||
className="w-60 center pt4", | ||
children=[ | ||
dcc.Tabs( | ||
id="tabs", | ||
value="tab-1", | ||
children=[ | ||
dcc.Tab(label="Normal Graph", value="tab-1", style={'backgroundColor': '#f5f5f5'}), | ||
dcc.Tab(label="Funky Graph", value="tab-2", style={'backgroundColor': '#f5f5f5'}), | ||
], | ||
colors={ | ||
"primary": "white", | ||
"background": "white", | ||
"border": "#d2d2d2", | ||
}, | ||
parent_style=card_style, | ||
), | ||
html.Div( | ||
style={ | ||
"border": "1px solid #d2d2d2", | ||
"borderTop": "none", | ||
"paddingTop": "32px", | ||
"box-shadow": "0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.3)", | ||
"marginTop": "32px", | ||
"height": "498px" | ||
}, | ||
children=[ | ||
dcc.Loading(id='tabs-content', type='graph') | ||
] | ||
), | ||
], | ||
style={}, | ||
), | ||
html.Div( | ||
className="w-80 center", | ||
children=[ | ||
dcc.Loading(id='output-1') | ||
], | ||
), | ||
html.Div( | ||
className="w-80 center", | ||
children=[ | ||
dcc.Input( | ||
className="db center mv4 ph2 pv1", id="input-1", value="Type here!" | ||
) | ||
], | ||
), | ||
], | ||
)], type='cube', fullscreen=True) | ||
|
||
|
||
@app.callback(Output('tabs-content', 'children'), | ||
[Input('tabs', 'value')]) | ||
def render_content(tab): | ||
time.sleep(2) | ||
if tab == 'tab-1': | ||
return html.Div(id='loading-1', children=[ | ||
dcc.Graph( | ||
id='graph-2-tabs', | ||
figure=go.Figure( | ||
data=[ | ||
go.Bar( | ||
x=[1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, | ||
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012], | ||
y=[219, 146, 112, 127, 124, 180, 236, 207, 236, 263, | ||
350, 430, 474, 526, 488, 537, 500, 439], | ||
name='Rest of world', | ||
marker=go.bar.Marker( | ||
color='rgb(55, 83, 109)' | ||
) | ||
), | ||
go.Bar( | ||
x=[1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, | ||
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012], | ||
y=[16, 13, 10, 11, 28, 37, 43, 55, 56, 88, 105, 156, 270, | ||
299, 340, 403, 549, 499], | ||
name='China', | ||
marker=go.bar.Marker( | ||
color='rgb(26, 118, 255)' | ||
) | ||
) | ||
], | ||
layout=go.Layout( | ||
title='US Export of Plastic Scrap', | ||
showlegend=True, | ||
legend=go.layout.Legend( | ||
x=0, | ||
y=1.0 | ||
), | ||
margin=go.layout.Margin(l=40, r=0, t=40, b=30) | ||
) | ||
), | ||
) | ||
]) | ||
elif tab == 'tab-2': | ||
return html.Div(id='loading-2', children=[ | ||
dcc.Graph( | ||
id='graph-1-tabs', | ||
figure=go.Figure( | ||
data=[ | ||
go.Bar( | ||
x=[1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, | ||
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012], | ||
y=[219, 146, 112, 127, 124, 180, 236, 207, 236, 263, | ||
350, 430, 474, 526, 488, 537, 500, 439], | ||
name='Rest of world', | ||
marker=go.bar.Marker( | ||
color='hotpink' | ||
) | ||
), | ||
go.Bar( | ||
x=[1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, | ||
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012], | ||
y=[16, 13, 10, 11, 28, 37, 43, 55, 56, 88, 105, 156, 270, | ||
299, 340, 403, 549, 499], | ||
name='China', | ||
marker=go.bar.Marker( | ||
color='gold' | ||
) | ||
) | ||
], | ||
layout=go.Layout( | ||
title='US Export of Plastic Scrap', | ||
showlegend=True, | ||
legend=go.layout.Legend( | ||
x=0, | ||
y=1.0 | ||
), | ||
margin=go.layout.Margin(l=40, r=0, t=40, b=30) | ||
) | ||
), | ||
) | ||
]) | ||
|
||
|
||
if __name__ == "__main__": | ||
app.run_server(debug=True) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,21 +12,26 @@ export default class TreeContainer extends Component { | |
} | ||
|
||
render() { | ||
return render(this.props.layout); | ||
return recursivelyRender(this.props.layout, this.props.loading); | ||
} | ||
} | ||
|
||
TreeContainer.propTypes = { | ||
layout: PropTypes.object, | ||
loading: PropTypes.bool | ||
}; | ||
|
||
function render(component) { | ||
function recursivelyRender(component, loading = false) { | ||
if ( | ||
R.contains(R.type(component), ['String', 'Number', 'Null', 'Boolean']) | ||
) { | ||
return component; | ||
} | ||
|
||
if(R.isEmpty(component)) { | ||
return null; | ||
} | ||
|
||
// Create list of child elements | ||
let children; | ||
|
||
|
@@ -55,7 +60,9 @@ function render(component) { | |
children = (Array.isArray(componentProps.children) | ||
? componentProps.children | ||
: [componentProps.children] | ||
).map(render); | ||
).map(child => { | ||
return recursivelyRender(child, loading); | ||
}); | ||
} | ||
|
||
if (!component.type) { | ||
|
@@ -78,9 +85,9 @@ function render(component) { | |
...children | ||
); | ||
|
||
return <NotifyObservers id={componentProps.id}>{parent}</NotifyObservers>; | ||
return <NotifyObservers id={componentProps.id} loading={loading}>{parent}</NotifyObservers>; | ||
} | ||
|
||
render.propTypes = { | ||
recursivelyRender.propTypes = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🐱 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does 🐱 mean? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah never mind, I found this again 😸 |
||
children: PropTypes.object, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
import {connect} from 'react-redux'; | ||
import {isEmpty} from 'ramda'; | ||
import {contains, isEmpty} from 'ramda'; | ||
import {notifyObservers, updateProps} from '../../actions'; | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import {STATUS} from '../../constants/constants'; | ||
|
||
/* | ||
* NotifyObservers passes a connected `setProps` handler down to | ||
|
@@ -13,6 +14,7 @@ function mapStateToProps(state) { | |
return { | ||
dependencies: state.dependenciesRequest.content, | ||
paths: state.paths, | ||
requestQueue: state.requestQueue, | ||
}; | ||
} | ||
|
||
|
@@ -27,6 +29,8 @@ function mergeProps(stateProps, dispatchProps, ownProps) { | |
children: ownProps.children, | ||
dependencies: stateProps.dependencies, | ||
paths: stateProps.paths, | ||
loading: ownProps.loading, | ||
requestQueue: stateProps.requestQueue, | ||
|
||
fireEvent: function fireEvent({event}) { | ||
// Update this component's observers with the updated props | ||
|
@@ -56,9 +60,30 @@ function NotifyObserversComponent({ | |
|
||
dependencies, | ||
|
||
loading, | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why extra newlines at 60, 62, 64? |
||
fireEvent, | ||
setProps, | ||
requestQueue, | ||
}) { | ||
// loading prop coming from TreeContainer | ||
let isLoading = loading; | ||
let loadingProp; | ||
let loadingComponent; | ||
|
||
requestQueue.map(r => { | ||
if (r.status === 'loading' && contains(id, r.controllerId)) { | ||
isLoading = true; | ||
loadingComponent = r.controllerId.split('.')[0]; | ||
loadingProp = r.controllerId.split('.')[1]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can split only one time: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Had a hard time figuring this out, that is not a proper map. It should be a for loop or a filter or a find. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the most appropriate would be a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have been using |
||
} | ||
}); | ||
|
||
const thisRequest = requestQueue.filter(r => contains(id, r.controllerId)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The filter is here. |
||
if (thisRequest.status === STATUS.OK) { | ||
isLoading = false; | ||
} | ||
|
||
const thisComponentTriggersEvents = | ||
dependencies && | ||
dependencies.find(dependency => | ||
|
@@ -102,6 +127,13 @@ function NotifyObserversComponent({ | |
extraProps.fireEvent = fireEvent; | ||
} | ||
|
||
// Set loading state | ||
extraProps.loading_state = { | ||
is_loading: isLoading, | ||
prop_name: loadingProp, | ||
component_name: loadingComponent, | ||
}; | ||
|
||
if (!isEmpty(extraProps)) { | ||
return React.cloneElement(children, extraProps); | ||
} | ||
|
@@ -112,6 +144,7 @@ NotifyObserversComponent.propTypes = { | |
id: PropTypes.string.isRequired, | ||
children: PropTypes.node.isRequired, | ||
path: PropTypes.array.isRequired, | ||
loading: PropTypes.bool, | ||
}; | ||
|
||
export default connect( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,7 +51,7 @@ class Reloader extends React.Component { | |
) { | ||
// Look if it was a css file. | ||
let was_css = false; | ||
for (let a of reloadRequest.content.files) { | ||
for (const a of reloadRequest.content.files) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that is an error, make sure it works because I kinda remember putting const and it failed when there was multiple files. There can be multiple files if multiple assets files are saved at the same time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This must be some artifact from a merge with master, I haven't touched any of the reloading code as far as I remember. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't had a chance to rebase yet, because I'm still working on fixing the tests There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's prettier that changes it, I remember it changed it also when I ran it, maybe add an exclude here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still need to change this back. |
||
if (a.is_css) { | ||
was_css = true; | ||
const nodesToDisable = []; | ||
|
Uh oh!
There was an error while loading. Please reload this page.