show a list of milestones for a project

This commit is contained in:
Radek Stepan 2016-01-18 20:52:24 +01:00
parent fee4d13696
commit eec0259fea
5 changed files with 109 additions and 56 deletions

View File

@ -92,6 +92,8 @@ export default React.createClass({
// Show project milestones.
milestones(owner, name) {
document.title = `${owner}/${name}`;
process.nextTick(() => { actions.emit('projects.load', { owner, name }); });
return <MilestonesPage owner={owner} name={name} />;
},

View File

@ -11,7 +11,7 @@ import Link from './Link.jsx';
export default React.createClass({
displayName: 'Projects.jsx',
displayName: 'Milestones.jsx',
mixins: [ Format ],
@ -20,7 +20,7 @@ export default React.createClass({
},
render() {
let projects = this.props.projects;
let { projects, project } = this.props;
// Show the projects with errors first.
let errors = _(projects.list).filter('errors').map((project, i) => {
@ -36,12 +36,16 @@ export default React.createClass({
);
}).value();
// Now for the list of projects.
let list = _.map(projects.index, ([ pI, mI ]) => {
// Now for the list of milestones.
let list = [];
_.each(projects.index, ([ pI, mI ]) => {
let { owner, name, milestones } = projects.list[pI];
let milestone = milestones[mI];
return (
// Filter down?
if (!(!project || (project.owner == owner && project.name == name))) return;
list.push(
<tr className={cls({ 'done': milestone.stats.isDone })} key={`${pI}-${mI}`}>
<td className="repo">
<Link route={{ 'to': 'milestones', 'params': { owner, name } }} className="project">
@ -74,21 +78,38 @@ export default React.createClass({
// Wait for something to show.
if (!errors.length && !list.length) return false;
return (
<div id="projects">
<div className="header">
<a className="sort" onClick={this._onSort}><Icon name="sort"/> Sorted by {projects.sortBy}</a>
<h2>Projects</h2>
if (project) {
return (
<div id="projects">
<div className="header">
<a className="sort" onClick={this._onSort}><Icon name="sort"/> Sorted by {projects.sortBy}</a>
<h2>Milestones</h2>
</div>
<table>
<tbody>
{list}
</tbody>
</table>
<div className="footer" />
</div>
<table>
<tbody>
{errors}
{list}
</tbody>
</table>
<div className="footer" />
</div>
);
);
} else {
return (
<div id="projects">
<div className="header">
<a className="sort" onClick={this._onSort}><Icon name="sort"/> Sorted by {projects.sortBy}</a>
<h2>Projects</h2>
</div>
<table>
<tbody>
{errors}
{list}
</tbody>
</table>
<div className="footer" />
</div>
);
}
}
});

View File

@ -4,6 +4,8 @@ import Page from '../mixins/Page.js';
import Notify from '../components/Notify.jsx';
import Header from '../components/Header.jsx';
import Milestones from '../components/Milestones.jsx';
import Hero from '../components/Hero.jsx';
export default React.createClass({
@ -12,12 +14,25 @@ export default React.createClass({
mixins: [ Page ],
render() {
let content;
if (!this.state.app.loading) {
let projects = this.state.projects;
content = <Milestones projects={projects} project={this.props} />;
}
return (
<div>
<Notify />
<Header {...this.state} />
<div id="page" />
<div id="page">
<div id="title">
<div className="wrap">
<h2 className="title">{this.props.owner}/{this.props.name}</h2>
</div>
</div>
<div id="content" className="wrap">{content}</div>
</div>
<div id="footer">
<div className="wrap">

View File

@ -4,7 +4,7 @@ import Page from '../mixins/Page.js';
import Notify from '../components/Notify.jsx';
import Header from '../components/Header.jsx';
import Projects from '../components/Projects.jsx';
import Milestones from '../components/Milestones.jsx';
import Hero from '../components/Hero.jsx';
export default React.createClass({
@ -18,8 +18,7 @@ export default React.createClass({
if (!this.state.app.loading) {
let projects = this.state.projects;
if (projects.list.length) {
// Show a list of projects.
content = <Projects projects={projects} />;
content = <Milestones projects={projects} />;
} else {
content = <Hero />;
}

View File

@ -59,46 +59,62 @@ class ProjectsStore extends Store {
});
}
// Start fetching milestones and issues for projects.
onProjectsLoad() {
// Fetch milestones and issues for a project(s).
onProjectsLoad(project) {
let projects = this.get('list');
// Quit if we have no projects.
if (!projects.length) return;
// Fetch milestones and issues for a project.
let get = (user, p) => {
// Fetch their milestones.
milestones.fetchAll(user, p, this.cb((err, milestones) => { // async
// Save the error if project does not exist.
if (err) return this.saveError(p, err);
// Now add in the issues.
milestones.forEach((milestone) => {
// Do we have this milestone already? Skip fetching issues then.
if (_.find(p.milestones, ({ number }) => {
return milestone.number === number;
})) {
return;
}
// OK fetch all the issues for this milestone then.
issues.fetchAll(user, {
'owner': p.owner,
'name': p.name,
'milestone': milestone.number
}, this.cb((err, obj) => { // async
// Save any errors on the project.
if (err) return this.saveError(p, err);
// Add in the issues to the milestone.
_.extend(milestone, { 'issues': obj });
// Save the milestone.
this.addMilestone(p, milestone);
}));
});
}));
};
// Wait for the user to get resolved.
this.get('user', this.cb((user) => { // async
// For all projects.
projects.forEach((project) => {
// Fetch their milestones.
milestones.fetchAll(user, project, this.cb((err, milestones) => { // async
// Save the error if project does not exist.
if (err) return this.saveError(project, err);
// Now add in the issues.
milestones.forEach((milestone) => {
// Do we have this milestone already? Skip fetching issues then.
if (_.find(project.milestones, ({ number }) => {
return milestone.number === number;
})) {
return;
}
// OK fetch all the issues for this milestone then.
issues.fetchAll(user, {
'owner': project.owner,
'name': project.name,
'milestone': milestone.number
}, this.cb((err, obj) => { // async
// Save any errors on the project.
if (err) return this.saveError(project, err);
// Add in the issues to the milestone.
_.extend(milestone, { 'issues': obj });
// Save the milestone.
this.addMilestone(project, milestone);
}));
});
}));
});
if (project) {
// For a single project.
_.find(this.get('list'), (obj) => {
if (project.owner == obj.owner && project.name == obj.name) {
project = obj; // expand by saved properties
return true;
};
return false;
});
// For a single project.
get(user, project);
} else {
// For all projects.
projects.forEach(_.partial(get, user));
}
}));
}