mirror of
https://github.com/reactos/developer-web-interface.git
synced 2024-11-23 03:49:43 +00:00
Better handle loading states
Now if BuildBot does not have build data, it will be indicated with question mark. Moved pagination to a separate component, got rid of pageReducer
This commit is contained in:
parent
9d00ab2f3f
commit
55258739d2
@ -6,18 +6,29 @@ import {
|
|||||||
Route,
|
Route,
|
||||||
Redirect
|
Redirect
|
||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
|
import { connect } from 'react-redux'
|
||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import Commits from './components/Commits';
|
import Commits from './components/Commits';
|
||||||
import Pulls from './components/Pulls';
|
import Pulls from './components/Pulls';
|
||||||
|
import Loading from './components/Loading'
|
||||||
import configureStore from './redux/store';
|
import configureStore from './redux/store';
|
||||||
|
import { loadBuilders } from './redux/actions'
|
||||||
|
import { LOAD_STATE } from './redux/constants'
|
||||||
|
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
export default function App() {
|
class App extends React.PureComponent {
|
||||||
return (
|
// things which are needed regardles the current view
|
||||||
<Provider store={store}>
|
componentDidMount() {
|
||||||
<Router>
|
this.props.dispatch(loadBuilders())
|
||||||
<div>
|
}
|
||||||
<Header/>
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Header/>
|
||||||
|
{this.props.canRender ?
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/pulls/:pull_state"><Pulls/></Route>
|
<Route path="/pulls/:pull_state"><Pulls/></Route>
|
||||||
<Route path="/commits/:branch"><Commits/></Route>
|
<Route path="/commits/:branch"><Commits/></Route>
|
||||||
@ -26,7 +37,22 @@ export default function App() {
|
|||||||
<Route path="/commits"><Redirect to="/commits/master"/></Route>
|
<Route path="/commits"><Redirect to="/commits/master"/></Route>
|
||||||
<Route path="/"><Redirect to="/commits/master"/></Route>
|
<Route path="/"><Redirect to="/commits/master"/></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
: <Loading text="Loading basic data..." />}
|
||||||
|
</React.Fragment>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return ({canRender: state.isLoading.buildersDataState === LOAD_STATE.LOADED})
|
||||||
|
}
|
||||||
|
|
||||||
|
const WrappedApp = connect(mapStateToProps)(App)
|
||||||
|
|
||||||
|
export default function outerApp() {
|
||||||
|
return (
|
||||||
|
<Provider store={store}>
|
||||||
|
<Router>
|
||||||
|
<WrappedApp />
|
||||||
</Router>
|
</Router>
|
||||||
</Provider>
|
</Provider>
|
||||||
);
|
);
|
||||||
|
@ -7,11 +7,7 @@ import {
|
|||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownItem
|
DropdownItem
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
import {
|
import { loadBranches, loadCommits } from '../redux/actions';
|
||||||
loadBranches,
|
|
||||||
loadCommits,
|
|
||||||
loadBuilders
|
|
||||||
} from '../redux/actions';
|
|
||||||
|
|
||||||
class Branches extends React.Component {
|
class Branches extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -21,7 +17,6 @@ class Branches extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.loadBuilders();
|
|
||||||
this.props.loadBranches();
|
this.props.loadBranches();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +71,7 @@ const mapStateToProps = ({ branches }) => ({
|
|||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
loadCommits: (branch, next) => dispatch(loadCommits(branch, next)),
|
loadCommits: (branch, next) => dispatch(loadCommits(branch, next)),
|
||||||
loadBranches: () => dispatch(loadBranches()),
|
loadBranches: () => dispatch(loadBranches())
|
||||||
loadBuilders: () => dispatch(loadBuilders())
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
@ -6,17 +6,15 @@ import Branches from './Branches';
|
|||||||
import './styles/Commit.css';
|
import './styles/Commit.css';
|
||||||
import CommitsCard from './CommitsCard';
|
import CommitsCard from './CommitsCard';
|
||||||
import Loading from './Loading';
|
import Loading from './Loading';
|
||||||
|
import Pagination from './Pagination'
|
||||||
|
import { LOAD_STATE } from '../redux/constants'
|
||||||
|
|
||||||
|
|
||||||
class Commits extends React.PureComponent {
|
class Commits extends React.PureComponent {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.loadCommits(this.props.branch);
|
if (this.props.firstLoad) {
|
||||||
this.props.loadBuilds();
|
this.props.loadCommits(this.props.branch, 1); // TODO: remove the hack
|
||||||
}
|
this.props.loadBuilds();
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
if (this.props.branch !== prevProps.branch) {
|
|
||||||
this.props.loadCommits(this.props.branch)
|
|
||||||
this.props.loadBuilds()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +33,7 @@ class Commits extends React.PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {branch, page} = this.props;
|
const { branch, currentPage } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='container mt-2'>
|
<div className='container mt-2'>
|
||||||
@ -46,7 +44,7 @@ class Commits extends React.PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.props.isLoading.load ? (
|
{this.props.isLoading ? (
|
||||||
<Loading
|
<Loading
|
||||||
text={`Fetching latest Commits of ${branch} for you...`}
|
text={`Fetching latest Commits of ${branch} for you...`}
|
||||||
/>
|
/>
|
||||||
@ -60,38 +58,10 @@ class Commits extends React.PureComponent {
|
|||||||
Err:{this.props.error}
|
Err:{this.props.error}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<Pagination
|
||||||
<button
|
currentPage={currentPage}
|
||||||
type='button'
|
nextPage={() => this.props.loadCommits(branch, currentPage + 1)}
|
||||||
onClick={() => {
|
prevPage={() => this.props.loadCommits(branch, currentPage - 1)} />
|
||||||
this.props.loadCommits(branch, page.prev);
|
|
||||||
}}
|
|
||||||
className='btn btn-primary '
|
|
||||||
disabled={
|
|
||||||
page.prev === null || this.props.error !== null
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className='fa fa-caret-left' aria-hidden='true' />
|
|
||||||
Previous Page{' '}
|
|
||||||
</button>{' '}
|
|
||||||
<button
|
|
||||||
type='button'
|
|
||||||
onClick={() => {
|
|
||||||
this.props.loadCommits(branch, page.next);
|
|
||||||
}}
|
|
||||||
className='btn btn-primary'
|
|
||||||
disabled={
|
|
||||||
page.next === null || this.props.error !== null
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Next Page{' '}
|
|
||||||
<i className='fa fa-caret-right' aria-hidden='true' />
|
|
||||||
</button>
|
|
||||||
<footer className='blockquote-footer'>
|
|
||||||
Page {page.next - 1}
|
|
||||||
</footer>
|
|
||||||
<div className='footer-blockquote' />
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -110,15 +80,15 @@ const mapStateToProps = ({
|
|||||||
commits,
|
commits,
|
||||||
builders,
|
builders,
|
||||||
error,
|
error,
|
||||||
page,
|
|
||||||
builds,
|
builds,
|
||||||
tests
|
tests
|
||||||
}) => ({
|
}) => ({
|
||||||
isLoading,
|
isLoading: isLoading.commitsLoadInfo.lastState !== LOAD_STATE.LOADED,
|
||||||
|
firstLoad: !isLoading.commitsLoadInfo.loadedPages.includes(1), //if we need to load first page
|
||||||
|
currentPage: isLoading.commitsLoadInfo.currentPage,
|
||||||
commits,
|
commits,
|
||||||
builders,
|
builders,
|
||||||
error,
|
error,
|
||||||
page,
|
|
||||||
builds,
|
builds,
|
||||||
tests
|
tests
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux'
|
||||||
import { UncontrolledCollapse, CardBody, Card, CardHeader } from 'reactstrap';
|
import { UncontrolledCollapse, CardBody, Card, CardHeader } from 'reactstrap';
|
||||||
import BuildDetails from './BuildDetails';
|
import BuildDetails from './BuildDetails';
|
||||||
import TestDetails from './TestDetails';
|
import TestDetails from './TestDetails';
|
||||||
import { JOB_STATUS } from '../redux/constants'
|
import { JOB_STATUS, LOAD_STATE } from '../redux/constants'
|
||||||
import { statusElement } from './utils'
|
import { statusElement } from './utils'
|
||||||
|
|
||||||
function firstLineTrimmed(str) {
|
function firstLineTrimmed(str) {
|
||||||
@ -16,7 +17,7 @@ function firstLineTrimmed(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTotalStatus(jobs) {
|
function getTotalStatus(jobs) {
|
||||||
if (!jobs.length) return null
|
if (!jobs || !jobs.length) return JOB_STATUS.NO_DATA
|
||||||
|
|
||||||
let ret = JOB_STATUS.SUCCESS
|
let ret = JOB_STATUS.SUCCESS
|
||||||
|
|
||||||
@ -30,31 +31,31 @@ function getTotalStatus(jobs) {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
function CommitsCard({sha, ...props}) {
|
function CommitsCard({sha, author, commit, loadStatus, ...props}) {
|
||||||
let tog = 'toggler' + sha;
|
let tog = 'toggler' + sha;
|
||||||
let committerDate = new Date(props.commit.committer.date);
|
let committerDate = new Date(commit.committer.date);
|
||||||
let authorDate = new Date(props.commit.author.date);
|
let authorDate = new Date(commit.author.date);
|
||||||
let author = encodeURIComponent(props.commit.author.name);
|
const author_login = author ? author.login : commit.author.name
|
||||||
let committer = encodeURIComponent(props.commit.committer.name);
|
const builds = props.builds ? props.builds : []
|
||||||
|
const tests = props.tests ? props.tests : []
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="mb-1">
|
<Card className="mb-1">
|
||||||
<CardHeader className='new' type='button' id={tog}>
|
<CardHeader className='new' type='button' id={tog}>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col-sm-9'>
|
<div className='col-sm-9'>
|
||||||
<a className="text-monospace" href={`https://github.com/reactos/reactos/commit/${sha}`}>{sha.substring(0, 7)}</a>
|
<a className="text-monospace" href={`https://github.com/reactos/reactos/commit/${sha}`}>{sha.substring(0, 7)}</a>
|
||||||
{" "}{firstLineTrimmed(props.commit.message)}
|
{" "}{firstLineTrimmed(commit.message)}
|
||||||
</div>
|
</div>
|
||||||
<div className='col-sm-2'>{props.author.login}</div>
|
<div className='col-sm-2'>{author_login}</div>
|
||||||
<div className="col-sm-1">
|
<div className="col-sm-1">
|
||||||
{props.builds &&
|
{loadStatus.buildBot === LOAD_STATE.LOADING
|
||||||
props.builds.length > 0
|
? <span title="Loading results"><i className="fa fa-refresh fa-spin" /></span>
|
||||||
? statusElement(getTotalStatus(props.builds), "Build status")
|
: statusElement(getTotalStatus(props.builds), "Build status") }
|
||||||
: <span title="Loading results"><i className="fa fa-refresh fa-spin" /></span> }
|
|
||||||
{" "}
|
{" "}
|
||||||
{props.tests &&
|
{loadStatus.buildBot === LOAD_STATE.LOADING
|
||||||
props.tests.length > 0
|
? <span title="Loading results"><i className="fa fa-refresh fa-spin" /></span>
|
||||||
? statusElement(getTotalStatus(props.tests), "Test status")
|
: statusElement(getTotalStatus(props.tests), "Test status") }
|
||||||
: <span title="Loading results"><i className="fa fa-refresh fa-spin" /></span> }
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
@ -66,13 +67,13 @@ function CommitsCard({sha, ...props}) {
|
|||||||
<a
|
<a
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noreferrer noopener'
|
rel='noreferrer noopener'
|
||||||
href={props.commit.html_url}
|
href={commit.html_url}
|
||||||
>
|
>
|
||||||
{sha}
|
{sha}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>Commit Msg:</strong> {props.commit.message}
|
<strong>Commit Msg:</strong> {commit.message}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
@ -81,11 +82,11 @@ function CommitsCard({sha, ...props}) {
|
|||||||
<a
|
<a
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noreferrer noopener'
|
rel='noreferrer noopener'
|
||||||
href={`https://git.reactos.org/?p=reactos.git;a=search;s=${author};st=author`}
|
href={`https://git.reactos.org/?p=reactos.git;a=search;s=${encodeURIComponent(commit.author.name)};st=author`}
|
||||||
>
|
>
|
||||||
{props.commit.author.name}
|
{commit.author.name}
|
||||||
</a>
|
</a>
|
||||||
{` <${props.commit.author.email}>`}
|
{` <${commit.author.email}>`}
|
||||||
</div>
|
</div>
|
||||||
<div className='col-sm'>
|
<div className='col-sm'>
|
||||||
<strong>Author Date: </strong>
|
<strong>Author Date: </strong>
|
||||||
@ -98,11 +99,11 @@ function CommitsCard({sha, ...props}) {
|
|||||||
<a
|
<a
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noreferrer noopener'
|
rel='noreferrer noopener'
|
||||||
href={`https://git.reactos.org/?p=reactos.git;a=search;s=${committer};st=committer`}
|
href={`https://git.reactos.org/?p=reactos.git;a=search;s=${encodeURIComponent(commit.committer.name)};st=committer`}
|
||||||
>
|
>
|
||||||
{props.commit.committer.name}
|
{commit.committer.name}
|
||||||
</a>
|
</a>
|
||||||
{` <${props.commit.committer.email}>`}
|
{` <${commit.committer.email}>`}
|
||||||
</div>
|
</div>
|
||||||
<div className='col-sm'>
|
<div className='col-sm'>
|
||||||
<strong>Committer Date: </strong>
|
<strong>Committer Date: </strong>
|
||||||
@ -113,23 +114,15 @@ function CommitsCard({sha, ...props}) {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-5">
|
<div className="col-md-5">
|
||||||
<h5>Build Details:</h5>
|
<h5>Build Details:</h5>
|
||||||
{props.builds ? (
|
{loadStatus.buildBot === LOAD_STATE.LOADING
|
||||||
<BuildDetails builds={props.builds} />
|
? <strong>Loading builds data...</strong>
|
||||||
) : (
|
: <BuildDetails builds={builds} /> }
|
||||||
<div>
|
|
||||||
<strong>Loading Builds...</strong>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
<h5>Test Details:</h5>
|
<h5>Test Details:</h5>
|
||||||
{props.tests ? (
|
{loadStatus.buildBot === LOAD_STATE.LOADING
|
||||||
<TestDetails tests={props.tests} previousTests={props.previousTests} />
|
? <strong>Loading tests data...</strong>
|
||||||
) : (
|
: <TestDetails tests={tests} previousTests={props.previousTests} /> }
|
||||||
<div>
|
|
||||||
<strong>No data Exists</strong>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
@ -137,4 +130,9 @@ function CommitsCard({sha, ...props}) {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default CommitsCard;
|
|
||||||
|
function mapStateToProps(state, ownProps) {
|
||||||
|
return {...ownProps, loadStatus: state.isLoading.byCommit[ownProps.sha]}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(CommitsCard);
|
||||||
|
30
client/src/components/Pagination.js
Normal file
30
client/src/components/Pagination.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
|
||||||
|
export default function Pagination({currentPage, nextPage, prevPage}) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
onClick={prevPage}
|
||||||
|
className='btn btn-primary '
|
||||||
|
disabled={currentPage === 1}
|
||||||
|
>
|
||||||
|
<i className='fa fa-caret-left' aria-hidden='true' />
|
||||||
|
Previous Page{' '}
|
||||||
|
</button>{' '}
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
onClick={nextPage}
|
||||||
|
className='btn btn-primary'
|
||||||
|
>
|
||||||
|
Next Page{' '}
|
||||||
|
<i className='fa fa-caret-right' aria-hidden='true' />
|
||||||
|
</button>
|
||||||
|
<footer className='blockquote-footer'>
|
||||||
|
Page {currentPage}
|
||||||
|
</footer>
|
||||||
|
<div className='footer-blockquote' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -4,16 +4,14 @@ import { NavLink, useParams } from 'react-router-dom';
|
|||||||
import { loadPulls } from '../redux/actions';
|
import { loadPulls } from '../redux/actions';
|
||||||
import './styles/Pulls.css';
|
import './styles/Pulls.css';
|
||||||
import Loading from './Loading';
|
import Loading from './Loading';
|
||||||
|
import Pagination from './Pagination'
|
||||||
import PullsCard from './PullsCard';
|
import PullsCard from './PullsCard';
|
||||||
|
import { LOAD_STATE } from '../redux/constants'
|
||||||
|
|
||||||
class Pulls extends React.PureComponent {
|
class Pulls extends React.PureComponent {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.loadPulls(this.props.pullState);
|
if (this.props.firstLoad) {
|
||||||
}
|
this.props.loadPulls(this.props.pullState, 1)
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
if (this.props.pullState !== prevProps.pullState) {
|
|
||||||
this.props.loadPulls(this.props.pullState)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +28,7 @@ class Pulls extends React.PureComponent {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
render() {
|
render() {
|
||||||
const {pullState, page} = this.props;
|
const { pullState, currentPage } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='container mt-2'>
|
<div className='container mt-2'>
|
||||||
@ -51,7 +49,7 @@ class Pulls extends React.PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.props.isLoading.load ? (
|
{this.props.isLoading ? (
|
||||||
<Loading text='Fetching latest PRs for you...' />
|
<Loading text='Fetching latest PRs for you...' />
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
@ -63,38 +61,10 @@ class Pulls extends React.PureComponent {
|
|||||||
Err:{this.props.error}
|
Err:{this.props.error}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<Pagination
|
||||||
<button
|
currentPage={currentPage}
|
||||||
type='button'
|
nextPage={() => this.props.loadPulls(pullState, currentPage + 1)}
|
||||||
onClick={() => {
|
prevPage={() => this.props.loadPulls(pullState, currentPage - 1)} />
|
||||||
this.props.loadPulls(pullState, page.prev);
|
|
||||||
}}
|
|
||||||
className='btn btn-primary '
|
|
||||||
disabled={
|
|
||||||
page.prev === null || this.props.error !== null
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className='fa fa-caret-left' aria-hidden='true' />
|
|
||||||
Previous Page{' '}
|
|
||||||
</button>{' '}
|
|
||||||
<button
|
|
||||||
type='button'
|
|
||||||
onClick={() => {
|
|
||||||
this.props.loadPulls(pullState, page.next);
|
|
||||||
}}
|
|
||||||
className='btn btn-primary'
|
|
||||||
disabled={
|
|
||||||
page.next === null || this.props.error !== null
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Next Page{' '}
|
|
||||||
<i className='fa fa-caret-right' aria-hidden='true' />
|
|
||||||
</button>
|
|
||||||
<footer className='blockquote-footer'>
|
|
||||||
Page {page.next - 1}
|
|
||||||
</footer>
|
|
||||||
<div className='footer-blockquote' />
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -111,16 +81,16 @@ function PullsWrapper(props) {
|
|||||||
const mapStateToProps = ({
|
const mapStateToProps = ({
|
||||||
pulls,
|
pulls,
|
||||||
builders,
|
builders,
|
||||||
page,
|
|
||||||
isLoading,
|
isLoading,
|
||||||
error,
|
error,
|
||||||
builds,
|
builds,
|
||||||
tests
|
tests
|
||||||
}) => ({
|
}) => ({
|
||||||
|
isLoading: isLoading.pullsLoadInfo.lastState !== LOAD_STATE.LOADED,
|
||||||
|
firstLoad: !isLoading.pullsLoadInfo.loadedPages.includes(1), //if we need to load first page
|
||||||
|
currentPage: isLoading.pullsLoadInfo.currentPage,
|
||||||
pulls,
|
pulls,
|
||||||
builders,
|
builders,
|
||||||
page,
|
|
||||||
isLoading,
|
|
||||||
error,
|
error,
|
||||||
builds,
|
builds,
|
||||||
tests
|
tests
|
||||||
|
@ -10,6 +10,8 @@ export function statusElement(status, statusText) {
|
|||||||
return <span className="text-warning" title={statusText}><i className="fa fa-hourglass" /></span>
|
return <span className="text-warning" title={statusText}><i className="fa fa-hourglass" /></span>
|
||||||
case JOB_STATUS.FAILURE:
|
case JOB_STATUS.FAILURE:
|
||||||
return <span className="text-danger" title={statusText}><i className="fa fa-times" /></span>
|
return <span className="text-danger" title={statusText}><i className="fa fa-times" /></span>
|
||||||
|
case JOB_STATUS.NO_DATA:
|
||||||
|
return <span title={statusText}><i className="fa fa-question" /></span>
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,8 @@ export const setTestmanError = error => ({
|
|||||||
error
|
error
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setPages = (next, prev) => ({
|
// branches
|
||||||
type: 'PAGE_LOAD_SUCCESS',
|
|
||||||
next,
|
|
||||||
prev
|
|
||||||
});
|
|
||||||
export const loadBranches = () => ({
|
export const loadBranches = () => ({
|
||||||
type: BRANCHES.LOAD
|
type: BRANCHES.LOAD
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,15 @@ export const PULL_STATE = {
|
|||||||
export const JOB_STATUS = {
|
export const JOB_STATUS = {
|
||||||
SUCCESS: 0,
|
SUCCESS: 0,
|
||||||
FAILURE: 1,
|
FAILURE: 1,
|
||||||
ONGOING: 2
|
ONGOING: 2,
|
||||||
|
NO_DATA: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LOAD_STATE = {
|
||||||
|
NOT_LOADED: 0,
|
||||||
|
LOADING: 1,
|
||||||
|
LOADED: 2,
|
||||||
|
ERROR: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BUILDER_TYPE = {
|
export const BUILDER_TYPE = {
|
||||||
|
@ -6,7 +6,6 @@ import errorReducer from './errorReducer';
|
|||||||
import branchReducer from './branchReducer';
|
import branchReducer from './branchReducer';
|
||||||
import builderReducer from './builderReducer';
|
import builderReducer from './builderReducer';
|
||||||
import pullsReducer from './pullsReducer';
|
import pullsReducer from './pullsReducer';
|
||||||
import pageReducer from './pageReducer';
|
|
||||||
import builds from './builds';
|
import builds from './builds';
|
||||||
import tests from './tests'
|
import tests from './tests'
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ const rootReducer = combineReducers({
|
|||||||
branches: branchReducer,
|
branches: branchReducer,
|
||||||
builders: builderReducer,
|
builders: builderReducer,
|
||||||
pulls: pullsReducer,
|
pulls: pullsReducer,
|
||||||
page: pageReducer,
|
|
||||||
builds,
|
builds,
|
||||||
tests
|
tests
|
||||||
});
|
});
|
||||||
|
@ -1,45 +1,89 @@
|
|||||||
import { COMMITS, BRANCHES, PULLS, BUILD_DATA, BUILDERS } from '../constants';
|
import { COMMITS, BRANCHES, PULLS, BUILD_DATA, TEST_DATA, BUILDERS, LOAD_STATE } from '../constants';
|
||||||
|
|
||||||
const loadingReducer = (state = { newPage: 1, load: false }, action) => {
|
const defaultState = {
|
||||||
|
byCommit: {},
|
||||||
|
buildersDataState: LOAD_STATE.NOT_LOADED,
|
||||||
|
commitsLoadInfo: {lastState: LOAD_STATE.NOT_LOADED, currentPage: 1, loadedPages: []},
|
||||||
|
pullsLoadInfo: {lastState: LOAD_STATE.NOT_LOADED, currentPage: 1, loadedPages: []},
|
||||||
|
buildBotLoadInfo: {lastState: LOAD_STATE.NOT_LOADED},
|
||||||
|
testManLoadInfo: {lastState: LOAD_STATE.NOT_LOADED}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadingReducer(state = defaultState, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case COMMITS.LOAD:
|
|
||||||
return { newPage: action.newPage, load: true };
|
|
||||||
|
|
||||||
case BUILDERS.LOAD:
|
case BUILDERS.LOAD:
|
||||||
return { ...state, load: true };
|
return { ...state, buildersDataState: LOAD_STATE.LOADING }
|
||||||
|
|
||||||
case PULLS.LOAD:
|
|
||||||
return { newPage: action.newPage, load: true };
|
|
||||||
|
|
||||||
case BRANCHES.LOAD:
|
|
||||||
return { newPage: action.newPage, load: true };
|
|
||||||
|
|
||||||
case BUILD_DATA.LOAD:
|
|
||||||
return { newPage: action.newPage, load: true };
|
|
||||||
|
|
||||||
case COMMITS.LOAD_SUCCESS:
|
|
||||||
return { ...state, load: false };
|
|
||||||
|
|
||||||
case BUILDERS.LOAD_SUCCESS:
|
case BUILDERS.LOAD_SUCCESS:
|
||||||
return { ...state, load: true };
|
return { ...state, buildersDataState: LOAD_STATE.LOADED }
|
||||||
|
|
||||||
case PULLS.LOAD_SUCCESS:
|
case COMMITS.LOAD: {
|
||||||
return { ...state, load: false };
|
const commitsLoadInfo = {
|
||||||
|
...state.commitsLoadInfo,
|
||||||
|
lastState: LOAD_STATE.LOADING,
|
||||||
|
lastPage: action.newPage
|
||||||
|
}
|
||||||
|
|
||||||
case BRANCHES.LOAD_SUCCESS:
|
return { ...state, commitsLoadInfo}
|
||||||
return { newPage: action.newPage, load: true };
|
}
|
||||||
|
case COMMITS.LOAD_SUCCESS: {
|
||||||
|
const byCommit = {...state.byCommit}
|
||||||
|
|
||||||
case BUILD_DATA.LOAD_SUCCESS:
|
const commitsLoadInfo = {
|
||||||
return { load: false };
|
...state.commitsLoadInfo,
|
||||||
|
lastState: LOAD_STATE.LOADED,
|
||||||
|
currentPage: state.commitsLoadInfo.lastPage,
|
||||||
|
loadedPages: state.commitsLoadInfo.loadedPages.concat([state.commitsLoadInfo.lastPage])
|
||||||
|
}
|
||||||
|
|
||||||
case COMMITS.LOAD_FAIL:
|
for(let commit of Object.values(action.commits))
|
||||||
return { ...state, load: false };
|
{
|
||||||
|
byCommit[commit.sha] = {buildBot: LOAD_STATE.LOADING, tests: LOAD_STATE.LOADING}
|
||||||
|
}
|
||||||
|
|
||||||
case PULLS.LOAD_FAIL:
|
return { ...state, byCommit, commitsLoadInfo}
|
||||||
return { ...state, load: false };
|
}
|
||||||
|
case BUILD_DATA.LOAD: {
|
||||||
|
const byCommit = {...state.byCommit}
|
||||||
|
for(let sha of Object.keys(byCommit))
|
||||||
|
{
|
||||||
|
byCommit[sha] = {buildBot: LOAD_STATE.LOADING, tests: byCommit[sha].tests}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {...state, byCommit };
|
||||||
|
}
|
||||||
|
case PULLS.LOAD: {
|
||||||
|
const pullsLoadInfo = {
|
||||||
|
...state.pullsLoadInfo,
|
||||||
|
lastState: LOAD_STATE.LOADING,
|
||||||
|
lastPage: action.newPage
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...state, pullsLoadInfo}
|
||||||
|
}
|
||||||
|
case PULLS.LOAD_SUCCESS: {
|
||||||
|
const pullsLoadInfo = {
|
||||||
|
...state.pullsLoadInfo,
|
||||||
|
lastState: LOAD_STATE.LOADED,
|
||||||
|
currentPage: state.pullsLoadInfo.lastPage,
|
||||||
|
loadedPages: state.pullsLoadInfo.loadedPages.concat([state.pullsLoadInfo.lastPage])
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...state, pullsLoadInfo }
|
||||||
|
}
|
||||||
|
case BUILD_DATA.LOAD_SUCCESS: {
|
||||||
|
const byCommit = {...state.byCommit}
|
||||||
|
for(let [sha, build] of Object.entries(action.builds))
|
||||||
|
{
|
||||||
|
if (byCommit[sha]) {
|
||||||
|
byCommit[sha] = {buildBot: LOAD_STATE.LOADED, tests: byCommit[sha].tests}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...state, byCommit };
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return { ...state, load: false };
|
return state
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import { BRANCHES } from '../constants';
|
|
||||||
const pageReducer = (state = { next: 1, prev: 0 }, action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case BRANCHES.CURRENT:
|
|
||||||
return {
|
|
||||||
next: 1,
|
|
||||||
prev: 0
|
|
||||||
};
|
|
||||||
case 'PAGE_LOAD_SUCCESS':
|
|
||||||
return {
|
|
||||||
next: action.next,
|
|
||||||
prev: action.prev
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default pageReducer;
|
|
@ -1,21 +1,13 @@
|
|||||||
import { throttle, call, put, select } from 'redux-saga/effects';
|
import { throttle, call, put, select } from 'redux-saga/effects';
|
||||||
import { COMMITS } from '../constants';
|
import { COMMITS } from '../constants';
|
||||||
import { fetchCommits } from '../api';
|
import { fetchCommits } from '../api';
|
||||||
import { setCommits, setCommitsError, setPages } from '../actions';
|
import { setCommits, setCommitsError } from '../actions';
|
||||||
|
|
||||||
export const getNewPage = state => parseInt(state.isLoading.newPage, 10);
|
|
||||||
|
|
||||||
function* handleCommitsLoad(action) {
|
function* handleCommitsLoad(action) {
|
||||||
try {
|
try {
|
||||||
const newPage = yield select(getNewPage);
|
let commits = yield call(fetchCommits, action.branch, action.newPage)
|
||||||
let commits = yield call(fetchCommits, action.branch, newPage);
|
|
||||||
yield put(setCommits(commits.commits.body));
|
yield put(setCommits(commits.commits.body));
|
||||||
yield put(
|
|
||||||
setPages(
|
|
||||||
commits.page.next !== undefined ? commits.page.next.page : null,
|
|
||||||
commits.page.prev !== undefined ? commits.page.prev.page : null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//dispatch error
|
//dispatch error
|
||||||
yield put(setCommitsError(error.toString()));
|
yield put(setCommitsError(error.toString()));
|
||||||
|
@ -1,23 +1,16 @@
|
|||||||
import { takeEvery, call, put, select } from 'redux-saga/effects';
|
import { takeEvery, call, put, select } from 'redux-saga/effects';
|
||||||
import { PULLS } from '../constants';
|
import { PULLS } from '../constants';
|
||||||
import { fetchPulls } from '../api';
|
import { fetchPulls } from '../api';
|
||||||
import { setPulls, setPullsError, setPages } from '../actions';
|
import { setPulls, setPullsError } from '../actions';
|
||||||
const getNewPage = state => parseInt(state.isLoading.newPage, 10);
|
|
||||||
|
|
||||||
function* handlePullsLoad(action) {
|
function* handlePullsLoad(action) {
|
||||||
try {
|
try {
|
||||||
const newPage = yield select(getNewPage);
|
let pulls = yield call(fetchPulls, action.state, action.newPage);
|
||||||
let pulls = yield call(fetchPulls, action.state, newPage);
|
yield put(setPulls(pulls.pulls.body));
|
||||||
yield put(setPulls(pulls.pulls.body));
|
} catch (error) {
|
||||||
yield put(
|
yield put(setPullsError(error.toString()));
|
||||||
setPages(
|
}
|
||||||
pulls.page.next !== undefined ? pulls.page.next.page : null,
|
|
||||||
pulls.page.prev !== undefined ? pulls.page.prev.page : null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
yield put(setPullsError(error.toString()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function* watchPullsLoad() {
|
export default function* watchPullsLoad() {
|
||||||
|
@ -9,7 +9,11 @@ function* handleTestmanLoad() {
|
|||||||
const shas = pulls.map(pull => pull.merge_commit_sha);
|
const shas = pulls.map(pull => pull.merge_commit_sha);
|
||||||
const testResults = yield call(fetchTests, shas[9], shas[0], 1);
|
const testResults = yield call(fetchTests, shas[9], shas[0], 1);
|
||||||
const testByPulls = {};
|
const testByPulls = {};
|
||||||
|
console.log(shas)
|
||||||
for (let sha of shas) {
|
for (let sha of shas) {
|
||||||
|
// some pulls don't have merge_commit_sha
|
||||||
|
if (!sha) continue
|
||||||
|
|
||||||
testByPulls[sha] = testResults.filter(test =>
|
testByPulls[sha] = testResults.filter(test =>
|
||||||
sha.startsWith(test.revision._text)
|
sha.startsWith(test.revision._text)
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user