Skip to content
Snippets Groups Projects
Commit b66baea9 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 82cef8dd
No related branches found
No related tags found
No related merge requests found
Showing
with 278 additions and 77 deletions
import $ from 'jquery';
import { slugify } from './lib/utils/text_utility';
import fetchGroupPathAvailability from '~/pages/groups/new/fetch_group_path_availability';
import flash from '~/flash';
import { __ } from '~/locale';
 
export default class Group {
constructor() {
this.groupPath = $('#group_path');
this.groupName = $('#group_name');
this.parentId = $('#group_parent_id');
this.updateHandler = this.update.bind(this);
this.resetHandler = this.reset.bind(this);
this.updateGroupPathSlugHandler = this.updateGroupPathSlug.bind(this);
if (this.groupName.val() === '') {
this.groupName.on('keyup', this.updateHandler);
this.groupPath.on('keydown', this.resetHandler);
if (!this.parentId.val()) {
this.groupName.on('blur', this.updateGroupPathSlugHandler);
}
}
}
 
Loading
Loading
@@ -21,5 +29,21 @@ export default class Group {
reset() {
this.groupName.off('keyup', this.updateHandler);
this.groupPath.off('keydown', this.resetHandler);
this.groupName.off('blur', this.checkPathHandler);
}
updateGroupPathSlug() {
const slug = this.groupPath.val() || slugify(this.groupName.val());
if (!slug) return;
fetchGroupPathAvailability(slug)
.then(({ data }) => data)
.then(data => {
if (data.exists && data.suggests.length > 0) {
const suggestedSlug = data.suggests[0];
this.groupPath.val(suggestedSlug);
}
})
.catch(() => flash(__('An error occurred while checking group path')));
}
}
Loading
Loading
@@ -138,6 +138,14 @@ export const stripHtml = (string, replace = '') => {
*/
export const convertToCamelCase = string => string.replace(/(_\w)/g, s => s[1].toUpperCase());
 
/**
* Converts camelCase string to snake_case
*
* @param {*} string
*/
export const convertToSnakeCase = string =>
slugifyWithUnderscore(string.match(/([a-zA-Z][^A-Z]*)/g).join(' '));
/**
* Converts a sentence to lower case from the second word onwards
* e.g. Hello World => Hello world
Loading
Loading
import axios from '~/lib/utils/axios_utils';
const rootUrl = gon.relative_url_root;
export default function fetchGroupPathAvailability(groupPath) {
return axios.get(`${rootUrl}/users/${groupPath}/suggests`);
}
import InputValidator from '~/validators/input_validator';
import _ from 'underscore';
import fetchGroupPathAvailability from './fetch_group_path_availability';
import flash from '~/flash';
import { __ } from '~/locale';
const debounceTimeoutDuration = 1000;
const invalidInputClass = 'gl-field-error-outline';
const successInputClass = 'gl-field-success-outline';
const successMessageSelector = '.validation-success';
const pendingMessageSelector = '.validation-pending';
const unavailableMessageSelector = '.validation-error';
const suggestionsMessageSelector = '.gl-path-suggestions';
export default class GroupPathValidator extends InputValidator {
constructor(opts = {}) {
super();
const container = opts.container || '';
const validateElements = document.querySelectorAll(`${container} .js-validate-group-path`);
this.debounceValidateInput = _.debounce(inputDomElement => {
GroupPathValidator.validateGroupPathInput(inputDomElement);
}, debounceTimeoutDuration);
validateElements.forEach(element =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
eventHandler(event) {
const inputDomElement = event.target;
GroupPathValidator.resetInputState(inputDomElement);
this.debounceValidateInput(inputDomElement);
}
static validateGroupPathInput(inputDomElement) {
const groupPath = inputDomElement.value;
if (inputDomElement.checkValidity() && groupPath.length > 0) {
GroupPathValidator.setMessageVisibility(inputDomElement, pendingMessageSelector);
fetchGroupPathAvailability(groupPath)
.then(({ data }) => data)
.then(data => {
GroupPathValidator.setInputState(inputDomElement, !data.exists);
GroupPathValidator.setMessageVisibility(inputDomElement, pendingMessageSelector, false);
GroupPathValidator.setMessageVisibility(
inputDomElement,
data.exists ? unavailableMessageSelector : successMessageSelector,
);
if (data.exists) {
GroupPathValidator.showSuggestions(inputDomElement, data.suggests);
}
})
.catch(() => flash(__('An error occurred while validating group path')));
}
}
static showSuggestions(inputDomElement, suggestions) {
const messageElement = inputDomElement.parentElement.parentElement.querySelector(
suggestionsMessageSelector,
);
const textSuggestions = suggestions && suggestions.length > 0 ? suggestions.join(', ') : 'none';
messageElement.textContent = textSuggestions;
}
static setMessageVisibility(inputDomElement, messageSelector, isVisible = true) {
const messageElement = inputDomElement.parentElement.parentElement.querySelector(
messageSelector,
);
messageElement.classList.toggle('hide', !isVisible);
}
static setInputState(inputDomElement, success = true) {
inputDomElement.classList.toggle(successInputClass, success);
inputDomElement.classList.toggle(invalidInputClass, !success);
}
static resetInputState(inputDomElement) {
GroupPathValidator.setMessageVisibility(inputDomElement, successMessageSelector, false);
GroupPathValidator.setMessageVisibility(inputDomElement, unavailableMessageSelector, false);
if (inputDomElement.checkValidity()) {
inputDomElement.classList.remove(successInputClass, invalidInputClass);
}
}
}
import $ from 'jquery';
import BindInOut from '~/behaviors/bind_in_out';
import Group from '~/group';
import initAvatarPicker from '~/avatar_picker';
import GroupPathValidator from './group_path_validator';
 
document.addEventListener('DOMContentLoaded', () => {
const parentId = $('#group_parent_id');
if (!parentId.val()) {
new GroupPathValidator(); // eslint-disable-line no-new
}
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
initAvatarPicker();
Loading
Loading
/* eslint-disable func-names, no-var */
import $ from 'jquery';
import BranchGraph from '../../../network/branch_graph';
 
export default (function() {
function Network(opts) {
var vph;
$('#filter_ref').click(function() {
return $(this)
.closest('form')
.submit();
});
this.branch_graph = new BranchGraph($('.network-graph'), opts);
vph = $(window).height() - 250;
$('.network-graph').css({
height: `${vph}px`,
});
const vph = $(window).height() - 250;
export default class Network {
constructor(opts) {
this.opts = opts;
this.filter_ref = $('#filter_ref');
this.network_graph = $('.network-graph');
this.filter_ref.click(() => this.submit());
this.branch_graph = new BranchGraph(this.network_graph, this.opts);
this.network_graph.css({ height: `${vph}px` });
}
 
return Network;
})();
submit() {
return this.filter_ref.closest('form').submit();
}
}
Loading
Loading
@@ -30,67 +30,65 @@ const projectSelect = () => {
$(select).select2({
placeholder,
minimumInputLength: 0,
query: (function(_this) {
return function(query) {
var finalCallback, projectsCallback;
finalCallback = function(projects) {
var data;
data = {
results: projects,
};
return query.callback(data);
query: query => {
var finalCallback, projectsCallback;
finalCallback = function(projects) {
var data;
data = {
results: projects,
};
if (_this.includeGroups) {
projectsCallback = function(projects) {
var groupsCallback;
groupsCallback = function(groups) {
var data;
data = groups.concat(projects);
return finalCallback(data);
};
return Api.groups(query.term, {}, groupsCallback);
};
} else {
projectsCallback = finalCallback;
}
if (_this.groupId) {
return Api.groupProjects(
_this.groupId,
query.term,
{
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
with_shared: _this.withShared,
include_subgroups: _this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else if (_this.userId) {
return Api.userProjects(
_this.userId,
query.term,
{
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
with_shared: _this.withShared,
include_subgroups: _this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else {
return Api.projects(
query.term,
{
order_by: _this.orderBy,
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
membership: !_this.allProjects,
},
projectsCallback,
);
}
return query.callback(data);
};
})(this),
if (this.includeGroups) {
projectsCallback = function(projects) {
var groupsCallback;
groupsCallback = function(groups) {
var data;
data = groups.concat(projects);
return finalCallback(data);
};
return Api.groups(query.term, {}, groupsCallback);
};
} else {
projectsCallback = finalCallback;
}
if (this.groupId) {
return Api.groupProjects(
this.groupId,
query.term,
{
with_issues_enabled: this.withIssuesEnabled,
with_merge_requests_enabled: this.withMergeRequestsEnabled,
with_shared: this.withShared,
include_subgroups: this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else if (this.userId) {
return Api.userProjects(
this.userId,
query.term,
{
with_issues_enabled: this.withIssuesEnabled,
with_merge_requests_enabled: this.withMergeRequestsEnabled,
with_shared: this.withShared,
include_subgroups: this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else {
return Api.projects(
query.term,
{
order_by: this.orderBy,
with_issues_enabled: this.withIssuesEnabled,
with_merge_requests_enabled: this.withMergeRequestsEnabled,
membership: !this.allProjects,
},
projectsCallback,
);
}
},
id(project) {
if (simpleFilter) return project.id;
return JSON.stringify({
Loading
Loading
Loading
Loading
@@ -563,3 +563,10 @@ img.emoji {
 
.gl-font-size-small { font-size: $gl-font-size-small; }
.gl-line-height-24 { line-height: $gl-line-height-24; }
.gl-font-size-12 { font-size: $gl-font-size-12; }
.gl-font-size-14 { font-size: $gl-font-size-14; }
.gl-font-size-16 { font-size: $gl-font-size-16; }
.gl-font-size-20 { font-size: $gl-font-size-20; }
.gl-font-size-28 { font-size: $gl-font-size-28; }
.gl-font-size-42 { font-size: $gl-font-size-42; }
Loading
Loading
@@ -325,6 +325,12 @@ $gl-grayish-blue: #7f8fa4;
$gl-gray-dark: #313236;
$gl-gray-light: #5c5c5c;
$gl-header-color: #4c4e54;
$gl-font-size-12: 12px;
$gl-font-size-14: 14px;
$gl-font-size-16: 16px;
$gl-font-size-20: 20px;
$gl-font-size-28: 28px;
$gl-font-size-42: 42px;
 
$type-scale: (
1: 12px,
Loading
Loading
Loading
Loading
@@ -22,11 +22,16 @@
- if parent
%strong= parent.full_path + '/'
= f.hidden_field :parent_id
= f.text_field :path, placeholder: 'my-awesome-group', class: 'form-control',
= f.text_field :path, placeholder: 'my-awesome-group', class: 'form-control js-validate-group-path',
autofocus: local_assigns[:autofocus] || false, required: true,
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
title: _('Please choose a group URL with no special characters.'),
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
%p.validation-error.gl-field-error.field-validation.hide
= _('Group path is already taken. Suggestions: ')
%span.gl-path-suggestions
%p.validation-success.gl-field-success.field-validation.hide= _('Group path is available.')
%p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking group path availability...')
 
- if @group.persisted?
.alert.alert-warning.prepend-top-10
Loading
Loading
---
title: New group path uniqueness check
merge_request: 17394
author:
type: added
---
title: Remove IIFEs from project_select.js
merge_request: 19288
author: minghuan lei
type: other
---
title: Removed IIFEs from network.js file
merge_request: 19254
author: nuwe1
type: other
Loading
Loading
@@ -1517,6 +1517,9 @@ msgstr ""
msgid "An error occurred when updating the issue weight"
msgstr ""
 
msgid "An error occurred while checking group path"
msgstr ""
msgid "An error occurred while deleting the approvers group"
msgstr ""
 
Loading
Loading
@@ -1679,6 +1682,9 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
 
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
 
Loading
Loading
@@ -3059,6 +3065,9 @@ msgstr ""
msgid "Checking branch availability..."
msgstr ""
 
msgid "Checking group path availability..."
msgstr ""
msgid "Checking username availability..."
msgstr ""
 
Loading
Loading
@@ -8359,6 +8368,12 @@ msgstr ""
msgid "Group overview content"
msgstr ""
 
msgid "Group path is already taken. Suggestions: "
msgstr ""
msgid "Group path is available."
msgstr ""
msgid "Group pipeline minutes were successfully reset."
msgstr ""
 
Loading
Loading
@@ -16967,6 +16982,12 @@ msgstr ""
msgid "There was an error fetching configuration for charts"
msgstr ""
 
msgid "There was an error fetching cycle analytics stages."
msgstr ""
msgid "There was an error fetching data for the selected stage"
msgstr ""
msgid "There was an error fetching label data for the selected group"
msgstr ""
 
Loading
Loading
@@ -17009,6 +17030,9 @@ msgstr ""
msgid "There was an error while fetching cycle analytics data."
msgstr ""
 
msgid "There was an error while fetching cycle analytics summary data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -90,6 +90,19 @@ describe('text_utility', () => {
});
});
 
describe('convertToSnakeCase', () => {
it.each`
txt | result
${'snakeCase'} | ${'snake_case'}
${'snake Case'} | ${'snake_case'}
${'snake case'} | ${'snake_case'}
${'snake_case'} | ${'snake_case'}
${'snakeCasesnake Case'} | ${'snake_casesnake_case'}
`('converts string $txt to $result string', ({ txt, result }) => {
expect(textUtils.convertToSnakeCase(txt)).toEqual(result);
});
});
describe('convertToSentenceCase', () => {
it('converts Sentence Case to Sentence case', () => {
expect(textUtils.convertToSentenceCase('Hello World')).toBe('Hello world');
Loading
Loading
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment