import $ from 'jquery'; import Api from '~/api'; import initPopover from '~/blob/suggest_gitlab_ci_yml'; import { createAlert } from '~/alert'; import { __ } from '~/locale'; import toast from '~/vue_shared/plugins/global_toast'; import BlobCiYamlSelector from './template_selectors/ci_yaml_selector'; import DockerfileSelector from './template_selectors/dockerfile_selector'; import GitignoreSelector from './template_selectors/gitignore_selector'; import LicenseSelector from './template_selectors/license_selector'; import MetricsDashboardSelector from './template_selectors/metrics_dashboard_selector'; export default class FileTemplateMediator { constructor({ editor, currentAction, projectId }) { this.editor = editor; this.currentAction = currentAction; this.projectId = projectId; this.initTemplateSelectors(); this.initDomElements(); this.initDropdowns(); this.initPageEvents(); this.cacheFileContents(); } initTemplateSelectors() { // Order dictates template type dropdown item order this.templateSelectors = [ GitignoreSelector, BlobCiYamlSelector, MetricsDashboardSelector, DockerfileSelector, LicenseSelector, ].map((TemplateSelectorClass) => new TemplateSelectorClass({ mediator: this })); } initDomElements() { const $templatesMenu = $('.template-selectors-menu'); const $undoMenu = $templatesMenu.find('.template-selectors-undo-menu'); const $fileEditor = $('.file-editor'); this.$templatesMenu = $templatesMenu; this.$undoMenu = $undoMenu; this.$undoBtn = $undoMenu.find('button'); this.$templateSelectors = $templatesMenu.find('.template-selector-dropdowns-wrap'); this.$filenameInput = $fileEditor.find('.js-file-path-name-input'); this.$fileContent = $fileEditor.find('#file-content'); this.$commitForm = $fileEditor.find('form'); this.$navLinks = $fileEditor.find('.nav-links'); } initDropdowns() { if (this.currentAction !== 'create') { this.hideTemplateSelectorMenu(); } this.displayMatchedTemplateSelector(); } initPageEvents() { this.listenForFilenameInput(); this.listenForPreviewMode(); } listenForFilenameInput() { this.$filenameInput.on('keyup blur', () => { this.displayMatchedTemplateSelector(); }); } listenForPreviewMode() { this.$navLinks.on('click', 'a', (e) => { const urlPieces = e.target.href.split('#'); const hash = urlPieces[1]; if (hash === 'preview') { this.hideTemplateSelectorMenu(); } else if (hash === 'editor' && this.templateSelectors.find((sel) => sel.dropdown !== null)) { this.showTemplateSelectorMenu(); } }); } selectTemplateFile(selector, query, data) { const self = this; const { name } = selector.config; const suggestCommitChanges = document.querySelector('.js-suggest-gitlab-ci-yml-commit-changes'); selector.renderLoading(); this.fetchFileTemplate(selector.config.type, query, data) .then((file) => { this.setEditorContent(file); this.setFilename(name); selector.renderLoaded(); toast(__(`${query} template applied`), { action: { text: __('Undo'), onClick: (e, toastObj) => { self.restoreFromCache(); toastObj.hide(); }, }, }); if (suggestCommitChanges) { initPopover(suggestCommitChanges); } }) .catch((err) => createAlert({ message: __(`An error occurred while fetching the template: ${err}`), }), ); } displayMatchedTemplateSelector() { const currentInput = this.getFilename(); const matchedSelector = this.templateSelectors.find((sel) => sel.config.pattern.test(currentInput), ); const currentSelector = this.templateSelectors.find((sel) => !sel.isHidden()); if (matchedSelector) { if (currentSelector) { currentSelector.hide(); } matchedSelector.show(); this.showTemplateSelectorMenu(); } else { this.hideTemplateSelectorMenu(); } } fetchFileTemplate(type, query, data = {}) { return new Promise((resolve) => { const resolveFile = (file) => resolve(file); Api.projectTemplate(this.projectId, type, query, data, resolveFile); }); } setEditorContent(file) { if (!file && file !== '') return; const newValue = file.content || file; this.editor.setValue(newValue, 1); this.editor.focus(); this.editor.navigateFileStart(); } hideTemplateSelectorMenu() { this.$templatesMenu.hide(); } showTemplateSelectorMenu() { this.$templatesMenu.show(); this.cacheToggleText(); } cacheToggleText() { this.cachedToggleText = this.getTemplateSelectorToggleText(); } cacheFileContents() { this.cachedContent = this.editor.getValue(); this.cachedFilename = this.getFilename(); } restoreFromCache() { this.setEditorContent(this.cachedContent); this.setFilename(this.cachedFilename); this.setTemplateSelectorToggleText(); } getTemplateSelectorToggleText() { return this.$templateSelectors .find('.js-template-selector-wrap:visible .dropdown-toggle-text') .text(); } setTemplateSelectorToggleText() { return this.$templateSelectors .find('.js-template-selector-wrap:visible .dropdown-toggle-text') .text(this.cachedToggleText); } getFilename() { return this.$filenameInput.val(); } setFilename(name) { const input = this.$filenameInput.get(0); if (name !== undefined && input.value !== name) { input.value = name; input.dispatchEvent(new Event('change')); } } }