GitLab steht Mittwoch, den 23. September, zwischen 10:00 und 12:00 Uhr aufgrund von Wartungsarbeiten nicht zur Verfügung.

Commit 1b7eddd8 authored by Alfredo Sumaran's avatar Alfredo Sumaran

Merge branch 'refactor-templates-js' into 'master'

Refactor template selector JavaScript

See merge request !9792
parents 453d755a faf7865c
/* eslint-disable no-param-reassign, comma-dangle */
/* global Api */
require('./template_selector');
((global) => {
class BlobCiYamlSelector extends gl.TemplateSelector {
requestFile(query) {
return Api.gitlabCiYml(query.name, this.requestFileSuccess.bind(this));
}
requestFileSuccess(file) {
return super.requestFileSuccess(file);
}
}
global.BlobCiYamlSelector = BlobCiYamlSelector;
class BlobCiYamlSelectors {
constructor({ editor, $dropdowns } = {}) {
this.editor = editor;
this.$dropdowns = $dropdowns || $('.js-gitlab-ci-yml-selector');
this.initSelectors();
}
initSelectors() {
const editor = this.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
});
});
}
}
global.BlobCiYamlSelectors = BlobCiYamlSelectors;
})(window.gl || (window.gl = {}));
/* global Api */
require('./template_selector');
(() => {
const global = window.gl || (window.gl = {});
class BlobDockerfileSelector extends gl.TemplateSelector {
requestFile(query) {
return Api.dockerfileYml(query.name, this.requestFileSuccess.bind(this));
}
requestFileSuccess(file) {
return super.requestFileSuccess(file);
}
}
global.BlobDockerfileSelector = BlobDockerfileSelector;
})();
(() => {
const global = window.gl || (window.gl = {});
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 gl.BlobDockerfileSelector({
editor,
pattern: /(Dockerfile)/,
data: $dropdown.data('data'),
wrapper: $dropdown.closest('.js-dockerfile-selector-wrap'),
dropdown: $dropdown,
});
});
}
}
global.BlobDockerfileSelectors = BlobDockerfileSelectors;
})();
/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, camelcase, object-shorthand, quotes, comma-dangle, prefer-arrow-callback, no-unused-vars, prefer-template, no-useless-escape, no-alert, max-len */
/* eslint-disable func-names, object-shorthand, prefer-arrow-callback */
/* global Dropzone */
(function() {
this.BlobFileDropzone = (function() {
function BlobFileDropzone(form, method) {
var dropzone, form_dropzone, submitButton;
form_dropzone = form.find('.dropzone');
Dropzone.autoDiscover = false;
dropzone = form_dropzone.dropzone({
autoDiscover: false,
autoProcessQueue: false,
url: form.attr('action'),
// Rails uses a hidden input field for PUT
// http://stackoverflow.com/questions/21056482/how-to-set-method-put-in-form-tag-in-rails
method: method,
clickable: true,
uploadMultiple: false,
paramName: "file",
maxFilesize: gon.max_file_size || 10,
parallelUploads: 1,
maxFiles: 1,
addRemoveLinks: true,
previewsContainer: '.dropzone-previews',
headers: {
"X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
},
init: function() {
this.on('addedfile', function(file) {
$('.dropzone-alerts').html('').hide();
});
this.on('success', function(header, response) {
window.location.href = response.filePath;
});
this.on('maxfilesexceeded', function(file) {
this.removeFile(file);
});
return this.on('sending', function(file, xhr, formData) {
formData.append('target_branch', form.find('input[name="target_branch"]').val());
formData.append('create_merge_request', form.find('.js-create-merge-request').val());
formData.append('commit_message', form.find('.js-commit-message').val());
});
},
// Override behavior of adding error underneath preview
error: function(file, errorMessage) {
var stripped;
stripped = $("<div/>").html(errorMessage).text();
$('.dropzone-alerts').html('Error uploading file: \"' + stripped + '\"').show();
export default class BlobFileDropzone {
constructor(form, method) {
const formDropzone = form.find('.dropzone');
Dropzone.autoDiscover = false;
const dropzone = formDropzone.dropzone({
autoDiscover: false,
autoProcessQueue: false,
url: form.attr('action'),
// Rails uses a hidden input field for PUT
// http://stackoverflow.com/questions/21056482/how-to-set-method-put-in-form-tag-in-rails
method: method,
clickable: true,
uploadMultiple: false,
paramName: 'file',
maxFilesize: gon.max_file_size || 10,
parallelUploads: 1,
maxFiles: 1,
addRemoveLinks: true,
previewsContainer: '.dropzone-previews',
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'),
},
init: function () {
this.on('addedfile', function () {
$('.dropzone-alerts').html('').hide();
});
this.on('success', function (header, response) {
window.location.href = response.filePath;
});
this.on('maxfilesexceeded', function (file) {
this.removeFile(file);
}
});
submitButton = form.find('#submit-all')[0];
submitButton.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
alert("Please select a file");
}
dropzone[0].dropzone.processQueue();
return false;
});
}
});
this.on('sending', function (file, xhr, formData) {
formData.append('target_branch', form.find('input[name="target_branch"]').val());
formData.append('create_merge_request', form.find('.js-create-merge-request').val());
formData.append('commit_message', form.find('.js-commit-message').val());
});
},
// Override behavior of adding error underneath preview
error: function (file, errorMessage) {
const stripped = $('<div/>').html(errorMessage).text();
$('.dropzone-alerts').html(`Error uploading file: "${stripped}"`).show();
this.removeFile(file);
},
});
return BlobFileDropzone;
})();
}).call(window);
const submitButton = form.find('#submit-all')[0];
submitButton.addEventListener('click', function (e) {
e.preventDefault();
e.stopPropagation();
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
// eslint-disable-next-line no-alert
alert('Please select a file');
}
dropzone[0].dropzone.processQueue();
return false;
});
}
}
/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params */
/* global Api */
require('./template_selector');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
this.BlobGitignoreSelector = (function(superClass) {
extend(BlobGitignoreSelector, superClass);
function BlobGitignoreSelector() {
return BlobGitignoreSelector.__super__.constructor.apply(this, arguments);
}
BlobGitignoreSelector.prototype.requestFile = function(query) {
return Api.gitignoreText(query.name, this.requestFileSuccess.bind(this));
};
return BlobGitignoreSelector;
})(gl.TemplateSelector);
}).call(window);
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-cond-assign, no-sequences, comma-dangle, max-len */
/* global BlobGitignoreSelector */
(function() {
this.BlobGitignoreSelectors = (function() {
function BlobGitignoreSelectors(opts) {
var ref;
this.$dropdowns = (ref = opts.$dropdowns) != null ? ref : $('.js-gitignore-selector'), this.editor = opts.editor;
this.$dropdowns.each((function(_this) {
return function(i, dropdown) {
var $dropdown;
$dropdown = $(dropdown);
return new BlobGitignoreSelector({
pattern: /(.gitignore)/,
data: $dropdown.data('data'),
wrapper: $dropdown.closest('.js-gitignore-selector-wrap'),
dropdown: $dropdown,
editor: _this.editor
});
};
})(this));
}
return BlobGitignoreSelectors;
})();
}).call(window);
/* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, comma-dangle */
/* global Api */
require('./template_selector');
(function() {
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
this.BlobLicenseSelector = (function(superClass) {
extend(BlobLicenseSelector, superClass);
function BlobLicenseSelector() {
return BlobLicenseSelector.__super__.constructor.apply(this, arguments);
}
BlobLicenseSelector.prototype.requestFile = function(query) {
var data;
data = {
project: this.dropdown.data('project'),
fullname: this.dropdown.data('fullname')
};
return Api.licenseText(query.id, data, this.requestFileSuccess.bind(this));
};
return BlobLicenseSelector;
})(gl.TemplateSelector);
}).call(window);
/* eslint-disable no-unused-vars, no-param-reassign */
/* global BlobLicenseSelector */
((global) => {
class BlobLicenseSelectors {
constructor({ $dropdowns, editor }) {
this.$dropdowns = $('.js-license-selector');
this.editor = 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,
});
});
}
}
global.BlobLicenseSelectors = BlobLicenseSelectors;
})(window.gl || (window.gl = {}));
/* eslint-disable comma-dangle, object-shorthand, func-names, space-before-function-paren, arrow-parens, no-unused-vars, class-methods-use-this, no-var, consistent-return, no-param-reassign, max-len */
((global) => {
class TemplateSelector {
constructor({ dropdown, data, pattern, wrapper, editor, fileEndpoint, $input } = {}) {
this.onClick = this.onClick.bind(this);
this.dropdown = dropdown;
this.data = data;
this.pattern = pattern;
this.wrapper = wrapper;
this.editor = editor;
this.fileEndpoint = fileEndpoint;
this.$input = $input || $('#file_name');
this.dropdownIcon = $('.fa-chevron-down', this.dropdown);
this.buildDropdown();
this.bindEvents();
this.onFilenameUpdate();
this.autosizeUpdateEvent = document.createEvent('Event');
this.autosizeUpdateEvent.initEvent('autosize:update', true, false);
}
buildDropdown() {
return this.dropdown.glDropdown({
data: this.data,
filterable: true,
selectable: true,
toggleLabel: this.toggleLabel,
search: {
fields: ['name']
},
clicked: this.onClick,
text: function(item) {
return item.name;
}
});
}
bindEvents() {
return this.$input.on('keyup blur', (e) => this.onFilenameUpdate());
}
toggleLabel(item) {
return item.name;
}
onFilenameUpdate() {
var filenameMatches;
if (!this.$input.length) {
return;
}
filenameMatches = this.pattern.test(this.$input.val().trim());
if (!filenameMatches) {
this.wrapper.addClass('hidden');
return;
}
return this.wrapper.removeClass('hidden');
}
onClick(item, el, e) {
e.preventDefault();
return this.requestFile(item);
}
requestFile(item) {
// This `requestFile` method is an abstract method that should
// be added by all subclasses.
}
// To be implemented on the extending class
// e.g.
// Api.gitignoreText item.name, @requestFileSuccess.bind(@)
requestFileSuccess(file, { skipFocus } = {}) {
if (!file) return;
const oldValue = this.editor.getValue();
const newValue = file.content;
this.editor.setValue(newValue, 1);
if (!skipFocus) this.editor.focus();
if (this.editor instanceof jQuery) {
this.editor.get(0).dispatchEvent(this.autosizeUpdateEvent);
}
}
startLoadingSpinner() {
this.dropdownIcon
.addClass('fa-spinner fa-spin')
.removeClass('fa-chevron-down');
}
stopLoadingSpinner() {
this.dropdownIcon
.addClass('fa-chevron-down')
.removeClass('fa-spinner fa-spin');
}
}
global.TemplateSelector = TemplateSelector;
})(window.gl || (window.gl = {}));
/* 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));
}
}
/* 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,
});
});
}
}
/* 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));
}
}
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,
});
});
}
}
/* 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));
}
}
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,
});
});
}
}
/* 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));
}
}
/* 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,
});
});
}
}
/* eslint-disable class-methods-use-this, no-unused-vars */
export default class TemplateSelector {
constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) {
this.pattern = pattern;
this.editor = editor;
this.dropdown = dropdown;
this.$dropdownContainer = wrapper;
this.$filenameInput = $input || $('#file_name');
this.$dropdownIcon = $('.fa-chevron-down', dropdown);
this.initDropdown(dropdown, data);
this.listenForFilenameInput();
this.renderMatchedDropdown();
this.initAutosizeUpdateEvent();
}
initDropdown(dropdown, data) {
return $(dropdown).glDropdown({
data,
filterable: true,
selectable: true,
toggleLabel: item => item.name,
search: {
fields: ['name'],
},
clicked: (item, el, e) => this.fetchFileTemplate(item, el, e),
text: item => item.name,
});
}
initAutosizeUpdateEvent() {
this.autosizeUpdateEvent = document.createEvent('Event');
this.autosizeUpdateEvent.initEvent('autosize:update', true, false);
}
listenForFilenameInput() {
return this.$filenameInput.on('keyup blur', e => this.renderMatchedDropdown(e));
}
renderMatchedDropdown() {
if (!this.$filenameInput.length) {
return null;
}
const filenameMatches = this.pattern.test(this.$filenameInput.val().trim());
if (!filenameMatches) {
return this.$dropdownContainer.addClass('hidden');
}
return this.$dropdownContainer.removeClass('hidden');
}
fetchFileTemplate(item, el, e) {
e.preventDefault();
return this.requestFile(item);
}
requestFile(item) {
// This `requestFile` method is an abstract method that should
// be added by all subclasses.
}
// To be implemented on the extending class
// e.g. Api.gitlabCiYml(query.name, file => this.setEditorContent(file));
setEditorContent(file, { skipFocus } = {}) {
if (!file) return;
const newValue = file.content;
this.editor.setValue(newValue, 1);
if (!skipFocus) this.editor.focus();
if (this.editor instanceof jQuery) {
this.editor.get(0).dispatchEvent(this.autosizeUpdateEvent);
}
}
startLoadingSpinner() {
this.$dropdownIcon
.addClass('fa-spinner fa-spin')
.removeClass('fa-chevron-down');
}
stopLoadingSpinner() {
this.$dropdownIcon
.addClass('fa-chevron-down')
.removeClass('fa-spinner fa-spin');
}
}