1
0
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:
Mateusz Kwasniewski 2023-11-03 10:10:46 +01:00 committed by GitHub
parent a2b0507459
commit fe61947435
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 167 additions and 0 deletions

View File

@ -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);
});
});
});

View File

@ -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);
};