498 lines
28 KiB
JavaScript
498 lines
28 KiB
JavaScript
"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, cssClass;
|
|
$scope.state = state;
|
|
$scope.selected = selected;
|
|
$scope.linkOptions = angular.copy(_.sortBy(getLinkOptions(type), 'type'));
|
|
$scope.availableEntities = null;
|
|
$scope.selected.advancedFilters = [];
|
|
$scope.searchConfig = angular.copy(configurationModel.get('outage.searchFilter'));
|
|
$scope.ticketType = type;
|
|
var filterDictionary = _.keyBy($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 = _.find($scope.selected.advancedFilters, { criteria: { name: 'relatedCI' } }), ciNamesFilter = _.find($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 = _.find($scope.searchConfig, { name: 'name' }) || {};
|
|
var allRelatedCiFilter = _.find(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 = _.find($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.iconClass = function (option, type) {
|
|
if (option.serviceType === "Security Incident") {
|
|
cssClass = 'icon-security-incident';
|
|
}
|
|
else {
|
|
cssClass = 'icon-' + type;
|
|
}
|
|
return cssClass;
|
|
};
|
|
$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, endDate;
|
|
if (filterItem.criteria.value) {
|
|
if (filterItem.criteria.value.startDate) {
|
|
startDate = filterItem.criteria.value.startDate;
|
|
}
|
|
else if (filterItem.criteria.value.length && filterItem.criteria.value[0] && filterItem.criteria.value[0].start) {
|
|
startDate = filterItem.criteria.value[0].start;
|
|
}
|
|
if (filterItem.criteria.value.endDate) {
|
|
endDate = filterItem.criteria.value.endDate;
|
|
}
|
|
else if (filterItem.criteria.value.length && filterItem.criteria.value[0] && filterItem.criteria.value[0].end) {
|
|
endDate = filterItem.criteria.value[0].end;
|
|
}
|
|
}
|
|
else {
|
|
startDate = $scope.$eval(filterItem.defaultValues.start, { moment: moment });
|
|
endDate = $scope.$eval(filterItem.defaultValues.end, { moment: moment });
|
|
}
|
|
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 });
|
|
}
|
|
}
|
|
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 = _.find(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.title && entity.type === EntityVO.TYPE_OUTAGE) {
|
|
relatedObj.desc = entity.desc;
|
|
}
|
|
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);
|
|
if (configurationModel.showARMessageOnGetEntry && actionItems.length && selected.entities
|
|
&& selected.entities.length && selected.entities[0].type === EntityVO.TYPE_ASSET) {
|
|
ticketModel.getARMessageInformation(actionItems[0].uuid, actionItems[0].type);
|
|
}
|
|
state.processing = false;
|
|
}).catch(function (response) {
|
|
systemAlertService.error({
|
|
text: response.message ? response.message : 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
|
|
var tempRelation = _.find(ticket.relations, { relationshipType: RelationItemVO.TYPE_ORIGINALOF });
|
|
if (tempRelation && tempRelation.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);
|
|
}
|
|
}
|
|
}).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);
|
|
}
|
|
]);
|
|
})();
|