1 // Include app dependency on ngMaterial
2 angular.module('AnswerApp', ['ngMaterial', 'ngCookies', 'motion', 'ngResource', 'flow', 'ngSanitize'])
3 .controller("AnswerController", function($rootScope, $scope, $http, $cookies, socket, $location, $timeout, $document, $window) {
7 $scope.textMessage = "";
10 $scope.interactionId = 0;
11 $scope.interactionClosed = false;
13 $scope.motionUrl = "";
14 $scope.chatWebsiteId = "";
18 $scope.interactionData = {};
19 $scope.error_message = "";
24 $scope.reportMemberId = 0;
25 $scope.contactName = "";
26 $scope.ngFlowOptions = {
27 target: '/api/attachments',
31 simultaneousUploads: 1,
33 progressCallbacksInterval: 1000,
34 allowDuplicateUploads: true
37 // ng-flow will be injected into here through its directive
42 $scope.dispositions = [];
45 $scope.dispo.firstLevelDisposition = null;
46 $scope.dispo.secondLevelDisposition = null;
47 $scope.dispo.thirdLevelDisposition = null;
48 $scope.dispo.anySecondLevelDisposition = null;
49 $scope.dispo.anyThirdLevelDisposition = null;
50 $scope.dispo.mandatoryDisposition = false;
51 $scope.dispo.mandatoryDispositionPause = '';
52 $scope.dispo.note = '';
59 function parseJwt(token) {
60 var base64Url = token.split('.')[1];
61 var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
62 var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
63 return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
66 return JSON.parse(jsonPayload);
70 function closeInteraction() {
74 id: $scope.interactionId,
76 closeReason: 'contact',
77 closedAt: new Date() // moment().format('YYYY-MM-DD HH:mm:ss'),
80 $http.put($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId + "/custom_update", msg, {
82 'Authorization': 'Bearer ' + $scope.token
86 function ret(response) {}
90 $scope.close = function() {
94 $scope.keyPress = function(keyEvent) {
95 if (keyEvent.which === 13)
96 if ($scope.text.content) {
98 msg.body = $scope.text.content;
104 this.$onInit = function() {
105 var urlParams = new URLSearchParams(window.location.search);
106 var params = urlParams.get("params");
107 var arr = params.split("|");
109 $scope.messageId = arr[0];
110 $scope.motionUrl = arr[1];
111 $scope.chatWebsiteId = arr[2];
112 $scope.interactionId = arr[3];
116 $scope.token = $cookies.get('motion.token');
117 if (_.isNil($scope.token))
118 $scope.error_message = "XCally motion token not valid, please connect to XCally Motion, then retry";
121 window.addEventListener("message", function(event) {
123 let message = event.data;
124 if (message == null || message.namespace == null || message.namespace != 'webclient.teleniasoftware.com') {
125 console.info("Received Unknown message", message);
129 if (message.event == 'callEvent') {
130 tvoxCallId = message.data.callId;
131 if (message.data.state == "IDLE") {
135 if (!_primaryCallInfo) {
136 _primaryCallInfo = message.data;
137 alert(_primaryCallInfo)
138 if (_callInfoCallback !== null)
139 _callInfoCallback(_primaryCallInfo);
143 tvoxSendReadyEvent();
144 var js = parseJwt($scope.token);
145 $scope.userId = js.id;
146 $rootScope.userId = js.id;
147 $http.get($scope.motionUrl + "/api/users/" + $scope.userId, {
149 'Authorization': 'Bearer ' + $scope.token
152 then(function(response) {
153 $scope.userData = response.data;
155 $http.get($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId, {
157 'Authorization': 'Bearer ' + $scope.token
160 then(function(response) {
161 $scope.interactionData = response.data;
167 socket.on('chatMessage:save', onMessageSave);
168 socket.on('chatInteraction:save', onInteractionSave);
169 socket.on('chatInteraction:update', onInteractionSave);
172 $http.get($scope.motionUrl + "/api/chat/websites/" + $scope.chatWebsiteId, {
174 'Authorization': 'Bearer ' + $scope.token
178 function successCallback(response) {
179 $scope.dispo.mandatoryDisposition = response.mandatoryDisposition;
181 //if ($scope.mandatoryDisposition) {
182 //$scope.mandatoryDispositionPause = response.mandatoryDispositionPause.name;
185 $scope.logo = $scope.motionUrl + "/api/chat/websites/" + $scope.chatWebsiteId + "/logo?token=" + response.token;
187 url: $scope.motionUrl + "/api/chat/messages/" + $scope.messageId + "/accept",
190 'Authorization': 'Bearer ' + $scope.token
193 id: $scope.messageId,
194 UserId: $scope.userId,
198 .then(function(message) {
199 $scope.userId = message.data.interaction.UserId;
200 $scope.contactId = message.data.interaction.ContactId;
201 $http.get($scope.motionUrl + "/api/chat/interactions/" + message.data.interaction.id + "/messages", {
203 'Authorization': 'Bearer ' + $scope.token
207 function ret(response) {
208 $scope.messages.rows = response.data.rows;
209 $http.get($scope.motionUrl + "/api/cm/contacts/" + $scope.contactId, {
211 'Authorization': 'Bearer ' + $scope.token
215 function ret(contact) {
218 $scope.contactData = contact.data;
219 if (contact.data.firstName !== null)
220 fn = contact.data.firstName;
221 if (contact.data.lastName !== null)
222 ln = contact.data.lastName;
223 $scope.contactName = fn + " " + ln;
224 createReportSession();
232 $http.get($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId + "/messages", {
234 'Authorization': 'Bearer ' + $scope.token
238 function ret(response) {
239 $scope.messages.rows = response.data.rows;
240 $http.get($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId, {
242 'Authorization': 'Bearer ' + $scope.token
246 function ret(response) {
247 $scope.userId = response.data.UserId;
248 $scope.contactId = response.data.ContactId;
249 $http.get($scope.motionUrl + "/api/cm/contacts/" + $scope.contactId, {
251 'Authorization': 'Bearer ' + $scope.token
255 function ret(contact) {
256 $scope.contactData = contact.data;
259 if (contact.data.firstName !== null)
260 fn = contact.data.firstName;
261 if (contact.data.lastName !== null)
262 ln = contact.data.lastName;
263 $scope.contactName = fn + " " + ln;
264 createReportSession();
275 function errorCallback(response) {
276 console.log("Unable to perform get request", response);
283 function createReportSession() {
284 if ($scope.reportMemberId > 0) {
285 closeReportSession(true);
291 function openReportSession() {
294 membername: $scope.userData.name,
295 interface: $scope.userData.interface,
296 type: "TVOX_SESSION",
298 role: $scope.userData.role,
299 internal: $scope.userData.internal,
300 uniqueid: $scope.interactionId
302 $http.post($scope.motionUrl + "/api/members/reports", obj, {
304 'Authorization': 'Bearer ' + $scope.token
308 function ret(response) {
309 console.log("RMID", response.data.id);
310 $scope.reportMemberId = response.data.id;
315 function loadDispositions() {
316 var dispositions = [];
317 var filters = "ChatWebsiteId=null&FaxAccountId=null&ListId=null&MailAccountId=null&OpenchannelAccountId=null&SmsAccountId=null&WhatsappAccountId=null&nolimit=true";
318 $http.get($scope.motionUrl + "/api/dispositions?" + filters, {
320 'Authorization': 'Bearer ' + $scope.token
325 if (res.data.rows.length) {
326 $scope.dispositions = _.concat($scope.dispositions, res.data.rows);
328 filters = "ChatWebsiteId=" + $scope.chatWebsiteId + "&nolimit=true";
329 $http.get($scope.motionUrl + "/api/dispositions?" + filters, {
331 'Authorization': 'Bearer ' + $scope.token
336 if (res.data.rows.length) {
337 $scope.dispositions = _.concat(dispositions, res.data.rows);
347 $scope.onDispositionChange = function(level) {
348 if (level === 'first') {
349 $scope.dispo.anySecondLevelDisposition = $scope.dispo.firstLevelDisposition ?
350 _.some($scope.dispositions, ['ParentId', $scope.dispo.firstLevelDisposition.id]) : false;
352 if (!$scope.dispo.firstLevelDisposition) $scope.dispo.secondLevelDisposition = undefined;
353 } else if (level === 'second') {
354 $scope.dispo.anyThirdLevelDisposition = _.some($scope.dispositions, ['ParentId', $scope.dispo.secondLevelDisposition.id]);
358 $scope.clearDispositionSelection = function(level) {
359 if (level === 'second') {
360 $scope.dispo.secondLevelDisposition = undefined;
361 $scope.dispo.thirdLevelDisposition = undefined;
362 } else if (level === 'third') {
363 $scope.dispo.thirdLevelDisposition = undefined;
368 $scope.upload = function() {
370 $scope.ngFlow.flow.opts.headers = {
371 'X-Requested-With': 'XMLHttpRequest',
372 Authorization: 'Bearer ' + $scope.token
375 $scope.ngFlow.flow.upload();
381 $scope.send = function() {
382 if ($scope.text.content) {
384 msg.body = $scope.text.content;
390 function sendMessage(msg) {
392 msg.ChatInteractionId = $scope.interactionId;
393 msg.ChatWebsiteId = $scope.chatWebsiteId;
394 msg.ContactId = $scope.contactId;
395 msg.UserId = $scope.userId;
396 msg.direction = "out";
399 $http.post($scope.motionUrl + "/api/chat/messages", msg, {
401 'Authorization': 'Bearer ' + $scope.token
405 function ret(response) {
406 $scope.text.content = "";
412 function onInteractionSave(interaction) {
413 // NOTE: return when is not a right interaction
414 if (interaction && interaction.id != $scope.interactionId) {
418 if (interaction.closed) {
419 $scope.interactionClosed = true;
420 closeReportSession(false);
425 $scope.fileAdded = function(file) {
426 if (file.size > 10240000) {
427 alert("File too big");
430 title: 'File too big',
431 msg: 'The max allowed size is ' + maxFileSizeMb + 'MB'
442 * Automatically triggers when files added to the uploader
444 $scope.fileSuccess = function(file, message) {
445 var attachment = JSON.parse(message);
446 var body = attachment.name;
451 ($location.protocol() + '://' + $location.host()) +
452 '/api/chat/interactions/' +
453 $scope.interactionId +
454 '/attachment_download?attachId=' +
458 '" target="_self">' +
464 AttachmentId: attachment.id
468 $scope.saveDisposition = function() {
472 closeReason: 'agent',
473 disposition: $scope.dispo.firstLevelDisposition ? $scope.dispo.firstLevelDisposition.name : null,
474 secondDisposition: $scope.dispo.secondLevelDisposition ? $scope.dispo.secondLevelDisposition.name : undefined,
475 thirdDisposition: $scope.dispo.thirdLevelDisposition ? $scope.dispo.thirdLevelDisposition.name : undefined,
476 mote: $scope.dispo.note
479 $http.put($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId, obj, {
481 'Authorization': 'Bearer ' + $scope.token
485 function ret(response) {
486 if ($scope.reportMemberId > 0)
487 closeReportSession(false);
488 tvoxCloseInteraction(tvoxCallId);
496 function scrollToBottom() {
497 $timeout(function() {
498 var interactionContent = angular.element($document.find("md-content"));
499 if (interactionContent && interactionContent[0]) {
500 interactionContent[0].scrollTop = interactionContent[0].scrollHeight;
506 function onMessageSave(msg) {
509 if (msg.ChatWebsiteId == $scope.chatWebsiteId && msg.ChatInteractionId == $scope.interactionId) {
510 if ($scope.messages) {
511 found = _.find($scope.messages.rows, {
524 $scope.messages.rows.push(msg);
525 if (msg.direction == "in") {
526 $http.put($scope.motionUrl + "/api/chat/messages/" + msg.id + "/accept", {
528 UserId: $scope.userId
531 'Authorization': 'Bearer ' + $scope.token
535 function ret(response) {}
544 $scope.accept = function(event) {}
546 $window.onfocus = function() {
547 createReportSession();
549 $window.onblur = function() {
550 if ($scope.reportMemberId > 0) {
551 closeReportSession(false);
555 function closeReportSession(openNewSession) {
559 $http.put($scope.motionUrl + "/api/members/reports/" + $scope.reportMemberId, obj, {
561 'Authorization': 'Bearer ' + $scope.token
565 function ret(response) {
566 $scope.reportMemberId = 0;
567 if (openNewSession) {