SmartIT_Extensions/BMC/smart-it-full-helix/scripts/app/field-customization/custom-field-directives.js

977 lines
55 KiB
JavaScript

"use strict";
// jscs:disable validateIndentation
(function () {
'use strict';
$.widget('ui.numericSpinner', $.ui.spinner, {
_format: function (value) {
return value.toFixed(this._precision());
}
});
angular.module('myitsmApp')
.factory('customFieldLinkFunction', ['events', function (events) {
return function (scope) {
scope.showMeridian = window.showMeridian;
scope.onFieldValueChange = function (field) {
field = field || scope.data;
// this is result of user interaction, so field wil always have value
field.hasValue = true;
scope.$parent.$emit(events.FIELD_VALUE_CHANGE, field);
};
};
}])
.filter('customFieldLabelI18n', ['screenConfigurationModel', function (screenConfigurationModel) {
return function (data, ticketType) {
var classId;
if (data.extension && data.extension.length > 0 && data.extension[0].classId) {
classId = data.extension[0].classId;
}
var localizedField = screenConfigurationModel.getLocalizedFieldByNameForTicketType(data.name, ticketType, classId);
return (localizedField && localizedField.label) ? localizedField.label : data.label;
};
}])
.directive('customFieldLabel', function () {
return {
restrict: 'E',
replace: true,
template: '<label ux-id="field-label" id="{{data.name + \'Label\'}}" class="label__text label_control-wrap" ng-class="{\'required__label\': data.isRequired && ($parent.$parent.editMode || $parent.$parent.$parent.editMode)}" data-required="{{\'common.label.required.bracketed\' | i18n}}" ng-hide="hideLabel()" aria-label="{{ data | customFieldLabelI18n: typeOfTicket }}" title="{{ data | customFieldLabelI18n: typeOfTicket }}" for="{{data.name + \'InputBox\'}}">{{ data | customFieldLabelI18n: typeOfTicket }}</label>',
link: function (scope) {
//scope leaks so careful of setting anything here
scope.typeOfTicket = scope.context ? (scope.context.type || scope.context.ticketType) : '';
scope.hideLabel = function () {
var isDataPresent;
if (scope.alwaysShowLabel) {
return false;
}
isDataPresent = scope.data.ootb || !!scope.data.value || scope.data.value === 0;
return scope.isHideLabel && (!scope.$parent.$parent.editMode || !(scope.$parent.$parent.$parent && scope.$parent.$parent.$parent.editMode)) ? scope.isHideLabel : !((!scope.data.hideLabel && isDataPresent) || scope.$parent.$parent.editMode || (scope.$parent.$parent.$parent && scope.$parent.$parent.$parent.editMode));
};
}
};
})
.directive('characterCustomField', ['customFieldLinkFunction', '$filter', 'events', function (customFieldLinkFunction, $filter, events) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
charLimit: '=',
isHideLabel: '=',
typeOfTicket: '=?'
},
templateUrl: 'views/field-customization/custom-fields/character-custom-field.html',
link: function (scope, element) {
customFieldLinkFunction(scope);
scope.status = {
isCollapsed: true
};
//The logic of generating Id for other ticket types is different than that of Task. Task uses Field Id 1 as its
//primary Ticket Id. The input char length is returned as 1, but the task ID is more than 1 char so, UC shows the
//maximum characters reached message always.The below fix is to set the field maxLength to 15.
if (scope.data.label === 'Task ID') {
scope.data.maxLength = 15;
}
scope.$watch('data.setValueFlag', function (value) {
if (value && value !== '#$#') {
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
if (scope.data.maxLength > 0) {
element.find('.form-control').attr('maxlength', scope.data.maxLength);
}
var originaldata = _.cloneDeep(scope.data.value);
scope.$on(events.SAVE_CHANGES, function () {
originaldata = _.cloneDeep(scope.data.value);
});
scope.$on(events.DISCARD_CHANGES, function () {
scope.data.value = _.cloneDeep(originaldata);
});
}
};
}])
.directive('textareaCustomField', ['customFieldLinkFunction', '$filter', 'events', function (customFieldLinkFunction, $filter, events) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
isHideLabel: '=',
charLimit: '=?',
},
templateUrl: 'views/field-customization/custom-fields/textarea-custom-field.html',
link: function (scope, element) {
customFieldLinkFunction(scope);
scope.status = {
isCollapsed: true
};
scope.$watch('data.setValueFlag', function (value) {
if (value && value !== '#$#') {
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
if (scope.data.maxLength > 0) {
element.find('.form-control').attr('maxlength', scope.data.maxLength);
}
var originaldata = _.cloneDeep(scope.data.value);
scope.$on(events.SAVE_CHANGES, function () {
originaldata = _.cloneDeep(scope.data.value);
});
scope.$on(events.DISCARD_CHANGES, function () {
scope.data.value = _.cloneDeep(originaldata);
});
}
};
}])
.directive('staticSelectionCustomField', ['customFieldLinkFunction', 'screenConfigurationModel', 'events', '$filter', '$rootScope',
function (customFieldLinkFunction, screenConfigurationModel, events, $filter, $rootScope) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
context: '=',
isEditable: '=',
isHideLabel: '='
},
templateUrl: 'views/field-customization/custom-fields/static-selection-custom-field.html',
link: function (scope) {
customFieldLinkFunction(scope);
var field = scope.data;
var fieldLabels = screenConfigurationModel.fieldLabels || [];
var dropdownLabels;
scope.dropdownOptions = {
selectedOption: null
};
if (EntityVO.ENTITIES_WITH_NEW_CUSTOMIZATION.indexOf(scope.context.type) !== -1) {
dropdownLabels = {
options: field.options
};
}
else {
dropdownLabels = _.find(fieldLabels, function (fieldItem) {
var validField = fieldItem.name === scope.data.name;
if (validField && scope.context && scope.context.ticketType === EntityVO.TYPE_ASSET) {
if (fieldItem.classIds && fieldItem.classIds.length) {
validField = fieldItem.classIds[0] === 'ITSM AssetBase' || fieldItem.classIds[0] === scope.context.classId;
}
}
return validField;
});
}
var dynamicSelectionOptions = [
{ index: 0, value: 0, label: $filter('i18n')('customField.selection.label.yes') },
{ index: 1, value: 1, label: $filter('i18n')('customField.selection.label.no') }
];
scope.handleRadioEnterKey = function (option) {
if (!scope.data.isReadOnly && scope.isEditable) {
scope.selectItem(option);
if (!scope.data.radioFieldVal) {
scope.data.radioFieldVal = !scope.data.radioFieldVal;
}
;
}
};
scope.options = (field.isSelectionField()) ? dynamicSelectionOptions : (dropdownLabels && dropdownLabels.options || []);
scope.selectItem = function (option) {
scope.dropdownOptions.selectedOption = option;
if (!_.isEmpty(option)) {
if (field.isRadioField() && option.index === field.getValue()) {
scope.dropdownOptions.selectedOption = null;
scope.data.radioFieldVal = null;
field.clearValue();
}
else {
field.setValue(option.name ? option.name : option.value);
}
}
else {
field.clearValue();
}
scope.onFieldValueChange();
};
scope.$watch('data.setValueFlag', function (value) {
if (value !== '#$#') {
refreshValue();
scope.onFieldValueChange();
field.setValueFlag = '#$#';
}
});
var unbindRootScopeListener = $rootScope.$on(events.TICKET_TEMPLATE_UPDATED, function (events, data) {
if (scope.data.name === 'serviceType' && data) {
if (data.selectedServiceType && data.selectedServiceType.name) {
var option = _.find(scope.options, { name: data.selectedServiceType.name });
if (option) {
scope.selectItem(option);
}
}
else {
scope.selectItem(null);
}
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
scope.$on(events.RISK_LEVEL_CHANGE, function (events, field) {
if (scope.data.name === "changeReason") {
if (angular.isUndefined(scope.data.originalRequired) || scope.data.originalRequired === null) {
scope.data.originalRequired = scope.data.isRequired;
}
scope.data.isRequired = scope.data.originalRequired || field.isRequired;
}
});
function refreshValue() {
var selectedValueIndex = scope.data.getValue();
if (selectedValueIndex && (typeof selectedValueIndex === 'object')) {
selectedValueIndex = selectedValueIndex.name;
}
scope.data.radioFieldVal = scope.data.value;
if (angular.isDefined(selectedValueIndex) && selectedValueIndex !== null) {
if (scope.data.ootb) {
scope.dropdownOptions.selectedOption = _.find(scope.options, { name: selectedValueIndex });
if (!scope.dropdownOptions.selectedOption) { // Fix for SW00538722
scope.dropdownOptions.selectedOption = _.find(scope.options, { index: selectedValueIndex });
}
}
else {
scope.dropdownOptions.selectedOption = _.find(scope.options, function (option) {
return option.index === selectedValueIndex || option.name === selectedValueIndex;
});
}
}
else {
scope.dropdownOptions.selectedOption = null;
}
}
refreshValue();
scope.$on(events.REFRESH_FIELD_VALUES, refreshValue);
scope.$on('$destroy', function () {
unbindRootScopeListener();
});
}
};
}])
.directive('checkboxCustomField', ['customFieldLinkFunction', 'screenConfigurationModel', '$filter', 'events',
function (customFieldLinkFunction, screenConfigurationModel, $filter, events) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
isHideLabel: '=',
typeOfTicket: '=?'
},
templateUrl: 'views/field-customization/custom-fields/checkbox-custom-field.html',
link: function (scope) {
customFieldLinkFunction(scope);
//value of checkbox ngModel should be true or false for required validation to work.
scope.checkbox = {
value: scope.data.value !== -1 && scope.data.value !== undefined && scope.data.value !== null
};
var field = scope.data, oldFieldData = angular.copy(scope.data);
var fieldLabels = screenConfigurationModel.fieldLabels || [];
var checkboxLabels = _.find(fieldLabels, { name: field.name }) || field;
var cbDynamicOption = getCbDynamicOption(field.value);
scope.editLabel = (checkboxLabels && checkboxLabels.options && checkboxLabels.options.length) ? checkboxLabels.options[0].label : '';
if (field.isSelectionField()) {
scope.cbOption = cbDynamicOption;
if (field.dynamicField) {
scope.alwaysShowLabel = true;
}
}
else {
scope.cbOption = (checkboxLabels && checkboxLabels.options) ? checkboxLabels.options[0] : { index: -1, label: '-' };
if (checkboxLabels && checkboxLabels.options && field.value !== checkboxLabels.options[0].index) {
field.setValue(-1);
scope.cbOption = { index: -1, label: '-' };
}
}
scope.$watch('data.setValueFlag', function (value) {
if (value !== '#$#') {
if (!field.isSelectionField()) {
if (value !== -1) {
field.setValue(-1);
}
else {
field.setValue((checkboxLabels && checkboxLabels.options && checkboxLabels.options.length) ? checkboxLabels.options[0].index : 0);
}
}
else {
scope.cbOption = getCbDynamicOption(value);
if (value) {
field.clearValue();
}
}
scope.selectItem();
field.setValueFlag = '#$#';
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
scope.selectItem = function () {
if (!field.isSelectionField()) {
if (!(field.value === -1 || field.value === null || field.value === undefined)) {
field.setValue(-1);
scope.cbOption = { index: -1, label: '-' };
}
else {
scope.cbOption = (checkboxLabels && checkboxLabels.options && checkboxLabels.options.length) ? checkboxLabels.options[0] : { index: 0, label: '' };
field.setValue((checkboxLabels && checkboxLabels.options && checkboxLabels.options.length) ? checkboxLabels.options[0].index : 0);
}
}
else {
if (field.value !== null && field.value !== '' && field.value !== undefined) {
field.clearValue();
}
else {
field.setValue(scope.cbOption.index);
}
scope.cbOption = getCbDynamicOption(field.value);
}
scope.onFieldValueChange();
};
function getCbDynamicOption(value) {
return (value === null) ?
{ index: 0, label: $filter('i18n')('customField.checkbox.label.off') } :
{ index: 0, label: $filter('i18n')('customField.checkbox.label.on') };
}
function handleDiscardChanges() {
var oldVal = oldFieldData.getValue();
if (field.isSelectionField()) {
if (oldVal === null || oldVal === '' || oldVal === undefined) {
field.clearValue();
}
else {
field.setValue(scope.cbOption.index);
}
scope.cbOption = getCbDynamicOption(field.value);
}
else {
if (oldVal === -1 || oldVal === null || oldVal === undefined) {
field.setValue(-1);
scope.cbOption = { index: -1, label: '-' };
}
else {
scope.cbOption = (checkboxLabels && checkboxLabels.options && checkboxLabels.options.length) ? checkboxLabels.options[0] : { index: 0, label: '' };
field.setValue(oldVal);
}
}
}
function updateOldDataField() {
oldFieldData = angular.copy(scope.data);
}
scope.$on(events.RESET_DYNAMIC_FIELDS, handleDiscardChanges);
scope.$on(events.UPDATE_DYNAMIC_DATA, updateOldDataField);
}
};
}])
.directive('numberCustomField', ['customFieldLinkFunction', '$filter', 'events', function (customFieldLinkFunction, $filter, events) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
isHideLabel: '=',
typeOfTicket: '=?'
},
templateUrl: 'views/field-customization/custom-fields/number-custom-field.html',
link: function (scope) {
scope.data.step = Math.pow(10, -scope.data.precision);
scope.$watch('data.setValueFlag', function (value) {
if (value !== '#$#') {
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
customFieldLinkFunction(scope);
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
var originaldata = _.cloneDeep(scope.data.value);
scope.$on(events.SAVE_CHANGES, function () {
originaldata = _.cloneDeep(scope.data.value);
});
scope.$on(events.DISCARD_CHANGES, function () {
scope.data.value = _.cloneDeep(originaldata);
});
}
};
}])
.directive('dateTimeCustomField', ['customFieldLinkFunction', '$filter', 'events', 'configurationModel', function (customFieldLinkFunction, $filter, events, configurationModel) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
isHideLabel: '=',
typeOfTicket: '=?'
},
templateUrl: 'views/field-customization/custom-fields/datetime-custom-field.html',
link: function (scope) {
customFieldLinkFunction(scope);
scope.status = {
opened: false
};
scope.datePickerOptions = {
startingDay: configurationModel.getWeekStartingDay(),
'show-weeks': false,
minDate: moment().year(1970).month(0).date(2),
maxDate: moment().year(2038).month(0).date(18)
};
scope.$watch('data.setValueFlag', function (value) {
if (value && value !== '#$#') {
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
scope.open = function ($event) {
$event.preventDefault();
$event.stopPropagation();
scope.status.opened = true;
};
var originaldata = _.cloneDeep(scope.data.value);
scope.$on(events.SAVE_CHANGES, function () {
originaldata = _.cloneDeep(scope.data.value);
});
scope.$on(events.DISCARD_CHANGES, function () {
scope.data.value = _.cloneDeep(originaldata);
});
}
};
}])
.directive('dateCustomField', ['customFieldLinkFunction', '$filter', 'configurationModel', function (customFieldLinkFunction, $filter, configurationModel) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
isHideLabel: '='
},
templateUrl: 'views/field-customization/custom-fields/date-custom-field.html',
link: function (scope) {
customFieldLinkFunction(scope);
scope.status = {
opened: false
};
scope.datePickerOptions = {
startingDay: configurationModel.getWeekStartingDay(),
'show-weeks': false,
minDate: moment().year(1970).month(0).date(2)
};
if (!scope.data.isDateTimeField()) {
if (scope.data.value) {
/* We are using the date filter in date-custom-field template and the date filter converts the epoch value according to the current timezone. We need to display date values in GMT.
The getTimezoneOffset () method returns the time difference between UTC time and local time in minutes. Adding timezone offset as it is being removed by the date filter */
var gmtDate = new Date(scope.data.value);
var fieldValue = gmtDate.valueOf() + (gmtDate.getTimezoneOffset() * 60000);
if (fieldValue) {
scope.data.value = fieldValue;
}
}
}
scope.$watch('data.setValueFlag', function (value) {
if (value && value !== '#$#') {
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
scope.open = function ($event) {
$event.preventDefault();
$event.stopPropagation();
scope.status.opened = true;
};
}
};
}])
.directive('timeCustomField', ['customFieldLinkFunction', '$filter', 'events', function (customFieldLinkFunction, $filter, events) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
isEditable: '=',
isHideLabel: '='
},
templateUrl: 'views/field-customization/custom-fields/time-custom-field.html',
link: function (scope) {
scope.$watch('data.setValueFlag', function (value) {
if (value && value !== '#$#') {
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
customFieldLinkFunction(scope);
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
var originaldata = _.cloneDeep(scope.data.value);
scope.$on(events.SAVE_CHANGES, function () {
originaldata = _.cloneDeep(scope.data.value);
});
scope.$on(events.DISCARD_CHANGES, function () {
scope.data.value = _.cloneDeep(originaldata);
});
}
};
}])
.directive('validNumber', ['$timeout', function ($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elem, attr, ctrl) {
ctrl.$parsers.push(checkPrecision, checkRequired);
function checkPrecision(val) {
var stringVal = val ? val.toString() : '';
// do nothing if we got an invalid number or smth like '123' or '123.'
if (!stringVal || stringVal.indexOf('.') === -1 || !stringVal.split('.')[1].length) {
return val;
}
var precision = parseInt(attr.precision);
var precisionLen = stringVal.split('.')[1].length;
var valid = true;
var newVal = val;
var sliceAmount = 0;
var parseVal = '';
if (!precision) {
// precision=0 but we got 123.4
valid = false;
sliceAmount = precisionLen + 1; // +1 means to cut decimal separator '.' as well
}
else if (precision < precisionLen) {
// precision=2 but we got 123.456
valid = false;
sliceAmount = precisionLen - attr.precision;
}
if (!valid) {
newVal = parseFloat(stringVal.slice(0, 0 - sliceAmount)); // slice last sliceAmount digits
parseVal = stringVal.slice(0, 0 - sliceAmount);
$timeout(function () {
ctrl.$setViewValue(attr.numberType === 'integer' ? parseInt(parseVal) : parseFloat(parseVal));
ctrl.$render();
}, 0);
}
return newVal;
}
function checkRequired(val) {
if (JSON.parse(attr.numberRequired)) {
if (ctrl.$isEmpty(val)) {
ctrl.$setValidity('required', false);
}
else if (!isNaN(val)) {
ctrl.$setValidity('required', true);
return val;
}
}
else {
ctrl.$setValidity('required', true);
return val;
}
}
}
};
}])
.directive('numberInput', ['i18nService', function (i18nService) {
return {
restrict: 'A',
require: 'ngModel',
scope: {
min: '@',
max: '@',
precision: '@',
numberType: '@'
},
link: function (scope, element, attrs, ctrl) {
var min = parseFloat(attrs.min);
var max = parseFloat(attrs.max);
var precision = parseInt(attrs.precision);
if (isNaN(precision)) {
precision = 0;
}
var step = Math.pow(10, -precision);
var numberType = attrs.numberType;
element.numericSpinner({
step: step,
spin: function (event, ui) {
var newValue = ui.value;
// min/max limits are enforced here because
// ui.spinner has issues with extreme max and min values
if (newValue > max) {
newValue = max;
}
if (newValue < min) {
newValue = min;
}
ctrl.$setViewValue(newValue);
scope.$apply();
}
});
ctrl.$formatters.unshift(function () {
var floatValue = parseFloat(ctrl.$modelValue);
if (isNaN(floatValue)) {
return ctrl.$modelValue;
}
else {
return floatValue.toFixed(precision);
}
});
// this fix triggers validation on clearing of required input
var keyUpHandler = function (numberInput, digits) {
if (digits.length === 1 && digits[0] === '') {
ctrl.$setViewValue('');
scope.$apply();
}
};
var radixPoint = i18nService.language === 'de' ? ',' : '.';
switch (numberType) {
case 'integer':
element.inputmask('integer', { rightAlign: false, onKeyUp: keyUpHandler });
break;
case 'decimal':
element.inputmask('decimal', {
rightAlign: false,
skipRadixDance: true,
radixPoint: radixPoint,
digits: precision,
onKeyUp: keyUpHandler
});
break;
case 'real':
element.inputmask('real', {
rightAlign: false,
skipRadixDance: true,
radixPoint: radixPoint,
digits: precision,
onKeyUp: keyUpHandler
});
break;
}
}
};
}])
.directive('menuCustomField', ['customFieldLinkFunction', 'screenConfigurationModel', 'screenConfigurationService',
'metadataModel', 'objectValueMapperService', '$filter', 'events', '$timeout',
function (customFieldLinkFunction, screenConfigurationModel, screenConfigurationService, metadataModel, objectValueMapperService, $filter, events, $timeout) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
context: '=',
isEditable: '=',
isNew: '=?',
getFieldValue: '&',
onSelectCb: '&',
isHideLabel: '='
},
templateUrl: 'views/field-customization/custom-fields/menu-custom-field.html',
link: function (scope) {
customFieldLinkFunction(scope);
var field = scope.data, context = scope.context, contextType = context && context.ticketType === EntityVO.TYPE_ASSET ? context.ticketType : context.type, classId = context && context.ticketType === EntityVO.TYPE_ASSET ? context.classId : null;
scope.getCustomFieldFieldValue = scope.getFieldValue();
scope.onSelectCb = scope.onSelectCb() ? scope.onSelectCb() : angular.noop;
scope.state = {
loading: false
};
var tooltipPromise;
if (field.name == 'company') {
field.isLocationCompany = true;
}
scope.$watch('data.setValueFlag', function (value) {
if (value !== '#$#') {
if (!_.isEmpty(value)) {
scope.data.setValue(value);
scope.data.setLinkedFieldValue(value);
//Todo: fetch corresponding field option from backend by passing the menu name and value and set them correctly
/*scope.state.loading = true;
return scope.loadDynamicSelectionValues(value)
.then(function (resp) {
var selectedOption = _.find(resp, function (option) {
return option.name === value || option.label === value;
});
if (selectedOption) {
scope.selectItem(selectedOption);
}
}).finally(function () {
scope.state.loading = false;
scope.data.setValueFlag = '#$#';
})*/
}
else {
scope.state.loading = false;
scope.data.clearValue();
scope.data.clearLinkedFieldValue();
}
scope.onFieldValueChange();
scope.data.setValueFlag = '#$#';
}
});
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
metadataModel.getMetadataByType(EntityVO.TYPE_GLOBAL).then(function (metadata) {
if (metadata.configurationParameters.CustomizationTypeaheadLength) {
scope.typeaheadMinLength = parseInt(metadata.configurationParameters.CustomizationTypeaheadLength);
}
else {
scope.typeaheadMinLength = 3;
}
});
scope.loadDynamicSelectionValues = function (searchText) {
return metadataModel.getMetadataByType(contextType).then(function (metadata) {
var dependencies = {};
if (contextType === EntityVO.TYPE_TASK || contextType === EntityVO.TYPE_WORKORDER) {
var locationCompany = context.locationCompany;
}
//For new customization types we need to get dependency values from objectValueMapperService as data in context is stale
if (_.includes(EntityVO.ENTITIES_WITH_NEW_CUSTOMIZATION, contextType)) {
_.forEach(field.dependency, function (dependentField) {
var fieldObj = objectValueMapperService.getFieldByName(dependentField.name);
dependencies[dependentField.name] = objectValueMapperService.getExactValueByFieldName(dependentField.name) || null;
//since there is no locationcompnay field for Incident create, we need to use the customer company value
if (!fieldObj && dependentField.name === 'locationCompany') {
fieldObj = objectValueMapperService.getFieldByName('company');
dependencies[dependentField.name] = objectValueMapperService.getExactValueByFieldName('company');
if (dependencies[dependentField.name] === '') {
dependencies[dependentField.name] = locationCompany;
}
}
if (fieldObj && fieldObj.dataType === 'dropdown') {
if (fieldObj.options && fieldObj.options.length > 0) {
_.forEach(fieldObj.options, function (option) {
if (option.name === dependencies[dependentField.name]) {
dependencies[dependentField.name] = option.index;
}
});
}
}
else if (fieldObj && fieldObj.dataType === 'widget' && fieldObj.members.length && fieldObj.members[0].dataType === 'dropdown') {
if (fieldObj.members[0].options && fieldObj.members[0].options.length > 0) {
_.forEach(fieldObj.members[0].options, function (option) {
if (option.name === dependencies[dependentField.name]) {
dependencies[dependentField.name] = option.index;
}
});
}
}
});
}
else {
_.forEach(field.dependency, function (dependentField) {
dependencies[dependentField.name] = scope.getCustomFieldFieldValue(dependentField.name); //get value for custom field (lookup in fieldsConfig and in context.customFields.fieldName)
if (_.isUndefined(dependencies[dependentField.name]) && contextType !== 'asset') {
//Warning:: Special handling for fields done here, but should have been handled by backend
//As agreed backend will either send the field and metadata mapping or accept the name in the field object for dependencies on dropdown fields
//e.g. In the menu/expand/ call we will send {priority: "High"} instead of {priority: 2}
//Due to time constraints this was hardcoded in UC instead of backend handling
var specialFieldsList = [EntityVO.TYPE_PRIORITY, EntityVO.TYPE_URGENCY, EntityVO.TYPE_IMPACT, EntityVO.TYPE_STATUS];
dependencies[dependentField.name] = screenConfigurationService.getContextPropertyByMetadataMapping(context, metadata, dependentField.name, scope.isNew) || null;
if (dependencies[dependentField.name] !== null && dependencies[dependentField.name] !== undefined
&& (contextType === EntityVO.TYPE_KNOWNERROR || contextType === EntityVO.TYPE_PROBLEM)
&& _.includes(specialFieldsList, dependentField.name)) {
var optionsList;
switch (dependentField.name) {
case EntityVO.TYPE_PRIORITY:
optionsList = metadata.priorities;
break;
case EntityVO.TYPE_URGENCY:
optionsList = metadata.urgencies;
break;
case EntityVO.TYPE_IMPACT:
optionsList = metadata.impacts;
break;
case EntityVO.TYPE_STATUS:
optionsList = metadata.statuses;
break;
default:
optionsList = [];
break;
}
if (optionsList.length) {
dependencies[dependentField.name] = _.result(_.find(optionsList, { 'name': dependencies[dependentField.name] }), 'index');
}
}
}
else if (_.isUndefined(dependencies[dependentField.name]) && contextType === 'asset') {
//DRSMX-66920 : Menu dependency in SmartIT not working as expected
//When dependent field names are different than the field names coming in the asset metaData, backend is expecting to pass the dependent fieldNames as per metaData
var metaDataKey = metadata && metadata.ootbMapping && metadata.ootbMapping[dependentField.name] && metadata.ootbMapping[dependentField.name][0];
if (metaDataKey && metaDataKey !== dependentField.name) {
var dependentFieldValue = screenConfigurationService.getContextPropertyByMetadataMapping(context, metadata, dependentField.name);
if (!dependentFieldValue && metaDataKey === 'companyName') {
dependentFieldValue = context && context.company && context.company.name ? context.company.name : '';
}
else if (!dependentFieldValue && metaDataKey === 'siteGroup') {
dependentFieldValue = context && context.site && context.site.siteGroup ? context.site.siteGroup : '';
}
else if (!dependentFieldValue && metaDataKey === 'siteName') {
dependentFieldValue = context && context.site && context.site.name ? context.site.name : '';
}
else if (!dependentFieldValue && metaDataKey === 'siteRegion') {
dependentFieldValue = context && context.site && context.site.region ? context.site.region : '';
}
delete dependencies[dependentField.name];
dependencies[metaDataKey] = dependentFieldValue ? dependentFieldValue : null;
}
else {
dependencies[dependentField.name] = screenConfigurationService.getContextPropertyByMetadataMapping(context, metadata, dependentField.name);
}
}
});
}
var hasCreateScreen = scope.isNew && _.includes([EntityVO.TYPE_PROBLEM, EntityVO.TYPE_KNOWNERROR], contextType) ? false : scope.isNew;
return screenConfigurationModel.loadDynamicSelectionFieldLabels(contextType, field.menu, searchText, dependencies, classId, field.name, hasCreateScreen).then(function (data) {
if (tooltipPromise) {
$timeout.cancel(scope.tooltipPromise);
}
scope.exceedsChunkSize = data.exceedsChunkSize;
scope.state.isTooltipOpen = data.exceedsChunkSize;
tooltipPromise = $timeout(function () {
scope.state.isTooltipOpen = false;
}, 10000);
return data.items;
});
}).finally(function () {
scope.state.loading = false;
});
};
scope.onInputFocusBlur = function () {
scope.state.isTooltipOpen = false;
};
scope.selectItem = function (option) {
var newFieldValue;
if (!_.isEmpty(option)) {
if (field.name === 'assignee' || field.name === 'assigneeName' || field.name === 'managerName') {
newFieldValue = option.label;
field.assigneeLoginId = option.value;
}
else {
//handle 'case 3', option -> {label: 'aaa', value: 'bbb'} && _.isUndefined(field.valueField) == true -> set value instead of label to field
newFieldValue = (!field.valueField && option.value) ? option.value : option.label;
}
field.setValue(newFieldValue);
field.setLinkedFieldValue(option.value);
if (_.includes(EntityVO.ENTITIES_WITH_NEW_CUSTOMIZATION, contextType) && field.valueField) {
objectValueMapperService.setByProperty(field.valueField, 'value', option.value);
}
scope.$emit(events.CLEAR_DEPENDANT_FIELDS, field.name);
}
else {
field.clearValue();
field.clearLinkedFieldValue();
if (_.includes(EntityVO.ENTITIES_WITH_NEW_CUSTOMIZATION, contextType) && field.valueField) {
objectValueMapperService.setByProperty(field.valueField, 'value', '');
}
}
scope.onFieldValueChange();
scope.onSelectCb();
scope.$emit(events.CUSTOM_FIELD_VALUE_CHANGE);
};
}
};
}])
.directive('groupCustomField', ['customFieldLinkFunction', 'events', 'screenConfigurationService', 'metadataModel', '$filter', 'objectValueMapperService',
function (customFieldLinkFunction, events, screenConfigurationService, metadataModel, $filter, objectValueMapperService) {
return {
restrict: 'E',
replace: true,
scope: {
data: '=',
context: '=',
getFieldValue: '&',
isNew: '=?',
isHideLabel: '='
},
templateUrl: 'views/field-customization/custom-fields/group-custom-field.html',
controller: 'LaunchActionController',
link: function (scope) {
var context = scope.context, contextType = context && context.ticketType === EntityVO.TYPE_ASSET ? context.ticketType : context.type;
customFieldLinkFunction(scope);
scope.$watch('$parent.editMode', function (newValue) {
scope.editMode = newValue;
}, true);
scope.$watch('context', function () {
scope.checkEditable();
}, true);
scope.getFieldValue = scope.getFieldValue();
scope.isEditable = function (field) {
if (scope.context.type === EntityVO.TYPE_ASSET) {
return !field.isReadOnly;
}
else {
return field.isEditable(scope.context.accessMappings);
}
};
if (scope.isHideLabel) {
scope.tooltipToShow = $filter('customFieldLabelI18n')(scope.data);
}
scope.clearDependantFieldValues = function (event, fieldName) {
_.forEach(scope.data.members, function (groupField) {
if (!groupField.dependency || !groupField.dependency.length) {
groupField.groupEditable = true;
return;
}
else if (_.findIndex(groupField.dependency, { name: fieldName }) > -1) {
groupField.clearValue();
groupField.clearLinkedFieldValue();
scope.onFieldValueChange(groupField);
}
});
};
//todo: minimize calls of function (tier3 changed -> no need to check editability of tier1)
scope.checkEditable = function () {
var editGroup = true;
metadataModel.getMetadataByType(contextType).then(function (metadata) {
_.forEach(scope.data.members, function (groupField) {
if (!groupField.dependency || !groupField.dependency.length) {
groupField.groupEditable = true;
return;
}
_.forEach(groupField.dependency, function (dependency) {
if (!scope.getFieldValue(dependency.name)) {
var fieldValue = objectValueMapperService.getExactValueByFieldName(dependency.name);
if (!fieldValue) {
editGroup = false;
}
}
});
if (!editGroup) {
groupField.groupEditable = false;
groupField.clearValue();
groupField.clearLinkedFieldValue();
scope.onFieldValueChange(groupField);
}
else {
groupField.groupEditable = true;
}
});
});
};
scope.checkEditable();
scope.$on(events.REFRESH_FIELD_VALUES, scope.checkEditable);
scope.$on(events.CLEAR_DEPENDANT_FIELDS, scope.clearDependantFieldValues);
}
};
}]);
}());