Skip to content

Commit 8e70cec

Browse files
committed
Support GitLab Issues
Move GitHub Tasks to github namespace `/tasks/github` Add a new gitlab route `/tasks/gitlab` Add a new gitlab serializer Closes #38
1 parent 7572626 commit 8e70cec

File tree

18 files changed

+220
-48
lines changed

18 files changed

+220
-48
lines changed

app/controllers/tasks.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ import {inject} from '@ember/service';
44
export default Controller.extend({
55
organizations: inject(),
66
queryParams: ['org'],
7+
78
});

app/controllers/tasks/github.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Controller from '@ember/controller';
2+
3+
export default Controller.extend({
4+
5+
});

app/models/gitlab-task.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import TaskModel from './task';
2+
3+
export default TaskModel.extend({});

app/router.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ const Router = EmberRouter.extend({
77
});
88

99
Router.map(function() {
10-
this.route('tasks');
10+
this.route('tasks', function() {
11+
this.route('gitlab');
12+
this.route('github');
13+
});
1114
});
1215

1316
export default Router;

app/routes/tasks.js

+4-37
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,11 @@ export default Route.extend({
1414
},
1515
},
1616

17-
currentOrg: computed('params.org', function () {
18-
return this.get('organizations').fetch(this.get('params')['org']);
19-
}),
20-
21-
model(params) {
22-
this.set('params', params);
23-
let org = this.get('organizations').fetch(params['org']);
24-
let githubParams = [];
25-
let store = this.get('store');
26-
27-
if(org && org.trackers){
28-
githubParams = org.trackers
29-
.filter((tracker) => tracker.type == 'github')
30-
.map((tracker) => tracker.identifier);
31-
} else {
32-
throw 'Unsupported Org';
33-
}
34-
35-
let tasks = this.github.tasks({orgs: githubParams});
36-
tasks.then((data) => {
37-
data.forEach(function(task) {
38-
task.organization = params['org'];
39-
store.pushPayload('github-task', task);
40-
});
41-
return data;
42-
});
43-
44-
const onlySelectedOrg = (task) => {
45-
return task.organization == params['org'];
46-
}
47-
48-
return tasks.then(() => {
49-
return this.store.peekAll('github-task').filter(onlySelectedOrg);
50-
});
17+
beforeModel(transition) {
18+
this.set('currentOrg', transition.queryParams['org']);
5119
},
5220

53-
setupController(controller, model) {
21+
setupController(controller) {
5422
controller.set('currentOrg', this.get('currentOrg'));
55-
controller.set('tasks', model);
56-
},
23+
}
5724
});

app/routes/tasks/github.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Route from '@ember/routing/route';
2+
import {inject} from '@ember/service';
3+
import {getTrackerIdentifiers} from '../../utils/task-utils';
4+
5+
export default Route.extend({
6+
// services
7+
github: inject(),
8+
organizations: inject(),
9+
store: inject(),
10+
11+
model(params, transition) {
12+
let currentOrg = transition.queryParams['org']
13+
let org = this.get('organizations').fetch(currentOrg);
14+
let store = this.get('store');
15+
let github = this.get('github');
16+
let identifiers = getTrackerIdentifiers(org, 'github');
17+
18+
let tasks = github.tasks({orgs: identifiers});
19+
tasks.then((data) => {
20+
data.forEach(function(task) {
21+
task.organization = currentOrg;
22+
store.pushPayload('github-task', task);
23+
});
24+
return data;
25+
});
26+
27+
const onlySelectedOrg = (task) => {
28+
return task.organization == currentOrg;
29+
}
30+
31+
return tasks.then(() => {
32+
return store.peekAll('github-task').filter(onlySelectedOrg);
33+
});
34+
},
35+
36+
setupController(controller, model) {
37+
controller.set('tasks', model);
38+
},
39+
});

app/routes/tasks/gitlab.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Route from '@ember/routing/route';
2+
import {inject} from '@ember/service';
3+
4+
export default Route.extend({
5+
gitlab: inject(),
6+
store: inject(),
7+
model() {
8+
const store = this.get('store');
9+
return this.get('gitlab').tasks({projects: ['coala/mobans']}).then(data => {
10+
for (let task of data) {
11+
store.pushPayload('gitlab-task', task);
12+
}
13+
return store.peekAll('gitlab-task');
14+
});
15+
}
16+
});

app/routes/tasks/index.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Route from '@ember/routing/route';
2+
3+
export default Route.extend({
4+
beforeModel(transition) {
5+
if (transition.queryParams['org']) {
6+
this.transitionTo('tasks.github');
7+
} else {
8+
this.transitionTo('/');
9+
}
10+
},
11+
});

app/serializers/gitlab-task.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import DS from 'ember-data';
2+
3+
export default DS.JSONSerializer.extend({
4+
pushPayload(store, payload) {
5+
const task = {};
6+
task.id = payload.id
7+
task.bodyText = payload.description
8+
task.commentCount = payload.user_notes_count
9+
task.updatedAt = payload.updated_at
10+
task.url = payload.web_url
11+
task.title = payload.title
12+
13+
task.author = {}
14+
task.author.url = payload.author.web_url
15+
task.author.login = payload.author.username
16+
task.author.avatarUrl = payload.author.avatar_url
17+
18+
task.repository = {}
19+
task.repository.nameWithOwner = payload.repository.path_with_namespace
20+
task.repository.url = payload.repository.web_url
21+
22+
task.isPullRequest = payload._type == 'PullRequest';
23+
24+
store.push(this.normalize(store.modelFor('gitlab-task'), task));
25+
return task;
26+
},
27+
});

app/services/gitlab.js

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// https://gitlab.com/api/v4/projects/coala%2Fmobans/issues?order_by=created_at&state=opened
2+
import AjaxService from 'ember-ajax/services/ajax';
3+
import RSVP from 'rsvp';
4+
5+
const ENDPOINT = 'https://gitlab.com/api/v4';
6+
const PROJECT_ENDPOINT = ENDPOINT + '/projects/{projectId}'
7+
const ISSUE_ENDPOINT = PROJECT_ENDPOINT + '/issues?order_by=created_at&state=opened&per_page=100';
8+
9+
function buildIssuesUrl(projectId) {
10+
return ISSUE_ENDPOINT.replace('{projectId}', encodeURIComponent(projectId));
11+
}
12+
13+
function buildProjectUrl(projectId) {
14+
return PROJECT_ENDPOINT.replace('{projectId}', encodeURIComponent(projectId));
15+
}
16+
17+
export default AjaxService.extend({
18+
host: 'https://gitlab.com/',
19+
_issueUrl: '',
20+
init() {
21+
this._super(...arguments);
22+
this.set('headers', {'Private-Token': 'sVfZzagWtemrV-suxYK-'});
23+
},
24+
25+
tasks({projects}) {
26+
let tasks = projects.map((projectId) => {
27+
const embedRepoInfo = (tasks) => {
28+
return new Promise((resolve, reject) => {
29+
this.fetchRepositoryInfo(projectId).then((repoInfo) => {
30+
tasks.map((task) => {
31+
task.repository = repoInfo;
32+
task.type = 'gitlab-task';
33+
return task;
34+
})
35+
resolve(tasks)
36+
}).catch((error) => reject(error));
37+
});
38+
}
39+
40+
return this.fetchIssues(projectId).then(embedRepoInfo)
41+
});
42+
43+
return RSVP.all(tasks).then((tasks) => {
44+
return tasks.reduce((combinedTasks, tasks) => {
45+
return combinedTasks.concat(tasks);
46+
}, [])
47+
})
48+
},
49+
50+
fetchRepositoryInfo(projectId) {
51+
return this.request(buildProjectUrl(projectId));
52+
},
53+
54+
fetchIssues(projectId) {
55+
return this.request(buildIssuesUrl(projectId));
56+
},
57+
58+
});

app/templates/tasks.hbs

+7-10
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,16 @@
1414
</p>
1515
<ul class="menu-list">
1616
{{#each-in organizations.list as |slug org| }}
17-
<li>
18-
{{#link-to "tasks" (query-params org=slug)}}
19-
{{org.name}}
20-
{{/link-to}}
21-
</li>
17+
<li>
18+
{{#link-to (query-params org=slug)}}
19+
{{org.name}}
20+
{{/link-to}}
21+
</li>
2222
{{/each-in}}
2323
</ul>
2424
</aside>
2525
</section>
2626
<div class="column is-three-quarters">
27-
{{#each tasks as |task|}}
28-
{{task-item task=task}}
29-
<hr>
30-
{{/each}}
27+
{{outlet}}
3128
</div>
32-
</div>
29+
</div>

app/templates/tasks/github.hbs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<nav class="panel">
2+
<p class="panel-tabs is-size-4">
3+
<a class="is-active" disabled>GitHub</a>
4+
<a>|</a>
5+
{{#link-to 'tasks.gitlab'}}
6+
GitLab
7+
{{/link-to}}
8+
</p>
9+
</nav>
10+
{{#each tasks as |task|}}
11+
{{task-item task=task}}
12+
<hr>
13+
{{/each}}

app/templates/tasks/gitlab.hbs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<nav class="panel">
2+
<p class="panel-tabs is-size-4">
3+
{{#link-to 'tasks.github'}}
4+
GitHub
5+
{{/link-to}}
6+
<a>|</a>
7+
<a class="is-active" disabled>GitLab</a>
8+
</p>
9+
</nav>
10+
{{#each model as |task|}}
11+
{{task-item task=task}}
12+
<hr>
13+
{{/each}}

app/templates/tasks/index.hbs

Whitespace-only changes.

app/templates/tasks/loading.hbs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="is-loading">
2+
Loading...
3+
</div>

app/utils/task-utils.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const getTrackerIdentifiers = (org, trackerType) => {
2+
if(org && org.trackers){
3+
return org.trackers
4+
.filter((tracker) => tracker.type == trackerType)
5+
.map((tracker) => tracker.identifier);
6+
} else {
7+
return [];
8+
}
9+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@fortawesome/ember-fontawesome": "^0.1.0-8",
2121
"@fortawesome/free-solid-svg-icons": "^5.1.0-8",
2222
"broccoli-asset-rev": "^2.4.5",
23+
"ember-ajax": "^3.1.0",
2324
"ember-cli": "~3.1.4",
2425
"ember-cli-app-version": "^3.2.0",
2526
"ember-cli-babel": "^6.6.0",

yarn.lock

+6
Original file line numberDiff line numberDiff line change
@@ -2384,6 +2384,12 @@ electron-to-chromium@^1.3.47:
23842384
version "1.3.48"
23852385
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz#d3b0d8593814044e092ece2108fc3ac9aea4b900"
23862386

2387+
ember-ajax@^3.1.0:
2388+
version "3.1.0"
2389+
resolved "https://registry.yarnpkg.com/ember-ajax/-/ember-ajax-3.1.0.tgz#3db36e67357ef447639517656aeac4bb13e73a9c"
2390+
dependencies:
2391+
ember-cli-babel "^6.6.0"
2392+
23872393
23882394
version "0.3.5"
23892395
resolved "https://registry.yarnpkg.com/ember-ast-helpers/-/ember-ast-helpers-0.3.5.tgz#db72afd9bc3de03759720ff7b03d4e3b2c7f2351"

0 commit comments

Comments
 (0)