"use strict"; (function () { 'use strict'; angular.module('ticketModule') .controller('TicketController', ['$scope', '$rootScope', '$state', '$q', '$filter', '$modal', '$window', '$injector', 'ticketModel', 'relationModel', 'approvalModel', 'knowledgeArticleModel', 'categoriesService', 'ticketActionService', 'followService', 'screenConfigurationModel', 'events', 'systemAlertService', 'srdModel', 'metadataModel', '$timeout', '$location', 'emailModel', 'relationService', 'approvalService', 'i18nService', 'collisionModel', 'searchModel', 'configurationModel', 'userModel', 'chatModel', 'layoutConfigurationModel', '$log', 'permissionModel', 'objectValueMapperService', 'expressionEvaluatorService', function ($scope, $rootScope, $state, $q, $filter, $modal, $window, $injector, ticketModel, relationModel, approvalModel, knowledgeArticleModel, categoriesService, ticketActionService, followService, screenConfigurationModel, events, systemAlertService, srdModel, metadataModel, $timeout, $location, emailModel, relationService, approvalService, i18nService, collisionModel, searchModel, configurationModel, userModel, chatModel, layoutConfigurationModel, $log, permissionModel, objectValueMapperService, expressionEvaluatorService) { var id = $scope.id, type = $scope.type, state = { dataIsLoading: true }, relationCounters = { tickets: 0, linkedItems: 0 }, hasCollisions = false, showAffectedServiceRelation = false, screenName = screenConfigurationModel.getScreenNameByTicketType(type), //Last argument makes ticketModel request ticket data from the server, instead of cached value //It is particularly important when navigating from global search preview to full profile page of the item ticketPromise = ticketModel.getTicket(id, type, true), metaDataPromise = metadataModel.getMetadataByTypes(EntityVO.ALL_TYPES), globalMetaDataPromise = metadataModel.getMetadataByType(EntityVO.TYPE_GLOBAL), layoutConfigurationPromise = layoutConfigurationModel.loadScreenLayout(screenName), screenConfigurationPromise = screenConfigurationModel.isV2CompatibleScreen(screenName) ? screenConfigurationModel.loadScreenConfigurationByName(screenName) : screenConfigurationModel.loadScreenConfigurationAndCustomFieldLabels(screenName, type), promises = [ticketPromise, metaDataPromise, layoutConfigurationPromise, screenConfigurationPromise], handleGlobalMetaDataPromise = function (globalMetadata) { if (globalMetadata && globalMetadata.configurationParameters) { showAffectedServiceRelation = (globalMetadata.configurationParameters.affectedServiceRelation === "true"); } //Async request for relations to be used by other components relationModel.getRelations(id, type).then(function () { $scope.relations = angular.copy(relationModel.cache); }); }; //todo: Viktor implement silent check for ticket updates $scope.metadata = {}; $scope.isFullVersion = true; $scope.numberOfRelatedTasks = 0; $scope.numberOfLinkedResources = 0; $scope.editHeader = false; //indicator flag if header is under edit mode $scope.isContactCollapsed = true; $scope.hasAlerts = false; //Indicates if the alert carousel has to be displayed - UC/Change/Collisions - Enhancement to display Collisions $scope.dirty = false; $scope.loggedInUserId = userModel.decodedUserId || userModel.userId; $scope.isCategoriesEmpty = false; $scope.hasEditPermission = permissionModel.hasPermissionForTicket(type); $scope.availableForAssignment = userModel.userFullData.availableForAssignment; $scope.chatModel = { connected: chatModel.connected }; $scope.$watch(function () { return chatModel.connected; }, function (newVal) { $scope.chatModel.connected = newVal; }); // delete cache $scope.$on('$destroy', function () { delete ticketModel.cache[id]; delete relationModel.cache[id]; //unregistered listener on traversing from ticket view mode var unbindRootScopeListener = objectValueMapperService.isProviderActionEventRegistered(); if (unbindRootScopeListener) { unbindRootScopeListener(); objectValueMapperService.registerProviderActionCallExpressionEvent(null); } }); $scope.refreshTicket = function (fromCache) { $scope.state.dataIsLoading = true; //delete cache if (!fromCache) { delete ticketModel.cache[id]; delete relationModel.cache[id]; approvalModel.clearListOfApproversCache(id); } if ($scope.basicData && $scope.basicData.accessMappings && !$scope.basicData.accessMappings.impactEditAllowed && !searchModel.disableImpactAnalysis) { $scope.moreDropDownOptions = null; } //get the details ticketPromise = ticketModel.getTicket(id, type, !fromCache); metaDataPromise = metadataModel.getMetadataByTypes(EntityVO.ALL_TYPES); globalMetaDataPromise = metadataModel.getMetadataByType(EntityVO.TYPE_GLOBAL); layoutConfigurationPromise = layoutConfigurationModel.loadScreenLayout(screenName, !fromCache); screenConfigurationPromise = screenConfigurationModel.getScreenNameByTicketType(type) && !fromCache ? (screenConfigurationModel.isV2CompatibleScreen(screenName) ? screenConfigurationModel.loadScreenConfigurationByName(screenName, true) : screenConfigurationModel.loadScreenConfigurationAndCustomFieldLabels(screenName, type, true)) : $q.when({}); promises = [ticketPromise, metaDataPromise, layoutConfigurationPromise, screenConfigurationPromise]; globalMetaDataPromise.then(handleGlobalMetaDataPromise); // since relations cache is deleted, we need to get the relations again. relationModel.getRelations(id, type).then(function (response) { $scope.relations = angular.copy(relationModel.cache); }); $scope.$emit(events.REFRESH_TICKET); $q.all(promises).then(function (responses) { processPromises(responses); }).finally(postProcessPromises); }; $scope.relations = angular.copy(relationModel.cache); $scope.$watchCollection('relations', function () { updateRelations(); }, true); /*This event captures the addition of related items, or tasks to a ticket. In case of related items addition cache is updated from the response but in case of task addition no cache is set, so getRelations is called which brings all the relations and set the cache.*/ $scope.$on(events.RELATIONS_UPDATE_COMPLETE, function (event, updateFlag) { if (updateFlag) { delete relationModel.cache[id]; relationModel.getRelations($scope.id, $scope.type).then(function (response) { $scope.relations = angular.copy(relationModel.cache); updateRelations(); }); } else { $scope.relations = angular.copy(relationModel.cache); updateRelations(); } }); $scope.moreDropDownActionsCallbackFuncns = { runImpactAnalysis: function () { function showConfirmationDialog(title, text, command) { return systemAlertService.modal({ title: title, text: text, type: 'info', buttons: [ { text: i18nService.getLocalizedString('impact.analysis.cancel.existing.yes'), data: true }, { text: i18nService.getLocalizedString('impact.analysis.cancel.existing.no'), data: false } ] }).result.then(function (data) { if (data) { initiateImpactAnalysisCall(command); } }); } function initiateImpactAnalysisCall(command) { ticketModel.impactAnalysisAction($scope.basicData.id, $scope.basicData.type, command) .then(function (response) { $scope.basicData.hasImpactAnalysis = false; if (response && response.status && response.status.value) { $scope.basicData.hasImpactAnalysis = true; if (response.status.value === 'Relationship Assessment Completed') { $scope.basicData.impactAnalysisStatus = 'Completed'; } else if (response.status.value === 'Analysis Completed' || response.status.value === 'Analysis In Progress' || response.status.value === 'Relationship Assessment In Progress') { $scope.basicData.impactAnalysisStatus = 'Pending'; } else { $scope.basicData.impactAnalysisStatus = 'Unknown'; } } }); } var title, text, command; if ($scope.basicData.hasImpactAnalysis && $scope.basicData.impactAnalysisStatus === 'Pending') { title = i18nService.getLocalizedString('impact.analysis.cancel.existing.modal.title'); text = i18nService.getLocalizedString('impact.analysis.cancel.existing.modal.text'); command = { "command": "force_start" }; showConfirmationDialog(title, text, command); } else if ($scope.basicData.hasImpactAnalysis && $scope.basicData.impactAnalysisStatus === 'Completed') { title = i18nService.getLocalizedString('impact.analysis.dismiss.existing.modal.title'); text = i18nService.getLocalizedString('impact.analysis.dismiss.existing.modal.text'); command = { "command": "force_start" }; showConfirmationDialog(title, text, command); } else if (!$scope.basicData.hasImpactAnalysis && relationCounters.CIs === 0 && !$scope.basicData.impactedService) { return systemAlertService.modal({ title: i18nService.getLocalizedString('impact.analysis.noCIs.modal.title'), text: i18nService.getLocalizedString('impact.analysis.noCIs.modal.text'), type: 'info', buttons: [ { text: i18nService.getLocalizedString('common.labels.ok'), data: false } ] }); } else { command = { "command": "start" }; initiateImpactAnalysisCall(command); } } }; $scope.$watch('basicData', function () { if ($scope.basicData) { showAlerts(); updateRelations(); $scope.relations = angular.copy(relationModel.cache); } if ($scope.basicData && $scope.basicData.accessMappings && $scope.basicData.accessMappings.impactEditAllowed && !searchModel.disableImpactAnalysis) { var moreDropDownActionItems = configurationModel.get('moreActions.' + $scope.type); $scope.moreDropDownOptions = { 'actions': moreDropDownActionItems, 'registeredCallbacks': $scope.moreDropDownActionsCallbackFuncns }; } }, true); globalMetaDataPromise.then(handleGlobalMetaDataPromise); $scope.$on('$stateChangeStart', function (event, toState, toParams) { if ($scope.dirty) { event.preventDefault(); var modalInstance = systemAlertService.modal({ title: i18nService.getLocalizedString('common.notification.dirty.title'), text: i18nService.getLocalizedString('common.notification.dirty.message'), buttons: [ { text: i18nService.getLocalizedString('common.notification.dirty.button1'), data: { stateName: toState.name, stateParams: toParams } }, { text: i18nService.getLocalizedString('common.notification.dirty.button2') } ] }); modalInstance.result.then(function (data) { if (!_.isEmpty(data)) { $scope.dirty = false; var modalStack = $injector.get('$modalStack'); modalStack.dismissAll(); $state.transitionTo(data.stateName, data.stateParams); } else { // need to undo $window.history.back() by calling forward(), otherwise cancel won't work on second try $window.history.forward(); if ($scope.type === EntityVO.TYPE_SERVICEREQUEST && $scope.isCrossLaunchRequest) { srdModel.launchAIF(true, // createNew true, // historyBackOnCancel $scope, $scope.template.name, $scope.template.templateObject.crossLaunchURL, $scope.basicData.customer.id, $scope.basicData.contact ? $scope.basicData.contact.id : null); } } }); } }); $q.all(promises).then(function (responses) { processPromises(responses); }) .catch(function (e) { systemAlertService.error({ text: e.data.detailMessage || e.data.error || e, clear: false }); throw e; }) .finally(postProcessPromises); function processPromises(responses) { $scope.basicData = responses[0]; $scope.basicData.isFullVersion = $scope.isFullVersion; $scope.metadata = _.findWhere(responses[1], { metadatatype: $scope.type }); $scope.screenLayout = responses[2]; $scope.basicData.type = $scope.type; $scope.basicData.hasImpactAnalysis = false; $scope.isSBEApprovalLoaded = false; $scope.$broadcast(events.TICKET_BASIC_DATA_LOADED); initBasicData(); } function initBasicData() { if ($scope.basicData.type === EntityVO.TYPE_CHANGE || $scope.basicData.type === EntityVO.TYPE_RELEASE) { if ($scope.basicData.isInApproval && $scope.basicData.accessMappings.summaryEditAllowed) { $scope.basicData.accessMappings.statusEditAllowed = true; } } if ($scope.basicData.desc) { $scope.basicData.desc = $scope.basicData.desc.replace(' ', ' '); } var allEntityCategories = $scope.basicData.categorizations; if (!!$scope.basicData.resCategorizations && $scope.basicData.isClosed()) { allEntityCategories = $scope.basicData.categorizations.concat($scope.basicData.resCategorizations); } else if ($scope.basicData.type === EntityVO.TYPE_INCIDENT) { $scope.basicData.categorizations.push(_.find($scope.basicData.resCategorizations, { 'name': 'resolutionProduct' })); $scope.basicData.categorizations.push(_.find($scope.basicData.resCategorizations, { 'name': 'resolution' })); allEntityCategories = $scope.basicData.categorizations; } if (allEntityCategories && $scope.basicData.type !== EntityVO.TYPE_ACTIVITY) { $scope.basicData.allCategories = categoriesService.populateCategories(allEntityCategories, $scope.metadata); $scope.basicData.noCategories = (_.filter($scope.basicData.allCategories, 'valueToShow')).length; } if ($scope.metadata && !$scope.basicData.priority && !_.isEmpty($scope.metadata.priorities)) { $scope.basicData.priority = _.last($scope.metadata.priorities).name; } if ($scope.basicData.type === EntityVO.TYPE_TASK) { $scope.isParentAppEnabled = configurationModel.isServerApplicationEnabled($scope.basicData.parentName); } if ($scope.basicData.type === EntityVO.TYPE_SERVICEREQUEST) { if ($scope.basicData.expectedDate) { $scope.basicData.expectedDate = getTimestamp($scope.basicData.expectedDate, $scope.basicData.expectedTime); } if ($scope.basicData.requiredDate) { $scope.basicData.requiredDate = getTimestamp($scope.basicData.requiredDate, $scope.basicData.requiredTime); } // Display Date and Time based on Time Zone at client side. _.forEach($scope.basicData.questionResponses, function (questionResponse) { if (questionResponse.value && questionResponse.format === 'DATE_TIME') { questionResponse.displayValue = $filter('humanizedAbsoluteDateFormat')(questionResponse.value * 1000); } else if (questionResponse.value && questionResponse.format === 'DATE_ONLY') { questionResponse.displayValue = $filter('dateFormat')(questionResponse.value * 1000); } else if (questionResponse.value && questionResponse.format === 'TIME_ONLY') { questionResponse.displayValue = moment.unix(questionResponse.value).format('LT'); } }); } if ($scope.basicData.type === EntityVO.TYPE_SBEREQUEST) { // Display Date and Time based on Time Zone at client side. _.forEach($scope.basicData.answers, function (questionResponse) { if (questionResponse.value && questionResponse.format === 'DATE_TIME_FIELD') { questionResponse.displayValue = $filter('humanizedAbsoluteDateFormat')(questionResponse.value * 1000); } else if (questionResponse.value && questionResponse.format === 'DATE_FIELD') { questionResponse.displayValue = $filter('dateFormat')(questionResponse.value * 1000); } else if (questionResponse.value && questionResponse.format === 'TIME_FIELD') { questionResponse.displayValue = moment(questionResponse.displayValue, 'hh:mm:ss').format('LT'); } }); } getCollisions(); //get the status of an impact analysis job if (!searchModel.disableImpactAnalysis && $scope.basicData.accessMappings && $scope.basicData.accessMappings.impactEditAllowed) { getImpactAnalysisStatus(); } if ($scope.basicData.brokerVendorName) { ticketModel.getVendorInfo($scope.basicData.displayId, $scope.basicData.type).then(function (response) { $scope.basicData.vendorInfo = _.sortBy(response, 'id'); }); } $scope.$emit(events.TICKET_BASIC_DATA_LOADED, { ticket: $scope.basicData }); } function postProcessPromises() { $scope.state.dataIsLoading = false; if (_.isUndefined($scope.basicData)) { $scope.basicData = {}; } } // TODO: get rid of $scope soup, aha +1 $scope.ticketActions = { assign: function ($event, singleEditMode, activeRole) { var ticket = singleEditMode ? _.cloneDeep($scope.ticket) : $scope.ticket; ticketActionService.assign($event, singleEditMode, ticket, $scope, activeRole); }, assignToMe: function ($event, role, singleEditMode) { var ticket = singleEditMode ? _.cloneDeep($scope.ticket) : $scope.ticket; ticketActionService.assignToMe($event, role, singleEditMode, ticket, $scope); }, share: function () { ticketActionService.share($scope.ticket); }, follow: function () { return ticketActionService.follow($scope.ticket); }, unfollow: function () { return ticketActionService.unfollow($scope.ticket); }, showPrintDialog: function ($event) { ticketActionService.showPrintDialog($event, $scope.ticket, relationCounters, $scope.ticket.feed); }, editStatus: function ($event) { ticketActionService.showEditStatusDialog($scope.basicData, false, false).result.then(function (statusData) { $event.currentTarget.focus(); return ticketModel.refreshStatus($scope.basicData.id, $scope.basicData.type, statusData); //todo: refresh ticket }, function () { $event.currentTarget.focus(); }).then(function () { //the updated target date needs to be broadcasted to the edit header directive $scope.$broadcast(events.PROBLEM_UPDATE_TARGET_DATE_EVENT, $scope.basicData.targetDate); $scope.$broadcast(events.CLOSE_EDIT_MODE_ON_STATUS_CLOSED_FROM_BLADE, $scope.basicData.accessMappings); $scope.$emit(events.TICKET_PROFILE_RESEND_EVENT, { eventName: events.REFRESH_ACTIVITY_FEED }); }); }, editHeader: function (data) { if (data) { var headerData; data.summary = data.summary.replace(/\u00a0/g, ' '); if ([EntityVO.TYPE_INCIDENT, EntityVO.TYPE_PROBLEM, EntityVO.TYPE_KNOWNERROR].indexOf($scope.type) >= 0) { headerData = { summary: data.summary, impact: data.impact.name, urgency: data.urgency.name, priority: data.priority.name }; } else if ($scope.type === EntityVO.TYPE_CHANGE) { headerData = { summary: data.summary }; } else { headerData = { summary: data.summary, priority: data.priority.name }; } if ($scope.type === EntityVO.TYPE_PROBLEM || $scope.type === EntityVO.TYPE_KNOWNERROR) { headerData.targetDate = moment(data.targetDate).valueOf(); } ticketModel.editHeader($scope.basicData.id, $scope.type, headerData).then(function (response) { var refreshSLA = false; if ($scope.basicData.priority !== response.priority) { refreshSLA = true; $scope.$emit(events.TICKET_PROFILE_RESEND_EVENT, { eventName: events.REFRESH_ACTIVITY_FEED }); } if ($scope.basicData.targetDate !== response.targetDate) { refreshSLA = true; } $scope.basicData = _.merge($scope.basicData, response); if (refreshSLA) { ticketModel.refreshSLA($scope.basicData); } $scope.editHeader = false; }); } else { $scope.editHeader = false; } }, editCustomerCard: function (personInfo) { var contact = {}, customer = {}; if (personInfo.length > 0) { var customerInfo = personInfo[0].data; customer = { site: customerInfo.site, phone: customerInfo.phone, loginId: customerInfo.loginId }; } if (personInfo.length > 1) { contact = { phone: personInfo[1].data.phone, loginId: personInfo[1].data.loginId }; } return ticketModel.editCustomerCard($scope.basicData.id, $scope.type, { customer: customer, contact: contact }).then(function (response) { $scope.basicData = _.assign($scope.basicData, response); $scope.basicData.customer.loginId = customer.loginId; $scope.basicData.contact.loginId = contact.loginId; }); }, viewCustomForm: function () { srdModel.launchAIF(false, // createNew false, // historyBackOnCancel $scope, $scope.basicData.requestTemplateTitle, $scope.basicData.crossLaunchURLDisplay); }, confirmAction: function (action) { ticketActionService.confirmAction($scope.ticket, action, $scope).then(function () { $scope.$emit(events.TICKET_PROFILE_RESEND_EVENT, { eventName: events.REFRESH_ACTIVITY_FEED }); ticketActionService.applyAction($scope.ticket, action, $scope); }); }, applyAction: function (action) { ticketActionService.applyAction($scope.ticket, action, $scope); }, showApprovalList: function () { if (type === EntityVO.TYPE_SERVICEREQUEST || type === EntityVO.TYPE_SBEREQUEST) { _.forEach($scope.basicData.approvalSummaries, function (item) { item.status.name = item.status.value ? item.status.value.split(' ').join('_').toLowerCase() : ''; }); approvalService.showApproversDialog($scope.basicData.approvalList, $scope.basicData); } }, editPlans: function () { //handleToggleEditMode(null,elemId); return ticketActionService.showPlansEditDialog($scope.metadata, $scope.basicData); }, showAttachmentPreviewer: function (plan) { ticketModel.showAttachmentPreviewerPopup(plan); } }; $scope.toggleFollowingFlag = function () { var toggleFollowingFunction = $scope.basicData.following ? $scope.ticketActions.unfollow : $scope.ticketActions.follow; toggleFollowingFunction($scope.basicData).then(function () { $scope.basicData.following = !$scope.basicData.following; }); }; $scope.enableHeaderEdit = function () { $scope.editHeader = true; }; $scope.disableDuplicateOfEdit = function () { $scope.basicData.status.value = 'Pending'; $scope.basicData.accessMappings.detailsEditAllowed = false; $scope.basicData.accessMappings.statusEditAllowed = false; $scope.basicData.accessMappings.relationsEditAllowed = false; }; /** * Returns true if panel has custom fields * * @param panelId * @return {boolean} */ $scope.hasCustomFields = function (panelId) { var panel = screenConfigurationModel.getPanelById(panelId); return panel && panel.hasCustomFields(); }; $scope.editDisabledFor = function (sectionId) { return $scope.activeEditableSectionId && $scope.activeEditableSectionId !== sectionId; }; $scope.editDatesView = function () { $state.go('changeEditDates', { id: $scope.basicData.id }); }; $scope.$on(events.DISABLE_PARENT_EDITMODE, function (event, data) { $scope.$broadcast(events.DISABLE_EDITPARENT, data); }); $scope.$on(events.DISABLE_EDITMODE, function (event, childEditMode) { $scope.$broadcast(events.DISABLE_EDIT, childEditMode); }); $scope.$on(events.DISABLE_CHILD_EDITMODE, function (event, childEditMode) { $scope.$broadcast(events.DISABLE_EDITCHILD, childEditMode); }); $scope.clearCategories = function (selectedServiceType) { $scope.$broadcast(events.CLEAR_ALL_CATEGORIES, selectedServiceType); }; /** * Handler for toggling edit mode * * @param event * @param editableContentSectionId */ function handleToggleEditMode(event, editableContentSectionId) { $scope.dirty = true; $scope.activeEditableSectionId = editableContentSectionId; if (editableContentSectionId === 'ticket-header') { $scope.enableHeaderEdit(); } var categoriesList = objectValueMapperService.getFieldsByType('category'); _.forEach(categoriesList, function (categoryField) { if (categoryField.readOnlyCondition) { categoryField.isReadOnly = expressionEvaluatorService.evaluate(categoryField.readOnlyCondition); return; } categoryField.isReadOnly = categoryField.readOnly; }); } function handleEditComplete() { $scope.dirty = false; $scope.activeEditableSectionId = null; if (type === EntityVO.TYPE_CHANGE) { getCollisions(); } } //Fix for SW00537558 to handle assignment changes for all WO,PBI, PKE and Task ticket //types as we do not use the widgets here.Should be removed when we update these ticket //types to use the assignment widgets in later versions of 2.0 function handleAssignmentComplete(event, data) { if (data.type !== EntityVO.TYPE_CHANGE && data.type !== EntityVO.TYPE_INCIDENT) { $scope.basicData.assignee = data.assignee; $scope.basicData.supportGroup = data.supportGroup; $scope.basicData.manager = data.manager; $scope.basicData.managerGroup = data.managerGroup; $scope.basicData.coordinator = data.coordinator; $scope.basicData.coordinatorGroup = data.coordinatorGroup; } } function updateRelationCounters() { var relatedCIs; relationCounters.tasks = relationService.getRelatedTasks($scope.relations[id]).length; relationCounters.linkedItems = relationService.getRelatedLinkedItems($scope.relations[id], $scope.basicData, showAffectedServiceRelation).length; relatedCIs = relationService.getRelatedCIs($scope.relations[id]); relationCounters.CIs = _.chain(relatedCIs).reject(function (linkedItem) { var context = $scope.basicData; return !showAffectedServiceRelation && context && _.contains([context.causalCI && context.causalCI.reconciliationId, context.impactedService && context.impactedService.reconciliationId], linkedItem.id) && linkedItem.type === EntityVO.TYPE_ASSET; }).value().length; } $scope.calculateRisk = function (riskLevelSelectionMode) { if (riskLevelSelectionMode === 'auto') { $scope.state.risklevelLoading = true; ticketModel.calculateRisk($scope.basicData.id).then(function (response) { if (response.riskLevel === null) { $scope.basicData.isCalculateRiskNull = true; } console.log(response.riskLevel); var index = _.findIndex($scope.metadata.riskLevels, { name: response.riskLevel }); if (index !== -1) { $scope.basicData.titleRiskLevelCls = 'risk-level-' + (index + 1); $scope.basicData.riskLevel = _.find($scope.metadata.riskLevels, { name: response.riskLevel }); } else if (!$scope.basicData.riskLevel) { $scope.basicData.titleRiskLevelCls = 'risk-level-1'; $scope.basicData.riskLevel = $scope.metadata.riskLevels[0]; } $scope.state.risklevelLoading = false; }); } }; $scope.riskLevel = function () { return $scope.basicData.riskLevel ? $scope.basicData.riskLevel.label : ''; }; /** * Added by ygowtham on 6/17/2015 for I1 - G1.3 * * Display Alerts Carousel based in the presence of alerts, approvals and collision * Calculate number of alerts to be passed to the Alerts Carousel Directive */ function showAlerts() { $scope.alertDetails = { alertItems: [] }; var alertHeading = []; if (type === EntityVO.TYPE_CHANGE || type === EntityVO.TYPE_RELEASE) { //TODO: Change the hasCollisions to $scope.basicData.hasCollisions or similar based on what the back end returns if ($scope.basicData.isInApproval || hasCollisions || $scope.basicData.hasImpactAnalysis) { $scope.hasAlerts = true; if ($scope.basicData.isInApproval) { $scope.alertDetails.alertItems.push("approval_banner"); alertHeading.push(i18nService.getLocalizedString('alert.heading.approvalBanner')); } if (hasCollisions && !searchModel.disableCollisionManagement) { $scope.alertDetails.alertItems.push("collision_banner"); alertHeading.push(i18nService.getLocalizedString('alert.heading.collisions')); } if ($scope.basicData.hasImpactAnalysis && !searchModel.disableImpactAnalysis && $scope.basicData.accessMappings && $scope.basicData.accessMappings.impactEditAllowed) { $scope.alertDetails.alertItems.push("impact_analysis_banner"); alertHeading.push(i18nService.getLocalizedString('alert.heading.impactAnalysis')); } } else { $scope.hasAlerts = false; } $scope.alertDetails.alertHeading = alertHeading.join(', '); } if (type === EntityVO.TYPE_SBEREQUEST && $scope.basicData.isInApproval && !$scope.isSBEApprovalLoaded) { $scope.isSBEApprovalLoaded = true; approvalService.getListOfApprovers({ id: $scope.basicData.id, type: EntityVO.TYPE_SBEREQUEST }).then(function (result) { if (result) { $scope.basicData.approvalSummaries = result.approvalSummaries; $scope.basicData.approvalList = result.approvalList; $scope.basicData.isUserApprovalPending = result.isUserApprovalPending; $scope.basicData.groupedSummary = result.groupedSummary; } }); } } function getCollisions() { if ($scope.basicData.type === EntityVO.TYPE_CHANGE) { collisionModel.getListOfCollisionsById($scope.basicData, false) .then(function (collisionSummary) { if (collisionSummary.totalUnaddressedCount > 0) { $scope.collisions = collisionSummary; hasCollisions = true; } else { hasCollisions = false; } }) .finally(function () { showAlerts(); }); } } function handleApproveUpdatingComplete() { $scope.state.dataIsLoading = true; ticketModel.getTicketDetails($scope.basicData.id, $scope.basicData.type).finally(function () { $scope.state.dataIsLoading = false; }).then(function (ticketDetails) { $scope.basicData.isInApproval = ticketDetails.isInApproval; showAlerts(); return ticketModel.refreshStatus($scope.basicData.id, $scope.basicData.type, { status: ticketDetails.status.value, updatedTickets: [ticketDetails] }); }); } function fetchResolutionCategories(generalCategories) { var resProductCategoryData, resOperationCategoryData, categorizations = [], resCategoryCheck, resProductCategoryCheck; _.forEach(generalCategories, function (category) { if (category.name === EntityVO.CATEGORY_OPERATIONAL) { resOperationCategoryData = {}; resOperationCategoryData.name = EntityVO.CATEGORY_RESOLUTION; if (category.tiers.operationCategoryTier1) { resOperationCategoryData.tiers = { resOperationCategoryTier1: '', resOperationCategoryTier2: '', resOperationCategoryTier3: '' }; resOperationCategoryData.tiers.resOperationCategoryTier1 = category.tiers.operationCategoryTier1; if (category.tiers.operationCategoryTier2) { resOperationCategoryData.tiers.resOperationCategoryTier2 = category.tiers.operationCategoryTier2; if (category.tiers.operationCategoryTier3) { resOperationCategoryData.tiers.resOperationCategoryTier3 = category.tiers.operationCategoryTier3; } } } } else if (category.name === EntityVO.CATEGORY_PRODUCT) { resProductCategoryData = {}; resProductCategoryData.name = EntityVO.CATEGORY_RESOLUTION_PRODUCT; if (category.tiers.productCategoryTier1) { resProductCategoryData.tiers = { resProductCategoryTier1: '', resProductCategoryTier2: '', resProductCategoryTier3: '', resProductName: '', resProductModelVersion: '' }; resProductCategoryData.tiers.resProductCategoryTier1 = category.tiers.productCategoryTier1; if (category.tiers.productCategoryTier2) { resProductCategoryData.tiers.resProductCategoryTier2 = category.tiers.productCategoryTier2; if (category.tiers.productCategoryTier3) { resProductCategoryData.tiers.resProductCategoryTier3 = category.tiers.productCategoryTier3; if (category.tiers.productName) { resProductCategoryData.tiers.resProductName = category.tiers.productName; } if (category.tiers.productModelVersion) { resProductCategoryData.tiers.resProductModelVersion = category.tiers.productModelVersion; } } } } } }); var params = { entityType: $scope.basicData.type, criteria: { depends: { id: $scope.basicData.id }, company: $scope.basicData.company, serviceType: $scope.basicData.serviceType } }; if (resOperationCategoryData && resOperationCategoryData.tiers && resOperationCategoryData.tiers.resOperationCategoryTier1) { var resOperationParams = _.cloneDeep(params), operationCategoryTiers; resOperationParams.categoryType = EntityVO.CATEGORY_RESOLUTION; _.merge(resOperationParams.criteria.depends, resOperationCategoryData.tiers); _.forEach($scope.basicData.allCategories, function (category) { if (category.name === EntityVO.CATEGORY_OPERATIONAL) { operationCategoryTiers = categoriesService.collectTiersValues(category.listOfTiers); } }); if (operationCategoryTiers && operationCategoryTiers.operationCategoryTier1) { _.merge(resOperationParams.criteria.depends, operationCategoryTiers); } resCategoryCheck = categoriesService.checkCategoryTierData(resOperationParams); resCategoryCheck.then(function (response) { if (response === true) { categorizations.push(resOperationCategoryData); } }); } if (resProductCategoryData && resProductCategoryData.tiers && resProductCategoryData.tiers.resProductCategoryTier1) { var resProductParams = _.cloneDeep(params); resProductParams.categoryType = EntityVO.CATEGORY_RESOLUTION_PRODUCT; _.merge(resProductParams.criteria.depends, resProductCategoryData.tiers); resProductCategoryCheck = categoriesService.checkCategoryTierData(resProductParams); resProductCategoryCheck.then(function (response) { if (response === true) { categorizations.push(resProductCategoryData); } }); } return $q.all([resCategoryCheck, resProductCategoryCheck]).then(function () { return categorizations; }); } function resolveTicketFromRs(event, resourceItem) { //todo: on UI introduce some transparent spinner to indicate status updating happening var statusData = { status: 'Resolved', statusReason: 'No Further Action Required', resNote: resourceItem.title || resourceItem.desc }; if (resourceItem.updateCategories) { fetchResolutionCategories(resourceItem.categorizations).then(function (categorizations) { if (categorizations.length > 0) { statusData.categorizations = categorizations; } ticketModel.update(id, type, statusData).then(function (response) { if (response && response.status !== 500) { $scope.$broadcast(events.AFTER_SAVED_CHANGES, $scope.basicData); } return; }); }); } else { ticketModel.update(id, type, statusData).then(function (response) { if (response && response.status !== 500) { $scope.$broadcast(events.AFTER_SAVED_CHANGES, $scope.basicData); } return; }); } } function markTicketAsDuplicateFromRs() { //todo: on UI introduce some transparent spinner to indicate status updating happening state.dataIsLoading = true; ticketModel.getTicket($scope.basicData.id, $scope.basicData.type, true).then(function (responce) { $scope.basicData.status = responce.status; $scope.basicData.accessMappings = responce.accessMappings; }).finally(function () { state.dataIsLoading = false; }); } function getImpactAnalysisStatus() { ticketModel.getImpactAnalysisStatus($scope.basicData.id, $scope.basicData.type).then(function (response) { if (response.status && response.status.value) { $scope.basicData.hasImpactAnalysis = true; if (response.status.value === 'Relationship Assessment Completed') { $scope.basicData.impactAnalysisStatus = 'Completed'; } else if (response.status.value === 'Analysis Completed' || response.status.value === 'Analysis In Progress' || response.status.value === 'Relationship Assessment In Progress') { $scope.basicData.impactAnalysisStatus = 'Pending'; } else { $scope.basicData.impactAnalysisStatus = 'Unknown'; } } if ($scope.basicData.hasImpactAnalysis) { showAlerts(); } }); } function getTimestamp(date, time) { time = time ? moment(time) : moment(date); return moment(date).set('hours', time.get('hours')).set('minutes', time.get('minutes')).format('X') * 1000; } function handleShownAssignmentBlade($event, data) { var isAssignToMeAction = false, originalEvent = data.originalEvent, doNotSaveSelection = !data.saveSelection; if (data) { isAssignToMeAction = !!data.assignToMe; if (data.role) { var assigneeRole = data.role; if (assigneeRole === 'manager') { assigneeRole = $scope.type + assigneeRole; } else if (assigneeRole === 'assignee') { if ([EntityVO.TYPE_CHANGE, EntityVO.TYPE_PROBLEM, EntityVO.TYPE_RELEASE].indexOf($scope.type) !== -1) { assigneeRole = $scope.type + 'coordinator'; } else { assigneeRole = 'ticketassignee'; } } } if (isAssignToMeAction) { $scope.ticketActions.assignToMe(originalEvent, assigneeRole, doNotSaveSelection); } else { $scope.ticketActions.assign(originalEvent, doNotSaveSelection, assigneeRole); } } else { $log.warn('Could not open assignment blade. Required Event data is missing. '); return; } } function handleAfterSavedChanges(e, updatedTicket) { $scope.state.dataIsLoading = true; $scope.basicData = updatedTicket; $scope.$emit(events.TICKET_PROFILE_RESEND_EVENT, { eventName: events.REFRESH_ACTIVITY_FEED }); relationModel.refreshRelations(id, type).then(function (response) { $scope.relations = angular.copy(relationModel.cache); }); initBasicData(); $timeout(function () { // This timeout is to make sure that dataIsLoading flag change will affect editable-layout-section directive // and it will result in its re-initialization with all fields and widgets inside re-init as well // Without timeout, flag is being changed in one digest, which does not affect editable-layout-section directive $scope.state.dataIsLoading = false; }); } function updateRelations() { updateRelationCounters(); if ($scope.type === EntityVO.TYPE_PROBLEM && $scope.relations && $scope.basicData) { _.each($scope.relations[$scope.basicData.id], function (relation) { if (relation.type === EntityVO.TYPE_KNOWNERROR && relation.relationshipType === RelationItemVO.TYPE_INITIATES) { $scope.basicData.hasInitiatesRelation = true; } }); } //if there are any CI relations, enable 'Initiate Impact Analysis' in the More actions drop down if ($scope.basicData && $scope.basicData.accessMappings && $scope.basicData.accessMappings.impactEditAllowed && !searchModel.disableImpactAnalysis) { var moreDropDownActionItems = configurationModel.get('moreActions.' + $scope.type); $scope.moreDropDownOptions = { 'actions': moreDropDownActionItems, 'registeredCallbacks': $scope.moreDropDownActionsCallbackFuncns }; } } $scope.state = state; $scope.relationCounters = relationCounters; $scope.$on(events.AFFECTED_SERVICE_UPDATE_SAVED, function () { $scope.$broadcast(events.REFRESH_RELATED_ITEM_LIST, { event: events.AFFECTED_SERVICE_UPDATE_SAVED }); }); /** * On refresh ticket from title-bar */ $scope.$on(events.REFRESH_TICKET_FROM_TITLE_BAR, function () { $scope.refreshTicket(); }); $scope.$on(events.CHANGE_TO_EDIT_MODE, function (event, editMode) { $scope.$broadcast(events.CHANGE_TO_EDIT_MODE, editMode); }); $scope.$on(events.TOGGLE_EDIT_MODE, handleToggleEditMode); $scope.$on(events.EDIT_COMPLETE, handleEditComplete); $scope.$on(events.SHOW_APPROVERS, $scope.ticketActions.showApprovalList); $scope.$on(events.APPROVE_UPDATING_COMPLETE, handleApproveUpdatingComplete); $scope.$on(events.RESOLVE_TICKET_FROM_RS, resolveTicketFromRs); $scope.$on(events.MARK_AS_DUPLICATE_OF_FROM_RS, markTicketAsDuplicateFromRs); $scope.$on(events.LINKED_CI_SAVE_COMPLETE, handleEditComplete); $scope.$on(events.SHOW_ASSIGN_TICKET_BLADE, handleShownAssignmentBlade); $scope.$on(events.AFTER_SAVED_CHANGES, handleAfterSavedChanges); $scope.$on(events.TICKET_ASSIGNEES_UPDATED_FROM_BLADE, handleAssignmentComplete); }]); })();