diff --git a/client/src/App.js b/client/src/App.js
index 29ff278..05b023d 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -6,18 +6,29 @@ import {
Route,
Redirect
} from "react-router-dom";
+import { connect } from 'react-redux'
import Header from './components/Header';
import Commits from './components/Commits';
import Pulls from './components/Pulls';
+import Loading from './components/Loading'
import configureStore from './redux/store';
+import { loadBuilders } from './redux/actions'
+import { LOAD_STATE } from './redux/constants'
+
+
const store = configureStore();
-export default function App() {
- return (
-
-
-
-
+class App extends React.PureComponent {
+ // things which are needed regardles the current view
+ componentDidMount() {
+ this.props.dispatch(loadBuilders())
+ }
+
+ render() {
+ return (
+
+
+ {this.props.canRender ?
@@ -26,7 +37,22 @@ export default function App() {
-
+ : }
+ )
+ }
+}
+
+function mapStateToProps(state) {
+ return ({canRender: state.isLoading.buildersDataState === LOAD_STATE.LOADED})
+}
+
+const WrappedApp = connect(mapStateToProps)(App)
+
+export default function outerApp() {
+ return (
+
+
+
);
diff --git a/client/src/components/Branches.js b/client/src/components/Branches.js
index 3eb654f..751a384 100644
--- a/client/src/components/Branches.js
+++ b/client/src/components/Branches.js
@@ -7,11 +7,7 @@ import {
DropdownMenu,
DropdownItem
} from 'reactstrap';
-import {
- loadBranches,
- loadCommits,
- loadBuilders
-} from '../redux/actions';
+import { loadBranches, loadCommits } from '../redux/actions';
class Branches extends React.Component {
constructor(props) {
@@ -21,7 +17,6 @@ class Branches extends React.Component {
};
}
componentDidMount() {
- this.props.loadBuilders();
this.props.loadBranches();
}
@@ -76,8 +71,7 @@ const mapStateToProps = ({ branches }) => ({
const mapDispatchToProps = dispatch => ({
loadCommits: (branch, next) => dispatch(loadCommits(branch, next)),
- loadBranches: () => dispatch(loadBranches()),
- loadBuilders: () => dispatch(loadBuilders())
+ loadBranches: () => dispatch(loadBranches())
});
export default connect(
diff --git a/client/src/components/Commits.js b/client/src/components/Commits.js
index e573041..8a63138 100644
--- a/client/src/components/Commits.js
+++ b/client/src/components/Commits.js
@@ -6,17 +6,15 @@ import Branches from './Branches';
import './styles/Commit.css';
import CommitsCard from './CommitsCard';
import Loading from './Loading';
+import Pagination from './Pagination'
+import { LOAD_STATE } from '../redux/constants'
+
class Commits extends React.PureComponent {
componentDidMount() {
- this.props.loadCommits(this.props.branch);
- this.props.loadBuilds();
- }
-
- componentDidUpdate(prevProps) {
- if (this.props.branch !== prevProps.branch) {
- this.props.loadCommits(this.props.branch)
- this.props.loadBuilds()
+ if (this.props.firstLoad) {
+ this.props.loadCommits(this.props.branch, 1); // TODO: remove the hack
+ this.props.loadBuilds();
}
}
@@ -35,7 +33,7 @@ class Commits extends React.PureComponent {
};
render() {
- const {branch, page} = this.props;
+ const { branch, currentPage } = this.props
return (
@@ -46,7 +44,7 @@ class Commits extends React.PureComponent {
- {this.props.isLoading.load ? (
+ {this.props.isLoading ? (
@@ -60,38 +58,10 @@ class Commits extends React.PureComponent {
Err:{this.props.error}
) : (
-
-
{' '}
-
-
-
-
+ this.props.loadCommits(branch, currentPage + 1)}
+ prevPage={() => this.props.loadCommits(branch, currentPage - 1)} />
)}
)}
@@ -110,15 +80,15 @@ const mapStateToProps = ({
commits,
builders,
error,
- page,
builds,
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,
builders,
error,
- page,
builds,
tests
});
diff --git a/client/src/components/CommitsCard.js b/client/src/components/CommitsCard.js
index 4680841..5ada73e 100644
--- a/client/src/components/CommitsCard.js
+++ b/client/src/components/CommitsCard.js
@@ -1,8 +1,9 @@
import React from 'react';
+import { connect } from 'react-redux'
import { UncontrolledCollapse, CardBody, Card, CardHeader } from 'reactstrap';
import BuildDetails from './BuildDetails';
import TestDetails from './TestDetails';
-import { JOB_STATUS } from '../redux/constants'
+import { JOB_STATUS, LOAD_STATE } from '../redux/constants'
import { statusElement } from './utils'
function firstLineTrimmed(str) {
@@ -16,7 +17,7 @@ function firstLineTrimmed(str) {
}
function getTotalStatus(jobs) {
- if (!jobs.length) return null
+ if (!jobs || !jobs.length) return JOB_STATUS.NO_DATA
let ret = JOB_STATUS.SUCCESS
@@ -30,31 +31,31 @@ function getTotalStatus(jobs) {
return ret
}
-function CommitsCard({sha, ...props}) {
+function CommitsCard({sha, author, commit, loadStatus, ...props}) {
let tog = 'toggler' + sha;
- let committerDate = new Date(props.commit.committer.date);
- let authorDate = new Date(props.commit.author.date);
- let author = encodeURIComponent(props.commit.author.name);
- let committer = encodeURIComponent(props.commit.committer.name);
+ let committerDate = new Date(commit.committer.date);
+ let authorDate = new Date(commit.author.date);
+ const author_login = author ? author.login : commit.author.name
+ const builds = props.builds ? props.builds : []
+ const tests = props.tests ? props.tests : []
+
return (
{sha.substring(0, 7)}
- {" "}{firstLineTrimmed(props.commit.message)}
+ {" "}{firstLineTrimmed(commit.message)}
-
{props.author.login}
+
{author_login}
- {props.builds &&
- props.builds.length > 0
- ? statusElement(getTotalStatus(props.builds), "Build status")
- : }
+ {loadStatus.buildBot === LOAD_STATE.LOADING
+ ?
+ : statusElement(getTotalStatus(props.builds), "Build status") }
{" "}
- {props.tests &&
- props.tests.length > 0
- ? statusElement(getTotalStatus(props.tests), "Test status")
- : }
+ {loadStatus.buildBot === LOAD_STATE.LOADING
+ ?
+ : statusElement(getTotalStatus(props.tests), "Test status") }
@@ -66,13 +67,13 @@ function CommitsCard({sha, ...props}) {
{sha}
- Commit Msg: {props.commit.message}
+ Commit Msg: {commit.message}
Committer Date:
@@ -113,23 +114,15 @@ function CommitsCard({sha, ...props}) {
Build Details:
- {props.builds ? (
-
- ) : (
-
- Loading Builds...
-
- )}
+ {loadStatus.buildBot === LOAD_STATE.LOADING
+ ?
Loading builds data...
+ :
}
Test Details:
- {props.tests ? (
-
- ) : (
-
- No data Exists
-
- )}
+ {loadStatus.buildBot === LOAD_STATE.LOADING
+ ?
Loading tests data...
+ :
}
@@ -137,4 +130,9 @@ function CommitsCard({sha, ...props}) {
);
}
-export default CommitsCard;
+
+function mapStateToProps(state, ownProps) {
+ return {...ownProps, loadStatus: state.isLoading.byCommit[ownProps.sha]}
+}
+
+export default connect(mapStateToProps)(CommitsCard);
diff --git a/client/src/components/Pagination.js b/client/src/components/Pagination.js
new file mode 100644
index 0000000..9a9f09a
--- /dev/null
+++ b/client/src/components/Pagination.js
@@ -0,0 +1,30 @@
+import React from 'react'
+
+
+export default function Pagination({currentPage, nextPage, prevPage}) {
+ return (
+
+
{' '}
+
+
+
+
+ )
+}
diff --git a/client/src/components/Pulls.js b/client/src/components/Pulls.js
index 678ee9e..074ef4b 100644
--- a/client/src/components/Pulls.js
+++ b/client/src/components/Pulls.js
@@ -4,16 +4,14 @@ import { NavLink, useParams } from 'react-router-dom';
import { loadPulls } from '../redux/actions';
import './styles/Pulls.css';
import Loading from './Loading';
+import Pagination from './Pagination'
import PullsCard from './PullsCard';
+import { LOAD_STATE } from '../redux/constants'
class Pulls extends React.PureComponent {
componentDidMount() {
- this.props.loadPulls(this.props.pullState);
- }
-
- componentDidUpdate(prevProps) {
- if (this.props.pullState !== prevProps.pullState) {
- this.props.loadPulls(this.props.pullState)
+ if (this.props.firstLoad) {
+ this.props.loadPulls(this.props.pullState, 1)
}
}
@@ -30,7 +28,7 @@ class Pulls extends React.PureComponent {
);
};
render() {
- const {pullState, page} = this.props;
+ const { pullState, currentPage } = this.props;
return (
@@ -51,7 +49,7 @@ class Pulls extends React.PureComponent {
- {this.props.isLoading.load ? (
+ {this.props.isLoading ? (
) : (
@@ -63,38 +61,10 @@ class Pulls extends React.PureComponent {
Err:{this.props.error}
) : (
-
-
{' '}
-
-
-
-
+ this.props.loadPulls(pullState, currentPage + 1)}
+ prevPage={() => this.props.loadPulls(pullState, currentPage - 1)} />
)}
)}
@@ -111,16 +81,16 @@ function PullsWrapper(props) {
const mapStateToProps = ({
pulls,
builders,
- page,
isLoading,
error,
builds,
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,
builders,
- page,
- isLoading,
error,
builds,
tests
diff --git a/client/src/components/utils.js b/client/src/components/utils.js
index 69ba525..8a23b95 100644
--- a/client/src/components/utils.js
+++ b/client/src/components/utils.js
@@ -10,6 +10,8 @@ export function statusElement(status, statusText) {
return
case JOB_STATUS.FAILURE:
return
+ case JOB_STATUS.NO_DATA:
+ return
default:
return null
}
diff --git a/client/src/redux/actions/index.js b/client/src/redux/actions/index.js
index a02779a..a800f80 100644
--- a/client/src/redux/actions/index.js
+++ b/client/src/redux/actions/index.js
@@ -71,11 +71,8 @@ export const setTestmanError = error => ({
error
});
-export const setPages = (next, prev) => ({
- type: 'PAGE_LOAD_SUCCESS',
- next,
- prev
-});
+// branches
+
export const loadBranches = () => ({
type: BRANCHES.LOAD
});
diff --git a/client/src/redux/constants/index.js b/client/src/redux/constants/index.js
index 86242a3..4ba3d9d 100644
--- a/client/src/redux/constants/index.js
+++ b/client/src/redux/constants/index.js
@@ -7,7 +7,15 @@ export const PULL_STATE = {
export const JOB_STATUS = {
SUCCESS: 0,
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 = {
diff --git a/client/src/redux/reducers/index.js b/client/src/redux/reducers/index.js
index 94316db..8c6998e 100644
--- a/client/src/redux/reducers/index.js
+++ b/client/src/redux/reducers/index.js
@@ -6,7 +6,6 @@ import errorReducer from './errorReducer';
import branchReducer from './branchReducer';
import builderReducer from './builderReducer';
import pullsReducer from './pullsReducer';
-import pageReducer from './pageReducer';
import builds from './builds';
import tests from './tests'
@@ -17,7 +16,6 @@ const rootReducer = combineReducers({
branches: branchReducer,
builders: builderReducer,
pulls: pullsReducer,
- page: pageReducer,
builds,
tests
});
diff --git a/client/src/redux/reducers/loadingReducer.js b/client/src/redux/reducers/loadingReducer.js
index d46b3cb..4a2153a 100644
--- a/client/src/redux/reducers/loadingReducer.js
+++ b/client/src/redux/reducers/loadingReducer.js
@@ -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) {
- case COMMITS.LOAD:
- return { newPage: action.newPage, load: true };
-
case BUILDERS.LOAD:
- return { ...state, load: true };
-
- 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 };
+ return { ...state, buildersDataState: LOAD_STATE.LOADING }
case BUILDERS.LOAD_SUCCESS:
- return { ...state, load: true };
+ return { ...state, buildersDataState: LOAD_STATE.LOADED }
- case PULLS.LOAD_SUCCESS:
- return { ...state, load: false };
+ case COMMITS.LOAD: {
+ const commitsLoadInfo = {
+ ...state.commitsLoadInfo,
+ lastState: LOAD_STATE.LOADING,
+ lastPage: action.newPage
+ }
- case BRANCHES.LOAD_SUCCESS:
- return { newPage: action.newPage, load: true };
+ return { ...state, commitsLoadInfo}
+ }
+ case COMMITS.LOAD_SUCCESS: {
+ const byCommit = {...state.byCommit}
- case BUILD_DATA.LOAD_SUCCESS:
- return { load: false };
+ const commitsLoadInfo = {
+ ...state.commitsLoadInfo,
+ lastState: LOAD_STATE.LOADED,
+ currentPage: state.commitsLoadInfo.lastPage,
+ loadedPages: state.commitsLoadInfo.loadedPages.concat([state.commitsLoadInfo.lastPage])
+ }
- case COMMITS.LOAD_FAIL:
- return { ...state, load: false };
+ for(let commit of Object.values(action.commits))
+ {
+ byCommit[commit.sha] = {buildBot: LOAD_STATE.LOADING, tests: LOAD_STATE.LOADING}
+ }
- case PULLS.LOAD_FAIL:
- return { ...state, load: false };
+ return { ...state, byCommit, commitsLoadInfo}
+ }
+ 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:
- return { ...state, load: false };
+ return state
}
};
diff --git a/client/src/redux/reducers/pageReducer.js b/client/src/redux/reducers/pageReducer.js
deleted file mode 100644
index 792a8bf..0000000
--- a/client/src/redux/reducers/pageReducer.js
+++ /dev/null
@@ -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;
diff --git a/client/src/redux/sagas/commitsSaga.js b/client/src/redux/sagas/commitsSaga.js
index 0c45707..e9bb32a 100644
--- a/client/src/redux/sagas/commitsSaga.js
+++ b/client/src/redux/sagas/commitsSaga.js
@@ -1,21 +1,13 @@
import { throttle, call, put, select } from 'redux-saga/effects';
import { COMMITS } from '../constants';
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) {
try {
- const newPage = yield select(getNewPage);
- let commits = yield call(fetchCommits, action.branch, newPage);
+ let commits = yield call(fetchCommits, action.branch, action.newPage)
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) {
//dispatch error
yield put(setCommitsError(error.toString()));
diff --git a/client/src/redux/sagas/pullsSaga.js b/client/src/redux/sagas/pullsSaga.js
index ec7edbb..3161886 100644
--- a/client/src/redux/sagas/pullsSaga.js
+++ b/client/src/redux/sagas/pullsSaga.js
@@ -1,23 +1,16 @@
import { takeEvery, call, put, select } from 'redux-saga/effects';
import { PULLS } from '../constants';
import { fetchPulls } from '../api';
-import { setPulls, setPullsError, setPages } from '../actions';
-const getNewPage = state => parseInt(state.isLoading.newPage, 10);
+import { setPulls, setPullsError } from '../actions';
+
function* handlePullsLoad(action) {
- try {
- const newPage = yield select(getNewPage);
- let pulls = yield call(fetchPulls, action.state, newPage);
- yield put(setPulls(pulls.pulls.body));
- yield put(
- 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()));
- }
+ try {
+ let pulls = yield call(fetchPulls, action.state, action.newPage);
+ yield put(setPulls(pulls.pulls.body));
+ } catch (error) {
+ yield put(setPullsError(error.toString()));
+ }
}
export default function* watchPullsLoad() {
diff --git a/client/src/redux/sagas/pullsTestmanSaga.js b/client/src/redux/sagas/pullsTestmanSaga.js
index d2018d0..c405eab 100644
--- a/client/src/redux/sagas/pullsTestmanSaga.js
+++ b/client/src/redux/sagas/pullsTestmanSaga.js
@@ -9,7 +9,11 @@ function* handleTestmanLoad() {
const shas = pulls.map(pull => pull.merge_commit_sha);
const testResults = yield call(fetchTests, shas[9], shas[0], 1);
const testByPulls = {};
+ console.log(shas)
for (let sha of shas) {
+ // some pulls don't have merge_commit_sha
+ if (!sha) continue
+
testByPulls[sha] = testResults.filter(test =>
sha.startsWith(test.revision._text)
);