diff --git a/src/js/modules/github/request.js b/src/js/modules/github/request.js index d8767db..9569b3e 100644 --- a/src/js/modules/github/request.js +++ b/src/js/modules/github/request.js @@ -56,45 +56,6 @@ export default { request(data, cb); }, - // Get all open milestones. - allMilestones: (user, { owner, name }, cb) => { - let token = (user && user.credential != null) ? user.credential.accessToken : null; - let data = _.defaults({ - 'path': `/repos/${owner}/${name}/milestones`, - 'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }, - 'headers': headers(token) - }, defaults.github); - - request(data, cb); - }, - - // Get one open milestone. - oneMilestone: (user, { owner, name, milestone }, cb) => { - let token = (user && user.credential != null) ? user.credential.accessToken : null; - let data = _.defaults({ - 'path': `/repos/${owner}/${name}/milestones/${milestone}`, - 'query': { 'state': 'open', 'sort': 'due_date', 'direction': 'asc' }, - 'headers': headers(token) - }, defaults.github); - - request(data, function(err, data) { - console.log('oneMilestone', data); - cb(err, data); - }); - }, - - // Get all issues for a state.. - allIssues: (user, { owner, name, milestone }, query, cb) => { - let token = (user && user.credential != null) ? user.credential.accessToken : null; - let data = _.defaults({ - 'path': `/repos/${owner}/${name}/issues`, - 'query': _.extend(query, { milestone, 'per_page': '100' }), - 'headers': headers(token) - }, defaults.github); - - return request(data, cb); - }, - allProjects: (user, { owner, name }, cb) => { let token = (user && user.credential != null) ? user.credential.accessToken : null; @@ -117,10 +78,8 @@ export default { }, method: 'POST', }, defaults.github); - request(data, (err, result) => { - console.log('graphql response!', err, result); - cb(err, result); - }); + + request(data, cb); }, oneProject: (user, { owner, name, project }, cb) => { @@ -147,11 +106,8 @@ export default { }, method: 'POST', }, defaults.github); - request(data, (err, result) => { - console.log('graphql response!', err, result); - // Filter down to cards that are issues (as opposed to notes) here? - cb(err, result); - }); + + request(data, cb); } }; @@ -246,6 +202,3 @@ let error = (err) => { return text; }; - -// oneMilestone: -// - returns lists of open and closed issues. \ No newline at end of file diff --git a/src/js/stores/index.js b/src/js/stores/index.js index 4349c00..d15a72c 100644 --- a/src/js/stores/index.js +++ b/src/js/stores/index.js @@ -1,8 +1,8 @@ // The app store needs to go last because it loads user. -import projectsStore from './projectsStore.js'; +import reposStore from './reposStore.js'; import appStore from './appStore.js'; export default { 'app': appStore, - 'projects': projectsStore + 'repos': reposStore }; diff --git a/src/js/stores/projectsStore.js b/src/js/stores/reposStore.js similarity index 50% rename from src/js/stores/projectsStore.js rename to src/js/stores/reposStore.js index 714834a..df0637c 100644 --- a/src/js/stores/projectsStore.js +++ b/src/js/stores/reposStore.js @@ -12,17 +12,17 @@ import stats from '../modules/stats.js'; import request from '../modules/github/request.js'; import issues from '../modules/github/issues.js'; -class ProjectsStore extends Store { +class ReposStore extends Store { // Initial payload. constructor() { - // Init the projects from local storage. - let list = lscache.get('projects') || []; + // Init the repos from local storage. + const list = lscache.get('repos') || []; super({ - // A stack of projects. - list: list, - // A sorted projects and milestones index. + // A stack of repos. + list, + // A sorted repos and projects index. 'index': [], // The default sort order. 'sortBy': 'priority', @@ -30,20 +30,20 @@ class ProjectsStore extends Store { 'sortFns': [ 'progress', 'priority', 'name' ] }); - // Listen to only projects actions. - actions.on('projects.*', (obj, event) => { + // Listen to only repos actions. + actions.on('repos.*', (obj, event) => { let fn = `on.${event}`.replace(/[.]+(\w|$)/g, (m, p) => p.toUpperCase()); // Run? (fn in this) && this[fn](obj); }); // Listen to when user is ready and save info on us. - actions.on('user.ready', (user) => this.set('user', user)); + actions.on('user.ready', user => this.set('user', user)); - // Persist projects in local storage (sans milestones and issues). + // Persist repos in local storage (sans projects and issues). this.on('list.*', () => { if (process.browser) { - lscache.set('projects', _.pluckMany(this.get('list'), [ 'owner', 'name' ])); + lscache.set('repos', _.pluckMany(this.get('list'), [ 'owner', 'name' ])); } }); @@ -56,56 +56,54 @@ class ProjectsStore extends Store { // Debounce. if (process.browser) { // easier to test - this.onProjectsSearch = _.debounce(this.onProjectsSearch, 500); + this.onReposSearch = _.debounce(this.onReposSearch, 500); } } - // Fetch milestone(s) and issues for a project(s). - onProjectsLoad(args) { - let projects = this.get('list'); + // Fetch issues for a repo(s). + onReposLoad(args) { + let repos = this.get('list'); // Reset first. - projects = _.each(projects, (p) => delete p.errors); + repos = _.each(repos, r => delete r.errors); // Wait for the user to get resolved. - this.get('user', this.cb((user) => { // async + this.get('user', this.cb(user => { // async if (args) { - if ('milestone' in args) { - // For a single milestone. - this.getMilestone(user, { + if ('project' in args) { + // For a single project. + this.getProject(user, { 'owner': args.owner, 'name': args.name - }, args.milestone, true); // notify as well - } else if ('project' in args) { - // ... + }, args.project, true); // notify as well } else { - // For a single project. - _.find(this.get('list'), (obj) => { + // For a single repo. + _.find(this.get('list'), obj => { if (args.owner == obj.owner && args.name == obj.name) { args = obj; // expand by saved properties return true; }; return false; }); - this.getProject(user, args); + this.getRepo(user, args); } } else { - // For all projects. - _.each(projects, project => this.getProject(user, project)); + // For all repos. + _.each(repos, r => this.getRepo(user, r)); } })); } // Push to the stack unless it exists already. - onProjectsAdd(project) { - if (!_.find(this.get('list'), project)) { - this.push('list', project); + onRepoAdd(repo) { + if (!_.find(this.get('list'), repo)) { + this.push('list', repo); } } - // Cycle through projects sort order. - onProjectsSort() { - let { sortBy, sortFns } = this.get(); + // Cycle through repos sort order. + onReposSort() { + const { sortBy, sortFns } = this.get(); let idx = 1 + sortFns.indexOf(sortBy); if (idx === sortFns.length) idx = 0; @@ -113,8 +111,8 @@ class ProjectsStore extends Store { this.set('sortBy', sortFns[idx]); } - // Demonstration projects. - onProjectsDemo() { + // Demonstration repos. + onReposDemo() { this.set({ 'list': [ { 'owner': 'd3', 'name': 'd3' }, @@ -125,8 +123,8 @@ class ProjectsStore extends Store { }); } - // Search for projects. - onProjectsSearch(text) { + // Search for repos. + onRepoSearch(text) { if (!text || !text.length) return; // Wait for the user to get resolved. @@ -169,10 +167,10 @@ class ProjectsStore extends Store { })); } - // Delete a project. - onProjectsDelete(project) { - let i = this.findIndex(project); - // Delete the project. + // Delete a repo. + onRepoDelete(repo) { + const i = this.findIndex(repo); + // Delete the repo. this.del(`list.${i}`); // And the index, sorting again. this.set('index', []); @@ -183,10 +181,10 @@ class ProjectsStore extends Store { comparator() { let { list, sortBy } = this.get(); - // Convert existing index into actual project milestone. + // Convert existing index into actual repo project. let deIdx = (fn) => { return ([ i, j ], ...rest) => { - return fn.apply(this, [ [ list[i], list[i].milestones[j] ] ].concat(rest)); + return fn.apply(this, [ [ list[i], list[i].projects[j] ] ].concat(rest)); }; }; @@ -205,43 +203,43 @@ class ProjectsStore extends Store { switch (sortBy) { // From highest progress points. case 'progress': - return deIdx(([ , aM ], [ , bM ]) => { - defaults([ aM, bM ], { 'stats.progress.points': 0 }); + return deIdx(([ , aP ], [ , bP ]) => { + defaults([ aP, bP ], { 'stats.progress.points': 0 }); // Simple points difference. - return aM.stats.progress.points - bM.stats.progress.points; + return aP.stats.progress.points - bP.stats.progress.points; }); // From most delayed in days. case 'priority': - return deIdx(([ , aM ], [ , bM ]) => { - // Milestones with no deadline are always at the "beginning". - defaults([ aM, bM ], { 'stats.progress.time': 0, 'stats.days': 1e3 }); + return deIdx(([ , aP ], [ , bP ]) => { + // Projects with no deadline are always at the "beginning". + defaults([ aP, bP ], { 'stats.progress.time': 0, 'stats.days': 1e3 }); // % difference in progress times the number of days ahead or behind. - let [ $a, $b ] = _.map([ aM, bM ], ({ stats }) => { + let [ $a, $b ] = _.map([ aP, bP ], ({ stats }) => { return (stats.progress.points - stats.progress.time) * stats.days; }); return $b - $a; }); - // Based on project then milestone name including semver. + // Based on repo then project name including semver. case 'name': - return deIdx(([ aP, aM ], [ bP, bM ]) => { + return deIdx(([ aR, aP ], [ bR, bP ]) => { let owner, name; - if (owner = bP.owner.localeCompare(aP.owner)) { + if (owner = bR.owner.localeCompare(aR.owner)) { return owner; } - if (name = bP.name.localeCompare(aP.name)) { + if (name = bR.name.localeCompare(aR.name)) { return name; } // Try semver. - if (semver.valid(bM.title) && semver.valid(aM.title)) { - return semver.gt(bM.title, aM.title); + if (semver.valid(bP.title) && semver.valid(aP.title)) { + return semver.gt(bP.title, aP.title); // Back to string compare. } else { - return bM.title.localeCompare(aM.title); + return bP.title.localeCompare(aP.title); } }); @@ -251,61 +249,39 @@ class ProjectsStore extends Store { } } - // Fetch milestones and issues for a project. - getProject(user, p) { - // Fetch their milestones. - request.allMilestones(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; - })) { - // Fetch all the issues for this milestone. - this.getIssues(user, p, milestone); - } + // Fetch projects in a repo. + getProjects(user, r) { + request.allProjects(user, r, this.cb((err, projects) => { // async + // Save the error if repo does not exist. + if (err) return this.saveError(r, err); + projects.forEach(obj => { + // Save the projet. + // TODO do something with obj and projects + this.addProject(r, obj, say); }); })); } - // Fetch a single milestone. - getMilestone(user, p, m, say) { - // Fetch the single milestone. - request.oneMilestone(user, { - 'owner': p.owner, - 'name': p.name, - 'milestone': m - }, this.cb((err, milestone) => { // async - // Save the error if project does not exist. - if (err) return this.saveError(p, err, say); - // Now add in the issues. - this.getIssues(user, p, milestone, say); - })); - } - - // Fetch all issues for a milestone. - getIssues(user, p, m, say) { - issues.fetchAll(user, { - 'owner': p.owner, - 'name': p.name, - 'milestone': m.number + // Fetch a single project. + getProject(user, r, p, say) { + request.oneProject(user, { + 'owner': r.owner, + 'name': r.name, + 'project': p }, this.cb((err, obj) => { // async - // Save any errors on the project. - if (err) return this.saveError(p, err, say); - // Add in the issues to the milestone. - _.extend(m, { 'issues': obj }); - // Save the milestone. - this.addMilestone(p, m, say); + // Save the error if repo does not exist. + if (err) return this.saveError(r, err, say); + // Save the projet. + // TODO do something with obj and p + this.addProject(r, obj, say); })); } - // Talk about the stats of a milestone. - notify(milestone) { - if (milestone.stats.isEmpty) { + // Talk about the stats of a project. + notify(project) { + if (project.stats.isEmpty) { let left; - if (left = milestone.issues.open.size) { + if (left = project.issues.open.size) { return actions.emit('system.notify', { 'text': `No progress has been made, ${left} point${(left > 1) ? 's' : ''} left`, 'system': true, @@ -313,7 +289,7 @@ class ProjectsStore extends Store { }); } else { return actions.emit('system.notify', { - 'text': 'This milestone has no issues', + 'text': 'This project has no issues', 'type': 'warn', 'system': true, 'ttl': null @@ -321,66 +297,66 @@ class ProjectsStore extends Store { } } - if (milestone.stats.isDone) { + if (project.stats.isDone) { actions.emit('system.notify', { - 'text': 'This milestone is complete', + 'text': 'This project is complete', 'type': 'success' }); } - if (milestone.stats.isOverdue) { + if (project.stats.isOverdue) { actions.emit('system.notify', { - 'text': 'This milestone is overdue', + 'text': 'This project is overdue', 'type': 'warn' }); } } - // Add a milestone for a project. - addMilestone(project, milestone, say) { + // Add a project for a repo. + addProject(repo, project, say) { // Add in the stats. let i, j; - _.extend(milestone, { 'stats': stats(milestone) }); + _.extend(project, { 'stats': stats(project) }); // Notify? - if (say) this.notify(milestone); + if (say) this.notify(project); - // If project hasn't been found, add it behind the scenes. - if ((i = this.findIndex(project)) < 0) { - i = this.push('list', project); + // If repo hasn't been found, add it behind the scenes. + if ((i = this.findIndex(repo)) < 0) { + i = this.push('list', repo); } - // Does the milestone exist already? - let milestones; - if (milestones = this.get(`list.${i}.milestones`)) { - j = _.findIndex(milestones, { 'number': milestone.number }); + // Does the project exist already? + let projects; + if (projects = this.get(`list.${i}.projects`)) { + j = _.findIndex(projects, { 'number': project.number }); // Just make an update then. if (j != -1) { - return this.set(`list.${i}.milestones.${j}`, milestone); + return this.set(`list.${i}.projects.${j}`, project); } } - // Push the milestone and return the index. - j = this.push(`list.${i}.milestones`, milestone); + // Push the project and return the index. + j = this.push(`list.${i}.projects`, project); - // Now index this milestone. - this.sort([ i, j ], [ project, milestone ]); + // Now index this project. + this.sort([ i, j ], [ repo, project ]); } - // Find index of a project. + // Find index of a repo. findIndex({ owner, name }) { return _.findIndex(this.get('list'), { owner, name }); } - // Save an error from loading milestones or issues. - // TODO: clear these when we fetch all projects anew. - saveError(project, err, say=false) { + // Save an error from loading projects. + // TODO: clear these when we fetch all repos anew. + saveError(repo, err, say=false) { var idx; - if ((idx = this.findIndex(project)) > -1) { + if ((idx = this.findIndex(repo)) > -1) { this.push(`list.${idx}.errors`, err); } else { - // Create the stub project behind the scenes. - this.push('list', _.extend({}, project, { 'errors': [ err ] })); + // Create the stub repo behind the scenes. + this.push('list', _.extend({}, repo, { 'errors': [ err ] })); } // Notify? @@ -393,29 +369,29 @@ class ProjectsStore extends Store { }); } - // Sort projects (update the index). Can pass reference to the - // project and milestone index in the stack. + // Sort repos (update the index). Can pass reference to the + // repo and project index in the stack. sort(ref, data) { let idx; // Get the existing index. - let index = this.get('index'); + const index = this.get('index'); - // Index one milestone in an already sorted index. + // Index one project in an already sorted index. if (ref) { idx = sortedIndex(index, data, this.comparator()); index.splice(idx, 0, ref); // Sort them all. } else { - let list = this.get('list'); + const list = this.get('list'); for (let i = 0; i < list.length; i++) { - let p = list[i]; - // TODO: need to show projects that failed too... - if (p.milestones == null) continue; - // Walk the milestones. - for (let j = 0; j < p.milestones.length; j++) { - let m = p.milestones[j]; + const r = list[i]; + // TODO: need to show repos that failed too... + if (r.projects == null) continue; + // Walk the projects. + for (let j = 0; j < r.projects.length; j++) { + const p = r.projects[j]; // Run a comparator here inserting into index. - idx = sortedIndex(index, [ p, m ], this.comparator()); + idx = sortedIndex(index, [ r, p ], this.comparator()); index.splice(idx, 0, [ i, j ]); } } @@ -424,7 +400,7 @@ class ProjectsStore extends Store { this.set('index', index); } - // Do we have this project? Case-insensitive. + // Do we have this repo? Case-insensitive. has(o, n) { o = o.toUpperCase() ; n = n.toUpperCase(); return !!_.find(this.get('list'), ({ owner, name }) => { @@ -434,4 +410,4 @@ class ProjectsStore extends Store { } -export default new ProjectsStore(); +export default new ReposStore();