"use strict"; /** * Created by viktor.shevchenko on 12/10/2014. */ (function () { 'use strict'; angular.module('createTicketModule') .controller('CreateKnowledgeArticleController', ['$scope', 'localStorageService', '$modal', 'searchService', 'relationModel', '$state', '$timeout', 'systemAlertService', 'attachmentService', 'metadataModel', 'categoriesService', 'knowledgeArticleModel', 'ticketModel', '$q', '$filter', 'configurationModel', function ($scope, localStorageService, $modal, searchService, relationModel, $state, $timeout, systemAlertService, attachmentService, metadataModel, categoriesService, knowledgeArticleModel, ticketModel, $q, $filter, configurationModel) { if (!configurationModel.isServerApplicationEnabled(EntityVO.TYPE_KNOWLEDGE)) { $state.go('unauthorized'); return; } $scope.editMode = true; //flag that is used for category directive var article = {}, metadata, knowledgeTitleChangeTimer, state = {}, localStorageDefaultTemplateKey = 'DEFAULT_KA_TEMPLATE', currentUserId = localStorageService.get('user.userId'), savedTemplate = localStorageService.get(localStorageDefaultTemplateKey), defaultTemplateId = (savedTemplate && (savedTemplate.user === currentUserId)) ? savedTemplate.templateId : null, localStorageLastVisibilitySetKey = 'LAST_SET_OF_VISIBILITY_GROUPS', draftArticle = {}; setInitialState(); loadAvailableTemplates().then(function () { if (defaultTemplateId) { $scope.selectedTemplate = _.find($scope.templates, { id: defaultTemplateId }); loadDraftData().then(function () { state.isTemplateSelected = true; state.isTemplateAccepted = true; }); } }); function setInitialState() { state = angular.extend(state, { dataIsLoading: false, isTemplateSelected: false, isTemplateAccepted: false, rememberTemplate: false, showMetadata: true, loadingMergeWindow: false, showingMergeTool: false, similarArticles: [], showSimilarArticles: false, loadVisibility: false, loadingSimilarArticles: false, similarArticlePromise: null, allowStateChange: false }); $scope.attachments = []; $scope.linkedItems = []; $scope.titleMaxLength = 4000; } function loadAvailableTemplates() { state.dataIsLoading = true; return knowledgeArticleModel.getKnowledgeArticleTemplates().then(function (templates) { $scope.templates = angular.copy(templates); _.remove($scope.templates, { name: 'Decision Tree' }); return templates; }).finally(function () { state.dataIsLoading = false; }); } function loadDraftData() { var metaDataPromise = metadataModel.getMetadataByType(EntityVO.TYPE_KNOWLEDGE), kaDraftPromise = knowledgeArticleModel.getDraft($scope.selectedTemplate.id, $scope.articleContext); state.dataIsLoading = true; return $q.all([metaDataPromise, kaDraftPromise]).then(function (result) { metadata = result[0]; angular.extend(article, result[1]); $scope.article.categoriesControls = _.cloneDeep(categoriesService.populateCategories($scope.article.defaultCategorization, metadata)); $scope.article.categoriesSet = _.cloneDeep(categoriesService.populateMultipleCategories($scope.article.allCategories, metadata)); draftArticle = _.cloneDeep($scope.article); _.forEach($scope.article.content, function (content) { if (content.snippet) { content.snippet = _.compact(content.snippet.split('\n')).join('
'); } }); }).finally(function () { state.dataIsLoading = false; }); } //template selection screen $scope.selectTemplate = function (template) { state.isTemplateSelected = true; $scope.selectedTemplate = _.cloneDeep(template); }; //template details screen $scope.backToTemplateSelection = function () { $scope.selectedTemplate = null; state.isTemplateSelected = false; state.rememberTemplate = false; }; $scope.acceptTemplate = function () { loadDraftData().then(function () { setDefaultTemplate(state.rememberTemplate ? $scope.selectedTemplate.id : null); state.isTemplateAccepted = true; }); }; $scope.mergeAndAcceptTemplate = function () { var newContent = '', previousArticle = _.cloneDeep(article); runMergeForChangeTemplate() .then(function (content) { $scope.previousTemplate = null; newContent = content; state.dataIsLoading = true; return knowledgeArticleModel.getDraft($scope.selectedTemplate.id); }) .then(function (result) { angular.extend(article, knowledgeArticleModel.mergeArticleMetaData(result, previousArticle, newContent)); setDefaultTemplate(state.rememberTemplate ? $scope.selectedTemplate.id : null); state.isTemplateAccepted = true; }).finally(function () { state.dataIsLoading = false; }); }; function setDefaultTemplate(templateId) { state.rememberTemplate = false; localStorageService.set(localStorageDefaultTemplateKey, { templateId: templateId, user: currentUserId }); } function runMergeForChangeTemplate() { return openMergeTool({ input: $scope.article.content, output: _.cloneDeep($scope.selectedTemplate.templateObject.sections), outputTitle: ['create.knowledge.merge.change.output.title'], inputTitle: ['create.knowledge.merge.change.input.title.first', 'create.knowledge.merge.change.input.title.second'] }).then(function (content) { return content; }); } //knowledge article edit screen $scope.changeTemplate = function () { state.isTemplateSelected = false; state.isTemplateAccepted = false; $scope.previousTemplate = _.cloneDeep($scope.selectedTemplate); setDefaultTemplate(null); loadAvailableTemplates(); }; $scope.clearTitle = function () { $scope.article.title = ''; $scope.onKnowledgeTitleChange(); }; $scope.onKnowledgeTitleChange = function (value) { state.similarArticles = []; state.loadingSimilarArticles = false; if (knowledgeTitleChangeTimer) { $timeout.cancel(knowledgeTitleChangeTimer); } if (value && value.length >= 3) { knowledgeTitleChangeTimer = $timeout(function () { state.loadingSimilarArticles = true; if (state.similarArticlePromise) { state.similarArticlePromise.finally(function () { state.loadingSimilarArticles = true; state.similarArticles = []; }); } state.similarArticlePromise = knowledgeArticleModel.findArticleByText({ search_text: value }).then(function (articles) { state.similarArticles = articles; _.remove(state.similarArticles, { templateName: 'Decision Tree' }); //Currently not supporting decision tree }).finally(function () { state.loadingSimilarArticles = false; }); }, 1000); } }; $scope.mergeSimilarArticle = function (id) { state.dataIsLoading = true; knowledgeArticleModel.getKnowledgeArticleById(id).then(function (data) { state.dataIsLoading = false; state.showingMergeTool = true; return openMergeTool({ input: data.content, output: _.cloneDeep(article.content), outputTitle: ['create.knowledge.merge.output.title'], inputTitle: ['create.knowledge.merge.input.title.first', 'create.knowledge.merge.input.title.second'] }); }).then(function (content) { article.content = content; }).finally(function () { state.showingMergeTool = false; }); }; $scope.updateSimilarArticle = function (id) { state.dataIsLoading = true; knowledgeArticleModel.getKnowledgeArticleById(id).then(function (data) { state.dataIsLoading = false; if (data.accessMappings.detailsEditAllowed) { state.showingMergeTool = true; return openMergeTool({ input: _.cloneDeep(article.content), output: _.cloneDeep(data.content), outputTitle: ['create.knowledge.merge.instead.output.title'], inputTitle: ['create.knowledge.merge.instead.input.title.first', 'create.knowledge.merge.instead.input.title.second'] }); } else { systemAlertService.info({ text: $filter('i18n')('create.knowledge.similar.edit.instead.deny') }); return $q.reject(); } }).then(function (content) { openArticleForEdit(id, content); }).finally(function () { state.showingMergeTool = false; }); }; function openArticleForEdit(id, content) { state.allowStateChange = true; $state.go('knowledge', { id: id, content: content, editMode: true }); } function openMergeTool(mergeParams) { var parentScope = $scope; return $modal.open({ templateUrl: 'views/knowledge-article/article-merge-tool.html', controller: ['$scope', '$modalInstance', 'mergeParams', function ($scope, $modalInstance, mergeParams) { $scope.input = { content: mergeParams.input }; $scope.output = { content: mergeParams.output }; $scope.outputTitle = mergeParams.outputTitle || []; $scope.inputTitle = mergeParams.inputTitle || []; $scope.merge = function () { $modalInstance.close($scope.output.content); }; parentScope.$on('$destroy', $modalInstance.close); } ], windowClass: 'modal_article-merge-tool', backdrop: false, keyboard: false, resolve: { mergeParams: function () { return mergeParams; } } }).result; } $scope.handleFileChange = function (fileInput) { var newAttachment = attachmentService.prepareFileToUpload({ fileInput: fileInput }); if (newAttachment && newAttachment.size <= 0) { systemAlertService.warning({ text: $filter('i18n')('attachment.file_empty'), icon: 'icon-exclamation_triangle', clear: true, hide: 5000 }); return; } if (newAttachment) { $scope.attachments ? $scope.attachments.push(newAttachment) : $scope.attachments = [newAttachment]; } }; $scope.dismissAttachment = function ($e, attachment) { var index = $scope.attachments.indexOf(attachment); if (index >= 0) { $scope.attachments.splice(index, 1); } $e.stopImmediatePropagation(); }; $scope.addLinkedItem = function ($event) { var modalInstance = $modal.open({ templateUrl: 'views/ticket/link-item-action-blade.html', windowClass: 'action-blade', controller: 'LinkController', resolve: { linkParams: function () { return { selectedItems: [{ id: null, type: EntityVO.TYPE_KNOWLEDGE }], isDraft: true }; } } }); modalInstance.result.then(function (linkedItems) { Array.prototype.push.apply($scope.linkedItems, linkedItems); }).finally(function () { $event.currentTarget.focus(); }); }; $scope.removeLinkedItem = function (item) { _.pull($scope.linkedItems, item); }; $scope.createArticle = function () { var createdArticle; $scope.state.dataIsLoading = true; $scope.article.allCategories = categoriesService.collectValues($scope.article.categoriesSet, $scope.article); saveSetOfVisibilityGroups(article.articleVisibilityGroup); article.title = article.title.replace(/\u00a0/g, ' '); article.parentTicketType = ticketModel.articleParent ? ticketModel.articleParent.type : ''; setTimeout(function () { knowledgeArticleModel.createArticle(currentUserId, article).then(function (result) { createdArticle = result; if (ticketModel.articleParent) { delete ticketModel.articleParent; } }).then(function () { var linkingPromise = $scope.linkedItems.length ? linkItems(createdArticle) : $q.when(1), attachmentPromise = $scope.attachments.length ? addAttachments(createdArticle) : $q.when(1); knowledgeArticleModel.getArticleRevisionsById(createdArticle.id); //just to preload revisions, so user wont wait for them on article detail page. return $q.all([linkingPromise, attachmentPromise]); }).then(function () { $scope.onCreateArticleCompleted(createdArticle); }).catch(function (error) { systemAlertService.error({ text: (error.data.defaultMessage) || (error.data.errorCode ? $filter('i18n')('error.unknown') : error.data.error) }); }).finally(function () { $scope.state.dataIsLoading = false; }); }, 200); }; function saveSetOfVisibilityGroups(visibilities) { localStorageService.set(localStorageLastVisibilitySetKey, visibilities); } function linkItems(createdArticle) { return relationModel.addRelation({ uuid: createdArticle.id, type: EntityVO.TYPE_KNOWLEDGE }, _.map($scope.linkedItems, function (item) { return _.omit(item, ['realObject', 'isPoi']); })); } function addAttachments(createdArticle) { return attachmentService.uploadAttachment(createdArticle.type, createdArticle.id, $scope.attachments); } $scope.onCreateArticleCompleted = function (createdArticle) { state.allowStateChange = true; $state.go('knowledge', { id: createdArticle.id }); }; $scope.cancel = function () { if ($scope.previousTemplate) { state.isTemplateSelected = true; state.isTemplateAccepted = true; $scope.selectedTemplate = _.cloneDeep($scope.previousTemplate); $scope.previousTemplate = null; } else { //trick to avoid triggering $stateChangeStart event $state.go('dashboard', {}, { notify: false }).then(function () { $scope.$emit('$stateChangeSuccess'); }); } }; $scope.discard = function () { showLeaveCreateKnowledgeArticleDialog().then(function (result) { result && $scope.cancel(); }); }; function showLeaveCreateKnowledgeArticleDialog() { var modal = systemAlertService.modal({ type: 'info', title: $filter('i18n')('common.notification.dirty.title'), text: $filter('i18n')('common.notification.dirty.loseChanges'), buttons: [ { text: $filter('i18n')('common.button.yes'), data: true }, { text: $filter('i18n')('common.button.no'), data: false } ] }); return modal.result; } function isArticleDirty() { return isArticleTitleDirty() || isArticleContentDirty() || isArticleMetadataDirty(); } function isArticleContentDirty() { var rawContent = getRawArticleContent(); return !angular.equals(draftArticle.content, rawContent); } function isArticleTitleDirty() { return article.title && article.title.trim(); } function isArticleMetadataDirty() { var articleMetadata = _.omit(article, ['categoriesControls', 'content', 'title']), draftArticleMetadata = _.omit(article, ['categoriesControls', 'content', 'title']); return !angular.equals(articleMetadata, draftArticleMetadata); } function getRawArticleContent() { var articleContentCopy = _.cloneDeep(article.content); return _.map(articleContentCopy, function (section) { section.snippet = $(section.snippet).text(); return section; }); } $scope.state = state; $scope.article = article; $scope.searchService = searchService; $scope.$on('$stateChangeStart', function (event, toState, toParams) { if (!state.allowStateChange && state.isTemplateSelected && state.isTemplateAccepted && isArticleDirty()) { event.preventDefault(); showLeaveCreateKnowledgeArticleDialog().then(function (result) { if (result) { state.allowStateChange = true; $state.go(toState.name, toParams); } }); } }); } ]) .controller('CreateKnowledgeArticleModalController', ['$scope', '$controller', '$modalInstance', 'ticketModel', function ($scope, $controller, $modalInstance, ticketModel) { function initArticleContext() { if (ticketModel.articleParent.type === EntityVO.TYPE_PROBLEM || ticketModel.articleParent.type === EntityVO.TYPE_KNOWNERROR || ticketModel.articleParent.type === EntityVO.TYPE_INCIDENT || ticketModel.articleParent.type === EntityVO.TYPE_WORKORDER) { $scope.articleContext = { id: ticketModel.articleParent.id, type: ticketModel.articleParent.type }; } } initArticleContext(); $.extend(this, $controller('CreateKnowledgeArticleController', { $scope: $scope })); $scope.onCreateArticleCompleted = function (createdArticle) { $modalInstance.close(createdArticle); }; $scope.cancel = function () { $modalInstance.dismiss(); }; $scope.$on('$stateChangeSuccess', $modalInstance.dismiss); } ]); })();