diff options
Diffstat (limited to 'app/assets/javascripts/blob')
27 files changed, 924 insertions, 134 deletions
diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js new file mode 100644 index 00000000000..68d4ddad551 --- /dev/null +++ b/app/assets/javascripts/blob/3d_viewer/index.js @@ -0,0 +1,147 @@ +import * as THREE from 'three/build/three.module'; +import STLLoaderClass from 'three-stl-loader'; +import OrbitControlsClass from 'three-orbit-controls'; +import MeshObject from './mesh_object'; + +const STLLoader = STLLoaderClass(THREE); +const OrbitControls = OrbitControlsClass(THREE); + +export default class Renderer { + constructor(container) { + this.renderWrapper = this.render.bind(this); + this.objects = []; + + this.container = container; + this.width = this.container.offsetWidth; + this.height = 500; + + this.loader = new STLLoader(); + + this.fov = 45; + this.camera = new THREE.PerspectiveCamera( + this.fov, + this.width / this.height, + 1, + 1000, + ); + + this.scene = new THREE.Scene(); + + this.scene.add(this.camera); + + // Setup the viewer + this.setupRenderer(); + this.setupGrid(); + this.setupLight(); + + // Setup OrbitControls + this.controls = new OrbitControls( + this.camera, + this.renderer.domElement, + ); + this.controls.minDistance = 5; + this.controls.maxDistance = 30; + this.controls.enableKeys = false; + + this.loadFile(); + } + + setupRenderer() { + this.renderer = new THREE.WebGLRenderer({ + antialias: true, + }); + + this.renderer.setClearColor(0xFFFFFF); + this.renderer.setPixelRatio(window.devicePixelRatio); + this.renderer.setSize( + this.width, + this.height, + ); + } + + setupLight() { + // Point light illuminates the object + const pointLight = new THREE.PointLight( + 0xFFFFFF, + 2, + 0, + ); + + pointLight.castShadow = true; + + this.camera.add(pointLight); + + // Ambient light illuminates the scene + const ambientLight = new THREE.AmbientLight( + 0xFFFFFF, + 1, + ); + this.scene.add(ambientLight); + } + + setupGrid() { + this.grid = new THREE.GridHelper( + 20, + 20, + 0x000000, + 0x000000, + ); + + this.scene.add(this.grid); + } + + loadFile() { + this.loader.load(this.container.dataset.endpoint, (geo) => { + const obj = new MeshObject(geo); + + this.objects.push(obj); + this.scene.add(obj); + + this.start(); + this.setDefaultCameraPosition(); + }); + } + + start() { + // Empty the container first + this.container.innerHTML = ''; + + // Add to DOM + this.container.appendChild(this.renderer.domElement); + + // Make controls visible + this.container.parentNode.classList.remove('is-stl-loading'); + + this.render(); + } + + render() { + this.renderer.render( + this.scene, + this.camera, + ); + + requestAnimationFrame(this.renderWrapper); + } + + changeObjectMaterials(type) { + this.objects.forEach((obj) => { + obj.changeMaterial(type); + }); + } + + setDefaultCameraPosition() { + const obj = this.objects[0]; + const radius = (obj.geometry.boundingSphere.radius / 1.5); + const dist = radius / (Math.sin((this.fov * (Math.PI / 180)) / 2)); + + this.camera.position.set( + 0, + dist + 1, + dist, + ); + + this.camera.lookAt(this.grid); + this.controls.update(); + } +} diff --git a/app/assets/javascripts/blob/3d_viewer/mesh_object.js b/app/assets/javascripts/blob/3d_viewer/mesh_object.js new file mode 100644 index 00000000000..96758884abf --- /dev/null +++ b/app/assets/javascripts/blob/3d_viewer/mesh_object.js @@ -0,0 +1,49 @@ +import { + Matrix4, + MeshLambertMaterial, + Mesh, +} from 'three/build/three.module'; + +const defaultColor = 0xE24329; +const materials = { + default: new MeshLambertMaterial({ + color: defaultColor, + }), + wireframe: new MeshLambertMaterial({ + color: defaultColor, + wireframe: true, + }), +}; + +export default class MeshObject extends Mesh { + constructor(geo) { + super( + geo, + materials.default, + ); + + this.geometry.computeBoundingSphere(); + + this.rotation.set(-Math.PI / 2, 0, 0); + + if (this.geometry.boundingSphere.radius > 4) { + const scale = 4 / this.geometry.boundingSphere.radius; + + this.geometry.applyMatrix( + new Matrix4().makeScale( + scale, + scale, + scale, + ), + ); + this.geometry.computeBoundingSphere(); + + this.position.x = -this.geometry.boundingSphere.center.x; + this.position.z = this.geometry.boundingSphere.center.y; + } + } + + changeMaterial(type) { + this.material = materials[type]; + } +} diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js index c9fe23aec75..4568b86f298 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js +++ b/app/assets/javascripts/blob/blob_file_dropzone.js @@ -35,7 +35,7 @@ export default class BlobFileDropzone { this.removeFile(file); }); this.on('sending', function (file, xhr, formData) { - formData.append('target_branch', form.find('input[name="target_branch"]').val()); + formData.append('branch_name', form.find('input[name="branch_name"]').val()); formData.append('create_merge_request', form.find('.js-create-merge-request').val()); formData.append('commit_message', form.find('.js-commit-message').val()); }); diff --git a/app/assets/javascripts/blob/blob_fork_suggestion.js b/app/assets/javascripts/blob/blob_fork_suggestion.js new file mode 100644 index 00000000000..aa9a4e1c99a --- /dev/null +++ b/app/assets/javascripts/blob/blob_fork_suggestion.js @@ -0,0 +1,15 @@ +function BlobForkSuggestion(openButton, cancelButton, suggestionSection) { + if (openButton) { + openButton.addEventListener('click', () => { + suggestionSection.classList.remove('hidden'); + }); + } + + if (cancelButton) { + cancelButton.addEventListener('click', () => { + suggestionSection.classList.add('hidden'); + }); + } +} + +export default BlobForkSuggestion; diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js new file mode 100644 index 00000000000..3062cd51ee3 --- /dev/null +++ b/app/assets/javascripts/blob/file_template_mediator.js @@ -0,0 +1,241 @@ +/* eslint-disable class-methods-use-this */ +/* global Flash */ + +import FileTemplateTypeSelector from './template_selectors/type_selector'; +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'; + +export default class FileTemplateMediator { + constructor({ editor, currentAction }) { + this.editor = editor; + this.currentAction = currentAction; + + this.initTemplateSelectors(); + this.initTemplateTypeSelector(); + this.initDomElements(); + this.initDropdowns(); + this.initPageEvents(); + } + + initTemplateSelectors() { + // Order dictates template type dropdown item order + this.templateSelectors = [ + GitignoreSelector, + BlobCiYamlSelector, + DockerfileSelector, + LicenseSelector, + ].map(TemplateSelectorClass => new TemplateSelectorClass({ mediator: this })); + } + + initTemplateTypeSelector() { + this.typeSelector = new FileTemplateTypeSelector({ + mediator: this, + dropdownData: this.templateSelectors + .map((templateSelector) => { + const cfg = templateSelector.config; + + return { + name: cfg.name, + key: cfg.key, + }; + }), + }); + } + + 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.typeSelector.show(); + } else { + this.hideTemplateSelectorMenu(); + } + + this.displayMatchedTemplateSelector(); + } + + initPageEvents() { + this.listenForFilenameInput(); + this.prepFileContentForSubmit(); + this.listenForPreviewMode(); + } + + listenForFilenameInput() { + this.$filenameInput.on('keyup blur', () => { + this.displayMatchedTemplateSelector(); + }); + } + + prepFileContentForSubmit() { + this.$commitForm.submit(() => { + this.$fileContent.val(this.editor.getValue()); + }); + } + + 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.showTemplateSelectorMenu(); + } + }); + } + + selectTemplateType(item, el, e) { + if (e) { + e.preventDefault(); + } + + this.templateSelectors.forEach((selector) => { + if (selector.config.key === item.key) { + selector.show(); + } else { + selector.hide(); + } + }); + + this.typeSelector.setToggleText(item.name); + + this.cacheToggleText(); + } + + selectTemplateFile(selector, query, data) { + selector.renderLoading(); + // in case undo menu is already already there + this.destroyUndoMenu(); + this.fetchFileTemplate(selector.config.endpoint, query, data) + .then((file) => { + this.showUndoMenu(); + this.setEditorContent(file); + this.setFilename(selector.config.name); + selector.renderLoaded(); + }) + .catch(err => new Flash(`An error occurred while fetching the template: ${err}`)); + } + + displayMatchedTemplateSelector() { + const currentInput = this.getFilename(); + this.templateSelectors.forEach((selector) => { + const match = selector.config.pattern.test(currentInput); + + if (match) { + this.typeSelector.show(); + this.selectTemplateType(selector.config); + this.showTemplateSelectorMenu(); + } + }); + } + + fetchFileTemplate(apiCall, query, data) { + return new Promise((resolve) => { + const resolveFile = file => resolve(file); + + if (!data) { + apiCall(query, resolveFile); + } else { + apiCall(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(); + } + + findTemplateSelectorByKey(key) { + return this.templateSelectors.find(selector => selector.config.key === key); + } + + showUndoMenu() { + this.$undoMenu.removeClass('hidden'); + + this.$undoBtn.on('click', () => { + this.restoreFromCache(); + this.destroyUndoMenu(); + }); + } + + destroyUndoMenu() { + this.cacheFileContents(); + this.cacheToggleText(); + this.$undoMenu.addClass('hidden'); + this.$undoBtn.off('click'); + } + + hideTemplateSelectorMenu() { + this.$templatesMenu.hide(); + } + + showTemplateSelectorMenu() { + this.$templatesMenu.show(); + } + + 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); + } + + getTypeSelectorToggleText() { + return this.typeSelector.getToggleText(); + } + + getFilename() { + return this.$filenameInput.val(); + } + + setFilename(name) { + this.$filenameInput.val(name); + } + + getSelected() { + return this.templateSelectors.find(selector => selector.selected); + } +} diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js new file mode 100644 index 00000000000..31dd45fac89 --- /dev/null +++ b/app/assets/javascripts/blob/file_template_selector.js @@ -0,0 +1,60 @@ +/* global Api */ + +export default class FileTemplateSelector { + constructor(mediator) { + this.mediator = mediator; + this.$dropdown = null; + this.$wrapper = null; + } + + init() { + const cfg = this.config; + + this.$dropdown = $(cfg.dropdown); + this.$wrapper = $(cfg.wrapper); + this.$loadingIcon = this.$wrapper.find('.fa-chevron-down'); + this.$dropdownToggleText = this.$wrapper.find('.dropdown-toggle-text'); + + this.initDropdown(); + } + + show() { + if (this.$dropdown === null) { + this.init(); + } + + this.$wrapper.removeClass('hidden'); + } + + hide() { + if (this.$dropdown !== null) { + this.$wrapper.addClass('hidden'); + } + } + + getToggleText() { + return this.$dropdownToggleText.text(); + } + + setToggleText(text) { + this.$dropdownToggleText.text(text); + } + + renderLoading() { + this.$loadingIcon + .addClass('fa-spinner fa-spin') + .removeClass('fa-chevron-down'); + } + + renderLoaded() { + this.$loadingIcon + .addClass('fa-chevron-down') + .removeClass('fa-spinner fa-spin'); + } + + reportSelection(query, el, e, data) { + e.preventDefault(); + return this.mediator.selectTemplateFile(this, query, data); + } +} + diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js new file mode 100644 index 00000000000..9b8bfbfc8c0 --- /dev/null +++ b/app/assets/javascripts/blob/notebook/index.js @@ -0,0 +1,85 @@ +/* eslint-disable no-new */ +import Vue from 'vue'; +import VueResource from 'vue-resource'; +import NotebookLab from 'vendor/notebooklab'; + +Vue.use(VueResource); +Vue.use(NotebookLab); + +export default () => { + const el = document.getElementById('js-notebook-viewer'); + + new Vue({ + el, + data() { + return { + error: false, + loadError: false, + loading: true, + json: {}, + }; + }, + template: ` + <div class="container-fluid md prepend-top-default append-bottom-default"> + <div + class="text-center loading" + v-if="loading && !error"> + <i + class="fa fa-spinner fa-spin" + aria-hidden="true" + aria-label="iPython notebook loading"> + </i> + </div> + <notebook-lab + v-if="!loading && !error" + :notebook="json" + code-css-class="code white" /> + <p + class="text-center" + v-if="error"> + <span v-if="loadError"> + An error occured whilst loading the file. Please try again later. + </span> + <span v-else> + An error occured whilst parsing the file. + </span> + </p> + </div> + `, + methods: { + loadFile() { + this.$http.get(el.dataset.endpoint) + .then((res) => { + this.json = res.json(); + this.loading = false; + }) + .catch((e) => { + if (e.status) { + this.loadError = true; + } + + this.error = true; + }); + }, + }, + mounted() { + if (gon.katex_css_url) { + const katexStyles = document.createElement('link'); + katexStyles.setAttribute('rel', 'stylesheet'); + katexStyles.setAttribute('href', gon.katex_css_url); + document.head.appendChild(katexStyles); + } + + if (gon.katex_js_url) { + const katexScript = document.createElement('script'); + katexScript.addEventListener('load', () => { + this.loadFile(); + }); + katexScript.setAttribute('src', gon.katex_js_url); + document.head.appendChild(katexScript); + } else { + this.loadFile(); + } + }, + }); +}; diff --git a/app/assets/javascripts/blob/notebook_viewer.js b/app/assets/javascripts/blob/notebook_viewer.js new file mode 100644 index 00000000000..b7a0a195a92 --- /dev/null +++ b/app/assets/javascripts/blob/notebook_viewer.js @@ -0,0 +1,3 @@ +import renderNotebook from './notebook'; + +document.addEventListener('DOMContentLoaded', renderNotebook); diff --git a/app/assets/javascripts/blob/pdf/index.js b/app/assets/javascripts/blob/pdf/index.js new file mode 100644 index 00000000000..a74c2db9a61 --- /dev/null +++ b/app/assets/javascripts/blob/pdf/index.js @@ -0,0 +1,62 @@ +/* eslint-disable no-new */ +import Vue from 'vue'; +import PDFLab from 'vendor/pdflab'; +import workerSrc from 'vendor/pdf.worker'; + +Vue.use(PDFLab, { + workerSrc, +}); + +export default () => { + const el = document.getElementById('js-pdf-viewer'); + + return new Vue({ + el, + data() { + return { + error: false, + loadError: false, + loading: true, + pdf: el.dataset.endpoint, + }; + }, + methods: { + onLoad() { + this.loading = false; + }, + onError(error) { + this.loading = false; + this.loadError = true; + this.error = error; + }, + }, + template: ` + <div class="container-fluid md prepend-top-default append-bottom-default"> + <div + class="text-center loading" + v-if="loading && !error"> + <i + class="fa fa-spinner fa-spin" + aria-hidden="true" + aria-label="PDF loading"> + </i> + </div> + <pdf-lab + v-if="!loadError" + :pdf="pdf" + @pdflabload="onLoad" + @pdflaberror="onError" /> + <p + class="text-center" + v-if="error"> + <span v-if="loadError"> + An error occured whilst loading the file. Please try again later. + </span> + <span v-else> + An error occured whilst decoding the file. + </span> + </p> + </div> + `, + }); +}; diff --git a/app/assets/javascripts/blob/pdf_viewer.js b/app/assets/javascripts/blob/pdf_viewer.js new file mode 100644 index 00000000000..91abe9dd699 --- /dev/null +++ b/app/assets/javascripts/blob/pdf_viewer.js @@ -0,0 +1,3 @@ +import renderPDF from './pdf'; + +document.addEventListener('DOMContentLoaded', renderPDF); diff --git a/app/assets/javascripts/blob/sketch/index.js b/app/assets/javascripts/blob/sketch/index.js new file mode 100644 index 00000000000..0799991aa40 --- /dev/null +++ b/app/assets/javascripts/blob/sketch/index.js @@ -0,0 +1,73 @@ +import JSZip from 'jszip'; +import JSZipUtils from 'jszip-utils'; + +export default class SketchLoader { + constructor(container) { + this.container = container; + this.loadingIcon = this.container.querySelector('.js-loading-icon'); + + this.load(); + } + + load() { + return this.getZipFile() + .then(data => JSZip.loadAsync(data)) + .then(asyncResult => asyncResult.files['previews/preview.png'].async('uint8array')) + .then((content) => { + const url = window.URL || window.webkitURL; + const blob = new Blob([new Uint8Array(content)], { + type: 'image/png', + }); + const previewUrl = url.createObjectURL(blob); + + this.render(previewUrl); + }) + .catch(this.error.bind(this)); + } + + getZipFile() { + return new JSZip.external.Promise((resolve, reject) => { + JSZipUtils.getBinaryContent(this.container.dataset.endpoint, (err, data) => { + if (err) { + reject(err); + } else { + resolve(data); + } + }); + }); + } + + render(previewUrl) { + const previewLink = document.createElement('a'); + const previewImage = document.createElement('img'); + + previewLink.href = previewUrl; + previewLink.target = '_blank'; + previewImage.src = previewUrl; + previewImage.className = 'img-responsive'; + + previewLink.appendChild(previewImage); + this.container.appendChild(previewLink); + + this.removeLoadingIcon(); + } + + error() { + const errorMsg = document.createElement('p'); + + errorMsg.className = 'prepend-top-default append-bottom-default text-center'; + errorMsg.textContent = ` + Cannot show preview. For previews on sketch files, they must have the file format + introduced by Sketch version 43 and above. + `; + this.container.appendChild(errorMsg); + + this.removeLoadingIcon(); + } + + removeLoadingIcon() { + if (this.loadingIcon) { + this.loadingIcon.remove(); + } + } +} diff --git a/app/assets/javascripts/blob/sketch_viewer.js b/app/assets/javascripts/blob/sketch_viewer.js new file mode 100644 index 00000000000..0640dd26855 --- /dev/null +++ b/app/assets/javascripts/blob/sketch_viewer.js @@ -0,0 +1,8 @@ +/* eslint-disable no-new */ +import SketchLoader from './sketch'; + +document.addEventListener('DOMContentLoaded', () => { + const el = document.getElementById('js-sketch-viewer'); + + new SketchLoader(el); +}); diff --git a/app/assets/javascripts/blob/stl_viewer.js b/app/assets/javascripts/blob/stl_viewer.js new file mode 100644 index 00000000000..f611c4fe640 --- /dev/null +++ b/app/assets/javascripts/blob/stl_viewer.js @@ -0,0 +1,19 @@ +import Renderer from './3d_viewer'; + +document.addEventListener('DOMContentLoaded', () => { + const viewer = new Renderer(document.getElementById('js-stl-viewer')); + + [].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => { + el.addEventListener('click', (e) => { + const target = e.target; + + e.preventDefault(); + + document.querySelector('.js-material-changer.active').classList.remove('active'); + target.classList.add('active'); + target.blur(); + + viewer.changeObjectMaterials(target.dataset.type); + }); + }); +}); diff --git a/app/assets/javascripts/blob/template_selectors/template_selector.js b/app/assets/javascripts/blob/template_selector.js index d7c1c32efbd..d7c1c32efbd 100644 --- a/app/assets/javascripts/blob/template_selectors/template_selector.js +++ b/app/assets/javascripts/blob/template_selector.js diff --git a/app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js b/app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js deleted file mode 100644 index 5a5954e7751..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selector.js +++ /dev/null @@ -1,9 +0,0 @@ -/* global Api */ - -import TemplateSelector from './template_selector'; - -export default class BlobCiYamlSelector extends TemplateSelector { - requestFile(query) { - return Api.gitlabCiYml(query.name, (file, config) => this.setEditorContent(file, config)); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selectors.js b/app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selectors.js deleted file mode 100644 index 7a4d6a42a03..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_ci_yaml_selectors.js +++ /dev/null @@ -1,23 +0,0 @@ -/* global Api */ - -import BlobCiYamlSelector from './blob_ci_yaml_selector'; - -export default class BlobCiYamlSelectors { - constructor({ editor, $dropdowns }) { - this.$dropdowns = $dropdowns || $('.js-gitlab-ci-yml-selector'); - this.initSelectors(editor); - } - - initSelectors(editor) { - this.$dropdowns.each((i, dropdown) => { - const $dropdown = $(dropdown); - return new BlobCiYamlSelector({ - editor, - pattern: /(.gitlab-ci.yml)/, - data: $dropdown.data('data'), - wrapper: $dropdown.closest('.js-gitlab-ci-yml-selector-wrap'), - dropdown: $dropdown, - }); - }); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/blob_dockerfile_selector.js deleted file mode 100644 index 19f8820a0cb..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_dockerfile_selector.js +++ /dev/null @@ -1,9 +0,0 @@ -/* global Api */ - -import TemplateSelector from './template_selector'; - -export default class BlobDockerfileSelector extends TemplateSelector { - requestFile(query) { - return Api.dockerfileYml(query.name, (file, config) => this.setEditorContent(file, config)); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_dockerfile_selectors.js b/app/assets/javascripts/blob/template_selectors/blob_dockerfile_selectors.js deleted file mode 100644 index da067035b43..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_dockerfile_selectors.js +++ /dev/null @@ -1,23 +0,0 @@ -import BlobDockerfileSelector from './blob_dockerfile_selector'; - -export default class BlobDockerfileSelectors { - constructor({ editor, $dropdowns }) { - this.editor = editor; - this.$dropdowns = $dropdowns || $('.js-dockerfile-selector'); - this.initSelectors(); - } - - initSelectors() { - const editor = this.editor; - this.$dropdowns.each((i, dropdown) => { - const $dropdown = $(dropdown); - return new BlobDockerfileSelector({ - editor, - pattern: /(Dockerfile)/, - data: $dropdown.data('data'), - wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'), - dropdown: $dropdown, - }); - }); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_gitignore_selector.js b/app/assets/javascripts/blob/template_selectors/blob_gitignore_selector.js deleted file mode 100644 index 0b6b02fc2b3..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_gitignore_selector.js +++ /dev/null @@ -1,9 +0,0 @@ -/* global Api */ - -import TemplateSelector from './template_selector'; - -export default class BlobGitignoreSelector extends TemplateSelector { - requestFile(query) { - return Api.gitignoreText(query.name, (file, config) => this.setEditorContent(file, config)); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_gitignore_selectors.js b/app/assets/javascripts/blob/template_selectors/blob_gitignore_selectors.js deleted file mode 100644 index dc485d97677..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_gitignore_selectors.js +++ /dev/null @@ -1,23 +0,0 @@ -import BlobGitignoreSelector from './blob_gitignore_selector'; - -export default class BlobGitignoreSelectors { - constructor({ editor, $dropdowns }) { - this.$dropdowns = $dropdowns || $('.js-gitignore-selector'); - this.editor = editor; - this.initSelectors(); - } - - initSelectors() { - this.$dropdowns.each((i, dropdown) => { - const $dropdown = $(dropdown); - - return new BlobGitignoreSelector({ - pattern: /(.gitignore)/, - data: $dropdown.data('data'), - wrapper: $dropdown.closest('.js-gitignore-selector-wrap'), - dropdown: $dropdown, - editor: this.editor, - }); - }); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_license_selector.js b/app/assets/javascripts/blob/template_selectors/blob_license_selector.js deleted file mode 100644 index e9cb31cc2dc..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_license_selector.js +++ /dev/null @@ -1,13 +0,0 @@ -/* global Api */ - -import TemplateSelector from './template_selector'; - -export default class BlobLicenseSelector extends TemplateSelector { - requestFile(query) { - const data = { - project: this.dropdown.data('project'), - fullname: this.dropdown.data('fullname'), - }; - return Api.licenseText(query.id, data, (file, config) => this.setEditorContent(file, config)); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/blob_license_selectors.js b/app/assets/javascripts/blob/template_selectors/blob_license_selectors.js deleted file mode 100644 index a44f4f78b2d..00000000000 --- a/app/assets/javascripts/blob/template_selectors/blob_license_selectors.js +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable no-unused-vars, no-param-reassign */ - -import BlobLicenseSelector from './blob_license_selector'; - -export default class BlobLicenseSelectors { - constructor({ $dropdowns, editor }) { - this.$dropdowns = $dropdowns || $('.js-license-selector'); - this.initSelectors(editor); - } - - initSelectors(editor) { - this.$dropdowns.each((i, dropdown) => { - const $dropdown = $(dropdown); - - return new BlobLicenseSelector({ - editor, - pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i, - data: $dropdown.data('data'), - wrapper: $dropdown.closest('.js-license-selector-wrap'), - dropdown: $dropdown, - }); - }); - } -} diff --git a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js new file mode 100644 index 00000000000..935df07677c --- /dev/null +++ b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js @@ -0,0 +1,32 @@ +/* global Api */ + +import FileTemplateSelector from '../file_template_selector'; + +export default class BlobCiYamlSelector extends FileTemplateSelector { + constructor({ mediator }) { + super(mediator); + this.config = { + key: 'gitlab-ci-yaml', + name: '.gitlab-ci.yml', + pattern: /(.gitlab-ci.yml)/, + endpoint: Api.gitlabCiYml, + dropdown: '.js-gitlab-ci-yml-selector', + wrapper: '.js-gitlab-ci-yml-selector-wrap', + }; + } + + initDropdown() { + // maybe move to super class as well + this.$dropdown.glDropdown({ + data: this.$dropdown.data('data'), + filterable: true, + selectable: true, + toggleLabel: item => item.name, + search: { + fields: ['name'], + }, + clicked: (query, el, e) => this.reportSelection(query.name, el, e), + text: item => item.name, + }); + } +} diff --git a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js new file mode 100644 index 00000000000..b4b4d09c315 --- /dev/null +++ b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js @@ -0,0 +1,32 @@ +/* global Api */ + +import FileTemplateSelector from '../file_template_selector'; + +export default class DockerfileSelector extends FileTemplateSelector { + constructor({ mediator }) { + super(mediator); + this.config = { + key: 'dockerfile', + name: 'Dockerfile', + pattern: /(Dockerfile)/, + endpoint: Api.dockerfileYml, + dropdown: '.js-dockerfile-selector', + wrapper: '.js-dockerfile-selector-wrap', + }; + } + + initDropdown() { + // maybe move to super class as well + this.$dropdown.glDropdown({ + data: this.$dropdown.data('data'), + filterable: true, + selectable: true, + toggleLabel: item => item.name, + search: { + fields: ['name'], + }, + clicked: (query, el, e) => this.reportSelection(query.name, el, e), + text: item => item.name, + }); + } +} diff --git a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js new file mode 100644 index 00000000000..aefae54ae71 --- /dev/null +++ b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js @@ -0,0 +1,31 @@ +/* global Api */ + +import FileTemplateSelector from '../file_template_selector'; + +export default class BlobGitignoreSelector extends FileTemplateSelector { + constructor({ mediator }) { + super(mediator); + this.config = { + key: 'gitignore', + name: '.gitignore', + pattern: /(.gitignore)/, + endpoint: Api.gitignoreText, + dropdown: '.js-gitignore-selector', + wrapper: '.js-gitignore-selector-wrap', + }; + } + + initDropdown() { + this.$dropdown.glDropdown({ + data: this.$dropdown.data('data'), + filterable: true, + selectable: true, + toggleLabel: item => item.name, + search: { + fields: ['name'], + }, + clicked: (query, el, e) => this.reportSelection(query.name, el, e), + text: item => item.name, + }); + } +} diff --git a/app/assets/javascripts/blob/template_selectors/license_selector.js b/app/assets/javascripts/blob/template_selectors/license_selector.js new file mode 100644 index 00000000000..c8abd689ab4 --- /dev/null +++ b/app/assets/javascripts/blob/template_selectors/license_selector.js @@ -0,0 +1,38 @@ +/* global Api */ + +import FileTemplateSelector from '../file_template_selector'; + +export default class BlobLicenseSelector extends FileTemplateSelector { + constructor({ mediator }) { + super(mediator); + this.config = { + key: 'license', + name: 'LICENSE', + pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i, + endpoint: Api.licenseText, + dropdown: '.js-license-selector', + wrapper: '.js-license-selector-wrap', + }; + } + + initDropdown() { + this.$dropdown.glDropdown({ + data: this.$dropdown.data('data'), + filterable: true, + selectable: true, + toggleLabel: item => item.name, + search: { + fields: ['name'], + }, + clicked: (query, el, e) => { + const data = { + project: this.$dropdown.data('project'), + fullname: this.$dropdown.data('fullname'), + }; + + this.reportSelection(query.id, el, e, data); + }, + text: item => item.name, + }); + } +} diff --git a/app/assets/javascripts/blob/template_selectors/type_selector.js b/app/assets/javascripts/blob/template_selectors/type_selector.js new file mode 100644 index 00000000000..56f23ef0568 --- /dev/null +++ b/app/assets/javascripts/blob/template_selectors/type_selector.js @@ -0,0 +1,25 @@ +import FileTemplateSelector from '../file_template_selector'; + +export default class FileTemplateTypeSelector extends FileTemplateSelector { + constructor({ mediator, dropdownData }) { + super(mediator); + this.mediator = mediator; + this.config = { + dropdown: '.js-template-type-selector', + wrapper: '.js-template-type-selector-wrap', + dropdownData, + }; + } + + initDropdown() { + this.$dropdown.glDropdown({ + data: this.config.dropdownData, + filterable: false, + selectable: true, + toggleLabel: item => item.name, + clicked: (item, el, e) => this.mediator.selectTemplateType(item, el, e), + text: item => item.name, + }); + } + +} |