1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-11-01 19:07:38 +01:00
unleash.unleash/frontend/src/hooks/useSearch.ts

131 lines
3.7 KiB
TypeScript
Raw Normal View History

interface IUseSearchOutput {
getSearchText: (input: string) => string;
data: any[];
getSearchContext: () => IGetSearchContextOutput;
}
export interface IGetSearchContextOutput {
data: any[];
columns: any[];
searchValue: string;
}
export const useSearch = (
columns: any[],
searchValue: string,
data: any[]
): IUseSearchOutput => {
const getSearchText = getSearchTextGenerator(columns);
const getSearchContext = () => {
return { data, searchValue, columns };
};
if (!searchValue) return { data, getSearchText, getSearchContext };
const search = () => {
const filteredData = filter(columns, searchValue, data);
const searchedData = searchInFilteredData(
columns,
getSearchText(searchValue),
filteredData
);
return searchedData;
};
return { data: search(), getSearchText, getSearchContext };
};
export const filter = (columns: any[], searchValue: string, data: any[]) => {
let filteredDataSet = data;
getFilterableColumns(columns)
.filter(column => isValidFilter(searchValue, column.filterName))
.forEach(column => {
const values = getFilterValues(column.filterName, searchValue);
filteredDataSet = filteredDataSet.filter(row => {
if (column.filterBy) {
return column.filterBy(row, values);
}
return defaultFilter(getColumnValues(column, row), values);
});
});
return filteredDataSet;
};
export const searchInFilteredData = (
columns: any[],
searchValue: string,
filteredData: any[]
) => {
const searchableColumns = columns.filter(
column => column.searchable && column.accessor
);
return filteredData.filter(row => {
return searchableColumns.some(column => {
if (column.searchBy) {
return column.searchBy(row, searchValue);
}
return defaultSearch(getColumnValues(column, row), searchValue);
});
});
};
const defaultFilter = (fieldValue: string, values: string[]) =>
values.some(value => fieldValue?.toLowerCase() === value?.toLowerCase());
const defaultSearch = (fieldValue: string, value: string) =>
fieldValue?.toLowerCase().includes(value?.toLowerCase());
export const getSearchTextGenerator = (columns: any[]) => {
const filters = columns
.filter(column => column.filterName)
.map(column => column.filterName);
const isValidSearch = (fragment: string) => {
return filters.some(filter => isValidFilter(fragment, filter));
};
return (searchValue: string) =>
searchValue
.split(' ')
.filter(fragment => !isValidSearch(fragment))
.join(' ');
};
export const isValidFilter = (input: string, match: string) =>
new RegExp(`${match}:\\w+`).test(input);
export const getFilterableColumns = (columns: any[]) =>
columns.filter(column => column.filterName && column.accessor);
export const getColumnValues = (column: any, row: any) => {
const value =
typeof column.accessor === 'function'
? column.accessor(row)
: column.accessor.includes('.')
? column.accessor
.split('.')
.reduce((object: any, key: string) => object[key], row)
: row[column.accessor];
if (column.filterParsing) {
return column.filterParsing(value);
}
return value;
};
export const getFilterValues = (filterName: string, searchValue: string) =>
searchValue
?.split(`${filterName}:`)[1]
?.split(' ')[0]
?.split(',')
.filter(value => value) ?? [];