Show progress bar for fetchData()
This will allow to show users that data loading is still in progress for slow connections. Partial-Bug: #1549744 Change-Id: Ic1fc8e5da324c4ece3bac63045eb32b37b163c7a
This commit is contained in:
parent
10c845b1bd
commit
cadf1c78ee
|
@ -21,6 +21,7 @@ import Backbone from 'backbone';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import models from 'models';
|
import models from 'models';
|
||||||
|
import dispatcher from 'dispatcher';
|
||||||
import {NailgunUnavailabilityDialog} from 'views/dialogs';
|
import {NailgunUnavailabilityDialog} from 'views/dialogs';
|
||||||
import KeystoneClient from 'keystone_client';
|
import KeystoneClient from 'keystone_client';
|
||||||
import RootComponent from 'views/root';
|
import RootComponent from 'views/root';
|
||||||
|
@ -217,11 +218,13 @@ class App {
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPage(Page, options = []) {
|
loadPage(Page, options = []) {
|
||||||
|
dispatcher.trigger('pageLoadStarted');
|
||||||
return (Page.fetchData ? Page.fetchData(...options) : $.Deferred().resolve())
|
return (Page.fetchData ? Page.fetchData(...options) : $.Deferred().resolve())
|
||||||
.done((pageOptions) => {
|
.done((pageOptions) => {
|
||||||
if (!this.rootComponent) this.renderLayout();
|
if (!this.rootComponent) this.renderLayout();
|
||||||
this.setPage(Page, pageOptions);
|
this.setPage(Page, pageOptions);
|
||||||
});
|
})
|
||||||
|
.always(() => dispatcher.trigger('pageLoadFinished'));
|
||||||
}
|
}
|
||||||
|
|
||||||
setPage(Page, options) {
|
setPage(Page, options) {
|
||||||
|
|
|
@ -905,6 +905,25 @@ input[type=range] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-load-progress {
|
||||||
|
position: absolute;
|
||||||
|
height: 5px;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 40;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.2s linear 0.2s;
|
||||||
|
.page-load-progress-bar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: @navbar-color-hover;
|
||||||
|
box-shadow: 0 0 8px @navbar-color-hover;
|
||||||
|
transition: width 0.35s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BREADCRUMBS
|
// BREADCRUMBS
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
|
|
|
@ -373,6 +373,54 @@ export var Footer = React.createClass({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export var PageLoadProgressBar = React.createClass({
|
||||||
|
mixins: [
|
||||||
|
dispatcherMixin('pageLoadStarted', 'showProgressBar'),
|
||||||
|
dispatcherMixin('pageLoadFinished', 'hideProgressBar')
|
||||||
|
],
|
||||||
|
getDefaultProps() {
|
||||||
|
return {
|
||||||
|
initialProgress: 10,
|
||||||
|
maxProgress: 94,
|
||||||
|
progressStep: 2,
|
||||||
|
stepDelay: 300
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
progress: this.props.initialProgress
|
||||||
|
};
|
||||||
|
},
|
||||||
|
showProgressBar() {
|
||||||
|
this.setState({progress: this.props.initialProgress, visible: true});
|
||||||
|
this.activeInterval = setInterval(() => {
|
||||||
|
if (this.state.progress < this.props.maxProgress) {
|
||||||
|
this.setState({progress: this.state.progress + this.props.progressStep});
|
||||||
|
}
|
||||||
|
}, this.props.stepDelay);
|
||||||
|
},
|
||||||
|
hideProgressBar() {
|
||||||
|
clearInterval(this.activeInterval);
|
||||||
|
this.setState({progress: 100, visible: false}, () => {
|
||||||
|
setTimeout(() => this.setState({progress: this.props.initialProgress}), 400);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
componentWillUnmount() {
|
||||||
|
clearInterval(this.activeInterval);
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className='page-load-progress' style={{opacity: this.state.visible ? 1 : 0}}>
|
||||||
|
<div
|
||||||
|
className='page-load-progress-bar'
|
||||||
|
style={{width: this.state.progress + '%'}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export var Breadcrumbs = React.createClass({
|
export var Breadcrumbs = React.createClass({
|
||||||
mixins: [
|
mixins: [
|
||||||
dispatcherMixin('updatePageLayout', 'refresh')
|
dispatcherMixin('updatePageLayout', 'refresh')
|
||||||
|
|
|
@ -20,7 +20,9 @@ import React from 'react';
|
||||||
import dispatcher from 'dispatcher';
|
import dispatcher from 'dispatcher';
|
||||||
import utils from 'utils';
|
import utils from 'utils';
|
||||||
import {dispatcherMixin} from 'component_mixins';
|
import {dispatcherMixin} from 'component_mixins';
|
||||||
import {Navbar, Breadcrumbs, DefaultPasswordWarning, BootstrapError, Footer} from 'views/layout';
|
import {
|
||||||
|
Navbar, Breadcrumbs, PageLoadProgressBar, DefaultPasswordWarning, BootstrapError, Footer
|
||||||
|
} from 'views/layout';
|
||||||
import {DragDropContext} from 'react-dnd';
|
import {DragDropContext} from 'react-dnd';
|
||||||
import HTML5Backend from 'react-dnd-html5-backend';
|
import HTML5Backend from 'react-dnd-html5-backend';
|
||||||
|
|
||||||
|
@ -68,6 +70,7 @@ var RootComponent = React.createClass({
|
||||||
<div id='content-wrapper'>
|
<div id='content-wrapper'>
|
||||||
<div className={utils.classNames(layoutClasses)}>
|
<div className={utils.classNames(layoutClasses)}>
|
||||||
{!Page.hiddenLayout && [
|
{!Page.hiddenLayout && [
|
||||||
|
<PageLoadProgressBar key='page-load-progress' />,
|
||||||
<Navbar
|
<Navbar
|
||||||
key='navbar'
|
key='navbar'
|
||||||
ref='navbar'
|
ref='navbar'
|
||||||
|
|
Loading…
Reference in New Issue