Commit 01a18396 authored by Phil Hughes's avatar Phil Hughes

Merge branch '1967-search-issues-multiple-assignees' into 'master'

Allow multiple assignees to be chosen from dropdown filters

Closes #1967

See merge request !1494
parents 4e2209f1 1a9c7d3f
...@@ -10,4 +10,4 @@ import './filtered_search_tokenizer'; ...@@ -10,4 +10,4 @@ import './filtered_search_tokenizer';
import './filtered_search_visual_tokens'; import './filtered_search_visual_tokens';
// EE-only // EE-only
import './filtered_search_token_keys_with_weights'; import './filtered_search_token_keys_issues_ee';
...@@ -11,7 +11,7 @@ class FilteredSearchDropdownManager { ...@@ -11,7 +11,7 @@ class FilteredSearchDropdownManager {
this.page = page; this.page = page;
if (this.page === 'issues' || this.page === 'boards') { if (this.page === 'issues' || this.page === 'boards') {
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeysWithWeights; this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeysIssuesEE;
} }
this.setupMapping(); this.setupMapping();
......
...@@ -14,7 +14,7 @@ class FilteredSearchManager { ...@@ -14,7 +14,7 @@ class FilteredSearchManager {
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys; this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys;
if (page === 'issues' || page === 'boards') { if (page === 'issues' || page === 'boards') {
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeysWithWeights; this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeysIssuesEE;
} }
this.recentSearchesStore = new RecentSearchesStore({ this.recentSearchesStore = new RecentSearchesStore({
......
...@@ -18,15 +18,20 @@ const weightConditions = [{ ...@@ -18,15 +18,20 @@ const weightConditions = [{
value: 'any', value: 'any',
}]; }];
class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys { class FilteredSearchTokenKeysIssuesEE extends gl.FilteredSearchTokenKeys {
static get() { static get() {
const tokenKeys = Array.from(super.get()); const tokenKeys = Array.from(super.get());
// Enable multiple assignees
const assigneeTokenKey = tokenKeys.find(tk => tk.key === 'assignee');
assigneeTokenKey.type = 'array';
tokenKeys.push(weightTokenKey); tokenKeys.push(weightTokenKey);
return tokenKeys; return tokenKeys;
} }
static getKeys() { static getKeys() {
const tokenKeys = FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = FilteredSearchTokenKeysIssuesEE.get();
return tokenKeys.map(i => i.key); return tokenKeys.map(i => i.key);
} }
...@@ -40,18 +45,18 @@ class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys { ...@@ -40,18 +45,18 @@ class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys {
} }
static searchByKey(key) { static searchByKey(key) {
const tokenKeys = FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = FilteredSearchTokenKeysIssuesEE.get();
return tokenKeys.find(tokenKey => tokenKey.key === key) || null; return tokenKeys.find(tokenKey => tokenKey.key === key) || null;
} }
static searchBySymbol(symbol) { static searchBySymbol(symbol) {
const tokenKeys = FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = FilteredSearchTokenKeysIssuesEE.get();
return tokenKeys.find(tokenKey => tokenKey.symbol === symbol) || null; return tokenKeys.find(tokenKey => tokenKey.symbol === symbol) || null;
} }
static searchByKeyParam(keyParam) { static searchByKeyParam(keyParam) {
const tokenKeys = FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = FilteredSearchTokenKeysIssuesEE.get();
const alternativeTokenKeys = FilteredSearchTokenKeysWithWeights.getAlternatives(); const alternativeTokenKeys = FilteredSearchTokenKeysIssuesEE.getAlternatives();
const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys); const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys);
return tokenKeysWithAlternative.find((tokenKey) => { return tokenKeysWithAlternative.find((tokenKey) => {
...@@ -66,16 +71,16 @@ class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys { ...@@ -66,16 +71,16 @@ class FilteredSearchTokenKeysWithWeights extends gl.FilteredSearchTokenKeys {
} }
static searchByConditionUrl(url) { static searchByConditionUrl(url) {
const conditions = FilteredSearchTokenKeysWithWeights.getConditions(); const conditions = FilteredSearchTokenKeysIssuesEE.getConditions();
return conditions.find(condition => condition.url === url) || null; return conditions.find(condition => condition.url === url) || null;
} }
static searchByConditionKeyValue(key, value) { static searchByConditionKeyValue(key, value) {
const conditions = FilteredSearchTokenKeysWithWeights.getConditions(); const conditions = FilteredSearchTokenKeysIssuesEE.getConditions();
return conditions return conditions
.find(condition => condition.tokenKey === key && condition.value === value) || null; .find(condition => condition.tokenKey === key && condition.value === value) || null;
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchTokenKeysWithWeights = FilteredSearchTokenKeysWithWeights; gl.FilteredSearchTokenKeysIssuesEE = FilteredSearchTokenKeysIssuesEE;
import '~/extensions/array'; import '~/extensions/array';
import '~/filtered_search/filtered_search_token_keys_with_weights'; import '~/filtered_search/filtered_search_token_keys_issues_ee';
(() => { (() => {
describe('Filtered Search Token Keys With Weights', () => { describe('Filtered Search Token Keys (Issues EE)', () => {
const weightTokenKey = { const weightTokenKey = {
key: 'weight', key: 'weight',
type: 'string', type: 'string',
...@@ -15,7 +15,7 @@ import '~/filtered_search/filtered_search_token_keys_with_weights'; ...@@ -15,7 +15,7 @@ import '~/filtered_search/filtered_search_token_keys_with_weights';
let tokenKeys; let tokenKeys;
beforeEach(() => { beforeEach(() => {
tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
}); });
it('should return tokenKeys', () => { it('should return tokenKeys', () => {
...@@ -32,16 +32,21 @@ import '~/filtered_search/filtered_search_token_keys_with_weights'; ...@@ -32,16 +32,21 @@ import '~/filtered_search/filtered_search_token_keys_with_weights';
}); });
it('should always return the same array', () => { it('should always return the same array', () => {
const tokenKeys2 = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys2 = gl.FilteredSearchTokenKeysIssuesEE.get();
expect(tokenKeys).toEqual(tokenKeys2); expect(tokenKeys).toEqual(tokenKeys2);
}); });
it('should return assignee as an array', () => {
const assignee = tokenKeys.find(tokenKey => tokenKey.key === 'assignee');
expect(assignee.type).toEqual('array');
});
}); });
describe('getKeys', () => { describe('getKeys', () => {
it('should return keys', () => { it('should return keys', () => {
const getKeys = gl.FilteredSearchTokenKeysWithWeights.getKeys(); const getKeys = gl.FilteredSearchTokenKeysIssuesEE.getKeys();
const keys = gl.FilteredSearchTokenKeysWithWeights.get().map(i => i.key); const keys = gl.FilteredSearchTokenKeysIssuesEE.get().map(i => i.key);
keys.forEach((key, i) => { keys.forEach((key, i) => {
expect(key).toEqual(getKeys[i]); expect(key).toEqual(getKeys[i]);
...@@ -53,7 +58,7 @@ import '~/filtered_search/filtered_search_token_keys_with_weights'; ...@@ -53,7 +58,7 @@ import '~/filtered_search/filtered_search_token_keys_with_weights';
let conditions; let conditions;
beforeEach(() => { beforeEach(() => {
conditions = gl.FilteredSearchTokenKeysWithWeights.getConditions(); conditions = gl.FilteredSearchTokenKeysIssuesEE.getConditions();
}); });
it('should return conditions', () => { it('should return conditions', () => {
...@@ -72,89 +77,89 @@ import '~/filtered_search/filtered_search_token_keys_with_weights'; ...@@ -72,89 +77,89 @@ import '~/filtered_search/filtered_search_token_keys_with_weights';
describe('searchByKey', () => { describe('searchByKey', () => {
it('should return null when key not found', () => { it('should return null when key not found', () => {
const tokenKey = gl.FilteredSearchTokenKeysWithWeights.searchByKey('notakey'); const tokenKey = gl.FilteredSearchTokenKeysIssuesEE.searchByKey('notakey');
expect(tokenKey === null).toBe(true); expect(tokenKey === null).toBe(true);
}); });
it('should return tokenKey when found by key', () => { it('should return tokenKey when found by key', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
const result = gl.FilteredSearchTokenKeysWithWeights.searchByKey(tokenKeys[0].key); const result = gl.FilteredSearchTokenKeysIssuesEE.searchByKey(tokenKeys[0].key);
expect(result).toEqual(tokenKeys[0]); expect(result).toEqual(tokenKeys[0]);
}); });
it('should return weight tokenKey when found by weight key', () => { it('should return weight tokenKey when found by weight key', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
const match = tokenKeys.find(tk => tk.key === weightTokenKey.key); const match = tokenKeys.find(tk => tk.key === weightTokenKey.key);
const result = gl.FilteredSearchTokenKeysWithWeights.searchByKey(weightTokenKey.key); const result = gl.FilteredSearchTokenKeysIssuesEE.searchByKey(weightTokenKey.key);
expect(result).toEqual(match); expect(result).toEqual(match);
}); });
}); });
describe('searchBySymbol', () => { describe('searchBySymbol', () => {
it('should return null when symbol not found', () => { it('should return null when symbol not found', () => {
const tokenKey = gl.FilteredSearchTokenKeysWithWeights.searchBySymbol('notasymbol'); const tokenKey = gl.FilteredSearchTokenKeysIssuesEE.searchBySymbol('notasymbol');
expect(tokenKey === null).toBe(true); expect(tokenKey === null).toBe(true);
}); });
it('should return tokenKey when found by symbol', () => { it('should return tokenKey when found by symbol', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
const result = gl.FilteredSearchTokenKeysWithWeights.searchBySymbol(tokenKeys[0].symbol); const result = gl.FilteredSearchTokenKeysIssuesEE.searchBySymbol(tokenKeys[0].symbol);
expect(result).toEqual(tokenKeys[0]); expect(result).toEqual(tokenKeys[0]);
}); });
it('should return weight tokenKey when found by weight symbol', () => { it('should return weight tokenKey when found by weight symbol', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
const match = tokenKeys.find(tk => tk.key === weightTokenKey.key); const match = tokenKeys.find(tk => tk.key === weightTokenKey.key);
const result = gl.FilteredSearchTokenKeysWithWeights.searchBySymbol(weightTokenKey.symbol); const result = gl.FilteredSearchTokenKeysIssuesEE.searchBySymbol(weightTokenKey.symbol);
expect(result).toEqual(match); expect(result).toEqual(match);
}); });
}); });
describe('searchByKeyParam', () => { describe('searchByKeyParam', () => {
it('should return null when key param not found', () => { it('should return null when key param not found', () => {
const tokenKey = gl.FilteredSearchTokenKeysWithWeights.searchByKeyParam('notakeyparam'); const tokenKey = gl.FilteredSearchTokenKeysIssuesEE.searchByKeyParam('notakeyparam');
expect(tokenKey === null).toBe(true); expect(tokenKey === null).toBe(true);
}); });
it('should return tokenKey when found by key param', () => { it('should return tokenKey when found by key param', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
const result = gl.FilteredSearchTokenKeysWithWeights const result = gl.FilteredSearchTokenKeysIssuesEE
.searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`); .searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
expect(result).toEqual(tokenKeys[0]); expect(result).toEqual(tokenKeys[0]);
}); });
it('should return alternative tokenKey when found by key param', () => { it('should return alternative tokenKey when found by key param', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.getAlternatives(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.getAlternatives();
const result = gl.FilteredSearchTokenKeysWithWeights const result = gl.FilteredSearchTokenKeysIssuesEE
.searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`); .searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
expect(result).toEqual(tokenKeys[0]); expect(result).toEqual(tokenKeys[0]);
}); });
it('should return weight tokenKey when found by weight key param', () => { it('should return weight tokenKey when found by weight key param', () => {
const tokenKeys = gl.FilteredSearchTokenKeysWithWeights.get(); const tokenKeys = gl.FilteredSearchTokenKeysIssuesEE.get();
const match = tokenKeys.find(tk => tk.key === weightTokenKey.key); const match = tokenKeys.find(tk => tk.key === weightTokenKey.key);
const result = gl.FilteredSearchTokenKeysWithWeights.searchByKeyParam(weightTokenKey.key); const result = gl.FilteredSearchTokenKeysIssuesEE.searchByKeyParam(weightTokenKey.key);
expect(result).toEqual(match); expect(result).toEqual(match);
}); });
}); });
describe('searchByConditionUrl', () => { describe('searchByConditionUrl', () => {
it('should return null when condition url not found', () => { it('should return null when condition url not found', () => {
const condition = gl.FilteredSearchTokenKeysWithWeights.searchByConditionUrl(null); const condition = gl.FilteredSearchTokenKeysIssuesEE.searchByConditionUrl(null);
expect(condition === null).toBe(true); expect(condition === null).toBe(true);
}); });
it('should return condition when found by url', () => { it('should return condition when found by url', () => {
const conditions = gl.FilteredSearchTokenKeysWithWeights.getConditions(); const conditions = gl.FilteredSearchTokenKeysIssuesEE.getConditions();
const result = gl.FilteredSearchTokenKeysWithWeights const result = gl.FilteredSearchTokenKeysIssuesEE
.searchByConditionUrl(conditions[0].url); .searchByConditionUrl(conditions[0].url);
expect(result).toBe(conditions[0]); expect(result).toBe(conditions[0]);
}); });
it('should return weight condition when found by weight url', () => { it('should return weight condition when found by weight url', () => {
const conditions = gl.FilteredSearchTokenKeysWithWeights.getConditions(); const conditions = gl.FilteredSearchTokenKeysIssuesEE.getConditions();
const weightConditions = conditions.filter(c => c.tokenKey === 'weight'); const weightConditions = conditions.filter(c => c.tokenKey === 'weight');
const result = gl.FilteredSearchTokenKeysWithWeights const result = gl.FilteredSearchTokenKeysIssuesEE
.searchByConditionUrl(weightConditions[0].url); .searchByConditionUrl(weightConditions[0].url);
expect(result).toBe(weightConditions[0]); expect(result).toBe(weightConditions[0]);
}); });
...@@ -162,22 +167,22 @@ import '~/filtered_search/filtered_search_token_keys_with_weights'; ...@@ -162,22 +167,22 @@ import '~/filtered_search/filtered_search_token_keys_with_weights';
describe('searchByConditionKeyValue', () => { describe('searchByConditionKeyValue', () => {
it('should return null when condition tokenKey and value not found', () => { it('should return null when condition tokenKey and value not found', () => {
const condition = gl.FilteredSearchTokenKeysWithWeights const condition = gl.FilteredSearchTokenKeysIssuesEE
.searchByConditionKeyValue(null, null); .searchByConditionKeyValue(null, null);
expect(condition === null).toBe(true); expect(condition === null).toBe(true);
}); });
it('should return condition when found by tokenKey and value', () => { it('should return condition when found by tokenKey and value', () => {
const conditions = gl.FilteredSearchTokenKeysWithWeights.getConditions(); const conditions = gl.FilteredSearchTokenKeysIssuesEE.getConditions();
const result = gl.FilteredSearchTokenKeysWithWeights const result = gl.FilteredSearchTokenKeysIssuesEE
.searchByConditionKeyValue(conditions[0].tokenKey, conditions[0].value); .searchByConditionKeyValue(conditions[0].tokenKey, conditions[0].value);
expect(result).toEqual(conditions[0]); expect(result).toEqual(conditions[0]);
}); });
it('should return weight condition when found by weight tokenKey and value', () => { it('should return weight condition when found by weight tokenKey and value', () => {
const conditions = gl.FilteredSearchTokenKeysWithWeights.getConditions(); const conditions = gl.FilteredSearchTokenKeysIssuesEE.getConditions();
const weightConditions = conditions.filter(c => c.tokenKey === 'weight'); const weightConditions = conditions.filter(c => c.tokenKey === 'weight');
const result = gl.FilteredSearchTokenKeysWithWeights const result = gl.FilteredSearchTokenKeysIssuesEE
.searchByConditionKeyValue(weightConditions[0].tokenKey, weightConditions[0].value); .searchByConditionKeyValue(weightConditions[0].tokenKey, weightConditions[0].value);
expect(result).toEqual(weightConditions[0]); expect(result).toEqual(weightConditions[0]);
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment