mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-13 13:39:01 +08:00
fix: having filter removing payload (#2706)
This commit is contained in:
parent
679eb39256
commit
18fc1a2761
@ -6,7 +6,11 @@ import createQueryParams from 'lib/createQueryParams';
|
|||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||||
// ** Types
|
// ** Types
|
||||||
import { IGetAggregateAttributePayload } from 'types/api/queryBuilder/getAggregatorAttribute';
|
import { IGetAggregateAttributePayload } from 'types/api/queryBuilder/getAggregatorAttribute';
|
||||||
import { IQueryAutocompleteResponse } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import {
|
||||||
|
BaseAutocompleteData,
|
||||||
|
IQueryAutocompleteResponse,
|
||||||
|
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
export const getAggregateAttribute = async ({
|
export const getAggregateAttribute = async ({
|
||||||
aggregateOperator,
|
aggregateOperator,
|
||||||
@ -26,11 +30,15 @@ export const getAggregateAttribute = async ({
|
|||||||
})}`,
|
})}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const payload: BaseAutocompleteData[] =
|
||||||
|
response.data.data.attributeKeys?.map((item) => ({ ...item, id: uuid() })) ||
|
||||||
|
[];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: response.statusText,
|
message: response.statusText,
|
||||||
payload: response.data.data,
|
payload: { attributeKeys: payload },
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ErrorResponseHandler(e as AxiosError);
|
return ErrorResponseHandler(e as AxiosError);
|
||||||
|
@ -5,7 +5,11 @@ import createQueryParams from 'lib/createQueryParams';
|
|||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||||
// ** Types
|
// ** Types
|
||||||
import { IGetAttributeKeysPayload } from 'types/api/queryBuilder/getAttributeKeys';
|
import { IGetAttributeKeysPayload } from 'types/api/queryBuilder/getAttributeKeys';
|
||||||
import { IQueryAutocompleteResponse } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import {
|
||||||
|
BaseAutocompleteData,
|
||||||
|
IQueryAutocompleteResponse,
|
||||||
|
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
export const getAggregateKeys = async ({
|
export const getAggregateKeys = async ({
|
||||||
aggregateOperator,
|
aggregateOperator,
|
||||||
@ -28,11 +32,15 @@ export const getAggregateKeys = async ({
|
|||||||
})}&tagType=${tagType}`,
|
})}&tagType=${tagType}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const payload: BaseAutocompleteData[] =
|
||||||
|
response.data.data.attributeKeys?.map((item) => ({ ...item, id: uuid() })) ||
|
||||||
|
[];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
error: null,
|
error: null,
|
||||||
message: response.statusText,
|
message: response.statusText,
|
||||||
payload: response.data.data,
|
payload: { attributeKeys: payload },
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ErrorResponseHandler(e as AxiosError);
|
return ErrorResponseHandler(e as AxiosError);
|
||||||
|
@ -10,20 +10,27 @@ import {
|
|||||||
import {
|
import {
|
||||||
BoolOperators,
|
BoolOperators,
|
||||||
DataSource,
|
DataSource,
|
||||||
LogsAggregatorOperator,
|
|
||||||
MetricAggregateOperator,
|
MetricAggregateOperator,
|
||||||
NumberOperators,
|
NumberOperators,
|
||||||
PanelTypeKeys,
|
PanelTypeKeys,
|
||||||
QueryAdditionalFilter,
|
QueryAdditionalFilter,
|
||||||
ReduceOperators,
|
ReduceOperators,
|
||||||
StringOperators,
|
StringOperators,
|
||||||
TracesAggregatorOperator,
|
|
||||||
} from 'types/common/queryBuilder';
|
} from 'types/common/queryBuilder';
|
||||||
import { SelectOption } from 'types/common/select';
|
import { SelectOption } from 'types/common/select';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
import {
|
||||||
|
logsAggregateOperatorOptions,
|
||||||
|
metricAggregateOperatorOptions,
|
||||||
|
tracesAggregateOperatorOptions,
|
||||||
|
} from './queryBuilderOperators';
|
||||||
|
|
||||||
export const MAX_FORMULAS = 20;
|
export const MAX_FORMULAS = 20;
|
||||||
export const MAX_QUERIES = 26;
|
export const MAX_QUERIES = 26;
|
||||||
|
|
||||||
|
export const selectValueDivider = '--';
|
||||||
|
|
||||||
export const formulasNames: string[] = Array.from(
|
export const formulasNames: string[] = Array.from(
|
||||||
Array(MAX_FORMULAS),
|
Array(MAX_FORMULAS),
|
||||||
(_, i) => `F${i + 1}`,
|
(_, i) => `F${i + 1}`,
|
||||||
@ -37,10 +44,10 @@ export enum QueryBuilderKeys {
|
|||||||
GET_ATTRIBUTE_KEY = 'GET_ATTRIBUTE_KEY',
|
GET_ATTRIBUTE_KEY = 'GET_ATTRIBUTE_KEY',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mapOfOperators: Record<DataSource, string[]> = {
|
export const mapOfOperators = {
|
||||||
metrics: Object.values(MetricAggregateOperator),
|
metrics: metricAggregateOperatorOptions,
|
||||||
logs: Object.values(LogsAggregatorOperator),
|
logs: logsAggregateOperatorOptions,
|
||||||
traces: Object.values(TracesAggregatorOperator),
|
traces: tracesAggregateOperatorOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mapOfFilters: Record<DataSource, QueryAdditionalFilter[]> = {
|
export const mapOfFilters: Record<DataSource, QueryAdditionalFilter[]> = {
|
||||||
@ -78,6 +85,7 @@ export const initialHavingValues: HavingForm = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const initialAggregateAttribute: IBuilderQuery['aggregateAttribute'] = {
|
export const initialAggregateAttribute: IBuilderQuery['aggregateAttribute'] = {
|
||||||
|
id: uuid(),
|
||||||
dataType: null,
|
dataType: null,
|
||||||
key: '',
|
key: '',
|
||||||
isColumn: null,
|
isColumn: null,
|
||||||
|
304
frontend/src/constants/queryBuilderOperators.ts
Normal file
304
frontend/src/constants/queryBuilderOperators.ts
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
import {
|
||||||
|
LogsAggregatorOperator,
|
||||||
|
MetricAggregateOperator,
|
||||||
|
TracesAggregatorOperator,
|
||||||
|
} from 'types/common/queryBuilder';
|
||||||
|
import { SelectOption } from 'types/common/select';
|
||||||
|
|
||||||
|
export const metricAggregateOperatorOptions: SelectOption<string, string>[] = [
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.NOOP,
|
||||||
|
label: 'NOOP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.COUNT,
|
||||||
|
label: 'Count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.COUNT_DISTINCT,
|
||||||
|
// eslint-disable-next-line sonarjs/no-duplicate-string
|
||||||
|
label: 'Count Distinct',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.SUM,
|
||||||
|
label: 'Sum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.AVG,
|
||||||
|
label: 'Avg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.MAX,
|
||||||
|
label: 'Max',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.MIN,
|
||||||
|
label: 'Min',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P05,
|
||||||
|
label: 'P05',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P10,
|
||||||
|
label: 'P10',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P20,
|
||||||
|
label: 'P20',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P25,
|
||||||
|
label: 'P25',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P50,
|
||||||
|
label: 'P50',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P75,
|
||||||
|
label: 'P75',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P90,
|
||||||
|
label: 'P90',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P95,
|
||||||
|
label: 'P95',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.P99,
|
||||||
|
label: 'P99',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.RATE,
|
||||||
|
label: 'Rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.SUM_RATE,
|
||||||
|
label: 'Sum_rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.AVG_RATE,
|
||||||
|
label: 'Avg_rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.MAX_RATE,
|
||||||
|
label: 'Max_rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.MIN_RATE,
|
||||||
|
label: 'Min_rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.RATE_SUM,
|
||||||
|
label: 'Rate_sum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.RATE_AVG,
|
||||||
|
label: 'Rate_avg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.RATE_MIN,
|
||||||
|
label: 'Rate_min',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.RATE_MAX,
|
||||||
|
label: 'Rate_max',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.HIST_QUANTILE_50,
|
||||||
|
label: 'Hist_quantile_50',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.HIST_QUANTILE_75,
|
||||||
|
label: 'Hist_quantile_75',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.HIST_QUANTILE_90,
|
||||||
|
label: 'Hist_quantile_90',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.HIST_QUANTILE_95,
|
||||||
|
label: 'Hist_quantile_95',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MetricAggregateOperator.HIST_QUANTILE_99,
|
||||||
|
label: 'Hist_quantile_99',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const tracesAggregateOperatorOptions: SelectOption<string, string>[] = [
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.NOOP,
|
||||||
|
label: 'NOOP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.COUNT,
|
||||||
|
label: 'Count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.COUNT_DISTINCT,
|
||||||
|
label: 'Count Distinct',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.SUM,
|
||||||
|
label: 'Sum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.AVG,
|
||||||
|
label: 'Avg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.MAX,
|
||||||
|
label: 'Max',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.MIN,
|
||||||
|
label: 'Min',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P05,
|
||||||
|
label: 'P05',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P10,
|
||||||
|
label: 'P10',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P20,
|
||||||
|
label: 'P20',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P25,
|
||||||
|
label: 'P25',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P50,
|
||||||
|
label: 'P50',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P75,
|
||||||
|
label: 'P75',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P90,
|
||||||
|
label: 'P90',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P95,
|
||||||
|
label: 'P95',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.P99,
|
||||||
|
label: 'P99',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.RATE,
|
||||||
|
label: 'Rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.RATE_SUM,
|
||||||
|
label: 'Rate_sum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.RATE_AVG,
|
||||||
|
label: 'Rate_avg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.RATE_MIN,
|
||||||
|
label: 'Rate_min',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TracesAggregatorOperator.RATE_MAX,
|
||||||
|
label: 'Rate_max',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const logsAggregateOperatorOptions: SelectOption<string, string>[] = [
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.NOOP,
|
||||||
|
label: 'NOOP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.COUNT,
|
||||||
|
label: 'Count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.COUNT_DISTINCT,
|
||||||
|
label: 'Count Distinct',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.SUM,
|
||||||
|
label: 'Sum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.AVG,
|
||||||
|
label: 'Avg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.MAX,
|
||||||
|
label: 'Max',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.MIN,
|
||||||
|
label: 'Min',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P05,
|
||||||
|
label: 'P05',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P10,
|
||||||
|
label: 'P10',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P20,
|
||||||
|
label: 'P20',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P25,
|
||||||
|
label: 'P25',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P50,
|
||||||
|
label: 'P50',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P75,
|
||||||
|
label: 'P75',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P90,
|
||||||
|
label: 'P90',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P95,
|
||||||
|
label: 'P95',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.P99,
|
||||||
|
label: 'P99',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.RATE,
|
||||||
|
label: 'Rate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.RATE_SUM,
|
||||||
|
label: 'Rate_sum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.RATE_AVG,
|
||||||
|
label: 'Rate_avg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.RATE_MIN,
|
||||||
|
label: 'Rate_min',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: LogsAggregatorOperator.RATE_MAX,
|
||||||
|
label: 'Rate_max',
|
||||||
|
},
|
||||||
|
];
|
@ -2,14 +2,19 @@
|
|||||||
import { AutoComplete, Spin } from 'antd';
|
import { AutoComplete, Spin } from 'antd';
|
||||||
// ** Api
|
// ** Api
|
||||||
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
|
import { getAggregateAttribute } from 'api/queryBuilder/getAggregateAttribute';
|
||||||
import { initialAggregateAttribute } from 'constants/queryBuilder';
|
import {
|
||||||
|
initialAggregateAttribute,
|
||||||
|
QueryBuilderKeys,
|
||||||
|
selectValueDivider,
|
||||||
|
} from 'constants/queryBuilder';
|
||||||
import { getFilterObjectValue } from 'lib/newQueryBuilder/getFilterObjectValue';
|
import { getFilterObjectValue } from 'lib/newQueryBuilder/getFilterObjectValue';
|
||||||
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
||||||
import React, { memo, useMemo, useState } from 'react';
|
import React, { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
import { ExtendedSelectOption } from 'types/common/select';
|
import { ExtendedSelectOption } from 'types/common/select';
|
||||||
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import { selectStyle } from '../QueryBuilderSearch/config';
|
import { selectStyle } from '../QueryBuilderSearch/config';
|
||||||
// ** Types
|
// ** Types
|
||||||
@ -19,57 +24,60 @@ export const AggregatorFilter = memo(function AggregatorFilter({
|
|||||||
onChange,
|
onChange,
|
||||||
query,
|
query,
|
||||||
}: AgregatorFilterProps): JSX.Element {
|
}: AgregatorFilterProps): JSX.Element {
|
||||||
const [searchText, setSearchText] = useState<string>('');
|
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
|
||||||
|
|
||||||
const { data, isFetching } = useQuery(
|
const { data, isFetching } = useQuery(
|
||||||
[
|
[
|
||||||
'GET_AGGREGATE_ATTRIBUTE',
|
QueryBuilderKeys.GET_AGGREGATE_ATTRIBUTE,
|
||||||
searchText,
|
query.aggregateAttribute.key,
|
||||||
query.aggregateOperator,
|
query.aggregateOperator,
|
||||||
query.dataSource,
|
query.dataSource,
|
||||||
],
|
],
|
||||||
async () =>
|
async () =>
|
||||||
getAggregateAttribute({
|
getAggregateAttribute({
|
||||||
searchText,
|
searchText: query.aggregateAttribute.key,
|
||||||
aggregateOperator: query.aggregateOperator,
|
aggregateOperator: query.aggregateOperator,
|
||||||
dataSource: query.dataSource,
|
dataSource: query.dataSource,
|
||||||
}),
|
}),
|
||||||
{ enabled: !!query.aggregateOperator && !!query.dataSource },
|
{
|
||||||
|
enabled: !!query.aggregateOperator && !!query.dataSource,
|
||||||
|
onSuccess: (data) => {
|
||||||
|
const options: ExtendedSelectOption[] =
|
||||||
|
data?.payload?.attributeKeys?.map((item) => ({
|
||||||
|
label: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
|
value: `${transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
})}${selectValueDivider}${item.id || uuid()}`,
|
||||||
|
key: item.id || uuid(),
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
setOptionsData(options);
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSearchAttribute = (searchText: string): void => {
|
const handleChangeAttribute = useCallback(
|
||||||
const { key } = getFilterObjectValue(searchText);
|
(
|
||||||
setSearchText(key);
|
value: string,
|
||||||
};
|
option: ExtendedSelectOption | ExtendedSelectOption[],
|
||||||
|
): void => {
|
||||||
|
const currentOption = option as ExtendedSelectOption;
|
||||||
|
|
||||||
const optionsData: ExtendedSelectOption[] =
|
const { key } = getFilterObjectValue(value);
|
||||||
data?.payload?.attributeKeys?.map((item) => ({
|
|
||||||
label: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
value: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
key: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
})) || [];
|
|
||||||
|
|
||||||
const handleChangeAttribute = (value: string): void => {
|
const currentAttributeObj = data?.payload?.attributeKeys?.find(
|
||||||
const { key, isColumn } = getFilterObjectValue(value);
|
(item) => currentOption.key === item.id,
|
||||||
const currentAttributeObj = data?.payload?.attributeKeys?.find(
|
) || { ...initialAggregateAttribute, key };
|
||||||
(item) => item.key === key && isColumn === item.isColumn,
|
|
||||||
) || { ...initialAggregateAttribute, key };
|
|
||||||
|
|
||||||
setSearchText('');
|
onChange(currentAttributeObj);
|
||||||
onChange(currentAttributeObj);
|
},
|
||||||
};
|
[data, onChange],
|
||||||
|
);
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -88,12 +96,10 @@ export const AggregatorFilter = memo(function AggregatorFilter({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoComplete
|
<AutoComplete
|
||||||
showSearch
|
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
style={selectStyle}
|
style={selectStyle}
|
||||||
showArrow={false}
|
showArrow={false}
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
onSearch={handleSearchAttribute}
|
|
||||||
notFoundContent={isFetching ? <Spin size="small" /> : null}
|
notFoundContent={isFetching ? <Spin size="small" /> : null}
|
||||||
options={optionsData}
|
options={optionsData}
|
||||||
value={value}
|
value={value}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import { Select, Spin } from 'antd';
|
import { Select, Spin } from 'antd';
|
||||||
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
|
import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys';
|
||||||
// ** Constants
|
// ** Constants
|
||||||
import { QueryBuilderKeys } from 'constants/queryBuilder';
|
import { QueryBuilderKeys, selectValueDivider } from 'constants/queryBuilder';
|
||||||
import { getFilterObjectValue } from 'lib/newQueryBuilder/getFilterObjectValue';
|
import { getFilterObjectValue } from 'lib/newQueryBuilder/getFilterObjectValue';
|
||||||
// ** Components
|
// ** Components
|
||||||
// ** Helpers
|
// ** Helpers
|
||||||
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
|
||||||
import React, { memo, useMemo, useState } from 'react';
|
import React, { memo, useState } from 'react';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
import { ExtendedSelectOption } from 'types/common/select';
|
import { ExtendedSelectOption } from 'types/common/select';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import { selectStyle } from '../QueryBuilderSearch/config';
|
import { selectStyle } from '../QueryBuilderSearch/config';
|
||||||
import { GroupByFilterProps } from './GroupByFilter.interfaces';
|
import { GroupByFilterProps } from './GroupByFilter.interfaces';
|
||||||
@ -20,6 +21,7 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
disabled,
|
disabled,
|
||||||
}: GroupByFilterProps): JSX.Element {
|
}: GroupByFilterProps): JSX.Element {
|
||||||
const [searchText, setSearchText] = useState<string>('');
|
const [searchText, setSearchText] = useState<string>('');
|
||||||
|
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
|
||||||
const [isFocused, setIsFocused] = useState<boolean>(false);
|
const [isFocused, setIsFocused] = useState<boolean>(false);
|
||||||
|
|
||||||
const { data, isFetching } = useQuery(
|
const { data, isFetching } = useQuery(
|
||||||
@ -31,7 +33,38 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
aggregateOperator: query.aggregateOperator,
|
aggregateOperator: query.aggregateOperator,
|
||||||
searchText,
|
searchText,
|
||||||
}),
|
}),
|
||||||
{ enabled: !disabled && isFocused, keepPreviousData: true },
|
{
|
||||||
|
enabled: !disabled && isFocused,
|
||||||
|
onSuccess: (data) => {
|
||||||
|
const keys = query.groupBy.reduce<string[]>((acc, item) => {
|
||||||
|
acc.push(item.key);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const filteredOptions: BaseAutocompleteData[] =
|
||||||
|
data?.payload?.attributeKeys?.filter(
|
||||||
|
(attrKey) => !keys.includes(attrKey.key),
|
||||||
|
) || [];
|
||||||
|
|
||||||
|
const options: ExtendedSelectOption[] =
|
||||||
|
filteredOptions.map((item) => ({
|
||||||
|
label: transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
}),
|
||||||
|
value: `${transformStringWithPrefix({
|
||||||
|
str: item.key,
|
||||||
|
prefix: item.type || '',
|
||||||
|
condition: !item.isColumn,
|
||||||
|
})}${selectValueDivider}${item.id || uuid()}`,
|
||||||
|
key: item.id || uuid(),
|
||||||
|
title: item.key,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
setOptionsData(options);
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSearchKeys = (searchText: string): void => {
|
const handleSearchKeys = (searchText: string): void => {
|
||||||
@ -46,51 +79,27 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
setIsFocused(true);
|
setIsFocused(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const optionsData: ExtendedSelectOption[] = useMemo(() => {
|
|
||||||
if (data && data.payload && data.payload.attributeKeys) {
|
|
||||||
return data.payload.attributeKeys.map((item) => ({
|
|
||||||
label: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
value: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
key: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
const handleChange = (values: ExtendedSelectOption[]): void => {
|
const handleChange = (values: ExtendedSelectOption[]): void => {
|
||||||
const groupByValues: BaseAutocompleteData[] = values.map((item) => {
|
const groupByValues: BaseAutocompleteData[] = values.map((item) => {
|
||||||
const responseKeys = data?.payload?.attributeKeys || [];
|
const responseKeys = data?.payload?.attributeKeys || [];
|
||||||
const { key, isColumn } = getFilterObjectValue(item.value);
|
const { key } = getFilterObjectValue(item.value);
|
||||||
|
|
||||||
const existGroupResponse = responseKeys.find(
|
const existGroupResponse = responseKeys.find(
|
||||||
(group) => group.key === key && group.isColumn === isColumn,
|
(group) => group.id === item.key,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existGroupResponse) {
|
if (existGroupResponse) {
|
||||||
return existGroupResponse;
|
return existGroupResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const existGroupQuery = query.groupBy.find(
|
const existGroupQuery = query.groupBy.find((group) => group.id === item.key);
|
||||||
(group) => group.key === key && group.isColumn === isColumn,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existGroupQuery) {
|
if (existGroupQuery) {
|
||||||
return existGroupQuery;
|
return existGroupQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
id: uuid(),
|
||||||
isColumn: null,
|
isColumn: null,
|
||||||
key,
|
key,
|
||||||
dataType: null,
|
dataType: null,
|
||||||
@ -98,7 +107,6 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
setSearchText('');
|
|
||||||
onChange(groupByValues);
|
onChange(groupByValues);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,16 +116,12 @@ export const GroupByFilter = memo(function GroupByFilter({
|
|||||||
prefix: item.type || '',
|
prefix: item.type || '',
|
||||||
condition: !item.isColumn,
|
condition: !item.isColumn,
|
||||||
}),
|
}),
|
||||||
key: transformStringWithPrefix({
|
key: item.id || uuid(),
|
||||||
|
value: `${transformStringWithPrefix({
|
||||||
str: item.key,
|
str: item.key,
|
||||||
prefix: item.type || '',
|
prefix: item.type || '',
|
||||||
condition: !item.isColumn,
|
condition: !item.isColumn,
|
||||||
}),
|
})}${selectValueDivider}${item.id || uuid()}`,
|
||||||
value: transformStringWithPrefix({
|
|
||||||
str: item.key,
|
|
||||||
prefix: item.type || '',
|
|
||||||
condition: !item.isColumn,
|
|
||||||
}),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -204,7 +204,9 @@ export function HavingFilter({
|
|||||||
|
|
||||||
const handleDeselect = (value: string): void => {
|
const handleDeselect = (value: string): void => {
|
||||||
const result = localValues.filter((item) => item !== value);
|
const result = localValues.filter((item) => item !== value);
|
||||||
setLocalValues(result);
|
const having: Having[] = result.map(transformFromStringToHaving);
|
||||||
|
onChange(having);
|
||||||
|
resetChanges();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { SelectProps } from 'antd';
|
import { SelectProps } from 'antd';
|
||||||
|
import { SelectOption } from 'types/common/select';
|
||||||
|
|
||||||
export type OperatorsSelectProps = Omit<SelectProps, 'onChange' | 'value'> & {
|
export type OperatorsSelectProps = Omit<SelectProps, 'onChange' | 'value'> & {
|
||||||
operators: string[];
|
operators: SelectOption<string, string>[];
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { Select } from 'antd';
|
import { Select } from 'antd';
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
// ** Types
|
|
||||||
import { SelectOption } from 'types/common/select';
|
|
||||||
// ** Helpers
|
|
||||||
import { transformToUpperCase } from 'utils/transformToUpperCase';
|
|
||||||
|
|
||||||
|
// ** Types
|
||||||
import { selectStyle } from '../QueryBuilderSearch/config';
|
import { selectStyle } from '../QueryBuilderSearch/config';
|
||||||
import { OperatorsSelectProps } from './OperatorsSelect.interfaces';
|
import { OperatorsSelectProps } from './OperatorsSelect.interfaces';
|
||||||
|
|
||||||
@ -14,16 +11,9 @@ export const OperatorsSelect = memo(function OperatorsSelect({
|
|||||||
onChange,
|
onChange,
|
||||||
...props
|
...props
|
||||||
}: OperatorsSelectProps): JSX.Element {
|
}: OperatorsSelectProps): JSX.Element {
|
||||||
const operatorsOptions: SelectOption<string, string>[] = operators.map(
|
|
||||||
(operator) => ({
|
|
||||||
label: transformToUpperCase(operator),
|
|
||||||
value: operator,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
options={operatorsOptions}
|
options={operators}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
style={selectStyle}
|
style={selectStyle}
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
UseQueryOperations,
|
UseQueryOperations,
|
||||||
} from 'types/common/operations.types';
|
} from 'types/common/operations.types';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
import { SelectOption } from 'types/common/select';
|
||||||
|
|
||||||
export const useQueryOperations: UseQueryOperations = ({ query, index }) => {
|
export const useQueryOperations: UseQueryOperations = ({ query, index }) => {
|
||||||
const {
|
const {
|
||||||
@ -21,7 +22,7 @@ export const useQueryOperations: UseQueryOperations = ({ query, index }) => {
|
|||||||
removeEntityByIndex,
|
removeEntityByIndex,
|
||||||
panelType,
|
panelType,
|
||||||
} = useQueryBuilder();
|
} = useQueryBuilder();
|
||||||
const [operators, setOperators] = useState<string[]>([]);
|
const [operators, setOperators] = useState<SelectOption<string, string>[]>([]);
|
||||||
const [listOfAdditionalFilters, setListOfAdditionalFilters] = useState<
|
const [listOfAdditionalFilters, setListOfAdditionalFilters] = useState<
|
||||||
string[]
|
string[]
|
||||||
>([]);
|
>([]);
|
||||||
@ -90,7 +91,7 @@ export const useQueryOperations: UseQueryOperations = ({ query, index }) => {
|
|||||||
...query,
|
...query,
|
||||||
...initCopyResult,
|
...initCopyResult,
|
||||||
dataSource: nextSource,
|
dataSource: nextSource,
|
||||||
aggregateOperator: newOperators[0],
|
aggregateOperator: newOperators[0].value,
|
||||||
};
|
};
|
||||||
|
|
||||||
setOperators(newOperators);
|
setOperators(newOperators);
|
||||||
|
@ -4,28 +4,30 @@ import {
|
|||||||
BaseAutocompleteData,
|
BaseAutocompleteData,
|
||||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||||
|
|
||||||
const isTypeExist = (str: string): boolean => {
|
const getType = (str: string): AutocompleteType | null => {
|
||||||
const types: AutocompleteType[] = ['tag', 'resource'];
|
const types: AutocompleteType[] = ['tag', 'resource'];
|
||||||
let isExist = false;
|
|
||||||
|
let currentType: AutocompleteType | null = null;
|
||||||
|
|
||||||
types.forEach((type) => {
|
types.forEach((type) => {
|
||||||
if (str.includes(type)) {
|
if (str.includes(type)) {
|
||||||
isExist = true;
|
currentType = type;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return isExist;
|
return currentType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFilterObjectValue = (
|
export const getFilterObjectValue = (
|
||||||
value: string,
|
value: string,
|
||||||
): Omit<BaseAutocompleteData, 'dataType' | 'type'> => {
|
): Omit<BaseAutocompleteData, 'dataType' | 'id'> => {
|
||||||
const isExist = isTypeExist(value);
|
const type = getType(value);
|
||||||
|
|
||||||
if (!isExist) {
|
if (!type) {
|
||||||
return { isColumn: true, key: value };
|
return { isColumn: true, key: value, type: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
const splittedValue = value.split(TYPE_ADDON_REGEXP);
|
const splittedValue = value.split(TYPE_ADDON_REGEXP);
|
||||||
|
|
||||||
return { isColumn: false, key: splittedValue[1] };
|
return { isColumn: false, key: splittedValue[1], type };
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { mapOfOperators, PANEL_TYPES } from 'constants/queryBuilder';
|
import { mapOfOperators, PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
|
||||||
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
import { DataSource, StringOperators } from 'types/common/queryBuilder';
|
||||||
|
import { SelectOption } from 'types/common/select';
|
||||||
|
|
||||||
type GetQueryOperatorsParams = {
|
type GetQueryOperatorsParams = {
|
||||||
dataSource: DataSource;
|
dataSource: DataSource;
|
||||||
@ -11,12 +12,12 @@ type GetQueryOperatorsParams = {
|
|||||||
export const getOperatorsBySourceAndPanelType = ({
|
export const getOperatorsBySourceAndPanelType = ({
|
||||||
dataSource,
|
dataSource,
|
||||||
panelType,
|
panelType,
|
||||||
}: GetQueryOperatorsParams): string[] => {
|
}: GetQueryOperatorsParams): SelectOption<string, string>[] => {
|
||||||
let operatorsByDataSource = mapOfOperators[dataSource];
|
let operatorsByDataSource = mapOfOperators[dataSource];
|
||||||
|
|
||||||
if (dataSource !== DataSource.METRICS && panelType !== PANEL_TYPES.LIST) {
|
if (dataSource !== DataSource.METRICS && panelType !== PANEL_TYPES.LIST) {
|
||||||
operatorsByDataSource = operatorsByDataSource.filter(
|
operatorsByDataSource = operatorsByDataSource.filter(
|
||||||
(operator) => operator !== StringOperators.NOOP,
|
(operator) => operator.value !== StringOperators.NOOP,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ export function QueryBuilderProvider({
|
|||||||
aggregateOperator: getOperatorsBySourceAndPanelType({
|
aggregateOperator: getOperatorsBySourceAndPanelType({
|
||||||
dataSource: initialDataSource,
|
dataSource: initialDataSource,
|
||||||
panelType,
|
panelType,
|
||||||
})[0],
|
})[0].value,
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ export type DataType = 'int64' | 'float64' | 'string' | 'bool';
|
|||||||
export type AutocompleteType = 'tag' | 'resource';
|
export type AutocompleteType = 'tag' | 'resource';
|
||||||
|
|
||||||
export interface BaseAutocompleteData {
|
export interface BaseAutocompleteData {
|
||||||
|
id?: string;
|
||||||
dataType: DataType | null;
|
dataType: DataType | null;
|
||||||
isColumn: boolean | null;
|
isColumn: boolean | null;
|
||||||
key: string;
|
key: string;
|
||||||
@ -12,5 +13,5 @@ export interface BaseAutocompleteData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IQueryAutocompleteResponse {
|
export interface IQueryAutocompleteResponse {
|
||||||
attributeKeys: BaseAutocompleteData[];
|
attributeKeys: BaseAutocompleteData[] | null;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteRe
|
|||||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||||
import { DataSource } from 'types/common/queryBuilder';
|
import { DataSource } from 'types/common/queryBuilder';
|
||||||
|
|
||||||
|
import { SelectOption } from './select';
|
||||||
|
|
||||||
type UseQueryOperationsParams = Pick<QueryProps, 'index' | 'query'>;
|
type UseQueryOperationsParams = Pick<QueryProps, 'index' | 'query'>;
|
||||||
|
|
||||||
export type HandleChangeQueryData = <
|
export type HandleChangeQueryData = <
|
||||||
@ -17,7 +19,7 @@ export type UseQueryOperations = (
|
|||||||
params: UseQueryOperationsParams,
|
params: UseQueryOperationsParams,
|
||||||
) => {
|
) => {
|
||||||
isMetricsDataSource: boolean;
|
isMetricsDataSource: boolean;
|
||||||
operators: string[];
|
operators: SelectOption<string, string>[];
|
||||||
listOfAdditionalFilters: string[];
|
listOfAdditionalFilters: string[];
|
||||||
handleChangeOperator: (value: string) => void;
|
handleChangeOperator: (value: string) => void;
|
||||||
handleChangeAggregatorAttribute: (value: BaseAutocompleteData) => void;
|
handleChangeAggregatorAttribute: (value: BaseAutocompleteData) => void;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user