Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/issues/create_merge_request_dropdown.js')
-rw-r--r--app/assets/javascripts/issues/create_merge_request_dropdown.js120
1 files changed, 80 insertions, 40 deletions
diff --git a/app/assets/javascripts/issues/create_merge_request_dropdown.js b/app/assets/javascripts/issues/create_merge_request_dropdown.js
index 27ba94c8381..caf82e482ea 100644
--- a/app/assets/javascripts/issues/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/issues/create_merge_request_dropdown.js
@@ -11,6 +11,10 @@ import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+import {
+ findInvalidBranchNameCharacters,
+ humanizeBranchValidationErrors,
+} from '~/lib/utils/text_utility';
import api from '~/api';
// Todo: Remove this when fixing issue in input_setter plugin
@@ -19,6 +23,12 @@ const InputSetter = { ...ISetter };
const CREATE_MERGE_REQUEST = 'create-mr';
const CREATE_BRANCH = 'create-branch';
+const VALIDATION_TYPE_BRANCH_UNAVAILABLE = 'branch_unavailable';
+const VALIDATION_TYPE_INVALID_CHARS = 'invalid_chars';
+
+const INPUT_TARGET_BRANCH = 'branch';
+const INPUT_TARGET_REF = 'ref';
+
function createEndpoint(projectPath, endpoint) {
if (canCreateConfidentialMergeRequest()) {
return endpoint.replace(
@@ -30,6 +40,23 @@ function createEndpoint(projectPath, endpoint) {
return endpoint;
}
+function getValidationError(target, inputValue, validationType) {
+ const invalidChars = findInvalidBranchNameCharacters(inputValue.value);
+ let text;
+
+ if (invalidChars && validationType === VALIDATION_TYPE_INVALID_CHARS) {
+ text = humanizeBranchValidationErrors(invalidChars);
+ }
+
+ if (validationType === VALIDATION_TYPE_BRANCH_UNAVAILABLE) {
+ text =
+ target === INPUT_TARGET_BRANCH
+ ? __('Branch is already taken')
+ : __('Source is not available');
+ }
+
+ return text;
+}
export default class CreateMergeRequestDropdown {
constructor(wrapperEl) {
this.wrapperEl = wrapperEl;
@@ -124,18 +151,19 @@ export default class CreateMergeRequestDropdown {
.then(({ data }) => {
this.setUnavailableButtonState(false);
- if (data.can_create_branch) {
- this.available();
- this.enable();
- this.updateBranchName(data.suggested_branch_name);
-
- if (!this.droplabInitialized) {
- this.droplabInitialized = true;
- this.initDroplab();
- this.bindEvents();
- }
- } else {
+ if (!data.can_create_branch) {
this.hide();
+ return;
+ }
+
+ this.available();
+ this.enable();
+ this.updateBranchName(data.suggested_branch_name);
+
+ if (!this.droplabInitialized) {
+ this.droplabInitialized = true;
+ this.initDroplab();
+ this.bindEvents();
}
})
.catch(() => {
@@ -274,7 +302,7 @@ export default class CreateMergeRequestDropdown {
const tags = data[Object.keys(data)[1]];
let result;
- if (target === 'branch') {
+ if (target === INPUT_TARGET_BRANCH) {
result = CreateMergeRequestDropdown.findByValue(branches, ref);
} else {
result =
@@ -354,10 +382,10 @@ export default class CreateMergeRequestDropdown {
}
if (event.target === this.branchInput) {
- target = 'branch';
+ target = INPUT_TARGET_BRANCH;
({ value } = this.branchInput);
} else if (event.target === this.refInput) {
- target = 'ref';
+ target = INPUT_TARGET_REF;
if (event.target === document.activeElement) {
value =
event.target.value.slice(0, event.target.selectionStart) +
@@ -382,7 +410,7 @@ export default class CreateMergeRequestDropdown {
this.createBranchPath = this.wrapperEl.dataset.createBranchPath;
this.createMrPath = this.wrapperEl.dataset.createMrPath;
- if (target === 'branch') {
+ if (target === INPUT_TARGET_BRANCH) {
this.branchIsValid = true;
} else {
this.refIsValid = true;
@@ -473,7 +501,7 @@ export default class CreateMergeRequestDropdown {
showAvailableMessage(target) {
const { input, message } = this.getTargetData(target);
- const text = target === 'branch' ? __('Branch name') : __('Source');
+ const text = target === INPUT_TARGET_BRANCH ? __('Branch name') : __('Source');
this.removeMessage(target);
input.classList.add('gl-field-success-outline');
@@ -484,7 +512,7 @@ export default class CreateMergeRequestDropdown {
showCheckingMessage(target) {
const { message } = this.getTargetData(target);
- const text = target === 'branch' ? __('branch name') : __('source');
+ const text = target === INPUT_TARGET_BRANCH ? __('branch name') : __('source');
this.removeMessage(target);
message.classList.add('gl-text-gray-600');
@@ -492,10 +520,9 @@ export default class CreateMergeRequestDropdown {
message.style.display = 'inline-block';
}
- showNotAvailableMessage(target) {
+ showNotAvailableMessage(target, validationType = VALIDATION_TYPE_BRANCH_UNAVAILABLE) {
const { input, message } = this.getTargetData(target);
- const text =
- target === 'branch' ? __('Branch is already taken') : __('Source is not available');
+ const text = getValidationError(target, input, validationType);
this.removeMessage(target);
input.classList.add('gl-field-error-outline');
@@ -511,35 +538,35 @@ export default class CreateMergeRequestDropdown {
updateBranchName(suggestedBranchName) {
this.branchInput.value = suggestedBranchName;
- this.updateCreatePaths('branch', suggestedBranchName);
+ this.updateInputState(INPUT_TARGET_BRANCH, suggestedBranchName, '');
+ this.updateCreatePaths(INPUT_TARGET_BRANCH, suggestedBranchName);
}
updateInputState(target, ref, result) {
// target - 'branch' or 'ref' - which the input field we are searching a ref for.
// ref - string - what a user typed.
// result - string - what has been found on backend.
+ if (target === INPUT_TARGET_BRANCH) this.updateTargetBranchInput(ref, result);
+ if (target === INPUT_TARGET_REF) this.updateRefInput(ref, result);
+
+ if (this.inputsAreValid()) {
+ this.enable();
+ } else {
+ this.disableCreateAction();
+ }
+ }
- // If a found branch equals exact the same text a user typed,
- // that means a new branch cannot be created as it already exists.
+ updateRefInput(ref, result) {
+ this.refInput.dataset.value = ref;
if (ref === result) {
- if (target === 'branch') {
- this.branchIsValid = false;
- this.showNotAvailableMessage('branch');
- } else {
- this.refIsValid = true;
- this.refInput.dataset.value = ref;
- this.showAvailableMessage('ref');
- this.updateCreatePaths(target, ref);
- }
- } else if (target === 'branch') {
- this.branchIsValid = true;
- this.showAvailableMessage('branch');
- this.updateCreatePaths(target, ref);
+ this.refIsValid = true;
+ this.showAvailableMessage(INPUT_TARGET_REF);
+ this.updateCreatePaths(INPUT_TARGET_REF, ref);
} else {
this.refIsValid = false;
this.refInput.dataset.value = ref;
this.disableCreateAction();
- this.showNotAvailableMessage('ref');
+ this.showNotAvailableMessage(INPUT_TARGET_REF);
// Show ref hint.
if (result) {
@@ -547,11 +574,24 @@ export default class CreateMergeRequestDropdown {
this.refInput.setSelectionRange(ref.length, result.length);
}
}
+ }
- if (this.inputsAreValid()) {
- this.enable();
+ updateTargetBranchInput(ref, result) {
+ const branchNameErrors = findInvalidBranchNameCharacters(ref);
+ const isInvalidString = branchNameErrors.length;
+ if (ref !== result && !isInvalidString) {
+ this.branchIsValid = true;
+ // If a found branch equals exact the same text a user typed,
+ // Or user typed input contains invalid chars,
+ // that means a new branch cannot be created as it already exists.
+ this.showAvailableMessage(INPUT_TARGET_BRANCH, VALIDATION_TYPE_BRANCH_UNAVAILABLE);
+ this.updateCreatePaths(INPUT_TARGET_BRANCH, ref);
+ } else if (isInvalidString) {
+ this.branchIsValid = false;
+ this.showNotAvailableMessage(INPUT_TARGET_BRANCH, VALIDATION_TYPE_INVALID_CHARS);
} else {
- this.disableCreateAction();
+ this.branchIsValid = false;
+ this.showNotAvailableMessage(INPUT_TARGET_BRANCH);
}
}