SmartIT_Extensions/BMC/smart-it-full-helix/scripts/app/admin/screen-configuration/screen-configuration-model.js

1376 lines
70 KiB
JavaScript

"use strict";
/**
* Created by igor.samulenko on 4/29/2014.
*/
(function () {
'use strict';
angular.module('adminModule')
.factory('screenConfigurationModel', ['$q', 'screenConfigurationService', 'configurationModel', 'i18nService', 'pwaModel',
function ($q, screenConfigurationService, configurationModel, i18nService, pwaModel) {
var screenConfigurationModel = {
appConfig: null,
screenList: null,
screensCacheByName: {},
fieldList: null,
fieldLabels: null,
selectedFieldList: null,
actionList: null,
actionOrder: 'custom',
actionUrlParams: null,
availableFieldsCache: {},
runtimeActionsCache: {},
dynamicSelectionFieldLabelsCache: {},
providerPromise: {},
providerHardReload: true,
allFieldsLoaded: {
basicTab: false,
datesTab: false
}
}, customLabelPromise = null, configByNamePromise = {}, fieldLabelDictionary = {}, screenTypeMap = {
incident: ScreenConfigurationVO.prototype.INCIDENT_VIEW_SCREEN,
workorder: ScreenConfigurationVO.prototype.WORK_ORDER_VIEW_SCREEN,
task: ScreenConfigurationVO.prototype.TASK_VIEW_SCREEN,
person: ScreenConfigurationVO.prototype.PERSON_DETAILS_SCREEN,
change: ScreenConfigurationVO.prototype.CHANGE_VIEW_SCREEN,
problem: ScreenConfigurationVO.prototype.PROBLEM_DETAILS_SCREEN,
knownerror: ScreenConfigurationVO.prototype.KNOWN_ERROR_DETAILS_SCREEN,
asset: ScreenConfigurationVO.prototype.ASSET_SCREEN,
create: {
incident: ScreenConfigurationVO.prototype.CREATE_INCIDENT_SCREEN,
change: ScreenConfigurationVO.prototype.CREATE_CHANGE_SCREEN,
workorder: ScreenConfigurationVO.prototype.CREATE_WORK_ORDER_SCREEN,
task: ScreenConfigurationVO.prototype.CREATE_TASK_SCREEN
}
}, dataSourceMap = {
incident: EntityVO.TYPE_INCIDENT,
workorder: EntityVO.TYPE_WORKORDER,
task: EntityVO.TYPE_TASK,
person: 'Person',
change: EntityVO.TYPE_CHANGE,
problem: EntityVO.TYPE_PROBLEM,
knownerror: EntityVO.TYPE_KNOWNERROR,
asset: 'Asset'
};
// editor actions
var ACTION_CREATE = 'create', ACTION_UPDATE = 'update', ACTION_REMOVE = 'remove';
/**
* Public functions
*/
/**
* Loads screen configuration
*/
var screenConfigurationPromise = $q.defer();
screenConfigurationModel.loadConfiguration = function () {
screenConfigurationModel.appConfig = {};
screenConfigurationModel.screenList = [];
// Using fromConfig flag, required by backend since this call is used
// only on screen configuration
return screenConfigurationService.loadConfiguration({ fromConfig: true })
.then(handleConfigurationLoadSuccess);
};
/**
* Get screen configuration for specific screen by name
* @param {string} screenName - name of the screen to load
* @param {boolean} force - if true, will enforce request for screen configuration to be sent
* @param {object} options - additional request params
* @return {Promise}
*/
screenConfigurationModel.loadScreenConfigurationByName = function (screenName, force, options) {
var cachedScreen = force ? angular.noop() : getScreenByName(screenName), screenPromise;
if (cachedScreen) {
screenPromise = $q.when(cachedScreen);
}
else {
if (!configByNamePromise[screenName]) {
configByNamePromise[screenName] = screenConfigurationService.loadScreenConfigurationByName(screenName, options)
.then(function (screenConfig) {
screenConfigurationModel.screensCacheByName[screenName] = screenConfig.screens[0];
screenConfigurationModel.screenList = _.reject(screenConfigurationModel.screensCacheByName, function (screen) {
return screen.datasource !== 'Person' && !configurationModel.isServerApplicationEnabled(screen.datasource.toLowerCase());
});
configByNamePromise[screenName] = null;
return angular.copy(screenConfigurationModel.screensCacheByName[screenName]);
});
}
screenPromise = configByNamePromise[screenName];
}
return screenPromise;
};
screenConfigurationModel.loadScreenConfigurationAndCustomFieldLabels = function (screenName, ticketType, force) {
var deferred = $q.defer();
screenConfigurationModel.loadScreenConfigurationByName(screenName, force)
.then(function () {
return screenConfigurationModel.loadFieldsLabels(ticketType);
})
.finally(function () {
deferred.resolve();
});
return deferred.promise;
};
/**
* Refreshes metadata for specific datasource
*
* @param {String} datasource
* @param {String} screenName - optional parameter, used for screens that support v2 calls only
* @returns {*}
*/
screenConfigurationModel.refreshMetadataForDatasource = function (datasource, screenName) {
var params = {
datasource: datasource
};
if (screenName) {
params.screen = screenName;
}
var refreshMeta = function () {
if (fieldLabelDictionary[datasource]) {
delete fieldLabelDictionary[datasource];
}
};
if (screenConfigurationModel.isV2CompatibleScreen(screenName)) {
return screenConfigurationService.refreshMetadataV2(params).then(refreshMeta);
}
else {
return screenConfigurationService.refreshMetadata(params).then(refreshMeta);
}
};
/**
* Loads field data required for custom area editor
* @param panel
* @returns {*}
*/
screenConfigurationModel.loadFields = function (panel) {
var availableFieldListPromise = screenConfigurationModel.loadAvailableFieldList(panel), selectedFieldListPromise = screenConfigurationModel.loadSelectedFieldList(panel);
return $q.all([availableFieldListPromise, selectedFieldListPromise]);
};
/**
* Loads list of fields available for selection
* @param {PanelVO} panel
*/
screenConfigurationModel.loadAvailableFieldList = function (panel) {
var query = { datasource: panel.dataSource }, promise;
if (panel.dataSource === 'Asset') {
query.assetType = panel.shortId;
if (panel.shortId === 'typeSpecific') {
query.classId = panel.classId;
}
}
if (screenConfigurationModel.isV2CompatibleScreen(panel.parentScreenName)) {
query.screen = panel.parentScreenName;
promise = screenConfigurationService.loadAvailableFieldListV2(query);
}
else {
promise = screenConfigurationService.loadAvailableFieldList(query);
}
return promise.then(handleAvailableFieldListLoadSuccess);
};
/**
* Loads available fields list for four new screens introduced in v2.0.
* @returns {Array<FieldVO>} - list of
*/
screenConfigurationModel.loadAvailableFieldListForAllNewScreens = function (force) {
var screensData = [];
if (configurationModel.isServerApplicationEnabled(EntityVO.TYPE_INCIDENT)) {
screensData.push({ datasource: EntityVO.TYPE_INCIDENT, screen: ScreenConfigurationVO.prototype.INCIDENT_VIEW_SCREEN }, { datasource: EntityVO.TYPE_INCIDENT, screen: ScreenConfigurationVO.prototype.CREATE_INCIDENT_SCREEN });
}
if (configurationModel.isServerApplicationEnabled(EntityVO.TYPE_CHANGE)) {
screensData.push({ datasource: EntityVO.TYPE_CHANGE, screen: ScreenConfigurationVO.prototype.CHANGE_VIEW_SCREEN }, { datasource: EntityVO.TYPE_CHANGE, screen: ScreenConfigurationVO.prototype.CREATE_CHANGE_SCREEN });
}
if (configurationModel.isServerApplicationEnabled(EntityVO.TYPE_WORKORDER)) {
screensData.push({ datasource: EntityVO.TYPE_WORKORDER, screen: ScreenConfigurationVO.prototype.WORK_ORDER_VIEW_SCREEN }, { datasource: EntityVO.TYPE_WORKORDER, screen: ScreenConfigurationVO.prototype.CREATE_WORK_ORDER_SCREEN });
}
if (configurationModel.isServerApplicationEnabled(EntityVO.TYPE_TASK)) {
screensData.push({ datasource: EntityVO.TYPE_TASK, screen: ScreenConfigurationVO.prototype.TASK_VIEW_SCREEN }, { datasource: EntityVO.TYPE_TASK, screen: ScreenConfigurationVO.prototype.CREATE_TASK_SCREEN });
}
var promises = {};
if (force) {
screensData.forEach(function (screenData) {
promises[screenData.screen] = screenConfigurationService.loadAvailableFieldListV2(screenData)
.then(function (availableFields) {
screenConfigurationModel.availableFieldsCache[screenData.screen] = availableFields;
});
});
}
else {
promises = [$q.when(screenConfigurationModel.availableFieldsCache)];
}
return $q.all(promises).then(function () {
return angular.copy(screenConfigurationModel.availableFieldsCache);
});
};
/**
* Loads Actions and Url params w.r.t to resource
* @param resourceType
*/
screenConfigurationModel.loadActions = function (resourceType) {
return screenConfigurationService.loadActions({ resourceType: resourceType }).then(handleActionsLoadSuccess);
};
screenConfigurationModel.loadActionUrlParams = function (resourceType) {
return screenConfigurationService.loadActionUrlParams({ resourceType: resourceType }).then(handleActionUrlParamsLoadSuccess);
};
/**
* Loads Actions V2 and Url params w.r.t to resource
* @param resourceType
*/
screenConfigurationModel.loadActionsNew = function (resourceType) {
if (!screenConfigurationModel.providerPromise[resourceType] || screenConfigurationModel.providerHardReload) {
screenConfigurationModel.providerPromise[resourceType] = screenConfigurationService.loadActionsNew({ resourceType: resourceType }).then(handleActionsLoadSuccess);
screenConfigurationModel.providerHardReload = false;
return screenConfigurationModel.providerPromise[resourceType];
}
else {
return screenConfigurationModel.providerPromise[resourceType];
}
};
/**
* Loads list of selected fields
* @param {PanelVO} panel
*/
screenConfigurationModel.loadSelectedFieldList = function (panel) {
var query = {
datasource: panel.dataSource
};
if (panel.dataSource === 'Asset') {
query.assetType = panel.shortId;
if (panel.shortId === 'typeSpecific') {
query.classId = panel.classId;
}
}
return screenConfigurationService.loadSelectedFieldList(query).then(handleSelectedFieldListLoadSuccess);
};
/**
* Loads fields labels
* @param {String} ticketType
*/
screenConfigurationModel.loadFieldsLabels = function (ticketType) {
var editTicketScreenName = screenTypeMap[ticketType], createTicketScreenName = screenTypeMap.create[ticketType];
var screen = _.find(screenConfigurationModel.screensCacheByName, function (scr) {
return [editTicketScreenName, createTicketScreenName].indexOf((scr || {}).name) !== -1;
});
var promise = $q.when(1);
if (screen) {
var dataSource = screen.datasource, cachedLabels = fieldLabelDictionary[dataSource];
if (cachedLabels) {
handleFieldLabelsLoadSuccess(cachedLabels, dataSource);
}
else {
if (customLabelPromise === null) {
customLabelPromise = screenConfigurationService
.loadFieldsLabels({ datasource: dataSource })
.then(function (labels) {
handleFieldLabelsLoadSuccess(labels, dataSource);
customLabelPromise = null;
return screenConfigurationModel.fieldLabels;
});
}
promise = customLabelPromise;
}
}
else {
console.log('Warning: screen configuration for ' + ticketType + ' not found.');
}
return promise;
};
screenConfigurationModel.loadMockDependantFieldMappings = function () {
return screenConfigurationService.loadMockDependantFieldMappings();
};
/**
* Loads fields labels
* @param {String} ticketType
* @param {String} menuName
* @param {Object} params
* @param {Object} dependencies
*/
screenConfigurationModel.loadDynamicSelectionFieldLabels = function (ticketType, menuName, searchText, dependencies, classId, fieldName, isNew, useChunk) {
var screen = getScreenForTicketType(isNew ? ('create.' + ticketType) : ticketType), params = {
datasource: screen ? screen.datasource : ticketType,
menuName: menuName,
searchText: searchText
};
function escapeRegExp(string) {
return string.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
if (classId) {
params.classId = classId;
}
if (screen) {
var dynamicFieldCache = screenConfigurationModel.dynamicSelectionFieldLabelsCache[fieldName];
useChunk = dynamicFieldCache && dynamicFieldCache.searchData && dynamicFieldCache.searchData.exceedsChunkSize ? true : useChunk;
// If chunk size exceeds, new call should be made for any non-matching text
if (!useChunk && angular.isDefined(dynamicFieldCache)
&& ((!dynamicFieldCache.searchData.exceedsChunkSize && _.startsWith(searchText, dynamicFieldCache.searchText))
|| (dynamicFieldCache.searchData.exceedsChunkSize && searchText === dynamicFieldCache.searchText))) {
if (dynamicFieldCache.datasource === params.datasource && _.isEqual(dependencies, dynamicFieldCache.dependencies)) {
var searchData = _.cloneDeep(dynamicFieldCache.searchData), escaped = escapeRegExp(searchText), formatted = escaped.replace(/%/g, '.*');
formatted = '.*' + formatted + '.*';
formatted = new RegExp('^' + formatted + '$', 'im');
var searchItemList = void 0;
if (searchData && Array.isArray(searchData)) {
searchItemList = searchData;
}
else if (searchData && searchData.items && Array.isArray(searchData.items)) {
searchItemList = searchData.items;
}
_.remove(searchItemList, function (field) {
//To support search using wildcard '%' also.
if (!field.displayLabel.match(formatted) && !field.value.match(formatted)) {
return true;
}
});
return $q.when(searchData);
}
}
return screenConfigurationService.loadDynamicSelectionFieldLabels(params, dependencies).then(function (data) {
screenConfigurationModel.dynamicSelectionFieldLabelsCache[fieldName] = {
searchText: searchText,
searchData: data,
datasource: params.datasource,
dependencies: dependencies
};
return { items: data.items, exceedsChunkSize: data.exceedsChunkSize };
});
}
else {
console.log('Warning: screen configuration for ' + ticketType + ' not found.');
return $q.reject();
}
};
/**
* Helper method, which marks fields as updated. Used for v2 customization save call
* @param {FieldVO} field
* @param {PanelVO} panel
*/
screenConfigurationModel.markFieldUpdated = function (field, panel) {
var isNewField = !field.id || panel.addedFields.some(function (aField) {
return field.id === aField.id;
});
if (!isNewField) {
field.wasUpdated = true;
}
};
/**
* Checks whether particular screen supports v2 res calls
*
* @param {string} screenName - name of the screen
* @returns {boolean}
*/
screenConfigurationModel.isV2CompatibleScreen = function (screenName) {
return ScreenConfigurationVO.prototype.isV2Compatible(screenName);
};
/**
* Saves custom field configuration for panel
* @param {PanelVO} panel
*/
screenConfigurationModel.savePanelConfiguration = function (panel) {
var updatedFields = [], addedFields = [], removedFields = [], useV2Flow = screenConfigurationModel.isV2CompatibleScreen(panel.parentScreenName);
if (useV2Flow) {
var fields = getPanelUpdatedFieldsForV2Call(panel);
fields.forEach(function (field) {
addUpdatedField(field, panel);
});
}
else {
// update field ordering
panel.fields.forEach(function (field, index) {
var members = [];
field.displayOrder = index;
field.groupMember = false;
if (field.dependency) {
for (var j = 0; j < field.dependency.length; j++) {
delete field.dependency[j].availability;
delete field.dependency[j].fieldUnavailableOn;
}
}
// Handle group fields, but skip this if field is a widget
if (!field.isWidget()) {
field.members.forEach(function (gfield, gindex) {
var temp = { "name": gfield.name };
gfield.displayOrder = gindex;
gfield.groupMember = true;
if (gfield.dependency) {
for (var j = 0; j < gfield.dependency.length; j++) {
delete gfield.dependency[j].availability;
delete gfield.dependency[j].fieldUnavailableOn;
}
}
if (gfield.id) {
addUpdatedField(gfield, panel);
if (gfield.current) {
temp = gfield.current;
}
}
members.push(temp);
});
field.members = members;
}
if (field.id) {
addUpdatedField(field, panel);
}
});
}
function addUpdatedField(field, panel) {
if (panel.shortId !== 'typeSpecific') {
delete field.extension;
}
if (useV2Flow) {
updatedFields.push(angular.extend({
state: ACTION_UPDATE,
screenId: panel.parentScreenId,
screenName: panel.parentScreenName,
panelId: panel.id,
panelName: panel.name,
datasource: panel.dataSource
}, new GalileoFieldV2VO().build(field)));
}
else {
updatedFields.push(angular.extend({
state: ACTION_UPDATE,
areaId: panel.id
}, new GalileoFieldVO().build(field)));
}
}
if (useV2Flow) {
addedFields = getPanelAddedFieldsForV2Call(panel);
removedFields = getPanelRemovedFieldsForV2Call(panel);
}
else {
addedFields = panel.addedFields.map(function (field) {
var newField;
if (panel.shortId !== 'typeSpecific') {
delete field.extension;
}
newField = angular.extend({
state: ACTION_CREATE,
areaId: panel.id
}, new GalileoFieldVO().build(field));
return newField;
});
removedFields = panel.removedFields.map(function (field) {
var removedField;
if (panel.shortId !== 'typeSpecific') {
delete field.extension;
}
removedField = angular.extend({
state: ACTION_REMOVE,
areaId: panel.id
}, new GalileoFieldVO().build(field));
return removedField;
});
}
if (!useV2Flow) {
addedFields.forEach(function (field, index) {
var fieldIndex = _.findIndex(updatedFields, { name: field.name });
if (fieldIndex != -1) {
updatedFields = _.slice(updatedFields, 0, fieldIndex);
}
});
}
var saveFieldConfiguration = useV2Flow ? screenConfigurationService.saveFieldConfigurationV2 : screenConfigurationService.saveFieldConfiguration;
return saveFieldConfiguration([].concat(removedFields, addedFields, updatedFields), panel.shortId)
.catch(function (e) {
throw e;
})
.finally(function () {
screenConfigurationModel.clearActionsListCacheForType(panel.dataSource.toLowerCase());
});
};
function getPanelFieldsV2Call(panel, action) {
var fields = [];
if (action === ACTION_CREATE) {
fields = panel.addedFields;
}
else if (action === ACTION_REMOVE) {
fields = panel.removedFields;
}
return fields.reduce(function (acc, field) {
var fieldCopy = _.cloneDeep(field);
if (field.isGroupField()) {
// Should use original members list for remove action, because user can firs remove group members
// manually and then remove group, so members array will be empty, which is wrong
var groupMembers = (action === ACTION_REMOVE) ? field.initialMembers : field.members;
fieldCopy.members = groupMembers.map(function (member) {
return new GalileoFieldV2VO().build(member);
});
}
// Don't need to send group members separately.
// Group field members array will be used on the backend
if (!field.isGroupMember()) {
acc.push(angular.extend({
state: action,
screenId: panel.parentScreenId,
screenName: panel.parentScreenName,
panelId: panel.id,
panelName: panel.name,
datasource: panel.dataSource
}, new GalileoFieldV2VO().build(fieldCopy)));
}
return acc;
}, []);
}
function getPanelAddedFieldsForV2Call(panel) {
return getPanelFieldsV2Call(panel, ACTION_CREATE);
}
function getPanelRemovedFieldsForV2Call(panel) {
return getPanelFieldsV2Call(panel, ACTION_REMOVE);
}
function getPanelUpdatedFieldsForV2Call(panel) {
return panel.fields.reduce(function (acc, field, index) {
var fieldMembers = [];
if (field.displayOrder !== index) {
field.displayOrder = index;
screenConfigurationModel.markFieldUpdated(field, panel);
}
if (field.dependency) {
for (var j = 0; j < field.dependency.length; j++) {
delete field.dependency[j].availability;
delete field.dependency[j].fieldUnavailableOn;
}
}
// Handle group fields, but skip this if field is a widget
if (field.isGroupField()) {
fieldMembers = field.members.map(function (gfield, gindex) {
if (gfield.displayOrder !== gindex) {
gfield.displayOrder = gindex;
screenConfigurationModel.markFieldUpdated(gfield, panel);
}
if (gfield.dependency) {
for (var j = 0; j < gfield.dependency.length; j++) {
delete gfield.dependency[j].availability;
delete gfield.dependency[j].fieldUnavailableOn;
}
}
if (!gfield.id || gfield.wasUpdated) {
screenConfigurationModel.markFieldUpdated(field, panel);
}
return new GalileoFieldV2VO().build(gfield);
});
}
if (field.id && field.wasUpdated) {
var fieldCopy = _.cloneDeep(field);
fieldCopy.members = fieldMembers;
acc.push(fieldCopy);
}
return acc;
}, []);
}
/**
* Saves custom action configuration
* @param {PanelVO} panel
*/
screenConfigurationModel.saveActionConfiguration = function (actionList, actionOrder) {
var actionObj = {
actionOrder: actionOrder,
actionList: []
};
actionList.forEach(function (action) {
delete action.isOpen;
actionObj.actionList.push(action);
});
return screenConfigurationService.saveActionConfiguration(actionObj).then(handleActionsLoadSuccess);
};
/**
+ * Saves custom action configuration V2
+ * @param {PanelVO} panel
+
*/
screenConfigurationModel.saveFieldConfigurationV2 = function (actionList, actionOrder) {
var actionObj = {
actionOrder: actionOrder,
actionList: []
};
actionList.forEach(function (action) {
delete action.isOpen;
actionObj.actionList.push(action);
});
return screenConfigurationService.saveFieldConfigurationV2(actionObj).then(handleActionsLoadSuccess);
};
/**
* Finds a panel with specified name
* @param {String} panelId
*/
screenConfigurationModel.getPanelById = function (panelId) {
var screenName = panelId.split('.')[0];
var panelName = panelId.split('.')[1];
var screen = getScreenByName(screenName);
return screen ? screen.getPanelByName(panelName) : null;
};
/**
* Get list of editable fields for screen with specified name
* @param {String} screenName
* @return {Array} fields
*/
screenConfigurationModel.getEditableFieldsForScreen = function (screenName) {
var screen = getScreenByName(screenName);
return _.filter(screen ? screen.getFields() : [], { editable: true });
};
/**
* Get list of required fields for screen with specified name
* @param {String} screenName
* @return {Array} fields
*/
screenConfigurationModel.getRequiredFieldsForScreen = function (screenName) {
var screen = getScreenByName(screenName);
return _.filter(screen ? screen.getFields() : [], { required: true });
};
/**
* Get list of available fields for screen with specified name
* @param screenName
* @param {Array<FieldVO>} availableFields - optional param of available fields to build list from
* @return {Array} fields
*/
screenConfigurationModel.getAvailableFieldsForScreen = function (screenName, availableFields) {
var screen = getScreenByName(screenName);
var fields = screen ? screen.getFields() : [];
return (availableFields || screenConfigurationModel.fieldList).filter(function (field) {
return !_.filter(fields, { name: field.name, dataType: field.dataType }).length;
});
};
/**
* Get list of available fields for screen with specified name
* @param screenName
* @return {Array} fields
*/
screenConfigurationModel.getFieldByName = function (screenName, fieldName) {
var screen = getScreenByName(screenName);
var fields = screen ? screen.getFields() : [];
return _.find(fields, { name: fieldName });
};
/**
* Get list of available fields for screen with specified name and classId
* @param screenName, classId
* @return {Array} fields
*/
screenConfigurationModel.getAvailableFieldsForScreenByClassId = function (screenName, classId) {
var screen = getScreenByName(screenName);
var fields = screen ? screen.getFields() : [];
return screenConfigurationModel.fieldList.filter(function (field) {
var i, j;
var selectedfields = _.filter(fields, { name: field.name });
if (!selectedfields.length) {
return true;
}
else {
for (i = 0; i < selectedfields.length; i++) {
for (j = 0; j < selectedfields[i].extension.length; j++) {
if (selectedfields[i].extension[j].classId === classId.name) {
return false;
}
}
}
return true;
}
});
};
/**
* Get assignment panel descriptor
*
* @param ticket
* @returns {ScreenConfigurationVO}
*/
screenConfigurationModel.getAssignmentPanel = function (ticket) {
var panel;
if (ticket.type) {
var screen = getScreenForTicketType(ticket.type);
if (screen) {
panel = screen.getPanelByName('Assignment');
}
}
return panel || {};
};
/**
* Get Avialable accelerators V2
*
* @param type
* @param {String} screenName - screen name for accelerators
* @returns OOTB fields + avilable custom fields map
*/
screenConfigurationModel.getAccelerators = function (type, screenName) {
var promise;
// if (screenConfigurationModel.isV2CompatibleScreen(screenName) && ([ScreenConfigurationVO.prototype.WORK_ORDER_VIEW_SCREEN, ScreenConfigurationVO.prototype.TASK_VIEW_SCREEN].indexOf(screenName) === -1)) {
if (screenConfigurationModel.isV2CompatibleScreen(screenName)) {
promise = screenConfigurationService.getNewAcceleratorsByType({
datasource: type,
screen: screenName
}).then(function (data) {
return data;
});
}
else {
promise = screenConfigurationService.getAcceleratorsByType({ datasource: type }).then(function (data) {
return data;
});
}
return promise;
};
/**
* Collect field value changes
*
* @param {Array} changedFields
* @param {Object} originalFields
*/
screenConfigurationModel.collectChanges = function (changedFields, originalFields, ticket) {
var changes = {};
_.forEach(changedFields, function (field) {
var isGroupMember = field.isGroupMember();
if (field.editable || isGroupMember) {
var newValue = field.getValue(), oldValue = originalFields ? originalFields[field.name] : '', valueChanged = (isValid(newValue) && (newValue !== oldValue)) || (newValue === null && isValid(oldValue) && oldValue !== '');
if (valueChanged || isGroupMember) {
if (field.type === 'category') {
var category = getCategoryValue(newValue);
//Asset and knowledge needs to be handled separately as currently a seperate call is made to specially save
//their categories (at least for assets)
if (category) {
if (_.find(ticket.resCategorizations, { name: category.name })) {
if (changes.resCategorizations instanceof Array) {
changes.resCategorizations.push(category);
}
else {
changes.resCategorizations = [category];
}
}
else if (_.find(ticket.categorizations, { name: category.name })) {
if (changes.categorizations instanceof Array) {
changes.categorizations.push(category);
}
else {
changes.categorizations = [category];
}
}
}
}
else if (field.dataType === 'widget') {
_.forEach(field.members, function (member) {
changes[member.name] = field.value[member.name];
});
}
else {
changes[field.name] = newValue;
}
if (field.isMenuField() && newValue === '') { //special handling for menu fields, they cannot be '', null or menuItem
changes[field.name] = null;
}
if (field.linkedFieldExist()) {
changes[field.valueField] = field.getLinkedValue();
}
}
}
});
return changes;
};
screenConfigurationModel.composePanelId = function (ticketType, panelName) {
return screenConfigurationModel.getScreenNameByTicketType(ticketType) + '.' + panelName;
};
/**
* Init custom field values from ticket data
*
* @param {Array} fields
* @param {TicketVO} ticket
*/
screenConfigurationModel.initFieldValues = function (fields, ticket, metadata, fromAssignment) {
var ootbMappingKey, setValuesdefer = $q.defer(), noOfFieldsSet = 0;
if (fields && fields.length > 0) {
var fieldValues;
_.each(fields, function (field) {
if ((ticket.type === 'incident' || ticket.type === 'change') && field.name === 'summary') {
field.charLimit = 100;
}
else if (ticket.type === 'task' && field.name === 'summary') {
field.charLimit = 255;
}
if (field.isWidget()) {
field.label = i18nService.getLocalizedString('field.widget.' + field.name + '.label');
}
if (field.type === FieldVO.prototype.PERSON_NAME) {
var fieldName = field.name === 'requestedFor' ? 'customer' : field.name;
fieldValues = ticket[fieldName];
if (field.name === "contact") {
if (_.isEmpty(ticket[fieldName])) {
fieldValues = undefined;
}
}
else if (field.isAssigneeWidget()) {
field.primaryKey = getOotbPrimaryKeyForWidget(field, metadata);
fieldValues = ticket[field.primaryKey];
}
field.setValue(fieldValues);
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.PRIORITY) {
field.setValue({
impact: ticket.impact,
urgency: ticket.urgency,
priority: ticket.priority
});
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.TICKET_CLASS) {
field.setValue({
timing: ticket.timing,
timingReason: ticket.timingReason
});
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.AFFECTED_ASSET) {
fieldValues = {
'ci': ticket[field.name],
'company': ticket.company,
'customer': ticket.customer,
'ticketType': ticket.type
};
if (_.isEmpty(ticket[field.name]) || _.isEmpty(ticket[field.name].name)) {
fieldValues.ci = null;
}
field.setValue(fieldValues);
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.TICKET_LOCATION) {
if (ticket.location) {
fieldValues = {
'siteId': ticket.location.siteId,
'region': ticket.location.region,
'siteGroup': ticket.location.siteGroup,
'name': ticket.location.name,
'companyName': ticket.location.companyName,
'address': ticket.location.address
};
}
else {
fieldValues = {
'siteId': null,
'region': null,
'siteGroup': null,
'name': null,
'companyName': null,
'address': null
};
}
field.setValue(fieldValues);
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.IMPACTED_AREAS) {
field.setValue({ impactedAreas: ticket.impactedAreas });
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.CATEGORY_FIELD) {
field.setValue(_.findLast(_.cloneDeep(ticket.allCategories), { name: field.getCategorizationPropertyName() }));
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.PERSON_SITE) {
var siteInfo = _.cloneDeep(ticket.customer.site);
siteInfo = siteInfo ? siteInfo : {};
var siteValue = {
site: {
name: siteInfo.name,
id: siteInfo.siteId,
attributeMap: {
siteAddress: siteInfo.address,
regionName: siteInfo.region,
siteGroupName: siteInfo.siteGroup
}
},
siteGroup: {
name: siteInfo.siteGroup,
attributeMap: {
regionName: siteInfo.region
}
},
region: {
name: siteInfo.region
},
company: ticket.customer.company
};
field.setValue(siteValue);
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.PERSON_LOCATION_MAP) {
ticket.customer.site && field.setValue(ticket.customer.site.address);
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.POI_LOCATION) {
field.setValue(_.cloneDeep(ticket.location));
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.CATEGORY_COMPANY) {
if (ticket.locationCompany && ticket.locationCompany.name) {
field.setValue(ticket.locationCompany.name);
}
noOfFieldsSet++;
}
else if (field.type === FieldVO.prototype.TASK_PHASE) {
if (ticket.selectedPhase) {
field.setValue({
phaseGuid: ticket.selectedPhase.guid,
phaseName: ticket.selectedPhase.name
});
}
noOfFieldsSet++;
}
else if (field.isSupportGroupWidget()) {
field.primaryKey = getOotbPrimaryKeyForWidget(field, metadata);
var supportGroup = angular.copy(ticket[field.primaryKey]);
if (supportGroup) {
supportGroup.supportGroups = supportGroup.name || supportGroup.supportGroups;
}
field.setValue(supportGroup);
noOfFieldsSet++;
}
else if (field.isGroupField()) {
screenConfigurationModel.initFieldValues(field.members, ticket, metadata);
noOfFieldsSet++;
}
else {
if (field.isWidget() && field.members.length > 0) {
field.setValue(getOotbFieldValue(ticket, metadata, field));
noOfFieldsSet++;
}
else {
if (metadata) {
ootbMappingKey = metadata.ootbMapping[field.name];
}
if (!field.ootb) {
if (!fromAssignment) {
// from assignment blade no need to update
field.setValue(_.get(ticket.customFields, field.name));
}
noOfFieldsSet++;
}
else if (ootbMappingKey && ootbMappingKey.length > 0) { //if field is ootb
field.setValue(getFieldValue(field.name, ootbMappingKey, ticket));
if (field.name === 'assignee' || field.name === 'assigneeName' || field.name === 'managerName') {
var tempFieldName = ootbMappingKey[0].split('.');
field.assigneeLoginId = ticket[tempFieldName[0]] ? ticket[tempFieldName[0]].loginId : null;
}
noOfFieldsSet++;
}
else {
if (!fromAssignment) {
// from assignment blade no need to update
field.setValue(ticket[field.name]);
}
noOfFieldsSet++;
}
}
}
if (noOfFieldsSet === fields.length) {
setValuesdefer.resolve();
}
});
}
else {
setValuesdefer.resolve();
}
return setValuesdefer.promise;
};
/**
* Update ticket data from custom field values
*
* @param {TicketVO} ticket
* @param {Object} changes
*/
screenConfigurationModel.updateTicketData = function (ticket, changes) {
if (_.size(changes)) {
if (!ticket.customFields) {
ticket.customFields = {};
}
_.forOwn(changes, function (value, fieldName) {
ticket.customFields[fieldName] = value;
});
}
};
/**
* Check if all required fields are filled
* @param ticket
*/
screenConfigurationModel.ticketDataIsValid = function (ticket) {
var screenName = screenConfigurationModel.getScreenNameByTicketType(ticket.type);
var requiredFields = screenConfigurationModel.getRequiredFieldsForScreen(screenName);
var result = true;
_.each(requiredFields, function (field) {
if (!field.isCheckboxField()) {
result = result && isValid(ticket.customFields[field.name]);
}
});
return result;
};
/**
* Check the number of reguired fields missing
* @param ticket
*/
screenConfigurationModel.ticketNumOfRequiredFieldMissing = function (ticket) {
var screenName = screenConfigurationModel.getScreenNameByTicketType(ticket.type);
var requiredFields = screenConfigurationModel.getRequiredFieldsForScreen(screenName);
var numOfRequiredFieldMissing = 0;
_.each(requiredFields, function (field) {
if (!isValid(ticket.customFields[field.name])) {
numOfRequiredFieldMissing += 1;
}
});
return numOfRequiredFieldMissing;
};
/**
* Load actions for record for runtime menu
* @param resourceType
* @param refreshData
*/
screenConfigurationModel.loadActionsForRuntime = function (resourceType, refreshData) {
return executeLoadActionsForRuntime(false, resourceType, refreshData);
};
/**
* Load actions for record for runtime menu
* @param resourceType
* @param refreshData
*/
screenConfigurationModel.loadActionsForRuntimeV2 = function (resourceType, refreshData) {
return executeLoadActionsForRuntime(true, resourceType, refreshData);
};
/**
* Gets runtime actions for new and old screen types
* @param {Boolean} useV2Call - should be true for v2 screens, otherwise false. Controls corresponding method on service
* @param {String} resourceType - ticket type to load actions for
* @param {Boolean} refreshData - should be true, when cached value should be ignored and should be retrieved from server
* @returns {Promise}
*/
function executeLoadActionsForRuntime(useV2Call, resourceType, refreshData) {
var getActionsMethod = useV2Call ? 'loadActionsNew' : 'loadActions', cachedActions = screenConfigurationModel.runtimeActionsCache[resourceType];
if (!refreshData && cachedActions) {
return $q.when(cachedActions);
}
var actionsPromise = screenConfigurationService[getActionsMethod]({ resourceType: resourceType })
.then(function (items) {
screenConfigurationModel.runtimeActionsCache[resourceType] = items;
});
screenConfigurationModel.runtimeActionsCache[resourceType] = actionsPromise;
return screenConfigurationModel.runtimeActionsCache[resourceType];
}
/**
* Clears actions list from local cache by type
*
* @param {String} type - ticket type to clear cache for
*/
screenConfigurationModel.clearActionsListCacheForType = function (type) {
if (screenConfigurationModel.runtimeActionsCache[type]) {
delete screenConfigurationModel.runtimeActionsCache[type];
}
};
/**
* Execute provider action
* @param actionId
* @param resourceId
*/
screenConfigurationModel.executeProviderAction = function (actionId, resourceId) {
return screenConfigurationService.executeProviderAction(actionId, resourceId);
};
screenConfigurationModel.executeProviderActionV3 = function (actionId, resourceId, params) {
return screenConfigurationService.executeProviderActionV3(actionId, resourceId, params);
};
screenConfigurationModel.getSmartReporterUrl = function () {
return screenConfigurationService.getSmartReporterUrl();
};
screenConfigurationModel.getExternalUrl = function (urlName) {
if (screenConfigurationModel.externalUrl) {
return $q.when(screenConfigurationModel.externalUrl[urlName]);
}
else {
return screenConfigurationService.getExternalUrl().then(function (url) {
if (!screenConfigurationModel.externalUrl) {
screenConfigurationModel.externalUrl = url;
}
return url[urlName];
});
}
};
/**
* Get List Of Action Templates Metadata based on resourceType
* @param withMetadata
* @param resourceType
*/
screenConfigurationModel.getTemplateList = function (withMetadata, resourceType) {
return screenConfigurationService.getTemplateList({ withMetadata: withMetadata, resourceType: resourceType });
};
/**
* Get List Of Action Templates Metadata based on templateId
* @param templateId
*/
screenConfigurationModel.getTemplateById = function (templateId) {
return screenConfigurationService.getTemplateById({ templateId: templateId });
};
/**
* Get Existing Action Container
* @param resourceType
* @param supportedPlatforms
*/
screenConfigurationModel.getExistingContainer = function (resourceType, supportedPlatforms) {
return screenConfigurationService.getExistingContainer({ resourceType: resourceType, supportedPlatforms: supportedPlatforms });
};
/**
* Create custom action Url
* @param actionOrder
*/
screenConfigurationModel.createUrlAction = function (actionList, actionOrder, resourceType) {
var actionObj = {
actionOrder: actionOrder,
actionList: actionList,
resourceType: resourceType
};
return screenConfigurationService.createUrlAction(actionObj).then(handleActionsLoadSuccess);
};
screenConfigurationModel.refreshServerCache = function () {
return screenConfigurationService.refreshServerCache();
};
function getOotbPrimaryKeyForWidget(field, metadata) {
var ootbMappingKey, widgetMember = field.members[0];
if (widgetMember) {
ootbMappingKey = _.last(metadata.ootbMapping[widgetMember.name]);
return _.head(ootbMappingKey.split('.'));
}
return '';
}
function getOotbFieldValue(ticket, metadata, field) {
if (field.members.length > 0) {
var ticketFieldValue = {};
field.members.forEach(function (member) {
var ootbMappingKey = metadata.ootbMapping[member.name];
ticketFieldValue[member.name] = (ootbMappingKey && ootbMappingKey.length > 0)
? getFieldValue(field.name, ootbMappingKey, ticket) : ticket[member.name];
});
return ticketFieldValue;
}
}
function getFieldValue(name, ootbMappingKey, ticket) {
var ticketCopy = _.cloneDeep(ticket);
if (name.indexOf('CategoryTier') !== -1 || name === 'resProductName' || (_.startsWith(_.last(ootbMappingKey), 'categorizations'))) {
if (!ticketCopy.categorizations.tiers) {
ticketCopy.categorizations.tiers = {};
ticketCopy.categorizations.forEach(function (categorization) {
_.extend(ticketCopy.categorizations.tiers, categorization.tiers);
});
}
if (ticketCopy.resCategorizations && !ticketCopy.resCategorizations.tiers) {
ticketCopy.resCategorizations.tiers = {};
ticketCopy.resCategorizations.forEach(function (resCategorization) {
_.extend(ticketCopy.resCategorizations.tiers, resCategorization.tiers);
});
}
}
return _.get(ticketCopy, _.last(ootbMappingKey));
}
/**
* Private functions
*/
function collectTiersValues(listOfTiers) {
var tiers = {};
_.forEach(listOfTiers, function (tier) {
tiers[tier.name] = tier.selectedValue;
});
return tiers;
}
/**
* Get category values in the format expected by server
*/
function getCategoryValue(category) {
if (category.dirty) {
var cat = {
name: category.name,
tiers: collectTiersValues(category.listOfTiers)
};
if (category.primary) {
cat.primary = true;
}
if (category.company) {
cat.company = category.company;
}
return cat;
}
return null;
}
/**
* Get screen configuration by specified name
* @param {String} screenName
* @returns {ScreenConfigurationVO}
*/
function getScreenByName(screenName) {
return angular.copy(screenConfigurationModel.screensCacheByName[screenName]);
}
/**
* Returns true if value is valid
* @param value
* @returns {boolean}
*/
function isValid(value) {
return angular.isDefined(value) && value !== null;
}
screenConfigurationModel.getScreenNameByTicketType = function (ticketType) {
return _.get(screenTypeMap, ticketType);
};
/**
* Get screen configuration for specified ticket type
* @param {String} ticketType
* @return {ScreenConfigurationVO} screen configuration
*/
function getScreenForTicketType(ticketType) {
var screenName = screenConfigurationModel.getScreenNameByTicketType(ticketType);
return getScreenByName(screenName);
}
/**
* Handler for success load of app config
* @param {ApplicationConfigurationVO} appConfig
*/
function handleConfigurationLoadSuccess(appConfig) {
screenConfigurationModel.appConfig = appConfig;
var savedAssetScreen;
if (pwaModel.isPwaEnabled()) {
_.remove(appConfig.screens, function (screen) {
if (screen.name === "assetScreen" && _.includes(configurationModel.get('pwaEnabledTickets.tickets'), screen.datasource.toLowerCase())) {
savedAssetScreen = screen;
}
return screen.datasource && _.includes(configurationModel.get('pwaEnabledTickets.tickets'), screen.datasource.toLowerCase());
});
}
var screenList = appConfig.screens;
_.forEach(appConfig.screens, function (screen) {
if (screen.datasource !== 'Person' && !configurationModel.isServerApplicationEnabled(screen.datasource.toLowerCase())) {
screenList = _.reject(screenList, { datasource: screen.datasource });
}
screenConfigurationModel.screensCacheByName[screen.name] = screen;
});
screenConfigurationModel.screenList = angular.copy(screenList);
if (savedAssetScreen) {
screenConfigurationModel.savedAssetScreen = savedAssetScreen;
screenConfigurationModel.screensCacheByName[savedAssetScreen.name] = savedAssetScreen;
}
if (!appConfig.screens.length) {
console.log('Warning: screen list of application configuration is empty.');
screenConfigurationPromise.reject();
}
}
/**
* Handler for success load of available field list
* @param {Array} fieldList
*/
function handleAvailableFieldListLoadSuccess(fieldList) {
var uniqueFieldsList = fieldList.reduce(function (res, field) {
var isFieldAlreadySelected = res.some(function (selectedField) {
return selectedField.name === field.name && selectedField.dataType === field.dataType;
});
if (!isFieldAlreadySelected) {
res.push(field);
}
return res;
}, []);
screenConfigurationModel.fieldList = _.sortBy(uniqueFieldsList, 'name');
screenConfigurationModel.fieldDictionary = _.keyBy(uniqueFieldsList, 'name');
}
/**
* Handler for success load of available field list
* @param {Array} fieldList
*/
function handleActionsLoadSuccess(data) {
_.forEach(data.actionList, function (actionItem) {
actionItem.label = actionItem.labels[i18nService.language] || actionItem.labels.default;
});
if (data.actionOrder === 'alphabetical') {
screenConfigurationModel.actionList = _.sortBy(data.actionList, 'label');
}
else {
screenConfigurationModel.actionList = _.sortBy(data.actionList, 'sequenceNo');
}
screenConfigurationModel.actionOrder = data.actionOrder;
}
/**
* Handler for success load of available field list
* @param {Array} fieldList
*/
function handleActionUrlParamsLoadSuccess(data) {
screenConfigurationModel.actionUrlParams = data;
}
/**
* Handler for success load of selected field list
* @param {Array} fieldList
*/
function handleSelectedFieldListLoadSuccess(fieldList) {
screenConfigurationModel.selectedFieldDictionary = _.keyBy(fieldList, 'name');
}
/**
* Handler for success load of field list
* @param {Array} fieldLabels
* @param {String} dataSource
*/
function handleFieldLabelsLoadSuccess(fieldLabels, dataSource) {
if (!fieldLabelDictionary[dataSource]) {
fieldLabelDictionary[dataSource] = fieldLabels;
}
screenConfigurationModel.fieldLabels = fieldLabels.items;
}
screenConfigurationModel.getLocalizedFieldByNameForTicketType = function (fieldName, ticketType, assetClassId) {
var localizedField;
if (ticketType) {
var dataSource = dataSourceMap[ticketType];
localizedField = _.find(fieldLabelDictionary && fieldLabelDictionary[dataSource] && fieldLabelDictionary[dataSource].items, { name: fieldName });
}
if (!(localizedField && localizedField.label) && assetClassId) {
localizedField = _.find(screenConfigurationModel.fieldLabels, function (fieldLabel) {
return fieldLabel.name == fieldName && fieldLabel.classIds[0] == assetClassId;
});
}
if (!(localizedField && localizedField.label)) {
localizedField = _.find(screenConfigurationModel.fieldLabels, { name: fieldName });
}
return localizedField;
};
screenConfigurationModel.checkExpressionValid = function (node, fieldAcceleratorsList) {
var _errorMsg = '', _checkExpressionValid = function (node) {
var result;
if (!_errorMsg && node) {
if (node.left) {
return _checkExpressionValid(node.left);
}
if (node.right) {
return _checkExpressionValid(node.right);
}
if (node.type === 'Identifier') {
if (!_.startsWith(node.name, '$') || !_.find(fieldAcceleratorsList, { name: node.name })) {
_errorMsg = i18nService.getLocalizedStringwithParams('expression.builder.error.invalidIdentifier', node.name);
return _errorMsg;
}
}
else if (node.type === 'Compound') {
_errorMsg = i18nService.getLocalizedString('expression.builder.standard.error');
return _errorMsg;
}
else if (node.type === 'CallExpression') {
if (!_.includes(['NOOP', 'REPLACE', 'DATEADD', 'DATEDIFF', 'HASROLE', 'INGROUP', 'SELECTIONINDEX', 'SELECTIONLABEL', 'ISREQUIRED', 'ISREADONLY', 'ISHIDDEN', 'ONCHANGE'], node.callee.name)) {
_errorMsg = i18nService.getLocalizedStringwithParams('expression.builder.error.functionNotSupported', node.callee.name);
return _errorMsg;
}
_.each(node.arguments, function (item) {
return _checkExpressionValid(item);
});
}
else if (node.type === 'ConditionalExpression') {
result = _checkExpressionValid(node.test);
if (!result) {
result = _checkExpressionValid(node.consequent);
if (!result) {
return _checkExpressionValid(node.alternate);
}
}
}
}
else {
return _errorMsg;
}
};
return _checkExpressionValid(node);
};
/**
* Checks whether the screen supports expressions in actions
*
* @param {string} ticketType - type of the ticket
* @returns {boolean}
*/
screenConfigurationModel.isTicketEnabledForProviderActionExpression = function (ticketType) {
return ScreenConfigurationVO.prototype.isTicketEnabledForProviderActionExpression(ticketType);
};
return screenConfigurationModel;
}]);
})();