diff --git a/frontend/src/api/queryBuilder/getAttributeKeys.ts b/frontend/src/api/queryBuilder/getAttributeKeys.ts index b42566a75e..439c20f132 100644 --- a/frontend/src/api/queryBuilder/getAttributeKeys.ts +++ b/frontend/src/api/queryBuilder/getAttributeKeys.ts @@ -11,6 +11,7 @@ export const getAggregateKeys = async ({ searchText, dataSource, aggregateAttribute, + tagType, }: IGetAttributeKeysPayload): Promise< SuccessResponse | ErrorResponse > => { @@ -18,7 +19,7 @@ export const getAggregateKeys = async ({ const response: AxiosResponse<{ data: IQueryAutocompleteResponse; }> = await ApiV3Instance.get( - `autocomplete/attribute_keys?aggregateOperator=${aggregateOperator}&dataSource=${dataSource}&aggregateAttribute=${aggregateAttribute}&searchText=${searchText}`, + `autocomplete/attribute_keys?aggregateOperator=${aggregateOperator}&dataSource=${dataSource}&aggregateAttribute=${aggregateAttribute}&tagType=${tagType}&searchText=${searchText}`, ); return { diff --git a/frontend/src/constants/useQueryKeys.ts b/frontend/src/constants/useQueryKeys.ts index 705d5ef350..c765c17748 100644 --- a/frontend/src/constants/useQueryKeys.ts +++ b/frontend/src/constants/useQueryKeys.ts @@ -1,3 +1,4 @@ export enum QueryBuilderKeys { GET_AGGREGATE_ATTRIBUTE = 'GET_AGGREGATE_ATTRIBUTE', + GET_AGGREGATE_KEYS = 'GET_AGGREGATE_KEYS', } diff --git a/frontend/src/container/QueryBuilder/components/FilterLabel/FilterLabel.styled.ts b/frontend/src/container/QueryBuilder/components/FilterLabel/FilterLabel.styled.ts index 8eb97a32f3..d379f6cbbe 100644 --- a/frontend/src/container/QueryBuilder/components/FilterLabel/FilterLabel.styled.ts +++ b/frontend/src/container/QueryBuilder/components/FilterLabel/FilterLabel.styled.ts @@ -2,7 +2,6 @@ import styled from 'styled-components'; export const StyledLabel = styled.div` padding: 0 0.6875rem; - min-width: 6.5rem; width: fit-content; min-height: 2rem; display: inline-flex; diff --git a/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.styled.ts b/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.styled.ts index f876af973b..6344456d0b 100644 --- a/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.styled.ts +++ b/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.styled.ts @@ -1,9 +1,12 @@ import { Button } from 'antd'; import styled from 'styled-components'; -export const StyledButton = styled(Button)` +export const StyledButton = styled(Button)<{ isAvailableToDisable: boolean }>` min-width: 2rem; height: 2.25rem; padding: 0.125rem; border-radius: 0.375rem; + margin-right: 0.1rem; + pointer-events: ${(props): string => + props.isAvailableToDisable ? 'default' : 'none'}; `; diff --git a/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.tsx b/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.tsx index 3af9d3aa37..8573579be7 100644 --- a/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.tsx +++ b/frontend/src/container/QueryBuilder/components/ListMarker/ListMarker.tsx @@ -30,7 +30,8 @@ export function ListMarker({ icon={buttonProps.icon} onClick={buttonProps.onClick} className={className} - style={{ marginRight: '0.1rem', ...style }} + isAvailableToDisable={isAvailableToDisable} + style={style} > {labelName} diff --git a/frontend/src/container/QueryBuilder/components/Query/Query.tsx b/frontend/src/container/QueryBuilder/components/Query/Query.tsx index 81427bc260..a41eb51e5d 100644 --- a/frontend/src/container/QueryBuilder/components/Query/Query.tsx +++ b/frontend/src/container/QueryBuilder/components/Query/Query.tsx @@ -8,13 +8,14 @@ import { } from 'container/QueryBuilder/components'; import { AggregatorFilter, + GroupByFilter, OperatorsSelect, } from 'container/QueryBuilder/filters'; // Context import { useQueryBuilder } from 'hooks/useQueryBuilder'; // ** Hooks import React from 'react'; -import { AutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataSource } from 'types/common/queryBuilder'; // ** Constants import { @@ -55,40 +56,66 @@ export function Query({ handleSetQueryData(index, { disabled: !query.disabled }); }; - const handleChangeAggregatorAttribute = (value: AutocompleteData): void => { + const handleChangeAggregatorAttribute = ( + value: BaseAutocompleteData, + ): void => { handleSetQueryData(index, { aggregateAttribute: value }); }; + const handleChangeGroupByKeys = (values: BaseAutocompleteData[]): void => { + handleSetQueryData(index, { groupBy: values }); + }; + return ( - - - - {queryVariant === 'dropdown' ? ( - - ) : ( - - )} - + - - + + + + {queryVariant === 'dropdown' ? ( + + ) : ( + + )} + {/* TODO: here will be search */} + + + + + + + + + + + + + + + + + + + + + + ); diff --git a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts index 81ba34a2c2..e8e4f072fb 100644 --- a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts +++ b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.intefaces.ts @@ -1,7 +1,7 @@ -import { AutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { IBuilderQueryForm } from 'types/api/queryBuilder/queryBuilderData'; export type AgregatorFilterProps = { - onChange: (value: AutocompleteData) => void; + onChange: (value: BaseAutocompleteData) => void; query: IBuilderQueryForm; }; diff --git a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx index 13a25216ce..6eebe2f955 100644 --- a/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx +++ b/frontend/src/container/QueryBuilder/filters/AggregatorFilter/AggregatorFilter.tsx @@ -68,10 +68,8 @@ export function AggregatorFilter({ return ( void; +}; + +export type GroupByFilterValue = { + disabled: boolean | undefined; + key: string; + label: string; + title: string | undefined; + value: string; +}; diff --git a/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx b/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx new file mode 100644 index 0000000000..3cda80d704 --- /dev/null +++ b/frontend/src/container/QueryBuilder/filters/GroupByFilter/GroupByFilter.tsx @@ -0,0 +1,100 @@ +import { Select, Spin } from 'antd'; +// ** Api +import { getAggregateKeys } from 'api/queryBuilder/getAttributeKeys'; +// ** Constants +import { QueryBuilderKeys } from 'constants/useQueryKeys'; +// ** Components +// ** Helpers +import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix'; +import React, { useState } from 'react'; +import { useQuery } from 'react-query'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { SelectOption } from 'types/common/select'; + +// ** Types +import { + GroupByFilterProps, + GroupByFilterValue, +} from './GroupByFilter.interfaces'; + +export function GroupByFilter({ + query, + onChange, +}: GroupByFilterProps): JSX.Element { + const [searchText, setSearchText] = useState(''); + + const { data, isFetching } = useQuery( + [QueryBuilderKeys.GET_AGGREGATE_KEYS, searchText], + async () => + getAggregateKeys({ + aggregateAttribute: query.aggregateAttribute.key, + tagType: query.aggregateAttribute.type, + dataSource: query.dataSource, + aggregateOperator: query.aggregateOperator, + searchText, + }), + { enabled: !!query.aggregateAttribute.key, keepPreviousData: true }, + ); + + const handleSearchKeys = (searchText: string): void => { + setSearchText(searchText); + }; + + const optionsData: SelectOption[] = + data?.payload?.attributeKeys?.map((item) => ({ + label: transformStringWithPrefix({ + str: item.key, + prefix: item.type || '', + condition: !item.isColumn, + }), + value: item.key, + })) || []; + + const handleChange = (values: GroupByFilterValue[]): void => { + const groupByValues: BaseAutocompleteData[] = values.map((item) => { + const iterationArray = data?.payload?.attributeKeys || query.groupBy; + const existGroup = iterationArray.find((group) => group.key === item.value); + if (existGroup) { + return existGroup; + } + + return { + isColumn: null, + key: item.value, + dataType: null, + type: null, + }; + }); + + onChange(groupByValues); + }; + + const values: GroupByFilterValue[] = query.groupBy.map((item) => ({ + label: transformStringWithPrefix({ + str: item.key, + prefix: item.type || '', + condition: !item.isColumn, + }), + key: item.key, + value: item.key, + disabled: undefined, + title: undefined, + })); + + return ( +