SmartIT_Extensions/BMC/smart-it-full/scripts/app/layout-configuration/status-bar-component/status-bar-controller.js

373 lines
22 KiB
JavaScript

"use strict";
/**
* Created by andey on 19-08-2017.
*/
(function () {
'use strict';
angular.module('layoutConfigModule')
.controller('StatusBarController', ['$scope', 'events', 'objectValueMapperService', 'fieldValidationModel',
'ticketModel', '$rootScope', '$modal', 'screenConfigurationModel',
function ($scope, events, objectValueMapperService, fieldValidationModel, ticketModel, $rootScope, $modal, screenConfigurationModel) {
var originalStatus, originalStatusReason;
var selected = {
status: null,
statusReason: null,
resolutionNote: null
}, statusField = new FieldVO().build({
name: $scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatus' : 'status',
type: 'characterField',
dataType: 'text',
ootb: true,
editable: true,
readOnly: false
}), validStatuses, originalTicket;
if ($scope.data) {
statusField = angular.copy($scope.data);
}
$scope.statusField = statusField;
$scope.defaultResolutionNoteLength = 250;
$scope.displayTruncatedText = false;
$scope.isStatusDisabled = function () {
return $scope.ticket.accessMappings.allEditAllowed === false || ($scope.ticket.type === EntityVO.TYPE_TASK
? $scope.ticket.accessMappings.fieldMappings.taskStatus === 'read'
: $scope.ticket.accessMappings.fieldMappings.status === 'read');
};
$scope.isStatusReasonDisabled = function () {
return $scope.ticket.accessMappings.allEditAllowed === false || ($scope.ticket.type === EntityVO.TYPE_TASK
? $scope.ticket.accessMappings.fieldMappings.taskStatusReason === 'read'
: $scope.ticket.accessMappings.fieldMappings.statusReason === 'read');
};
$scope.isResolutionDisabled = function () {
return $scope.ticket.accessMappings.fieldMappings.statusReason === 'read';
};
var statusReasonField = new FieldVO().build({
name: $scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatusReason' : 'statusReason',
type: 'characterField',
dataType: 'text',
ootb: true
}), resolutionNoteField = new FieldVO().build({
name: 'resolution',
type: 'characterField',
dataType: 'text',
ootb: true
});
$scope.statusReasonField = statusReasonField;
function init() {
selected.status = _.cloneDeep(_.find($scope.metadata.statuses, { name: $scope.ticket.status.value }));
originalStatus = _.cloneDeep(selected.status);
if (!_.isEmpty(selected.status)) {
selected.statusReason = _.find(selected.status.statusReasons, { name: $scope.ticket.status.reason });
if ($scope.ticket.status.reason && !selected.statusReason) {
var screenName = screenConfigurationModel.getScreenNameByTicketType($scope.ticket.type), screenPanels = screenConfigurationModel.screensCacheByName[screenName]
? screenConfigurationModel.screensCacheByName[screenName].panels : [], statusFieldFull, statusReasonFieldFull;
_.forEach(screenPanels, function (panel) {
statusFieldFull = _.findLast(panel.fields, { name: 'status' });
if (statusFieldFull) {
return false;
}
});
statusReasonFieldFull = _.find(statusFieldFull.members, { name: statusReasonField.name });
selected.statusReason = _.find(statusReasonFieldFull.options, { name: $scope.ticket.status.reason });
}
}
else {
selected.statusReason = null;
}
originalStatusReason = _.cloneDeep(selected.statusReason);
selected.resolutionNote = $scope.ticket.resolution ? $scope.ticket.resolution : '';
selected.resolutionNoteLength = selected.resolutionNote ? selected.resolutionNote.length : 0;
if (selected.resolutionNoteLength > $scope.defaultResolutionNoteLength) {
$scope.displayTruncatedText = true;
}
if (selected.status && selected.status.invalidStatusTransitions && selected.status.invalidStatusTransitions.length) {
$scope.availableStatuses = _.filter($scope.metadata.statuses, function (status) {
return ~_.indexOf(selected.status.invalidStatusTransitions, status.name) ? false : true;
});
}
else if (selected.status && selected.status.validKnowledgeTransitions) {
if (selected.status.validKnowledgeTransitions.length) {
$scope.availableStatuses = _.filter($scope.metadata.statuses, function (status) {
return _.find(selected.status.validKnowledgeTransitions, { validStatus: status.name });
});
}
else {
$scope.availableStatuses = [];
}
}
else if ($scope.ticket.type === EntityVO.TYPE_CHANGE || (($scope.ticket.type === EntityVO.TYPE_PROBLEM || $scope.ticket.type === EntityVO.TYPE_KNOWNERROR) && !$scope.isDraft)) {
ticketModel.getAvailableStatuses($scope.ticket.id, $scope.ticket.type).then(function (validStatuses) {
$scope.availableStatuses = _.filter($scope.metadata.statuses, function (status) {
return validStatuses.indexOf(status.name) !== -1;
});
});
}
else if ($scope.ticket.type === EntityVO.TYPE_RELEASE && !$scope.isDraft) {
$scope.availableMilestoneStatuses = _.filter($scope.metadata.milestones, function (milestone) {
return _.findIndex(validStatuses, { milestone: milestone.name }) !== -1;
});
$scope.changeMileStone(selected.milestone, 'release');
}
else {
$scope.availableStatuses = $scope.metadata.statuses;
}
statusField.value = selected.status && selected.status.name;
statusReasonField.value = selected.statusReason && selected.statusReason.name;
resolutionNoteField.value = selected.resolutionNote;
objectValueMapperService.addFields([statusField, statusReasonField, resolutionNoteField]);
$scope.selected = selected;
statusField.value = selected.status && selected.status.name;
statusReasonField.value = selected.statusReason ? selected.statusReason.name : '';
resolutionNoteField.value = selected.resolutionNote || '';
if (selected.status && selected.status.name === 'Pending' && selected.status.statusReasons) {
_.remove(selected.status.statusReasons, function (reason) {
return reason.name === 'Pending Original Incident';
});
}
}
init();
$scope.loadMore = function () {
$scope.selected.expanded = (_.isUndefined($scope.selected.expanded)) ? true : !$scope.selected.expanded;
};
$scope.$watch('statusField.setValueFlag', function (value) {
var status;
if (value !== '#$#') {
if (value) {
status = _.find($scope.metadata.statuses, { name: value });
if (status) {
$scope.changeStatus(status);
}
}
$scope.statusField.setValueFlag = '#$#';
}
});
$scope.$watch('statusReasonField.setValueFlag', function (value) {
var statusReason;
if (value !== '#$#') {
if (value) {
statusReason = _.find(selected.status.statusReasons, { name: value });
if (statusReason) {
$scope.changeStatusReason(statusReason);
}
}
$scope.statusReasonField.setValueFlag = '#$#';
}
});
$scope.changeStatus = function (status) {
selected.status = status;
selected.statusReason = null;
if ($scope.ticket.type && $scope.ticket.type === 'incident' && $scope.ticket.resolution === null && (selected.status.name !== 'Closed' && selected.status.name !== 'Resolved')) {
selected.resolutionNote = '';
$scope.changeResolutionNote();
}
var statusField = objectValueMapperService.getFieldByName($scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatus' : 'status');
statusField.value = selected.status.name;
//set the status reason field value on status change, otherwise the expressions are not evaluated correctly
var statusReasonField = objectValueMapperService.getFieldByName($scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatusReason' : 'statusReason');
statusReasonField.value = selected.statusReason && selected.statusReason.name;
var memberName = $scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatus' : 'status';
$scope.$emit(events.WIDGET_VALUE_CHANGE, { fieldName: statusField.name, memberName: memberName });
$scope.fixScheduledDates = $scope.ticket.type === 'change' && selected.status.name === 'Scheduled For Review'
&& (($scope.ticket.scheduledStartDate && $scope.ticket.scheduledStartDate.valueOf() <= $scope.ticket.earliestStartDate)
|| ($scope.ticket.scheduledEndDate && $scope.ticket.scheduledEndDate.valueOf() <= $scope.ticket.earliestStartDate));
if ($scope.ticket.type && $scope.ticket.type === 'change' && selected.status.name === 'Completed') {
selected.statusReason = _.find(status.statusReasons, { name: 'Final Review Required' });
}
if (selected.status && selected.status.name === 'Pending' && selected.status.statusReasons) {
_.remove(selected.status.statusReasons, function (reason) {
return reason.name === 'Pending Original Incident';
});
}
};
$scope.changeStatusReason = function (statusReason) {
selected.statusReason = statusReason;
var statusReasonField = objectValueMapperService.getFieldByName($scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatusReason' : 'statusReason');
statusReasonField.value = selected.statusReason.name;
var memberName = $scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatusReason' : 'statusReason';
$scope.$emit(events.WIDGET_VALUE_CHANGE, { fieldName: statusReasonField.name, memberName: memberName });
};
$scope.changeResolutionNote = function () {
var resolutionNoteField = objectValueMapperService.getFieldByName('resolution');
resolutionNoteField.value = selected.resolutionNote;
$scope.$emit(events.WIDGET_VALUE_CHANGE, { fieldName: resolutionNoteField.name, memberName: 'resolution' });
};
$scope.needResolutionNote = function () {
return ($scope.ticket.type === EntityVO.TYPE_INCIDENT) && (~[EntityVO.STATUS_CLOSED, EntityVO.STATUS_RESOLVED].indexOf(selected.status.name.toLowerCase()) || !_.isEmpty($scope.ticket.resolution));
};
$scope.isFieldRequired = function (fieldName) {
if (fieldName === 'statusReason') {
if ($scope.ticket.type === EntityVO.TYPE_INCIDENT || $scope.ticket.type === EntityVO.TYPE_CHANGE || $scope.ticket.type === EntityVO.TYPE_RELEASE
|| $scope.ticket.type === EntityVO.TYPE_PROBLEM || $scope.ticket.type === EntityVO.TYPE_TASK || $scope.ticket.type === EntityVO.TYPE_KNOWNERROR) {
return fieldValidationModel.isFieldRequired($scope.ticket.type, $scope.selected.status.name, $scope.ticket.timing, fieldName);
}
else if ($scope.ticket.type === EntityVO.TYPE_WORKORDER || $scope.ticket.type === EntityVO.TYPE_ACTIVITY) {
return false;
}
else {
return true;
}
}
//only show when moving from a status where it's not required to a status where it's required
return fieldValidationModel.isFieldRequired($scope.ticket.type, $scope.ticket.status.value, $scope.ticket.timing, fieldName)
&& !fieldValidationModel.isFieldRequired($scope.ticket.type, originalTicket.status.value, $scope.ticket.timing, fieldName);
};
$scope.switchState = function (direction, ticketType) {
var currentStatusIndex, switchToState = {}, prevStatusIndex, nextStatusIndex;
if (ticketType !== 'release') {
currentStatusIndex = _.findIndex($scope.availableStatuses, function (status) {
return status.index === $scope.selected.status.index;
});
}
else {
currentStatusIndex = _.findIndex($scope.availableMilestoneStatuses, function (status) {
return status.index === $scope.selected.milestone.index;
});
}
if (currentStatusIndex !== -1) {
if (direction === 'prev') {
if ((ticketType === 'change' || ticketType === 'problem')
&& $scope.availableStatuses[currentStatusIndex].name === 'Completed') {
prevStatusIndex = currentStatusIndex !== 0 ? parseInt(currentStatusIndex - 2) : 0;
}
else {
prevStatusIndex = currentStatusIndex !== 0 ? parseInt(currentStatusIndex - 1) : 0;
}
if (ticketType === 'release') {
switchToState = $scope.availableMilestoneStatuses[prevStatusIndex] || {};
}
else {
switchToState = $scope.availableStatuses[prevStatusIndex] || {};
}
}
else if (direction === 'next') {
if (((ticketType === 'change' && ($scope.availableStatuses[currentStatusIndex].name === 'Implementation In Progress'
|| $scope.availableStatuses[currentStatusIndex].name === 'Planning In Progress')) || ticketType === 'problem')
&& $scope.availableStatuses[currentStatusIndex + 1]
&& $scope.availableStatuses[currentStatusIndex + 1].name === 'Pending') {
nextStatusIndex = currentStatusIndex !== $scope.availableStatuses.length - 1 ? parseInt(currentStatusIndex + 2) : $scope.availableStatuses.length - 1;
}
else {
nextStatusIndex = currentStatusIndex !== $scope.availableStatuses.length - 1 ? parseInt(currentStatusIndex + 1) : $scope.availableStatuses.length - 1;
}
if (ticketType === 'release') {
switchToState = $scope.availableMilestoneStatuses[nextStatusIndex] || {};
}
else {
switchToState = $scope.availableStatuses[nextStatusIndex] || {};
}
}
}
if (ticketType !== 'release') {
$scope.changeStatus(switchToState, ticketType);
}
else {
selected.status = {};
$scope.changeMileStone(switchToState, ticketType);
}
};
$scope.clearStatusReason = function (item) {
var statusReasonField = objectValueMapperService.getFieldByName($scope.ticket.type === EntityVO.TYPE_TASK ? 'taskStatusReason' : 'statusReason');
statusReasonField.value = "";
};
$scope.checkStatusSwitcherIsDisabled = function (type, ticketType) {
var noSwitchStatuses = ['Pending', 'Cancelled', 'Closed', 'Rejected'], currentStatusIndex, nextStatusIndex, nextStatus;
if (ticketType !== 'release') {
currentStatusIndex = _.findIndex($scope.availableStatuses, function (status) {
return status.index === $scope.selected.status.index;
});
}
else {
currentStatusIndex = _.findIndex($scope.availableMilestoneStatuses, function (status) {
return status.index === $scope.selected.milestone.index;
});
}
if (currentStatusIndex !== -1 && ticketType !== 'release') {
if (type === 'prev') {
return ((currentStatusIndex === 0)
|| noSwitchStatuses.indexOf($scope.selected.status.name) >= 0);
}
else if (type === 'next') {
if (((ticketType === 'change'
&& ($scope.availableStatuses[currentStatusIndex].name === 'Implementation In Progress'
|| $scope.availableStatuses[currentStatusIndex].name === 'Planning In Progress'))
|| (ticketType === 'problem' || ticketType === 'knownerror'))
&& $scope.availableStatuses[currentStatusIndex + 1]
&& ($scope.availableStatuses[currentStatusIndex + 1].name === 'Pending'
|| $scope.availableStatuses[currentStatusIndex + 1].name === 'Cancelled')) {
nextStatusIndex = parseInt(currentStatusIndex + 2);
nextStatus = $scope.availableStatuses[nextStatusIndex] || {};
}
else {
nextStatusIndex = parseInt(currentStatusIndex + 1);
nextStatus = $scope.availableStatuses[nextStatusIndex] || {};
}
if ($scope.selected.status.name === 'Completed' && nextStatus.name === 'Closed') {
return (noSwitchStatuses.indexOf($scope.selected.status.name) >= 0);
}
else {
return (noSwitchStatuses.indexOf(nextStatus.name) >= 0
|| noSwitchStatuses.indexOf($scope.selected.status.name) >= 0);
}
}
}
if (currentStatusIndex !== -1 && ticketType === 'release') {
if (type === 'prev') {
return (currentStatusIndex === 0);
}
else if (type === 'next') {
nextStatusIndex = parseInt(currentStatusIndex + 1);
if ($scope.availableMilestoneStatuses[nextStatusIndex] === undefined) {
return true;
}
}
}
};
$scope.$on(events.TOGGLE_EDIT_MODE, handleToggleEditMode);
$scope.$on(events.AFTER_SAVED_CHANGES, afterSaveChangesHandler);
$scope.$on(events.DISCARD_CHANGES, handleDiscardChanges);
var unbindRootScopeListener = $rootScope.$on(events.TICKET_TEMPLATE_UPDATED, function (e, value) {
selected.status = value.selectedStatus;
selected.statusReason = value.selectedStatusReason;
statusField.value = value.selectedStatus.name;
selected.resolutionNote = value.resolution;
});
function handleToggleEditMode() {
$scope.editMode = true;
}
function afterSaveChangesHandler() {
$scope.editMode = false;
originalStatus = _.cloneDeep(selected.status);
originalStatusReason = _.cloneDeep(selected.statusReason);
}
function handleDiscardChanges() {
$scope.editMode = false;
selected.status = _.cloneDeep(originalStatus);
selected.statusReason = _.cloneDeep(originalStatusReason);
init();
}
function checkIfValidDates() {
var scheduledStartTime = $scope.ticket.scheduledStartDate.valueOf(), scheduledEndTime = $scope.ticket.scheduledEndDate.valueOf();
$scope.fixScheduledDates = $scope.ticket && $scope.ticket.type === 'change'
&& selected.status.name === 'Scheduled For Review'
&& (scheduledStartTime <= $scope.ticket.earliestStartDate || scheduledEndTime <= $scope.ticket.earliestStartDate);
}
$scope.$watch('ticket.scheduledStartDate', function () {
if ($scope.ticket && $scope.ticket.type === 'change'
&& selected.status.name === 'Scheduled For Review' && $scope.ticket.scheduledStartDate) {
checkIfValidDates();
}
});
$scope.$watch('ticket.scheduledEndDate', function () {
if ($scope.ticket && $scope.ticket.type === 'change'
&& selected.status.name === 'Scheduled For Review' && $scope.ticket.scheduledEndDate) {
checkIfValidDates();
}
});
$scope.editTicketStatus = function () {
$scope.$emit(events.EDIT_STATUS_CLICK);
};
$scope.$on('$destroy', function () {
unbindRootScopeListener();
});
}]);
})();