From b75be7fff49dc0476e5145d3eacdfed6b34d0016 Mon Sep 17 00:00:00 2001 From: Chris Brame Date: Sat, 7 Nov 2015 13:31:09 -0500 Subject: [PATCH] Ticket Subscribers --- src/controllers/api/v1/tickets.js | 41 ++++++++++- src/controllers/api/v1/users.js | 6 ++ src/controllers/debug.js | 73 +++++++++++++++++++ src/controllers/index.js | 4 +- src/emitter/events.js | 62 +++++++++------- src/helpers/hbs/helpers.js | 11 +++ src/helpers/utils/index.js | 8 ++ src/mailer/index.js | 1 + .../templates/ticket-comment-added/html.hbs | 49 +++++++++++++ src/mailer/templates/ticket-updated/html.hbs | 37 ++++++++++ src/models/ticket.js | 44 ++++++++--- .../js/angularjs/controllers/singleTicket.js | 16 ++++ src/public/js/modules/socket.io/ticketsUI.js | 35 +++------ src/public/js/modules/ui.js | 6 +- src/routes/index.js | 2 + src/socketserver.js | 32 +++++--- src/views/subviews/profile.hbs | 12 +++ src/views/subviews/singleticket.hbs | 28 +++++-- 18 files changed, 385 insertions(+), 82 deletions(-) create mode 100644 src/controllers/debug.js create mode 100644 src/mailer/templates/ticket-comment-added/html.hbs create mode 100644 src/mailer/templates/ticket-updated/html.hbs diff --git a/src/controllers/api/v1/tickets.js b/src/controllers/api/v1/tickets.js index 3c2755c47..674ebd3e4 100644 --- a/src/controllers/api/v1/tickets.js +++ b/src/controllers/api/v1/tickets.js @@ -115,6 +115,12 @@ api_tickets.get = function(req, res) { * @apiVersion 0.1.0 * @apiGroup Ticket * @apiHeader {string} accesstoken The access token for the logged in user + * + * @apiParamExample {json} Request-Example: + * { + * "subject": "Subject", + * } + * * @apiExample Example usage: * curl -H "accesstoken: {accesstoken}" -l http://localhost/api/v1/tickets * @@ -159,6 +165,7 @@ api_tickets.create = function(req, res) { ticket.issue = marked(tIssue); ticket.tags = tags; ticket.history = [HistoryItem]; + ticket.subscribers = [req.user._id]; ticket.save(function(err, t) { if (err) { response.success = false; @@ -405,7 +412,6 @@ api_tickets.removeAttachment = function(req, res) { var fs = require('fs'); var path = require('path'); var dir = path.join(__dirname, '../../../../public', a.path); - console.log(dir); if (fs.existsSync(dir)) fs.unlinkSync(dir); ticket.save(function(err, t) { @@ -417,4 +423,37 @@ api_tickets.removeAttachment = function(req, res) { }); }; +api_tickets.subscribe = function(req, res) { + var ticketId = req.params.id; + var data = req.body; + if (_.isUndefined(data.user) || _.isUndefined(data.subscribe)) return res.status(400).json({'error': 'Invalid Payload.'}); + + var ticketModel = require('../../../models/ticket'); + ticketModel.getTicketById(ticketId, function(err, ticket) { + if (err) return res.status(400).json({'error': 'Invalid Ticket Id'}); + + async.series([ + function(callback) { + if (data.subscribe) { + ticket.addSubscriber(data.user, function() { + callback(); + }); + } else { + ticket.removeSubscriber(data.user, function() { + callback(); + }); + } + } + ], function() { + ticket.save(function(err) { + if (err) return res.status(400).json({'error': err}); + + emitter.emit('ticket:subscribers:update'); + + res.json({'success': true}); + }); + }); + }); +}; + module.exports = api_tickets; \ No newline at end of file diff --git a/src/controllers/api/v1/users.js b/src/controllers/api/v1/users.js index f4d35a57c..78d701e7c 100644 --- a/src/controllers/api/v1/users.js +++ b/src/controllers/api/v1/users.js @@ -93,6 +93,12 @@ api_users.update = function(req, res) { * @apiExample Example usage: * curl -H "Content-Type: application/json" -H "accesstoken: {accesstoken}" -X PUT -d "{\"preference\":\"{preference_name}\",\"value\":{value}}" -l http://localhost/api/v1/users/{username}/updatepreferences * + * @apiParamExample {json} Request: + * { + * "preference": "preference_name", + * "value": "preference_value" + * } + * * @apiSuccess {object} user Saved User Object [Stripped] * * @apiError InvalidPostData The data was invalid diff --git a/src/controllers/debug.js b/src/controllers/debug.js new file mode 100644 index 000000000..91f45aa5e --- /dev/null +++ b/src/controllers/debug.js @@ -0,0 +1,73 @@ +/* + . .o8 oooo + .o8 "888 `888 + .o888oo oooo d8b oooo oooo .oooo888 .ooooo. .oooo.o 888 oooo + 888 `888""8P `888 `888 d88' `888 d88' `88b d88( "8 888 .8P' + 888 888 888 888 888 888 888ooo888 `"Y88b. 888888. + 888 . 888 888 888 888 888 888 .o o. )88b 888 `88b. + "888" d888b `V88V"V8P' `Y8bod88P" `Y8bod8P' 8""888P' o888o o888o + ======================================================================== + Created: 11/06/2015 + Author: Chris Brame + + **/ + +var async = require('async'); +var path = require('path'); +var _ = require('underscore'); +var _s = require('underscore.string'); +var flash = require('connect-flash'); +var userSchema = require('../models/user'); +var reports = require('../models/report'); +var permissions = require('../permissions'); +var mongoose = require('mongoose'); +var winston = require('winston'); + +var debugController = {}; + +debugController.content = {}; + +debugController.sendmail = function(req, res, next) { + var mailer = require('../mailer'); + var emailTemplates = require('email-templates'); + var templateDir = path.resolve(__dirname, '..', 'mailer', 'templates'); + + emailTemplates(templateDir, function(err, template) { + if (err) { + winston.error(err); + } else { + + template('ticket-updated', function(err, html) { + if (err) { + winston.error(err); + } else { + var mailOptions = { + from: 'no-reply@trudesk.io', + to: 'chris.brame@granvillecounty.org', + subject: 'Trudesk Launch', + html: html, + generateTextFromHTML: true + }; + + mailer.sendMail(mailOptions, function(err, info) { + if (err) { + winston.warn(err); + return res.send(err); + } + + + return res.status(200).send('OK'); + }); + } + }); + } + }); +}; + +function handleError(res, err) { + if (err) { + return res.render('error', {layout: false, error: err, message: err.message}); + } +} + +module.exports = debugController; \ No newline at end of file diff --git a/src/controllers/index.js b/src/controllers/index.js index 95973a350..e0c1babd7 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -21,7 +21,9 @@ var Controllers = { groups: require('./groups'), reports: require('./reports'), notices: require('./notices'), - api: require('./api') + api: require('./api'), + + debug: require('./debug') }; module.exports = Controllers; diff --git a/src/emitter/events.js b/src/emitter/events.js index fb862b150..fecece8be 100644 --- a/src/emitter/events.js +++ b/src/emitter/events.js @@ -196,8 +196,8 @@ var notifications = require('../notifications'); // Load Push Events var mailer = require('../mailer'); var emails = []; async.each(ticket.subscribers, function(member, cb) { - if (_.isUndefined(member.email)) return cb(); - if (member._id.toString() == comment.owner._id.toString()) return cb(); + if (_.isUndefined(member) || _.isUndefined(member.email)) return cb(); + if (member._id.toString() == comment.owner.toString()) return cb(); emails.push(member.email); @@ -212,38 +212,44 @@ var notifications = require('../notifications'); // Load Push Events winston.warn('[trudesk:events:sendSubscriberEmail] - Error: ' + err.message); return c(err); } else { - var locals = { - ticket: ticket, - comment: comment - }; - - template('ticket-comment-added', locals, function(err, html) { - if (err) { - winston.warn('[trudesk:events:sendSubscriberEmail] - Error: ' + err.message); - return c(err); - } else { - var mailOptions = { - to: emails.join(), - subject: 'Updated: Ticket #' + ticket.uid + '-' + ticket.subject, - html: html, - generateTextFromHTML: true - }; - - mailer.sendMail(mailOptions, function(err, info) { - if (err) { - return c(err, null); - } - - return c(null, info); - }); - } + ticket.populate('comments.owner', function(err, ticket) { + if (err) return true; + + var locals = { + ticket: ticket, + comment: comment + }; + + template('ticket-comment-added', locals, function(err, html) { + if (err) { + winston.warn('[trudesk:events:sendSubscriberEmail] - Error: ' + err.message); + return c(err); + } else { + var mailOptions = { + to: emails.join(), + subject: 'Updated: Ticket #' + ticket.uid + '-' + ticket.subject, + html: html, + generateTextFromHTML: true + }; + + mailer.sendMail(mailOptions, function(err, info) { + if (err) { + winston.warn('[trudesk:events:sendSubscriberEmail] - Error: ' + err.message); + return c(); + } + + winston.debug('Sent Subscriber Mail.'); + return c(null, info); + }); + } + }); }); } }); }); } ], function(err, result) { - + //Blank }); }); })(); diff --git a/src/helpers/hbs/helpers.js b/src/helpers/hbs/helpers.js index de9d30e3c..00f7b1ef5 100644 --- a/src/helpers/hbs/helpers.js +++ b/src/helpers/hbs/helpers.js @@ -489,6 +489,8 @@ var helpers = { checkPerm: function(user, perm, options) { var P = require('../../permissions'); + if (_.isUndefined(user)) return options.inverse(this); + if (P.canThis(user.role, perm)) { return options.fn(this); } else { @@ -528,6 +530,15 @@ var helpers = { } else { return options.inverse(this); } + }, + + isSubscribed: function(arr, value) { + var result = _.some(arr, function(i) { + if (_.isUndefined(i) || _.isUndefined(value)) return false; + return i._id.toString() == value.toString(); + }); + + return !!result; } }; diff --git a/src/helpers/utils/index.js b/src/helpers/utils/index.js index 4aa772583..4843077a3 100644 --- a/src/helpers/utils/index.js +++ b/src/helpers/utils/index.js @@ -20,6 +20,14 @@ module.exports.sendToSelf = function (socket, method, data) { socket.emit(method, data); }; +module.exports._sendToSelf = function(io, socketId, method, data) { + __.each(io.sockets.sockets, function(socket) { + if (socket.id == socketId) { + socket.emit(method, data); + } + }); +}; + module.exports.sendToAllConnectedClients = function (io, method, data) { io.sockets.emit(method, data); }; diff --git a/src/mailer/index.js b/src/mailer/index.js index ed38bac3b..38b5bcf77 100644 --- a/src/mailer/index.js +++ b/src/mailer/index.js @@ -39,6 +39,7 @@ var transporter = nodeMailer.createTransport({ pass: nconf.get('mailer:password') ? nconf.get('mailer:password') : '' }, tls: { + rejectUnauthorized: false, ciphers: 'SSLv3' } }); diff --git a/src/mailer/templates/ticket-comment-added/html.hbs b/src/mailer/templates/ticket-comment-added/html.hbs new file mode 100644 index 000000000..ab2b4fb05 --- /dev/null +++ b/src/mailer/templates/ticket-comment-added/html.hbs @@ -0,0 +1,49 @@ + + + + + Updated: Ticket #{{ticket.uid}} + + + +
+

Updated: {{{ticket.subject}}}

+
Ticket Group: {{ticket.group.name}}
+
Ticket Submitted by: {{ticket.owner.fullname}}
+
Submitted Date: {{ticket.date}}
+
Ticket Type: {{ticket.type.name}}
+
Ticket Priority: {{ticket.priority}}
+
Tags: {{ticket.tags}}
+ +

+

Ticket Issue

+
+

{{{ticket.issue}}}

+ +

+

Comments

+
+ {{#each ticket.comments}} +
{{owner.fullname}}
+
{{date}}
+
+

{{{comment}}}

+
+
+ {{/each}} +
+ + \ No newline at end of file diff --git a/src/mailer/templates/ticket-updated/html.hbs b/src/mailer/templates/ticket-updated/html.hbs new file mode 100644 index 000000000..45844d78d --- /dev/null +++ b/src/mailer/templates/ticket-updated/html.hbs @@ -0,0 +1,37 @@ + + + + + Ticket #{{ticket.uid}} + + + +
+

{{{ticket.subject}}}

+
Ticket Group: {{ticket.group.name}}
+
Ticket Submitted by: {{ticket.owner.fullname}}
+
Submitted Date: {{ticket.date}}
+
Ticket Type: {{ticket.type.name}}
+
Ticket Priority: {{ticket.priority}}
+
Tags: {{ticket.tags}}
+ +

+

Ticket Issue

+
+

{{{ticket.issue}}}

+
+ + \ No newline at end of file diff --git a/src/models/ticket.js b/src/models/ticket.js index 3df196691..3b007ac51 100644 --- a/src/models/ticket.js +++ b/src/models/ticket.js @@ -78,7 +78,7 @@ var ticketSchema = mongoose.Schema({ notes: [commentSchema], attachments:[attachmentSchema], history: [historySchema], - subscribers:{ type: [mongoose.Schema.Types.ObjectId], ref: 'accounts' } + subscribers:[{ type: mongoose.Schema.Types.ObjectId, ref: 'accounts' }] }); ticketSchema.plugin(deepPopulate); @@ -390,6 +390,31 @@ ticketSchema.methods.removeAttachment = function(ownerId, attachmentId, callback callback(null, self); }; +ticketSchema.methods.addSubscriber = function(userId, callback) { + var self = this; + + var hasSub = _.some(self.subscribers, function(i) { + return i._id.toString() == userId.toString(); + }); + + if (!hasSub) + self.subscribers.push(userId); + + callback(null, self); +}; + +ticketSchema.methods.removeSubscriber = function(userId, callback) { + var self = this; + + var user = _.find(self.subscribers, function(i) { return i._id.toString() == userId.toString(); }); + + if (_.isUndefined(user) || _.isEmpty(user) || _.isNull(user)) return callback(null, self); + + self.subscribers = _.reject(self.subscribers, function(i) { return i._id.toString() == userId.toString(); }); + + callback(null, self); +}; + /** * Gets all tickets that are not marked as deleted

* @@ -413,7 +438,7 @@ ticketSchema.statics.getAll = function(callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']) + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']) .sort({'status': 1}); return q.exec(callback); @@ -443,7 +468,7 @@ ticketSchema.statics.getTickets = function(grpId, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']) + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']) .sort({'status': 1}); return q.exec(callback); @@ -497,7 +522,7 @@ ticketSchema.statics.getTicketsWithObject = function(grpId, object, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']) + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']) .sort('-uid') //.sort({'status': 1}) .skip(page*limit) @@ -557,7 +582,6 @@ ticketSchema.statics.getCountWithObject = function(grpId, object, callback) { } if (!_.isUndefined(object.filter) && !_.isUndefined(object.filter.assignee)) { - console.log(object.filter.assignee); q.where({assignee: {$in: object.filter.assignee}}); } @@ -596,7 +620,7 @@ ticketSchema.statics.getTicketsWithLimit = function(grpId, limit, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']) + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']) .sort({'uid': -1}) .sort({'status': 1}) .limit(limit); @@ -630,7 +654,7 @@ ticketSchema.statics.getTicketsByStatus = function(grpId, status, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']) + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']) .sort({'uid': -1}); return q.exec(callback); @@ -654,7 +678,7 @@ ticketSchema.statics.getTicketByUid = function(uid, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'comments', 'comments.owner', 'history.owner']); + .deepPopulate(['group', 'comments', 'comments.owner', 'history.owner', 'subscribers']); return q.exec(callback); }; @@ -677,7 +701,7 @@ ticketSchema.statics.getTicketById = function(id, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']); + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']); return q.exec(callback); }; @@ -691,7 +715,7 @@ ticketSchema.statics.getAssigned = function(user_id, callback) { .populate('owner') .populate('assignee') .populate('type') - .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner']); + .deepPopulate(['group', 'group.members', 'group.sendMailTo', 'comments', 'comments.owner', 'history.owner', 'subscribers']); return q.exec(callback); }; diff --git a/src/public/js/angularjs/controllers/singleTicket.js b/src/public/js/angularjs/controllers/singleTicket.js index edd436dee..5b6138874 100644 --- a/src/public/js/angularjs/controllers/singleTicket.js +++ b/src/public/js/angularjs/controllers/singleTicket.js @@ -147,6 +147,22 @@ define(['angular', 'underscore', 'jquery', 'modules/socket', 'modules/navigation $(inputField).trigger('click'); } }; + + $scope.SubscriberChange = function() { + var id = $('#__ticketId').html(); + $http.put( + '/api/v1/tickets/' + id + '/subscribe', + { + "user" : $scope.user, + "subscribe": $scope.subscribed + } + ).success(function() { + + }).error(function(e) { + console.log('[trudesk:singleTicket:SubscriberChange] - ' + e); + helpers.showFlash('Error: ' + e.message, true); + }); + }; }) .directive('closeMouseUp', ['$document', function($document) { return { diff --git a/src/public/js/modules/socket.io/ticketsUI.js b/src/public/js/modules/socket.io/ticketsUI.js index 52683a77f..67d501aad 100644 --- a/src/public/js/modules/socket.io/ticketsUI.js +++ b/src/public/js/modules/socket.io/ticketsUI.js @@ -23,31 +23,16 @@ define('modules/socket.io/ticketsUI', [ ], function($, _, moment, helpers, nav) { var ticketsUI = {}; - ticketsUI.setShowNotice = function(socket, notice) { - socket.emit('setShowNotice', notice); - }; - - ticketsUI.updateShowNotice = function(socket) { - socket.removeAllListeners('updateShowNotice'); - socket.on('updateShowNotice', function(notice) { - var $noticeDiv = $('div#notice-banner'); - var $dateFormated = moment(notice.activeDate).format('MM/DD/YYYY HH:mm'); - var $message = ' - Important: ' + notice.message; - var $bgColor = notice.color; - $noticeDiv.css('background', $bgColor); - $noticeDiv.html($dateFormated + $message); - $noticeDiv.removeClass('hide'); - }); - }; - - ticketsUI.setClearNotice = function(socket) { - socket.emit('setClearNotice'); - }; - - ticketsUI.updateClearNotice = function(socket) { - socket.removeAllListeners('updateClearNotice'); - socket.on('updateClearNotice', function() { - $('div#notice-banner').addClass('hide'); + ticketsUI.updateSubscribe = function(socket) { + socket.removeAllListeners('ticket:subscriber:update'); + socket.on('ticket:subscriber:update', function(data) { + var $subscribeSwitch = $('input#subscribeSwitch[data-subscribe-userId="' + data.user + '"]'); + if ($subscribeSwitch.length > 0) { + if (data.subscribe) + $subscribeSwitch.prop('checked', true); + else + $subscribeSwitch.prop('checked', false); + } }); }; diff --git a/src/public/js/modules/ui.js b/src/public/js/modules/ui.js index 49876d118..898cab401 100644 --- a/src/public/js/modules/ui.js +++ b/src/public/js/modules/ui.js @@ -19,10 +19,11 @@ define('modules/ui', [ 'modules/navigation', 'modules/socket.io/messagesUI', 'modules/socket.io/noticeUI', + 'modules/socket.io/ticketsUI', 'nicescroll', 'history' -], function($, _, helpers, nav, msgUI, noticeUI) { +], function($, _, helpers, nav, msgUI, noticeUI, ticketsUI) { var socketUi = {}, socket = io.connect(); @@ -53,6 +54,7 @@ define('modules/ui', [ this.updateSingleMessageItem(socket); this.updateShowNotice(socket); this.updateClearNotice(socket); + this.updateSubscribe(socket); }; socketUi.setMessageRead = function(messageId) { @@ -85,6 +87,8 @@ define('modules/ui', [ socketUi.updateShowNotice = noticeUI.updateShowNotice; socketUi.updateClearNotice = noticeUI.updateClearNotice; + socketUi.updateSubscribe = ticketsUI.updateSubscribe; + socketUi.onReconnect = function() { socket.removeAllListeners('reconnect'); socket.on('reconnect', function() { diff --git a/src/routes/index.js b/src/routes/index.js index 19afa62fe..7df58bd5c 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -105,6 +105,7 @@ function mainRoutes(router, middleware, controllers) { router.get('/api/v1/tickets/:uid', middleware.api, controllers.api.tickets.single); router.put('/api/v1/tickets/:id', middleware.api, controllers.api.tickets.update); router.delete('/api/v1/tickets/:id', middleware.api, controllers.api.tickets.delete); + router.put('/api/v1/tickets/:id/subscribe', middleware.api, controllers.api.tickets.subscribe); router.post('/api/v1/tickets/addcomment', middleware.api, controllers.api.tickets.postComment); router.delete('/api/v1/tickets/:tid/attachments/remove/:aid', middleware.api, controllers.api.tickets.removeAttachment); router.get('/api/v1/groups', middleware.api, middleware.cache(5*60), controllers.api.groups.get); @@ -127,6 +128,7 @@ function mainRoutes(router, middleware, controllers) { router.put('/api/v1/notices/:id', middleware.api, controllers.api.notices.updateNotice); router.delete('/api/v1/notices/:id', middleware.api, controllers.api.notices.deleteNotice); + //router.get('/debug/sendmail', controllers.debug.sendmail); //router.get('/api/v1/import', middleware.api, controllers.api.import); } diff --git a/src/socketserver.js b/src/socketserver.js index 6a8685457..f9f22b187 100644 --- a/src/socketserver.js +++ b/src/socketserver.js @@ -239,24 +239,35 @@ module.exports = function(ws) { var ticketId = data.ticketId; var ticketSchema = require('./models/ticket'); ticketSchema.getTicketById(ticketId, function(err, ticket) { - if (err) return true + if (err) return true; - ticket.setAssignee(ownerId, userId, function(err, t) { - if (err) { - winston.warn(err); - return true; + async.parallel({ + setAssignee: function(callback) { + ticket.setAssignee(ownerId, userId, function(err, ticket) { + callback(err, ticket); + }); + }, + subscriber: function(callback) { + ticket.addSubscriber(userId, function(err, ticket) { + callback(err, ticket); + }); } + }, function(err, results) { + if (err) return true; - t.save(function(err, tt) { + ticket = results.subscriber; + ticket.save(function(err, ticket) { if (err) return true; - ticketSchema.populate(tt, 'assignee', function(err){ + ticketSchema.populate(ticket, 'assignee', function(err) { if (err) return true; + emitter.emit('ticket:subscriber:update', {user: userId, subscribe: true}); emitter.emit('ticket:updated', ticketId); - utils.sendToAllConnectedClients(io, 'updateAssignee', tt); + utils.sendToAllConnectedClients(io, 'updateAssignee', ticket); }); }); - }) + + }); }); }); @@ -389,8 +400,7 @@ module.exports = function(ws) { if (_.isUndefined(ticketId) || _.isUndefined(commentId) || _.isUndefined(comment)) return true; comment = comment.replace(/(\r\n|\n\r|\r|\n)/g, "
"); var markedComment = marked(comment); - console.log(comment); - console.log(markedComment); + ticketSchema.getTicketById(ticketId, function(err, ticket) { if (err) return winston.error(err); diff --git a/src/views/subviews/profile.hbs b/src/views/subviews/profile.hbs index f370f7cab..4cda9ff67 100644 --- a/src/views/subviews/profile.hbs +++ b/src/views/subviews/profile.hbs @@ -57,6 +57,18 @@ + + + + + + + + + + + + diff --git a/src/views/subviews/singleticket.hbs b/src/views/subviews/singleticket.hbs index 8927b92fe..b4ca4a122 100644 --- a/src/views/subviews/singleticket.hbs +++ b/src/views/subviews/singleticket.hbs @@ -1,4 +1,10 @@ -
+
+
@@ -174,10 +180,22 @@ {{data.ticket.commentCount}} Comment{{#unless_eq data.ticket.commentCount compare=1}}s{{/unless_eq}}
-
- +
+ + +
+