From a587e30046e04d6771d4cad1b96650a7d7a26232 Mon Sep 17 00:00:00 2001 From: Maciej Garycki Date: Wed, 27 Apr 2016 12:30:58 +0200 Subject: [PATCH] tiny refactor: moved view preparing to common view builder, added command skeleton #14 --- app.js | 3 +- app/services/cronjobs/jobs/forecast.js | 2 +- app/services/forecast/view.js | 97 +++++++++++++++ .../lib/actions/schedule.js | 95 +++++++++++++++ app/services/slack/notifier/forecast.js | 110 ++---------------- 5 files changed, 206 insertions(+), 101 deletions(-) create mode 100644 app/services/forecast/view.js create mode 100644 app/services/interactive_session/lib/actions/schedule.js diff --git a/app.js b/app.js index 07d65eb..8b8b275 100644 --- a/app.js +++ b/app.js @@ -20,7 +20,8 @@ var notifier = require('./app/services/notifier'), reportNotifier = require('./app/services/report')(slack, harvest), slackNotifier = require('./app/services/slack/notifier')(slack, harvest), - slackForecastNotifier = require('./app/services/slack/notifier/forecast')(slack, harvest), + forecastViewBuilder = require('./app/services/forecast/view.js'), + slackForecastNotifier = require('./app/services/slack/notifier/forecast')(slack, harvest, forecastViewBuilder), slackReminder = require('./app/services/slack/notifier/remind')(slack, harvest), i18n = require('i18n'), forecast = require('./app/services/forecast')('default', config.forecast), diff --git a/app/services/cronjobs/jobs/forecast.js b/app/services/cronjobs/jobs/forecast.js index b8ee38e..21a404d 100644 --- a/app/services/cronjobs/jobs/forecast.js +++ b/app/services/cronjobs/jobs/forecast.js @@ -66,7 +66,7 @@ var */ shouldRunNow : function (config) { - return false; + return true; }, diff --git a/app/services/forecast/view.js b/app/services/forecast/view.js new file mode 100644 index 0000000..02add81 --- /dev/null +++ b/app/services/forecast/view.js @@ -0,0 +1,97 @@ +/*jshint node: true*/ +'use strict'; + +var _ = require('lodash'), + tools = require('./../tools.js'), + i18n = require('i18n'), + viewBuilder = { + + /** + * Aggregates assignments by user + * + * @param {Object} assignments + * @returns {Object} + */ + aggregateByUser : function (assignments) + { + var results = {}; + _.each(assignments, function (assignment) { + var person = assignment.person, + harvestUserId = person ? person.harvest_user_id : null + ; + + if (harvestUserId) { + results[harvestUserId] = results[harvestUserId] || { + person : person, + assignments : [] + }; + + results[harvestUserId].assignments.push(assignment); + } + }); + + return results; + }, + + format : function (title, text) + { + return "\n" + [title, text].join("\n") + "\n"; + }, + + /** + * + * @param {Object} userAssignments + * @returns {undefined} + */ + prepareTitle : function (userAssignments) + { + + var name = userAssignments.person.first_name + ' ' + userAssignments.person.last_name; + return '*' + i18n.__('Projects assignments schedule for {{name}}:', { + name : name + }) + '*'; + + }, + + + /** + * prepares the text and triggers propper event when ready + * + * @param {Object} userAssignments + * @returns {undefined} + */ + prepareText : function (userAssignments) + { + var results = []; + + _.each(userAssignments.assignments, function (assignment) { + var text = [], + project = assignment.project, + client = project ? assignment.project.client : null, + timeSeconds = assignment.allocation, + timeText = tools.formatSeconds(Number(timeSeconds)) + ; + + text.push(timeText); + if (client) { + text.push(client.name); + } + if (project) { + text.push(project.name); + } + + if (!project && !client) { + text.push(i18n.__('N/A')); + } + + results.push(text.join(' - ')); + }); + + return results.join("\n"); + } + } +; + + + +module.exports = viewBuilder; \ No newline at end of file diff --git a/app/services/interactive_session/lib/actions/schedule.js b/app/services/interactive_session/lib/actions/schedule.js new file mode 100644 index 0000000..1a7ed55 --- /dev/null +++ b/app/services/interactive_session/lib/actions/schedule.js @@ -0,0 +1,95 @@ +/*jshint node: true*/ +'use strict'; + +var + scheduleProvider, + interactiveSession = require('./../user_session.js'), + tools = require('./../../../tools.js'), + _ = require('lodash'), + viewBuilder = require('./../../../forecast/view'), + forecast = require('./../../../forecast')('default'), + i18n = require('i18n'), + logger = require('./../../../logger.js')('default'), + StepProvider = require('./../step_provider.js'), + moment = require('moment') +; + +scheduleProvider = new StepProvider('schedule'); +scheduleProvider.addStep(1, { + execute : function (params, callback) + { + var that = this, + action = tools.validateGet(params, 'action'), + userId = params.userId, + assignmentsByUser, + userAssignments + ; + + + if (forecast === null) { + return null; + } + var options = { + startDate : moment().startOf('day'), + endDate : moment().endOf('day') + }; + + forecast.assignments(options, function (error, assignments) { + if (error) { + logger.error(i18n.__('Failed loading forecast schedule.', {})); + callback(error, null); + return; + } else { + logger.info(i18n.__('Successfully loaded forecast schedule.'), {}); + + assignmentsByUser = viewBuilder.aggregateByUser(assignments); + userAssignments = !!assignmentsByUser[userId] ? assignmentsByUser[userId] : null; + if (!userAssignments) { + callback(that.getView(null), null); + return; + } + + step = interactiveSession + .getDefault() + .createStep(userId, {}, action) + ; + step.addParam('userAssignments', userAssignments); + callback(null, step); + } + }); + }, + + postExecute: function (step, callback) + { + var userId = step.getParam('userId'); + interactiveSession + .getDefault() + .clear(userId) + ; + callback(); + }, + prepareStep: function (step) + { + return null; + }, + + getView: function (step) + { + var userAssignments, + view, + errorString = i18n.__('Currently you have no tasks scheduled.') + ; + + if (step === null) { + view = errorString; + } else { + userAssignments = step.getParam('userAssignments'); + view = viewBuilder.getView(userAssignments); + } + + + return view; + } +}); + +module.exports = scheduleProvider; \ No newline at end of file diff --git a/app/services/slack/notifier/forecast.js b/app/services/slack/notifier/forecast.js index 9d0221f..7243593 100644 --- a/app/services/slack/notifier/forecast.js +++ b/app/services/slack/notifier/forecast.js @@ -4,7 +4,6 @@ var _ = require('lodash'), events = require("events"), logger = require('./../../logger.js')('default'), - tools = require('./../../tools.js'), i18n = require('i18n'), instance = null ; @@ -30,40 +29,6 @@ function getUserName (users, harvestUserId) } -/** - * Aggregates assignments by user - * - * @param {Object} assignments - * @returns {Object} - */ -function aggregateByUser (assignments) -{ - var results = {}; - _.each(assignments, function (assignment) { - var person = assignment.person, - harvestUserId = person ? person.harvest_user_id : null - ; - - if (harvestUserId) { - results[harvestUserId] = results[harvestUserId] || { - person : person, - assignments : [] - }; - - results[harvestUserId].assignments.push(assignment); - } - }); - - return results; -} - - -function format (title, text) -{ - return "\n" + [title, text].join("\n") + "\n"; -} - - /** * Sends notifications via slack * @@ -71,18 +36,19 @@ function format (title, text) * * @param {Object} slack The slack object * @param {Object} harvest The harvest object + * @param {Object} viewBuilder Forecast slack message view builder * @constructor */ -function SlackNotifier (slack, harvest) +function SlackNotifier (slack, harvest, viewBuilder) { this.slack = slack; this.harvest = harvest; + this.viewBuilder = viewBuilder; } var SlackNotifierPrototype = function () { - /** * Sends notification to slack * @@ -93,23 +59,23 @@ var SlackNotifierPrototype = function () { var that = this, assignments = slackContext.assignments, - assignmentsByUser = aggregateByUser(assignments) + assignmentsByUser = that.viewBuilder.aggregateByUser(assignments) ; _.each(assignmentsByUser, function (userAssignments, harvestId) { if (!userAssignments.assignments.length) { return; } - var text = that.prepareText(userAssignments), - title = that.prepareTitle(userAssignments), - slackId = getUserName(that.slack.users, harvestId), - fullText = format(title, text) + + + var slackId = getUserName(that.slack.users, harvestId), + view = that.viewBuilder.getView(userAssignments) ; if (!slackId) { return; } - that.slack.sendMessage(fullText, { + that.slack.sendMessage(view, { channel : '@' + slackId }, function (err, httpResponse, body) { if (err === null) { @@ -120,60 +86,6 @@ var SlackNotifierPrototype = function () }); }); }; - - - - /** - * - * @param {Object} userAssignments - * @returns {undefined} - */ - this.prepareTitle = function (userAssignments) - { - - var name = userAssignments.person.first_name + ' ' + userAssignments.person.last_name; - return '*' + i18n.__('Projects assignments schedule for {{name}}:', { - name : name - }) + '*'; - - } - - - /** - * prepares the text and triggers propper event when ready - * - * @param {Object} userAssignments - * @returns {undefined} - */ - this.prepareText = function (userAssignments) - { - var results = []; - - _.each(userAssignments.assignments, function (assignment) { - var text = [], - project = assignment.project, - client = project ? assignment.project.client : null, - timeSeconds = assignment.allocation, - timeText = tools.formatSeconds(Number(timeSeconds)) - ; - - text.push(timeText); - if (client) { - text.push(client.name); - } - if (project) { - text.push(project.name); - } - - if (!project && !client) { - text.push(i18n.__('N/A')); - } - - results.push(text.join(' - ')); - }); - - return results.join("\n"); - }; }; SlackNotifierPrototype.prototype = new events.EventEmitter(); @@ -182,8 +94,8 @@ SlackNotifierPrototype.prototype = new events.EventEmitter(); SlackNotifier.prototype = new SlackNotifierPrototype(); SlackNotifier.prototype.constructor = SlackNotifier; -module.exports = function (slack, harvest) { - instance = new SlackNotifier(slack, harvest); +module.exports = function (slack, harvest, viewBuilder) { + instance = new SlackNotifier(slack, harvest, viewBuilder); module.exports.instance = instance; return instance;