"use strict"; (function () { 'use strict'; angular.module('ticketModule').controller('LinkController', ['$scope', '$modalInstance', 'linkParams', 'configurationModel', 'searchService', 'ticketModel', 'relationModel', '$q', 'metadataModel', 'searchModel', 'assetService', 'authService', 'roles', 'systemAlertService', 'i18nService', 'events', '$filter', function ($scope, $modalInstance, linkParams, configurationModel, searchService, ticketModel, relationModel, $q, metadataModel, searchModel, assetService, authService, roles, systemAlertService, i18nService, events, $filter) { var type = linkParams.selectedItems[0].ticketType ? linkParams.selectedItems[0].ticketType : linkParams.selectedItems[0].type, isSingle = linkParams.selectedItems.length === 1, linkConfig = configurationModel.get('link'), selected = { linkOption: {} }, state = { searching: false, processing: false, isDirty: false }, deselectAllEntities = function () { _.forEach(selected.entities, function (entity) { entity.isSelected = false; }); selected.entities = []; }, globalMetadata; $scope.state = state; $scope.selected = selected; $scope.linkOptions = _.sortBy(getLinkOptions(type), 'type'); $scope.availableEntities = null; $scope.selected.advancedFilters = []; $scope.searchConfig = angular.copy(configurationModel.get('outage.searchFilter')); $scope.ticketType = type; var filterDictionary = _.indexBy($scope.searchConfig, 'label'); //Sorting array of relation types _.each($scope.linkOptions, function (item) { item.relations = item.relations ? item.relations.sort() : []; }); $q.all([metadataModel.getMetadataByType(EntityVO.TYPE_GLOBAL), metadataModel.getMetadataByType(EntityVO.TYPE_OUTAGE)]).then(function (metadata) { globalMetadata = metadata[0]; var outageMetadata = metadata[1]; if (filterDictionary.unavailabilityStatus.options.length === 0) { _.forEach(outageMetadata.statuses, function (status) { var active = false; //Defect #SW00490745 fix if ((linkParams.selectedItems[0].timing === 'Latent' && status.name === 'Restored') || (linkParams.selectedItems[0].timing !== 'Latent' && status.name === 'Scheduled')) { active = true; } filterDictionary.unavailabilityStatus.options.push({ name: status.label, type: 'dynamic', criteria: { name: 'unavailabilityStatus', value: [status.name] }, active: active }); if (active === true) { $scope.selected.advancedFilters.push({ name: status.label, type: 'dynamic', criteria: { name: 'unavailabilityStatus', value: [status.name] }, active: active }); } }); } if (filterDictionary.unavailabilityType.options.length === 0) { _.forEach(outageMetadata.types, function (type) { filterDictionary.unavailabilityType.options.push({ name: type.label, type: 'dynamic', criteria: { name: 'unavailabilityType', value: [type.name] } }); }); } if (filterDictionary.ciName.options.length !== 0) { _.forEach(filterDictionary.ciName.options, function (type) { if (type.active === true) { $scope.selected.advancedFilters.push({ name: type.label, type: 'constant', criteria: { name: 'relatedCI', value: [type.name] }, active: type.active }); } }); } }); if (type === EntityVO.TYPE_CHANGE) { //Custom functionality for advanced search of Outages, when All related CIs and $scope.$watch(function () { var relatedCIFilter = _.findWhere($scope.selected.advancedFilters, { criteria: { name: 'relatedCI' } }), ciNamesFilter = _.findWhere($scope.selected.advancedFilters, { criteria: { name: 'name' } }); return { relatedCI: relatedCIFilter, keywords: ciNamesFilter }; }, function (newVal, oldVal) { var ciNameFilter, oldKeywords = oldVal.keywords, newKeywords = newVal.keywords, relatedCiOld = oldVal.relatedCI, relatedCiNew = newVal.relatedCI; if (newKeywords && !oldKeywords) { ciNameFilter = _.findWhere($scope.searchConfig, { name: 'name' }) || {}; var allRelatedCiFilter = _.findWhere(ciNameFilter.options, { name: 'relatedCI' }) || {}; allRelatedCiFilter.active = false; var filterIndex = $scope.selected.advancedFilters.indexOf(relatedCiNew); $scope.selected.advancedFilters.splice(filterIndex, 1); } else if (relatedCiNew && !relatedCiOld) { ciNameFilter = _.findWhere($scope.searchConfig, { name: 'name' }) || {}; _.each(ciNameFilter.options, function (filter) { if (filter.criteria && filter.criteria.name === 'name') { filter.active = false; } }); $scope.selected.advancedFilters = _.reject($scope.selected.advancedFilters, { criteria: { name: 'name' } }); } }, true); $scope.searchCIsByKeyword = function (searchText) { return assetService.getListOfAssets(searchText).then(function (result) { var ciList = []; try { ciList = result[0].items[0].objects; } catch (e) { console.log(e); } return ciList; }); }; } $scope.selectLinkOption = function (linkOption) { state.isDirty = true; selected.linkOption = linkOption; selected.relation = selected.linkOption.relations.length === 1 ? linkOption.relations[0] : ''; selected.searchText = ''; selected.entities = []; $scope.availableEntities = null; //Use-case when suggested entities should be shown, before user start searching if ([EntityVO.TYPE_OUTAGE].indexOf(linkOption.type) >= 0 && type === EntityVO.TYPE_CHANGE) { state.searching = true; searchModel.getFilteredSuggestedOutagesList(ticket) .then(function (suggestedOutages) { if (suggestedOutages && suggestedOutages.length > 0) { $scope.availableEntities = suggestedOutages; state.showSuggestedItemsTooltip = true; } //$scope.selected.advancedFilters.push(filterDictionary.ciName.options[0]); }) .finally(function () { state.searching = false; }); } }; $scope.searchEntities = function () { var params = {}, jsonParams = {}; // if there is no searchText, the request fails on the backend // with an error 'The Search Text field cannot be null.' if (!selected.searchText) { return false; } if (state.showSuggestedItemsTooltip) { state.showSuggestedItemsTooltip = false; } state.searching = true; selected.entities = []; if (selected.linkOption.type === EntityVO.TYPE_OUTAGE) { if (selected.searchText) { params.searchText = selected.searchText; } _.each($scope.selected.advancedFilters, function (filterItem) { if (filterItem.criteria.name === 'scheduledStartDates') { var startDate = filterItem.criteria.value ? filterItem.criteria.value.startDate : eval(filterItem.defaultValues.start), endDate = filterItem.criteria.value ? filterItem.criteria.value.endDate : eval(filterItem.defaultValues.end); params.scheduledDate = [{ start: startDate, end: endDate }]; } else if (filterItem.criteria.name === 'unavailabilityStatus') { !params.unavailabilityStatus ? params.unavailabilityStatus = [filterItem.criteria.value[0]] : params.unavailabilityStatus.push(filterItem.criteria.value[0]); } else if (filterItem.criteria.name === 'unavailabilityType') { !params.unavailabilityType ? params.unavailabilityType = [filterItem.criteria.value[0]] : params.unavailabilityType.push(filterItem.criteria.value[0]); } else if (filterItem.criteria.name === 'relatedCI') { params.relatedCI = true; } else if (filterItem.criteria.name === 'name') { !params.ciNames ? params.ciNames = [filterItem.criteria.value[0]] : params.ciNames.push(filterItem.criteria.value[0]); } }); return searchModel.getFilteredOutagesList(params, ticket) .then(function (searchResults) { $scope.availableEntities = searchResults; }) .finally(function () { state.searching = false; }); } else { params = { search_text: selected.searchText, types: selected.linkOption.type, chunk_index: 0, chunk_size: 50 }; if (selected.linkOption.type === EntityVO.TYPE_ASSET) { params.chunk_size = globalMetadata.configurationParameters && globalMetadata.configurationParameters.assetSearchQueryLimit ? globalMetadata.configurationParameters.assetSearchQueryLimit : 4; } jsonParams = { allowSpecialCharacters: true }; if (type === EntityVO.TYPE_KNOWLEDGE && linkParams.isDraft) { //To show retired articles while searching for related items. params.suggest_search = true; } } function postSearch(data) { var searchResults = data.items.length > 0 ? data.items[0].results : []; if (isSingle && type !== EntityVO.TYPE_ASSET && type !== EntityVO.TYPE_KNOWLEDGE) { if (selected.linkOption.type === EntityVO.TYPE_ASSET) { //remove asset that is impacted service if (ticket.impactedService && ticket.impactedService.reconciliationId) { searchResults = _.reject(searchResults, { id: ticket.impactedService.reconciliationId }); } //remove asset that is casualCI if (ticket.causalCI && ticket.causalCI.reconciliationId) { searchResults = _.reject(searchResults, { id: ticket.causalCI.reconciliationId }); } } else { //remove current item from search results searchResults = _.reject(searchResults, { id: linkParams.selectedItems[0].id }); //remove already related items from search results //Defect fix: SW00523402 // _.forEach(ticket.relations, function (relatedItem) { // searchResults = _.reject(searchResults, { id: relatedItem.id }); // }); } } $scope.availableEntities = searchResults; } var promarr = [searchService.getGlobalSearchResults(params, jsonParams)]; if (!metadataModel.cache[selected.linkOption.type]) { promarr.push(metadataModel.getMetadataByType(selected.linkOption.type)); } return $q.all(promarr).then(function (data) { postSearch(data[0]); }).finally(function () { state.searching = false; }); }; $scope.selectEntity = function (entity) { if (entity.isSelected) { if (selected.relation === RelationItemVO.TYPE_DUPLICATEOF && selected.entities.length) { deselectAllEntities(); } if (entity.type === EntityVO.TYPE_OUTAGE) { var relatedAsset = _.findWhere(ticket.relations, { id: entity.affectedAsset.reconciliationId }); if (!relatedAsset) { entity.affectedAsset.isRelatedToCR = true; } } selected.entities.push(entity); } else { if (entity.type === EntityVO.TYPE_OUTAGE && entity.affectedAsset.isRelatedToCR) { entity.affectedAsset.isRelatedToCR = false; } _.remove(selected.entities, { id: entity.id }); } }; $scope.selectRelation = function (relation) { if (relation === RelationItemVO.TYPE_DUPLICATEOF && selected.entities.length && isSingle) { //only 1 can be marked duplicate so deselect all and keep only one selected _.forEach(selected.entities, function (entity) { entity.isSelected = false; }); _.last(selected.entities).isSelected = true; _.remove(selected.entities, { isSelected: false }); } if (relation === RelationItemVO.TYPE_ORIGINALOF) { _.forEach(selected.entities, function (entity) { if (!entity.additionalInformation.accessMappings.duplicateActionAllowed) { entity.isSelected = false; } }); } selected.relation = relation; }; $scope.isEntityDisabled = function (entity) { return (selected.relation === RelationItemVO.TYPE_ORIGINALOF && !entity.additionalInformation.accessMappings.duplicateActionAllowed); }; $scope.link = function () { var actionItems = _.map(linkParams.selectedItems, function (item) { var actionObj = {}; if (type === EntityVO.TYPE_ASSET) { actionObj = { uuid: item.reconciliationId, type: item.ticketType }; } else { actionObj = { uuid: item.id, type: item.type }; } return actionObj; }), alreadyRelatedItems = { length: 0 }, relateItems = _.map(selected.entities, function (entity) { var matchRelatedItems, relatedObj = { id: entity.id, relationshipType: selected.relation, tag: RelationItemVO.TAG_LINKEDITEM, type: selected.linkOption.type, desc: entity.title }; if (entity.displayId) { relatedObj.displayId = entity.displayId; } if (linkParams.selectedItems.length === 1 && linkParams.selectedItems[0].displayId) { relatedObj.parentDisplayId = linkParams.selectedItems[0].displayId; } matchRelatedItems = _.find(relationModel.cache && relationModel.cache[actionItems[0] && actionItems[0].uuid], function (item) { if (item.id === entity.id && item.relationshipType === selected.relation) { return item; } }); if (matchRelatedItems) { alreadyRelatedItems[entity.id] = matchRelatedItems; alreadyRelatedItems.length++; } else { return relatedObj; } }), linkFn = linkParams.isDraft ? $q.when : relationModel.bulkAddRelation; relateItems = _.without(relateItems, undefined); if (alreadyRelatedItems.length > 0) { systemAlertService.warning({ text: $filter('i18n')('ticket.notification.alreadyExist.message', alreadyRelatedItems.length), hide: 10000 }); } if (relateItems.length) { state.processing = true; linkFn(actionItems, relateItems).then(function () { var linkedItems = _.map(selected.entities, function (entity, idx) { var relation = relateItems[idx]; if (relation) { if (entity.type === EntityVO.TYPE_ASSET) { relation.realObject = { assignee: entity.additionalInformation.assignee, priority: entity.additionalInformation.priority, status: entity.additionalInformation.status, assetType: entity.additionalInformation.assetType, name: entity.additionalInformation.name, manufacturer: entity.additionalInformation.manufacturer, model: entity.additionalInformation.product.model, reconciliationId: entity.additionalInformation.reconciliationId, classId: entity.additionalInformation.classId, title: entity.title }; relation.displayId = entity.displayId || ''; } else { relation.realObject = entity; relation.displayId = entity.displayId || ''; } return new RelationItemVO().build(relation); } }); linkedItems = _.without(linkedItems, undefined); $modalInstance.close(linkedItems); $scope.$parent.$broadcast(events.RELATIONS_UPDATE_COMPLETE); state.processing = false; }).catch(function (response) { systemAlertService.error({ text: response.data.results.error, clear: false }); $modalInstance.dismiss(); }); } }; if (isSingle && type !== EntityVO.TYPE_ASSET && type !== EntityVO.TYPE_KNOWLEDGE) { var id = linkParams.selectedItems[0].id, ticket = {}; if (linkParams.isDraft) { ticket = ticketModel.cache[id]; ticket.relations = relationModel.cache[id]; } else { state.processing = true; $q.all([ticketModel.getTicket(id, type), relationModel.getRelations(id, type)]).then(function (result) { ticket = angular.copy(result[0]); ticket.relations = result[1]; if (type === EntityVO.TYPE_INCIDENT) { //INFO: SW00531355 if (_.find(ticket.relations, { relationshipType: RelationItemVO.TYPE_ORIGINALOF }).relationshipType) { //if item is already a original of other incident var incidentToIncidentLinkOption = _.find($scope.linkOptions, { type: type }); incidentToIncidentLinkOption.relations = _.without(incidentToIncidentLinkOption.relations, RelationItemVO.TYPE_DUPLICATEOF); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_SERVICEREQUEST)) { //if srm is not installed $scope.linkOptions = _.reject($scope.linkOptions, { type: EntityVO.TYPE_WORKORDER }); } } }).finally(function () { state.processing = false; }); } } if ($scope.linkOptions.length === 1) { $scope.selectLinkOption($scope.linkOptions[0]); } function getLinkOptions(type) { var options = linkConfig[type]; if (type === EntityVO.TYPE_CHANGE && !linkParams.linkFromTicketConsole) { options = _.reject(options, { type: EntityVO.TYPE_ASSET }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_ASSET)) { options = _.reject(options, { type: EntityVO.TYPE_ASSET }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_WORKORDER) || !authService.isAuthorized(roles.ITSM_AGENT_ROLE)) { options = _.reject(options, { type: EntityVO.TYPE_WORKORDER }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_CHANGE) || !authService.isAuthorized(roles.ITSM_CHANGE_USER_ROLE)) { options = _.reject(options, { type: EntityVO.TYPE_CHANGE }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_RELEASE) || !authService.isAuthorized(roles.ITSM_RELEASE_USER_ROLE)) { options = _.reject(options, { type: EntityVO.TYPE_RELEASE }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_INCIDENT) || !authService.isAuthorized(roles.ITSM_AGENT_ROLE)) { options = _.reject(options, { type: EntityVO.TYPE_INCIDENT }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_PROBLEM) || !authService.isAuthorized(roles.ITSM_PROBLEM_USER_ROLE)) { options = _.reject(options, { type: EntityVO.TYPE_PROBLEM }); } if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_KNOWNERROR) || !authService.isAuthorized(roles.ITSM_PROBLEM_USER_ROLE)) { options = _.reject(options, { type: EntityVO.TYPE_KNOWNERROR }); } return options; } $scope.close = function () { if (state.isDirty) { var modalInstance = systemAlertService.modal({ title: i18nService.getLocalizedString('common.notification.dirty.title'), text: i18nService.getLocalizedString('common.notification.dirty.message'), buttons: [ { text: i18nService.getLocalizedString('common.labels.yes'), data: true }, { text: i18nService.getLocalizedString('common.labels.no'), data: false } ] }); modalInstance.result.then(function (data) { if (data) { $modalInstance.dismiss(); } }); } else { $modalInstance.dismiss(); } }; function handleModalBackdropClick() { $scope.close(); } $scope.$on(events.MODAL_BACKDROP_CLICK, handleModalBackdropClick); } ]); })();