Skip to content

Commit

Permalink
Support GitLab Issues
Browse files Browse the repository at this point in the history
Move GitHub Tasks to github namespace `/tasks/github`
Add a new gitlab route `/tasks/gitlab`
Add a new gitlab serializer

Closes coala#38
  • Loading branch information
bekicot committed Jul 12, 2018
1 parent c520198 commit 101c4b0
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 8 deletions.
4 changes: 4 additions & 0 deletions app/controllers/tasks/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Controller from '@ember/controller';

export default Controller.extend({
});
2 changes: 1 addition & 1 deletion app/data/organizations.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default {
},
{
type: 'gitlab',
identifier: 'coala',
identifier: 'coala/mobans',
},
],
},
Expand Down
3 changes: 3 additions & 0 deletions app/models/gitlab-task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import TaskModel from './task';

export default TaskModel.extend({});
1 change: 1 addition & 0 deletions app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Router = EmberRouter.extend({
Router.map(function mainRoute() {
return this.route('tasks', function tasksRoute() {
this.route('github');
this.route('gitlab');
});
});

Expand Down
23 changes: 23 additions & 0 deletions app/routes/tasks/gitlab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Route from '@ember/routing/route';
import { inject } from '@ember/service';

export default Route.extend({
gitlab: inject(),
store: inject(),
organizations: inject(),

model(params, transition) {
const { org } = transition.queryParams;
const store = this.get('store');
const projects = this.get('organizations').fetchGitlabProjects(org);
if (projects.length > 0) {
return this.get('gitlab').tasks({ projects }).then((data) => {
data.forEach((task) => {
store.pushPayload('gitlab-task', task);
});
return store.peekAll('gitlab-task');
});
}
return [];
},
});
30 changes: 30 additions & 0 deletions app/serializers/gitlab-task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import DS from 'ember-data';

export default DS.JSONSerializer.extend({
pushPayload(store, payload) {
const task = {};
task.id = payload.id;
task.bodyText = payload.description;
task.commentCount = payload.user_notes_count;
// Set the default color to 65C8FF, otherwise, we need to refetch the default
// color from `project/:id/labels` endpoint.
task.labels = payload.labels.map(label => ({ color: '65C8FF', name: label }));
task.updatedAt = payload.updated_at;
task.title = payload.title;
task.url = payload.web_url;

task.author = {};
task.author.url = payload.author.web_url;
task.author.login = payload.author.username;
task.author.avatarUrl = payload.author.avatar_url;

task.repository = {};
task.repository.nameWithOwner = payload.repository.path_with_namespace;
task.repository.url = payload.repository.web_url;

task.isPullRequest = payload._type === 'PullRequest';

store.push(this.normalize(store.modelFor('gitlab-task'), task));
return task;
},
});
50 changes: 50 additions & 0 deletions app/services/gitlab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// https://gitlab.com/api/v4/projects/coala%2Fmobans/issues?order_by=created_at&state=opened
import AjaxService from 'ember-ajax/services/ajax';
import RSVP from 'rsvp';

const ENDPOINT = 'https://gitlab.com/api/v4';
const PROJECT_ENDPOINT = `${ENDPOINT}/projects/{projectId}`;
const ISSUE_ENDPOINT = `${PROJECT_ENDPOINT}/issues?order_by=created_at&state=opened&per_page=100`;

function buildIssuesUrl(projectId) {
return ISSUE_ENDPOINT.replace('{projectId}', encodeURIComponent(projectId));
}

function buildProjectUrl(projectId) {
return PROJECT_ENDPOINT.replace('{projectId}', encodeURIComponent(projectId));
}

export default AjaxService.extend({
host: 'https://gitlab.com/',
_issueUrl: '',
init(...arg) {
this._super(...arg);
this.set('headers', { 'Private-Token': 'sVfZzagWtemrV-suxYK-' });
},

tasks({ projects }) {
const tasks = projects.map((projectId) => {
const embedRepoInfo = taskList => this.fetchRepositoryInfo(projectId)
.then(repoInfo => taskList.map((task) => {
const decoratedTask = Object.assign({}, task);
decoratedTask.repository = repoInfo;
decoratedTask.type = 'gitlab-task';
return decoratedTask;
}));
return this.fetchIssues(projectId).then(embedRepoInfo);
});

return RSVP.all(tasks).then(taskList =>
taskList
.reduce((combinedTasks, initialTasklist) => combinedTasks.concat(initialTasklist), []));
},

fetchRepositoryInfo(projectId) {
return this.request(buildProjectUrl(projectId));
},

fetchIssues(projectId) {
return this.request(buildIssuesUrl(projectId));
},

});
18 changes: 16 additions & 2 deletions app/services/organizations.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Object, { computed } from '@ember/object';
import EmberObject, { computed } from '@ember/object';
import Service from '@ember/service';
import organizations from '../data/organizations';

export default Service.extend({
init(...args) {
this._super(...args);
this.organizations = Object.create(organizations);
this.organizations = EmberObject.create(organizations);
},

list: computed('organizations', function getOrganizationList() {
Expand All @@ -15,4 +15,18 @@ export default Service.extend({
fetch(slug) {
return this.organizations.get(slug);
},

fetchGitlabProjects(slug) {
const { trackers } = this.fetch(slug);
if (!trackers) {
return [];
}
return trackers.reduce((previous, tracker) => {
if (tracker.type === 'gitlab') {
return [...previous, tracker.identifier];
}
return previous;
}, []);
},

});
5 changes: 0 additions & 5 deletions app/templates/tasks.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@
</aside>
</section>
<div class="column is-three-quarters">
<nav class="panel">
<p class="panel-tabs is-size-4">
<a class="is-active {{if isGithubpage "disabled"}}">GitHub</a>
</p>
</nav>
{{outlet}}
</div>
</div>
9 changes: 9 additions & 0 deletions app/templates/tasks/github.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
<nav class="panel">
<p class="panel-tabs is-size-4">
<a class="is-active" disabled>GitHub</a>
<a>|</a>
{{#link-to 'tasks.gitlab'}}
GitLab
{{/link-to}}
</p>
</nav>
{{#each tasks as |task|}}
{{task-item task=task}}
<hr>
Expand Down
16 changes: 16 additions & 0 deletions app/templates/tasks/gitlab.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<nav class="panel">
<p class="panel-tabs is-size-4">
{{#link-to 'tasks.github'}}
GitHub
{{/link-to}}
<a>|</a>
<a class="is-active" disabled>GitLab</a>
</p>
</nav>
{{#each model as |task|}}
{{task-item task=task}}
<hr>
{{/each}}
{{#unless model}}
<p>This Org doesn't have any gitlab repository.</p>
{{/unless}}
24 changes: 24 additions & 0 deletions tests/acceptance/tasks/list-gitlab-tasks-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Service from '@ember/service';
import { visit, find } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';

// Simulating empty gitlab Projects
const emptyGitlabOrgService = Service.extend({
fetchGitlabProjects: () => [],
fetch: () => ({}),
});

module('Acceptance/tasks/list-gitlab-tasks-test', function listGitlabTaskTests(hooks) {
setupApplicationTest(hooks);

hooks.beforeEach(function beforeEach() {
this.owner.register('service:organizations', emptyGitlabOrgService);
});

test('should show no gitlab repository', async function listGitlabTasks(assert) {
await visit('/tasks/gitlab?org=discourse');
const $noGitlabRepo = find('.is-three-quarters > p');
assert.equal($noGitlabRepo.innerText, "This Org doesn't have any gitlab repository.");
});
});

0 comments on commit 101c4b0

Please sign in to comment.