"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; }; } ]); })();