diff options
author | Sean McGivern <sean@mcgivern.me.uk> | 2017-03-13 16:56:33 +0000 |
---|---|---|
committer | Sean McGivern <sean@mcgivern.me.uk> | 2017-03-13 16:56:33 +0000 |
commit | 1585608bdcf932b58d301a7943c01ea824ea524e (patch) | |
tree | 86dc4290cf711aa6f19ab7dc64d432c849cd004b /app/assets | |
parent | 1d4b11f3388ddd7cf0076f95ac26196f6949dc0b (diff) | |
parent | e0fe2834ebe6d9678444c8a10b79ca093f944232 (diff) | |
download | gitlab-ce-1585608bdcf932b58d301a7943c01ea824ea524e.tar.gz |
Merge branch '24501-new-file-existing-branch' into 'master'
New file from interface on existing branch
Closes #24501
See merge request !8427
Diffstat (limited to 'app/assets')
-rw-r--r-- | app/assets/javascripts/blob/blob_file_dropzone.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/blob/create_branch_dropdown.js | 88 | ||||
-rw-r--r-- | app/assets/javascripts/blob/target_branch_dropdown.js | 152 | ||||
-rw-r--r-- | app/assets/javascripts/dispatcher.js | 26 | ||||
-rw-r--r-- | app/assets/javascripts/main.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/new_commit_form.js | 12 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/projects.scss | 3 |
7 files changed, 276 insertions, 9 deletions
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js index 5f14ff40eee..8f6bf162d6e 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js +++ b/app/assets/javascripts/blob/blob_file_dropzone.js @@ -36,7 +36,7 @@ this.removeFile(file); }); return this.on('sending', function(file, xhr, formData) { - formData.append('target_branch', form.find('.js-target-branch').val()); + 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()); }); diff --git a/app/assets/javascripts/blob/create_branch_dropdown.js b/app/assets/javascripts/blob/create_branch_dropdown.js new file mode 100644 index 00000000000..95517f51b1c --- /dev/null +++ b/app/assets/javascripts/blob/create_branch_dropdown.js @@ -0,0 +1,88 @@ +class CreateBranchDropdown { + constructor(el, targetBranchDropdown) { + this.targetBranchDropdown = targetBranchDropdown; + this.el = el; + this.dropdownBack = this.el.closest('.dropdown').querySelector('.dropdown-menu-back'); + this.cancelButton = this.el.querySelector('.js-cancel-branch-btn'); + this.newBranchField = this.el.querySelector('#new_branch_name'); + this.newBranchCreateButton = this.el.querySelector('.js-new-branch-btn'); + + this.newBranchCreateButton.setAttribute('disabled', ''); + + this.addBindings(); + this.cleanupWrapper = this.cleanup.bind(this); + document.addEventListener('beforeunload', this.cleanupWrapper); + } + + cleanup() { + this.cleanBindings(); + document.removeEventListener('beforeunload', this.cleanupWrapper); + } + + cleanBindings() { + this.newBranchField.removeEventListener('keyup', this.enableBranchCreateButtonWrapper); + this.newBranchField.removeEventListener('change', this.enableBranchCreateButtonWrapper); + this.newBranchField.removeEventListener('keydown', this.handleNewBranchKeydownWrapper); + this.dropdownBack.removeEventListener('click', this.resetFormWrapper); + this.cancelButton.removeEventListener('click', this.handleCancelClickWrapper); + this.newBranchCreateButton.removeEventListener('click', this.createBranchWrapper); + } + + addBindings() { + this.enableBranchCreateButtonWrapper = this.enableBranchCreateButton.bind(this); + this.handleNewBranchKeydownWrapper = this.handleNewBranchKeydown.bind(this); + this.resetFormWrapper = this.resetForm.bind(this); + this.handleCancelClickWrapper = this.handleCancelClick.bind(this); + this.createBranchWrapper = this.createBranch.bind(this); + + this.newBranchField.addEventListener('keyup', this.enableBranchCreateButtonWrapper); + this.newBranchField.addEventListener('change', this.enableBranchCreateButtonWrapper); + this.newBranchField.addEventListener('keydown', this.handleNewBranchKeydownWrapper); + this.dropdownBack.addEventListener('click', this.resetFormWrapper); + this.cancelButton.addEventListener('click', this.handleCancelClickWrapper); + this.newBranchCreateButton.addEventListener('click', this.createBranchWrapper); + } + + handleCancelClick(e) { + e.preventDefault(); + e.stopPropagation(); + + this.resetForm(); + this.dropdownBack.click(); + } + + handleNewBranchKeydown(e) { + const keyCode = e.which; + const ENTER_KEYCODE = 13; + if (keyCode === ENTER_KEYCODE) { + this.createBranch(e); + } + } + + enableBranchCreateButton() { + if (this.newBranchField.value !== '') { + this.newBranchCreateButton.removeAttribute('disabled'); + } else { + this.newBranchCreateButton.setAttribute('disabled', ''); + } + } + + resetForm() { + this.newBranchField.value = ''; + this.enableBranchCreateButtonWrapper(); + } + + createBranch(e) { + e.preventDefault(); + + if (this.newBranchCreateButton.getAttribute('disabled') === '') { + return; + } + const newBranchName = this.newBranchField.value; + this.targetBranchDropdown.setNewBranch(newBranchName); + this.resetForm(); + } +} + +window.gl = window.gl || {}; +gl.CreateBranchDropdown = CreateBranchDropdown; diff --git a/app/assets/javascripts/blob/target_branch_dropdown.js b/app/assets/javascripts/blob/target_branch_dropdown.js new file mode 100644 index 00000000000..216f069ef71 --- /dev/null +++ b/app/assets/javascripts/blob/target_branch_dropdown.js @@ -0,0 +1,152 @@ +/* eslint-disable class-methods-use-this */ +const SELECT_ITEM_MSG = 'Select'; + +class TargetBranchDropDown { + constructor(dropdown) { + this.dropdown = dropdown; + this.$dropdown = $(dropdown); + this.fieldName = this.dropdown.getAttribute('data-field-name'); + this.form = this.dropdown.closest('form'); + this.createDropdown(); + } + + static bootstrap() { + const dropdowns = document.querySelectorAll('.js-project-branches-dropdown'); + [].forEach.call(dropdowns, dropdown => new TargetBranchDropDown(dropdown)); + } + + createDropdown() { + const self = this; + this.$dropdown.glDropdown({ + selectable: true, + filterable: true, + search: { + fields: ['title'], + }, + data: (term, callback) => $.ajax({ + url: self.dropdown.getAttribute('data-refs-url'), + data: { + ref: self.dropdown.getAttribute('data-ref'), + show_all: true, + }, + dataType: 'json', + }).done(refs => callback(self.dropdownData(refs))), + toggleLabel(item, el) { + if (el.is('.is-active')) { + return item.text; + } + return SELECT_ITEM_MSG; + }, + clicked(item, el, e) { + e.preventDefault(); + self.onClick.call(self); + }, + fieldName: self.fieldName, + }); + return new gl.CreateBranchDropdown(this.form.querySelector('.dropdown-new-branch'), this); + } + + onClick() { + this.enableSubmit(); + this.$dropdown.trigger('change.branch'); + } + + enableSubmit() { + const submitBtn = this.form.querySelector('[type="submit"]'); + if (this.branchInput && this.branchInput.value) { + submitBtn.removeAttribute('disabled'); + } else { + submitBtn.setAttribute('disabled', ''); + } + } + + dropdownData(refs) { + const branchList = this.dropdownItems(refs); + this.cachedRefs = refs; + this.addDefaultBranch(branchList); + this.addNewBranch(branchList); + return { Branches: branchList }; + } + + dropdownItems(refs) { + return refs.map(this.dropdownItem); + } + + dropdownItem(ref) { + return { id: ref, text: ref, title: ref }; + } + + addDefaultBranch(branchList) { + // when no branch is selected do nothing + if (!this.branchInput) { + return; + } + + const branchInputVal = this.branchInput.value; + const currentBranchIndex = this.searchBranch(branchList, branchInputVal); + + if (currentBranchIndex === -1) { + this.unshiftBranch(branchList, this.dropdownItem(branchInputVal)); + } + } + + addNewBranch(branchList) { + if (this.newBranch) { + this.unshiftBranch(branchList, this.newBranch); + } + } + + searchBranch(branchList, branchName) { + return _.findIndex(branchList, el => branchName === el.id); + } + + unshiftBranch(branchList, branch) { + const branchIndex = this.searchBranch(branchList, branch.id); + + if (branchIndex === -1) { + branchList.unshift(branch); + } + } + + setNewBranch(newBranchName) { + this.newBranch = this.dropdownItem(newBranchName); + this.refreshData(); + this.selectBranch(this.searchBranch(this.glDropdown.fullData.Branches, newBranchName)); + } + + refreshData() { + this.glDropdown.fullData = this.dropdownData(this.cachedRefs); + this.clearFilter(); + } + + clearFilter() { + // apply an empty filter in order to refresh the data + this.glDropdown.filter.filter(''); + this.dropdown.closest('.dropdown').querySelector('.dropdown-page-one .dropdown-input-field').value = ''; + } + + selectBranch(index) { + const branch = this.dropdown.closest('.dropdown').querySelectorAll('li a')[index]; + + if (!branch.classList.contains('is-active')) { + branch.click(); + } else { + this.closeDropdown(); + } + } + + closeDropdown() { + this.dropdown.closest('.dropdown').querySelector('.dropdown-menu-close').click(); + } + + get branchInput() { + return this.form.querySelector(`input[name="${this.fieldName}"]`); + } + + get glDropdown() { + return this.$dropdown.data('glDropdown'); + } +} + +window.gl = window.gl || {}; +gl.TargetBranchDropDown = TargetBranchDropDown; diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 7b9b9123c31..5739a28699f 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -59,7 +59,7 @@ const UserCallout = require('./user_callout'); } Dispatcher.prototype.initPageScripts = function() { - var page, path, shortcut_handler; + var page, path, shortcut_handler, fileBlobPermalinkUrlElement, fileBlobPermalinkUrl; page = $('body').attr('data-page'); if (!page) { return false; @@ -245,16 +245,36 @@ const UserCallout = require('./user_callout'); case 'projects:tree:show': shortcut_handler = new ShortcutsNavigation(); new TreeView(); + gl.TargetBranchDropDown.bootstrap(); break; case 'projects:find_file:show': shortcut_handler = true; break; + case 'projects:blob:new': + gl.TargetBranchDropDown.bootstrap(); + break; + case 'projects:blob:create': + gl.TargetBranchDropDown.bootstrap(); + break; case 'projects:blob:show': + gl.TargetBranchDropDown.bootstrap(); + new LineHighlighter(); + shortcut_handler = new ShortcutsNavigation(); + fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url'); + fileBlobPermalinkUrl = fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href'); + new ShortcutsBlob({ + skipResetBindings: true, + fileBlobPermalinkUrl, + }); + break; + case 'projects:blob:edit': + gl.TargetBranchDropDown.bootstrap(); + break; case 'projects:blame:show': new LineHighlighter(); shortcut_handler = new ShortcutsNavigation(); - const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url'); - const fileBlobPermalinkUrl = fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href'); + fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url'); + fileBlobPermalinkUrl = fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href'); new ShortcutsBlob({ skipResetBindings: true, fileBlobPermalinkUrl, diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 689a6c3a93a..604ed91627a 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -66,6 +66,8 @@ import './blob/blob_gitignore_selectors'; import './blob/blob_license_selector'; import './blob/blob_license_selectors'; import './blob/template_selector'; +import './blob/create_branch_dropdown'; +import './blob/target_branch_dropdown'; // templates import './templates/issuable_template_selector'; diff --git a/app/assets/javascripts/new_commit_form.js b/app/assets/javascripts/new_commit_form.js index 747f693726e..ad36f08840d 100644 --- a/app/assets/javascripts/new_commit_form.js +++ b/app/assets/javascripts/new_commit_form.js @@ -3,19 +3,23 @@ var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; }; this.NewCommitForm = (function() { - function NewCommitForm(form) { + function NewCommitForm(form, targetBranchName = 'target_branch') { + this.form = form; + this.targetBranchName = targetBranchName; this.renderDestination = bind(this.renderDestination, this); - this.newBranch = form.find('.js-target-branch'); + this.targetBranchDropdown = form.find('button.js-target-branch'); this.originalBranch = form.find('.js-original-branch'); this.createMergeRequest = form.find('.js-create-merge-request'); this.createMergeRequestContainer = form.find('.js-create-merge-request-container'); + this.targetBranchDropdown.on('change.branch', this.renderDestination); this.renderDestination(); - this.newBranch.keyup(this.renderDestination); } NewCommitForm.prototype.renderDestination = function() { var different; - different = this.newBranch.val() !== this.originalBranch.val(); + var targetBranch = this.form.find(`input[name="${this.targetBranchName}"]`); + + different = targetBranch.val() !== this.originalBranch.val(); if (different) { this.createMergeRequestContainer.show(); if (!this.wasDifferent) { diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 4914933430f..efa47be9a73 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -795,7 +795,8 @@ pre.light-well { } .project-refs-form .dropdown-menu, -.dropdown-menu-projects { +.dropdown-menu-projects, +.dropdown-menu-branches { width: 300px; @media (min-width: $screen-sm-min) { |