cabdriver
Version:
Helps you to fill in your hours with taxi
197 lines (182 loc) • 8.11 kB
JavaScript
;
var JiraApi = require('jira-client');
var Moment = require('moment-timezone');
var Async = require('promise-async');
var _ = require('lodash');
var helper = require('../helper');
var Source = require('./source');
class Jira extends Source {
constructor(options, auth) {
super(options, auth);
this.type = 'jira';
}
// eslint-disable-next-line max-lines-per-function
generateEntries(auth) {
var me = this;
var config = {
protocol: 'https',
host: 'jira.liip.ch',
apiVersion: '2',
strictSSL: true,
oauth: {
consumer_key: auth.consumer_key,
consumer_secret: auth.consumer_secret,
access_token: auth.access_token,
access_token_secret: auth.access_token_secret
}
};
var jira = new JiraApi(config);
var startDateObj = Moment(me.options.startDate).tz('Europe/Zurich');
var endDateObj = Moment(me.options.endDate).tz('Europe/Zurich');
var currentUser = null;
return jira.getCurrentUser()
.then(function(user) {
currentUser = user.key;
// this query is an attempt to find issues that the current user potentially worked on, unfortunately
// there is currently no better way to do it since the defined startdate
// after getting this list, each issue's changelog is checked for action of the current user
var query = '(assignee = currentUser() OR reporter = currentUser() OR ' +
'creator = currentUser() OR watcher = currentUser() OR ' +
'key in issueHistory()) AND updatedDate >= ' + startDateObj.format('YYYY-MM-DD');
return jira.searchJira(query);
})
.then(function(result) {
return Async.map(
result.issues,
function(issue, issueCb) {
jira.findIssue(issue.key, 'changelog', '*all', '*')
.then(
me.generateDailyEntries(
currentUser,
startDateObj,
endDateObj,
me.options.verbose,
issueCb
)
)
.catch(function(err) {
console.log(err);
if (err.message) {
err = err.message;
}
helper.errorVerbose(
'Error fetching issue ' + issue.key + ': ' + err, me.options.verbose
);
issueCb(null, []);
});
});
})
.then(function(results) {
return _.flatten(results);
})
.catch(function(err) {
if (err.message) {
err = err.message;
}
throw new Error('The JIRA API returned an error: ' + err);
});
}
generateDailyEntries(currentUser, startDate, endDate, verbose, callback) {
var me = this;
return function(issue) {
var changelogMsgs = me.filterChangelogEntries(issue, currentUser, startDate, endDate, verbose);
var commentMsgs = me.filterCommentEntries(issue, currentUser, startDate, endDate, verbose);
var worklogMsgs = me.filterWorklogEntries(issue, currentUser, startDate, endDate, verbose);
// use worklog entries if they exist, otherwise use changelog
if (!_.isEmpty(worklogMsgs)) {
worklogMsgs = _.uniqWith(worklogMsgs, _.isEqual);
callback(null, worklogMsgs);
} else if (!_.isEmpty(changelogMsgs)) {
changelogMsgs = _.uniqWith(changelogMsgs, _.isEqual);
callback(null, changelogMsgs);
} else {
commentMsgs = _.uniqWith(commentMsgs, _.isEqual);
callback(null, commentMsgs);
}
};
}
getProject(issue) {
var project = issue.key.split('-')[0].toLowerCase();
return project;
}
filterChangelogEntries(issue, currentUser, startDate, endDate, verbose) {
var me = this;
helper.printVerbose('Issue ' + issue.key + ' changelog: [', verbose);
var myChangelogEntries = _.filter(issue.changelog.histories, function(entry) {
var created = Moment(entry.created).startOf('day');
var match = (
entry.author.key === currentUser &&
created.isBetween(
startDate.startOf('day'), endDate.endOf('day'), null, '[]'
)
);
helper.printVerbose((match ? 'x' : '.'), verbose);
return match;
});
helper.printVerbose(']\n', verbose);
var changelogMsgs = _.map(myChangelogEntries, function(entry) {
var msg = {
'project': me.getProject(issue),
'time': '1',
'text': issue.key + ': ' + issue.fields.summary,
'timestamp': Moment.tz(entry.created, 'Europe/Zurich').startOf('day').format('X'),
'type': 'jira',
'comment': false
};
return msg;
});
changelogMsgs = _.uniq(changelogMsgs, function(msg) {
return msg.timestamp;
});
return changelogMsgs;
}
filterCommentEntries(issue, currentUser, startDate, endDate, verbose) {
var me = this;
helper.printVerbose('Issue ' + issue.key + ' comments: [', verbose);
var myComments = _.filter(issue.fields.comment.comments, function(comment) {
var created = Moment(comment.created).startOf('day');
var match = comment.author.key === currentUser && created.isBetween(startDate, endDate, null, '[]');
helper.printVerbose((match ? 'x' : '.'), verbose);
return match;
});
helper.printVerbose(']\n', verbose);
var commentMsgs = _.map(myComments, function(entry) {
var msg = {
'project': me.getProject(issue),
'time': '1',
'text': issue.key + ': ' + issue.fields.summary,
'timestamp': Moment.tz(entry.created, 'Europe/Zurich').startOf('day').format('X'),
'type': 'jira',
'comment': false
};
return msg;
});
return commentMsgs;
}
filterWorklogEntries(issue, currentUser, startDate, endDate, verbose) {
var me = this;
helper.printVerbose('Issue ' + issue.key + ' worklog: [', verbose);
var myWorklog = _.filter(issue.fields.worklog.worklogs, function(log) {
var started = Moment(log.started).startOf('day');
var match = log.author.key === currentUser && started.isBetween(startDate, endDate, null, '[]');
helper.printVerbose((match ? 'x' : '.'), verbose);
return match;
});
helper.printVerbose(']\n', verbose);
var worklogMsgs = _.map(myWorklog, function(log) {
var hours = log.timeSpentSeconds / 3600;
var text = log.comment || issue.fields.summary;
var msg = {
'project': me.getProject(issue),
'time': (Math.round(hours * 100) / 100).toString(),
'text': issue.key + ' worklog: ' + text,
'timestamp': Moment.tz(log.started, 'Europe/Zurich').startOf('day').format('X'),
'type': 'jira',
'comment': false
};
return msg;
});
return worklogMsgs;
}
}
module.exports = Jira;