From 8fc894559c5915e2e01a80dedb192e5d797640d8 Mon Sep 17 00:00:00 2001 From: RealOrangeOne Date: Fri, 11 Mar 2016 20:56:26 +0000 Subject: [PATCH] Add list of recent builds --- app/components/builds/BuildItem.js | 75 +++++++++++++++++++++++- app/components/builds/BuildList.js | 12 +++- app/components/projects/ProjectItem.js | 2 +- app/components/routes/project-details.js | 51 ++++++++++++++-- 4 files changed, 130 insertions(+), 10 deletions(-) diff --git a/app/components/builds/BuildItem.js b/app/components/builds/BuildItem.js index b1ecdce..76c8e67 100644 --- a/app/components/builds/BuildItem.js +++ b/app/components/builds/BuildItem.js @@ -1,6 +1,8 @@ import React from 'react-native'; import GlobalStyles from '../../settings/styles'; import Icon from 'react-native-vector-icons/Octicons'; +import moment from 'moment'; +import { timeSince } from '../../helpers/time-utils'; const { View, @@ -18,11 +20,82 @@ const styles = StyleSheet.create({ borderBottomColor: GlobalStyles.get('CIRCLE_ITEM_BORDER'), borderBottomWidth: 2, flexDirection: 'row', + }, + button: { + marginVertical: 2.5, + }, + repoCell: { + paddingHorizontal: 4, + paddingVertical: 3, + flex: 0.84 + }, + buildCell: { + flex: 0.25, + padding: 4, + borderLeftColor: GlobalStyles.get('CIRCLE_ITEM_BORDER'), + borderLeftWidth: 1 + }, + colourPanel: { + flex: 0.02 + }, + repoName: { + fontSize: 15, + fontWeight: '500' + }, + details: { + fontSize: 12.5, + fontWeight: '300', + }, + detailsRow: { + flex: 1, + flexDirection: 'row' } }); export default class BuildItem extends React.Component { + constructor(props) { + super(props); + this._displayMoreInfo = this._displayMoreInfo.bind(this); + } + + _displayMoreInfo(build) { + const mask = build.build_time_millis <= 60000 ? 'ss[s]' : 'm:ss'; + const buildTime = moment.duration(build.build_time_millis, 'ms').format(mask); + const commit = build.all_commit_details[0]; + return ( + + + { this.props.statusColour } + + { buildTime } + { commit.commit.substring(0, 6) } + + ); + } + render() { - return null; + const build = this.props.build; + const buildDetails = this._displayMoreInfo(build); + return ( + + + + {build.branch} - #{build.build_num} + + + {timeSince(moment(build.stop_time).toDate())} ago + + + + { build.subject } + + + { buildDetails } + + + + ); } }; diff --git a/app/components/builds/BuildList.js b/app/components/builds/BuildList.js index 48d1f61..8202760 100644 --- a/app/components/builds/BuildList.js +++ b/app/components/builds/BuildList.js @@ -1,4 +1,5 @@ import React from 'react-native'; +import GlobalStyles from '../../settings/styles'; import BuildItem from './BuildItem'; const { @@ -21,10 +22,17 @@ const styles = StyleSheet.create({ export default class BuildList extends React.Component { constructor(props) { super(props); + const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); + this.state = { + dataSource: ds.cloneWithRows(this.props.builds), + }; } renderRow(build) { - return ; + const statusColour = build.status === 'failed' ? + GlobalStyles.get('CIRCLE_TEST_FAIL') : + GlobalStyles.get('CIRCLE_TEST_PASS'); + return ; } render() { @@ -33,7 +41,7 @@ export default class BuildList extends React.Component { + renderRow={this.renderRow.bind(this)} /> ); } diff --git a/app/components/projects/ProjectItem.js b/app/components/projects/ProjectItem.js index 1d31bbd..fae262a 100644 --- a/app/components/projects/ProjectItem.js +++ b/app/components/projects/ProjectItem.js @@ -46,7 +46,6 @@ const styles = StyleSheet.create({ details: { fontSize: 12.5, fontWeight: '300', - marginLeft: 3 }, detailsRow: { flex: 1, @@ -75,6 +74,7 @@ export default class ProjectItem extends React.Component { _viewBuildDetails() { const destination = RouteMaster.get('PROJECT_DETAILS'); + destination.title = this.props.project.reponame; destination.props = { project: this.props.project }; diff --git a/app/components/routes/project-details.js b/app/components/routes/project-details.js index c08135c..70a7e80 100644 --- a/app/components/routes/project-details.js +++ b/app/components/routes/project-details.js @@ -1,15 +1,15 @@ import React from 'react-native'; import { getProjectRecentBuilds } from '../../api/CircleCI'; import loaderHandler from 'react-native-busy-indicator/LoaderHandler'; -// import BuildList from '../builds/BuildList'; +import BuildList from '../builds/BuildList'; import GlobalStyles from '../../settings/styles'; - +import _ from 'underscore'; const { StyleSheet, View, BackAndroid, - Text + Text, } = React; const styles = StyleSheet.create({ @@ -24,6 +24,17 @@ const styles = StyleSheet.create({ statusHeading: { fontSize: 18, textAlign: 'center' + }, + statusRow: { + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'center', + }, + panel: { + alignItems: 'stretch', + borderBottomColor: GlobalStyles.get('CIRCLE_NAVBAR_TEXT'), + borderBottomWidth: 2, + paddingVertical: 10 } }); @@ -31,14 +42,42 @@ export default class ProjectDetails extends React.Component { constructor(props) { super(props); this.state = { - project: props.currentRoute.props.project + project: props.currentRoute.props.project, + recentBuilds: false }; } + + componentWillMount() { + loaderHandler.showLoader('Fetching Data'); + } + + componentDidMount() { + getProjectRecentBuilds(this.state.project.username, this.state.project.reponame, 30).then(function (recentBuilds) { + recentBuilds = _.sortBy(recentBuilds, (b) => b.stop_time).reverse(); + this.setState({ recentBuilds }); + }.bind(this)); + } + render() { + const master = this.state.project.branches[this.state.project.default_branch].recent_builds[0]; + const statusStyle = master.outcome === 'failed' ? + { color: GlobalStyles.get('CIRCLE_TEST_FAIL')} : + { color: GlobalStyles.get('CIRCLE_TEST_PASS')}; + let list = null; + if (this.state.recentBuilds) { + loaderHandler.hideLoader(); + list = ( ); + } return ( - {this.state.project.reponame} - Status: + + Recent Builds + + Status: + {master.outcome} + + + { list } ); }