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 = '';
58 function parseJwt(token) {
59 var base64Url = token.split('.')[1];
60 var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
61 var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
62 return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
65 return JSON.parse(jsonPayload);
69 function closeInteraction() {
73 id: $scope.interactionId,
75 closeReason: 'contact',
76 closedAt: new Date() // moment().format('YYYY-MM-DD HH:mm:ss'),
79 $http.put($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId + "/custom_update", msg, {
81 'Authorization': 'Bearer ' + $scope.token
85 function ret(response) {}
89 $scope.close = function() {
93 $scope.keyPress = function(keyEvent) {
94 if (keyEvent.which === 13)
95 if ($scope.text.content) {
97 msg.body = $scope.text.content;
102 this.$onInit = function() {
103 var urlParams = new URLSearchParams(window.location.search);
104 var params = urlParams.get("params");
105 var arr = params.split("|");
107 $scope.messageId = arr[0];
108 $scope.motionUrl = arr[1];
109 $scope.chatWebsiteId = arr[2];
110 $scope.interactionId = arr[3];
114 $scope.token = $cookies.get('motion.token');
115 if (_.isNil($scope.token))
116 $scope.error_message = "XCally motion token not valid, please connect to XCally Motion, then retry";
119 window.addEventListener("message", function(event) {
121 let message = event.data;
122 if (message == null || message.namespace == null || message.namespace != 'webclient.teleniasoftware.com') {
123 console.info("Received Unknown message", message);
127 if (message.event == 'callEvent') {
128 tvoxCallId = message.data.callId;
129 if (message.data.state == "IDLE") {
133 if (!_primaryCallInfo) {
134 _primaryCallInfo = message.data;
135 alert(_primaryCallInfo)
136 if (_callInfoCallback !== null)
137 _callInfoCallback(_primaryCallInfo);
141 tvoxSendReadyEvent();
142 var js = parseJwt($scope.token);
143 $scope.userId = js.id;
144 $rootScope.userId = js.id;
145 $http.get($scope.motionUrl + "/api/users/" + $scope.userId, {
147 'Authorization': 'Bearer ' + $scope.token
150 then(function(response) {
151 $scope.userData = response.data;
153 $http.get($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId, {
155 'Authorization': 'Bearer ' + $scope.token
158 then(function(response) {
159 $scope.interactionData = response.data;
165 socket.on('chatMessage:save', onMessageSave);
166 socket.on('chatInteraction:save', onInteractionSave);
167 socket.on('chatInteraction:update', onInteractionSave);
170 $http.get($scope.motionUrl + "/api/chat/websites/" + $scope.chatWebsiteId, {
172 'Authorization': 'Bearer ' + $scope.token
176 function successCallback(response) {
177 $scope.dispo.mandatoryDisposition = response.mandatoryDisposition;
179 //if ($scope.mandatoryDisposition) {
180 //$scope.mandatoryDispositionPause = response.mandatoryDispositionPause.name;
183 $scope.logo = $scope.motionUrl + "/api/chat/websites/" + $scope.chatWebsiteId + "/logo?token=" + response.token;
185 url: $scope.motionUrl + "/api/chat/messages/" + $scope.messageId + "/accept",
188 'Authorization': 'Bearer ' + $scope.token
191 id: $scope.messageId,
192 UserId: $scope.userId,
196 .then(function(message) {
197 $scope.userId = message.data.interaction.UserId;
198 $scope.contactId = message.data.interaction.ContactId;
199 $http.get($scope.motionUrl + "/api/chat/interactions/" + message.data.interaction.id + "/messages", {
201 'Authorization': 'Bearer ' + $scope.token
205 function ret(response) {
206 $scope.messages.rows = response.data.rows;
207 $http.get($scope.motionUrl + "/api/cm/contacts/" + $scope.contactId, {
209 'Authorization': 'Bearer ' + $scope.token
213 function ret(contact) {
216 $scope.contactData = contact.data;
217 if (contact.data.firstName !== null)
218 fn = contact.data.firstName;
219 if (contact.data.lastName !== null)
220 ln = contact.data.lastName;
221 $scope.contactName = fn + " " + ln;
222 createReportSession();
230 $http.get($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId + "/messages", {
232 'Authorization': 'Bearer ' + $scope.token
236 function ret(response) {
237 $scope.messages.rows = response.data.rows;
238 $http.get($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId, {
240 'Authorization': 'Bearer ' + $scope.token
244 function ret(response) {
245 $scope.userId = response.data.UserId;
246 $scope.contactId = response.data.ContactId;
247 $http.get($scope.motionUrl + "/api/cm/contacts/" + $scope.contactId, {
249 'Authorization': 'Bearer ' + $scope.token
253 function ret(contact) {
254 $scope.contactData = contact.data;
257 if (contact.data.firstName !== null)
258 fn = contact.data.firstName;
259 if (contact.data.lastName !== null)
260 ln = contact.data.lastName;
261 $scope.contactName = fn + " " + ln;
262 createReportSession();
273 function errorCallback(response) {
274 console.log("Unable to perform get request", response);
281 function createReportSession() {
282 if ($scope.reportMemberId > 0) {
283 closeReportSession(true);
289 function openReportSession() {
292 membername: $scope.userData.name,
293 interface: $scope.userData.interface,
294 type: "TVOX_SESSION",
296 role: $scope.userData.role,
297 internal: $scope.userData.internal,
298 uniqueid: $scope.interactionId
300 $http.post($scope.motionUrl + "/api/members/reports", obj, {
302 'Authorization': 'Bearer ' + $scope.token
306 function ret(response) {
307 $scope.reportMemberId = response.data.id;
312 function loadDispositions() {
313 var dispositions = [];
314 var filters = "ChatWebsiteId=null&FaxAccountId=null&ListId=null&MailAccountId=null&OpenchannelAccountId=null&SmsAccountId=null&WhatsappAccountId=null&nolimit=true";
315 $http.get($scope.motionUrl + "/api/dispositions?" + filters, {
317 'Authorization': 'Bearer ' + $scope.token
322 if (res.data.rows.length) {
323 $scope.dispositions = _.concat($scope.dispositions, res.data.rows);
325 filters = "ChatWebsiteId=" + $scope.chatWebsiteId + "&nolimit=true";
326 $http.get($scope.motionUrl + "/api/dispositions?" + filters, {
328 'Authorization': 'Bearer ' + $scope.token
333 if (res.data.rows.length) {
334 $scope.dispositions = _.concat(dispositions, res.data.rows);
344 $scope.onDispositionChange = function(level) {
345 if (level === 'first') {
346 $scope.dispo.anySecondLevelDisposition = $scope.dispo.firstLevelDisposition ?
347 _.some($scope.dispositions, ['ParentId', $scope.dispo.firstLevelDisposition.id]) : false;
349 if (!$scope.dispo.firstLevelDisposition) $scope.dispo.secondLevelDisposition = undefined;
350 } else if (level === 'second') {
351 $scope.dispo.anyThirdLevelDisposition = _.some($scope.dispositions, ['ParentId', $scope.dispo.secondLevelDisposition.id]);
355 $scope.clearDispositionSelection = function(level) {
356 if (level === 'second') {
357 $scope.dispo.secondLevelDisposition = undefined;
358 $scope.dispo.thirdLevelDisposition = undefined;
359 } else if (level === 'third') {
360 $scope.dispo.thirdLevelDisposition = undefined;
365 $scope.upload = function() {
367 $scope.ngFlow.flow.opts.headers = {
368 'X-Requested-With': 'XMLHttpRequest',
369 Authorization: 'Bearer ' + $scope.token
372 $scope.ngFlow.flow.upload();
378 $scope.send = function() {
379 if ($scope.text.content) {
381 msg.body = $scope.text.content;
387 function sendMessage(msg) {
389 msg.ChatInteractionId = $scope.interactionId;
390 msg.ChatWebsiteId = $scope.chatWebsiteId;
391 msg.ContactId = $scope.contactId;
392 msg.UserId = $scope.userId;
393 msg.direction = "out";
396 $http.post($scope.motionUrl + "/api/chat/messages", msg, {
398 'Authorization': 'Bearer ' + $scope.token
402 function ret(response) {
403 $scope.text.content = "";
409 function onInteractionSave(interaction) {
410 // NOTE: return when is not a right interaction
411 if (interaction && interaction.id != $scope.interactionId) {
415 if (interaction.closed) {
416 $scope.interactionClosed = true;
417 closeReportSession(false);
422 $scope.fileAdded = function(file) {
423 if (file.size > 10240000) {
424 alert("File too big");
427 title: 'File too big',
428 msg: 'The max allowed size is ' + maxFileSizeMb + 'MB'
439 * Automatically triggers when files added to the uploader
441 $scope.fileSuccess = function(file, message) {
442 var attachment = JSON.parse(message);
443 var body = attachment.name;
448 ($location.protocol() + '://' + $location.host()) +
449 '/api/chat/interactions/' +
450 $scope.interactionId +
451 '/attachment_download?attachId=' +
455 '" target="_self">' +
461 AttachmentId: attachment.id
465 $scope.saveDisposition = function() {
469 closeReason: 'agent',
470 disposition: $scope.dispo.firstLevelDisposition ? $scope.dispo.firstLevelDisposition.name : null,
471 secondDisposition: $scope.dispo.secondLevelDisposition ? $scope.dispo.secondLevelDisposition.name : undefined,
472 thirdDisposition: $scope.dispo.thirdLevelDisposition ? $scope.dispo.thirdLevelDisposition.name : undefined,
473 mote: $scope.dispo.note
476 $http.put($scope.motionUrl + "/api/chat/interactions/" + $scope.interactionId, obj, {
478 'Authorization': 'Bearer ' + $scope.token
482 function ret(response) {
483 if ($scope.reportMemberId > 0)
484 closeReportSession(false);
485 tvoxCloseInteraction(tvoxCallId);
493 function scrollToBottom() {
494 $timeout(function() {
495 var interactionContent = angular.element($document.find("md-content"));
496 if (interactionContent && interactionContent[0]) {
497 interactionContent[0].scrollTop = interactionContent[0].scrollHeight;
503 function onMessageSave(msg) {
506 if (msg.ChatWebsiteId == $scope.chatWebsiteId && msg.ChatInteractionId == $scope.interactionId) {
507 if ($scope.messages) {
508 found = _.find($scope.messages.rows, {
521 $scope.messages.rows.push(msg);
522 if (msg.direction == "in") {
523 $http.put($scope.motionUrl + "/api/chat/messages/" + msg.id + "/accept", {
525 UserId: $scope.userId
528 'Authorization': 'Bearer ' + $scope.token
532 function ret(response) {}
541 $scope.accept = function(event) {}
543 $window.onfocus = function() {
544 createReportSession();
546 $window.onblur = function() {
547 if ($scope.reportMemberId > 0) {
548 closeReportSession(false);
552 function closeReportSession(openNewSession) {
556 $http.put($scope.motionUrl + "/api/members/reports/" + $scope.reportMemberId, obj, {
558 'Authorization': 'Bearer ' + $scope.token
562 function ret(response) {
563 $scope.reportMemberId = 0;
564 if (openNewSession) {