Skip to content

Commit dcaef1c

Browse files
authored
Merge pull request #90 from ngoctay/feature/dev-challenges
Timeline and Milestone REST API + Misc Fixes
2 parents da3da62 + 157bb75 commit dcaef1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+10306
-372
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Authentication is handled via Authorization (Bearer) token header field. Token i
6262
```
6363
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbmlzdHJhdG9yIl0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJwc2hhaDEiLCJleHAiOjI0NjI0OTQ2MTgsInVzZXJJZCI6IjQwMTM1OTc4IiwiaWF0IjoxNDYyNDk0MDE4LCJlbWFpbCI6InBzaGFoMUB0ZXN0LmNvbSIsImp0aSI6ImY0ZTFhNTE0LTg5ODAtNDY0MC04ZWM1LWUzNmUzMWE3ZTg0OSJ9.XuNN7tpMOXvBG1QwWRQROj7NfuUbqhkjwn39Vy4tR5I
6464
```
65-
It's been signed with the secret 'secret'. This secret should match your entry in config/local.json. You can generate your own token using https://jwt.io
65+
It's been signed with the secret 'secret'. This secret should match your entry in config/local.js. You can generate your own token using https://jwt.io
6666

6767
### Local Deployment
6868
Build image:

config/custom-environment-variables.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"host": "PROJECTS_ES_URL",
1010
"apiVersion": "2.3",
1111
"indexName": "PROJECTS_ES_INDEX_NAME",
12-
"docType": "projectV4"
12+
"docType": "projectV4",
13+
"timelineIndexName": "TIMELINES_ES_INDEX_NAME",
14+
"timelineDocType": "TIMELINES_ES_DOC_TYPE"
1315
},
1416
"rabbitmqURL": "RABBITMQ_URL",
1517
"pubsubQueueName": "PUBSUB_QUEUE_NAME",

config/default.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
"host": "",
2121
"apiVersion": "2.3",
2222
"indexName": "projects",
23-
"docType": "projectV4"
23+
"docType": "projectV4",
24+
"timelineIndexName": "timelines",
25+
"timelineDocType": "timelineV4"
2426
},
2527
"systemUserClientId": "",
2628
"systemUserClientSecret": "",

config/test.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"host": "http://localhost:9200",
88
"apiVersion": "2.3",
99
"indexName": "projects_test",
10-
"docType": "projectV4"
10+
"docType": "projectV4",
11+
"timelineIndexName": "timelines_test",
12+
"timelineDocType": "timelineV4"
1113
},
1214
"rabbitmqUrl": "amqp://localhost:5672",
1315
"dbConfig": {

migrations/elasticsearch_sync.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import util from '../src/util';
1616

1717
const ES_PROJECT_INDEX = config.get('elasticsearchConfig.indexName');
1818
const ES_PROJECT_TYPE = config.get('elasticsearchConfig.docType');
19+
const ES_TIMELINE_INDEX = config.get('elasticsearchConfig.timelineIndexName');
1920

2021
// create new elasticsearch client
2122
// the client modifies the config object, so always passed the cloned object
@@ -323,10 +324,14 @@ esClient.indices.delete({
323324
ignore: [404],
324325
})
325326
.then(() => esClient.indices.create(getRequestBody(ES_PROJECT_INDEX)))
327+
// Re-create timeline index
328+
.then(() => esClient.indices.delete({ index: ES_TIMELINE_INDEX, ignore: [404] }))
329+
.then(() => esClient.indices.create({ index: ES_TIMELINE_INDEX }))
326330
.then(() => {
327331
console.log('elasticsearch indices synced successfully');
328332
process.exit();
329-
}).catch((err) => {
333+
})
334+
.catch((err) => {
330335
console.error('elasticsearch indices sync failed', err);
331336
process.exit();
332337
});

migrations/seedElasticsearchIndex.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import config from 'config';
66
import Promise from 'bluebird';
77
import models from '../src/models';
88
import RabbitMQService from '../src/services/rabbitmq';
9+
import { TIMELINE_REFERENCES } from '../src/constants';
910

1011
const logger = bunyan.createLogger({ name: 'init-es', level: config.get('logLevel') });
1112

@@ -23,6 +24,19 @@ function getProjectIds() {
2324
return [];
2425
}
2526

27+
/**
28+
* Retrieve timeline ids from cli if provided
29+
* @return {Array} list of timelineIds
30+
*/
31+
function getTimelineIds() {
32+
let timelineIdArg = _.find(process.argv, a => a.indexOf('timelineIds') > -1);
33+
if (timelineIdArg) {
34+
timelineIdArg = timelineIdArg.split('=');
35+
return timelineIdArg[1].split(',').map(i => parseInt(i, 10));
36+
}
37+
return [];
38+
}
39+
2640
Promise.coroutine(function* wrapped() {
2741
try {
2842
const rabbit = new RabbitMQService(logger);
@@ -58,12 +72,48 @@ Promise.coroutine(function* wrapped() {
5872
logger.info(`Retrieved #${members.length} members`);
5973
members = _.groupBy(members, 'projectId');
6074

75+
// Get timelines
76+
const timelineIds = getTimelineIds();
77+
const timelineWhereClause = (timelineIds.length > 0) ? { id: { $in: timelineIds } } : {};
78+
let timelines = yield models.Timeline.findAll({
79+
where: timelineWhereClause,
80+
include: [{ model: models.Milestone, as: 'milestones' }],
81+
});
82+
logger.info(`Retrieved #${projects.length} timelines`);
83+
84+
// Convert to raw json and remove unnecessary fields
85+
timelines = _.map(timelines, (timeline) => {
86+
const entity = _.omit(timeline.toJSON(), ['deletedBy', 'deletedAt']);
87+
entity.milestones = _.map(entity.milestones, milestone => _.omit(milestone, ['deletedBy', 'deletedAt']));
88+
return entity;
89+
});
90+
91+
// Get projectId for each timeline
92+
yield Promise.all(
93+
_.map(timelines, (timeline) => {
94+
if (timeline.reference === TIMELINE_REFERENCES.PROJECT) {
95+
timeline.projectId = timeline.referenceId;
96+
return Promise.resolve(timeline);
97+
}
98+
99+
return models.ProjectPhase.findById(timeline.referenceId)
100+
.then((phase) => {
101+
timeline.projectId = phase.projectId;
102+
return Promise.resolve(timeline);
103+
});
104+
}),
105+
);
106+
61107
const promises = [];
62108
_.forEach(projects, (p) => {
63109
p.members = members[p.id];
64110
logger.debug(`Processing Project #${p.id}`);
65111
promises.push(rabbit.publish('project.initial', p, {}));
66112
});
113+
_.forEach(timelines, (t) => {
114+
logger.debug(`Processing Timeline #${t.id}`);
115+
promises.push(rabbit.publish('timeline.initial', t, {}));
116+
});
67117
Promise.all(promises)
68118
.then(() => {
69119
logger.info(`Published ${promises.length} msgs`);

0 commit comments

Comments
 (0)