SmartIT_Extensions/BMC/smart-it-full-helix/scripts/app/admin/screen-configuration/launch-action-controller.js

453 lines
27 KiB
JavaScript

"use strict";
/**
* Created by abhatkha on 9/08/2017.
*/
(function () {
'use strict';
angular.module('adminModule')
.controller('LaunchActionController', ['$filter', '$modal', '$rootScope', '$scope', '$log', '$q', 'events', 'metadataModel',
'screenConfigurationModel', 'screenConfigurationService', 'systemAlertService', 'layoutConfigurationModel',
'objectValueMapperService', '$window', 'expressionEventManager', 'expressionEvaluatorService', '$timeout',
function ($filter, $modal, $rootScope, $scope, $log, $q, events, metadataModel, screenConfigurationModel, screenConfigurationService, systemAlertService, layoutConfigurationModel, objectValueMapperService, $window, expressionEventManager, expressionEvaluatorService, $timeout) {
var promptModal, metadata, contextId, type, isExecutingProviderAction;
$scope.providerActionToExecute = objectValueMapperService.providerActionToExecute;
$scope.context = $scope.context ? $scope.context : $scope.ticket;
if ($scope.bulkContextType) {
type = $scope.bulkContextType;
}
else {
type = $scope.context.ticketType || $scope.context.type;
}
metadataModel.getMetadataByType(type).then(function (data) {
metadata = data;
});
var fieldPropertyMapping = function (actionLists) {
$scope.actionLists = actionLists;
$scope.fieldActionMapping = {};
for (var i in actionLists) {
if (actionLists[i].mappedFields && actionLists[i].mappedFields.length > 0) {
var fieldArr = actionLists[i].mappedFields, fieldObjArr = _.uniqBy(fieldArr, function (field) {
return field.fieldName;
});
for (var j in fieldObjArr) {
$scope.fieldActionMapping[fieldObjArr[j].fieldName] = {
action: actionLists[i],
iconName: fieldObjArr[j].iconName
};
}
}
}
//store the fields with actions map in objectValueMapperService
objectValueMapperService.setFieldActionMapping($scope.fieldActionMapping, $scope.context.type);
};
var extractProviderActionExpressions = function (actionLists) {
var isActionOnTicketLoad;
if (actionLists) {
_.forEach(actionLists, function (action) {
if (action.expressions && action.expressions.length) {
_.forEach(action.expressions, function (expression) {
objectValueMapperService.addToProviderActionExpressionMapper(expression.condition, action);
if (expression.executeOn === 'On Ticket Load') {
isActionOnTicketLoad = true;
}
});
}
});
if (isActionOnTicketLoad) {
expressionEventManager.handleTicketLoadForActions();
}
}
};
if (EntityVO.ENTITIES_WITH_NEW_CUSTOMIZATION.indexOf(type) !== -1) {
screenConfigurationModel.providerHardReload = true;
$scope.associateActionPromise = screenConfigurationModel.loadActionsNew($scope.context.type).then(function () {
$scope.AssociateActionLists = screenConfigurationModel.actionList;
fieldPropertyMapping($scope.AssociateActionLists);
if (screenConfigurationModel.isTicketEnabledForProviderActionExpression(type)) {
extractProviderActionExpressions($scope.AssociateActionLists);
}
});
}
$scope.showEditor = function (callback, params, ticketObj, contentId) {
promptModal = $modal.open({
templateUrl: 'views/admin/screen-configuration/provider-user-prompt.html',
windowClass: 'action-blade provider-user-prompt',
backdrop: 'custom',
resolve: {
ticket: ['ticketModel', function (ticketModel) {
return ticketModel.getTicket(contentId, ticketObj.resource);
}]
},
controller: ['$scope', 'ticket', function ($scope, ticket) {
var fieldObj = {}, result = {}, promptField;
var initMappingFieldDefaultValue = function (field, defaultValue) {
if (field.isCheckboxField()) {
var cBoxOption = (field.options[0] || {});
if (_.includes(cBoxOption, defaultValue) || ['true', 'checked'].indexOf(defaultValue) !== -1 || defaultValue === 0) {
field.setValue(0);
}
}
else if (field.hasDateDataType() || field.hasDateTimeDataType()) {
var stringParseDate = moment(defaultValue);
if (stringParseDate.isValid()) {
field.setValue(stringParseDate.valueOf());
}
else {
// Can be the case when we try to parse string representation of timestamp
// it is worth to try to parse defaultValue to a number and parse
var numberParsedDate = moment(+defaultValue);
if (numberParsedDate.isValid()) {
field.setValue(numberParsedDate.valueOf());
}
}
}
else if (field.hasTimeDataType()) {
var amPmReg = new RegExp(/am|pm/, 'ig');
var parseFormat = 'HH:mm';
if (amPmReg.test(defaultValue)) {
parseFormat = 'hh:mma';
}
var setTimeValue = moment(defaultValue, parseFormat);
if (setTimeValue.isValid()) {
field.value = setTimeValue.valueOf();
}
}
else if (field.isDropdownField() || field.isRadioField()) {
var defaultValueOption = _.find(field.options, function (option) {
return _.includes(option, defaultValue);
});
if (defaultValueOption) {
field.setValue(defaultValueOption.name);
}
}
else {
field.setValue(defaultValue);
}
};
$scope.fieldArray = params.prompt;
// These are required for custom field directives, to render properly
$scope.editMode = true;
$scope.ticket = ticket;
$scope.fieldArray.forEach(function (field) {
if (field.defaultValue) {
initMappingFieldDefaultValue(field.mappedField, field.defaultValue);
}
});
$scope.getMappedFieldRenderType = function (field) {
var type = 'text';
if (field.isCheckboxField()) {
type = 'checkbox';
}
else if (field.hasDateDataType()) {
type = 'date';
}
else if (field.hasDateTimeDataType()) {
type = 'datetime';
}
else if (field.hasTimeDataType()) {
type = 'time';
}
else if (field.isNumberField()) {
type = 'number';
}
else if (field.isDropdownField() || field.isRadioField()) {
type = field.options.length > 0 ? 'enum' : 'text';
/*if (type === 'number') {
field.max = Infinity;
field.min = 0;
}*/
}
return type;
};
$scope.executeAction = function () {
var isEmptyPromptField = false, emptyFieldLabel = '';
for (var i in $scope.fieldArray) {
promptField = $scope.fieldArray[i];
fieldObj[promptField.mappedFieldId] = getMappedFieldValue(promptField.mappedField);
if (fieldObj[promptField.mappedFieldId] === null || fieldObj[promptField.mappedFieldId] === '') {
emptyFieldLabel += promptField.mappedFieldName + ' ';
isEmptyPromptField = true;
}
}
if (isEmptyPromptField) {
var message = emptyFieldLabel + $filter('i18n')('common.labels.nonEmpty');
systemAlertService.error({ text: message, clear: true, hide: 10000 });
}
else {
result = {};
_.extend(result, params, fieldObj);
callback(result, ticketObj, contentId);
promptModal.dismiss();
}
};
$scope.cancelExecution = function () {
isExecutingProviderAction = false;
promptModal.dismiss();
executeQueuedProviderAction(ticketObj);
};
function handleModalBackdropClick() {
$scope.cancelExecution();
}
var getMappedFieldValue = function (field) {
var value = field.getValue();
if (field.isDropdownField()) {
if (field.options.length && !field.ootb && value !== null) {
value = _.get(_.find(field.options, { name: value }), 'name');
}
}
else if (field.isCheckboxField() && value === null) {
value = -1;
}
return value;
};
$scope.$on(events.MODAL_BACKDROP_CLICK, handleModalBackdropClick);
}],
size: 'sm'
});
};
$scope.displaypromptModal = function (executeCallback, params, templateId, ticketObj, contentId) {
screenConfigurationModel.getTemplateById(templateId).then(function (templateObj) {
_.each(params.prompt, function (prompt) {
var mid = prompt.mappedFieldId, found = _.find(templateObj.mappings, { mappedFieldId: mid });
if (!_.isUndefined(found)) {
prompt.defaultValue = found.defaultValue || '';
prompt.mappedFieldName = found.mappedField.label || found.mappedFieldName;
prompt.dataType = found.mappedField.dataType;
prompt.mappedField = new FieldVO().build(found.mappedField);
prompt.mappedField.hideLabel = true;
prompt.mappedField.isReadOnly = false;
prompt.mappedField.isRequired = false;
prompt.mappedField.isHidden = false;
prompt.sequence = found.sequence;
}
});
params.prompt = _.sortBy(params.prompt, 'sequence'); //fix to show fields as per sequence in template object
$scope.showEditor(executeCallback, params, ticketObj, contentId);
});
};
$scope.launchAction = function (actionItem, actionType, $event, calledFromActionExpression) {
$log.topic('actionExecution', actionItem, actionType);
if (actionType === 'client') {
//URL action
//metadataModel.getMetadataByType(scope.context.type).then(function (metadata) {
//regex for finding square brackets [params] in the url
var re = new RegExp('\\[\\w+\\]'), url = actionItem.url, target = actionItem.target === 'new' ? '_blank' : '_self';
var findLabelObject = function (labelObject) {
return labelObject.name === key;
};
while (url.search(re) !== -1) {
var match = url.match(re), key = match[0].replace(/[\[\]']+/g, ''); //remove the square brackets
//check whether field is available in custom fields first else it should be in metadata
if ($scope.context.customFields && angular.isDefined($scope.context.customFields[key])) {
var selectionFieldObject = _.find(screenConfigurationModel.fieldLabels, findLabelObject);
if (selectionFieldObject && selectionFieldObject.options && (selectionFieldObject.options.length > $scope.context.customFields[key])) {
url = url.replace(re, selectionFieldObject.options[$scope.context.customFields[key]].label);
}
else {
url = url.replace(re, $scope.context.customFields[key]);
}
}
else {
var valueFromRecord = screenConfigurationService.getContextPropertyByMetadataMapping($scope.context, metadata, key) || '', localizedValue = $filter('localizeLabel')(valueFromRecord, key, $scope.context.type);
url = url.replace(re, localizedValue || valueFromRecord);
}
}
$log.topic('actionExecution', 'Launch URL action', url, target);
$window.open(encodeURI(url), target);
//});
}
else if (actionType === 'launch') {
$scope.launchActionCallback({ actionItem: actionItem, event: $event });
}
else {
//Provider action
contextId = type === EntityVO.TYPE_ASSET ? $scope.context.reconciliationId : $scope.context.id;
if (EntityVO.ENTITIES_WITH_NEW_CUSTOMIZATION.indexOf($scope.context.type) !== -1) {
$log.topic('providerExecution', 'New Provider action', actionItem, contextId);
if (calledFromActionExpression) {
$scope.getInputParams(actionItem, $scope.context, $scope.executeActionFromExpressionCallback, contextId);
}
else {
$scope.getInputParams(actionItem, $scope.context, $scope.executeActionCallback, contextId);
}
}
else {
$log.topic('actionExecution', 'Old Provider action', actionItem.id, contextId);
screenConfigurationModel.executeProviderAction(actionItem.id, contextId).then(function () {
var message = $filter('i18n')('screenConfiguration.providerActionExecuted', actionItem.actionName);
systemAlertService.success({ text: message, clear: true, hide: 10000 });
}).catch(function (error) {
systemAlertService.error({
text: (error.data && error.data.error) ? error.data.error : error.defaultMessage,
clear: false
});
});
}
}
};
$scope.getInputParams = function (actionObj, ticketObj, callback, contextId) {
var paramObj = { prompt: [] }, showUserPrompt = false, value, fieldDef, fieldName, obj, i;
for (i in actionObj.mappings) {
obj = actionObj.mappings[i];
if (obj.type.indexOf('input') === 0) {
if (obj.mappedFieldValue && (obj.type.indexOf('ticket') !== -1)) {
fieldName = obj.mappedFieldValue;
fieldDef = objectValueMapperService.getFieldDefinitionByName(fieldName, obj.mappedFieldId);
value = objectValueMapperService.getExactValueByFieldName(fieldName);
$log.topic('providerExecution', obj.type, 'fieldName:', fieldName, 'value :', value);
if (fieldDef && (fieldDef.isDropdownField() || fieldDef.isRadioField())) {
var selectedOption = _.find(fieldDef.options, { name: value });
if (selectedOption) {
value = selectedOption.index;
}
else {
value = undefined;
}
}
if (_.isString(value) && fieldDef && (fieldDef.isCheckboxField() || (value === "" && fieldDef.isNumberField()))) {
value = undefined;
}
if (fieldDef && (fieldDef.isDateTimeField() || fieldDef.isDateField()) && !value) {
// In order to prevent error from the backend, client should send null instead of empty string for dates
value = null;
}
paramObj[obj.mappedFieldId] = value;
$log.topic('providerExecution', obj.type, paramObj);
}
else if (obj.type.indexOf('prompt') !== -1) {
showUserPrompt = true;
paramObj.prompt.push(obj);
$log.topic('providerExecution', obj.type, paramObj);
}
else if (obj.type.indexOf('default') !== -1) {
if (obj.mappedFieldValue) {
paramObj[obj.mappedFieldId] = obj.mappedFieldValue;
}
else {
paramObj[obj.mappedFieldId] = '';
}
$log.topic('providerExecution', obj.type, paramObj);
}
}
}
if (showUserPrompt) {
$scope.displaypromptModal(callback, paramObj, actionObj.templateId, actionObj, contextId);
}
else {
callback(paramObj, actionObj, contextId);
$log.topic('providerExecution', actionObj, paramObj);
}
return paramObj;
};
var setOutputParams = function (actionObj, data) {
$log.topic('providerExecution', 'setOutputParams', data);
if (!_.isEmpty(data)) {
$log.topic('providerExecution', 'OPEN_EDIT_MODE');
$rootScope.$broadcast(events.OPEN_EDIT_MODE);
//Delaying setting field values, so that field values are set after edit mode is open
//Else the field value and originalData value will be the same and cannot reset to old value.
$timeout(function () {
objectValueMapperService.setFieldFromProvider(data, actionObj.mappings).then(function () {
$log.topic('providerExecution', 'Loaded output values');
});
});
}
};
$scope.executeActionCallback = function (params, actionItem, contextId) {
delete params.prompt;
if (actionItem.isSynchronous) {
$scope.$emit(events.PROVIDER_SHOW_LOADING);
}
screenConfigurationModel.executeProviderActionV3(actionItem.id, contextId, params).then(function (data) {
setOutputParams(actionItem, data);
var message = $filter('i18n')('screenConfiguration.providerActionExecuted', actionItem.label);
$scope.$emit(events.PROVIDER_HIDE_LOADING);
$log.topic('providerExecution', 'Show success message');
systemAlertService.success({ text: message, clear: true, hide: 10000 });
}).catch(function (error) {
$scope.$emit(events.PROVIDER_HIDE_LOADING);
systemAlertService.error({
text: (error.data && error.data.error) ? error.data.error : error.defaultMessage,
clear: false
});
});
};
$scope.executeActionFromExpressionCallback = function (params, actionItem, contextId) {
delete params.prompt;
if (actionItem.isSynchronous) {
$scope.$emit(events.PROVIDER_SHOW_LOADING);
}
screenConfigurationModel.executeProviderActionV3(actionItem.id, contextId, params).then(function (data) {
isExecutingProviderAction = false;
setOutputParams(actionItem, data);
var message = $filter('i18n')('screenConfiguration.providerActionExecutedFromExpression', actionItem.label);
$scope.$emit(events.PROVIDER_HIDE_LOADING);
$log.topic('providerExecution', 'Show success message');
systemAlertService.success({ text: message, clear: true, hide: 10000 });
executeQueuedProviderAction(actionItem);
}).catch(function (error) {
$scope.$emit(events.PROVIDER_HIDE_LOADING);
isExecutingProviderAction = false;
executeQueuedProviderAction(actionItem);
systemAlertService.error({
text: (error.data && error.data.error) ? error.data.error : error.defaultMessage,
clear: false
});
});
};
function executeQueuedProviderAction(actionItem) {
objectValueMapperService.clearProviderActionFieldName(actionItem.actionFieldName, actionItem.actionId);
clearProviderAction(actionItem);
if ($scope.providerActionsList.length) {
$timeout(function () {
$scope.launchActionFromExpression($scope.providerActionsList);
});
}
}
$scope.checkForOutputMapping = function (actionObj) {
var returnVal = false;
if (actionObj && actionObj.mappings && actionObj.mappings.length) {
if (!_.isUndefined(_.find(actionObj.mappings, { type: 'output' }))) {
returnVal = true;
}
}
return returnVal;
};
$scope.hide = function () {
promptModal.hide();
};
//whenever ticket is getting loaded or user clicks on cancel button of edit ticket this event is registered causing memory leak as well as firing multiple times.
if (!objectValueMapperService.isProviderActionEventRegistered()) {
objectValueMapperService.registerProviderActionCallExpressionEvent($rootScope.$on(events.PROVIDER_ACTION, function (event, data) {
if (data.length) {
$scope.providerActionsList = objectValueMapperService.getProviderActionsList();
if (_.size($scope.providerActionsList) && !isExecutingProviderAction) {
$scope.launchActionFromExpression($scope.providerActionsList);
}
}
}));
}
// $scope.$on('$destroy', function () {
// unbindRootScopeListener();
// });
$scope.launchActionFromExpression = function (actionList) {
if (!_.isArray(actionList) || (actionList && actionList.length <= 0)) {
return;
}
// the expression may no longer be valid based on the previous actions output mappings,
// so re-evaluate expression before executing the next action
var value = expressionEvaluatorService.evaluate(actionList[0].expression);
if (value) {
isExecutingProviderAction = true;
$scope.launchAction(actionList[0].action, actionList[0].action.actionType, null, true);
}
else if (actionList[0] && actionList[0].action) {
objectValueMapperService.clearProviderActionFieldName(actionList[0].action.actionFieldName, actionList[0].action.actionId);
}
};
function clearProviderAction(actionItem) {
objectValueMapperService.clearProviderActionFromList(actionItem);
}
}]);
})();