Skip to content
Snippets Groups Projects
Unverified Commit db91f7c7 authored by Kyle Doherty's avatar Kyle Doherty
Browse files

loading cycling

parents 5dccb898 28c282d1
No related branches found
No related tags found
No related merge requests found
......@@ -7,15 +7,24 @@ import LoadingSpinner from "metabase/components/LoadingSpinner.jsx";
import cx from "classnames";
export default class LoadingAndErrorWrapper extends Component {
state = {
messageIndex: 0,
sceneIndex: 0,
}
static propTypes = {
className: PropTypes.string,
error: PropTypes.any,
loading: PropTypes.any,
noBackground: PropTypes.bool,
noWrapper: PropTypes.bool,
children: PropTypes.any,
style: PropTypes.object,
showSpinner: PropTypes.bool
className: PropTypes.string,
error: PropTypes.any,
loading: PropTypes.any,
noBackground: PropTypes.bool,
noWrapper: PropTypes.bool,
children: PropTypes.any,
style: PropTypes.object,
showSpinner: PropTypes.bool,
loadingMessages: PropTypes.array,
messageInterval: PropTypes.number,
loadingScenes: PropTypes.array
};
static defaultProps = {
......@@ -24,7 +33,9 @@ export default class LoadingAndErrorWrapper extends Component {
loading: false,
noBackground: false,
noWrapper: false,
showSpinner: true
showSpinner: true,
loadingMessages: ['Loading...'],
messageInterval: 6000,
};
getErrorMessage() {
......@@ -38,6 +49,29 @@ export default class LoadingAndErrorWrapper extends Component {
);
}
componentDidMount () {
const { loadingMessages, messageInterval } = this.props;
// only start cycling if multiple messages are provided
if(loadingMessages.length > 1) {
this.cycle = setInterval(this.loadingInterval, messageInterval)
}
}
componentWillUnmount () {
clearInterval(this.cycle)
}
loadingInterval = () => {
this.cycleLoadingMessage()
if(this.props.loadingScenes) {
this.cycleLoadingScenes()
}
}
cycleLoadingScenes = () => {
}
getChildren() {
function resolveChild(child) {
if (Array.isArray(child)) {
......@@ -51,11 +85,41 @@ export default class LoadingAndErrorWrapper extends Component {
return resolveChild(this.props.children);
}
cycleLoadingMessage = () => {
this.setState({
messageIndex: this.state.messageIndex + 1 < this.props.loadingMessages.length -1
? this.state.messageIndex + 1
: 0
})
}
cycleLoadingScenes = () => {
this.setState({
sceneIndex: this.state.sceneIndex + 1 < this.props.loadingScenes.length -1
? this.state.sceneIndex + 1
: 0
})
}
render() {
const { loading, error, noBackground, noWrapper, showSpinner } = this.props;
const contentClassName = cx("wrapper py4 text-brand text-centered flex-full flex flex-column layout-centered", {
"bg-white": !noBackground
});
const {
loading,
error,
noBackground,
noWrapper,
showSpinner,
loadingMessages,
loadingScenes
} = this.props;
const { messageIndex, sceneIndex } = this.state;
const contentClassName = cx(
"wrapper py4 text-brand text-centered flex-full flex flex-column layout-centered",
{ "bg-white": !noBackground }
);
if (noWrapper && !error && !loading) {
return React.Children.only(this.getChildren());
}
......@@ -66,10 +130,12 @@ export default class LoadingAndErrorWrapper extends Component {
<h2 className="text-normal text-grey-2 ie-wrap-content-fix">{this.getErrorMessage()}</h2>
</div>
: loading ?
showSpinner &&
<div className={contentClassName}>
<LoadingSpinner />
<h2 className="text-normal text-grey-2 mt1">Loading...</h2>
{ loadingScenes && loadingScenes[sceneIndex] }
{ !loadingScenes && showSpinner && <LoadingSpinner /> }
<h2 className="text-normal text-grey-2 mt1">
{loadingMessages[messageIndex]}
</h2>
</div>
:
......
......@@ -77,3 +77,12 @@ textarea {
.undefined {
border: 1px solid red !important;
}
@keyframes spin {
100% { transform: rotate(360deg); }
}
@keyframes spin-reverse {
100% { transform: rotate(-360deg); }
}
import React from 'react'
import Icon from 'metabase/components/Icon'
const RotatingGear = ({name, speed, size, delay }) =>
<div style={{
animation: `${name} ${speed}ms linear ${delay}ms infinite`
}}>
<Icon name='gear' size={size} />
</div>
RotatingGear.defaultProps = {
name: 'spin',
delay: 0,
speed: 5000
}
const LoadingAnimation = () =>
<div className="relative" style={{ width: 300, height: 180 }}>
<div className="absolute" style={{ top: 20, left: 135 }}>
<RotatingGear size={90} />
</div>
<div className="absolute" style={{ top: 60, left: 80 }}>
<RotatingGear name='spin-reverse' size={60} speed={6000} />
</div>
<div className="absolute" style={{ top: 110, left: 125 }}>
<RotatingGear speed={7000} size={45} />
</div>
</div>
export default LoadingAnimation
......@@ -16,6 +16,7 @@ import {
import LoadingAndErrorWrapper from 'metabase/components/LoadingAndErrorWrapper'
import XRayComparison from 'metabase/xray/components/XRayComparison'
import LoadingAnimation from 'metabase/xray/components/LoadingAnimation'
import { hasComparison } from 'metabase/xray/utils'
......@@ -45,6 +46,7 @@ class SegmentComparison extends Component {
try {
await this.props.fetchSegmentComparison(segmentId1, segmentId2, cost)
} catch (error) {
console.log('error', error)
this.setState({ error })
}
}
......@@ -67,6 +69,14 @@ class SegmentComparison extends Component {
loading={isLoading || !hasComparison(comparison)}
error={error}
noBackground
loadingMessages={[
'Generating your comparison...',
'Teaching robots to love...',
'Still working...',
]}
loadingScenes={[
<LoadingAnimation />
]}
>
{ () =>
......
......@@ -103,7 +103,7 @@ describe("xray integration tests", () => {
expect(cardXRay.text()).toMatch(/Time breakout question/);
})
xit("let you see segment xray for a question containing a segment", async () => {
it("let you see segment xray for a question containing a segment", async () => {
const store = await createTestStore()
store.pushPath(Urls.question(segmentQuestion.id()))
const app = mount(store.getAppContainer());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment