"use strict"; (function () { 'use strict'; angular.module('liveChatModule') .controller('LiveChatController', ['$scope', '$rootScope', '$sce', 'i18nService', 'localStorageService', 'systemAlertService', '$window', 'configurationModel', 'authService', 'roles', 'userModel', 'events', 'metadataModel', 'ticketModel', 'relationModel', '$q', '$filter', '$state', 'utilityFunctions', 'smartRecorderModel', 'searchService', 'feedModel', 'attachmentService', 'personModel', '$timeout', 'authModel', 'liveChatService', 'LIVE_CHAT_EVENTS', 'LIVE_CHAT_APP_EVENTS', 'permissionModel', 'knowledgeArticleModel', function ($scope, $rootScope, $sce, i18nService, localStorageService, systemAlertService, $window, configurationModel, authService, roles, userModel, events, metadataModel, ticketModel, relationModel, $q, $filter, $state, utilityFunctions, smartRecorderModel, searchService, feedModel, attachmentService, personModel, $timeout, authModel, liveChatService, LIVE_CHAT_EVENTS, LIVE_CHAT_APP_EVENTS, permissionModel, knowledgeArticleModel) { $scope.state = { loadingLiveChat: true, creatingTicket: false, appModalEventConfirmWaiting: false }; $scope.isDirtyFlag = true; // this is used to show the dirty message on state change var lcDashboardTabId = 'liveChatDashboard'; var lcAgentConsoleTabId = 'liveChatAgentConsole'; var lcConsolePendingMsgKey = 'lcConsolePendingMsg'; // used to store the last pending message that Smart IT needs to send to LC, useful when a new tab is launched or on refresh var CREATE_TICKET_TIMEOUT = 30000; var summaryCharLimit = 100; $scope.agentChats = []; $scope.chatTicketDataForCreateMap = new Map(); $scope.createTicketInProgressForChatSessionSet = new Set(); $scope.hideForDashboard = false; $scope.noOfDraftScreensOpen = 0; $scope.userid = localStorageService.get('user.userId'); userModel.getFullCurrentUserData().then(function () { $scope.user = userModel.userFullData; $scope.context = { company: $scope.user && $scope.user.company && $scope.user.company.name, customerId: $scope.user.id, id: EntityVO.TYPE_LIVE_CHAT, type: EntityVO.TYPE_LIVE_CHAT, summary: '', status: '', accessMappings: { relationsEditAllowed: false, duplicateActionAllowed: true } }; }); $scope.isWOInstalled = configurationModel.isServerApplicationEnabled(EntityVO.TYPE_WORKORDER) && authService.isAuthorized(roles.ITSM_AGENT_ROLE); $scope.isIncidentCreateAllowed = true; $scope.isWOCreateAllowed = true; $scope.filterConfig = configurationModel.get('resource.filter'); $scope.filterConfigMap = _.keyBy($scope.filterConfig, 'name'); $scope.$on(events.PERSON_DATA_LOADED, chatCustomerDataLoaded); $scope.$on(events.SELECT_TEMPLATE_FROM_RS, saveTemplate); $scope.$on(events.UNSELECT_TEMPLATE_FROM_RS, unrelateTemplate); $scope.$on(events.SHARE_KNOWLEDGE_TO_LIVE_CHAT, sendMessageToChat); $scope.$on(events.SAVE_TO_TICKET_FROM_RS, saveToTicketFromRs); $scope.$on(events.REMOVE_FROM_TICKET_FROM_RS, removeFromTicketFromRs); $scope.$on(events.SEARCH_TEXT_CHANGED, saveSearchTextToselectedChatContext); $scope.$on(events.RELATE_TICKET_TO_CHAT, saveTicketToChat); $scope.$on(events.UNRELATE_TICKET_TO_CHAT, removeTicketFromChat); $scope.$on(events.TICKET_ASSIGNEES_UPDATED_FROM_BLADE, handleAssignmentComplete); function setTab() { var customerTabElem = angular.element('#live__agent-customer-tab'); customerTabElem.find('a').click(); } function sendChildMessage(message) { var targetFrame = window.frames.liveChatFrame; if (targetFrame !== undefined && targetFrame !== null) { targetFrame.postMessage(message, $scope.eschatServerUrl); console.log("Message Sent To Frame:" + JSON.stringify(message)); } } function uploadAttachmentsToWorkLog(attachments, chatSession) { if (chatSession.sessionid === $scope.selectedChat.sessionid) { if ($scope.selectedChat.ticket && $scope.selectedChat.ticket.ticketId) { processWorkNote($scope.selectedChat.ticket.ticketId, $scope.selectedChat.ticket.ticketType, { text: i18nService.getLocalizedString('live.chat.attachment.worknote'), attachments: attachments }); } } else { var agentChat = _.findIndex($scope.agentChats, { sid: chatSession.sessionid }); if ($scope.agentChats[agentChat] && $scope.agentChats[agentChat].selectedChatContext && $scope.agentChats[agentChat].selectedChatContext.ticket) { processWorkNote($scope.agentChats[agentChat].selectedChatContext.ticket.ticketId, $scope.agentChats[agentChat].selectedChatContext.ticket.ticketType, { text: i18nService.getLocalizedString('live.chat.attachment.worknote'), attachments: attachments }); } else if (chatSession && chatSession.metadata && chatSession.metadata.ticketid) { var ticketInfo_1, params = { search_text: chatSession.metadata.ticketid }, jsonParams = { types: ['tickets'] }; searchService.getGlobalSearchResults(params, jsonParams).then(function (response) { if (!_.isEmpty(response.items) && response.items[0] && response.items[0].results && response.items[0].results.length) { ticketInfo_1 = _.find(response.items[0].results, { displayId: chatSession.metadata.ticketid }); if (ticketInfo_1) { processWorkNote(ticketInfo_1.ticketId, ticketInfo_1.ticketType, { text: i18nService.getLocalizedString('live.chat.attachment.worknote'), attachments: attachments }); } } }); } } } function handleDraftCreateComplete(ticketData, chatSessionforCreate, relatedTicket) { showQuickTicketCreateSuccess(ticketData.type, ticketData, chatSessionforCreate, 'createTicket', relatedTicket); if (relatedTicket) { //create duplicate relationship between tickets var relatedTicketInfo = {}; relatedTicketInfo.desc = ticketData.summary; relatedTicketInfo.displayId = ticketData.displayId; relatedTicketInfo.id = relatedTicket.id; relatedTicketInfo.parentDisplayId = relatedTicket.displayId; relatedTicketInfo.tag = ticketData.type === EntityVO.TYPE_INCIDENT ? EntityVO.TYPE_RESOURCE : EntityVO.TYPE_LINKEDITEM; relatedTicketInfo.relationshipType = EntityVO.TYPE_RELATEDTO; relatedTicketInfo.type = ticketData.type; addRelation(ticketData.id, ticketData.type, [relatedTicketInfo]); } } function prepareDataForTicket(ticketData) { //chat data to create a ticket var chatLog = [], chatInlineNotes; if (ticketData && ticketData.chatLog) { //format chat log data for description _.forEach(ticketData.chatLog, function (log) { var chatLogObj, logText, tempElem = document.createElement('div'); tempElem.innerHTML = log.TEXT; var decodedText = tempElem.innerText; logText = decodedText.replace(/(<([^>]+)>)/ig, ""); chatLogObj = log.NAME + " (" + $filter('date')(log.UTCEPOCHTIMESTAMP, 'short') + "): " + logText + "\n" + "\n"; chatLog.push(chatLogObj); }); chatLog = chatLog.join(' '); chatLog = i18nService.getLocalizedString('live.chat.transcript.worknote') + "\n" + "\n" + chatLog; } if (ticketData && ticketData.chatNotes) { chatInlineNotes = i18nService.getLocalizedString('live.chat.inline.notes.worknote') + "\n" + "\n" + ticketData.chatNotes; } return { chatLog: chatLog, chatInlineNotes: chatInlineNotes }; } function requestNotificationPermission() { var notificationAPISupported = true; try { if (!window.Notification) { console.info("Notification API not supported on this platform"); notificationAPISupported = false; } } catch (err) { notificationAPISupported = false; } if (notificationAPISupported && window.Notification.permission === 'denied') { console.info("Notification API permission denied."); notificationAPISupported = false; } if (notificationAPISupported && window.Notification.permission !== 'granted') { // permission is either default or not granted yet window.Notification.requestPermission().then(function (permission) { var needsPermission = true; switch (permission) { case 'granted': needsPermission = false; break; case 'denied': needsPermission = true; break; } console.info("Notification API permission status= " + window.Notification.permission + ",needsPermission= " + needsPermission); }); } return notificationAPISupported; } var onLocalStorageChange = function ($event) { if ($event && $event.key === 'ls.lcConsolePendingMsg') { var pendingMsg = localStorageService.get(lcConsolePendingMsgKey); if (pendingMsg) { localStorageService.remove(lcConsolePendingMsgKey); sendChildMessage(pendingMsg); } } }; var liveChatListener = function (event) { if (event && event.origin && !_.includes($scope.eschatServerUrl, event.origin) && !_.includes($scope.smartITURL, event.origin)) { console.warn("Url Not allowed. event.origin does not match the eschat server url.\nevent.origin= " + event.origin + ' ,eschatServerUrl = ' + $scope.eschatServerUrl); return; } if (!event || !event.data || !event.data.event || (_.includes($scope.allowedWindowEvents, event.data.event) !== true && _.includes(LIVE_CHAT_EVENTS, event.data.event) !== true)) { console.warn("Ignoring. Not a LiveChat event."); return; } if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_login_completed) { $scope.title = window.document.title; $scope.state.loadingLiveChat = false; $scope.$apply(); if ($state.current.data.path === 'console') { $window.tabId = lcAgentConsoleTabId; onLocalStorageChange({ key: 'ls.lcConsolePendingMsg' }); } else if ($state.current.data.path === 'dashboard') { $window.tabId = lcDashboardTabId; } if (localStorageService.get($window.tabId) === "true") { console.info('A Live chat tab for ' + $state.current.data.path + ' is already open. We recommend to close this tab'); } else { localStorageService.set($window.tabId, "true"); } if (event.data.chatData && event.data.chatData.status !== 'error') { requestNotificationPermission(); } if (event.data.chatData && event.data.chatData.ticketConfigSettings) { $scope.ticketCreationConfigCompanyMap = JSON.parse(event.data.chatData.ticketConfigSettings) || {}; } } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_login_expired) { $scope.selectedChat = null; $scope.agentChats = []; window.location.reload(); } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_launch_live_chat && event.data.chatData) { // if the agent console tab is not already opened, then extract the path and open it in a new tab. if (localStorageService.get(lcAgentConsoleTabId) !== "true" && event.data.chatData.toState === 'console') { var url = $state.href('liveChatAgentConsole'); $window.open(url, '_blank', 'noopener, noreferrer'); } // this message would be picked up by the agent console, and sent to LC // if a new agent console tab has been opened, then this message would be read after successful login // if the agent console tab was already open, then setting the value in localStorage would trigger a 'storage' event, // which would then be sent to LC var message = { event: LIVE_CHAT_APP_EVENTS.app_display_chat, data: { chatSessionId: event.data.chatData.sessionId } }; localStorageService.set(lcConsolePendingMsgKey, message); } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_notify_on_change) { console.log(event.data); if ($scope.title && (event.data.chatData.showNotification === false || $scope.isBrowserTabFocus === true)) { window.document.title = $scope.title; console.debug('Live Chat sac_notify_on_change event but either notifications are disabled or browser tab is in focus. Ignoring event'); return; } var notificationAPISupported = requestNotificationPermission(); var hasFocus = window.document.hasFocus(); if ($scope.isBrowserTabFocus === false || hasFocus === false || event.data.chatData.showNotification === 'always') { if (notificationAPISupported && Notification.permission === 'granted') { var notificationOptions = event.data.chatData.options; if (notificationOptions) { var notificationTitle = event.data.chatData.notificationTitle || ''; var timeout = notificationOptions.timeout || 8; var newNotification = new Notification(notificationTitle, notificationOptions); if (navigator.userAgent.toLowerCase().indexOf('firefox') < 0) { newNotification.onclick = function (event) { event.preventDefault(); window.parent.focus(); window.focus(); }; } setTimeout(function () { newNotification.close(); }, timeout * 1000); } } else { console.info('Either Notification API not supported on this platform or permission not granted yet'); } window.document.title = event.data.chatData.browserTitle + ' ' + $scope.title; } else if ($scope.title) { window.document.title = $scope.title; console.debug('Live Chat sac_notify_on_change event but Smart IT has focus. Ignoring event'); } } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_agent_chats) { // if there are no chats, then clear everything in agent chats cache and the selected chat if (!event.data || !event.data.chatData || !event.data.chatData.agentChats || !event.data.chatData.agentChats.length) { $scope.selectedChat = null; $scope.agentChats = []; clearChatContext(); return; } //on load of live chat, cache all chats if (!$scope.agentChats.length) { $scope.agentChats = event.data.chatData.agentChats; } else { //if any chat is removed from the list, remove it from the cache var newAgentChats_1 = []; _.forEach($scope.agentChats, function (chat) { var validChat = _.findIndex(event.data.chatData.agentChats, { sid: chat.sid }); if (validChat !== -1) { newAgentChats_1.push(chat); } else { if ($scope.selectedChat && $scope.selectedChat.sessionid === chat.sid) { clearChatContext(); } } }); $scope.agentChats = newAgentChats_1; //if there are new chats, add them to the cache _.forEach(event.data.chatData.agentChats, function (chat) { if (_.findIndex($scope.agentChats, { sid: chat.sid }) === -1) { $scope.agentChats.push(chat); } }); } } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_on_request_chat_ticket_data) { $scope.state.createTicketRequestPendingFromLC = false; if ($scope.relateTicketToChatInProgress) { relateChatToTicket($scope.relatedTicketData, event.data.chatData.session); } else { proceedToCreateTicket(event.data.chatData.session, $scope.relatedTicketData); } } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_notify_on_error) { if ($scope.state.creatingTicket === true) { $scope.state.creatingTicket = false; systemAlertService.error({ text: $filter('i18n')('error.unknown'), clear: false }); } var debugInfo = void 0; if (event.data.chatData && event.data.chatData.sessionId) { debugInfo = 'Live Chat error: Event - ' + event.data.event + ' Session Id - ' + event.data.chatData.sessionId; } else { debugInfo = 'Live Chat error: Event - ' + event.data.event; } console.log(debugInfo); } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_files_uploaded && event.data.chatData.attachments) { uploadAttachmentsToWorkLog(event.data.chatData.attachments, event.data.chatData); } else if (event.data && event.data.event === LIVE_CHAT_EVENTS.sac_session_context_change) { var prevChatUser = $scope.selectedChat && $scope.selectedChat.user, prevChatCustomer = $scope.selectedChat && $scope.selectedChat.customer; console.log(event.data); $scope.selectedTemplate = null; $scope.sessionID = event.data.chatData.sessionid; $scope.context.selectedChat = true; $scope.selectedChat = event.data.chatData; $scope.selectedChat.user = event.data.chatData.metadata && (event.data.chatData.metadata.user || event.data.chatData.metadata.useremail); if (event.data.chatData.metadata && event.data.chatData.metadata.appData) { $scope.selectedChat.applicationData = JSON.parse(event.data.chatData.metadata.appData); } //set ticket data from app data for both create new ticket case and association with new ticket case if ($scope.selectedChat.applicationData && $scope.selectedChat.applicationData.newTicketDetails) { $scope.selectedChat.ticket = $scope.selectedChat.applicationData.newTicketDetails; } else if ($scope.selectedChat.applicationData && $scope.selectedChat.applicationData.ticketAssociationDetails && $scope.selectedChat.applicationData.ticketAssociationDetails.id) { $scope.selectedChat.ticket = { "ticketId": $scope.selectedChat.applicationData.ticketAssociationDetails.id, "ticketDisplayId": $scope.selectedChat.applicationData.ticketAssociationDetails.displayId, "ticketType": $scope.selectedChat.applicationData.ticketAssociationDetails.type }; } //load the pinned articles(stored in app data field on MCR) in Resources tab if ($scope.selectedChat.applicationData && $scope.selectedChat.applicationData.pinnedArticles && $scope.selectedChat.applicationData.pinnedArticles.length) { var promises_1 = []; var articles_1 = []; _.forEach($scope.selectedChat.applicationData.pinnedArticles, function (article) { relationModel.cache[$scope.selectedChat.sessionid] = relationModel.cache[$scope.selectedChat.sessionid] && relationModel.cache[$scope.selectedChat.sessionid].length ? relationModel.cache[$scope.selectedChat.sessionid] : []; var relationItemIdx = _.findIndex(relationModel.cache[$scope.selectedChat.sessionid], { id: article.id }); if (relationItemIdx === -1) { var promise = void 0; if (configurationModel.comaroundEnabled) { var params = { search_text: article.title }; promise = knowledgeArticleModel.getHKMRecommendedKA({}, params).then(function (data) { if (data && data.length > 0) { _.forEach(data, function (obj) { if (obj.id === article.id) { articles_1.push(obj); } }); } }); } else { var params = { search_text: article.displayId }; var jsonParams = { types: ['knowledge'] }; promise = searchService.getGlobalSearchResults(params, jsonParams).then(function (data) { if (data.items[0] && data.items[0].results && data.items[0].results.length > 0) { articles_1.push(data.items[0].results[0]); } }); } promises_1.push(promise); } }); $q.all(promises_1).then(function () { if (articles_1.length > 0) { relationModel.cache[$scope.selectedChat.sessionid] = articles_1; } $scope.$broadcast(events.REFRESH_RECOMMENDED_KNOWLEDGE, { isFromLiveChat: true }); }, function (reason) { console.log('Search pinned articles failed: ' + reason); }); } if ($scope.selectedChat.user === prevChatUser) { $scope.$broadcast('personDataUpdated', true); $scope.selectedChat.customer = prevChatCustomer; $scope.selectedChat.customerCompany = prevChatCustomer && prevChatCustomer.company; $scope.context.chatUserCompany = prevChatCustomer && prevChatCustomer.company && prevChatCustomer.company.name; } $scope.selectedChat.status = event.data.chatData.metadata && event.data.chatData.metadata.status; $scope.selectedChat.queueType = event.data.chatData.metadata && event.data.chatData.metadata.queueType; $scope.selectedChat.autoCreateTicketType = event.data.chatData.metadata && event.data.chatData.metadata.autoCreateTicketType; $scope.selectedChat.autoCreateTemplateId = event.data.chatData.metadata && event.data.chatData.metadata.autoCreateTemplateId; var agentChat_1 = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChat_1 !== -1) { $scope.context.id = event.data.chatData.sessionid; if ($scope.agentChats[agentChat_1].selectedChatContext) { $scope.context.status = $scope.selectedChat.status; $scope.context.accessMappings.relationsEditAllowed = $scope.context.status === 'Assigned' ? true : false; $scope.context.summary = $scope.agentChats[agentChat_1].selectedChatContext.summaryText || ($scope.selectedChat.applicationData && $scope.selectedChat.applicationData.searchText) ? $scope.agentChats[agentChat_1].selectedChatContext.summaryText || $scope.selectedChat.applicationData.searchText : ''; if ($scope.agentChats[agentChat_1].selectedChatContext.selectedTemplate) { $scope.context.selectedTemplate = $scope.agentChats[agentChat_1].selectedChatContext.selectedTemplate; $scope.selectedTemplate = $scope.context.selectedTemplate; } else { $scope.context.selectedTemplate = null; $scope.selectedTemplate = null; } if ($scope.agentChats[agentChat_1].selectedChatContext.selectedKnowledge) { $scope.context.selectedKnowledge = $scope.agentChats[agentChat_1].selectedChatContext.selectedKnowledge; } if ($scope.agentChats[agentChat_1].selectedChatContext.ticket) { $scope.selectedChat.ticket = $scope.agentChats[agentChat_1].selectedChatContext.ticket; } else if ($scope.selectedChat.ticket) { $scope.agentChats[agentChat_1].selectedChatContext.ticket = $scope.selectedChat.ticket; } else if (event.data.chatData.metadata.ticketid) { var ticketInfo_2, params = { search_text: event.data.chatData.metadata.ticketid }, jsonParams = { types: ['tickets'] }; searchService.getGlobalSearchResults(params, jsonParams).then(function (response) { if (!_.isEmpty(response.items) && response.items[0] && response.items[0].results) { ticketInfo_2 = _.find(response.items[0].results, { displayId: event.data.chatData.metadata.ticketid }); $scope.selectedChat.ticket = { ticketDisplayId: event.data.chatData.metadata.ticketid, ticketType: event.data.chatData.metadata.tickettype, ticketId: ticketInfo_2 && ticketInfo_2.id }; $scope.agentChats[agentChat_1].selectedChatContext.ticket = $scope.selectedChat.ticket; } }); } } else { $scope.context.status = $scope.selectedChat.status; $scope.context.accessMappings.relationsEditAllowed = $scope.context.status === 'Assigned' ? true : false; $scope.context.summary = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.searchText ? $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.searchText : ''; if ($scope.context.selectedTemplate) { $scope.context.selectedTemplate = null; $scope.selectedTemplate = null; } if ($scope.context.selectedKnowledge) { $scope.context.selectedKnowledge = null; } $scope.agentChats[agentChat_1].selectedChatContext = _.cloneDeep($scope.context); if ($scope.selectedChat.applicationData && $scope.selectedChat.applicationData.pinnedArticles && $scope.selectedChat.applicationData.pinnedArticles.length) { $scope.agentChats[agentChat_1].selectedChatContext.selectedKnowledge = $scope.selectedChat.applicationData.pinnedArticles; } if ($scope.selectedChat.ticket) { $scope.agentChats[agentChat_1].selectedChatContext.ticket = $scope.selectedChat.ticket; } else if (event.data.chatData.metadata.ticketid) { var ticketInfo_3, params = { search_text: event.data.chatData.metadata.ticketid }, jsonParams = { types: ['tickets'] }; searchService.getGlobalSearchResults(params, jsonParams).then(function (response) { if (!_.isEmpty(response.items) && response.items[0] && response.items[0].results) { ticketInfo_3 = _.find(response.items[0].results, { displayId: event.data.chatData.metadata.ticketid }); $scope.selectedChat.ticket = { ticketDisplayId: event.data.chatData.metadata.ticketid, ticketType: event.data.chatData.metadata.tickettype, ticketId: ticketInfo_3 && ticketInfo_3.id }; $scope.agentChats[agentChat_1].selectedChatContext.ticket = $scope.selectedChat.ticket; } }); } } } else { $scope.context.summary = ''; } $scope.$broadcast(events.ON_SELECTED_LIVE_CHAT, $scope.context); $scope.$apply(); setTab(); } //display confirmation modal else if (event.data.event && event.data.event === LIVE_CHAT_EVENTS.sac_open_confirmation_modal) { showModalDialog(event.data); } //when chat is closed from SSP or when another agent transferred the chat else if (event.data.event && (event.data.event === LIVE_CHAT_EVENTS.sac_session_cancelled || event.data.event === LIVE_CHAT_EVENTS.sac_session_transferred)) { var confirmationData = { confirmationEvent: event.data.event }, ticketData = void 0; var removeChat = _.findIndex($scope.agentChats, { sid: event.data.chatData.sessionid }); if (removeChat !== -1) { ticketData = $scope.agentChats[removeChat] && $scope.agentChats[removeChat].selectedChatContext && $scope.agentChats[removeChat].selectedChatContext.ticket; $scope.agentChats.splice(removeChat, 1); } if (ticketData && event.data.event === LIVE_CHAT_EVENTS.sac_session_cancelled) { updateTicketAndRemoveChat(ticketData, confirmationData, event.data.chatData.session, true, event.data.chatData.sessionid); } else if (!ticketData && event.data.event === LIVE_CHAT_EVENTS.sac_session_cancelled) { //create call log createCallLog($scope.selectedChat, event.data.chatData.sessionid); if ($scope.selectedChat && event.data.chatData.sessionid === $scope.selectedChat.sessionid) { $scope.selectedChat = null; event.data.chatData.sessionid = null; } } else { if ($scope.selectedChat.sessionid === event.data.chatData.sessionid) { clearChatContext(); } } } //When it fails to create the ticket, we open the draft screen in a new window which throws //this event when the ticket creation is successful. This event is NOT coming from ESCHAT/Live Chat else if (event.data.event && event.data.event === events.TICKET_CREATED_FROM_DRAFT) { var chatSessionIdforCreate = event.data.eventData.livechatTicketData.chatSessionId, relatedTicket = $scope.relatedTicketData, chatSessionforCreate = void 0; $scope.noOfDraftScreensOpen = --$scope.noOfDraftScreensOpen; // in case we have attachments, then we don't want to override the chat session object if ($scope.chatTicketDataForCreateMap && $scope.chatTicketDataForCreateMap.has(chatSessionIdforCreate)) { chatSessionforCreate = $scope.chatTicketDataForCreateMap.get(chatSessionIdforCreate); } handleDraftCreateComplete(event.data.eventData.livechatTicketData, chatSessionforCreate, relatedTicket); $scope.chatTicketDataForCreateMap.delete(chatSessionIdforCreate); } else if (event.data.event && event.data.event === events.DRAFT_TICKET_CLOSED) { // event from draftTicketController and pwaTicketController on closing the draft ticket screen $scope.noOfDraftScreensOpen = --$scope.noOfDraftScreensOpen; } else if (event.data.event && (event.data.event === events.LIVECHAT_CREATEINCIDENT_SUCCESS || event.data.event === events.LIVECHAT_CREATEWORKORDER_SUCCESS)) { $scope.noOfDraftScreensOpen = --$scope.noOfDraftScreensOpen; var ticketDataArr = event.data.eventData.split(';'); var livechatTicketData_1 = {}; _.forEach(ticketDataArr, function (entry) { var val = entry.split('='); livechatTicketData_1[val[0]] = val[1]; }); var chatSessionIdforCreate = livechatTicketData_1.chatSessionId, relatedTicket = $scope.relatedTicketData, chatSessionforCreate = void 0; // in case we have attachments, then we don't want to override the chat session object if ($scope.chatTicketDataForCreateMap && $scope.chatTicketDataForCreateMap.has(chatSessionIdforCreate)) { chatSessionforCreate = $scope.chatTicketDataForCreateMap.get(chatSessionIdforCreate); } // need to do this if the complete ticket object is not returned from draft controller if (!livechatTicketData_1.summary) { var chatIndex = _.findIndex($scope.agentChats, { sid: chatSessionIdforCreate }); if (chatIndex !== -1) { livechatTicketData_1.summary = $scope.agentChats[chatIndex].cleartextquestion.substring(0, summaryCharLimit); } } handleDraftCreateComplete(livechatTicketData_1, chatSessionforCreate, relatedTicket); $scope.chatTicketDataForCreateMap.delete(chatSessionIdforCreate); } }; var handleFocusChange = function ($event) { if ($event.type === 'blur') { $scope.isBrowserTabFocus = false; } else if ($event.type === 'focus') { $scope.isBrowserTabFocus = true; if ($scope.title) { window.document.title = $scope.title; } } }; var registerLiveChatListener = function () { if ($window.addEventListener) { $window.addEventListener('message', liveChatListener, false); $window.addEventListener('focus', handleFocusChange, false); $window.addEventListener('blur', handleFocusChange, false); $window.addEventListener('storage', onLocalStorageChange, false); } }; var unregisterLiveChatListener = function () { if ($window.removeEventListener) { $window.removeEventListener('message', liveChatListener, false); $window.removeEventListener('focus', handleFocusChange, false); $window.removeEventListener('blur', handleFocusChange, false); $window.removeEventListener('storage', onLocalStorageChange, false); } localStorageService.remove($window.tabId); localStorageService.remove(lcConsolePendingMsgKey); }; function init() { var eschatServerConfiguration = configurationModel.get('eschatConfiguration'); var isESChatIntegrationEnabled = eschatServerConfiguration.enableESChatIntegration || configurationModel.enableESChatIntegration; if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_LIVE_CHAT) || !isESChatIntegrationEnabled) { console.info('LiveChat.init() either Eschat application or ESChatIntegration is disabled. Navigating to dashboard.'); $state.go('dashboard'); return; } if (!eschatServerConfiguration.eschatServerUrl) { //if the url to load live chat doesn't exist $scope.showUnableToLoadMsg = true; $scope.state.loadingLiveChat = false; return; } else { $scope.showUnableToLoadMsg = false; } if ($state.current.data.path === 'dashboard') { $scope.hideForDashboard = true; } if (eschatServerConfiguration.eschatServerUrl) { localStorageService.set('eschatServerUrl', eschatServerConfiguration.eschatServerUrl); $scope.eschatServerUrl = eschatServerConfiguration.eschatServerUrl; $scope.smartITURL = window.location && window.location.origin; var path = $state.current.data.path; var userPref = ''; if ($rootScope.locale) { userPref = userPref + '&locale=' + $rootScope.locale; } if ($rootScope.timezone) { userPref = userPref + '&timezone=' + $rootScope.timezone; } $scope.crossLaunchLiveChatURL = $sce.trustAsResourceUrl(eschatServerConfiguration.eschatServerUrl + '/#?uid=' + encodeURIComponent($scope.userid) + userPref + '&embedded=smartit&path=' + path); } $scope.assignTicketToLiveAgent = eschatServerConfiguration.assignTicketToLiveAgent; $scope.allowedWindowEvents = [events.TICKET_CREATED_FROM_DRAFT, events.LIVECHAT_CREATEINCIDENT_SUCCESS, events.LIVECHAT_CREATEWORKORDER_SUCCESS, events.DRAFT_TICKET_CLOSED]; registerLiveChatListener(); setTab(); initAlertForDirtyForm(); //get global metadata metadataModel.getMetadataByType(EntityVO.TYPE_GLOBAL) .then(function (metadata) { $scope.createCallLogEnabled = metadata && metadata.configurationParameters && metadata.configurationParameters.enableSmartRecorderCallLog === 'true'; }); } $scope.createTicket = function (ticketType) { if (ticketType === EntityVO.TYPE_INCIDENT) { $scope.draftType = 'draftIncident'; } else if (ticketType === EntityVO.TYPE_WORKORDER) { $scope.draftType = 'draftWorkorder'; } var sessionId = $scope.selectedChat && $scope.selectedChat.sessionid; if ($scope.isAutoCreateTicketEnabled === true) { $scope.state.creatingTicket = false; if (sessionId) { if ($scope.createTicketInProgressForChatSessionSet.has(sessionId)) { console.warn('Auto ticket creation already in progress for sessionId: ' + sessionId); return; } $scope.createTicketInProgressForChatSessionSet.add(sessionId); } } else { $scope.state.creatingTicket = true; } $scope.ticketType = ticketType; //start - send an event to eschat to get the chat info to create a ticket var data = { event: LIVE_CHAT_APP_EVENTS.app_request_chat_ticket_data, data: { chatSessionId: sessionId } }; sendChildMessage(data); $scope.state.createTicketRequestPendingFromLC = true; //end $timeout(function () { if ($scope.state.creatingTicket === true && $scope.state.createTicketRequestPendingFromLC === true) { $scope.state.creatingTicket = false; console.log('No response from live chat on create ticket for sessionId: ' + sessionId); systemAlertService.error({ text: $filter('i18n')('error.unknown'), clear: false }); } }, CREATE_TICKET_TIMEOUT); }; function proceedToCreateTicket(chatSession, relatedTicket) { var metadata, ticketDataFromDraft, templateId; // Get metadata var metadataPromise = metadataModel.getMetadataByType($scope.ticketType); if (relatedTicket && (relatedTicket.templateGuid || relatedTicket.templateId)) { templateId = relatedTicket.templateGuid || relatedTicket.templateId; } else if (!relatedTicket) { var defaulTemplateFromConfig = $scope.selectedChatTicketConfig[$scope.ticketType].defaultTemplate; if ($scope.selectedTemplate) { templateId = $scope.selectedTemplate.id; } else if (defaulTemplateFromConfig) { templateId = defaulTemplateFromConfig.id; } } if (!_.isEmpty(ticketModel.cache.draft)) { delete ticketModel.cache.draft; } var ticketDataPromise = ticketModel.getDraft($scope.ticketType, templateId); $q.all([metadataPromise, ticketDataPromise]).then(function (results) { metadata = results[0]; // metadata ticketDataFromDraft = results[1]; // ticketdata // if the draft call returns an empty response, this happens when the template is deleted in ITSM if (!results[1] || !results[1].id) { $scope.state.creatingTicket = false; systemAlertService.error({ text: $filter('i18n')('error.unknown'), clear: false }); return; } if (templateId) { ticketDataFromDraft.templateGuid = templateId; } ticketDataFromDraft.chatSessionId = $scope.selectedChat.sessionid; //if the ticket is created from a ticket association and if the parent ticket doesn't use a template, //then the below fields will be copied to the new ticket if (relatedTicket && (relatedTicket.templateGuid || relatedTicket.templateId)) { ticketDataFromDraft.summary = relatedTicket.summary; ticketDataFromDraft.desc = relatedTicket.detailedDescription; ticketDataFromDraft.priority = relatedTicket.priority; if (relatedTicket && relatedTicket.categorizations) { var operationalCat = _.find(relatedTicket.categorizations, { name: 'operational' }); var productCat = _.find(relatedTicket.categorizations, { name: 'product' }); ticketDataFromDraft.categorizations = []; ticketDataFromDraft.categorizations.push(operationalCat); ticketDataFromDraft.categorizations.push(productCat); } } else { ticketDataFromDraft.summary = $scope.selectedChat.metadata.title.substring(0, summaryCharLimit); } if (relatedTicket && relatedTicket.reportedSource) { ticketDataFromDraft.reportedSource = relatedTicket.reportedSource; } else { ticketDataFromDraft.reportedSource = 'Chat'; } if ($scope.selectedChat.customer) { ticketDataFromDraft.customer = $scope.selectedChat.customer; } if ($scope.ticketType === EntityVO.TYPE_INCIDENT && !ticketDataFromDraft.priority) { if (!ticketDataFromDraft.impact) { ticketDataFromDraft.impact = _.last(metadata.impacts).name; } if (!ticketDataFromDraft.urgency) { ticketDataFromDraft.urgency = _.last(metadata.urgencies).name; } } //auto-assign to agent if the ticket is being created without a template and it's not an association ticket if (!templateId && $scope.assignTicketToLiveAgent) { liveChatService.assignToMe('ticketassignee', ticketDataFromDraft, chatSession, $scope); } else { handleAssignmentComplete('e', { ticket: ticketDataFromDraft, chatSession: chatSession }); } }); } function addRelation(uuid, type, relation) { relationModel.addRelation({ uuid: uuid, type: type }, relation); } function addWorkNoteForTicket(session, ticket) { var ticketData = { chatLog: session.chatlog, chatNotes: session.chatnotes, attachments: session.attachments }; var chatTicketData = prepareDataForTicket(ticketData); if (chatTicketData.chatLog) { processWorkNote(ticket.ticketId, ticket.ticketType, { text: chatTicketData.chatLog }, session.sessionid); } if (chatTicketData.chatInlineNotes) { processWorkNote(ticket.ticketId, ticket.ticketType, { text: chatTicketData.chatInlineNotes }, session.sessionid); } if (session.attachments && session.attachments.length) { var attachmentArray = session.attachments; if (attachmentArray.length > 3) { var attachmentLimit = 3, attachmentList = void 0; for (var i = 0, j = attachmentArray.length; i < j; i += attachmentLimit) { attachmentList = attachmentArray.slice(i, i + attachmentLimit); uploadAttachmentsToWorkLog(attachmentList, session); } } else { uploadAttachmentsToWorkLog(attachmentArray, session); } } } function processWorkNote(ticketId, ticketType, note, sessionId) { var workNote, ticketInfo = { type: ticketType, id: ticketId }; if (note.attachments) { workNote = { noteText: note.text, access: true, type: 35000, attachments: note.attachments }; return attachmentService.addWorknoteWithAttachment(ticketInfo, workNote); } else { workNote = { noteText: note.text, access: true, workInfoType: 35000, chatSessionId: sessionId }; return feedModel.saveNote(ticketInfo, workNote); } } function createCallLog(selectedChat, chatSessionIdToRemove) { if (!$scope.createCallLogEnabled) { selectedChat = null; systemAlertService.success({ text: i18nService.getLocalizedString('live.chat.createCallLog.success'), clear: true, hide: 10000 }); return; } if (!chatSessionIdToRemove) { $scope.state.creatingCallLog = true; } metadataModel.getMetadataByType(EntityVO.TYPE_SMART_RECORDER).then(function (results) { if (selectedChat) { if (results) { $scope.eventTypes = results.callLogEventTypes; } var callLogData = { persons: [] }; var dataObj = {}; if (selectedChat.customer) { dataObj.personId = selectedChat.customer.personId; dataObj.fullName = selectedChat.customer.fullName; dataObj.personType = 'customer'; callLogData.persons.push(dataObj); } callLogData.description = selectedChat.metadata.title; if (selectedChat.customerCompany) { callLogData.company = selectedChat.customerCompany.name; } var chatCallLogObj = { label: "Chat", value: "Chat" }; var chatCallLogEventIndex = _.findIndex($scope.eventTypes, chatCallLogObj); chatCallLogEventIndex = chatCallLogEventIndex !== -1 ? chatCallLogEventIndex : 0; callLogData.callLogEventType = $scope.eventTypes && $scope.eventTypes[chatCallLogEventIndex]; callLogData.chatSessionId = selectedChat.sessionid; smartRecorderModel.postCallLog(callLogData).then(function () { if (!chatSessionIdToRemove) { systemAlertService.success({ text: i18nService.getLocalizedString('live.chat.createCallLog.success'), clear: true, hide: 10000 }); $scope.state.creatingCallLog = false; } }, function (error) { if (!chatSessionIdToRemove) { systemAlertService.error({ text: (error && error.data && error.data.error) || error, clear: true, hide: 10000 }); $scope.state.creatingCallLog = false; } }); if (!chatSessionIdToRemove) { $scope.selectedChat = null; } if (chatSessionIdToRemove && chatSessionIdToRemove === selectedChat.sessionid) { $scope.selectedChat = null; chatSessionIdToRemove = null; } selectedChat = null; } else { console.error("Could not create a call log"); $scope.state.creatingCallLog = false; } }); } function showQuickTicketCreateSuccess(ticketType, ticketData, chatSession, action, relatedTicket) { // Save related resources. var agentChatIndex = _.findIndex($scope.agentChats, { sid: chatSession.sessionid }); var selectedResourcesToSave; if (chatSession.selectedResources) { selectedResourcesToSave = chatSession.selectedResources; } var transformedRelations = saveRelatedResources(selectedResourcesToSave, chatSession.sessionid); addResourceRelations(transformedRelations, ticketData, ticketData.id, (ticketType || $scope.ticketType)); var ticketDataForChat = { ticketType: ticketType, ticketDisplayId: ticketData.displayId, ticketId: ticketData.id }; if ($scope.selectedChat.sessionid === chatSession.sessionid) { $scope.selectedChat.ticket = ticketDataForChat; } if (agentChatIndex !== -1) { if ($scope.agentChats[agentChatIndex].selectedChatContext) { $scope.agentChats[agentChatIndex].selectedChatContext.ticket = ticketDataForChat; } } var msg; if (action === 'createTicket') { if (relatedTicket && relatedTicket.status && (relatedTicket.status.value === 'Resolved' || relatedTicket.status.value === 'Closed' || relatedTicket.status.value === 'Completed' || relatedTicket.status.value === 'Cancelled')) { msg = $filter('i18n')('live.chat.closed.ticket.relate.success', [utilityFunctions.getTicketCreatedSuccessMessageWithLink(ticketData.id, ticketData.displayId, ticketType, true)]); sendApplicationData(chatSession.sessionid, ticketDataForChat, relatedTicket); } else if (relatedTicket && relatedTicket.chatSessionId) { msg = $filter('i18n')('live.chat.associated.ticket.relate.success', [utilityFunctions.getTicketCreatedSuccessMessageWithLink(ticketData.id, ticketData.displayId, ticketType, true)]); sendApplicationData(chatSession.sessionid, ticketDataForChat, relatedTicket); } else { msg = $filter('i18n')('smartrecorder.quickTicketCreate.success', [utilityFunctions.getTicketCreatedSuccessMessageWithLink(ticketData.id, ticketData.displayId, ticketType, true)]); sendApplicationData(chatSession.sessionid, null, null, null, null, ticketData); } } else if (action === 'updateTicket') { msg = $filter('i18n')('live.chat.ticket.update.success', [utilityFunctions.getTicketCreatedSuccessMessageWithLink(ticketData.id, ticketData.displayId, ticketType, true)]); sendApplicationData(chatSession.sessionid, ticketDataForChat); } systemAlertService.success({ text: msg, clear: true, hide: 10000, isHTML: true }); if (chatSession) { addWorkNoteForTicket(chatSession, ticketDataForChat); getServiceRequestId(ticketType, ticketData.id, ticketData.displayId, chatSession.sessionid); } $scope.$broadcast('personDataUpdated', true); $scope.relatedTicketData = null; } function getServiceRequestId(parentTicketType, parentTicketId, parentDisplayId, sessionId, removeTicketAssociation) { searchService.getRequestForRelatedTicket(parentTicketId).then(function (srData) { //send the ticket data to eschat which will update the Master Chat Record form var appData = { data: { chatSessionId: sessionId, ticketId: parentDisplayId, ticketType: parentTicketType }, event: removeTicketAssociation ? LIVE_CHAT_APP_EVENTS.app_unrelate_ticket : LIVE_CHAT_APP_EVENTS.app_relate_ticket_to_chat }; var ticketType = parentTicketType, ticketId = parentDisplayId; if (srData && srData.appInstanceId === parentTicketId && srData.srDisplayId && srData.srDisplayId.length > 0) { ticketType = EntityVO.TYPE_SERVICEREQUEST; ticketId = srData.srDisplayId; } if (removeTicketAssociation) { appData.data.endUserTicketType = ticketType; appData.data.endUserTicketId = ticketId; sendApplicationData(sessionId, null, null, removeTicketAssociation); var messageToSend = $filter('i18n')('ticket.type.' + ticketType) + ' ' + ticketId + ' ' + $filter('i18n')('live.chat.ticket.unrelate.message'); appData.data.unRelateMessage = messageToSend; sendChildMessage(appData); $scope.state.creatingTicket = false; } else { var message_1 = { type: ticketType, ticketId: ticketId }; if (srData && srData.srDisplayId) { appData.data.endUserTicketType = EntityVO.TYPE_SERVICEREQUEST; appData.data.endUserTicketId = srData.srDisplayId; } sendChildMessage(appData); var messageToSend = $filter('i18n')('ticket.type.' + ticketType) + ' ' + ticketId + ' ' + $filter('i18n')('live.chat.ticket.message'); message_1.messageToSend = messageToSend; $timeout(function () { sendMessageToChat(null, message_1, sessionId); $scope.state.creatingTicket = false; $scope.createTicketInProgressForChatSessionSet.delete(sessionId); }, 1000); } }); } function sendApplicationData(sessionId, currentTicket, parentTicket, removeTicketAssociation, pinnedResources, newTicket) { var ticketAssocData, pinnedResourcesData = [], searchTextData, newTicketData; //store pinned articles in app data to load the pinned resources when a chat is either transfered or released if (pinnedResources) { if (pinnedResources.selectedKnowledge) { var pinnedKA_1; _.forEach(pinnedResources.selectedKnowledge, function (ka) { pinnedKA_1 = { id: ka.id, displayId: ka.displayId, type: EntityVO.TYPE_KNOWLEDGE }; if (configurationModel.comaroundEnabled) { pinnedKA_1.title = ka.title; } pinnedResourcesData.push(pinnedKA_1); }); } searchTextData = pinnedResources.summaryText || pinnedResources.summary; } else { pinnedResourcesData = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.pinnedArticles; searchTextData = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.searchText; } //this is in case of association (both update ticket and create ticket) if (currentTicket) { ticketAssocData = { "parentId": parentTicket && parentTicket.id ? parentTicket.id : '', "parentDisplayId": parentTicket && parentTicket.displayId ? parentTicket.displayId : '', "parentType": parentTicket && parentTicket.type ? parentTicket.type : '', "id": currentTicket.ticketId, "displayId": currentTicket.ticketDisplayId, "type": currentTicket.ticketType, "associationType": parentTicket ? 'create' : 'update' }; } else { ticketAssocData = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.ticketAssociationDetails; } if (removeTicketAssociation) { $scope.selectedChat.applicationData.ticketAssociationDetails = {}; ticketAssocData = {}; pinnedResourcesData = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.pinnedArticles; searchTextData = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.searchText; } //this is in case of create a new ticket by using the create ticket buttons if (newTicket) { newTicketData = { "ticketId": newTicket.id, "ticketDisplayId": newTicket.displayId, "ticketType": newTicket.type }; } else { newTicketData = $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.newTicketDetails; } $scope.selectedChat.applicationData = { ticketAssociationDetails: ticketAssocData, pinnedArticles: pinnedResourcesData, searchText: searchTextData, newTicketDetails: newTicketData }; var applicationData = JSON.stringify($scope.selectedChat.applicationData); var appData = { data: { chatSessionId: sessionId, appData: applicationData }, event: LIVE_CHAT_APP_EVENTS.app_save_appData }; console.log("Saving app data:" + JSON.stringify(appData)); sendChildMessage(appData); } function showQuickTicketCreateFailure(draftType, error, chatSession) { $scope.noOfDraftScreensOpen = ++$scope.noOfDraftScreensOpen; if ($scope.selectedChat && $scope.selectedChat.applicationData && $scope.selectedChat.applicationData.pinnedArticles) { chatSession.selectedResources = $scope.selectedChat.applicationData.pinnedArticles; } $scope.chatTicketDataForCreateMap.set(chatSession.sessionid, chatSession); $scope.createTicketInProgressForChatSessionSet.delete(chatSession.sessionid); $scope.state.creatingTicket = false; localStorageService.set('draft.ticket', ticketModel.cache.draft); localStorageService.set('draft.ticket.error', (error && error.data && error.data.error) || error); // prevent opening in new tab if the error is for unique index violation (https://jira.bmc.com/browse/DR931-742) if (!error || !error.data || (error && error.data && error.data.error.indexOf('ERROR (382)') === -1)) { var url = $state.href('liveChatDraft', { draftType: draftType }); $window.open(url, '_blank'); } } function saveTicketToChat(event, data) { systemAlertService.modal({ type: 'info', title: $filter('i18n')('live.chat.notification.title'), text: $filter('i18n')('live.chat.ticket.relate.confirmation.message'), buttons: [ { text: $filter('i18n')('common.button.yes'), data: true }, { text: $filter('i18n')('common.button.no'), data: false } ] }).result.then(function (result) { if (result) { $scope.relatedTicketData = data.ticket; //case 1 - if the ticket is resolved(INC) / completed(WO) or Cancelled or Closed OR if the ticket has a chat, create new ticket and use the same templated ID if it exists //case 2 - if the ticket is open and does not have a chat, associate the chat to the ticket if (data.ticket && (data.ticket.chatSessionId || (data.ticket.status && (data.ticket.status.value === 'Resolved' || data.ticket.status.value === 'Closed' || data.ticket.status.value === 'Completed' || data.ticket.status.value === 'Cancelled')))) { //create a new ticket and relate them $scope.createTicket(data.ticket.type); } else { $scope.state.creatingTicket = true; $scope.relateTicketToChatInProgress = true; //start - send an event to eschat to get the chat info to create a ticket var eventData = { event: LIVE_CHAT_APP_EVENTS.app_request_chat_ticket_data, data: { chatSessionId: data.chat && data.chat.sessionid } }; sendChildMessage(eventData); $scope.state.createTicketRequestPendingFromLC = true; //end $timeout(function () { if ($scope.state.creatingTicket === true && $scope.state.createTicketRequestPendingFromLC === true) { $scope.state.creatingTicket = false; console.log('No response from live chat on saving ticket to chat'); systemAlertService.error({ text: $filter('i18n')('error.unknown'), clear: false }); } }, CREATE_TICKET_TIMEOUT); } } }); } function removeTicketFromChat(event, data) { systemAlertService.modal({ type: 'info', title: $filter('i18n')('live.chat.notification.title'), text: $filter('i18n')('live.chat.ticket.unrelate.confirmation.message'), buttons: [ { text: $filter('i18n')('common.button.yes'), data: true }, { text: $filter('i18n')('common.button.no'), data: false } ] }).result.then(function (result) { if (result) { $scope.state.creatingTicket = true; var ticketData = { chatSessionId: '' }; if (data.ticket.id) { //update the ticket and clear the chat session ticketModel.update(data.ticket.id, data.ticket.type, ticketData).then(function (response) { if (response && response.data && response.data.error) { systemAlertService.error({ text: response.data.error, clear: true, hide: 10000 }); $scope.state.creatingTicket = false; return; } var msg = $filter('i18n')('live.chat.ticket.unrelate.success', [utilityFunctions.getTicketCreatedSuccessMessageWithLink(data.ticket.id, data.ticket.displayId, data.ticket.type, true)]); systemAlertService.success({ text: msg, clear: true, hide: 10000, isHTML: true }); $scope.$broadcast('personDataUpdated', true); if ($scope.selectedChat.sessionid) { getServiceRequestId(data.ticket.type, data.ticket.id, data.ticket.displayId, $scope.selectedChat.sessionid, true); } var workNote = $filter('i18n')('live.chat.ticket.unrelate.worknote', [$scope.user.fullName]); processWorkNote(data.ticket.id, data.ticket.type, { text: workNote }); if ($scope.selectedChat.applicationData && $scope.selectedChat.applicationData.ticketAssociationDetails && $scope.selectedChat.applicationData.ticketAssociationDetails.associationType === 'create') { //remove relationship between tickets var parent_1 = {}, relationToRemove = []; parent_1.parentType = $scope.selectedChat.applicationData.ticketAssociationDetails.parentType; parent_1.parentId = $scope.selectedChat.applicationData.ticketAssociationDetails.parentId; var obj = {}; obj.id = $scope.selectedChat.applicationData.ticketAssociationDetails.id; obj.type = $scope.selectedChat.applicationData.ticketAssociationDetails.type; obj.details = { 'parentDisplayId': $scope.selectedChat.applicationData.ticketAssociationDetails.parentDisplayId }; obj.relationshipType = EntityVO.TYPE_RELATEDTO; relationToRemove.push(obj); relationModel.removeRelation(parent_1, relationToRemove); //cancel the ticket var confirmationData = { confirmationEvent: LIVE_CHAT_APP_EVENTS.app_unrelate_ticket }; updateTicketAndRemoveChat($scope.selectedChat.ticket, confirmationData, null, null, null, true); } var chatToUpdate = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (chatToUpdate !== -1 && $scope.agentChats[chatToUpdate].selectedChatContext && $scope.agentChats[chatToUpdate].selectedChatContext.ticket) { $scope.agentChats[chatToUpdate].selectedChatContext.ticket = null; } $scope.selectedChat.ticket = null; }); } else { $scope.state.creatingTicket = false; } } }); } function handleAssignmentComplete(event, data) { var ticketDataFromDraft = data.ticket; var chatSession = data.chatSession; var relatedTicket = $scope.relatedTicketData; // clone ticketdata as quickTicketCreateData will shorten data that is being sent to server // and ticketDataFromDraft would be needed for draft in Edit Draft Screen. var ticketData = _.cloneDeep(ticketDataFromDraft); ticketData = quickTicketCreateData(ticketData, $scope.ticketType); // quick create mode or open draft by default var isDefaultDraftMode = $scope.selectedChatTicketConfig[$scope.ticketType].openDraftModeByDefault; if (isDefaultDraftMode === true && $scope.isAutoCreateTicketEnabled === false) { ticketModel.cache.draft = ticketDataFromDraft; showQuickTicketCreateFailure($scope.draftType, null, chatSession); } else { // Save draft ticketModel.saveQuickTicketDraft($scope.ticketType, ticketData).then(function () { handleDraftCreateComplete(ticketData, chatSession, relatedTicket); }).catch(function (error) { ticketModel.cache.draft = ticketDataFromDraft; showQuickTicketCreateFailure($scope.draftType, error, chatSession); }); } } function relateChatToTicket(ticket, session) { $scope.relateTicketToChatInProgress = false; var ticketData = { chatSessionId: session && session.sessionid }; if (ticket.id) { //update the ticket with the chat session ID ticketModel.update(ticket.id, ticket.type, ticketData).then(function (response) { if (response && response.data && response.data.error) { systemAlertService.error({ text: response.data.error, clear: true, hide: 10000 }); $scope.state.creatingTicket = false; return; } showQuickTicketCreateSuccess(ticket.type, ticket, session, 'updateTicket'); }); } } function setTicketCreationConfig() { $scope.selectedChatTicketConfig = { 'incident': { defaultTemplate: { type: 'incidentTemplate', id: '' }, openDraftModeByDefault: false }, 'workorder': { defaultTemplate: { type: 'workorderTemplate', id: '' }, openDraftModeByDefault: false } }; // go thru ticket config only if chat is assigned and has no ticket attached if ($scope.selectedChat.status === 'Assigned') { if (!$scope.ticketCreationConfigCompanyMap) { $scope.isIncidentCreateAllowed = true; $scope.isWOCreateAllowed = true; $scope.selectedChat.allowedTicketTypes = [EntityVO.TYPE_INCIDENT, EntityVO.TYPE_WORKORDER]; return; } var companyName = $scope.context.company ? $scope.context.company.toLowerCase() : 'global'; var ticketTypesConfigList = $scope.ticketCreationConfigCompanyMap[companyName]; if (!ticketTypesConfigList) { ticketTypesConfigList = $scope.ticketCreationConfigCompanyMap.global; //lowercase } if ($scope.selectedChat.ticket) { var ticketType = $scope.selectedChat.ticket.ticketType; if (ticketTypesConfigList[ticketType].openTicketOnClose) { // adding option to force edit mode from config if 'forceEdit' value is set, // till we don't allow edit mode OOTB if (ticketTypesConfigList[ticketType].openTicketOnCloseMode !== 'view' && ticketTypesConfigList[ticketType].openTicketOnCloseMode !== 'forceEdit') { // if mode value is incorrect, default to view ticketTypesConfigList[ticketType].openTicketOnCloseMode = 'view'; } $scope.selectedChatTicketConfig[ticketType].openTicketOnClose = ticketTypesConfigList[ticketType].openTicketOnClose; $scope.selectedChatTicketConfig[ticketType].openTicketOnCloseMode = ticketTypesConfigList[ticketType].openTicketOnCloseMode; } } else { $scope.isAutoCreateTicketEnabled = ticketTypesConfigList.autoCreate || false; // ignore the custom create options from MCR if auto create is not ON if (!$scope.isAutoCreateTicketEnabled) { $scope.selectedChat.autoCreateTicketType = undefined; $scope.selectedChat.autoCreateTemplateId = undefined; } else { $scope.autoCreateDefaultTicket = $scope.selectedChat.autoCreateTicketType; } if ($scope.autoCreateDefaultTicket !== EntityVO.TYPE_INCIDENT && $scope.autoCreateDefaultTicket !== EntityVO.TYPE_WORKORDER) { // if auto create ticket type from MCR is invalid, then clear the incorrect values // if auto create ticket type from MCR is invalid, then clear the incorrect values // if auto create ticket type from MCR is invalid, then clear the incorrect values // and ignore the template id from MCR as well $scope.autoCreateDefaultTicket = null; $scope.selectedChat.autoCreateTemplateId = undefined; } if ($scope.autoCreateDefaultTicket === null && (ticketTypesConfigList.autoCreateDefaultTicket === EntityVO.TYPE_INCIDENT || ticketTypesConfigList.autoCreateDefaultTicket === EntityVO.TYPE_WORKORDER)) { // validate auto create default ticket type from config $scope.autoCreateDefaultTicket = ticketTypesConfigList.autoCreateDefaultTicket; } if (ticketTypesConfigList && ticketTypesConfigList.hasOwnProperty(EntityVO.TYPE_INCIDENT)) { var incidentTicketConfig = ticketTypesConfigList[EntityVO.TYPE_INCIDENT]; $scope.isIncidentCreateAllowed = (incidentTicketConfig.hideCreateOption === true) ? false : true; $scope.selectedChatTicketConfig.incident.openDraftModeByDefault = incidentTicketConfig.openDraftModeByDefault || false; // either manual creation of incident is allowed or incident is the default ticket type for autoCreate var ticketTemplateId = $scope.selectedChat.autoCreateTemplateId || incidentTicketConfig.defaultTemplateId; if (($scope.isIncidentCreateAllowed === true || ($scope.isAutoCreateTicketEnabled && $scope.autoCreateDefaultTicket === EntityVO.TYPE_INCIDENT)) && ticketTemplateId) { $scope.selectedChatTicketConfig.incident.defaultTemplate.id = ticketTemplateId; } } else { // we default to always showing the option $scope.isIncidentCreateAllowed = true; } if ($scope.isWOInstalled && ticketTypesConfigList && ticketTypesConfigList.hasOwnProperty(EntityVO.TYPE_WORKORDER)) { var woTicketConfig = ticketTypesConfigList[EntityVO.TYPE_WORKORDER]; $scope.isWOCreateAllowed = (woTicketConfig.hideCreateOption === true) ? false : true; $scope.selectedChatTicketConfig.workorder.openDraftModeByDefault = woTicketConfig.openDraftModeByDefault || false; // either manual creation of WO is allowed or WO is the default ticket type for autoCreate var ticketTemplateId = $scope.selectedChat.autoCreateTemplateId || woTicketConfig.defaultTemplateId; if (($scope.isWOCreateAllowed === true || ($scope.isAutoCreateTicketEnabled && $scope.autoCreateDefaultTicket === EntityVO.TYPE_WORKORDER)) && ticketTemplateId) { $scope.selectedChatTicketConfig.workorder.defaultTemplate.id = ticketTemplateId; } } else if ($scope.isWOInstalled) { // we default to always showing the option $scope.isWOCreateAllowed = true; } else { $scope.isWOCreateAllowed = false; } if ($scope.isAutoCreateTicketEnabled && $scope.autoCreateDefaultTicket) { $scope.createTicket($scope.autoCreateDefaultTicket); } else if (!$scope.isAutoCreateTicketEnabled) { // fetch templates only for tickets that we are displaying on UI var ticketTypesAllowed = []; if ($scope.isIncidentCreateAllowed) { ticketTypesAllowed.push(EntityVO.TYPE_INCIDENT); } if ($scope.isWOInstalled && $scope.isWOCreateAllowed) { ticketTypesAllowed.push(EntityVO.TYPE_WORKORDER); } // do not search templates if no ticket types are allowed if (ticketTypesAllowed.length === 0) { ticketTypesAllowed.push('none'); } $scope.context.searchTicketTypes = ticketTypesAllowed; $scope.selectedChat.allowedTicketTypes = ticketTypesAllowed; // set template as selected in resources tab only if one ticket type is allowed if (ticketTypesAllowed.length === 1) { var isTemplateSelectedForChat = false; var agentChatIndex = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChatIndex !== -1) { if ($scope.agentChats[agentChatIndex].selectedChatContext && $scope.agentChats[agentChatIndex].selectedChatContext.selectedTemplate) { isTemplateSelectedForChat = true; } } if (!isTemplateSelectedForChat) { // show default template as selected in resources tab saveTemplate({}, $scope.selectedChatTicketConfig[ticketTypesAllowed[0]].defaultTemplate); $scope.context.selectedTemplate = $scope.selectedTemplate; } } } } } } function chatCustomerDataLoaded(event, person) { if ($scope.selectedChat.user === person.id) { $scope.selectedChat.customer = person; $scope.selectedChat.customerCompany = person.company; $scope.context.chatUserCompany = person.company && person.company.name; // for templates, we want to use customer's company $scope.context.company = $scope.context.chatUserCompany; $scope.context.customerId = person.id; // set ticket creation config whenever we switch a chat setTicketCreationConfig(); } else if ($scope.selectedChat.user !== personModel.personDetails.id) { personModel.getPersonDetailsByID($scope.selectedChat.user) .then(function (personDetails) { personModel.personDetails = personDetails; $scope.$broadcast('personDataUpdated'); }); console.warn('selected chat user id: ' + $scope.selectedChat.user + ', does not match with person id: ' + person.id); } } function clearChatContext(removeChat) { if (removeChat) { var removeChat_1 = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (removeChat_1 !== -1) { $scope.agentChats.splice(removeChat_1, 1); } } $scope.selectedChat = null; $scope.$broadcast(events.ON_SELECTED_LIVE_CHAT); personModel.personDetails = []; $scope.$broadcast('personDataUpdated'); $timeout(function () { $scope.state.appModalEventConfirmWaiting = false; }, 1000); } // call back used by resource slice directive to save selected template function saveTemplate(event, template) { if ($scope.selectedChat && template && template.id) { // allow the template to be set only if that ticket create is allowed if (($scope.isWOCreateAllowed && template.type === 'workorderTemplate') || ($scope.isIncidentCreateAllowed && template.type === 'incidentTemplate')) { $scope.selectedTemplate = template; var agentChat = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChat !== -1) { if ($scope.agentChats[agentChat].selectedChatContext) { $scope.agentChats[agentChat].selectedChatContext.selectedTemplate = $scope.selectedTemplate; } } } } } // call back used by resource slice directive to delete previously selected template function unrelateTemplate() { if ($scope.selectedChat) { $scope.selectedTemplate = null; var agentChat = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChat !== -1) { if ($scope.agentChats[agentChat].selectedChatContext) { $scope.agentChats[agentChat].selectedChatContext.selectedTemplate = $scope.selectedTemplate; } } } } // call back used by resource slice directive to save selected KA function saveToTicketFromRs(event, relationItem, isKASharedWithUser) { if ($scope.selectedChat) { angular.extend(relationItem, { tag: EntityVO.TYPE_RESOURCE, relationshipType: RelationItemVO.TYPE_RELATEDTO, isKASharedWithUser: isKASharedWithUser }); var agentChatIdx = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChatIdx !== -1) { if ($scope.agentChats[agentChatIdx].selectedChatContext) { if ($scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge) { var isRelatedItem = _.findIndex($scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge, { id: relationItem.id }); if (isRelatedItem === -1) { $scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge.push(relationItem); } } else { $scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge = []; $scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge.push(relationItem); } } } //save pinned articles in app data field on MCR sendApplicationData($scope.selectedChat.sessionid, null, null, null, $scope.agentChats[agentChatIdx].selectedChatContext); relationModel.cache[$scope.selectedChat.sessionid] = relationModel.cache[$scope.selectedChat.sessionid] && relationModel.cache[$scope.selectedChat.sessionid].length ? relationModel.cache[$scope.selectedChat.sessionid] : []; var relationItemIdx = _.findIndex(relationModel.cache[$scope.selectedChat.sessionid], { id: relationItem.id }); if (relationItemIdx === -1) { relationModel.cache[$scope.selectedChat.sessionid].push(relationItem); } } } // call back used by resource slice directive to delete previously selected KA function removeFromTicketFromRs(event, relationItem) { if ($scope.selectedChat) { var agentChatIdx = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChatIdx !== -1) { if ($scope.agentChats[agentChatIdx].selectedChatContext && $scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge) { var removeIdx = _.findIndex($scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge, { id: relationItem.id }); $scope.agentChats[agentChatIdx].selectedChatContext.selectedKnowledge.splice(removeIdx, 1); } } //save pinned articles in app data field on MCR sendApplicationData($scope.selectedChat.sessionid, null, null, null, $scope.agentChats[agentChatIdx].selectedChatContext); if (relationModel.cache[$scope.selectedChat.sessionid] && relationModel.cache[$scope.selectedChat.sessionid].length > 0) { var relationItemIdx = _.findIndex(relationModel.cache[$scope.selectedChat.sessionid], { id: relationItem.id }); relationModel.cache[$scope.selectedChat.sessionid].splice(relationItemIdx, 1); } } } function saveSearchTextToselectedChatContext(event, searchText) { if ($scope.selectedChat) { var agentChat = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (agentChat !== -1) { if ($scope.agentChats[agentChat].selectedChatContext) { $scope.agentChats[agentChat].selectedChatContext.summaryText = searchText; //save search text to app data on MCR sendApplicationData($scope.selectedChat.sessionid, null, null, null, $scope.agentChats[agentChat].selectedChatContext); } } } } // send message to chat conversation function sendMessageToChat(event, message, sessionId) { if (!$scope.selectedChat) { return; } var messageToSend, chatSessionId; //if sharing a KA if (message.type === EntityVO.TYPE_KNOWLEDGE) { if (!message.additionalInformation && !message.additionalInformation.crossLaunchURL) { return; } else { var midtierCrossLaunchURLForKA = message.additionalInformation && message.additionalInformation.crossLaunchURL; var KAShareMsg = $filter('i18n')('live.chat.KA.sharedWithUser'); messageToSend = "" + KAShareMsg + "
" + message.displayId + ": " + message.title + "<\/span>"; //shared articles should be saved to the ticket saveToTicketFromRs(event, message, true); chatSessionId = $scope.selectedChat.sessionid; } } else { messageToSend = message.messageToSend; chatSessionId = sessionId; } var data = { data: { chatSessionId: chatSessionId, messageToSend: messageToSend, type: message.type, ticketId: message.ticketId || message.displayId }, event: LIVE_CHAT_APP_EVENTS.app_send_message_to_chat }; sendChildMessage(data); } function showModalDialog(data) { var title = data.chatData.modalTitle, message, buttons, confirmationData = { confirmationData: data.action.confirmationData, confirmationEvent: data.action.confirmationEvent }; if (data.action.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session || data.action.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_abandon_session) { if ($scope.selectedChat.ticket) { if (data.action.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session) { ticketModel.getTicketDetails($scope.selectedChat.ticket.ticketId, $scope.selectedChat.ticket.ticketType, true).then(function (response) { if (response) { if (response.status && response.status.value) { if ((response.type === EntityVO.TYPE_INCIDENT && (response.status.value === 'Resolved' || response.status.value === 'Cancelled' || response.status.value === 'Closed')) || (response.type === EntityVO.TYPE_WORKORDER && (response.status.value === 'Completed' || response.status.value === 'Cancelled' || response.status.value === 'Closed'))) { message = data.chatData && data.chatData.modalMessage ? data.chatData.modalMessage : $filter('i18n')('live.chat.close.with.closed.ticket', [data.chatData.session.user.first_name, data.chatData.session.user.last_name]); buttons = getButtonsForDialog(false, confirmationData, data); openModalDialog(title, message, buttons, null, true); } else { message = i18nService.getLocalizedString('live.chat.close.with.ticket'); buttons = getButtonsForDialog(true, confirmationData, data); openModalDialog(title, message, buttons); } } else { //DRSMX-30719 - if the agent doesn't have access rights on the ticket, we will only close the chat and do nothing with the ticket message = data.chatData && data.chatData.modalMessage ? data.chatData.modalMessage : $filter('i18n')('live.chat.close.with.closed.ticket', [data.chatData.session.user.first_name, data.chatData.session.user.last_name]); buttons = getButtonsForDialog(false, confirmationData, data); openModalDialog(title, message, buttons, true); } } else { message = i18nService.getLocalizedString('live.chat.close.with.ticket'); buttons = getButtonsForDialog(true, confirmationData, data); openModalDialog(title, message, buttons); } }).catch(function (error) { message = i18nService.getLocalizedString('live.chat.close.with.ticket'); buttons = getButtonsForDialog(true, confirmationData, data); openModalDialog(title, message, buttons); }); } else if (data.action.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_abandon_session) { message = i18nService.getLocalizedString('live.chat.abandon.with.ticket'); buttons = getButtonsForDialog(false, confirmationData, data); openModalDialog(title, message, buttons); } } else { message = (data.action.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session) ? i18nService.getLocalizedString('live.chat.close.without.ticket') : i18nService.getLocalizedString('live.chat.abandon.without.ticket'); buttons = getButtonsForDialog(false, confirmationData, data); openModalDialog(title, message, buttons); } } else { message = data.chatData.modalMessage; buttons = getButtonsForDialog(false, confirmationData, data); openModalDialog(title, message, buttons); } } function getButtonsForDialog(showThreeBtns, confirmationData, sessionData) { var buttons; if (showThreeBtns) { buttons = [ { text: i18nService.getLocalizedString('common.button.yes'), data: { option: 'yes', confirmationData: confirmationData, session: sessionData.chatData.session } }, { text: i18nService.getLocalizedString('common.button.no'), data: { option: 'no', confirmationData: confirmationData, session: sessionData.chatData.session } }, { text: i18nService.getLocalizedString('common.button.cancel'), data: false } ]; } else { buttons = [ { text: i18nService.getLocalizedString('common.button.yes'), data: { option: 'yes', confirmationData: confirmationData, session: sessionData.chatData.session } }, { text: i18nService.getLocalizedString('common.button.cancel'), data: false } ]; } return buttons; } function addResourceRelations(transformedRelations, ticketData, ticketId, ticketType) { _.forEach(transformedRelations, function (relation) { delete relation.isKASharedWithUser; }); if (transformedRelations.length > 0) { if (configurationModel.comaroundEnabled) { var hkmKAList = _.remove(transformedRelations, { type: EntityVO.TYPE_KNOWLEDGE }); if (hkmKAList && hkmKAList.length) { relationModel.bulkAddRelationHKM({ uuid: ticketData.displayId || ticketData.ticketDisplayId }, hkmKAList); } } if (transformedRelations.length > 0) { addRelation(ticketId, ticketType, transformedRelations); } } } function openModalDialog(title, message, buttons, noAccessToTicket, isTicketClosed) { systemAlertService.modal({ title: title, text: message, buttons: buttons }).result.then(function (data) { if (data) { $scope.state.appModalEventConfirmWaiting = true; var removeChat = _.findIndex($scope.agentChats, { sid: $scope.selectedChat.sessionid }); if (!noAccessToTicket) { var ticketData = $scope.agentChats[removeChat] && $scope.agentChats[removeChat].selectedChatContext && $scope.agentChats[removeChat].selectedChatContext.ticket; if (data.confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session || data.confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_abandon_session) { if (ticketData) { if (data.option === 'yes' && !isTicketClosed) { if (ticketData.ticketDisplayId || ticketData.ticketType || ticketData.ticketId) { updateTicketAndRemoveChat(ticketData, data.confirmationData, data.session, null, null, null, true); return; } } else if (data.option === 'no' || isTicketClosed) { addWorkNoteForTicket(data.session, ticketData); if ($scope.agentChats[removeChat].selectedChatContext && $scope.agentChats[removeChat].selectedChatContext.selectedKnowledge) { var transformedRelations = saveRelatedResources($scope.agentChats[removeChat].selectedChatContext.selectedKnowledge, $scope.selectedChat.sessionid); addResourceRelations(transformedRelations, ticketData, ticketData.ticketId, ticketData.ticketType); } openTicketOnChatClose(ticketData.ticketId, ticketData.ticketType); clearChatContext(true); } } else { //create call log createCallLog($scope.selectedChat); clearChatContext(true); } } else if (data.confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_release_session) { clearChatContext(true); } } else { clearChatContext(true); } sendChildMessage({ data: data.confirmationData.confirmationData, event: data.confirmationData.confirmationEvent }); } }); } function updateTicketAndRemoveChat(ticket, confirmationData, session, cancelledByEndUser, chatSessionIdToRemove, removeTicketAssociation, clearChat) { var statusData; metadataModel.getMetadataByType(ticket.ticketType).then(function (results) { var ticketMetaData = results && results.statuses; var status, statusReason, resNote; //mark ticket as resolved if (ticket.ticketType === EntityVO.TYPE_INCIDENT) { if (confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session) { status = _.find(ticketMetaData, { name: 'Resolved' }); statusReason = _.find(status.statusReasons, { name: 'No Further Action Required' }); } else { status = _.find(ticketMetaData, { name: 'Cancelled' }); statusReason = _.find(status.statusReasons, { name: 'No longer a Causal CI' }); } if (confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session || confirmationData.confirmationEvent === LIVE_CHAT_EVENTS.sac_session_cancelled) { resNote = $filter('i18n')('live.chat.close.resolution.note'); } else if (confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_unrelate_ticket) { resNote = $filter('i18n')('live.chat.ticket.unrelate.success', [ticket.ticketDisplayId]); } else { resNote = $filter('i18n')('live.chat.abandon.resolution.note'); } statusData = { status: status.name, statusReason: statusReason.name, resNote: resNote }; } else if (ticket.ticketType === EntityVO.TYPE_WORKORDER) { if (confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session) { status = _.find(ticketMetaData, { name: 'Completed' }); statusReason = _.find(status.statusReasons, { name: 'Successful' }); } else { status = _.find(ticketMetaData, { name: 'Cancelled' }); statusReason = confirmationData.confirmationEvent === LIVE_CHAT_EVENTS.sac_session_cancelled ? _.find(status.statusReasons, { name: 'Cancelled by Requester' }) : _.find(status.statusReasons, { name: 'Cancelled by Support' }); } if (confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_event_confirm_close_session) { resNote = $filter('i18n')('live.chat.close.resolution.note'); } else if (confirmationData.confirmationEvent === LIVE_CHAT_APP_EVENTS.app_unrelate_ticket) { resNote = $filter('i18n')('live.chat.ticket.unrelate.success', [ticket.ticketDisplayId]); } else { resNote = $filter('i18n')('live.chat.abandon.resolution.note'); } statusData = { status: status.name, statusReason: statusReason.name, resNote: resNote }; } if (ticket.ticketId) { ticketModel.update(ticket.ticketId, ticket.ticketType, statusData, cancelledByEndUser).then(function (response) { if (removeTicketAssociation) { return; } //if the chat was cancelled by the end user and if the agent does not have access to update the ticket, there will be an error. //Trap the error and update the work notes and indicate the assignee to close the ticket if (response && response.status === 500) { var workNote = void 0; if (cancelledByEndUser) { workNote = $filter('i18n')('live.chat.cancel.enduser.worknote'); } else { workNote = resNote; } processWorkNote(ticket.ticketId, ticket.ticketType, { text: workNote }); } //if there is no error, update work notes with chat log, chat inline notes and attachments if (session) { addWorkNoteForTicket(session, ticket); } var transformedRelations = saveRelatedResources(null, session.sessionid); addResourceRelations(transformedRelations, ticket, ticket.ticketId, ticket.ticketType); if (clearChat) { openTicketOnChatClose(ticket.ticketId, ticket.ticketType); sendChildMessage({ data: confirmationData.confirmationData, event: confirmationData.confirmationEvent }); if ($scope.selectedChat.sessionid === confirmationData.confirmationData) { clearChatContext(true); } } if (!chatSessionIdToRemove && $scope.selectedChat.sessionid === confirmationData.confirmationData) { $scope.selectedChat = null; return; } if ((chatSessionIdToRemove && chatSessionIdToRemove === $scope.selectedChat.sessionid) || $scope.selectedChat.sessionid === confirmationData.confirmationData) { $scope.selectedChat = null; } }); } else { var ticketInfo_4, params = { search_text: ticket.ticketDisplayId }, jsonParams = { types: ['tickets'] }; searchService.getGlobalSearchResults(params, jsonParams).then(function (response) { if (!_.isEmpty(response.items) && response.items[0] && response.items[0].results && response.items[0].results.length) { ticketInfo_4 = _.find(response.items[0].results, { displayId: ticket.ticketDisplayId }); ticketModel.update(ticketInfo_4.id, ticketInfo_4.type, statusData).then(function () { if (removeTicketAssociation) { return; } //update work notes if (session) { addWorkNoteForTicket(session, ticket); } //update the ticket with any selected KA var transformedRelations = saveRelatedResources(null, session.sessionid); addResourceRelations(transformedRelations, ticketInfo_4, ticketInfo_4.id, ticketInfo_4.type); if (!chatSessionIdToRemove) { $scope.selectedChat = null; return; } if (chatSessionIdToRemove && chatSessionIdToRemove === $scope.selectedChat.sessionid) { $scope.selectedChat = null; } }); } }); } }); } function openTicketOnChatClose(ticketId, ticketType) { var ticketConfig = $scope.selectedChatTicketConfig[ticketType]; var openTicketOnClose = ticketConfig.openTicketOnClose; if (openTicketOnClose) { $scope.hasEditPermission = permissionModel.hasPermissionForTicket(ticketType); if (ticketConfig.openTicketOnCloseMode === 'forceEdit') { ticketConfig.openTicketOnCloseMode = 'edit'; } if ((ticketConfig.openTicketOnCloseMode === 'edit' && $scope.hasEditPermission) || (ticketConfig.openTicketOnCloseMode === 'view')) { var url = $state.href('liveChatDraft', { id: ticketId, draftType: ticketType, launchMode: ticketConfig.openTicketOnCloseMode }); $window.open(url, '_blank', 'noopener, noreferrer'); } } } function saveRelatedResources(selectedResourcesToSave, chatSessionId) { // Save related resources. var transformedRelations = []; var relations; if (selectedResourcesToSave) { relations = selectedResourcesToSave; } else { var agentChatIndex = _.findIndex($scope.agentChats, { sid: chatSessionId }); if (agentChatIndex !== -1) { if ($scope.agentChats[agentChatIndex].selectedChatContext && $scope.agentChats[agentChatIndex].selectedChatContext.selectedKnowledge) { relations = $scope.agentChats[agentChatIndex].selectedChatContext.selectedKnowledge; } } } if (relations) { for (var relationCounter = 0; relationCounter < relations.length; relationCounter++) { var relation = relations[relationCounter]; relation = new RelationItemVO().build(relation); relation.isPoi = undefined; relation.realObject = undefined; relation.entityLink = undefined; relation.isKASharedWithUser = relations[relationCounter].isKASharedWithUser; if (!relation.tag) { relation.tag = EntityVO.TYPE_RESOURCE; } if (!relation.relationshipType) { relation.relationshipType = EntityVO.TYPE_RELATEDTO; } if (!relation.type) { relation.type = EntityVO.TYPE_KNOWLEDGE; } transformedRelations.push(relation); } } return transformedRelations; } function quickTicketCreateData(ticketData, ticketType) { var createData, ticket; delete ticketData.accessMappings; if (ticketData.customer.accessMappings) { delete ticketData.customer.accessMappings; } if (ticketType === EntityVO.TYPE_INCIDENT) { if (ticketData.causalCI === '') { delete ticketData.causalCI; delete ticketData.causalCIreconId; } if (ticketData.impactedService === '') { delete ticketData.impactedService; delete ticketData.impactedServiceReconId; } if (ticketData.contact && ticketData.contact.accessMappings) { delete ticketData.contact.accessMappings; } } else if (ticketType === EntityVO.TYPE_WORKORDER) { ticket = ticketData; createData = { id: ticket.id, displayId: ticket.displayId, summary: ticket.summary, customer: ticket.customer, desc: ticket.desc, priority: ticket.priority, status: ticket.status, categorizations: ticket.categorizations, type: EntityVO.TYPE_WORKORDER }; if (ticket.reportedSource) { createData.reportedSource = ticket.reportedSource; } if (ticket.location && ticket.location.poiId) { createData.location = { poiId: ticket.location.poiId }; } if (ticket.locationCompany) { createData.locationCompany = ticket.locationCompany; } if (ticket.impactedService) { createData.impactedService = ticket.impactedService; } if (ticket.scheduledStartDate) { createData.scheduledStartDate = moment(ticket.scheduledStartDate).valueOf(); } if (ticket.scheduledEndDate) { createData.scheduledEndDate = moment(ticket.scheduledEndDate).valueOf(); } if (ticket.actualStartDate) { createData.actualStartDate = moment(ticket.actualStartDate).valueOf(); } if (ticket.actualEndDate) { createData.actualEndDate = moment(ticket.actualEndDate).valueOf(); } if (ticket.supportGroup) { createData.supportGroup = ticket.supportGroup; } if (ticket.assignee) { createData.assignee = ticket.assignee; } if (ticket.managerGroup) { createData.managerGroup = ticket.managerGroup; } if (ticket.manager) { createData.manager = ticket.manager; } if (ticket.templateId) { createData.templateId = ticket.templateId; } if (ticket.templateName) { createData.templateName = ticket.templateName; } if (ticket.attachments) { createData.attachments = ticket.attachments; } // prepare custom field values if (_.size(ticket.customFields)) { createData.customFields = ticket.customFields; } //prepare dynamic field values if (ticket.dynamicFields) { createData.dynamicFields = ticket.dynamicFields; } if (ticket.chatSessionId) { createData.chatSessionId = ticket.chatSessionId; } ticketData = createData; } return ticketData; } function initAlertForDirtyForm() { var text; $scope.$on('$stateChangeStart', function (event, toState, toParams) { if ($scope.isDirtyFlag === true && !$scope.state.loadingLiveChat && (toState.name !== 'liveChatAgentConsole' || toState.name !== 'liveChatDashboard')) { event.preventDefault(); if ($scope.noOfDraftScreensOpen > 0) { text = $filter('i18n')('live.chat.data-loss.notification.dirty.message'); } else { text = i18nService.getLocalizedString('live.chat.notification.dirty.message'); } var modalInstance = systemAlertService.modal({ title: i18nService.getLocalizedString('common.notification.dirty.title'), text: text, buttons: [ { text: i18nService.getLocalizedString('common.labels.yes'), data: { stateName: toState.name, stateParams: toParams } }, { text: i18nService.getLocalizedString('common.labels.no') } ] }); modalInstance.result.then(function (data) { if (!_.isEmpty(data)) { $scope.isDirtyFlag = false; $scope.noOfDraftScreensOpen = 0; unregisterLiveChatListener(); $state.transitionTo(data.stateName, data.stateParams); } }); } }); } init(); } ]); })();