Add list of recent builds
This commit is contained in:
parent
df83d61f7a
commit
8fc894559c
4 changed files with 130 additions and 10 deletions
|
@ -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 (
|
||||
<View style={styles.buildCell}>
|
||||
<Text style={styles.details}>
|
||||
<Icon name="info" /> { this.props.statusColour }
|
||||
</Text>
|
||||
<Text style={styles.details}><Icon name="clock" /> { buildTime }</Text>
|
||||
<Text style={styles.details}><Icon name="git-commit" /> { commit.commit.substring(0, 6) }</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
const build = this.props.build;
|
||||
const buildDetails = this._displayMoreInfo(build);
|
||||
return (
|
||||
<TouchableHighlight
|
||||
style={styles.button}
|
||||
underlayColor={GlobalStyles.get('CIRCLE_BG')}>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.repoCell}>
|
||||
<Text style={styles.repoName}>{build.branch} - #{build.build_num}</Text>
|
||||
<View style={styles.detailsRow}>
|
||||
<Text style={styles.details}>
|
||||
<Icon name="clock" /> {timeSince(moment(build.stop_time).toDate())} ago
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.detailsRow}>
|
||||
<Text style={styles.details}><Icon name="comment-discussion" /> { build.subject }</Text>
|
||||
</View>
|
||||
</View>
|
||||
{ buildDetails }
|
||||
<View style={[styles.colourPanel, {backgroundColor: this.props.statusColour}]} />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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 <BuildItem build={build} />;
|
||||
const statusColour = build.status === 'failed' ?
|
||||
GlobalStyles.get('CIRCLE_TEST_FAIL') :
|
||||
GlobalStyles.get('CIRCLE_TEST_PASS');
|
||||
return <BuildItem build={build} project={this.props.project} statusColour={statusColour} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -33,7 +41,7 @@ export default class BuildList extends React.Component {
|
|||
<ListView
|
||||
contentContainerStyle={styles.listView}
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this.renderRow} />
|
||||
renderRow={this.renderRow.bind(this)} />
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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 = ( <BuildList builds={this.state.recentBuilds} project={this.state.project}/> );
|
||||
}
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>{this.state.project.reponame}</Text>
|
||||
<Text style={styles.statusHeading}>Status: </Text>
|
||||
<View style={styles.panel}>
|
||||
<Text style={styles.title}>Recent Builds</Text>
|
||||
<View style={styles.statusRow}>
|
||||
<Text style={styles.statusHeading}>Status: </Text>
|
||||
<Text style={[styles.statusHeading, statusStyle]}>{master.outcome}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{ list }
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
Reference in a new issue