Merge pull request #26 from kawwong/detect-mezzurite
Add loading and not found view states
This commit is contained in:
Коммит
3735174a46
|
@ -13,6 +13,7 @@ class App extends Component {
|
|||
this.state = {
|
||||
applicationLoadTime: null,
|
||||
captureCycles: null,
|
||||
loading: true,
|
||||
framework: {
|
||||
name: null,
|
||||
version: null
|
||||
|
@ -21,8 +22,12 @@ class App extends Component {
|
|||
}
|
||||
|
||||
componentDidMount () {
|
||||
MezzuriteInspector.isMezzuritePresentAsync().then(() => {
|
||||
MezzuriteInspector.listenForTimingEvents((event) => this.handleTimingEvent(event));
|
||||
MezzuriteInspector.isMezzuritePresentAsync().then((mezzuritePresent) => {
|
||||
if (mezzuritePresent) {
|
||||
MezzuriteInspector.listenForTimingEvents((timingEvent) => this.handleTimingEvent(timingEvent));
|
||||
} else {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -57,6 +62,8 @@ class App extends Component {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +71,7 @@ class App extends Component {
|
|||
return (
|
||||
<div className='app'>
|
||||
<Header />
|
||||
<Main applicationLoadTime={this.state.applicationLoadTime} captureCycles={this.state.captureCycles} />
|
||||
<Main applicationLoadTime={this.state.applicationLoadTime} captureCycles={this.state.captureCycles} loading={this.state.loading} />
|
||||
<Footer packageName={this.state.framework.name} packageVersion={this.state.framework.version} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -8,6 +8,31 @@
|
|||
margin: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main--header-center {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
line-height: 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.main--header-link {
|
||||
color: var(--microsoft-blue);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.main--header-link:active {
|
||||
color: var(--microsoft-gray-darker);
|
||||
}
|
||||
|
||||
.main--header-text {
|
||||
max-width: 80%;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 540px) {
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import React from 'react';
|
||||
import { arrayOf, number, shape, string } from 'prop-types';
|
||||
import React, { Fragment } from 'react';
|
||||
import { arrayOf, bool, number, shape, string } from 'prop-types';
|
||||
|
||||
import './Main.css';
|
||||
import CaptureCycle from '../CaptureCycle/CaptureCycle';
|
||||
import MainLoading from './MainLoading';
|
||||
|
||||
const Main = (props) => {
|
||||
const noActiveCaptureCycles = props.captureCycles != null && props.captureCycles.length === 0 && props.applicationLoadTime != null;
|
||||
|
||||
return (
|
||||
props != null && <main className='main'>
|
||||
{props.applicationLoadTime == null && props.captureCycles == null &&
|
||||
<h2 className='main--header'>Mezzurite is working...</h2>
|
||||
}
|
||||
{props.applicationLoadTime != null && <h2 className='main--header'>App<span className='mobile-hidden'>lication</span> Load Time: {props.applicationLoadTime} ms</h2>}
|
||||
<h2 className={props.applicationLoadTime != null || props.loading ? 'main--header' : 'main--header main--header-center'}>
|
||||
{renderHeader(props.applicationLoadTime, props.loading)}
|
||||
</h2>
|
||||
{props.loading && <MainLoading />}
|
||||
{props.captureCycles != null && props.captureCycles.length > 0 && props.captureCycles.map((captureCycle, captureCycleIndex) => {
|
||||
if (captureCycle != null) {
|
||||
return (
|
||||
|
@ -33,6 +34,24 @@ const Main = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
const renderHeader = (applicationLoadTime, loading) => {
|
||||
if (applicationLoadTime == null) {
|
||||
if (loading) {
|
||||
return <Fragment>
|
||||
Mezzurite is working...
|
||||
</Fragment>;
|
||||
} else {
|
||||
return <span className='main--header-text'>
|
||||
Mezzurite was not detected. Follow <a className='main--header-link' href='https://github.com/Microsoft/Mezzurite#onboarding' target='_blank'>the instructions</a> to install Mezzurite.
|
||||
</span>;
|
||||
}
|
||||
} else {
|
||||
return <Fragment>
|
||||
App<span className='mobile-hidden'>lication</span> Load Time: {applicationLoadTime.toFixed(1)}ms
|
||||
</Fragment>;
|
||||
}
|
||||
};
|
||||
|
||||
Main.propTypes = {
|
||||
applicationLoadTime: number,
|
||||
captureCycles: arrayOf(
|
||||
|
@ -49,7 +68,8 @@ Main.propTypes = {
|
|||
time: string,
|
||||
viewportLoadTime: number
|
||||
})
|
||||
)
|
||||
),
|
||||
loading: bool
|
||||
};
|
||||
|
||||
export default Main;
|
||||
|
|
|
@ -12,9 +12,21 @@ describe('Main.js', () => {
|
|||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render without captureCycles', () => {
|
||||
it('should render with loading as true', () => {
|
||||
const tree = renderer
|
||||
.render(<Main applicationLoadTime={5.42} />);
|
||||
.render(<Main loading />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render without captureCycles and loading as true', () => {
|
||||
const tree = renderer
|
||||
.render(<Main applicationLoadTime={5.42} loading />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render without captureCycles and loading as false', () => {
|
||||
const tree = renderer
|
||||
.render(<Main applicationLoadTime={5.42} loading={false} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
@media only screen {
|
||||
.capture-cycle--skeleton {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.capture-cycle--skeleton-component {
|
||||
border-radius: 8px;
|
||||
height: 28px;
|
||||
margin: 0 16px 16px;
|
||||
}
|
||||
|
||||
.capture-cycle--skeleton-title {
|
||||
height: 24px;
|
||||
border-radius: 8px;
|
||||
margin: 16px auto 36px;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.shimmer {
|
||||
background: var(--microsoft-gray-lightest);
|
||||
background-image: -webkit-gradient(linear, left top, right top, from(var(--microsoft-gray-lightest)), color-stop(20%, var(--microsoft-gray-lighter)), color-stop(60%, var(--microsoft-gray-lightest)), to(var(--microsoft-gray-lightest)));
|
||||
background-image: -webkit-linear-gradient(left, var(--microsoft-gray-lightest) 0%, var(--microsoft-gray-lighter) 20%, var(--microsoft-gray-lightest) 60%, var(--microsoft-gray-lightest) 100%);
|
||||
background-image: -o-linear-gradient(left, var(--microsoft-gray-lightest) 0%, var(--microsoft-gray-lighter) 20%, var(--microsoft-gray-lightest) 60%, var(--microsoft-gray-lightest) 100%);
|
||||
background-image: linear-gradient(to right, var(--microsoft-gray-lightest) 0%, var(--microsoft-gray-lighter) 20%, var(--microsoft-gray-lightest) 60%, var(--microsoft-gray-lightest) 100%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 200vw 200vw;
|
||||
opacity: 0.6;
|
||||
-webkit-animation-duration: 2s;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
-webkit-animation-name: placeholderShimmer;
|
||||
-webkit-animation-timing-function: linear;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 540px) {
|
||||
.capture-cycle--skeleton-title {
|
||||
margin: 16px 16px 36px;
|
||||
max-width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes placeholderShimmer {
|
||||
0% {
|
||||
background-position: -100vw 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 100vw 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import React from 'react';
|
||||
|
||||
import './MainLoading.css';
|
||||
|
||||
const MainLoading = () => (
|
||||
<div className='capture-cycle--card capture-cycle--skeleton'>
|
||||
<div className='capture-cycle--skeleton-title shimmer' />
|
||||
<div className='capture-cycle--skeleton-container'>
|
||||
<div className='capture-cycle--skeleton-component shimmer' />
|
||||
<div className='capture-cycle--skeleton-component shimmer' />
|
||||
<div className='capture-cycle--skeleton-component shimmer' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default MainLoading;
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import ShallowRenderer from 'react-test-renderer/shallow';
|
||||
|
||||
import MainLoading from './MainLoading';
|
||||
|
||||
describe('MainLoading.js', () => {
|
||||
const renderer = new ShallowRenderer();
|
||||
|
||||
it('should render the main loading view', () => {
|
||||
const tree = renderer
|
||||
.render(<MainLoading />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -5,9 +5,21 @@ exports[`Main.js should be loading when the props are null 1`] = `
|
|||
className="main"
|
||||
>
|
||||
<h2
|
||||
className="main--header"
|
||||
className="main--header main--header-center"
|
||||
>
|
||||
Mezzurite is working...
|
||||
<span
|
||||
className="main--header-text"
|
||||
>
|
||||
Mezzurite was not detected. Follow
|
||||
<a
|
||||
className="main--header-link"
|
||||
href="https://github.com/Microsoft/Mezzurite#onboarding"
|
||||
target="_blank"
|
||||
>
|
||||
the instructions
|
||||
</a>
|
||||
to install Mezzurite.
|
||||
</span>
|
||||
</h2>
|
||||
</main>
|
||||
`;
|
||||
|
@ -19,15 +31,17 @@ exports[`Main.js should not error out when captureCycles contains a null element
|
|||
<h2
|
||||
className="main--header"
|
||||
>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.42
|
||||
ms
|
||||
<React.Fragment>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.4
|
||||
ms
|
||||
</React.Fragment>
|
||||
</h2>
|
||||
</main>
|
||||
`;
|
||||
|
@ -39,15 +53,17 @@ exports[`Main.js should render when captureCycles is an empty array 1`] = `
|
|||
<h2
|
||||
className="main--header"
|
||||
>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.42
|
||||
ms
|
||||
<React.Fragment>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.4
|
||||
ms
|
||||
</React.Fragment>
|
||||
</h2>
|
||||
<h3>
|
||||
No active capture cycles have completed.
|
||||
|
@ -55,10 +71,42 @@ exports[`Main.js should render when captureCycles is an empty array 1`] = `
|
|||
</main>
|
||||
`;
|
||||
|
||||
exports[`Main.js should render with loading as true 1`] = `
|
||||
<main
|
||||
className="main"
|
||||
>
|
||||
<h2
|
||||
className="main--header"
|
||||
>
|
||||
<React.Fragment>
|
||||
Mezzurite is working...
|
||||
</React.Fragment>
|
||||
</h2>
|
||||
<MainLoading />
|
||||
</main>
|
||||
`;
|
||||
|
||||
exports[`Main.js should render without applicationLoadTime 1`] = `
|
||||
<main
|
||||
className="main"
|
||||
>
|
||||
<h2
|
||||
className="main--header main--header-center"
|
||||
>
|
||||
<span
|
||||
className="main--header-text"
|
||||
>
|
||||
Mezzurite was not detected. Follow
|
||||
<a
|
||||
className="main--header-link"
|
||||
href="https://github.com/Microsoft/Mezzurite#onboarding"
|
||||
target="_blank"
|
||||
>
|
||||
the instructions
|
||||
</a>
|
||||
to install Mezzurite.
|
||||
</span>
|
||||
</h2>
|
||||
<CaptureCycle
|
||||
captureCycleIndex={0}
|
||||
insideViewportComponents={
|
||||
|
@ -74,22 +122,47 @@ exports[`Main.js should render without applicationLoadTime 1`] = `
|
|||
</main>
|
||||
`;
|
||||
|
||||
exports[`Main.js should render without captureCycles 1`] = `
|
||||
exports[`Main.js should render without captureCycles and loading as false 1`] = `
|
||||
<main
|
||||
className="main"
|
||||
>
|
||||
<h2
|
||||
className="main--header"
|
||||
>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.42
|
||||
ms
|
||||
<React.Fragment>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.4
|
||||
ms
|
||||
</React.Fragment>
|
||||
</h2>
|
||||
</main>
|
||||
`;
|
||||
|
||||
exports[`Main.js should render without captureCycles and loading as true 1`] = `
|
||||
<main
|
||||
className="main"
|
||||
>
|
||||
<h2
|
||||
className="main--header"
|
||||
>
|
||||
<React.Fragment>
|
||||
App
|
||||
<span
|
||||
className="mobile-hidden"
|
||||
>
|
||||
lication
|
||||
</span>
|
||||
Load Time:
|
||||
5.4
|
||||
ms
|
||||
</React.Fragment>
|
||||
</h2>
|
||||
<MainLoading />
|
||||
</main>
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MainLoading.js should render the main loading view 1`] = `
|
||||
<div
|
||||
className="capture-cycle--card capture-cycle--skeleton"
|
||||
>
|
||||
<div
|
||||
className="capture-cycle--skeleton-title shimmer"
|
||||
/>
|
||||
<div
|
||||
className="capture-cycle--skeleton-container"
|
||||
>
|
||||
<div
|
||||
className="capture-cycle--skeleton-component shimmer"
|
||||
/>
|
||||
<div
|
||||
className="capture-cycle--skeleton-component shimmer"
|
||||
/>
|
||||
<div
|
||||
className="capture-cycle--skeleton-component shimmer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
Загрузка…
Ссылка в новой задаче