DIsplay basic repo list

This commit is contained in:
Jake Howard 2016-02-23 23:12:32 +00:00
parent 659849cdee
commit 8c4f61506a
6 changed files with 130 additions and 24 deletions

View file

@ -6,15 +6,34 @@ function JSONify(response) {
return response.json(); return response.json();
} }
const [GET] = ['GET'];
export function checkToken(possibleToken) { export function checkToken(possibleToken) {
const url = endpoints.get('USER_INFO'); const url = endpoints.get('USER_INFO');
return request(url, 'GET', {}, possibleToken).then(function (response) { return request(url, GET, {}, possibleToken).then(function (response) {
return response.ok; return response.ok;
}); });
} }
export async function getUserDetails() {
const CIToken = await token.get();
const url = endpoints.get('USER_INFO');
return await request(url, GET, {}, CIToken).then(JSONify);
}
export async function getProjects() { export async function getProjects() {
const CIToken = await token.get(); const CIToken = await token.get();
const url = endpoints.get('ALL_PROJECTS'); const url = endpoints.get('ALL_PROJECTS');
return await request(url, 'GET', {}, CIToken).then(JSONify); return await request(url, GET, {}, CIToken).then(JSONify);
}
export async function getProjectRecentBuilds(user, repo) {
const CIToken = await token.get();
const url = endpoints.get('PROJECT_RECENTS').param({ user, repo });
return await request(
url,
GET,
{},
CIToken)
.then(JSONify);
} }

View file

@ -5,5 +5,7 @@ const URL_BASE = UrlAssembler('https://circleci.com/api/v1');
export default Map({ export default Map({
USER_INFO: URL_BASE.segment('/me'), USER_INFO: URL_BASE.segment('/me'),
ALL_PROJECTS: URL_BASE.segment('/projects') ALL_PROJECTS: URL_BASE.segment('/projects'),
RECENT_BUILDS: URL_BASE.segment('/recent-builds'),
PROJECT_RECENTS: URL_BASE.template('/project/:user/:repo')
}); });

View file

@ -32,7 +32,7 @@ export default class extends React.Component {
<View style={styles.container}> <View style={styles.container}>
<Component <Component
nav={nav} nav={nav}
currentRoute={props.route} currentRoute={route}
{...props} /> {...props} />
<BusyIndicator /> <BusyIndicator />
</View> </View>

View file

@ -1,15 +1,84 @@
import React from 'react-native'; import React from 'react-native';
import GlobalStyles from '../../settings/styles';
import { getProjectRecentBuilds } from '../../api/CircleCI';
var { const {
View, View,
Text, Text,
StyleSheet, StyleSheet
} = React; } = React;
const styles = StyleSheet.create({
container: {
flex: 1,
height: 70,
alignItems: 'stretch',
backgroundColor: GlobalStyles.get('CIRCLE_ITEM_BG'),
borderBottomColor: GlobalStyles.get('CIRCLE_ITEM_BORDER'),
borderBottomWidth: 1,
marginBottom: 5,
flexDirection: 'row'
},
cell: {
paddingHorizontal: 4,
paddingVertical: 2
},
imageCell: {
width: 45,
},
repoName: {
fontSize: 14,
fontWeight: '500'
}
});
export default class ProjectItem extends React.Component { export default class ProjectItem extends React.Component {
render() { constructor() {
super();
this.state = {
recentBuild: false
};
this._displayMoreInfo = this._displayMoreInfo.bind(this);
}
componentDidMount() {
getProjectRecentBuilds(this.props.project.username, this.props.project.reponame).then(function (recentBuild) {
this.setState({ recentBuild: recentBuild[0] });
}.bind(this));
}
_displayMoreInfo(mostRecentBuild) {
let seconds = Math.floor(mostRecentBuild.build_time_millis / 1000);
const minutes = Math.floor(seconds / 60);
seconds = seconds - (minutes * 60);
const format = minutes + ':' + seconds;
return ( return (
<Text>{this.props.project.reponame}</Text> <Text>{ format }</Text>
);
}
render() {
console.log(this.props.userDetails);
const project = this.props.project;
const mostRecentBuild = this.state.recentBuild;
const statusColour = mostRecentBuild.failed ? '#ED5C5C' : '#42C88A';
let username;
if (this.props.userDetails && this.props.userDetails.login !== project.username) {
username = project.username;
} else {
username = 'me';
}
const buildDetails = mostRecentBuild ? this._displayMoreInfo(mostRecentBuild) : null;
return (
<View style={styles.container}>
<View style={[styles.imageCell, {backgroundColor: statusColour}]}>
</View>
<View style={styles.cell}>
<Text style={styles.repoName}>{username}/{project.reponame}</Text>
{ buildDetails }
</View>
</View>
); );
} }
}; };

View file

@ -2,20 +2,19 @@ import React from 'react-native';
import ProjectItem from './ProjectItem'; import ProjectItem from './ProjectItem';
var { const {
ListView, ListView,
StyleSheet, StyleSheet,
Text,
ScrollView ScrollView
} = React; } = React;
var styles = StyleSheet.create({ const styles = StyleSheet.create({
composerListView: { listView: {
flex: 1, flex: 1,
flexDirection: 'row', flexDirection: 'column',
alignItems: 'stretch',
justifyContent: 'center', justifyContent: 'center',
flexWrap: 'wrap', flexWrap: 'wrap',
padding: 15
}, },
}); });
@ -23,24 +22,32 @@ export default class ProjectList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
console.log(JSON.stringify(this.props.data)); const sortedProjects = this._sortByDate(this.props.data);
this.state = { this.state = {
dataSource: ds.cloneWithRows(this.props.data) dataSource: ds.cloneWithRows(sortedProjects),
}; };
this.renderRow = this.renderRow.bind(this); this.renderRow = this.renderRow.bind(this);
} }
_sortByDate(projects) {
return projects.sort(function (a, b) {
const keyA = a.username + '/' + a.reponame;
const keyB = b.reponame + '/' + b.username;
if (keyA < keyB) { return -1; }
if (keyA > keyB) { return 1; }
return 0;
}.bind(this));
}
renderRow(project) { renderRow(project) {
return ( return <ProjectItem project={project} userDetails={this.props.userDetails} />;
<ProjectItem project={project} />
);
} }
render() { render() {
return ( return (
<ScrollView> <ScrollView>
<ListView <ListView
contentContainerStyle={styles.composerListView} contentContainerStyle={styles.listView}
dataSource={this.state.dataSource} dataSource={this.state.dataSource}
renderRow={this.renderRow} /> renderRow={this.renderRow} />
</ScrollView> </ScrollView>

View file

@ -1,12 +1,12 @@
import React from 'react-native'; import React from 'react-native';
import { getProjects } from '../../api/CircleCI'; import { getProjects, getUserDetails } from '../../api/CircleCI';
import loaderHandler from 'react-native-busy-indicator/LoaderHandler'; import loaderHandler from 'react-native-busy-indicator/LoaderHandler';
import ProjectList from '../projects/ProjectList'; import ProjectList from '../projects/ProjectList';
import GlobalStyles from '../../settings/styles'; import GlobalStyles from '../../settings/styles';
const { const {
StyleSheet, StyleSheet,
Text,
View, View,
BackAndroid, BackAndroid,
} = React; } = React;
@ -23,7 +23,8 @@ export default class Home extends React.Component {
super(); super();
this.state = { this.state = {
projects: '' projects: '',
userDetails: ''
}; };
} }
@ -37,18 +38,26 @@ export default class Home extends React.Component {
} }
componentDidMount() { componentDidMount() {
this.props.nav.navigationContext.addListener('didfocus', function () {
this.props.nav.immediatelyResetRouteStack([this.props.currentRoute]);
}.bind(this));
getProjects().then(function (data) { getProjects().then(function (data) {
this.setState({ this.setState({
projects: data projects: data
}); });
}.bind(this)); }.bind(this));
getUserDetails().then(function (userDetails) {
this.setState({userDetails});
}.bind(this));
} }
render() { render() {
let list; let list;
if (this.state.projects) { if (this.state.projects) {
list = ( list = (
<ProjectList data={this.state.projects} /> <ProjectList data={this.state.projects} userDetails={this.state.userDetails} />
); );
loaderHandler.hideLoader(); loaderHandler.hideLoader();
} else { } else {