Skip to content
Snippets Groups Projects
Commit efec7e08 authored by Dennis Tang's avatar Dennis Tang Committed by Phil Hughes
Browse files

Resolve "Frontend for clarifying the usefulness of the search bar"

parent 8a1d55a3
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
Showing
with 598 additions and 430 deletions
/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, one-var-declaration-per-line, max-len, vars-on-top, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */
/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, one-var-declaration-per-line, max-len, vars-on-top, wrap-iife, no-unused-vars, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */
/* global fuzzaldrinPlus */
 
import $ from 'jquery';
Loading
Loading
@@ -19,32 +19,42 @@ GitLabDropdownInput = (function() {
this.fieldName = this.options.fieldName || 'field-name';
$inputContainer = this.input.parent();
$clearButton = $inputContainer.find('.js-dropdown-input-clear');
$clearButton.on('click', (function(_this) {
// Clear click
return function(e) {
e.preventDefault();
e.stopPropagation();
return _this.input.val('').trigger('input').focus();
};
})(this));
$clearButton.on(
'click',
(function(_this) {
// Clear click
return function(e) {
e.preventDefault();
e.stopPropagation();
return _this.input
.val('')
.trigger('input')
.focus();
};
})(this),
);
 
this.input
.on('keydown', function (e) {
var keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
}
})
.on('input', function(e) {
var val = e.currentTarget.value || _this.options.inputFieldName;
val = val.split(' ').join('-') // replaces space with dash
.replace(/[^a-zA-Z0-9 -]/g, '').toLowerCase() // replace non alphanumeric
.replace(/(-)\1+/g, '-'); // replace repeated dashes
_this.cb(_this.options.fieldName, val, {}, true);
_this.input.closest('.dropdown')
.find('.dropdown-toggle-text')
.text(val);
});
.on('keydown', function(e) {
var keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
}
})
.on('input', function(e) {
var val = e.currentTarget.value || _this.options.inputFieldName;
val = val
.split(' ')
.join('-') // replaces space with dash
.replace(/[^a-zA-Z0-9 -]/g, '')
.toLowerCase() // replace non alphanumeric
.replace(/(-)\1+/g, '-'); // replace repeated dashes
_this.cb(_this.options.fieldName, val, {}, true);
_this.input
.closest('.dropdown')
.find('.dropdown-toggle-text')
.text(val);
});
}
 
GitLabDropdownInput.prototype.onInput = function(cb) {
Loading
Loading
@@ -61,7 +71,7 @@ GitLabDropdownFilter = (function() {
 
ARROW_KEY_CODES = [38, 40];
 
HAS_VALUE_CLASS = "has-value";
HAS_VALUE_CLASS = 'has-value';
 
function GitLabDropdownFilter(input, options) {
var $clearButton, $inputContainer, ref, timeout;
Loading
Loading
@@ -70,44 +80,59 @@ GitLabDropdownFilter = (function() {
this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true;
$inputContainer = this.input.parent();
$clearButton = $inputContainer.find('.js-dropdown-input-clear');
$clearButton.on('click', (function(_this) {
// Clear click
return function(e) {
e.preventDefault();
e.stopPropagation();
return _this.input.val('').trigger('input').focus();
};
})(this));
$clearButton.on(
'click',
(function(_this) {
// Clear click
return function(e) {
e.preventDefault();
e.stopPropagation();
return _this.input
.val('')
.trigger('input')
.focus();
};
})(this),
);
// Key events
timeout = "";
timeout = '';
this.input
.on('keydown', function (e) {
.on('keydown', function(e) {
var keyCode = e.which;
if (keyCode === 13 && !options.elIsInput) {
e.preventDefault();
}
})
.on('input', function() {
if (this.input.val() !== "" && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(HAS_VALUE_CLASS);
} else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.removeClass(HAS_VALUE_CLASS);
}
// Only filter asynchronously only if option remote is set
if (this.options.remote) {
clearTimeout(timeout);
return timeout = setTimeout(function() {
$inputContainer.parent().addClass('is-loading');
return this.options.query(this.input.val(), function(data) {
$inputContainer.parent().removeClass('is-loading');
return this.options.callback(data);
}.bind(this));
}.bind(this), 250);
} else {
return this.filter(this.input.val());
}
}.bind(this));
.on(
'input',
function() {
if (this.input.val() !== '' && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.addClass(HAS_VALUE_CLASS);
} else if (this.input.val() === '' && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
$inputContainer.removeClass(HAS_VALUE_CLASS);
}
// Only filter asynchronously only if option remote is set
if (this.options.remote) {
clearTimeout(timeout);
return (timeout = setTimeout(
function() {
$inputContainer.parent().addClass('is-loading');
return this.options.query(
this.input.val(),
function(data) {
$inputContainer.parent().removeClass('is-loading');
return this.options.callback(data);
}.bind(this),
);
}.bind(this),
250,
));
} else {
return this.filter(this.input.val());
}
}.bind(this),
);
}
 
GitLabDropdownFilter.prototype.shouldBlur = function(keyCode) {
Loading
Loading
@@ -120,7 +145,7 @@ GitLabDropdownFilter = (function() {
this.options.onFilter(search_text);
}
data = this.options.data();
if ((data != null) && !this.options.filterByText) {
if (data != null && !this.options.filterByText) {
results = data;
if (search_text !== '') {
// When data is an array of objects therefore [object Array] e.g.
Loading
Loading
@@ -130,7 +155,7 @@ GitLabDropdownFilter = (function() {
// ]
if (_.isArray(data)) {
results = fuzzaldrinPlus.filter(data, search_text, {
key: this.options.keys
key: this.options.keys,
});
} else {
// If data is grouped therefore an [object Object]. e.g.
Loading
Loading
@@ -149,7 +174,7 @@ GitLabDropdownFilter = (function() {
for (key in data) {
group = data[key];
tmp = fuzzaldrinPlus.filter(group, search_text, {
key: this.options.keys
key: this.options.keys,
});
if (tmp.length) {
results[key] = tmp.map(function(item) {
Loading
Loading
@@ -180,7 +205,10 @@ GitLabDropdownFilter = (function() {
elements.show().removeClass('option-hidden');
}
 
elements.parent().find('.dropdown-menu-empty-item').toggleClass('hidden', elements.is(':visible'));
elements
.parent()
.find('.dropdown-menu-empty-item')
.toggleClass('hidden', elements.is(':visible'));
}
};
 
Loading
Loading
@@ -194,23 +222,26 @@ GitLabDropdownRemote = (function() {
}
 
GitLabDropdownRemote.prototype.execute = function() {
if (typeof this.dataEndpoint === "string") {
if (typeof this.dataEndpoint === 'string') {
return this.fetchData();
} else if (typeof this.dataEndpoint === "function") {
} else if (typeof this.dataEndpoint === 'function') {
if (this.options.beforeSend) {
this.options.beforeSend();
}
return this.dataEndpoint("", (function(_this) {
// Fetch the data by calling the data funcfion
return function(data) {
if (_this.options.success) {
_this.options.success(data);
}
if (_this.options.beforeSend) {
return _this.options.beforeSend();
}
};
})(this));
return this.dataEndpoint(
'',
(function(_this) {
// Fetch the data by calling the data funcfion
return function(data) {
if (_this.options.success) {
_this.options.success(data);
}
if (_this.options.beforeSend) {
return _this.options.beforeSend();
}
};
})(this),
);
}
};
 
Loading
Loading
@@ -220,33 +251,41 @@ GitLabDropdownRemote = (function() {
}
 
// Fetch the data through ajax if the data is a string
return axios.get(this.dataEndpoint)
.then(({ data }) => {
if (this.options.success) {
return this.options.success(data);
}
});
return axios.get(this.dataEndpoint).then(({ data }) => {
if (this.options.success) {
return this.options.success(data);
}
});
};
 
return GitLabDropdownRemote;
})();
 
GitLabDropdown = (function() {
var ACTIVE_CLASS, FILTER_INPUT, NO_FILTER_INPUT, INDETERMINATE_CLASS, LOADING_CLASS, PAGE_TWO_CLASS, NON_SELECTABLE_CLASSES, SELECTABLE_CLASSES, CURSOR_SELECT_SCROLL_PADDING, currentIndex;
var ACTIVE_CLASS,
FILTER_INPUT,
NO_FILTER_INPUT,
INDETERMINATE_CLASS,
LOADING_CLASS,
PAGE_TWO_CLASS,
NON_SELECTABLE_CLASSES,
SELECTABLE_CLASSES,
CURSOR_SELECT_SCROLL_PADDING,
currentIndex;
 
LOADING_CLASS = "is-loading";
LOADING_CLASS = 'is-loading';
 
PAGE_TWO_CLASS = "is-page-two";
PAGE_TWO_CLASS = 'is-page-two';
 
ACTIVE_CLASS = "is-active";
ACTIVE_CLASS = 'is-active';
 
INDETERMINATE_CLASS = "is-indeterminate";
INDETERMINATE_CLASS = 'is-indeterminate';
 
currentIndex = -1;
 
NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
 
SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ", .option-hidden)";
SELECTABLE_CLASSES = '.dropdown-content li:not(' + NON_SELECTABLE_CLASSES + ', .option-hidden)';
 
CURSOR_SELECT_SCROLL_PADDING = 5;
 
Loading
Loading
@@ -263,15 +302,15 @@ GitLabDropdown = (function() {
this.opened = this.opened.bind(this);
this.shouldPropagate = this.shouldPropagate.bind(this);
self = this;
selector = $(this.el).data("target");
selector = $(this.el).data('target');
this.dropdown = selector != null ? $(selector) : $(this.el).parent();
// Set Defaults
this.filterInput = this.options.filterInput || this.getElement(FILTER_INPUT);
this.noFilterInput = this.options.noFilterInput || this.getElement(NO_FILTER_INPUT);
this.highlight = !!this.options.highlight;
this.filterInputBlur = this.options.filterInputBlur != null
? this.options.filterInputBlur
: true;
this.icon = !!this.options.icon;
this.filterInputBlur =
this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
// If no input is passed create a default one
self = this;
// If selector was passed
Loading
Loading
@@ -296,11 +335,17 @@ GitLabDropdown = (function() {
_this.fullData = data;
_this.parseData(_this.fullData);
_this.focusTextInput();
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val() && _this.filter.input.val().trim() !== '') {
if (
_this.options.filterable &&
_this.filter &&
_this.filter.input &&
_this.filter.input.val() &&
_this.filter.input.val().trim() !== ''
) {
return _this.filter.input.trigger('input');
}
};
// Remote data
// Remote data
})(this),
instance: this,
});
Loading
Loading
@@ -325,7 +370,7 @@ GitLabDropdown = (function() {
return function() {
selector = '.dropdown-content li:not(' + NON_SELECTABLE_CLASSES + ')';
if (_this.dropdown.find('.dropdown-toggle-page').length) {
selector = ".dropdown-page-one " + selector;
selector = '.dropdown-page-one ' + selector;
}
return $(selector, this.instance.dropdown);
};
Loading
Loading
@@ -341,80 +386,97 @@ GitLabDropdown = (function() {
if (_this.filterInput.val() !== '') {
selector = SELECTABLE_CLASSES;
if (_this.dropdown.find('.dropdown-toggle-page').length) {
selector = ".dropdown-page-one " + selector;
selector = '.dropdown-page-one ' + selector;
}
if ($(_this.el).is('input')) {
currentIndex = -1;
} else {
$(selector, _this.dropdown).first().find('a').addClass('is-focused');
$(selector, _this.dropdown)
.first()
.find('a')
.addClass('is-focused');
currentIndex = 0;
}
}
};
})(this)
})(this),
});
}
// Event listeners
this.dropdown.on("shown.bs.dropdown", this.opened);
this.dropdown.on("hidden.bs.dropdown", this.hidden);
$(this.el).on("update.label", this.updateLabel);
this.dropdown.on("click", ".dropdown-menu, .dropdown-menu-close", this.shouldPropagate);
this.dropdown.on('keyup', (function(_this) {
return function(e) {
// Escape key
if (e.which === 27) {
return $('.dropdown-menu-close', _this.dropdown).trigger('click');
}
};
})(this));
this.dropdown.on('blur', 'a', (function(_this) {
return function(e) {
var $dropdownMenu, $relatedTarget;
if (e.relatedTarget != null) {
$relatedTarget = $(e.relatedTarget);
$dropdownMenu = $relatedTarget.closest('.dropdown-menu');
if ($dropdownMenu.length === 0) {
return _this.dropdown.removeClass('show');
this.dropdown.on('shown.bs.dropdown', this.opened);
this.dropdown.on('hidden.bs.dropdown', this.hidden);
$(this.el).on('update.label', this.updateLabel);
this.dropdown.on('click', '.dropdown-menu, .dropdown-menu-close', this.shouldPropagate);
this.dropdown.on(
'keyup',
(function(_this) {
return function(e) {
// Escape key
if (e.which === 27) {
return $('.dropdown-menu-close', _this.dropdown).trigger('click');
}
}
};
})(this));
if (this.dropdown.find(".dropdown-toggle-page").length) {
this.dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on("click", (function(_this) {
};
})(this),
);
this.dropdown.on(
'blur',
'a',
(function(_this) {
return function(e) {
e.preventDefault();
e.stopPropagation();
return _this.togglePage();
var $dropdownMenu, $relatedTarget;
if (e.relatedTarget != null) {
$relatedTarget = $(e.relatedTarget);
$dropdownMenu = $relatedTarget.closest('.dropdown-menu');
if ($dropdownMenu.length === 0) {
return _this.dropdown.removeClass('show');
}
}
};
})(this));
})(this),
);
if (this.dropdown.find('.dropdown-toggle-page').length) {
this.dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on(
'click',
(function(_this) {
return function(e) {
e.preventDefault();
e.stopPropagation();
return _this.togglePage();
};
})(this),
);
}
if (this.options.selectable) {
selector = ".dropdown-content a";
if (this.dropdown.find(".dropdown-toggle-page").length) {
selector = ".dropdown-page-one .dropdown-content a";
selector = '.dropdown-content a';
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = '.dropdown-page-one .dropdown-content a';
}
this.dropdown.on("click", selector, function(e) {
var $el, selected, selectedObj, isMarking;
$el = $(e.currentTarget);
selected = self.rowClicked($el);
selectedObj = selected ? selected[0] : null;
isMarking = selected ? selected[1] : null;
if (this.options.clicked) {
this.options.clicked.call(this, {
selectedObj,
$el,
e,
isMarking,
});
}
this.dropdown.on(
'click',
selector,
function(e) {
var $el, selected, selectedObj, isMarking;
$el = $(e.currentTarget);
selected = self.rowClicked($el);
selectedObj = selected ? selected[0] : null;
isMarking = selected ? selected[1] : null;
if (this.options.clicked) {
this.options.clicked.call(this, {
selectedObj,
$el,
e,
isMarking,
});
}
 
// Update label right after all modifications in dropdown has been done
if (this.options.toggleLabel) {
this.updateLabel(selectedObj, $el, this);
}
// Update label right after all modifications in dropdown has been done
if (this.options.toggleLabel) {
this.updateLabel(selectedObj, $el, this);
}
 
$el.trigger('blur');
}.bind(this));
$el.trigger('blur');
}.bind(this),
);
}
}
 
Loading
Loading
@@ -452,10 +514,15 @@ GitLabDropdown = (function() {
html = [];
for (name in data) {
groupData = data[name];
html.push(this.renderItem({
header: name
// Add header for each group
}, name));
html.push(
this.renderItem(
{
header: name,
// Add header for each group
},
name,
),
);
this.renderData(groupData, name).map(function(item) {
return html.push(item);
});
Loading
Loading
@@ -474,20 +541,25 @@ GitLabDropdown = (function() {
if (group == null) {
group = false;
}
return data.map((function(_this) {
return function(obj, index) {
return _this.renderItem(obj, group, index);
};
})(this));
return data.map(
(function(_this) {
return function(obj, index) {
return _this.renderItem(obj, group, index);
};
})(this),
);
};
 
GitLabDropdown.prototype.shouldPropagate = function(e) {
var $target;
if (this.options.multiSelect || this.options.shouldPropagate === false) {
$target = $(e.target);
if ($target && !$target.hasClass('dropdown-menu-close') &&
!$target.hasClass('dropdown-menu-close-icon') &&
!$target.data('isLink')) {
if (
$target &&
!$target.hasClass('dropdown-menu-close') &&
!$target.hasClass('dropdown-menu-close-icon') &&
!$target.data('isLink')
) {
e.stopPropagation();
return false;
} else {
Loading
Loading
@@ -497,9 +569,11 @@ GitLabDropdown = (function() {
};
 
GitLabDropdown.prototype.filteredFullData = function() {
return this.fullData.filter(r => typeof r === 'object'
&& !Object.prototype.hasOwnProperty.call(r, 'beforeDivider')
&& !Object.prototype.hasOwnProperty.call(r, 'header')
return this.fullData.filter(
r =>
typeof r === 'object' &&
!Object.prototype.hasOwnProperty.call(r, 'beforeDivider') &&
!Object.prototype.hasOwnProperty.call(r, 'header'),
);
};
 
Loading
Loading
@@ -522,11 +596,16 @@ GitLabDropdown = (function() {
// matches the correct layout
const inputValue = this.filterInput.val();
if (this.fullData && hasMultiSelect && this.options.processData && inputValue.length === 0) {
this.options.processData.call(this.options, inputValue, this.filteredFullData(), this.parseData.bind(this));
this.options.processData.call(
this.options,
inputValue,
this.filteredFullData(),
this.parseData.bind(this),
);
}
 
contentHtml = $('.dropdown-content', this.dropdown).html();
if (this.remote && contentHtml === "") {
if (this.remote && contentHtml === '') {
this.remote.execute();
} else {
this.focusTextInput();
Loading
Loading
@@ -555,11 +634,11 @@ GitLabDropdown = (function() {
var $input;
this.resetRows();
this.removeArrayKeyEvent();
$input = this.dropdown.find(".dropdown-input-field");
$input = this.dropdown.find('.dropdown-input-field');
if (this.options.filterable) {
$input.blur();
}
if (this.dropdown.find(".dropdown-toggle-page").length) {
if (this.dropdown.find('.dropdown-toggle-page').length) {
$('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
}
if (this.options.hidden) {
Loading
Loading
@@ -601,7 +680,7 @@ GitLabDropdown = (function() {
GitLabDropdown.prototype.clearMenu = function() {
var selector;
selector = '.dropdown-content';
if (this.dropdown.find(".dropdown-toggle-page").length) {
if (this.dropdown.find('.dropdown-toggle-page').length) {
if (this.options.containerSelector) {
selector = this.options.containerSelector;
} else {
Loading
Loading
@@ -619,7 +698,7 @@ GitLabDropdown = (function() {
value = this.options.id ? this.options.id(data) : data.id;
 
if (value) {
value = value.toString().replace(/'/g, '\\\'');
value = value.toString().replace(/'/g, "\\'");
}
}
 
Loading
Loading
@@ -676,21 +755,27 @@ GitLabDropdown = (function() {
text = data.text != null ? data.text : '';
}
if (this.highlight) {
text = this.highlightTextMatches(text, this.filterInput.val());
text = data.template
? this.highlightTemplate(text, data.template)
: this.highlightTextMatches(text, this.filterInput.val());
}
// Create the list item & the link
var link = document.createElement('a');
 
link.href = url;
 
if (this.highlight) {
if (this.icon) {
text = `<span>${text}</span>`;
link.classList.add('d-flex', 'align-items-center');
link.innerHTML = data.icon ? data.icon + text : text;
} else if (this.highlight) {
link.innerHTML = text;
} else {
link.textContent = text;
}
 
if (selected) {
link.className = 'is-active';
link.classList.add('is-active');
}
 
if (group) {
Loading
Loading
@@ -703,17 +788,24 @@ GitLabDropdown = (function() {
return html;
};
 
GitLabDropdown.prototype.highlightTemplate = function(text, template) {
return `"<b>${_.escape(text)}</b>" ${template}`;
};
GitLabDropdown.prototype.highlightTextMatches = function(text, term) {
const occurrences = fuzzaldrinPlus.match(text, term);
const { indexOf } = [];
 
return text.split('').map(function(character, i) {
if (indexOf.call(occurrences, i) !== -1) {
return "<b>" + character + "</b>";
} else {
return character;
}
}).join('');
return text
.split('')
.map(function(character, i) {
if (indexOf.call(occurrences, i) !== -1) {
return '<b>' + character + '</b>';
} else {
return character;
}
})
.join('');
};
 
GitLabDropdown.prototype.noResults = function() {
Loading
Loading
@@ -748,13 +840,15 @@ GitLabDropdown = (function() {
}
 
field = [];
value = this.options.id
? this.options.id(selectedObject, el)
: selectedObject.id;
value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
if (isInput) {
field = $(this.el);
} else if (value != null) {
field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value.toString().replace(/'/g, '\\\'') + "']");
field = this.dropdown
.parent()
.find(
"input[name='" + fieldName + "'][value='" + value.toString().replace(/'/g, "\\'") + "']",
);
}
 
if (this.options.isSelectable && !this.options.isSelectable(selectedObject, el)) {
Loading
Loading
@@ -780,9 +874,12 @@ GitLabDropdown = (function() {
} else {
isMarking = true;
if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) {
this.dropdown.find("." + ACTIVE_CLASS).removeClass(ACTIVE_CLASS);
this.dropdown.find('.' + ACTIVE_CLASS).removeClass(ACTIVE_CLASS);
if (!isInput) {
this.dropdown.parent().find("input[name='" + fieldName + "']").remove();
this.dropdown
.parent()
.find("input[name='" + fieldName + "']")
.remove();
}
}
if (field && field.length && value == null) {
Loading
Loading
@@ -823,13 +920,16 @@ GitLabDropdown = (function() {
$('input[name="' + fieldName + '"]').remove();
}
 
$input = $('<input>').attr('type', 'hidden').attr('name', fieldName).val(value);
$input = $('<input>')
.attr('type', 'hidden')
.attr('name', fieldName)
.val(value);
if (this.options.inputId != null) {
$input.attr('id', this.options.inputId);
}
 
if (this.options.multiSelect) {
Object.keys(selectedObject).forEach((attribute) => {
Object.keys(selectedObject).forEach(attribute => {
$input.attr(`data-${attribute}`, selectedObject[attribute]);
});
}
Loading
Loading
@@ -844,13 +944,13 @@ GitLabDropdown = (function() {
GitLabDropdown.prototype.selectRowAtIndex = function(index) {
var $el, selector;
// If we pass an option index
if (typeof index !== "undefined") {
selector = SELECTABLE_CLASSES + ":eq(" + index + ") a";
if (typeof index !== 'undefined') {
selector = SELECTABLE_CLASSES + ':eq(' + index + ') a';
} else {
selector = ".dropdown-content .is-focused";
selector = '.dropdown-content .is-focused';
}
if (this.dropdown.find(".dropdown-toggle-page").length) {
selector = ".dropdown-page-one " + selector;
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = '.dropdown-page-one ' + selector;
}
// simulate a click on the first link
$el = $(selector, this.dropdown);
Loading
Loading
@@ -867,44 +967,47 @@ GitLabDropdown = (function() {
GitLabDropdown.prototype.addArrowKeyEvent = function() {
var $input, ARROW_KEY_CODES, selector;
ARROW_KEY_CODES = [38, 40];
$input = this.dropdown.find(".dropdown-input-field");
$input = this.dropdown.find('.dropdown-input-field');
selector = SELECTABLE_CLASSES;
if (this.dropdown.find(".dropdown-toggle-page").length) {
selector = ".dropdown-page-one " + selector;
}
return $('body').on('keydown', (function(_this) {
return function(e) {
var $listItems, PREV_INDEX, currentKeyCode;
currentKeyCode = e.which;
if (ARROW_KEY_CODES.indexOf(currentKeyCode) !== -1) {
e.preventDefault();
e.stopImmediatePropagation();
PREV_INDEX = currentIndex;
$listItems = $(selector, _this.dropdown);
// if @options.filterable
// $input.blur()
if (currentKeyCode === 40) {
// Move down
if (currentIndex < ($listItems.length - 1)) {
currentIndex += 1;
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = '.dropdown-page-one ' + selector;
}
return $('body').on(
'keydown',
(function(_this) {
return function(e) {
var $listItems, PREV_INDEX, currentKeyCode;
currentKeyCode = e.which;
if (ARROW_KEY_CODES.indexOf(currentKeyCode) !== -1) {
e.preventDefault();
e.stopImmediatePropagation();
PREV_INDEX = currentIndex;
$listItems = $(selector, _this.dropdown);
// if @options.filterable
// $input.blur()
if (currentKeyCode === 40) {
// Move down
if (currentIndex < $listItems.length - 1) {
currentIndex += 1;
}
} else if (currentKeyCode === 38) {
// Move up
if (currentIndex > 0) {
currentIndex -= 1;
}
}
} else if (currentKeyCode === 38) {
// Move up
if (currentIndex > 0) {
currentIndex -= 1;
if (currentIndex !== PREV_INDEX) {
_this.highlightRowAtIndex($listItems, currentIndex);
}
return false;
}
if (currentIndex !== PREV_INDEX) {
_this.highlightRowAtIndex($listItems, currentIndex);
if (currentKeyCode === 13 && currentIndex !== -1) {
e.preventDefault();
_this.selectRowAtIndex();
}
return false;
}
if (currentKeyCode === 13 && currentIndex !== -1) {
e.preventDefault();
_this.selectRowAtIndex();
}
};
})(this));
};
})(this),
);
};
 
GitLabDropdown.prototype.removeArrayKeyEvent = function() {
Loading
Loading
@@ -917,12 +1020,25 @@ GitLabDropdown = (function() {
};
 
GitLabDropdown.prototype.highlightRowAtIndex = function($listItems, index) {
var $dropdownContent, $listItem, dropdownContentBottom, dropdownContentHeight, dropdownContentTop, dropdownScrollTop, listItemBottom, listItemHeight, listItemTop;
var $dropdownContent,
$listItem,
dropdownContentBottom,
dropdownContentHeight,
dropdownContentTop,
dropdownScrollTop,
listItemBottom,
listItemHeight,
listItemTop;
if (!$listItems) {
$listItems = $(SELECTABLE_CLASSES, this.dropdown);
}
// Remove the class for the previously focused row
$('.is-focused', this.dropdown).removeClass('is-focused');
// Update the class for the row at the specific index
$listItem = $listItems.eq(index);
$listItem.find('a:first-child').addClass("is-focused");
$listItem.find('a:first-child').addClass('is-focused');
// Dropdown content scroll area
$dropdownContent = $listItem.closest('.dropdown-content');
dropdownScrollTop = $dropdownContent.scrollTop();
Loading
Loading
@@ -936,15 +1052,19 @@ GitLabDropdown = (function() {
if (!index) {
// Scroll the dropdown content to the top
$dropdownContent.scrollTop(0);
} else if (index === ($listItems.length - 1)) {
} else if (index === $listItems.length - 1) {
// Scroll the dropdown content to the bottom
$dropdownContent.scrollTop($dropdownContent.prop('scrollHeight'));
} else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) {
} else if (listItemBottom > dropdownContentBottom + dropdownScrollTop) {
// Scroll the dropdown content down
$dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING);
} else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) {
$dropdownContent.scrollTop(
listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING,
);
} else if (listItemTop < dropdownContentTop + dropdownScrollTop) {
// Scroll the dropdown content up
return $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING);
return $dropdownContent.scrollTop(
listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING,
);
}
};
 
Loading
Loading
@@ -965,7 +1085,9 @@ GitLabDropdown = (function() {
toggleText = this.options.updateLabel;
}
 
return $(this.el).find(".dropdown-toggle-text").text(toggleText);
return $(this.el)
.find('.dropdown-toggle-text')
.text(toggleText);
};
 
GitLabDropdown.prototype.clearField = function(field, isInput) {
Loading
Loading
/* eslint-disable no-return-assign, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-unused-vars, consistent-return, object-shorthand, prefer-template, quotes, class-methods-use-this, no-lonely-if, no-else-return, vars-on-top, max-len */
/* eslint-disable no-return-assign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, consistent-return, object-shorthand, prefer-template, class-methods-use-this, no-lonely-if, vars-on-top, max-len */
 
import $ from 'jquery';
import { escape, throttle } from 'underscore';
import { s__, sprintf } from '~/locale';
import { getIdenticonBackgroundClass, getIdenticonTitle } from '~/helpers/avatar_helper';
import axios from './lib/utils/axios_utils';
import DropdownUtils from './filtered_search/dropdown_utils';
import { isInGroupsPage, isInProjectPage, getGroupSlug, getProjectSlug } from './lib/utils/common_utils';
import {
isInGroupsPage,
isInProjectPage,
getGroupSlug,
getProjectSlug,
spriteIcon,
} from './lib/utils/common_utils';
 
/**
* Search input in top navigation bar.
Loading
Loading
@@ -52,6 +61,7 @@ function setSearchOptions() {
 
if ($dashboardOptionsDataEl.length) {
gl.dashboardOptions = {
name: s__('SearchAutocomplete|All GitLab'),
issuesPath: $dashboardOptionsDataEl.data('issuesPath'),
mrPath: $dashboardOptionsDataEl.data('mrPath'),
};
Loading
Loading
@@ -69,8 +79,8 @@ export default class SearchAutocomplete {
this.projectRef = projectRef || (this.optsEl.data('autocompleteProjectRef') || '');
this.dropdown = this.wrap.find('.dropdown');
this.dropdownToggle = this.wrap.find('.js-dropdown-search-toggle');
this.dropdownMenu = this.dropdown.find('.dropdown-menu');
this.dropdownContent = this.dropdown.find('.dropdown-content');
this.locationBadgeEl = this.getElement('.location-badge');
this.scopeInputEl = this.getElement('#scope');
this.searchInput = this.getElement('.search-input');
this.projectInputEl = this.getElement('#search_project_id');
Loading
Loading
@@ -78,6 +88,7 @@ export default class SearchAutocomplete {
this.searchCodeInputEl = this.getElement('#search_code');
this.repositoryInputEl = this.getElement('#repository_ref');
this.clearInput = this.getElement('.js-clear-input');
this.scrollFadeInitialized = false;
this.saveOriginalState();
 
// Only when user is logged in
Loading
Loading
@@ -98,17 +109,18 @@ export default class SearchAutocomplete {
this.onSearchInputFocus = this.onSearchInputFocus.bind(this);
this.onSearchInputKeyUp = this.onSearchInputKeyUp.bind(this);
this.onSearchInputKeyDown = this.onSearchInputKeyDown.bind(this);
this.setScrollFade = this.setScrollFade.bind(this);
}
getElement(selector) {
return this.wrap.find(selector);
}
 
saveOriginalState() {
return this.originalState = this.serializeState();
return (this.originalState = this.serializeState());
}
 
saveTextLength() {
return this.lastTextLength = this.searchInput.val().length;
return (this.lastTextLength = this.searchInput.val().length);
}
 
createAutocomplete() {
Loading
Loading
@@ -117,6 +129,7 @@ export default class SearchAutocomplete {
filterable: true,
filterRemote: true,
highlight: true,
icon: true,
enterCallback: false,
filterInput: 'input#search',
search: {
Loading
Loading
@@ -154,60 +167,87 @@ export default class SearchAutocomplete {
 
this.loadingSuggestions = true;
 
return axios.get(this.autocompletePath, {
params: {
project_id: this.projectId,
project_ref: this.projectRef,
term: term,
},
}).then((response) => {
// Hide dropdown menu if no suggestions returns
if (!response.data.length) {
this.disableAutocomplete();
return;
}
return axios
.get(this.autocompletePath, {
params: {
project_id: this.projectId,
project_ref: this.projectRef,
term: term,
},
})
.then(response => {
// Hide dropdown menu if no suggestions returns
if (!response.data.length) {
this.disableAutocomplete();
return;
}
 
const data = [];
// List results
let firstCategory = true;
let lastCategory;
for (let i = 0, len = response.data.length; i < len; i += 1) {
const suggestion = response.data[i];
// Add group header before list each group
if (lastCategory !== suggestion.category) {
if (!firstCategory) {
data.push('separator');
}
if (firstCategory) {
firstCategory = false;
const data = [];
// List results
let firstCategory = true;
let lastCategory;
for (let i = 0, len = response.data.length; i < len; i += 1) {
const suggestion = response.data[i];
// Add group header before list each group
if (lastCategory !== suggestion.category) {
if (!firstCategory) {
data.push('separator');
}
if (firstCategory) {
firstCategory = false;
}
data.push({
header: suggestion.category,
});
lastCategory = suggestion.category;
}
data.push({
header: suggestion.category,
id: `${suggestion.category.toLowerCase()}-${suggestion.id}`,
icon: this.getAvatar(suggestion),
category: suggestion.category,
text: suggestion.label,
url: suggestion.url,
});
lastCategory = suggestion.category;
}
data.push({
id: `${suggestion.category.toLowerCase()}-${suggestion.id}`,
category: suggestion.category,
text: suggestion.label,
url: suggestion.url,
});
}
// Add option to proceed with the search
if (data.length) {
data.push('separator');
data.push({
text: `Result name contains "${term}"`,
url: `/search?search=${term}&project_id=${this.projectInputEl.val()}&group_id=${this.groupInputEl.val()}`,
});
}
// Add option to proceed with the search
if (data.length) {
const icon = spriteIcon('search', 's16 inline-search-icon');
let template;
 
callback(data);
if (this.projectInputEl.val()) {
template = s__('SearchAutocomplete|in this project');
}
if (this.groupInputEl.val()) {
template = s__('SearchAutocomplete|in this group');
}
 
this.loadingSuggestions = false;
}).catch(() => {
this.loadingSuggestions = false;
});
data.unshift('separator');
data.unshift({
icon,
text: term,
template: s__('SearchAutocomplete|in all GitLab'),
url: `/search?search=${term}`,
});
if (template) {
data.unshift({
icon,
text: term,
template,
url: `/search?search=${term}&project_id=${this.projectInputEl.val()}&group_id=${this.groupInputEl.val()}`,
});
}
}
callback(data);
this.loadingSuggestions = false;
this.highlightFirstRow();
this.setScrollFade();
})
.catch(() => {
this.loadingSuggestions = false;
});
}
 
getCategoryContents() {
Loading
Loading
@@ -236,21 +276,21 @@ export default class SearchAutocomplete {
 
const issueItems = [
{
text: 'Issues assigned to me',
text: s__('SearchAutocomplete|Issues assigned to me'),
url: `${issuesPath}/?assignee_id=${userId}`,
},
{
text: "Issues I've created",
text: s__("SearchAutocomplete|Issues I've created"),
url: `${issuesPath}/?author_id=${userId}`,
},
];
const mergeRequestItems = [
{
text: 'Merge requests assigned to me',
text: s__('SearchAutocomplete|Merge requests assigned to me'),
url: `${mrPath}/?assignee_id=${userId}`,
},
{
text: "Merge requests I've created",
text: s__("SearchAutocomplete|Merge requests I've created"),
url: `${mrPath}/?author_id=${userId}`,
},
];
Loading
Loading
@@ -259,7 +299,7 @@ export default class SearchAutocomplete {
if (issuesDisabled) {
items = baseItems.concat(mergeRequestItems);
} else {
items = baseItems.concat(...issueItems, 'separator', ...mergeRequestItems);
items = baseItems.concat(...issueItems, ...mergeRequestItems);
}
return items;
}
Loading
Loading
@@ -272,8 +312,6 @@ export default class SearchAutocomplete {
search_code: this.searchCodeInputEl.val(),
repository_ref: this.repositoryInputEl.val(),
scope: this.scopeInputEl.val(),
// Location badge
_location: this.locationBadgeEl.text(),
};
}
 
Loading
Loading
@@ -283,10 +321,12 @@ export default class SearchAutocomplete {
this.searchInput.on('focus', this.onSearchInputFocus);
this.searchInput.on('blur', this.onSearchInputBlur);
this.clearInput.on('click', this.onClearInputClick);
this.locationBadgeEl.on('click', () => this.searchInput.focus());
this.dropdownContent.on('scroll', throttle(this.setScrollFade, 250));
}
 
enableAutocomplete() {
this.setScrollFade();
// No need to enable anything if user is not logged in
if (!gon.current_user_id) {
return;
Loading
Loading
@@ -308,10 +348,6 @@ export default class SearchAutocomplete {
onSearchInputKeyUp(e) {
switch (e.keyCode) {
case KEYCODE.BACKSPACE:
// when trying to remove the location badge
if (this.lastTextLength === 0 && this.badgePresent()) {
this.removeLocationBadge();
}
// When removing the last character and no badge is present
if (this.lastTextLength === 1) {
this.disableAutocomplete();
Loading
Loading
@@ -372,37 +408,13 @@ export default class SearchAutocomplete {
}
}
 
addLocationBadge(item) {
var badgeText, category, value;
category = item.category != null ? item.category + ": " : '';
value = item.value != null ? item.value : '';
badgeText = "" + category + value;
this.locationBadgeEl.text(badgeText).show();
return this.wrap.addClass('has-location-badge');
}
hasLocationBadge() {
return this.wrap.is('.has-location-badge');
}
restoreOriginalState() {
var i, input, inputs, len;
inputs = Object.keys(this.originalState);
for (i = 0, len = inputs.length; i < len; i += 1) {
input = inputs[i];
this.getElement("#" + input).val(this.originalState[input]);
this.getElement('#' + input).val(this.originalState[input]);
}
if (this.originalState._location === '') {
return this.locationBadgeEl.hide();
} else {
return this.addLocationBadge({
value: this.originalState._location,
});
}
}
badgePresent() {
return this.locationBadgeEl.length;
}
 
resetSearchState() {
Loading
Loading
@@ -411,22 +423,11 @@ export default class SearchAutocomplete {
results = [];
for (i = 0, len = inputs.length; i < len; i += 1) {
input = inputs[i];
// _location isnt a input
if (input === '_location') {
break;
}
results.push(this.getElement("#" + input).val(''));
results.push(this.getElement('#' + input).val(''));
}
return results;
}
 
removeLocationBadge() {
this.locationBadgeEl.hide();
this.resetSearchState();
this.wrap.removeClass('has-location-badge');
return this.disableAutocomplete();
}
disableAutocomplete() {
if (!this.searchInput.hasClass('disabled') && this.dropdown.hasClass('show')) {
this.searchInput.addClass('disabled');
Loading
Loading
@@ -444,23 +445,57 @@ export default class SearchAutocomplete {
onClick(item, $el, e) {
if (window.location.pathname.indexOf(item.url) !== -1) {
if (!e.metaKey) e.preventDefault();
if (!this.badgePresent) {
if (item.category === 'Projects') {
this.projectInputEl.val(item.id);
this.addLocationBadge({
value: 'This project',
});
}
if (item.category === 'Groups') {
this.groupInputEl.val(item.id);
this.addLocationBadge({
value: 'This group',
});
}
if (item.category === 'Projects') {
this.projectInputEl.val(item.id);
}
if (item.category === 'Groups') {
this.groupInputEl.val(item.id);
}
$el.removeClass('is-active');
this.disableAutocomplete();
return this.searchInput.val('').focus();
}
}
highlightFirstRow() {
this.searchInput.data('glDropdown').highlightRowAtIndex(null, 0);
}
getAvatar(item) {
if (!Object.hasOwnProperty.call(item, 'avatar_url')) {
return false;
}
const { label, id } = item;
const avatarUrl = item.avatar_url;
const avatar = avatarUrl
? `<img class="search-item-avatar" src="${avatarUrl}" />`
: `<div class="s16 avatar identicon ${getIdenticonBackgroundClass(id)}">${getIdenticonTitle(
escape(label),
)}</div>`;
return avatar;
}
isScrolledUp() {
const el = this.dropdownContent[0];
const currentPosition = this.contentClientHeight + el.scrollTop;
return currentPosition < this.maxPosition;
}
initScrollFade() {
const el = this.dropdownContent[0];
this.scrollFadeInitialized = true;
this.contentClientHeight = el.clientHeight;
this.maxPosition = el.scrollHeight;
this.dropdownMenu.addClass('dropdown-content-faded-mask');
}
setScrollFade() {
this.initScrollFade();
this.dropdownMenu.toggleClass('fade-out', !this.isScrolledUp());
}
}
Loading
Loading
@@ -3,7 +3,6 @@
*/
 
@mixin gitlab-theme(
$location-badge-color,
$search-and-nav-links,
$active-tab-border,
$border-and-box-shadow,
Loading
Loading
@@ -119,12 +118,6 @@
}
}
 
.location-badge {
color: $location-badge-color;
background-color: rgba($search-and-nav-links, 0.1);
border-right: 1px solid $sidebar-text;
}
.search-input::placeholder {
color: rgba($search-and-nav-links, 0.8);
}
Loading
Loading
@@ -141,10 +134,6 @@
background-color: $white-light;
}
 
.location-badge {
color: $gl-text-color;
}
.search-input-wrap {
.search-icon {
fill: rgba($search-and-nav-links, 0.8);
Loading
Loading
@@ -200,7 +189,6 @@
body {
&.ui-indigo {
@include gitlab-theme(
$indigo-100,
$indigo-200,
$indigo-500,
$indigo-700,
Loading
Loading
@@ -212,7 +200,6 @@ body {
 
&.ui-light-indigo {
@include gitlab-theme(
$indigo-100,
$indigo-200,
$indigo-500,
$indigo-500,
Loading
Loading
@@ -224,7 +211,6 @@ body {
 
&.ui-blue {
@include gitlab-theme(
$theme-blue-100,
$theme-blue-200,
$theme-blue-500,
$theme-blue-700,
Loading
Loading
@@ -236,7 +222,6 @@ body {
 
&.ui-light-blue {
@include gitlab-theme(
$theme-light-blue-100,
$theme-light-blue-200,
$theme-light-blue-500,
$theme-light-blue-500,
Loading
Loading
@@ -248,7 +233,6 @@ body {
 
&.ui-green {
@include gitlab-theme(
$theme-green-100,
$theme-green-200,
$theme-green-500,
$theme-green-700,
Loading
Loading
@@ -260,7 +244,6 @@ body {
 
&.ui-light-green {
@include gitlab-theme(
$theme-green-100,
$theme-green-200,
$theme-green-500,
$theme-green-500,
Loading
Loading
@@ -272,7 +255,6 @@ body {
 
&.ui-red {
@include gitlab-theme(
$theme-red-100,
$theme-red-200,
$theme-red-500,
$theme-red-700,
Loading
Loading
@@ -284,7 +266,6 @@ body {
 
&.ui-light-red {
@include gitlab-theme(
$theme-light-red-100,
$theme-light-red-200,
$theme-light-red-500,
$theme-light-red-500,
Loading
Loading
@@ -296,7 +277,6 @@ body {
 
&.ui-dark {
@include gitlab-theme(
$theme-gray-100,
$theme-gray-200,
$theme-gray-500,
$theme-gray-700,
Loading
Loading
@@ -308,7 +288,6 @@ body {
 
&.ui-light {
@include gitlab-theme(
$theme-gray-900,
$theme-gray-700,
$theme-gray-800,
$theme-gray-700,
Loading
Loading
@@ -357,10 +336,6 @@ body {
&:hover {
background-color: $white-light;
box-shadow: inset 0 0 0 1px $blue-200;
.location-badge {
box-shadow: inset 0 0 0 1px $blue-200;
}
}
}
 
Loading
Loading
@@ -373,13 +348,6 @@ body {
color: $gl-text-color;
}
}
.location-badge {
color: $theme-gray-700;
box-shadow: inset 0 0 0 1px $border-color;
background-color: $nav-badge-bg;
border-right: 0;
}
}
 
.nav-sidebar li.active {
Loading
Loading
Loading
Loading
@@ -467,7 +467,8 @@ $award-emoji-positive-add-lines: #bb9c13;
*/
$search-input-border-color: rgba($blue-400, 0.8);
$search-input-focus-shadow-color: $dropdown-input-focus-shadow;
$search-input-width: 220px;
$search-input-width: 240px;
$search-input-active-width: 320px;
$location-badge-active-bg: $blue-500;
$location-icon-color: #e7e9ed;
 
Loading
Loading
$search-dropdown-max-height: 400px;
$search-avatar-size: 16px;
.search-results {
.search-result-row {
border-bottom: 1px solid $border-color;
Loading
Loading
@@ -24,8 +27,9 @@
box-shadow: 0 0 4px lighten($search-input-focus-shadow-color, 20%);
}
 
input[type="checkbox"]:hover {
box-shadow: 0 0 2px 2px lighten($search-input-focus-shadow-color, 20%), 0 0 0 1px lighten($search-input-focus-shadow-color, 20%);
input[type='checkbox']:hover {
box-shadow: 0 0 2px 2px lighten($search-input-focus-shadow-color, 20%),
0 0 0 1px lighten($search-input-focus-shadow-color, 20%);
}
 
.search {
Loading
Loading
@@ -40,24 +44,15 @@ input[type="checkbox"]:hover {
height: 32px;
border: 0;
border-radius: $border-radius-default;
transition: border-color ease-in-out $default-transition-duration, background-color ease-in-out $default-transition-duration;
transition: border-color ease-in-out $default-transition-duration,
background-color ease-in-out $default-transition-duration,
width ease-in-out $default-transition-duration;
 
&:hover {
box-shadow: none;
}
}
 
.location-badge {
white-space: nowrap;
height: 32px;
font-size: 12px;
margin: -4px 4px -4px -4px;
line-height: 25px;
padding: 4px 8px;
border-radius: $border-radius-default 0 0 $border-radius-default;
transition: border-color ease-in-out $default-transition-duration;
}
.search-input {
border: 0;
font-size: 14px;
Loading
Loading
@@ -104,17 +99,28 @@ input[type="checkbox"]:hover {
}
 
.dropdown-header {
text-transform: uppercase;
font-size: 11px;
// Necessary because glDropdown doesn't support a second style of headers
font-weight: $gl-font-weight-bold;
// .dropdown-menu li has 1px side padding
padding: $gl-padding-8 17px;
color: $gl-text-color;
font-size: $gl-font-size;
line-height: 16px;
}
 
// Custom dropdown positioning
.dropdown-menu {
left: -5px;
max-height: $search-dropdown-max-height;
overflow: auto;
@include media-breakpoint-up(xl) {
width: $search-input-active-width;
}
}
 
.dropdown-content {
max-height: none;
max-height: $search-dropdown-max-height - 18px;
}
}
 
Loading
Loading
@@ -124,6 +130,10 @@ input[type="checkbox"]:hover {
border-color: $dropdown-input-focus-border;
box-shadow: none;
 
@include media-breakpoint-up(xl) {
width: $search-input-active-width;
}
.search-input-wrap {
.search-icon,
.clear-icon {
Loading
Loading
@@ -141,12 +151,6 @@ input[type="checkbox"]:hover {
color: $gl-text-color-tertiary;
}
}
.location-badge {
transition: all $default-transition-duration;
background-color: $nav-badge-bg;
border-color: $border-color;
}
}
 
&.has-value {
Loading
Loading
@@ -160,10 +164,24 @@ input[type="checkbox"]:hover {
}
}
 
&.has-location-badge {
.search-input-wrap {
width: 68%;
}
.inline-search-icon {
position: relative;
margin-right: 4px;
color: $gl-text-color-secondary;
}
.identicon,
.search-item-avatar {
flex-basis: $search-avatar-size;
flex-shrink: 0;
margin-right: 4px;
}
.search-item-avatar {
width: $search-avatar-size;
height: $search-avatar-size;
border-radius: 50%;
border: 1px solid $avatar-border;
}
}
 
Loading
Loading
Loading
Loading
@@ -82,16 +82,16 @@ module SearchHelper
ref = @ref || @project.repository.root_ref
 
[
{ category: "Current Project", label: "Files", url: project_tree_path(@project, ref) },
{ category: "Current Project", label: "Commits", url: project_commits_path(@project, ref) },
{ category: "Current Project", label: "Network", url: project_network_path(@project, ref) },
{ category: "Current Project", label: "Graph", url: project_graph_path(@project, ref) },
{ category: "Current Project", label: "Issues", url: project_issues_path(@project) },
{ category: "Current Project", label: "Merge Requests", url: project_merge_requests_path(@project) },
{ category: "Current Project", label: "Milestones", url: project_milestones_path(@project) },
{ category: "Current Project", label: "Snippets", url: project_snippets_path(@project) },
{ category: "Current Project", label: "Members", url: project_project_members_path(@project) },
{ category: "Current Project", label: "Wiki", url: project_wikis_path(@project) }
{ category: "In this project", label: "Files", url: project_tree_path(@project, ref) },
{ category: "In this project", label: "Commits", url: project_commits_path(@project, ref) },
{ category: "In this project", label: "Network", url: project_network_path(@project, ref) },
{ category: "In this project", label: "Graph", url: project_graph_path(@project, ref) },
{ category: "In this project", label: "Issues", url: project_issues_path(@project) },
{ category: "In this project", label: "Merge Requests", url: project_merge_requests_path(@project) },
{ category: "In this project", label: "Milestones", url: project_milestones_path(@project) },
{ category: "In this project", label: "Snippets", url: project_snippets_path(@project) },
{ category: "In this project", label: "Members", url: project_project_members_path(@project) },
{ category: "In this project", label: "Wiki", url: project_wikis_path(@project) }
]
else
[]
Loading
Loading
Loading
Loading
@@ -6,21 +6,19 @@
- group_data_attrs = { group_path: j(@group.path), name: @group.name, issues_path: issues_group_path(j(@group.path)), mr_path: merge_requests_group_path(j(@group.path)) }
- if @project && @project.persisted?
- project_data_attrs = { project_path: j(@project.path), name: j(@project.name), issues_path: project_issues_path(@project), mr_path: project_merge_requests_path(@project), issues_disabled: !@project.issues_enabled? }
.search.search-form{ class: "#{'has-location-badge' if label.present?}" }
.search.search-form
= form_tag search_path, method: :get, class: 'form-inline' do |f|
.search-input-container
- if label.present?
.location-badge= label
.search-input-wrap
.dropdown{ data: { url: search_autocomplete_path } }
= search_field_tag 'search', nil, placeholder: _('Search'),
= search_field_tag 'search', nil, placeholder: _('Search or jump to…'),
class: 'search-input dropdown-menu-toggle no-outline js-search-dashboard-options',
spellcheck: false,
tabindex: '1',
autocomplete: 'off',
data: { issues_path: issues_dashboard_path,
mr_path: merge_requests_dashboard_path },
aria: { label: _('Search') }
aria: { label: _('Search or jump to…') }
%button.hidden.js-dropdown-search-toggle{ type: 'button', data: { toggle: 'dropdown' } }
.dropdown-menu.dropdown-select
= dropdown_content do
Loading
Loading
---
title: UX improvements to top nav search bar
merge_request: 20537
author:
type: changed
doc/user/search/img/issues_mrs_shortcut.png

33.3 KiB | W: 1907px | H: 410px

doc/user/search/img/issues_mrs_shortcut.png

60.4 KiB | W: 1245px | H: 262px

doc/user/search/img/issues_mrs_shortcut.png
doc/user/search/img/issues_mrs_shortcut.png
doc/user/search/img/issues_mrs_shortcut.png
doc/user/search/img/issues_mrs_shortcut.png
  • 2-up
  • Swipe
  • Onion skin
doc/user/search/img/project_search.png

40.9 KiB | W: 1919px | H: 481px

doc/user/search/img/project_search.png

86.9 KiB | W: 1241px | H: 291px

doc/user/search/img/project_search.png
doc/user/search/img/project_search.png
doc/user/search/img/project_search.png
doc/user/search/img/project_search.png
  • 2-up
  • Swipe
  • Onion skin
Loading
Loading
@@ -4606,12 +4606,39 @@ msgstr ""
msgid "Search milestones"
msgstr ""
 
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
 
msgid "Search users"
msgstr ""
 
msgid "SearchAutocomplete|All GitLab"
msgstr ""
msgid "SearchAutocomplete|Issues I've created"
msgstr ""
msgid "SearchAutocomplete|Issues assigned to me"
msgstr ""
msgid "SearchAutocomplete|Merge requests I've created"
msgstr ""
msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr ""
msgid "SearchAutocomplete|in all GitLab"
msgstr ""
msgid "SearchAutocomplete|in this group"
msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
msgid "Seconds before reseting failure information"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -62,10 +62,6 @@ describe 'User uses header search field' do
end
end
 
it 'contains location badge' do
expect(page).to have_selector('.has-location-badge')
end
context 'when clicking the search field', :js do
before do
page.find('#search').click
Loading
Loading
.search.search-form.has-location-badge
%form.navbar-form
.search.search-form
%form.form-inline
.search-input-container
%div.location-badge
This project
.search-input-wrap
.dropdown
%input#search.search-input.dropdown-menu-toggle
Loading
Loading
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