"use strict";
(function () {
'use strict';
angular.module('consoleModule')
.controller('ConsoleController', ['$scope', 'knowledgeConsoleModel', 'ticketConsoleModel', 'assetConsoleModel', 'ticketActionService', 'userModel', 'followService', 'ribbonValidationService',
'$state', '$compile', '$modal', 'systemAlertService', '$filter', 'urlCreatorService', 'knowledgeArticleModel', 'events', 'emailModel', '$q', 'screenConfigurationModel', '$timeout', 'browser', '$rootScope',
function ($scope, knowledgeConsoleModel, ticketConsoleModel, assetConsoleModel, ticketActionService, userModel, followService, ribbonValidationService, $state, $compile, $modal, systemAlertService, $filter, urlCreatorService, knowledgeArticleModel, events, emailModel, $q, screenConfigurationModel, $timeout, browser, $rootScope) {
var state = {
bootstraping: true,
processing: false,
loadingMoreTickets: false,
updatingMetric: false
}, selectedItems = [], sortInfo = { fields: [], directions: [], columns: [] }, ngGridShowLoadingMoreSpinner = {
init: function (scope, grid) {
grid.$viewport.append($compile('
')($scope));
}
}, consoleModel = null, defaultPresets, userPresets, duplicatesPresets;
switch ($scope.consoleType) {
case 'ticket':
consoleModel = ticketConsoleModel;
break;
case 'knowledge':
consoleModel = knowledgeConsoleModel;
break;
case 'asset':
consoleModel = assetConsoleModel;
break;
}
if (consoleModel) {
$scope.ribbonConfig = consoleModel.ribbonConfig;
$scope.criteria = consoleModel.criteria;
$scope.selectedFilters = consoleModel.selectedFilters;
}
$scope.userModel = userModel;
$scope.ticketTypeSelected = [];
$scope.searchDisabled = false;
$scope.searchValue = '';
//todo: Viktor: I need to find better solution to eliminate copy-paste in ticketActions
$scope.itemActions = {
assign: function ($event) {
ticketActionService.showBulkAssignDialog($scope.selectedItems).result.then(function (newAssignee) {
var name = newAssignee.assignee.fullName ? newAssignee.assignee.fullName : newAssignee.group.name;
systemAlertService.success({
text: $scope.selectedItems.length + ' ' + $filter('i18n')('console.ribbonAction.assign.success') + ' ' + name,
hide: 10000
});
$event.currentTarget.focus();
return $scope.getNewItemList();
}, function () {
$event.currentTarget.focus();
});
},
share: function ($event) {
if ($scope.selectedItems[0].type === EntityVO.TYPE_SERVICEREQUEST || $scope.selectedItems[0].type === EntityVO.TYPE_KNOWLEDGE) {
ticketActionService.showShareDialog($scope.selectedItems).result.then(function () {
$scope.gridOptions.selectAll(false);
$event.currentTarget.focus();
}, function () {
$event.currentTarget.focus();
});
}
else {
emailModel.createEmail($scope.selectedItems);
}
},
link: function ($event) {
ticketActionService.showLinkDialog($scope.selectedItems, false).result.then(function () {
systemAlertService.success({
text: $filter('i18n')('console.ribbonAction.relation.success'),
hide: 10000
});
$scope.consoleItems.allSelected = false;
$scope.getNewItemList();
$event.currentTarget.focus();
}, function () {
$event.currentTarget.focus();
});
},
follow: function () {
state.processing = true;
followService.follow($scope.selectedItems).then(function () {
systemAlertService.success({
text: $filter('i18n')('console.ribbonAction.follow.success', $scope.selectedItems.length),
hide: 10000
});
($scope.consoleType === 'knowledge') && knowledgeArticleModel.updateCachedArticles(_.pluck($scope.selectedItems, 'id'), {
following: true
});
}).catch(function (error) {
if (error) {
systemAlertService.error({
text: error.data.errorCode ? $filter('i18n')('error.unknown') : error.data.error,
clear: false
});
}
}).finally(function () {
state.processing = false;
});
},
unfollow: function () {
state.processing = true;
followService.unfollow($scope.selectedItems).then(function () {
systemAlertService.success({
text: $filter('i18n')('console.ribbonAction.unfollow.success', $scope.selectedItems.length),
hide: 10000
});
($scope.consoleType === 'knowledge') && knowledgeArticleModel.updateCachedArticles(_.pluck($scope.selectedItems, 'id'), {
following: false
});
}).catch(function (error) {
if (error) {
systemAlertService.error({
text: error.data.errorCode ? $filter('i18n')('error.unknown') : error.data.error,
clear: false
});
}
}).finally(function () {
state.processing = false;
});
},
openInNewTab: function () {
var urls = selectedItems.map(function (item) {
return urlCreatorService.create(item);
});
_.forEach(urls, function (url) {
if (!!window.chrome) { // Chrome
var a = document.createElement('a'), evt = document.createEvent('MouseEvents');
a.setAttribute('href', url);
a.setAttribute('target', '_blank');
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, true, false, false, false, 0, null);
a.dispatchEvent(evt);
}
else {
window.open(url);
}
});
},
changeStatus: function ($event) {
ticketActionService.showEditStatusDialog($scope.selectedItems, false).result.then(function (statusData) {
systemAlertService.success({
text: $filter('i18n')('console.ribbonAction.editStatus.success') + statusData.status,
hide: 10000
});
$scope.consoleItems.allSelected = false;
$scope.getNewItemList();
$event.currentTarget.focus();
}, function () {
$event.currentTarget.focus();
});
},
assess: function () {
consoleModel.kcsFilters.assessmentMode = true;
$state.go(EntityVO.TYPE_KNOWLEDGE, { id: $scope.selectedItems[0].id, assessMode: true });
}
};
$scope.setDefaultPreset = function (userPreset) {
_.each($scope.userSavedFilterPresets, function (preset) {
preset.defaultpreset = false;
if (preset.name === userPreset.name) {
preset.defaultpreset = true;
}
});
if (userPreset.systemgenerated) {
var temp = _.find(duplicatesPresets, {
name: userPreset.name
});
if (temp) {
userPreset.id = temp.id;
}
else {
userPreset.id = null;
}
}
var filterSet = {
name: userPreset.name,
id: userPreset.id || null,
defaultpreset: userPreset.defaultpreset,
systemgenerated: userPreset.systemgenerated
};
userModel.updateUserPreferences(consoleModel.filterPreferenceGroup, filterSet)
.then(function (data) {
_.each(data, function (responsePreset) {
if (!(responsePreset.createDate && responsePreset.systemgenerated)) {
var index = _.findIndex(consoleModel.userSavedPresets, function (userSavedPreset) {
if (userSavedPreset.id === responsePreset.id) {
return true;
}
return false;
});
if (index > -1) {
if (consoleModel.userSavedPresets[index].columnId) {
responsePreset.columnId = consoleModel.userSavedPresets[index].columnId;
responsePreset.columnValue = angular.copy(consoleModel.userSavedPresets[index].columnValue);
}
consoleModel.userSavedPresets[index] = responsePreset;
}
}
});
$scope.setDefaultPresetOnload();
})
.catch(function () {
systemAlertService.warning({
text: $filter('i18n')('error.unknown'),
hide: 10000
});
return;
});
};
$scope.setDefaultPresetOnload = function () {
defaultPresets = [];
userPresets = [];
duplicatesPresets = [];
//find values for each pre-sets
_.each(consoleModel.userSavedPresets, function (preset) {
//need to check for ID - and replace createDate check
if (!preset.createDate) {
defaultPresets.push(preset);
}
if (preset.createDate && preset.systemgenerated) {
duplicatesPresets.push(preset);
}
if (!preset.systemgenerated) {
userPresets.push(preset);
}
});
//find id for default preset and match them
_.each(defaultPresets, function (preset) {
var temp = _.find(duplicatesPresets, {
name: preset.name,
systemgenerated: true
});
if (temp) {
preset.id = temp.id;
preset.defaultpreset = temp.defaultpreset;
}
});
// if no default selected then set fist to default on load always- SW00513638
var isDefaultPresent = _.find(consoleModel.userSavedPresets, { defaultpreset: true });
if (!isDefaultPresent) {
consoleModel.userSavedPresets[0].defaultpreset = true;
}
return consoleModel.userSavedPresets = defaultPresets.concat(userPresets);
};
$scope.init = function () {
$scope.columnsConfig = consoleModel.columnsConfig;
$scope.userSavedFilterPresets = $scope.setDefaultPresetOnload();
$scope.ticketMetric = consoleModel.statsConfig;
$scope.filterConfig = consoleModel.filterConfig;
$scope.ticketTypeFilter = consoleModel.ticketTypeFilter;
$scope.assetTypeFilter = consoleModel.assetTypeFilter;
//Make all filters visible by defa ult if no filters are pre-selected
var ticketTypesIndex = _.findIndex($scope.selectedFilters, function (filter) {
return filter.criteria.name === 'ticketTypes';
}), assetTypesIndex = _.findIndex($scope.selectedFilters, function (filter) {
return filter.criteria.name === 'assetTypes';
});
if (ticketTypesIndex !== -1) {
_.forEach($scope.selectedFilters, function (filter) {
if (filter.criteria.name === 'ticketTypes') {
$scope.updateFilterGrouping(filter.name);
}
});
}
else if (assetTypesIndex !== -1) {
_.forEach($scope.filterConfig, function (filter) {
filter.onDisplay = true;
if (filter.name === 'statuses') {
_.forEach(filter.options, function (specificStatus) {
specificStatus.onDisplay = true;
});
}
//Hide advanced asset filters which are type specific
if ($scope.consoleType === EntityVO.TYPE_ASSET) {
filter.onDisplay = filter.assetType ? false : true;
}
});
_.forEach($scope.selectedFilters, function (filter) {
if (filter.criteria.name === 'assetTypes') {
$scope.updateAssetFilterGrouping(filter.name);
}
});
}
else {
_.forEach($scope.filterConfig, function (filter) {
filter.onDisplay = true;
if (filter.name === 'statuses' || filter.name === 'priorities') {
_.forEach(filter.options, function (specificStatus) {
specificStatus.onDisplay = true;
});
}
});
}
$scope.setColumnDefinition();
if ($scope.displayMetric) {
$scope.getMetrics();
}
// SW00542241 - Fix for IE slowness of console
$scope.displayFilters = (!(browser.isIE && $scope.consoleType === 'ticket'));
$scope.normalizedFilterConfig = normalizeFilterConfig($scope.filterConfig);
return $scope.getNewItemList().finally(function () {
revalidateRibbon();
state.bootstraping = false;
});
};
function normalizeFilterConfig(filterConfig) {
return _.filter(filterConfig, function (filter, i, a) {
return filter.options.length && filter.onDisplay && filter !== $scope.ticketTypeFilter && filter !== $scope.assetTypeFilter;
});
}
$scope.getNewItemList = function (fromRefresh) {
if (fromRefresh) {
var filterCriteriaKeysList = Object.keys(consoleModel.criteria.filterCriteria);
filterCriteriaKeysList.forEach(function (key) {
var fCriteria = consoleModel.criteria.filterCriteria[key];
if (consoleModel.filterDict[key] && consoleModel.filterDict[key].options && consoleModel.filterDict[key].options.length && !_.isEmpty(fCriteria)) {
var filterObj = _.find(consoleModel.filterDict[key].options, (function (fCriteriaId) {
return function (item) {
return item.label === fCriteriaId;
};
}(fCriteria[0].id)));
if (filterObj && filterObj.type === "date" && filterObj.label != "customRange") {
if (fCriteria[0].start && filterObj.defaultValues.start) {
fCriteria[0].start = $rootScope.$eval(filterObj.defaultValues.start, { moment: moment });
}
if (fCriteria[0].end && filterObj.defaultValues.end) {
fCriteria[0].end = $rootScope.$eval(filterObj.defaultValues.end, { moment: moment });
}
}
}
});
}
consoleModel.dropCriteriaStartIndex();
if (!consoleModel.isSearchEnabled()) {
$scope.searchDisabled = true;
$scope.itemList = [];
$scope.totalItemsFound = 0;
return $q.when(1);
}
state.processing = true;
$scope.searchDisabled = false;
return getTickets().catch(function (error) {
if (error) {
systemAlertService.error({
text: error.data.errorCode ? $filter('i18n')('error.unknown') : error.data.error,
clear: false
});
}
}).finally(function () {
state.processing = consoleModel.metaDataRefresh || false;
if ($scope.userModel.isAccessibleUser) {
$scope.$broadcast(events.SELECT_ALL_TICKETS, false);
}
else {
$scope.gridOptions.selectAll(false);
}
});
};
$scope.loadMoreTickets = function () {
state.loadingMoreTickets = true;
getTickets().finally(function () {
state.loadingMoreTickets = false;
});
};
var getTickets = function () {
return consoleModel.getItemList().then(function (totalItems) {
if ($scope.isPublishedClicked) {
$scope.itemList = _.filter(consoleModel.itemList, function (item) {
return item.statusValue.value === 'Published';
});
$scope.totalItemsFound = totalItems;
$scope.isPublishedClicked = false;
}
else {
$scope.itemList = consoleModel.itemList;
$scope.totalItemsFound = totalItems;
}
});
};
$scope.refreshToShowStats = function () {
state.updatingMetric = true;
$scope.showStats = true;
consoleModel.getTicketConsoleMetric().finally(function () {
state.updatingMetric = false;
});
};
$scope.getMetrics = function () {
if ($scope.consoleType === 'asset' || $scope.searchDisabled) {
return;
}
$scope.showStats = _.cloneDeep(consoleModel.showStats);
if ($scope.showStats) {
state.updatingMetric = true;
consoleModel.getTicketConsoleMetric().finally(function () {
state.updatingMetric = false;
});
}
};
$scope.applySearch = function () {
var filter = _.find($scope.filterConfig, { name: 'keywords' });
var option = _.find(filter.options, { subtype: 'keyword' });
$scope.applyKeywordFilter(filter, option, this.searchValue);
$scope.applyFilter();
this.searchValue = '';
};
$scope.setColumnDefinition = function () {
$scope.columnsConfig = consoleModel.columnsConfig;
$scope.gridColumns = angular.copy(_.sortBy(_.filter($scope.columnsConfig, 'visible'), 'order'));
if (consoleModel.presetColumns && consoleModel.presetColumns.length) {
$scope.gridColumns = angular.copy(consoleModel.presetColumns);
}
if (window.isRtl) {
$scope.gridColumns.reverse();
}
};
$scope.startColumnConfigurator = function ($event) {
var columnConfigurator = $modal.open({
templateUrl: 'views/console/column-configurator-action-blade.html',
controller: 'ConsoleColumnConfiguratorController',
windowClass: 'action-blade',
size: 'lg',
resolve: {
params: function () {
return {
consoleType: $scope.consoleType
};
}
}
});
columnConfigurator.result.then(function (flag) {
if (flag === 'refresh') {
$scope.applyUserFilterPreset(consoleModel.userSavedFilterPresets[0]);
consoleModel.resetCache(function () {
$state.go('ticketConsole', { refreshMetadata: true }, { reload: true });
});
}
$scope.setColumnDefinition();
if (consoleModel.appliedPreset && !consoleModel.appliedPreset.columnId) {
consoleModel.populateAttributeNames();
}
}).finally(function () {
$event.currentTarget.focus();
});
};
$scope.openColumnConfigModal = function () {
if ($state.params.refreshMetadata) {
consoleModel.metaDataRefresh = false;
$scope.startColumnConfigurator();
}
};
//Filters shown and hidden as per ticket type selected
$scope.updateFilterGrouping = function (filterName) {
var ticketRemoved = _.remove($scope.ticketTypeSelected, function (ticketType) {
return filterName === ticketType;
});
if (ticketRemoved.length === 0 && !_.isUndefined($scope.filterConfig)) {
$scope.ticketTypeSelected.push(filterName);
}
_.forEach($scope.filterConfig, function (filter) {
if (angular.isUndefined(filter.ticketType) || $scope.ticketTypeSelected.length === 0
|| _.intersection(filter.ticketType, $scope.ticketTypeSelected).length !== 0) {
filter.onDisplay = true;
if (filter.name === 'statuses' || filter.name === 'priorities' || (filter.type === 'custom' && filter.fieldType === 'staticSelectionField')) { //Showing status filters as per ticket types selected
_.forEach(filter.options, function (specificStatus) {
if ($scope.ticketTypeSelected.length === 0
|| _.intersection(specificStatus.criteria.ticketTypes, $scope.ticketTypeSelected).length !== 0) {
specificStatus.onDisplay = true;
}
else {
specificStatus.onDisplay = false;
}
});
}
}
else {
filter.onDisplay = false;
}
});
};
//Filters shown and hidden as per asset type selected
$scope.updateAssetFilterGrouping = function () {
$scope.assetTypeFilter = consoleModel.assetTypeFilter;
$scope.filterConfig = consoleModel.filterConfig;
var selectedAssetTypes = _.pluck(_.filter($scope.assetTypeFilter.options, { 'active': true }), 'criteriaValue');
_.forEach($scope.filterConfig, function (filter) {
if (filter.assetType) {
//filter.onDisplay = _.intersection(filter.assetType, selectedAssetTypes).length ? true : false;
if (filter.criteriaKeys) {
if (filter.selectiveClearFilters) {
consoleModel.clearSelectiveCriteriaKeyValues(filter);
}
else {
consoleModel.clearCriteriaKeyValues(null, filter.criteriaKeys);
}
}
//Hide advanced filters when multiple asset types are selected
filter.onDisplay = selectedAssetTypes.length === 1 && selectedAssetTypes[0] === filter.assetType[0];
}
if (filter.name === 'assetSubTypes') {
_.forEach(filter.options, function (specificSubtype) {
specificSubtype.onDisplay = !selectedAssetTypes || !selectedAssetTypes.length || _.includes(selectedAssetTypes, specificSubtype.criteria.typeName);
});
}
});
};
$scope.filterButtonClicked = function () {
if (browser.isIE && $scope.consoleType === 'ticket') {
if (!$scope.displayFilters) {
state.processing = true;
}
$timeout(function () {
$scope.displayFilters = true;
}, 1);
}
else {
return false;
}
};
$scope.openLaunchActionBlade = function (actionItem, event) {
var modalInstance = $modal.open({
templateUrl: 'views/asset/asset-launch-action-blade.html',
controller: 'AssetLaunchActionController',
windowClass: 'action-blade',
size: 'lg',
resolve: {
linkParams: function () {
return {
selectedItem: $scope.selectedItems,
actionItem: actionItem
};
}
}
});
modalInstance.result.then(function (data) {
event.currentTarget.focus();
if (!_.isEmpty(data)) {
$scope.getNewItemList();
}
});
};
var openEntityDetailPage = function (ticketVO) {
if ($scope.consoleType === 'asset') {
$state.go(ticketVO.ticketType, {
assetId: ticketVO.reconciliationId,
assetClassId: ticketVO.classId
});
return;
}
// state names correspond to item type ("incident", "workorder")
var states = {
incident: EntityVO.TYPE_INCIDENT,
workorder: EntityVO.TYPE_WORKORDER,
task: EntityVO.TYPE_TASK,
request: EntityVO.TYPE_SERVICEREQUEST,
knowledge: EntityVO.TYPE_KNOWLEDGE,
change: EntityVO.TYPE_CHANGE,
problem: EntityVO.TYPE_PROBLEM,
knownerror: EntityVO.TYPE_KNOWNERROR,
asset: EntityVO.TYPE_ASSET,
release: EntityVO.TYPE_RELEASE
};
if (!states[ticketVO.type]) {
return;
}
if (states[ticketVO.type] === EntityVO.TYPE_KNOWLEDGE) {
$state.go(states[ticketVO.type], { id: ticketVO.id, preventIncrement: true });
return;
}
$state.go(states[ticketVO.type], { id: ticketVO.id });
};
var revalidateRibbon = function () {
$scope.ribbonConfig.forEach(function (item) {
item.isActive = item.active ? $scope.$eval(item.active, { ribbonValidationService: ribbonValidationService }) : false;
item.isHidden = item.hidden ? $scope.$eval(item.hidden, { ribbonValidationService: ribbonValidationService }) : false;
});
};
$scope.consoleItems = {
allSelected: false
};
$scope.gridOptions = {
data: 'itemList',
headerRowHeight: 43,
rowHeight: 40,
sortInfo: sortInfo,
useExternalSorting: true,
enableColumnResize: true,
showSelectionCheckbox: true,
checkboxHeaderTemplate: '',
// checkboxCellTemplate: '',
selectedItems: selectedItems,
beforeSelectionChange: function (rowItem, event) {
var result;
if (!event || !event.target || $(event.target).hasClass('ngSelectionCheckbox') || $(event.target).hasClass('ngSelectionCell')) {
result = true;
}
else {
result = false;
openEntityDetailPage(rowItem.entity);
}
return result;
},
afterSelectionChange: function () {
revalidateRibbon();
},
plugins: [ngGridShowLoadingMoreSpinner],
columnDefs: 'gridColumns'
};
if ($scope.consoleType === EntityVO.TYPE_ASSET) {
$scope.gridOptions.showSelectionCheckbox = false;
screenConfigurationModel.loadActionsForRuntime(EntityVO.TYPE_ASSET).then(function () {
var contextActions = screenConfigurationModel.runtimeActionsCache[EntityVO.TYPE_ASSET];
$scope.gridOptions.showSelectionCheckbox = _.some(contextActions.actionList, function (action) {
return action.actionType === 'launch' && _.includes(action.supportedPlatforms, 'web');
});
});
}
$scope.$on('ngGridEventScroll', function () {
if (($scope.criteria.chunkInfo.startIndex + consoleModel.defaultChunkSize) < $scope.totalItemsFound && !state.loadingMoreTickets) {
$scope.criteria.chunkInfo.startIndex += consoleModel.defaultChunkSize;
}
});
$scope.state = state;
$scope.selectedItems = selectedItems;
$scope.sortInfo = sortInfo;
$scope.openEntityDetailPage = openEntityDetailPage;
$scope.$watch('sortInfo', function (newValue, oldValue) {
if (!angular.equals(newValue, oldValue)) { //initialization of controller
$scope.criteria.sortInfo = {
sortFieldName: sortInfo.columns[0].colDef.attributeName,
sortFieldOrder: sortInfo.directions[0].toUpperCase()
};
}
}, true);
$scope.$watch('gridOptions.$gridScope.isColumnResizing', function (newValue, oldValue) {
if (newValue === false && oldValue === true) { //on stop resizing
$scope.gridOptions.$gridScope.hasUserChangedGridColumnWidths = false;
var colsToUpdate = {}, insertUpdateColumn = function (columnName, propName, propValue) {
if (!colsToUpdate[columnName]) {
colsToUpdate[columnName] = {};
}
colsToUpdate[columnName][propName] = propValue;
};
_.forEach($scope.gridOptions.$gridScope.columns, function (column) {
if (column.colDef.name) {
if (column.width !== column.colDef.width) {
insertUpdateColumn(column.colDef.name, 'width', column.width);
}
insertUpdateColumn(column.colDef.name, 'order', (column.colDef.index + 1));
insertUpdateColumn(column.colDef.name, 'visible', true);
if (consoleModel.columnsConfig[column.colDef.name].type) {
insertUpdateColumn(column.colDef.name, 'type', consoleModel.columnsConfig[column.colDef.name].type);
}
}
});
consoleModel.updateColumnConfig(colsToUpdate);
}
}, true);
$scope.handleRowSelection = function (selectedRows) {
$scope.selectedItems = selectedItems = selectedRows;
revalidateRibbon();
};
$scope.$watch('userModel.isAccessibleUser', function () {
if (selectedItems.length) {
for (var i = 0; i < selectedItems.length; i++) {
selectedItems[i].selected = false;
}
}
$scope.selectedItems = selectedItems = [];
if (!$scope.userModel.isAccessibleUser) {
$scope.gridOptions.selectedItems = selectedItems;
}
}, true);
$scope.$watch('totalItemsFound', function () {
if ($scope.userModel.isAccessibleUser) {
$scope.selectedItems = selectedItems = [];
}
}, true);
$scope.$on(events.UPDATE_GRID_COLUMNS, $scope.setColumnDefinition);
$scope.isAllTypeChange = function (selectedItems) {
var flag = true, i;
for (i = 0; i < selectedItems.length; i++) {
if (selectedItems[i].type !== EntityVO.TYPE_CHANGE) {
flag = false;
break;
}
}
return flag;
};
$scope.showChangeWarning = function (selectedItems) {
var flag = true, i;
for (i = 0; i < selectedItems.length; i++) {
if (selectedItems[i].type !== EntityVO.TYPE_CHANGE || !selectedItems[i].allowBulkUpdateStatus) {
flag = false;
break;
}
}
return flag;
};
}
]);
})();