"use strict"; /** * Created by viktor.shevchenko on 7/9/15. */ /* * Recommended KA directive loads related KA to a ticket and Similar KA + displays them in a list with the related on top. * */ angular.module('resourceModule') .directive('rsRecommendedKa', ['searchService', 'relationModel', '$q', 'configurationModel', 'events', '$filter', function (searchService, relationModel, $q, configurationModel, events, $filter) { return { require: '^rs', restrict: 'E', scope: {}, templateUrl: 'views/resource/rs-recommended-ka.html', link: function (scope, element, attrs, rsController) { angular.extend(scope, rsController); var context = scope.context, state = { isKnowledgeInstalled: configurationModel.isServerApplicationEnabled(EntityVO.TYPE_KNOWLEDGE), itemLimit: 4, isDataLoading: false, watchersOn: false }, similarItems, searchSimilarItemsParams = { query: { chunk_size: 15, need_totalcount: false }, post: { types: ['knowledge'], search_text: (context.summary || context.title) + (context.desc ? ' ' + context.desc : '') } }, initialItemLimit = 4; scope.comaroundEnabled = configurationModel.comaroundEnabled; if (scope.context.type === EntityVO.TYPE_LIVE_CHAT) { searchSimilarItemsParams.query.isFromLiveChat = true; } scope.recommendedArticles = []; scope.titleRegExp = new RegExp(/.{1,5}/g); scope.showOpcatFilterforSmartRecorder = false; scope.isSmartRecorderScreen = (scope.context.type === EntityVO.TYPE_SMARTRECORDER); var showFilterForRecommendedKnowledge = configurationModel.showFilterForRecommendedKnowledge ? true : false; scope.recommendedKAFilterCB = { company: showFilterForRecommendedKnowledge, category: scope.isSmartRecorderScreen ? false : showFilterForRecommendedKnowledge, showFilter: showFilterForRecommendedKnowledge }; function init() { if (!showFilterForRecommendedKnowledge && context.type !== EntityVO.TYPE_PROBLEM && context.type !== EntityVO.TYPE_KNOWNERROR) { updateSearchCompaniesParam(); searchSimilarItemsParams.post.sites = (context.customer && context.customer.site) ? [context.customer.site] : []; } else { searchSimilarItemsParams.query.recommendedSearch = true; } state.isDataLoading = true; if (!context.id) { state.isDataLoading = false; return; } var globalSearchPromise = filterRecommendedKAList(true); $q.all([relationModel.getRelations(context.id, context.type), globalSearchPromise]).then(function (response) { scope.contextRelations = angular.copy(relationModel.cache[context.id]); updateRecommendedKAList(response[1]); }).finally(function () { state.isDataLoading = false; }); } function populateRecommendedArticles(relatedItems) { if (relationModel.unlinked.length && !rsController.isKaSearchEnabled()) { //Case : Article is unlinked and it is recommended articles screen relationModel.unlinked.length = 0; state.isDataLoading = true; searchService.getGlobalSearchResults(searchSimilarItemsParams.query, searchSimilarItemsParams.post).then(function (response) { if (!_.isEmpty(response.items)) { similarItems = _.reject(response.items[0].results, { id: context.id }); } mergeRelatedAndSimilarArticles(relatedItems, similarItems); }).finally(function () { state.isDataLoading = false; }); return; } mergeRelatedAndSimilarArticles(relatedItems, similarItems); } function mergeRelatedAndSimilarArticles(relatedItems, similarItems) { var relatedArticles = _.filter(relatedItems, { type: EntityVO.TYPE_KNOWLEDGE }), similarNotRelatedArticles = _.reject(similarItems, function (similarItem) { return _.find(relatedArticles, { id: similarItem.id }); }), resolvedArticle = _.remove(relatedArticles, { relationshipType: EntityVO.TYPE_RESOLVED }); if (resolvedArticle && resolvedArticle.length) { relatedArticles = resolvedArticle.concat(relatedArticles); } scope.recommendedArticles = relatedArticles.concat(similarNotRelatedArticles); scope.$emit(events.RESOURCES_FOUND, { data: scope.recommendedArticles, type: 'articles' }); } function initWatchers() { state.watchersOn = true; scope.$watchCollection('contextRelations', function (relatedItems) { populateRecommendedArticles(relatedItems); }, true); scope.$watchCollection('context', function (newValue, oldValue) { var oldContextSummary = oldValue.summary || oldValue.title; var newContextSummary = newValue.summary || newValue.title; if (newContextSummary !== oldContextSummary || newValue.desc !== oldValue.desc || (!_.isEqual(newValue.company, oldValue.company)) || (!_.isEqual(newValue.customer && newValue.customer.company, oldValue.customer && oldValue.customer.company)) || (!_.isEqual(newValue.categorizations, oldValue.categorizations))) { searchSimilarItemsParams.post.search_text = (newValue.summary || newValue.title) + (newValue.desc ? ' ' + newValue.desc : ''); init(); } }); } function fetchContextCompany() { var companies = [{ name: 'All' }]; if (context.type === EntityVO.TYPE_KNOWLEDGE && context.company && context.company.name === 'All') { return companies; } if (context.type === EntityVO.TYPE_KNOWLEDGE || context.type === EntityVO.TYPE_PROBLEM || context.type === EntityVO.TYPE_KNOWNERROR) { companies.push({ name: context.company.name }); } else { companies.push(context.customer ? context.customer.company : { name: context.company }); } return companies; } scope.context = context; scope.state = state; //Knowledge status is not getting populated when using filter in html in case of browser refresh because metadataModel.cache doesn't fetch value at that time. scope.localizedStatus = function (status) { if (scope.comaroundEnabled) { return $filter('i18n')('hkm.status.' + status); } else { return $filter('localizeLabel')(status, 'status', 'knowledge'); } }; scope.getTicketLabel = function () { return $filter('i18n')('ticket.type.' + context.type); }; scope.toggleCompanyCategoryFilter = function () { state.isDataLoading = true; filterRecommendedKAList().then(function (response) { updateRecommendedKAList(response); }).finally(function () { state.isDataLoading = false; }); }; scope.isResourceSharable = function (resource) { if (scope.context.type !== EntityVO.TYPE_LIVE_CHAT) { return; } var additionalInformation = resource && resource.additionalInformation; var foundMatch = _.find(additionalInformation && additionalInformation.additionalCategoriesCompanies, { name: scope.context.chatUserCompany }); var comaroundUrl = additionalInformation && additionalInformation.comaroundGetUrl; var company = additionalInformation && additionalInformation.company; var companyMatch = (comaroundUrl && typeof comaroundUrl === "string" && comaroundUrl.length > 0) || (company && company.name === 'All' || (scope.context.chatUserCompany === (company && company.name)) || foundMatch); return scope.context.type === EntityVO.TYPE_LIVE_CHAT && scope.context.selectedChat && !resource.internalUse && (scope.context.status === 'Assigned' || scope.context.status === 'Participate(Assigned)') && companyMatch; }; function updateSearchCompaniesParam() { var companyList = fetchContextCompany(); if (companyList) { searchSimilarItemsParams.post.searchCompanies = companyList; } } function filterRecommendedKAList(fromInit) { scope.state.itemLimit = initialItemLimit; delete searchSimilarItemsParams.query.suggest_search; delete searchSimilarItemsParams.post.searchCompanies; delete searchSimilarItemsParams.post.category; if (scope.recommendedKAFilterCB.company) { searchSimilarItemsParams.query.suggest_search = true; updateSearchCompaniesParam(); } if (fromInit && scope.isSmartRecorderScreen && scope.recommendedKAFilterCB.showFilter) { if (scope.context.template && scope.context.template.templateObject) { var operationalCat = _.find(scope.context.template.templateObject.categorizations, { name: 'operational' }); if (operationalCat && !_.isEmpty(operationalCat.tiers)) { scope.showOpcatFilterforSmartRecorder = true; scope.recommendedKAFilterCB.category = true; } } } if (scope.recommendedKAFilterCB.category) { var context; if (!scope.isSmartRecorderScreen) { context = scope.context; } else { if (scope.context.template && scope.context.template.templateObject) { context = scope.context.template.templateObject; } } if (context) { var operationalCat = _.find(context.categorizations, { name: 'operational' }); if (operationalCat && !_.isEmpty(operationalCat.tiers)) { searchSimilarItemsParams.post.category = []; searchSimilarItemsParams.post.category.push({ name: operationalCat.name, tiers: operationalCat.tiers }); } } } if (scope.comaroundEnabled) { if (searchSimilarItemsParams.post) { delete searchSimilarItemsParams.post.types; delete searchSimilarItemsParams.post.sites; delete searchSimilarItemsParams.post.searchCompanies; } if (searchSimilarItemsParams.query && searchSimilarItemsParams.query.chunk_size) { searchSimilarItemsParams.query = { chunk_size: searchSimilarItemsParams.query.chunk_size }; } else { searchSimilarItemsParams.query = {}; } return searchService.getHKMRecommendedKA(searchSimilarItemsParams.query, searchSimilarItemsParams.post); } else { return searchService.getGlobalSearchResults(searchSimilarItemsParams.query, searchSimilarItemsParams.post); } } function updateRecommendedKAList(response) { if (!_.isEmpty(response.items)) { similarItems = _.reject(response.items[0].results, { id: context.id }); } if (!state.watchersOn) { initWatchers(); } else { populateRecommendedArticles(scope.contextRelations); } } init(); scope.$on(events.REFRESH_RESOURCE_FEED, function (event, data) { if (!data.isRefreshTicket) { init(); } }); scope.$on(events.REFRESH_RECOMMENDED_KNOWLEDGE, function () { scope.contextRelations = angular.copy(relationModel.cache[context.id]); populateRecommendedArticles(scope.contextRelations); }); scope.$on(events.UPDATE_CONTEXT_ON_REFRESH, function (event, updatedContext) { if (updatedContext) { context = scope.context = updatedContext; } }); } }; }]);