Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • rspeicher/gitlab
  • reprazent/gitlab
  • mwasilewski-gitlab/gitlab
  • mlapierre/gitlab
  • gl-gitaly/gitlab
  • gitlab-org/gitlab
  • 1and1_ebusiness/gitlab-ee
  • marin/gitlab-ee
  • max-group/gitlab-ee
  • cirosantilli/gitlab-ee
  • cernvcs/gitlab-ee
  • chrisrohr/gitlab-ee
  • stanhu/gitlab-ee
  • ealcantara/gitlab
  • sijis/gitlab-ee
  • kalibyrn/gitlab-ee
  • bbodenmiller/gitlab-ee
  • cvd/gitlab-ee
  • alexwarren/gitlab-ee
  • j.seto/gitlab
  • cmiskell/gitlab
  • Ashley/gitlab-ee
  • kkm/gitlab-ee
  • haynes/gitlab-ee
  • dblessing/gitlab-ee
  • allison.browne/gitlab
  • singingwolfboy/gitlab-ee
  • coderhugo/gitlab-ee
  • axil/gitlab-ee
  • truongsinh/gitlab-ee
  • tensky/gitlab-ee
  • rymai/gitlab-ee
  • jt-gitlab/gitlab-ee
  • patricio/gitlab-ee
  • b.lashen/gitlab-ee
  • acroitor/gitlab
  • rosiv/gitlab-ee
  • sune-keller/gitlab-ee
  • wiget/gitlab-ee
  • bandel/gitlab-ee
  • e4r7hbug/gitlab-ee
  • chaosaffe/gitlab-ee
  • yannick-croissant/gitlab-ee
  • jameslopez/gitlab-ee
  • xellor/gitlab-ee
  • ymotiongroup/gitlab-ee
  • cwilcox/gitlab-ee
  • daniel.hoffmann/gitlab-ee
  • johnnyeric/gitlab-ee
  • pidge/gitlab-ee
  • Posp/gitlab-ee
  • jonafato/gitlab-ee
  • Quintasan/gitlab
  • shobra/gitlab-ee
  • sleepyknife/gitlab-ee
  • yorickpeterse/gitlab
  • abualy/gitlab-ee
  • ci-test-user-mk/gitlab
  • jogo/gitlab-ee
  • foxnewsnetwork/gitlab-ee
  • riemers/gitlab-ee
  • pacoguzman/gitlab-ee
  • usr01/gitlab-ee
  • samuel.bernard/gitlab-ee
  • codelust/gitlab-ee
  • takitak/gitlab-ee
  • ftasdelen/gitlab-ee
  • qhcthanh/gitlab-ee
  • clairton/gitlab-ee
  • cuongtm/gitlab-ee
  • m5/gitlab-ee
  • Sivapuram/gitlab-ee
  • sbeleidy/gitlab-ee
  • baparici/gitlab-ee
  • Hubbitus/gitlab-ee
  • lbennett/gitlab-ee
  • klml/gitlab-ee
  • jaydeland/gitlab-ee
  • lupine/gitlab-ee
  • leftathome/gitlab-ee
  • ianb/gitlab-ee
  • mumayank/gitlab-ee
  • nagoyamavps/gitlab-ee
  • pattyhama/gitlab-ee
  • momirza/gitlab-ee
  • BhavaniM/gitlab-ee
  • morefice/gitlab
  • splattael-staging/gitlab
  • toanalien/gitlab-ee
  • clever_usr_name/gitlab-ee
  • oscar-lopez/gitlab-ee
  • svansteenis/gitlab-ee
  • prashtest/gitlab-ee
  • bonsai/gitlab-ee
  • graingert/gitlab-ee
  • niijv/gitlab-ee
  • abdiasshaw/gitlab-ee
  • peter9208/gitlab-ee
  • gforcada/gitlab-ee
  • broftkd/gitlab-ee
  • mkobel/gitlab-ee
  • mikaelz/gitlab-ee
  • OdNairy/gitlab-ee
  • christinebeaubrun/gitlab-ee
  • haakoo/gitlab-ee
  • Rencs/gitlab-ee
  • marcia/gitlab-ee
  • dehvmartins/gitlab-ee
  • rouzbeh84/gitlab-ee
  • gjunker/gitlab-ee
  • nick.thomas/gitlab-ee
  • heijmans/gitlab-ee
  • s.ghafarpour/gitlab-ee
  • markglenfletcher1/gitlab-ee
  • Benno/gitlab-ee
  • s2gluser/gitlab-ee
  • hazelyang/gitlab-ee
  • dewetblomerus/gitlab-ee
  • chrisbelyea/gitlab-ee
  • nick.volynkin/gitlab-ee
  • sevenseacat/gitlab-ee
  • yuanchenxi95/gitlab-ee
  • andyli/gitlab-ee
  • nacredata/gitlab-ee
  • srkaycg_admin/gitlab-ee
  • tagyangyang/gitlab-ee
  • miroslav.meca/gitlab-ee
  • cafed00d/gitlab-ee
  • iOrange/gitlab-ee
  • shackledtodesk/gitlab-ee
  • kalleva/gitlab-ee
  • paulsen.jan/gitlab-ee
  • hu19891110/gitlab-ee
  • gmeans/gitlab-ee
  • nithin2/gitlab-ee
  • dbelova/gitlab-ee
  • GeorgConradi/gitlab-ee
  • iunet/gitlab-ee
  • ephemeric/gitlab-ee
  • wendy0402/gitlab-ee
  • phil7/gitlab-ee
  • Eichi4Eichler/gitlab-ee
  • Munken/gitlab-ee
  • clim/gitlab-ee
  • averyduffin/gitlab-ee
  • DKovel/gitlab-ee
  • katrinleinweber/gitlab-ee
  • tmaier/gitlab-ee
  • Shahriar_Rabbi/gitlab-ee
  • Stretch96/gitlab-ee
  • brennanroberts/gitlab-ee
  • sanyatuning/gitlab-ee
  • hkrutzer/gitlab-ee
  • visualrobots/gitlab-ee
  • jieme/gitlab-ee
  • vansch/gitlab-ee
  • smuthusamy.fivedtech/gitlab-ee
  • almtoolbox/gitlab-ee
  • niketgupta6590/gitlab-ee
  • d.demichelis/gitlab-ee
  • LeclercA/gitlab-ee
  • bpietraga/gitlab-ee
  • ivikash/gitlab-ee
  • TobbenTM/gitlab-ee
  • YarNayar/gitlab-ee
  • dcondrey/gitlab-ee
  • atronah/gitlab-ee
  • mindupper/gitlab-ee
  • zyfran/gitlab-ee
  • savitojs/gitlab-ee
  • vino.v/gitlab-ee
  • athar/gitlab-ee
  • me63/gitlab-ee
  • l00mi/gitlab-ee
  • trentontri/gitlab-ee
  • peterlebrun/gitlab-ee
  • gwawr/gitlab-ee
  • isolation85/gitlab-ee
  • timothyandrew/gitlab-ee
  • shawonsoyket439/gitlab-ee
  • afolson/gitlab-ee
  • ismail-s/gitlab-ee
  • peterramsing/gitlab-ee
  • kason/gitlab-ee
  • al1_andre/gitlab-ee
  • pchojnacki/gitlab-ee
  • juliusv/gitlab-ee
  • scallopedllama/gitlab-ee
  • frech/gitlab-ee
  • z9g9l9/gitlab-ee
  • jamiekaw/gitlab-ee
  • mrburrito/gitlab-ee
  • headcrabmeat/gitlab-ee
  • cristiantmbr/gitlab-ee
  • revuel/gitlab-ee
  • Nnidyu/gitlab-ee
  • MrCirwos/gitlab-ee
  • Gutenevv/gitlab-ee
  • jmeyo/gitlab-ee
  • ollie314/gitlab-ee
  • sang9402/gitlab-ee
  • mickael9/gitlab-ee
  • vsizov/gitlab-ee
  • dosuken123/gitlab-ee
  • geoandri/gitlab-ee
  • afrastgeek/gitlab-ee
  • steveschooncts/gitlab-ee
  • dinsaw/gitlab-ee
  • xqua/gitlab-ee
  • smith-kyle/gitlab-ee
  • Mattlk13/gitlab-ee
  • andy_b_84/gitlab-ee
  • raansari/gitlab-ee
  • abitduck/gitlab-ee
  • mgresko/gitlab-ee
  • sidewinder12s/gitlab-ee
  • andresca/gitlab-ee
  • ccrebolder/gitlab-ee
  • rodrigo.pereira1/gitlab-ee
  • mohideen.rahuman/gitlab-ee
  • hebbet/gitlab-ee
  • smcgivern/gitlab-ee
  • heapifyman/gitlab-ee
  • TeNNoX/gitlab-ee
  • herryLi/gitlab-ee
  • AlexKalinin/gitlab-ee
  • vincedmg/gitlab-ee
  • martflu/gitlab-ee
  • derik/gitlab-ee
  • Ruby-and-Friends/gitlab-ee
  • wojciechlisik/gitlab-ee
  • winniehell-gitlab/gitlab-ee
  • Vaidehee5/gitlab-ee
  • vignesh.ravichandran02/gitlab-ee
  • tanyan2004/gitlab-ee
  • gitlabproject_s/gitlab-ee
  • virth/gitlab-ee
  • tmlee/gitlab-ee
  • hwdegroot/gitlab-ee
  • kybae/gitlab-ee
  • xiaogang_gitlab/gitlab-ee
  • jabber/gitlab-ee
  • eswar.madhira/gitlab-ee
  • alshamiri2/gitlab-ee
  • ba2014sheer/gitlab-ee
  • paulcodiny/gitlab-ee
  • glabio/gitlab-ee
  • lenghan1991/gitlab-ee
  • peterl/gitlab-ee
  • lucianomx/gitlab-ee
  • jbrandhorst/gitlab-ee
  • abushoeb/gitlab-ee
  • shellthor/gitlab-ee
  • jameshclrk/gitlab-ee
  • jontdelorme/gitlab-ee
  • tzc_007/gitlab-ee
  • indobits/gitlab-ee
  • dturner_ts/gitlab-ee
  • gauravkk22/gitlab-ee
  • andy9775/gitlab-ee
  • vladel/gitlab-ee
  • hakulatata99/gitlab-ee
  • lee0824/gitlab-ee
  • pk-codebox-evo/gitlab-ee
  • feshu/gitlab-ee
  • techguru/gitlab-ee
  • ei-grad/gitlab-ee
  • mccomput3rfr3ak/gitlab-ee
  • winnetou/gitlab-ee
  • julian-poidevin/gitlab-ee
  • arihantar/gitlab-ee
  • Trilom/gitlab-ee
  • Waysb1/gitlab-ee
  • jjung/gitlab-ee
  • xiaole/gitlab-ee
  • kikipq/gitlab-ee
  • rpadovani/gitlab-ee
  • zsturgess/gitlab-ee
  • mishunov/gitlab
  • nodeable/gitlab-ee
  • m1guelpiedrafita/gitlab-ee
  • jonas1/gitlab-ee
  • imranh/gitlab-ee
  • vitor.tyburski/gitlab-ee
  • pavel-voronin/gitlab-ee
  • alizadeh/gitlab-ee
  • aaaaaaq/gitlab-ee
  • JaKXz/gitlab-ee
  • umirra/gitlab-ee
  • jjcarstens/gitlab-ee
  • jenibella/gitlab-ee
  • hnk/gitlab-ee
  • roccolangeweg/gitlab-ee
  • batok/gitlab-ee
  • rajgomase24/gitlab-ee
  • qmnguyen0711/gitlab
  • 413063135/gitlab-ee
  • josephmarty/gitlab-ee
  • rdumont/gitlab-ee
  • gucong3000/gitlab-ee
  • ckatanda/gitlab-ee
  • overflowsith/gitlab-ee
  • TheJaredWilcurt/gitlab-ee
  • Riktos/gitlab-ee
  • losingle/gitlab-ee
  • mlushpenko/gitlab-ee
  • ericy_ts/gitlab-ee
  • fadb/gitlab-ee
  • dbvid/gitlab-ee
  • thejacer87/gitlab-ee
  • eli.boyarski/gitlab-ee
  • baldwinSPC/gitlab-ee
  • baldwinmathew/gitlab-ee
  • gsmethells/gitlab-ee
  • funkypenguin/gitlab-ee
  • rrentfro/gitlab-ee
  • M1TKO/gitlab-ee
  • SuriyaaKudoIsc/gitlab-ee
  • lmsurprenant/gitlab-ee
  • kay54088/gitlab-ee
  • pablo.catalina/gitlab-ee
  • xji/gitlab-ee
  • iscorer/gitlab-ee
  • kenny-evitt/gitlab-ee
  • Francis_Jude/gitlab-ee
  • xukaierwen/gitlab-ee
  • mustafayildirim/gitlab-ee
  • hh1/gitlab-ee
  • clamp27/gitlab-ee
  • UIPCO/gitlab-ee
  • chaase/gitlab-ee
  • matt.faure/gitlab-ee
  • wstomv/gitlab-ee
  • childNode/gitlab-ee
  • LockiStrike/gitlab-ee
  • Habiballah786/gitlab-ee
  • natebird/gitlab-ee
  • tamcv/gitlab-ee
  • adligithub/gitlab-ee
  • SuperDragon317/gitlab-ee
  • pkoretic/gitlab-ee
  • schoh/gitlab-ee
  • kpankonen/gitlab-ee
  • madnut_ua/gitlab-ee
  • smoothsailing/gitlab-ee
  • TimoSolo/gitlab-ee
  • collen/gitlab-ee
  • 0_0_0/gitlab-ee
  • innerwhisper/gitlab-ee
  • issue-reproduce-forks/gitlab-ee
  • szpak/gitlab-ee
  • zullusa/gitlab-ee
  • jamatute/gitlab-ee
  • mauriciomeirelles/gitlab-ee
  • anarcat/gitlab-ee
  • Shura/gitlab-ee
  • polarise/gitlab-ee
  • ecbrodie/gitlab-ee
  • odromark/gitlab-ee
  • senk/gitlab-ee
  • hiroponz/gitlab-ee
  • rawkode/gitlab-ee
  • HaPPyWaLLaCe/gitlab-ee
  • FeditskiyRoman/gitlab-ee
  • slrz/gitlab-ee
  • realsobek/gitlab-ee
  • Eternal21/gitlab-ee
  • leungpeng/gitlab-ee
  • nprabhu02/gitlab-ee
  • CodingGroup/gitlab-ee
  • smhoekstra/gitlab-ee
  • zeih/gitlab-ee
  • biancaghiurutan/gitlab-ee
  • bstrong/gitlab-ee
  • nap/gitlab-ee
  • mollybeth/gitlab-ee
  • Jeismeier/gitlab-ee
  • bouland/gitlab-ee
  • poneytruand/gitlab-ee
  • robotmay/gitlab
380 results
Show changes
Commits on Source (15)
Showing
with 88 additions and 79 deletions
Loading
@@ -13,13 +13,17 @@ export default {
Loading
@@ -13,13 +13,17 @@ export default {
required: false, required: false,
default: true, default: true,
}, },
allowedKeys: {
type: Array,
required: true,
},
}, },
   
computed: { computed: {
processedItems() { processedItems() {
return this.items.map((item) => { return this.items.map((item) => {
const { tokens, searchToken } const { tokens, searchToken }
= gl.FilteredSearchTokenizer.processTokens(item); = gl.FilteredSearchTokenizer.processTokens(item, this.allowedKeys);
   
const resultantTokens = tokens.map(token => ({ const resultantTokens = tokens.map(token => ({
prefix: `${token.key}:`, prefix: `${token.key}:`,
Loading
Loading
Loading
@@ -2,14 +2,18 @@ import Filter from '~/droplab/plugins/filter';
Loading
@@ -2,14 +2,18 @@ import Filter from '~/droplab/plugins/filter';
import './filtered_search_dropdown'; import './filtered_search_dropdown';
   
class DropdownHint extends gl.FilteredSearchDropdown { class DropdownHint extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) { constructor(droplab, dropdown, input, tokenKeys, filter) {
super(droplab, dropdown, input, filter); super(droplab, dropdown, input, filter);
this.config = { this.config = {
Filter: { Filter: {
template: 'hint', template: 'hint',
filterFunction: gl.DropdownUtils.filterHint.bind(null, input), filterFunction: gl.DropdownUtils.filterHint.bind(null, {
input,
allowedKeys: tokenKeys.getKeys(),
}),
}, },
}; };
this.tokenKeys = tokenKeys;
} }
   
itemClicked(e) { itemClicked(e) {
Loading
@@ -52,20 +56,13 @@ class DropdownHint extends gl.FilteredSearchDropdown {
Loading
@@ -52,20 +56,13 @@ class DropdownHint extends gl.FilteredSearchDropdown {
} }
   
renderContent() { renderContent() {
const dropdownData = []; const dropdownData = this.tokenKeys.get()
.map(tokenKey => ({
[].forEach.call(this.input.closest('.filtered-search-box-input-container').querySelectorAll('.dropdown-menu'), (dropdownMenu) => { icon: `fa-${tokenKey.icon}`,
const { icon, hint, tag, type } = dropdownMenu.dataset; hint: tokenKey.key,
if (icon && hint && tag) { tag: `<${tokenKey.symbol}${tokenKey.key}>`,
dropdownData.push( type: tokenKey.type,
Object.assign({ }));
icon: `fa-${icon}`,
hint,
tag: `<${tag}>`,
}, type && { type }),
);
}
});
   
this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config); this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config);
this.droplab.setData(this.hookId, dropdownData); this.droplab.setData(this.hookId, dropdownData);
Loading
Loading
Loading
@@ -5,7 +5,7 @@ import Filter from '~/droplab/plugins/filter';
Loading
@@ -5,7 +5,7 @@ import Filter from '~/droplab/plugins/filter';
import './filtered_search_dropdown'; import './filtered_search_dropdown';
   
class DropdownNonUser extends gl.FilteredSearchDropdown { class DropdownNonUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter, endpoint, symbol) { constructor(droplab, dropdown, input, tokenKeys, filter, endpoint, symbol) {
super(droplab, dropdown, input, filter); super(droplab, dropdown, input, filter);
this.symbol = symbol; this.symbol = symbol;
this.config = { this.config = {
Loading
Loading
Loading
@@ -4,7 +4,7 @@ import AjaxFilter from '~/droplab/plugins/ajax_filter';
Loading
@@ -4,7 +4,7 @@ import AjaxFilter from '~/droplab/plugins/ajax_filter';
import './filtered_search_dropdown'; import './filtered_search_dropdown';
   
class DropdownUser extends gl.FilteredSearchDropdown { class DropdownUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) { constructor(droplab, dropdown, input, tokenKeys, filter) {
super(droplab, dropdown, input, filter); super(droplab, dropdown, input, filter);
this.config = { this.config = {
AjaxFilter: { AjaxFilter: {
Loading
@@ -25,6 +25,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
Loading
@@ -25,6 +25,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
}, },
}, },
}; };
this.tokenKeys = tokenKeys;
} }
   
itemClicked(e) { itemClicked(e) {
Loading
@@ -43,7 +44,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
Loading
@@ -43,7 +44,7 @@ class DropdownUser extends gl.FilteredSearchDropdown {
   
getSearchInput() { getSearchInput() {
const query = gl.DropdownUtils.getSearchInput(this.input); const query = gl.DropdownUtils.getSearchInput(this.input);
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query); const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
   
let value = lastToken || ''; let value = lastToken || '';
   
Loading
Loading
Loading
@@ -50,10 +50,12 @@ class DropdownUtils {
Loading
@@ -50,10 +50,12 @@ class DropdownUtils {
return updatedItem; return updatedItem;
} }
   
static filterHint(input, item) { static filterHint(config, item) {
const { input, allowedKeys } = config;
const updatedItem = item; const updatedItem = item;
const searchInput = gl.DropdownUtils.getSearchQuery(input); const searchInput = gl.DropdownUtils.getSearchQuery(input);
const { lastToken, tokens } = gl.FilteredSearchTokenizer.processTokens(searchInput); const { lastToken, tokens } =
gl.FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
const lastKey = lastToken.key || lastToken || ''; const lastKey = lastToken.key || lastToken || '';
const allowMultiple = item.type === 'array'; const allowMultiple = item.type === 'array';
const itemInExistingTokens = tokens.some(t => t.key === item.hint); const itemInExistingTokens = tokens.some(t => t.key === item.hint);
Loading
Loading
Loading
@@ -2,10 +2,10 @@ import DropLab from '~/droplab/drop_lab';
Loading
@@ -2,10 +2,10 @@ import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
   
class FilteredSearchDropdownManager { class FilteredSearchDropdownManager {
constructor(baseEndpoint = '', page) { constructor(baseEndpoint = '', tokenizer, page) {
this.container = FilteredSearchContainer.container; this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, ''); this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
this.tokenizer = gl.FilteredSearchTokenizer; this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys; this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search'); this.filteredSearchInput = this.container.querySelector('.filtered-search');
this.page = page; this.page = page;
Loading
@@ -110,7 +110,8 @@ class FilteredSearchDropdownManager {
Loading
@@ -110,7 +110,8 @@ class FilteredSearchDropdownManager {
   
if (!mappingKey.reference) { if (!mappingKey.reference) {
const dl = this.droplab; const dl = this.droplab;
const defaultArguments = [null, dl, element, this.filteredSearchInput, key]; const defaultArguments =
[null, dl, element, this.filteredSearchInput, this.filteredSearchTokenKeys, key];
const glArguments = defaultArguments.concat(mappingKey.extraArguments || []); const glArguments = defaultArguments.concat(mappingKey.extraArguments || []);
   
// Passing glArguments to `new gl[glClass](<arguments>)` // Passing glArguments to `new gl[glClass](<arguments>)`
Loading
@@ -153,7 +154,8 @@ class FilteredSearchDropdownManager {
Loading
@@ -153,7 +154,8 @@ class FilteredSearchDropdownManager {
   
setDropdown() { setDropdown() {
const query = gl.DropdownUtils.getSearchQuery(true); const query = gl.DropdownUtils.getSearchQuery(true);
const { lastToken, searchToken } = this.tokenizer.processTokens(query); const { lastToken, searchToken } =
this.tokenizer.processTokens(query, this.filteredSearchTokenKeys.getKeys());
   
if (this.currentDropdown) { if (this.currentDropdown) {
this.updateCurrentDropdownOffset(); this.updateCurrentDropdownOffset();
Loading
Loading
Loading
@@ -19,6 +19,7 @@ class FilteredSearchManager {
Loading
@@ -19,6 +19,7 @@ class FilteredSearchManager {
   
this.recentSearchesStore = new RecentSearchesStore({ this.recentSearchesStore = new RecentSearchesStore({
isLocalStorageAvailable: RecentSearchesService.isAvailable(), isLocalStorageAvailable: RecentSearchesService.isAvailable(),
allowedKeys: this.filteredSearchTokenKeys.getKeys(),
}); });
const searchHistoryDropdownElement = document.querySelector('.js-filtered-search-history-dropdown'); const searchHistoryDropdownElement = document.querySelector('.js-filtered-search-history-dropdown');
const projectPath = searchHistoryDropdownElement ? const projectPath = searchHistoryDropdownElement ?
Loading
@@ -50,7 +51,7 @@ class FilteredSearchManager {
Loading
@@ -50,7 +51,7 @@ class FilteredSearchManager {
   
if (this.filteredSearchInput) { if (this.filteredSearchInput) {
this.tokenizer = gl.FilteredSearchTokenizer; this.tokenizer = gl.FilteredSearchTokenizer;
this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', page); this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', this.tokenizer, page);
   
this.recentSearchesRoot = new RecentSearchesRoot( this.recentSearchesRoot = new RecentSearchesRoot(
this.recentSearchesStore, this.recentSearchesStore,
Loading
@@ -326,7 +327,7 @@ class FilteredSearchManager {
Loading
@@ -326,7 +327,7 @@ class FilteredSearchManager {
handleInputVisualToken() { handleInputVisualToken() {
const input = this.filteredSearchInput; const input = this.filteredSearchInput;
const { tokens, searchToken } const { tokens, searchToken }
= gl.FilteredSearchTokenizer.processTokens(input.value); = this.tokenizer.processTokens(input.value, this.filteredSearchTokenKeys.getKeys());
const { isLastVisualTokenValid } const { isLastVisualTokenValid }
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
   
Loading
@@ -452,7 +453,8 @@ class FilteredSearchManager {
Loading
@@ -452,7 +453,8 @@ class FilteredSearchManager {
this.saveCurrentSearchQuery(); this.saveCurrentSearchQuery();
   
const { tokens, searchToken } const { tokens, searchToken }
= this.tokenizer.processTokens(searchQuery); = this.tokenizer.processTokens(searchQuery, this.filteredSearchTokenKeys.getKeys());
const currentState = gl.utils.getParameterByName('state') || 'opened'; const currentState = gl.utils.getParameterByName('state') || 'opened';
paths.push(`state=${currentState}`); paths.push(`state=${currentState}`);
   
Loading
Loading
Loading
@@ -3,21 +3,25 @@ const tokenKeys = [{
Loading
@@ -3,21 +3,25 @@ const tokenKeys = [{
type: 'string', type: 'string',
param: 'username', param: 'username',
symbol: '@', symbol: '@',
icon: 'pencil',
}, { }, {
key: 'assignee', key: 'assignee',
type: 'string', type: 'string',
param: 'username', param: 'username',
symbol: '@', symbol: '@',
icon: 'user',
}, { }, {
key: 'milestone', key: 'milestone',
type: 'string', type: 'string',
param: 'title', param: 'title',
symbol: '%', symbol: '%',
icon: 'clock-o',
}, { }, {
key: 'label', key: 'label',
type: 'array', type: 'array',
param: 'name[]', param: 'name[]',
symbol: '~', symbol: '~',
icon: 'tag',
}]; }];
   
const alternativeTokenKeys = [{ const alternativeTokenKeys = [{
Loading
@@ -56,6 +60,10 @@ class FilteredSearchTokenKeys {
Loading
@@ -56,6 +60,10 @@ class FilteredSearchTokenKeys {
return tokenKeys; return tokenKeys;
} }
   
static getKeys() {
return tokenKeys.map(i => i.key);
}
static getAlternatives() { static getAlternatives() {
return alternativeTokenKeys; return alternativeTokenKeys;
} }
Loading
Loading
Loading
@@ -5,6 +5,7 @@ const weightTokenKey = {
Loading
@@ -5,6 +5,7 @@ const weightTokenKey = {
type: 'string', type: 'string',
param: '', param: '',
symbol: '', symbol: '',
icon: 'balance-scale',
}; };
   
const weightConditions = [{ const weightConditions = [{
Loading
@@ -19,11 +20,16 @@ const weightConditions = [{
Loading
@@ -19,11 +20,16 @@ const weightConditions = [{
   
class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys { class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys {
static get() { static get() {
const tokenKeys = super.get(); const tokenKeys = Array.from(super.get());
tokenKeys.push(weightTokenKey); tokenKeys.push(weightTokenKey);
return tokenKeys; return tokenKeys;
} }
   
static getKeys() {
const tokenKeys = FilteredSearchTokenKeysWithWeights.get();
return tokenKeys.map(i => i.key);
}
static getAlternatives() { static getAlternatives() {
return super.getAlternatives(); return super.getAlternatives();
} }
Loading
Loading
import './filtered_search_token_keys'; import './filtered_search_token_keys';
   
class FilteredSearchTokenizer { class FilteredSearchTokenizer {
static processTokens(input) { static processTokens(input, allowedKeys) {
const allowedKeys = gl.FilteredSearchTokenKeys.get().map(i => i.key);
// Regex extracts `(token):(symbol)(value)` // Regex extracts `(token):(symbol)(value)`
// Values that start with a double quote must end in a double quote (same for single) // Values that start with a double quote must end in a double quote (same for single)
const tokenRegex = new RegExp(`(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`, 'g'); const tokenRegex = new RegExp(`(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`, 'g');
Loading
Loading
Loading
@@ -37,6 +37,7 @@ class RecentSearchesRoot {
Loading
@@ -37,6 +37,7 @@ class RecentSearchesRoot {
<recent-searches-dropdown-content <recent-searches-dropdown-content
:items="recentSearches" :items="recentSearches"
:is-local-storage-available="isLocalStorageAvailable" :is-local-storage-available="isLocalStorageAvailable"
:allowed-keys="allowedKeys"
/> />
`, `,
components: { components: {
Loading
Loading
import _ from 'underscore'; import _ from 'underscore';
   
class RecentSearchesStore { class RecentSearchesStore {
constructor(initialState = {}) { constructor(initialState = {}, allowedKeys) {
this.state = Object.assign({ this.state = Object.assign({
isLocalStorageAvailable: true, isLocalStorageAvailable: true,
recentSearches: [], recentSearches: [],
allowedKeys,
}, initialState); }, initialState);
} }
   
Loading
Loading
Loading
@@ -49,7 +49,7 @@
Loading
@@ -49,7 +49,7 @@
{{hint}} {{hint}}
%span.js-filter-tag.dropdown-light-content %span.js-filter-tag.dropdown-light-content
{{tag}} {{tag}}
#js-dropdown-author.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'pencil', hint: 'author', tag: '@author' } } #js-dropdown-author.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item %li.filter-dropdown-item
%button.btn.btn-link.dropdown-user %button.btn.btn-link.dropdown-user
Loading
@@ -59,7 +59,7 @@
Loading
@@ -59,7 +59,7 @@
{{name}} {{name}}
%span.dropdown-light-content %span.dropdown-light-content
@{{username}} @{{username}}
#js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'user', hint: 'assignee', tag: '@assignee' } } #js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } } %li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link %button.btn.btn-link
Loading
@@ -76,7 +76,7 @@
Loading
@@ -76,7 +76,7 @@
@{{username}} @{{username}}
   
- unless board && board.milestone_id - unless board && board.milestone_id
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'clock-o', hint: 'milestone', tag: '%milestone' } } #js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } } %li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link %button.btn.btn-link
Loading
@@ -93,7 +93,7 @@
Loading
@@ -93,7 +93,7 @@
%button.btn.btn-link.js-data-value %button.btn.btn-link.js-data-value
{{title}} {{title}}
   
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'tag', hint: 'label', tag: '~label', type: 'array' } } #js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } } %li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link %button.btn.btn-link
Loading
@@ -107,7 +107,7 @@
Loading
@@ -107,7 +107,7 @@
{{title}} {{title}}
   
- if type == :issues || type == :boards || type == :boards_modal - if type == :issues || type == :boards || type == :boards_modal
#js-dropdown-weight.filtered-search-input-dropdown-menu.dropdown-menu{ data: { icon: 'balance-scale', hint: 'weight', tag: 'weight' } } #js-dropdown-weight.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ 'data-dropdown' => true } %ul{ 'data-dropdown' => true }
%li.filter-dropdown-item{ 'data-value' => 'none' } %li.filter-dropdown-item{ 'data-value' => 'none' }
%button.btn.btn-link %button.btn.btn-link
Loading
Loading
---
title: Gracefully handle case when Geo secondary does not have the right db_key_base
merge_request:
author:
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveAssigneeIdFromIssue < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
# When a migration requires downtime you **must** uncomment the following
# constant and define a short and easy to understand explanation as to why the
# migration requires downtime.
# DOWNTIME_REASON = ''
# When using the methods "add_concurrent_index", "remove_concurrent_index" or
# "add_column_with_default" you must disable the use of transactions
# as these methods can not run in an existing transaction.
# When using "add_concurrent_index" or "remove_concurrent_index" methods make sure
# that either of them is the _only_ method called in the migration,
# any other changes should go in a separate migration.
# This ensures that upon failure _only_ the index creation or removing fails
# and can be retried or reverted easily.
#
# To disable transactions uncomment the following line and remove these
# comments:
disable_ddl_transaction!
def up
remove_column :issues, :assignee_id
end
def down
add_column :issues, :assignee_id, :integer
add_concurrent_index :issues, :assignee_id
end
end
Loading
@@ -11,7 +11,7 @@
Loading
@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
   
ActiveRecord::Schema.define(version: 20170523073948) do ActiveRecord::Schema.define(version: 20170516183131) do
   
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
Loading
@@ -567,6 +567,7 @@
Loading
@@ -567,6 +567,7 @@
   
create_table "issues", force: :cascade do |t| create_table "issues", force: :cascade do |t|
t.string "title" t.string "title"
t.integer "assignee_id"
t.integer "author_id" t.integer "author_id"
t.integer "project_id" t.integer "project_id"
t.datetime "created_at" t.datetime "created_at"
Loading
@@ -595,6 +596,7 @@
Loading
@@ -595,6 +596,7 @@
t.integer "last_edited_by_id" t.integer "last_edited_by_id"
end end
   
add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree
add_index "issues", ["confidential"], name: "index_issues_on_confidential", using: :btree add_index "issues", ["confidential"], name: "index_issues_on_confidential", using: :btree
add_index "issues", ["created_at"], name: "index_issues_on_created_at", using: :btree add_index "issues", ["created_at"], name: "index_issues_on_created_at", using: :btree
Loading
Loading
Loading
@@ -183,7 +183,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
Loading
@@ -183,7 +183,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
private private
   
def assigned_to_me(key) def assigned_to_me(key)
project.send(key).assigned_to(current_user) project.send(key).where(assignee_id: current_user.id)
end end
   
def project def project
Loading
Loading
Loading
@@ -94,8 +94,12 @@ class Geo < Grape::API
Loading
@@ -94,8 +94,12 @@ class Geo < Grape::API
def authenticate_by_gitlab_geo_node_token! def authenticate_by_gitlab_geo_node_token!
auth_header = headers['Authorization'] auth_header = headers['Authorization']
   
unless auth_header && Gitlab::Geo::JwtRequestDecoder.new(auth_header).decode begin
unauthorized! unless auth_header && Gitlab::Geo::JwtRequestDecoder.new(auth_header).decode
unauthorized!
end
rescue Gitlab::Geo::InvalidDecryptionKeyError => e
render_api_error!(e.to_s, 401)
end end
end end
   
Loading
Loading
module Gitlab module Gitlab
module Geo module Geo
InvalidDecryptionKeyError = Class.new(StandardError)
class JwtRequestDecoder class JwtRequestDecoder
IAT_LEEWAY = 60.seconds.to_i IAT_LEEWAY = 60.seconds.to_i
   
Loading
@@ -22,7 +24,13 @@ def decode_geo_request
Loading
@@ -22,7 +24,13 @@ def decode_geo_request
# For example: # For example:
# JWT payload = { "data": { "oid": "12345" }, iat: 123456 } # JWT payload = { "data": { "oid": "12345" }, iat: 123456 }
# #
data = decode_auth_header begin
data = decode_auth_header
rescue OpenSSL::Cipher::CipherError
message = 'Error decrypting the Geo secret from the database. Check that the primary and secondary have the same db_key_base.'
Rails.logger.error(message)
raise InvalidDecryptionKeyError.new(message)
end
   
return unless data.present? return unless data.present?
   
Loading
Loading
Loading
@@ -2,6 +2,8 @@ import Vue from 'vue';
Loading
@@ -2,6 +2,8 @@ import Vue from 'vue';
import eventHub from '~/filtered_search/event_hub'; import eventHub from '~/filtered_search/event_hub';
import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content'; import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content';
   
import '~/filtered_search/filtered_search_token_keys';
const createComponent = (propsData) => { const createComponent = (propsData) => {
const Component = Vue.extend(RecentSearchesDropdownContent); const Component = Vue.extend(RecentSearchesDropdownContent);
   
Loading
@@ -17,12 +19,14 @@ const trimMarkupWhitespace = text => text.replace(/(\n|\s)+/gm, ' ').trim();
Loading
@@ -17,12 +19,14 @@ const trimMarkupWhitespace = text => text.replace(/(\n|\s)+/gm, ' ').trim();
describe('RecentSearchesDropdownContent', () => { describe('RecentSearchesDropdownContent', () => {
const propsDataWithoutItems = { const propsDataWithoutItems = {
items: [], items: [],
allowedKeys: gl.FilteredSearchTokenKeys.getKeys(),
}; };
const propsDataWithItems = { const propsDataWithItems = {
items: [ items: [
'foo', 'foo',
'author:@root label:~foo bar', 'author:@root label:~foo bar',
], ],
allowedKeys: gl.FilteredSearchTokenKeys.getKeys(),
}; };
   
let vm; let vm;
Loading
Loading