@tiledesk/tiledesk-server 2.2.38 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +14 -657
  3. package/README.md +36 -21
  4. package/app.js +29 -5
  5. package/channels/chat21/chat21WebHook.js +12 -1
  6. package/config/labels/widget.json +320 -0
  7. package/event/botEvent.js +1 -1
  8. package/event/subscriptionEvent.js +11 -0
  9. package/fonts/Roboto-Italic.ttf +0 -0
  10. package/fonts/Roboto-Medium.ttf +0 -0
  11. package/fonts/Roboto-MediumItalic.ttf +0 -0
  12. package/fonts/Roboto-Regular.ttf +0 -0
  13. package/middleware/passport.js +4 -1
  14. package/models/lead.js +2 -0
  15. package/models/request.js +38 -11
  16. package/models/subscriptionLog.js +34 -0
  17. package/models/tagLibrary.js +42 -0
  18. package/package.json +4 -10
  19. package/pubmodules/activities/activityArchiver.js +295 -0
  20. package/pubmodules/activities/index.js +3 -0
  21. package/pubmodules/activities/models/activity.js +88 -0
  22. package/pubmodules/activities/routes/activity.js +710 -0
  23. package/pubmodules/activities/test/activityRoute.js +85 -0
  24. package/pubmodules/analytics/analytics.js +1719 -0
  25. package/pubmodules/analytics/index.js +3 -0
  26. package/pubmodules/canned/cannedResponse.js +51 -0
  27. package/pubmodules/canned/cannedResponseRoute.js +157 -0
  28. package/pubmodules/canned/index.js +3 -0
  29. package/pubmodules/messageActions/messageActionsInterceptor.js +4 -2
  30. package/pubmodules/pubModulesManager.js +115 -7
  31. package/pubmodules/rasa/index.js +8 -1
  32. package/pubmodules/rasa/listener.js +28 -7
  33. package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +3 -1
  34. package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +5 -3
  35. package/pubmodules/trigger/default.js +271 -0
  36. package/pubmodules/trigger/event/actionEventEmitter.js +10 -0
  37. package/pubmodules/trigger/event/flowEventEmitter.js +10 -0
  38. package/pubmodules/trigger/event/triggerEventEmitter.js +10 -0
  39. package/pubmodules/trigger/index.js +3 -0
  40. package/pubmodules/trigger/models/trigger.js +149 -0
  41. package/pubmodules/trigger/rulesTrigger.js +1181 -0
  42. package/pubmodules/trigger/start.js +114 -0
  43. package/pubmodules/trigger/triggerRoute.js +150 -0
  44. package/routes/department.js +51 -0
  45. package/routes/group.js +140 -0
  46. package/routes/lead.js +24 -1
  47. package/routes/message.js +6 -3
  48. package/routes/project.js +52 -0
  49. package/routes/public-request.js +265 -2
  50. package/routes/request.js +86 -13
  51. package/routes/subscription.js +140 -0
  52. package/routes/tag.js +138 -0
  53. package/routes/user-request.js +3 -2
  54. package/routes/widget.js +16 -1
  55. package/routes/widgetLoader.js +31 -0
  56. package/services/faqBotHandler.js +2 -2
  57. package/services/faqBotSupport.js +0 -1
  58. package/services/faqService.js +1 -1
  59. package/services/modulesManager.js +16 -182
  60. package/services/requestService.js +364 -6
  61. package/services/subscriptionNotifier.js +485 -0
  62. package/template/email/assignedEmailMessage.html +1 -1
  63. package/template/email/assignedRequest.html +1 -1
  64. package/template/email/newMessage.html +1 -1
  65. package/template/email/passwordChanged.html +1 -1
  66. package/template/email/pooledEmailMessage.html +1 -1
  67. package/template/email/pooledRequest.html +1 -1
  68. package/template/email/resetPassword.html +2 -2
  69. package/template/email/ticket.html +1 -1
  70. package/test/messageRoute.js +69 -0
  71. package/test/requestService.js +3 -1
  72. package/views/messages.jade +1 -1
@@ -0,0 +1,485 @@
1
+ var Subscription = require('../models/subscription');
2
+ var SubscriptionLog = require('../models/subscriptionLog');
3
+ const requestEvent = require('../event/requestEvent');
4
+ const messageEvent = require('../event/messageEvent');
5
+ const message2Event = require('../event/message2Event');
6
+ const leadEvent = require('../event/leadEvent');
7
+ const botEvent = require('../event/botEvent');
8
+ const authEvent = require('../event/authEvent');
9
+ const departmentEvent = require('../event/departmentEvent');
10
+ const groupEvent = require('../event/groupEvent');
11
+ const faqBotEvent = require('../event/faqBotEvent');
12
+ const eventEvent = require('../pubmodules/events/eventEvent');
13
+ const event2Event = require('../pubmodules/events/event2Event');
14
+ const projectEvent = require('../event/projectEvent');
15
+
16
+ // var Request = require("../models/request");
17
+ var Message = require("../models/message");
18
+ // var Faq_kb = require("../models/faq_kb");
19
+ var winston = require('../config/winston');
20
+ var jwt = require('jsonwebtoken');
21
+ var config = require('../config/database'); // get db config file
22
+ var cacheUtil = require("../utils/cacheUtil");
23
+
24
+
25
+ var webhook_origin = process.env.WEBHOOK_ORIGIN || "http://localhost:3000";
26
+ winston.debug("webhook_origin: "+webhook_origin);
27
+
28
+
29
+ var request = require('retry-request', {
30
+ request: require('request')
31
+ });
32
+
33
+ class SubscriptionNotifier {
34
+ // var SubscriptionNotifier = {
35
+
36
+
37
+ findSubscriber(event, id_project) {
38
+ return new Promise(function (resolve, reject) {
39
+ Subscription.find({event:event, $or:[{id_project: id_project}, {global: true}]})
40
+ .cache(cacheUtil.longTTL, id_project+":subscriptions:event:"+event)
41
+ .select("+secret +global")
42
+ .exec(function (err, subscriptions) {
43
+ // if (subscriptions && subscriptions.length>0) {
44
+ // winston.debug("Subscription.notify", event, item , "length", subscriptions.length);
45
+ // }
46
+ resolve(subscriptions);
47
+ });
48
+ });
49
+ }
50
+
51
+ notify(subscriptions, payload, callback) {
52
+ // winston.debug("Subscription.notify", event, item);
53
+
54
+ // Subscription.find({event:event, id_project: item.id_project}).exec(function (err, subscriptions) {
55
+ // if (subscriptions && subscriptions.length>0) {
56
+ // winston.debug("Subscription.notify", event, item , "length", subscriptions.length);
57
+ // }
58
+
59
+
60
+ //var json = {event: event, timestamp: Date.now(), payload: item};
61
+ winston.debug("subscriptions",subscriptions);
62
+ var json = {timestamp: Date.now(), payload: payload};
63
+ subscriptions.forEach(function(s) {
64
+
65
+ // winston.debug("s",s);
66
+ var secret = s.secret;
67
+
68
+ let sJson = s.toObject();
69
+ delete sJson.secret;
70
+ delete sJson.global;
71
+
72
+ json["hook"] = sJson;
73
+
74
+
75
+
76
+ var signOptions = {
77
+ issuer: 'https://tiledesk.com',
78
+ subject: 'subscription',
79
+ audience: 'https://tiledesk.com/subscriptions/'+s._id,
80
+ };
81
+
82
+ if (s.global==true){
83
+ signOptions.audience = 'https://tiledesk.com';
84
+ secret = config.secret;
85
+ }
86
+
87
+ var token = jwt.sign(sJson, secret, signOptions);
88
+ json["token"] = token;
89
+
90
+
91
+ // for sync use no retry
92
+
93
+ request({
94
+ url: s.target,
95
+ headers: {
96
+ 'Content-Type' : 'application/json',
97
+ 'x-hook-secret': secret,
98
+ 'User-Agent': 'tiledesk-webhooks',
99
+ 'Origin': webhook_origin
100
+ },
101
+ json: json,
102
+ method: 'POST'
103
+
104
+ }, function(err, response, json){
105
+ winston.debug("SENT " + s.event + " TO " + s.target, "with error " , err);
106
+ winston.debug("SubscriptionLog response", response);
107
+ winston.debug("SubscriptionLog json", json);
108
+
109
+ var subscriptionLog = new SubscriptionLog({event: s.event, target: s.target,
110
+ response: JSON.stringify(response),
111
+ body: JSON.stringify(json),
112
+ err: err, id_project:s.id_project});
113
+
114
+ subscriptionLog.save(function (errSL, sl) {
115
+ if (errSL) {
116
+ winston.error("Error saving subscriptionLog", errSL);
117
+ return 0;
118
+ }
119
+ winston.debug("SubscriptionLog saved", sl);
120
+ });
121
+
122
+ if (err) {
123
+ winston.error("Error sending webhook for event " + s.event + " TO " + s.target, "with error " , err);
124
+ if (callback) {
125
+ callback(err, json);
126
+ }
127
+
128
+ }
129
+ //return
130
+ // console.log("callback qui1", callback);
131
+ if (callback) {
132
+ // console.log("callback qui", json);
133
+ callback(null, json);
134
+ }
135
+
136
+ });
137
+ });
138
+ // });
139
+ }
140
+ // https://mongoosejs.com/docs/middleware.html#post-async
141
+ decorate(model, modelName) {
142
+ var isNew = false;
143
+
144
+ model.pre('save', function(next) {
145
+ isNew = this.isNew;
146
+ winston.debug("Subscription.notify.pre (isNew)", isNew);
147
+
148
+ return next();
149
+ });
150
+
151
+ //winston.debug("decorate");
152
+ // .afterCreate = function(item, next) {
153
+ model.post('save', function(doc, next) {
154
+
155
+ // If we have isNew flag then it's an update
156
+ var event = (isNew) ? 'create' : 'update';
157
+ winston.debug("Subscription.notify."+event);
158
+ next(null, doc);
159
+ SubscriptionNotifier.notify(modelName+'.'+event, doc);
160
+ });
161
+
162
+ // model.afterUpdate = function(item, next) {
163
+ // next(null, item);
164
+ // SubscriptionNotifier.notify(modelName+'.update', item);
165
+ // }
166
+
167
+ // model.afterDestroy = function(next) {
168
+ // next();
169
+ // SubscriptionNotifier.notify(modelName+'.delete', {});
170
+ // }
171
+ }
172
+
173
+ start() {
174
+ winston.debug('SubscriptionNotifier start');
175
+
176
+ var enabled = process.env.RESTHOOK_ENABLED || "false";
177
+ winston.debug('SubscriptionNotifier enabled:'+enabled);
178
+
179
+ if (enabled==="true") {
180
+ winston.debug('SubscriptionNotifier enabled');
181
+ }else {
182
+ winston.info('Resthook disabled');
183
+ return 0;
184
+ }
185
+
186
+
187
+ messageEvent.on('message.create', function(message) {
188
+ setImmediate(() => {
189
+ subscriptionNotifier.subscribe('message.create', message);
190
+ });
191
+ });
192
+
193
+ message2Event.on('message.create.**.channel.*', function(message) {
194
+ // message2Event.on('message.create.request.channel.*', function(message) {
195
+ winston.debug("message2Event: "+this.event, message);
196
+ subscriptionNotifier.subscribe(this.event, message);
197
+ }, {async: true});
198
+
199
+
200
+
201
+ // messageEvent.on('message.received.for.bot', function(message) {
202
+ // setImmediate(() => {
203
+ // subscriptionNotifier.subscribe('message.received.for.bot', message);
204
+ // });
205
+ // });
206
+
207
+ // messageEvent.on('message.received', function(message) {
208
+ // setImmediate(() => {
209
+ // subscriptionNotifier.subscribe('message.received', message);
210
+ // });
211
+ // });
212
+ // messageEvent.on('message.sending', function(message) {
213
+ // setImmediate(() => {
214
+ // subscriptionNotifier.subscribe('message.sending', message);
215
+ // });
216
+ // });
217
+
218
+
219
+ requestEvent.on('request.create', function(request) {
220
+ setImmediate(() => {
221
+ subscriptionNotifier.subscribe('request.create', request);
222
+ });
223
+ });
224
+
225
+ requestEvent.on('request.update', function(request) {
226
+ setImmediate(() => {
227
+ subscriptionNotifier.subscribe('request.update', request);
228
+ });
229
+ });
230
+
231
+ requestEvent.on('request.close', function(request) {
232
+ setImmediate(() => {
233
+ Message.find({recipient: request.request_id, id_project: request.id_project}).sort({updatedAt: 'asc'}).exec(function(err, messages) {
234
+ var requestJson = request.toJSON();
235
+ requestJson.messages = messages;
236
+ subscriptionNotifier.subscribe('request.close', requestJson);
237
+ });
238
+ });
239
+ });
240
+
241
+
242
+ leadEvent.on('lead.create', function(lead) {
243
+ setImmediate(() => {
244
+ subscriptionNotifier.subscribe('lead.create', lead);
245
+ });
246
+ });
247
+
248
+
249
+ botEvent.on('faqbot.create', function(faqBot) {
250
+ setImmediate(() => {
251
+ subscriptionNotifier.subscribe('faqbot.create', faqBot);
252
+ });
253
+ });
254
+
255
+ botEvent.on('faqbot.update', function(faqBot) {
256
+ setImmediate(() => {
257
+ subscriptionNotifier.subscribe('faqbot.update', faqBot);
258
+ });
259
+ });
260
+
261
+ botEvent.on('faqbot.delete', function(faqBot) {
262
+ setImmediate(() => {
263
+ subscriptionNotifier.subscribe('faqbot.delete', faqBot);
264
+ });
265
+ });
266
+
267
+ faqBotEvent.on('faq.create', function(faq) {
268
+ setImmediate(() => {
269
+ subscriptionNotifier.subscribe('faq.create', faq);
270
+ });
271
+ });
272
+
273
+ faqBotEvent.on('faq.update', function(faq) {
274
+ setImmediate(() => {
275
+ subscriptionNotifier.subscribe('faq.update', faq);
276
+ });
277
+ });
278
+ faqBotEvent.on('faq.delete', function(faq) {
279
+ setImmediate(() => {
280
+ subscriptionNotifier.subscribe('faq.delete', faq);
281
+ });
282
+ });
283
+
284
+ authEvent.on('user.signup', function(event) {
285
+ setImmediate(() => {
286
+ var user = event.savedUser;
287
+ delete user.password;
288
+
289
+ subscriptionNotifier.subscribe('user.signup', user);
290
+ });
291
+ });
292
+
293
+
294
+ // authEvent.emit('project_user.invite', {req:req, savedProject_userPopulated: savedProject_userPopulated});
295
+
296
+ authEvent.on('project_user.invite', function(event) {
297
+ setImmediate(() => {
298
+ subscriptionNotifier.subscribe('project_user.invite', event.savedProject_userPopulated);
299
+ });
300
+ });
301
+
302
+ // authEvent.emit('project_user.update', {updatedProject_userPopulated:updatedProject_userPopulated, req: req});
303
+
304
+ authEvent.on('project_user.update', function(event) {
305
+ setImmediate(() => {
306
+ subscriptionNotifier.subscribe('project_user.update', event.updatedProject_userPopulated);
307
+ });
308
+ });
309
+
310
+ // authEvent.emit('project_user.delete', {req: req, project_userPopulated: project_userPopulated});
311
+
312
+ authEvent.on('project_user.delete', function(event) {
313
+ setImmediate(() => {
314
+ subscriptionNotifier.subscribe('project_user.delete', event.project_userPopulated);
315
+ });
316
+ });
317
+
318
+
319
+ //TODO lanciare user.signin in questo modo uno esternamente con webhook può creare proactive greetings
320
+
321
+ departmentEvent.on('operator.select', function(result) {
322
+ winston.debug("departmentEvent.on(operator.select");
323
+
324
+ var operatorSelectedEvent = result.result;
325
+ var resolve = result.resolve;
326
+ var reject = result.reject;
327
+
328
+ // aggiungere context. lascio lo passso già a result.result
329
+ // operatorSelectedEvent["context"] = result.context;
330
+
331
+ var disableWebHookCall = result.disableWebHookCall;
332
+ winston.debug("subscriptionNotifier disableWebHookCall: "+ disableWebHookCall);
333
+
334
+ if (disableWebHookCall === true) {
335
+ winston.debug("subscriptionNotifier disableWebHookCall enabled: "+ disableWebHookCall);
336
+ return resolve(operatorSelectedEvent);
337
+ }
338
+ subscriptionNotifier.subscribe('operator.select', operatorSelectedEvent, function(err, json) {
339
+ winston.debug("qui callback",json, err);
340
+ if (err) {
341
+ if (err.code == 404) {
342
+ winston.debug("call resolve default resolve because not found", err);
343
+ }else {
344
+ winston.warn("call resolve default resolve because err", err);
345
+ }
346
+ return resolve(operatorSelectedEvent);
347
+ }
348
+ if (json && json.operators) {
349
+ winston.verbose("call resolve valid json", json);
350
+ return resolve(json);
351
+ }else {
352
+ winston.verbose("call resolve default resolve");
353
+ return resolve(operatorSelectedEvent);
354
+ }
355
+
356
+ });
357
+ });
358
+
359
+
360
+ departmentEvent.on('department.create', function(department) {
361
+ setImmediate(() => {
362
+ subscriptionNotifier.subscribe('department.create', department);
363
+ });
364
+ });
365
+
366
+
367
+ departmentEvent.on('department.update', function(department) {
368
+ setImmediate(() => {
369
+ subscriptionNotifier.subscribe('department.update', department);
370
+ });
371
+ });
372
+
373
+ departmentEvent.on('department.delete', function(department) {
374
+ setImmediate(() => {
375
+ subscriptionNotifier.subscribe('department.delete', department);
376
+ });
377
+ });
378
+
379
+
380
+ groupEvent.on('group.create', function(group) {
381
+ setImmediate(() => {
382
+ subscriptionNotifier.subscribe('group.create', group);
383
+ });
384
+ });
385
+
386
+
387
+ groupEvent.on('group.update', function(group) {
388
+ setImmediate(() => {
389
+ subscriptionNotifier.subscribe('group.update', group);
390
+ });
391
+ });
392
+
393
+ groupEvent.on('group.delete', function(group) {
394
+ setImmediate(() => {
395
+ subscriptionNotifier.subscribe('group.delete', group);
396
+ });
397
+ });
398
+
399
+ eventEvent.on('event.emit', function(event) {
400
+ setImmediate(() => {
401
+ subscriptionNotifier.subscribe('event.emit', event);
402
+ });
403
+ });
404
+
405
+ // event2Event.on(name, savedEventPopulated);
406
+ event2Event.on('**', function(savedEventPopulated) {
407
+ setImmediate(() => {
408
+ winston.debug("eventname",this.event);
409
+ subscriptionNotifier.subscribe('event.emit.'+this.event, savedEventPopulated);
410
+ });
411
+ });
412
+
413
+
414
+ projectEvent.on('project.create', function(project) {
415
+ setImmediate(() => {
416
+ var projectJson = project.toJSON();
417
+ projectJson.id_project = projectJson._id;
418
+ subscriptionNotifier.subscribe('project.create', projectJson);
419
+ });
420
+ });
421
+
422
+ projectEvent.on('project.update', function(project) {
423
+ setImmediate(() => {
424
+ var projectJson = project.toJSON();
425
+ projectJson.id_project = projectJson._id;
426
+ subscriptionNotifier.subscribe('project.update', projectJson);
427
+ });
428
+ });
429
+
430
+ projectEvent.on('project.downgrade', function(project) {
431
+ setImmediate(() => {
432
+ var projectJson = project.toJSON();
433
+ projectJson.id_project = projectJson._id;
434
+ subscriptionNotifier.subscribe('project.downgrade', projectJson);
435
+ });
436
+ });
437
+
438
+ projectEvent.on('project.delete', function(project) {
439
+ setImmediate(() => {
440
+ var projectJson = project.toJSON();
441
+ projectJson.id_project = projectJson._id;
442
+ subscriptionNotifier.subscribe('project.delete', projectJson);
443
+ });
444
+ });
445
+
446
+
447
+
448
+
449
+ // tagEvent.webhook for pypestream
450
+
451
+
452
+ // TODO add user events
453
+
454
+ winston.info('SubscriptionNotifier started');
455
+ }
456
+
457
+
458
+ subscribe(eventName, payload, callback ) {
459
+ winston.debug("Subscription.notify");
460
+ // findSubscriber(event, id_project)
461
+ subscriptionNotifier.findSubscriber(eventName, payload.id_project).then(function(subscriptions) {
462
+ //winston.debug("Subscription.notify subscriptionNotifier", subscriptions.length);
463
+ if (subscriptions && subscriptions.length>0) {
464
+ winston.debug("Subscription.notify", eventName, payload , "length", subscriptions.length);
465
+ subscriptionNotifier.notify(subscriptions, payload, callback);
466
+ } else {
467
+ if (callback) {
468
+ var err = {msg:"No subscriptions found", code:404};
469
+ callback(err, undefined);
470
+ }
471
+ }
472
+ });
473
+
474
+ }
475
+
476
+
477
+
478
+ };
479
+
480
+ var subscriptionNotifier = new SubscriptionNotifier();
481
+
482
+ // winston.debug('messageEvent', messageEvent);
483
+
484
+
485
+ module.exports = subscriptionNotifier;
@@ -82,7 +82,7 @@
82
82
 
83
83
  <div style="text-align:center">
84
84
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
85
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
85
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
86
86
  </a>
87
87
  </div>
88
88
  </tr>
@@ -82,7 +82,7 @@
82
82
 
83
83
  <div style="text-align:center">
84
84
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
85
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
85
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
86
86
  </a>
87
87
  </div>
88
88
  </tr>
@@ -80,7 +80,7 @@
80
80
 
81
81
  <div style="text-align:center">
82
82
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
83
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
83
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
84
84
  </a>
85
85
  </div>
86
86
  </tr>
@@ -72,7 +72,7 @@
72
72
 
73
73
  <div style="text-align:center">
74
74
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
75
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:50%;outline:none;text-decoration:none;border:none;" class="CToWUd">
75
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:50%;outline:none;text-decoration:none;border:none;" class="CToWUd">
76
76
  </a>
77
77
  </div>
78
78
  <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; border: 1px solid #e9e9e9;" bgcolor="#fff">
@@ -82,7 +82,7 @@
82
82
 
83
83
  <div style="text-align:center">
84
84
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
85
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
85
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
86
86
  </a>
87
87
  </div>
88
88
  </tr>
@@ -82,7 +82,7 @@
82
82
 
83
83
  <div style="text-align:center">
84
84
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
85
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
85
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
86
86
  </a>
87
87
  </div>
88
88
  </tr>
@@ -71,7 +71,7 @@
71
71
 
72
72
  <div style="text-align:center">
73
73
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
74
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:50%;outline:none;text-decoration:none;border:none;" class="CToWUd">
74
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:50%;outline:none;text-decoration:none;border:none;" class="CToWUd">
75
75
  </a>
76
76
  </div>
77
77
 
@@ -99,7 +99,7 @@
99
99
  Reset My Password
100
100
  </a>
101
101
  </div>
102
- <br><br>If you did not forgot your password you can safely ignore this email.
102
+ <br><br>If you didn't forget your password you can safely ignore this email.
103
103
  <br><br><span style="font-size:12px; ">If you're having trouble clicking the "Reset My Password" button, copy and paste the URL below into your web browser: </span>
104
104
  <br>
105
105
  <span style="color:#03a5e8; font-size:12px; ">{{baseScope.baseUrl}}/#/resetpassword/{{resetPswRequestId}}</span>
@@ -75,7 +75,7 @@
75
75
 
76
76
  <div style="text-align:center">
77
77
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
78
- <img src="https://tiledesk.com/tiledesk-logo-x1.png" style="width:20%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
78
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:20%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
79
79
  </a>
80
80
  </div>
81
81
  </td>
@@ -720,6 +720,75 @@ it('createWithPriority', function (done) {
720
720
 
721
721
 
722
722
 
723
+
724
+ // mocha test/messageRoute.js --grep 'createSimpleWithFollowers'
725
+
726
+ it('createSimpleWithFollowers', function (done) {
727
+ // this.timeout(10000);
728
+
729
+ var email = "test-message-create-" + Date.now() + "@email.com";
730
+ var pwd = "pwd";
731
+
732
+ userService.signup( email ,pwd, "Test Firstname", "Test lastname").then(function(savedUser) {
733
+ projectService.createAndReturnProjectAndProjectUser("message-create", savedUser._id).then(function(savedProjectAndPU) {
734
+
735
+ var savedProject = savedProjectAndPU.project;
736
+
737
+ chai.request(server)
738
+ .post('/'+ savedProject._id + '/requests/req123-createSimpleWithFollowers/messages')
739
+ .auth(email, pwd)
740
+ .set('content-type', 'application/json')
741
+ .send({"text":"text", "followers": [savedProjectAndPU.project_user._id.toString()]})
742
+ .end(function(err, res) {
743
+ //console.log("res", res);
744
+ console.log("res.body", JSON.stringify(res.body));
745
+ res.should.have.status(200);
746
+ res.body.should.be.a('object');
747
+
748
+ expect(res.body.sender).to.equal(savedUser._id.toString());
749
+ // expect(res.body.sender).to.equal(savedProjectAndPU.project_user._id.toString());
750
+ // expect(res.body.senderFullname).to.equal("senderFullname");
751
+ expect(res.body.recipient).to.equal("req123-createSimpleWithFollowers");
752
+ expect(res.body.text).to.equal("text");
753
+ expect(res.body.id_project).to.equal(savedProject._id.toString());
754
+ expect(res.body.createdBy).to.equal(savedUser._id.toString());
755
+ expect(res.body.status).to.equal(0);
756
+
757
+ expect(res.body.request.request_id).to.equal("req123-createSimpleWithFollowers");
758
+ expect(res.body.request.requester._id).to.equal(savedProjectAndPU.project_user._id.toString());
759
+ // expect(res.body.request.requester_id).to.equal("sender");
760
+ expect(res.body.request.first_text).to.equal("text");
761
+ expect(res.body.request.id_project).to.equal(savedProject._id.toString());
762
+ expect(res.body.request.createdBy).to.equal(savedUser._id.toString());
763
+
764
+ // expect(res.body.request.messages_count).to.equal(1);
765
+
766
+ expect(res.body.request.status).to.equal(200);
767
+ expect(res.body.request.snapshot.agents.length).to.equal(1);
768
+ expect(res.body.request.participants.length).to.equal(1);
769
+ expect(res.body.request.department).to.not.equal(null);
770
+ expect(res.body.request.lead).to.not.equal(null);
771
+
772
+ expect(res.body.channel_type).to.equal("group");
773
+ expect(res.body.channel.name).to.equal("chat21");
774
+ expect(res.body.request.channel.name).to.equal("chat21");
775
+
776
+
777
+ expect(res.body.request.location).to.equal(undefined);
778
+
779
+ expect(res.body.request.followers[0]).to.equal(savedProjectAndPU.project_user._id.toString());
780
+
781
+
782
+ done();
783
+ });
784
+ });
785
+ });
786
+ });
787
+
788
+
789
+
790
+
791
+
723
792
  it('getall', function (done) {
724
793
  // this.timeout(10000);
725
794
 
@@ -686,13 +686,15 @@ describe('RequestService', function () {
686
686
  savedProject._id, "5badfe5d553d1844ad654072"),
687
687
  messageService.create("5badfe5d553d1844ad654072", "test sender", savedRequest.request_id, "hello2",
688
688
  savedProject._id, "5badfe5d553d1844ad654072")]).then(function(all) {
689
- requestService.closeRequestByRequestId(savedRequest.request_id, savedProject._id).then(function(closedRequest) {
689
+ // closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by)
690
+ requestService.closeRequestByRequestId(savedRequest.request_id, savedProject._id, false, true, "user1").then(function(closedRequest) {
690
691
  winston.debug("resolve closedRequest", closedRequest.toObject());
691
692
  expect(closedRequest.status).to.equal(1000);
692
693
  expect(closedRequest.closed_at).to.not.equal(null);
693
694
  expect(closedRequest.transcript).to.contains("hello1");
694
695
  expect(closedRequest.transcript).to.contains("hello2");
695
696
  expect(closedRequest.snapshot.agents).to.equal(undefined);
697
+ expect(closedRequest.closed_by).to.equal("user1");
696
698
 
697
699
  done();
698
700
  }).catch(function(err){