From dd25ad95c77df8089aeaa9025dafc54b30eea3a0 Mon Sep 17 00:00:00 2001 From: Yevhen Shevchenko <90138953+yeshev@users.noreply.github.com> Date: Wed, 19 Apr 2023 07:25:18 +0300 Subject: [PATCH] feat(builder): add having filter (#2567) * feat(builder): add having filter * feat(builder): add having filter * feat(builder): add having filter * feat: return initial query builder * fix: having filter operators and values --- frontend/src/constants/queryBuilder.ts | 55 ++++- .../container/QueryBuilder/QueryBuilder.tsx | 14 +- .../AdditionalFiltersToggler.styled.ts | 10 +- .../AdditionalFiltersToggler.tsx | 17 +- .../FilterLabel/FilterLabel.styled.ts | 2 +- .../components/Formula/Formula.interfaces.ts | 5 +- .../components/Formula/Formula.tsx | 74 ++++++- .../ListItemWrapper.interfaces.ts | 3 + .../ListItemWrapper.styled.ts} | 2 +- .../ListItemWrapper/ListItemWrapper.tsx | 18 ++ .../components/ListItemWrapper/index.ts | 1 + .../ListMarker/ListMarker.interfaces.ts | 4 +- .../components/ListMarker/ListMarker.tsx | 6 +- .../QueryBuilder/components/Query/Query.tsx | 110 +++++++--- .../QueryBuilder/components/index.ts | 1 + .../HavingFilter/HavingFilter.interfaces.ts | 9 + .../filters/HavingFilter/HavingFilter.tsx | 196 ++++++++++++++++++ .../HavingFilter/__tests__/utils.test.tsx | 166 +++++++++++++++ .../filters/HavingFilter/index.ts | 1 + .../container/QueryBuilder/filters/index.ts | 1 + .../createNewBuilderItemName.ts | 17 ++ .../newQueryBuilder/createNewFormulaName.ts | 9 - .../lib/newQueryBuilder/createNewQueryName.ts | 14 -- .../lib/query/transformQueryBuilderData.ts | 22 ++ frontend/src/providers/QueryBuilder.tsx | 68 +++++- .../api/queryBuilder/queryBuilderData.ts | 8 +- frontend/src/types/common/queryBuilder.ts | 1 + 27 files changed, 727 insertions(+), 107 deletions(-) create mode 100644 frontend/src/container/QueryBuilder/components/ListItemWrapper/ListItemWrapper.interfaces.ts rename frontend/src/container/QueryBuilder/components/{Query/Query.styled.ts => ListItemWrapper/ListItemWrapper.styled.ts} (96%) create mode 100644 frontend/src/container/QueryBuilder/components/ListItemWrapper/ListItemWrapper.tsx create mode 100644 frontend/src/container/QueryBuilder/components/ListItemWrapper/index.ts create mode 100644 frontend/src/container/QueryBuilder/filters/HavingFilter/HavingFilter.interfaces.ts create mode 100644 frontend/src/container/QueryBuilder/filters/HavingFilter/HavingFilter.tsx create mode 100644 frontend/src/container/QueryBuilder/filters/HavingFilter/__tests__/utils.test.tsx create mode 100644 frontend/src/container/QueryBuilder/filters/HavingFilter/index.ts create mode 100644 frontend/src/lib/newQueryBuilder/createNewBuilderItemName.ts delete mode 100644 frontend/src/lib/newQueryBuilder/createNewFormulaName.ts delete mode 100644 frontend/src/lib/newQueryBuilder/createNewQueryName.ts create mode 100644 frontend/src/lib/query/transformQueryBuilderData.ts diff --git a/frontend/src/constants/queryBuilder.ts b/frontend/src/constants/queryBuilder.ts index 51fe841a4c..5c81778742 100644 --- a/frontend/src/constants/queryBuilder.ts +++ b/frontend/src/constants/queryBuilder.ts @@ -1,9 +1,11 @@ -// ** TODO: use it for creating formula names -// import { createNewFormulaName } from 'lib/newQueryBuilder/createNewFormulaName'; // ** Helpers -import { createNewQueryName } from 'lib/newQueryBuilder/createNewQueryName'; +import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName'; import { LocalDataType } from 'types/api/queryBuilder/queryAutocompleteResponse'; -import { IBuilderQueryForm } from 'types/api/queryBuilder/queryBuilderData'; +import { + Having, + IBuilderFormula, + IBuilderQueryForm, +} from 'types/api/queryBuilder/queryBuilderData'; import { BoolOperators, DataSource, @@ -14,6 +16,16 @@ import { TracesAggregatorOperator, } from 'types/common/queryBuilder'; +export const MAX_FORMULAS = 20; +export const MAX_QUERIES = 26; + +export const formulasNames: string[] = Array.from( + Array(MAX_FORMULAS), + (_, i) => `F${i + 1}`, +); +const alpha: number[] = Array.from(Array(MAX_QUERIES), (_, i) => i + 65); +export const alphabet: string[] = alpha.map((str) => String.fromCharCode(str)); + export enum QueryBuilderKeys { GET_AGGREGATE_ATTRIBUTE = 'GET_AGGREGATE_ATTRIBUTE', GET_AGGREGATE_KEYS = 'GET_AGGREGATE_KEYS', @@ -27,9 +39,15 @@ export const mapOfOperators: Record = { export const mapOfFilters: Record = { // eslint-disable-next-line sonarjs/no-duplicate-string - metrics: ['Having', 'Aggregation interval'], - logs: ['Limit', 'Having', 'Order by', 'Aggregation interval'], - traces: ['Limit', 'Having', 'Order by', 'Aggregation interval'], + metrics: ['Aggregation interval', 'Having'], + logs: ['Order by', 'Limit', 'Having', 'Aggregation interval'], + traces: ['Order by', 'Limit', 'Having', 'Aggregation interval'], +}; + +export const initialHavingValues: Having = { + columnName: '', + op: '', + value: [], }; export const initialAggregateAttribute: IBuilderQueryForm['aggregateAttribute'] = { @@ -41,7 +59,7 @@ export const initialAggregateAttribute: IBuilderQueryForm['aggregateAttribute'] export const initialQueryBuilderFormValues: IBuilderQueryForm = { dataSource: DataSource.METRICS, - queryName: createNewQueryName([]), + queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }), aggregateOperator: Object.values(MetricAggregateOperator)[0], aggregateAttribute: initialAggregateAttribute, tagFilters: { items: [], op: 'AND' }, @@ -56,6 +74,16 @@ export const initialQueryBuilderFormValues: IBuilderQueryForm = { reduceTo: '', }; +export const initialFormulaBuilderFormValues: IBuilderFormula = { + label: createNewBuilderItemName({ + existNames: [], + sourceNames: formulasNames, + }), + expression: '', + disabled: false, + legend: '', +}; + export const operatorsByTypes: Record = { string: Object.values(StringOperators), number: Object.values(NumberOperators), @@ -136,3 +164,14 @@ export const QUERY_BUILDER_OPERATORS_BY_TYPES = { OPERATORS.NOT_CONTAINS, ], }; + +export const HAVING_OPERATORS: string[] = [ + OPERATORS.EQUALS, + OPERATORS.NOT_EQUALS, + OPERATORS.IN, + OPERATORS.NIN, + OPERATORS.GTE, + OPERATORS.GT, + OPERATORS.LTE, + OPERATORS.LT, +]; diff --git a/frontend/src/container/QueryBuilder/QueryBuilder.tsx b/frontend/src/container/QueryBuilder/QueryBuilder.tsx index dd51a2061e..2bb16824c7 100644 --- a/frontend/src/container/QueryBuilder/QueryBuilder.tsx +++ b/frontend/src/container/QueryBuilder/QueryBuilder.tsx @@ -1,14 +1,13 @@ import { PlusOutlined } from '@ant-design/icons'; import { Button, Col, Row } from 'antd'; +import { MAX_FORMULAS, MAX_QUERIES } from 'constants/queryBuilder'; // ** Hooks import { useQueryBuilder } from 'hooks/useQueryBuilder'; -import { MAX_FORMULAS } from 'lib/newQueryBuilder/createNewFormulaName'; // ** Constants -import { MAX_QUERIES } from 'lib/newQueryBuilder/createNewQueryName'; import React, { memo, useEffect, useMemo } from 'react'; // ** Components -import { Query } from './components'; +import { Formula, Query } from './components'; // ** Types import { QueryBuilderProps } from './QueryBuilder.interfaces'; // ** Styles @@ -21,6 +20,7 @@ export const QueryBuilder = memo(function QueryBuilder({ queryBuilderData, setupInitialDataSource, addNewQuery, + addNewFormula, } = useQueryBuilder(); useEffect(() => { @@ -39,7 +39,7 @@ export const QueryBuilder = memo(function QueryBuilder({ ); const isDisabledFormulaButton = useMemo( - () => queryBuilderData.queryData.length >= MAX_FORMULAS, + () => queryBuilderData.queryFormulas.length >= MAX_FORMULAS, [queryBuilderData], ); @@ -58,6 +58,11 @@ export const QueryBuilder = memo(function QueryBuilder({ /> ))} + {queryBuilderData.queryFormulas.map((formula, index) => ( + + + + ))} @@ -75,6 +80,7 @@ export const QueryBuilder = memo(function QueryBuilder({