Skip to content
Snippets Groups Projects

Resolve "Customize branch name when using create branch in an issue"

Compare and Show latest version
3 files
+ 87
61
Compare changes
  • Side-by-side
  • Inline
Files
3
@@ -2,6 +2,7 @@
import Flash from './flash';
import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter';
import { __, sprintf } from './locale';
// Todo: Remove this when fixing issue in input_setter plugin
const InputSetter = Object.assign({}, ISetter);
@@ -55,7 +56,8 @@ export default class CreateMergeRequestDropdown {
this.dropdownToggle.addEventListener('click', this.onClickSetFocusOnBranchNameInput.bind(this));
this.branchInput.addEventListener('keyup', this.onChangeInput.bind(this));
this.refInput.addEventListener('keyup', this.onChangeInput.bind(this));
// this.refInput.addEventListener('keydown', this.processTab.bind(this));
this.refInput.addEventListener('keydown', CreateMergeRequestDropdown.processTab.bind(this));
this.refInput.addEventListener('blur', this.clearRefHint.bind(this));
}
checkAbilityToCreateBranch() {
@@ -87,6 +89,11 @@ export default class CreateMergeRequestDropdown {
});
}
clearRefHint() {
this.refInput.value = this.refInput.value.slice(0, this.refInput.selectionStart) +
this.refInput.value.slice(this.refInput.selectionEnd);
}
createBranch() {
return $.ajax({
method: 'POST',
@@ -141,10 +148,10 @@ export default class CreateMergeRequestDropdown {
this.dropdownToggle.removeAttribute('disabled');
}
findByValue(objects, ref, returnFirstMatch = false) {
static findByValue(objects, ref, returnFirstMatch = false) {
if (!objects || !objects.length) return false;
if (objects.indexOf(ref) > -1) return ref;
if (returnFirstMatch) return objects[0];
if (returnFirstMatch) return objects.find(item => new RegExp(`^${ref}`).test(item));
return false;
}
@@ -194,9 +201,10 @@ export default class CreateMergeRequestDropdown {
let result;
if (target === 'branch') {
result = this.findByValue(branches, ref);
result = CreateMergeRequestDropdown.findByValue(branches, ref);
} else {
result = this.findByValue(branches, ref, true) || this.findByValue(tags, ref, true);
result = CreateMergeRequestDropdown.findByValue(branches, ref, true) ||
CreateMergeRequestDropdown.findByValue(tags, ref, true);
}
return this.updateInputState(target, ref, result);
@@ -268,11 +276,11 @@ export default class CreateMergeRequestDropdown {
this.createMrPath = this.wrapperEl.dataset.createMrPath;
this.inputsAreValid = true;
this.enable();
this.showMessage(target, 'available');
this.showAvailableMessage(target);
return true;
}
this.showMessage(target, 'checking');
this.showCheckingMessage(target);
clearTimeout(this.getRefDelay);
this.getRefDelay = setTimeout(() => {
@@ -311,15 +319,21 @@ export default class CreateMergeRequestDropdown {
}
// `TAB` autocompletes the source.
processTab(event) {
static processTab(event) {
if (event.keyCode !== 9) return;
const value = event.srcElement.value;
event.preventDefault();
window.getSelection().removeAllRanges();
}
removeMessage(target) {
const input = target === 'branch' ? this.branchInput : this.refInput;
const message = target === 'branch' ? this.branchMessage : this.refMessage;
const inputClasses = ['gl-field-error-outline', 'gl-field-success-outline'];
const messageClasses = ['gl-field-hint', 'gl-field-error-message', 'gl-field-success-message'];
this.refInput.value = '';
this.refInput.value = value;
inputClasses.forEach((cssClass) => { input.classList.remove(cssClass); });
messageClasses.forEach((cssClass) => { message.classList.remove(cssClass); });
}
setUnavailableButtonState(isLoading = true) {
@@ -334,9 +348,7 @@ export default class CreateMergeRequestDropdown {
}
}
// target: 'branch', 'ref'
// type: 'checking', 'available', 'not_available'
showMessage(target, type) {
showAvailableMessage(target) {
let input;
let message;
let text;
@@ -351,42 +363,51 @@ export default class CreateMergeRequestDropdown {
text = 'source';
}
// Remove gl-field error classes
input.classList.remove('gl-field-error-outline');
input.classList.remove('gl-field-success-outline');
message.classList.remove('gl-field-hint');
message.classList.remove('gl-field-error-message');
message.classList.remove('gl-field-success-message');
this.removeMessage(target);
input.classList.add('gl-field-success-outline');
message.classList.add('gl-field-success-message');
message.textContent = sprintf(__('%{text} is available'), { text });
message.classList.remove('hide');
}
if (type === 'checking') {
message.classList.add('gl-field-hint');
message.textContent = `Checking ${text} availability...`;
message.classList.remove('hide');
showCheckingMessage(target) {
let message;
let text;
return;
if (target === 'branch') {
message = this.branchMessage;
text = 'branch name';
} else {
message = this.refMessage;
text = 'source';
}
if (type === 'not_available') {
if (target === 'branch') {
text = 'Branch is already taken';
} else {
text = 'Source is not available';
}
this.removeMessage(target);
message.classList.add('gl-field-hint');
message.textContent = sprintf(__('Checking %{text} availability...'), { text });
message.classList.remove('hide');
}
input.classList.add('gl-field-error-outline');
message.classList.add('gl-field-error-message');
message.textContent = text;
message.classList.remove('hide');
showNotAvailableMessage(target) {
let input;
let message;
let text;
return;
if (target === 'branch') {
input = this.branchInput;
message = this.branchMessage;
text = __('Branch is already taken');
} else {
input = this.refInput;
message = this.refMessage;
text = __('Source is not available');
}
if (type === 'available') {
input.classList.add('gl-field-success-outline');
message.classList.add('gl-field-success-message');
message.textContent = `${text} is available`;
message.classList.remove('hide');
}
this.removeMessage(target);
input.classList.add('gl-field-error-outline');
message.classList.add('gl-field-error-message');
message.textContent = text;
message.classList.remove('hide');
}
unavailable() {
@@ -395,16 +416,17 @@ export default class CreateMergeRequestDropdown {
}
updateInputState(target, ref, result) {
// These regexps are used to replace a backend generated new branch name and its source (ref) with
// user's inputs.
// These regexps are used to replace
// a backend generated new branch name and its source (ref)
// with user's inputs.
const regexps = {
branch: {
createBranchPath: new RegExp('(branch_name=)(.+?)(?=&issue)'),
createMrPath: new RegExp('(branch_name=)(.+?)(?=&ref)')
createMrPath: new RegExp('(branch_name=)(.+?)(?=&ref)'),
},
ref: {
createBranchPath: new RegExp('(ref=)(.+?)$'),
createMrPath: new RegExp('(ref=)(.+?)$')
createMrPath: new RegExp('(ref=)(.+?)$'),
},
};
@@ -414,25 +436,29 @@ export default class CreateMergeRequestDropdown {
if (target === 'branch') {
this.inputsAreValid = false;
this.disableCreateAction();
this.showMessage('branch', 'not_available');
this.showNotAvailableMessage('branch');
} else {
this.inputsAreValid = true;
this.enable();
this.showMessage('ref', 'available');
this.showAvailableMessage('ref');
this.createBranchPath = this.createBranchPath.replace(regexps.ref.createBranchPath, `$1${ref}`);
this.createMrPath = this.createMrPath.replace(regexps.ref.createMrPath, `$1${ref}`);
}
} else if (target === 'branch') {
this.inputsAreValid = true;
this.enable();
this.showAvailableMessage('branch');
this.createBranchPath = this.createBranchPath.replace(regexps.branch.createBranchPath, `$1${ref}`);
this.createMrPath = this.createMrPath.replace(regexps.branch.createMrPath, `$1${ref}`);
} else {
if (target === 'branch') {
this.inputsAreValid = true;
this.enable();
this.showMessage('branch', 'available');
this.createBranchPath = this.createBranchPath.replace(regexps.branch.createBranchPath, `$1${ref}`);
this.createMrPath = this.createMrPath.replace(regexps.branch.createMrPath, `$1${ref}`);
} else {
this.inputsAreValid = false;
this.disableCreateAction();
this.showMessage('ref', 'not_available');
this.inputsAreValid = false;
this.disableCreateAction();
this.showNotAvailableMessage('ref');
// Show ref hint.
if (result) {
this.refInput.value = result;
this.refInput.setSelectionRange(ref.length, result.length);
}
}
}
Loading