mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-31 00:16:47 +01:00
feat: serach and filter input to query param parser (#5255)
This commit is contained in:
parent
a2b0507459
commit
fe61947435
@ -0,0 +1,50 @@
|
||||
import { translateToQueryParams } from './searchToQueryParams';
|
||||
|
||||
describe('translateToQueryParams', () => {
|
||||
describe.each([
|
||||
['search', 'query=search'],
|
||||
[' search', 'query=search'],
|
||||
[' search ', 'query=search'],
|
||||
['search ', 'query=search'],
|
||||
['search with space', 'query=search with space'],
|
||||
['search type:release', 'query=search&type[]=release'],
|
||||
[' search type:release ', 'query=search&type[]=release'],
|
||||
[
|
||||
'search type:release,experiment',
|
||||
'query=search&type[]=release&type[]=experiment',
|
||||
],
|
||||
[
|
||||
'search type:release ,experiment',
|
||||
'query=search&type[]=release&type[]=experiment',
|
||||
],
|
||||
[
|
||||
'search type:release, experiment',
|
||||
'query=search&type[]=release&type[]=experiment',
|
||||
],
|
||||
[
|
||||
'search type:release , experiment',
|
||||
'query=search&type[]=release&type[]=experiment',
|
||||
],
|
||||
[
|
||||
'search type: release , experiment',
|
||||
'query=search&type[]=release&type[]=experiment',
|
||||
],
|
||||
['type:release', 'type[]=release'],
|
||||
['type: release', 'type[]=release'],
|
||||
['production:enabled', 'status[]=production:enabled'],
|
||||
[
|
||||
'development:enabled,disabled',
|
||||
'status[]=development:enabled&status[]=development:disabled',
|
||||
],
|
||||
['tag:simple:web', 'tag[]=simple:web'],
|
||||
['tag:enabled:enabled', 'tag[]=enabled:enabled'],
|
||||
[
|
||||
'tag:simple:web,complex:native',
|
||||
'tag[]=simple:web&tag[]=complex:native',
|
||||
],
|
||||
])('when input is "%s"', (input, expected) => {
|
||||
it(`returns "${expected}"`, () => {
|
||||
expect(translateToQueryParams(input)).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,117 @@
|
||||
const splitInputQuery = (searchString: string): string[] =>
|
||||
searchString.trim().split(/ (?=\w+:)/);
|
||||
|
||||
const isFilter = (part: string): boolean => part.includes(':');
|
||||
|
||||
const isStatusFilter = (key: string, values: string[]): boolean =>
|
||||
values.every((value) => value === 'enabled' || value === 'disabled');
|
||||
|
||||
const addStatusFilters = (
|
||||
key: string,
|
||||
values: string[],
|
||||
filterParams: Record<string, string | string[]>,
|
||||
): Record<string, string | string[]> => {
|
||||
const newStatuses = values.map((value) => `${key}:${value}`);
|
||||
return {
|
||||
...filterParams,
|
||||
status: [...(filterParams.status || []), ...newStatuses],
|
||||
};
|
||||
};
|
||||
|
||||
const addTagFilters = (
|
||||
values: string[],
|
||||
filterParams: Record<string, string | string[]>,
|
||||
): Record<string, string | string[]> => ({
|
||||
...filterParams,
|
||||
tag: [...(filterParams.tag || []), ...values],
|
||||
});
|
||||
|
||||
const addRegularFilters = (
|
||||
key: string,
|
||||
values: string[],
|
||||
filterParams: Record<string, string | string[]>,
|
||||
): Record<string, string | string[]> => ({
|
||||
...filterParams,
|
||||
[key]: [...(filterParams[key] || []), ...values],
|
||||
});
|
||||
|
||||
const handleFilter = (
|
||||
part: string,
|
||||
filterParams: Record<string, string | string[]>,
|
||||
): Record<string, string | string[]> => {
|
||||
const [key, ...valueParts] = part.split(':');
|
||||
const valueString = valueParts.join(':').trim();
|
||||
const values = valueString.split(',').map((value) => value.trim());
|
||||
|
||||
if (isStatusFilter(key, values)) {
|
||||
return addStatusFilters(key, values, filterParams);
|
||||
} else if (key === 'tag') {
|
||||
return addTagFilters(values, filterParams);
|
||||
} else {
|
||||
return addRegularFilters(key, values, filterParams);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearchTerm = (
|
||||
part: string,
|
||||
filterParams: Record<string, string | string[]>,
|
||||
): Record<string, string | string[]> => ({
|
||||
...filterParams,
|
||||
query: filterParams.query
|
||||
? `${filterParams.query} ${part.trim()}`
|
||||
: part.trim(),
|
||||
});
|
||||
|
||||
const appendFilterParamsToQueryParts = (
|
||||
params: Record<string, string | string[]>,
|
||||
): string[] => {
|
||||
let newQueryParts: string[] = [];
|
||||
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (Array.isArray(value)) {
|
||||
newQueryParts = [
|
||||
...newQueryParts,
|
||||
...value.map((item) => `${key}[]=${item}`),
|
||||
];
|
||||
} else {
|
||||
newQueryParts.push(`${key}=${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
return newQueryParts;
|
||||
};
|
||||
|
||||
const convertToQueryString = (
|
||||
params: Record<string, string | string[]>,
|
||||
): string => {
|
||||
const { query, ...filterParams } = params;
|
||||
let queryParts: string[] = [];
|
||||
|
||||
if (query) {
|
||||
queryParts.push(`query=${query}`);
|
||||
}
|
||||
|
||||
queryParts = queryParts.concat(
|
||||
appendFilterParamsToQueryParts(filterParams),
|
||||
);
|
||||
|
||||
return queryParts.join('&');
|
||||
};
|
||||
|
||||
const buildSearchParams = (
|
||||
input: string,
|
||||
): Record<string, string | string[]> => {
|
||||
const parts = splitInputQuery(input);
|
||||
return parts.reduce(
|
||||
(searchAndFilterParams, part) =>
|
||||
isFilter(part)
|
||||
? handleFilter(part, searchAndFilterParams)
|
||||
: handleSearchTerm(part, searchAndFilterParams),
|
||||
{},
|
||||
);
|
||||
};
|
||||
|
||||
export const translateToQueryParams = (searchString: string): string => {
|
||||
const searchParams = buildSearchParams(searchString);
|
||||
return convertToQueryString(searchParams);
|
||||
};
|
Loading…
Reference in New Issue
Block a user