Add searchBy
helper & SidebarItemEpicsSelect
- Adds `searchBy` util in common utils - Adds placeholder `SidebarItemEpicsSelect`
This commit is contained in:
parent
e84f5a673e
commit
6044b3ed1e
4 changed files with 109 additions and 0 deletions
|
@ -22,6 +22,8 @@ export default Vue.extend({
|
|||
components: {
|
||||
AssigneeTitle,
|
||||
Assignees,
|
||||
SidebarEpicsSelect: () =>
|
||||
import('ee_component/sidebar/components/sidebar_item_epics_select.vue'),
|
||||
RemoveBtn,
|
||||
Subscriptions,
|
||||
TimeTracker,
|
||||
|
|
|
@ -731,6 +731,66 @@ export const NavigationType = {
|
|||
TYPE_RESERVED: 255,
|
||||
};
|
||||
|
||||
/**
|
||||
* Method to perform case-insensitive search for a string
|
||||
* within multiple properties and return object containing
|
||||
* properties in case there are multiple matches or `null`
|
||||
* if there's no match.
|
||||
*
|
||||
* Eg; Suppose we want to allow user to search using for a string
|
||||
* within `iid`, `title`, `url` or `reference` props of a target object;
|
||||
*
|
||||
* const objectToSearch = {
|
||||
* "iid": 1,
|
||||
* "title": "Error omnis quos consequatur ullam a vitae sed omnis libero cupiditate. &3",
|
||||
* "url": "/groups/gitlab-org/-/epics/1",
|
||||
* "reference": "&1",
|
||||
* };
|
||||
*
|
||||
* Following is how we call searchBy and the return values it will yield;
|
||||
*
|
||||
* - `searchBy('omnis', objectToSearch);`: This will return `{ title: ... }` as our
|
||||
* query was found within title prop we only return that.
|
||||
* - `searchBy('1', objectToSearch);`: This will return `{ "iid": ..., "reference": ..., "url": ... }`.
|
||||
* - `searchBy('https://gitlab.com/groups/gitlab-org/-/epics/1', objectToSearch);`:
|
||||
* This will return `{ "url": ... }`.
|
||||
* - `searchBy('foo', objectToSearch);`: This will return `null` as no property value
|
||||
* matched with our query.
|
||||
*
|
||||
* You can learn more about behaviour of this method by referring to tests
|
||||
* within `spec/javascripts/lib/utils/common_utils_spec.js`.
|
||||
*
|
||||
* @param {string} query String to search for
|
||||
* @param {object} searchSpace Object containing properties to search in for `query`
|
||||
*/
|
||||
export const searchBy = (query = '', searchSpace = {}) => {
|
||||
const targetKeys = searchSpace !== null ? Object.keys(searchSpace) : [];
|
||||
|
||||
if (!query || !targetKeys.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const normalizedQuery = query.toLowerCase();
|
||||
const matches = targetKeys
|
||||
.filter(item => {
|
||||
const searchItem = `${searchSpace[item]}`.toLowerCase();
|
||||
|
||||
return (
|
||||
searchItem.indexOf(normalizedQuery) > -1 ||
|
||||
normalizedQuery.indexOf(searchItem) > -1 ||
|
||||
normalizedQuery === searchItem
|
||||
);
|
||||
})
|
||||
.reduce((acc, prop) => {
|
||||
const match = acc;
|
||||
match[prop] = searchSpace[prop];
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return Object.keys(matches).length ? matches : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the given Label has a special syntax `::` in
|
||||
* it's title.
|
||||
|
|
|
@ -65,6 +65,8 @@ Example response:
|
|||
"title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
|
||||
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
|
||||
"state": "opened",
|
||||
"web_edit_url": "http://localhost:3001/groups/test/-/epics/4",
|
||||
"reference": "&4",
|
||||
"author": {
|
||||
"id": 10,
|
||||
"name": "Lu Mayer",
|
||||
|
@ -118,6 +120,8 @@ Example response:
|
|||
"title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
|
||||
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
|
||||
"state": "opened",
|
||||
"web_edit_url": "http://localhost:3001/groups/test/-/epics/5",
|
||||
"reference": "&5",
|
||||
"author":{
|
||||
"id": 7,
|
||||
"name": "Pamella Huel",
|
||||
|
@ -182,6 +186,8 @@ Example response:
|
|||
"title": "Epic",
|
||||
"description": "Epic description",
|
||||
"state": "opened",
|
||||
"web_edit_url": "http://localhost:3001/groups/test/-/epics/6",
|
||||
"reference": "&6",
|
||||
"author": {
|
||||
"name" : "Alexandra Bashirian",
|
||||
"avatar_url" : null,
|
||||
|
@ -247,6 +253,8 @@ Example response:
|
|||
"title": "New Title",
|
||||
"description": "Epic description",
|
||||
"state": "opened",
|
||||
"web_edit_url": "http://localhost:3001/groups/test/-/epics/6",
|
||||
"reference": "&6",
|
||||
"author": {
|
||||
"name" : "Alexandra Bashirian",
|
||||
"avatar_url" : null,
|
||||
|
|
|
@ -895,6 +895,45 @@ describe('common_utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('searchBy', () => {
|
||||
const searchSpace = {
|
||||
iid: 1,
|
||||
reference: '&1',
|
||||
title: 'Error omnis quos consequatur ullam a vitae sed omnis libero cupiditate.',
|
||||
url: '/groups/gitlab-org/-/epics/1',
|
||||
};
|
||||
|
||||
it('returns null when `query` or `searchSpace` params are empty/undefined', () => {
|
||||
expect(commonUtils.searchBy('omnis', null)).toBeNull();
|
||||
expect(commonUtils.searchBy('', searchSpace)).toBeNull();
|
||||
expect(commonUtils.searchBy()).toBeNull();
|
||||
});
|
||||
|
||||
it('returns object with matching props based on `query` & `searchSpace` params', () => {
|
||||
// String `omnis` is found only in `title` prop so return just that
|
||||
expect(commonUtils.searchBy('omnis', searchSpace)).toEqual(
|
||||
jasmine.objectContaining({
|
||||
title: searchSpace.title,
|
||||
}),
|
||||
);
|
||||
|
||||
// String `1` is found in both `iid` and `reference` props so return both
|
||||
expect(commonUtils.searchBy('1', searchSpace)).toEqual(
|
||||
jasmine.objectContaining({
|
||||
iid: searchSpace.iid,
|
||||
reference: searchSpace.reference,
|
||||
}),
|
||||
);
|
||||
|
||||
// String `/epics/1` is found in `url` prop so return just that
|
||||
expect(commonUtils.searchBy('/epics/1', searchSpace)).toEqual(
|
||||
jasmine.objectContaining({
|
||||
url: searchSpace.url,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isScopedLabel', () => {
|
||||
it('returns true when `::` is present in title', () => {
|
||||
expect(commonUtils.isScopedLabel({ title: 'foo::bar' })).toBe(true);
|
||||
|
|
Loading…
Reference in a new issue