feat: add custom orderBy (#2975)

* feat: add custom orderBy

* chore: magic string is removed

---------

Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
Yevhen Shevchenko 2023-06-29 18:49:56 +03:00 committed by GitHub
parent 3464b2a59c
commit 0f998a4845
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 16 deletions

View File

@ -1,6 +1,8 @@
import { Select, Spin } from 'antd';
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
import { QueryBuilderKeys } from 'constants/queryBuilder';
import { IOption } from 'hooks/useResourceAttribute/types';
import { uniqWith } from 'lodash-es';
import * as Papa from 'papaparse';
import { useCallback, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
@ -9,6 +11,7 @@ import { DataSource, MetricAggregateOperator } from 'types/common/queryBuilder';
import { selectStyle } from '../QueryBuilderSearch/config';
import { getRemoveOrderFromValue } from '../QueryBuilderSearch/utils';
import { FILTERS } from './config';
import { OrderByFilterProps } from './OrderByFilter.interfaces';
import {
checkIfKeyPresent,
@ -22,7 +25,7 @@ export function OrderByFilter({
onChange,
}: OrderByFilterProps): JSX.Element {
const [searchText, setSearchText] = useState<string>('');
const [selectedValue, setSelectedValue] = useState<string[]>([]);
const [selectedValue, setSelectedValue] = useState<IOption[]>([]);
const { data, isFetching } = useQuery(
[QueryBuilderKeys.GET_AGGREGATE_KEYS, searchText],
@ -55,23 +58,41 @@ export function OrderByFilter({
.flat()
.concat([
{
label: `${query.aggregateOperator}(${query.aggregateAttribute.key}) asc`,
value: `${query.aggregateOperator}(${query.aggregateAttribute.key})${orderByValueDelimiter}asc`,
label: `${query.aggregateOperator}(${query.aggregateAttribute.key}) ${FILTERS.ASC}`,
value: `${query.aggregateOperator}(${query.aggregateAttribute.key})${orderByValueDelimiter}${FILTERS.ASC}`,
},
{
label: `${query.aggregateOperator}(${query.aggregateAttribute.key}) desc`,
value: `${query.aggregateOperator}(${query.aggregateAttribute.key})${orderByValueDelimiter}desc`,
label: `${query.aggregateOperator}(${query.aggregateAttribute.key}) ${FILTERS.DESC}`,
value: `${query.aggregateOperator}(${query.aggregateAttribute.key})${orderByValueDelimiter}${FILTERS.DESC}`,
},
]),
[query.aggregateAttribute.key, query.aggregateOperator, query.groupBy],
);
const customValue: IOption[] = useMemo(() => {
if (!searchText) return [];
return [
{
label: `${searchText} ${FILTERS.ASC}`,
value: `${searchText}${orderByValueDelimiter}${FILTERS.ASC}`,
},
{
label: `${searchText} ${FILTERS.DESC}`,
value: `${searchText}${orderByValueDelimiter}${FILTERS.DESC}`,
},
];
}, [searchText]);
const optionsData = useMemo(() => {
const options =
query.aggregateOperator === MetricAggregateOperator.NOOP
? noAggregationOptions
: aggregationOptions;
return options.filter(
const resultOption = [...customValue, ...options];
return resultOption.filter(
(option) =>
!getLabelFromValue(selectedValue).includes(
getRemoveOrderFromValue(option.value),
@ -79,30 +100,58 @@ export function OrderByFilter({
);
}, [
aggregationOptions,
customValue,
noAggregationOptions,
query.aggregateOperator,
selectedValue,
]);
const handleChange = (values: string[]): void => {
setSelectedValue(values);
const orderByValues: OrderByPayload[] = values.map((item) => {
const match = Papa.parse(item, { delimiter: '|' });
const getUniqValues = useCallback((values: IOption[]): IOption[] => {
const modifiedValues = values.map((item) => {
const match = Papa.parse(item.value, { delimiter: orderByValueDelimiter });
if (!match) return { label: item.label, value: item.value };
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
const [_, order] = match.data.flat() as string[];
if (order) return { label: item.label, value: item.value };
return {
label: `${item.value} ${FILTERS.ASC}`,
value: `${item.value}${orderByValueDelimiter}${FILTERS.ASC}`,
};
});
return uniqWith(
modifiedValues,
(current, next) =>
getRemoveOrderFromValue(current.value) ===
getRemoveOrderFromValue(next.value),
);
}, []);
const handleChange = (values: IOption[]): void => {
const result = getUniqValues(values);
setSelectedValue(result);
const orderByValues: OrderByPayload[] = result.map((item) => {
const match = Papa.parse(item.value, { delimiter: orderByValueDelimiter });
if (match) {
const [columnName, order] = match.data.flat() as string[];
return {
columnName: checkIfKeyPresent(columnName, query.aggregateAttribute.key)
? '#SIGNOZ_VALUE'
: columnName,
order,
order: order ?? 'asc',
};
}
return {
columnName: item,
order: '',
columnName: item.value,
order: 'asc',
};
});
setSearchText('');
onChange(orderByValues);
};
@ -126,6 +175,8 @@ export function OrderByFilter({
showSearch
disabled={isMetricsDataSource && isDisabledSelect}
showArrow={false}
value={selectedValue}
labelInValue
filterOption={false}
options={optionsData}
notFoundContent={isFetching ? <Spin size="small" /> : null}

View File

@ -0,0 +1,4 @@
export const FILTERS = {
ASC: 'asc',
DESC: 'desc',
};

View File

@ -2,9 +2,18 @@ import { IOption } from 'hooks/useResourceAttribute/types';
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
import * as Papa from 'papaparse';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { OrderByPayload } from 'types/api/queryBuilder/queryBuilderData';
export const orderByValueDelimiter = '|';
export const transformToOrderByStringValues = (
orderBy: OrderByPayload[],
): IOption[] =>
orderBy.map((item) => ({
label: `${item.columnName} ${item.order}`,
value: `${item.columnName}${orderByValueDelimiter}${item.order}`,
}));
export function mapLabelValuePairs(
arr: BaseAutocompleteData[],
): Array<IOption>[] {
@ -28,14 +37,15 @@ export function mapLabelValuePairs(
});
}
export function getLabelFromValue(arr: string[]): string[] {
export function getLabelFromValue(arr: IOption[]): string[] {
return arr.flat().map((item) => {
const match = Papa.parse(item, { delimiter: orderByValueDelimiter });
const match = Papa.parse(item.value, { delimiter: orderByValueDelimiter });
if (match) {
const [key] = match.data as string[];
return key[0];
}
return item;
return item.value;
});
}