[Refactor]: Added tag and datatype in options for query builder (#3555)

Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
Rajat Dabade 2023-12-20 15:31:37 +05:30 committed by GitHub
parent 581bd07b35
commit 6b2f03d43f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 166 additions and 30 deletions

View File

@ -25,7 +25,9 @@ import { ExtendedSelectOption } from 'types/common/select';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
import { transformToUpperCase } from 'utils/transformToUpperCase'; import { transformToUpperCase } from 'utils/transformToUpperCase';
import { removePrefix } from '../GroupByFilter/utils';
import { selectStyle } from '../QueryBuilderSearch/config'; import { selectStyle } from '../QueryBuilderSearch/config';
import OptionRenderer from '../QueryBuilderSearch/OptionRenderer';
// ** Types // ** Types
import { AgregatorFilterProps } from './AggregatorFilter.intefaces'; import { AgregatorFilterProps } from './AggregatorFilter.intefaces';
@ -64,11 +66,23 @@ export const AggregatorFilter = memo(function AggregatorFilter({
onSuccess: (data) => { onSuccess: (data) => {
const options: ExtendedSelectOption[] = const options: ExtendedSelectOption[] =
data?.payload?.attributeKeys?.map(({ id: _, ...item }) => ({ data?.payload?.attributeKeys?.map(({ id: _, ...item }) => ({
label: transformStringWithPrefix({ label: (
str: item.key, <OptionRenderer
prefix: item.type || '', label={transformStringWithPrefix({
condition: !item.isColumn, str: item.key,
}), prefix: item.type || '',
condition: !item.isColumn,
})}
value={removePrefix(
transformStringWithPrefix({
str: item.key,
prefix: item.type || '',
condition: !item.isColumn,
}),
)}
dataType={item.dataType}
/>
),
value: `${item.key}${selectValueDivider}${createIdFromObjectFields( value: `${item.key}${selectValueDivider}${createIdFromObjectFields(
item, item,
baseAutoCompleteIdKeysOrder, baseAutoCompleteIdKeysOrder,
@ -165,18 +179,19 @@ export const AggregatorFilter = memo(function AggregatorFilter({
[getAttributesData, handleChangeCustomValue, onChange], [getAttributesData, handleChangeCustomValue, onChange],
); );
const value = transformStringWithPrefix({ const value = removePrefix(
str: query.aggregateAttribute.key, transformStringWithPrefix({
prefix: query.aggregateAttribute.type || '', str: query.aggregateAttribute.key,
condition: !query.aggregateAttribute.isColumn, prefix: query.aggregateAttribute.type || '',
}); condition: !query.aggregateAttribute.isColumn,
}),
);
return ( return (
<AutoComplete <AutoComplete
getPopupContainer={popupContainer} getPopupContainer={popupContainer}
placeholder={placeholder} placeholder={placeholder}
style={selectStyle} style={selectStyle}
showArrow={false}
filterOption={false} filterOption={false}
onSearch={handleSearchText} onSearch={handleSearchText}
notFoundContent={isFetching ? <Spin size="small" /> : null} notFoundContent={isFetching ? <Spin size="small" /> : null}

View File

@ -14,14 +14,16 @@ import { chooseAutocompleteFromCustomValue } from 'lib/newQueryBuilder/chooseAut
// ** Helpers // ** Helpers
import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix'; import { transformStringWithPrefix } from 'lib/query/transformStringWithPrefix';
import { isEqual, uniqWith } from 'lodash-es'; import { isEqual, uniqWith } from 'lodash-es';
import { memo, useCallback, useEffect, useState } from 'react'; import { memo, ReactNode, useCallback, useEffect, useState } from 'react';
import { useQueryClient } from 'react-query'; import { useQueryClient } from 'react-query';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { SelectOption } from 'types/common/select'; import { SelectOption } from 'types/common/select';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
import { selectStyle } from '../QueryBuilderSearch/config'; import { selectStyle } from '../QueryBuilderSearch/config';
import OptionRenderer from '../QueryBuilderSearch/OptionRenderer';
import { GroupByFilterProps } from './GroupByFilter.interfaces'; import { GroupByFilterProps } from './GroupByFilter.interfaces';
import { removePrefix } from './utils';
export const GroupByFilter = memo(function GroupByFilter({ export const GroupByFilter = memo(function GroupByFilter({
query, query,
@ -30,9 +32,9 @@ export const GroupByFilter = memo(function GroupByFilter({
}: GroupByFilterProps): JSX.Element { }: GroupByFilterProps): JSX.Element {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const [searchText, setSearchText] = useState<string>(''); const [searchText, setSearchText] = useState<string>('');
const [optionsData, setOptionsData] = useState<SelectOption<string, string>[]>( const [optionsData, setOptionsData] = useState<
[], SelectOption<string, ReactNode>[]
); >([]);
const [localValues, setLocalValues] = useState<SelectOption<string, string>[]>( const [localValues, setLocalValues] = useState<SelectOption<string, string>[]>(
[], [],
); );
@ -61,13 +63,26 @@ export const GroupByFilter = memo(function GroupByFilter({
(attrKey) => !keys.includes(attrKey.key), (attrKey) => !keys.includes(attrKey.key),
) || []; ) || [];
const options: SelectOption<string, string>[] = const options: SelectOption<string, ReactNode>[] =
filteredOptions.map((item) => ({ filteredOptions.map((item) => ({
label: transformStringWithPrefix({ label: (
str: item.key, <OptionRenderer
prefix: item.type || '', key={item.key}
condition: !item.isColumn, label={transformStringWithPrefix({
}), str: item.key,
prefix: item.type || '',
condition: !item.isColumn,
})}
value={removePrefix(
transformStringWithPrefix({
str: item.key,
prefix: item.type || '',
condition: !item.isColumn,
}),
)}
dataType={item.dataType || ''}
/>
),
value: `${transformStringWithPrefix({ value: `${transformStringWithPrefix({
str: item.key, str: item.key,
prefix: item.type || '', prefix: item.type || '',
@ -152,11 +167,13 @@ export const GroupByFilter = memo(function GroupByFilter({
useEffect(() => { useEffect(() => {
const currentValues: SelectOption<string, string>[] = query.groupBy.map( const currentValues: SelectOption<string, string>[] = query.groupBy.map(
(item) => ({ (item) => ({
label: `${transformStringWithPrefix({ label: `${removePrefix(
str: item.key, transformStringWithPrefix({
prefix: item.type || '', str: item.key,
condition: !item.isColumn, prefix: item.type || '',
})}`, condition: !item.isColumn,
}),
)}`,
value: `${transformStringWithPrefix({ value: `${transformStringWithPrefix({
str: item.key, str: item.key,
prefix: item.type || '', prefix: item.type || '',
@ -176,7 +193,6 @@ export const GroupByFilter = memo(function GroupByFilter({
onSearch={handleSearchKeys} onSearch={handleSearchKeys}
showSearch showSearch
disabled={disabled} disabled={disabled}
showArrow={false}
filterOption={false} filterOption={false}
onBlur={handleBlur} onBlur={handleBlur}
onFocus={handleFocus} onFocus={handleFocus}

View File

@ -0,0 +1,14 @@
import { MetricsType } from 'container/MetricsApplication/constant';
export function removePrefix(str: string): string {
const tagPrefix = `${MetricsType.Tag}_`;
const resourcePrefix = `${MetricsType.Resource}_`;
if (str.startsWith(tagPrefix)) {
return str.slice(tagPrefix.length);
}
if (str.startsWith(resourcePrefix)) {
return str.slice(resourcePrefix.length);
}
return str;
}

View File

@ -0,0 +1,45 @@
import {
SelectOptionContainer,
TagContainer,
TagLabel,
TagValue,
} from './style';
import { getOptionType } from './utils';
function OptionRenderer({
label,
value,
dataType,
}: OptionRendererProps): JSX.Element {
const optionType = getOptionType(label);
return (
<span>
{optionType ? (
<SelectOptionContainer>
<div>{value}</div>
<div>
<TagContainer>
<TagLabel>Type: </TagLabel>
<TagValue>{optionType}</TagValue>
</TagContainer>
<TagContainer>
<TagLabel>Data type: </TagLabel>
<TagValue>{dataType}</TagValue>
</TagContainer>
</div>
</SelectOptionContainer>
) : (
<span>{label}</span>
)}
</span>
);
}
interface OptionRendererProps {
label: string;
value: string;
dataType: string;
}
export default OptionRenderer;

View File

@ -28,6 +28,7 @@ import { v4 as uuid } from 'uuid';
import { selectStyle } from './config'; import { selectStyle } from './config';
import { PLACEHOLDER } from './constant'; import { PLACEHOLDER } from './constant';
import OptionRenderer from './OptionRenderer';
import { StyledCheckOutlined, TypographyText } from './style'; import { StyledCheckOutlined, TypographyText } from './style';
import { import {
getOperatorValue, getOperatorValue,
@ -205,7 +206,11 @@ function QueryBuilderSearch({
> >
{options.map((option) => ( {options.map((option) => (
<Select.Option key={option.label} value={option.value}> <Select.Option key={option.label} value={option.value}>
{option.label} <OptionRenderer
label={option.label}
value={option.value}
dataType={option.dataType || ''}
/>
{option.selected && <StyledCheckOutlined />} {option.selected && <StyledCheckOutlined />}
</Select.Option> </Select.Option>
))} ))}

View File

@ -1,5 +1,5 @@
import { CheckOutlined } from '@ant-design/icons'; import { CheckOutlined } from '@ant-design/icons';
import { Typography } from 'antd'; import { Tag, Typography } from 'antd';
import styled from 'styled-components'; import styled from 'styled-components';
export const TypographyText = styled(Typography.Text)<{ export const TypographyText = styled(Typography.Text)<{
@ -15,3 +15,27 @@ export const TypographyText = styled(Typography.Text)<{
export const StyledCheckOutlined = styled(CheckOutlined)` export const StyledCheckOutlined = styled(CheckOutlined)`
float: right; float: right;
`; `;
export const SelectOptionContainer = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`;
export const TagContainer = styled(Tag)`
&&& {
border-radius: 0.25rem;
padding: 0.063rem 0.5rem;
font-weight: 600;
font-size: 0.75rem;
line-height: 1.25rem;
}
`;
export const TagLabel = styled.span`
font-weight: 400;
`;
export const TagValue = styled.span`
text-transform: capitalize;
`;

View File

@ -1,4 +1,5 @@
import { OPERATORS } from 'constants/queryBuilder'; import { OPERATORS } from 'constants/queryBuilder';
import { MetricsType } from 'container/MetricsApplication/constant';
import { parse } from 'papaparse'; import { parse } from 'papaparse';
import { orderByValueDelimiter } from '../OrderByFilter/utils'; import { orderByValueDelimiter } from '../OrderByFilter/utils';
@ -140,3 +141,15 @@ export function getRemoveOrderFromValue(tag: string): string {
} }
return tag; return tag;
} }
export function getOptionType(label: string): MetricsType | undefined {
let optionType;
if (label.startsWith('tag_')) {
optionType = MetricsType.Tag;
} else if (label.startsWith('resource_')) {
optionType = MetricsType.Resource;
}
return optionType;
}

View File

@ -14,4 +14,5 @@ export type Option = {
value: string; value: string;
label: string; label: string;
selected?: boolean; selected?: boolean;
dataType?: string;
}; };

View File

@ -43,6 +43,7 @@ export const useOptions = (
items?.map((item) => ({ items?.map((item) => ({
label: `${getLabel(item)}`, label: `${getLabel(item)}`,
value: item.key, value: item.key,
dataType: item.dataType,
})), })),
[getLabel], [getLabel],
); );

View File

@ -1,3 +1,5 @@
import { ReactNode } from 'react';
export type SelectOption<Value, Label extends unknown = string> = { export type SelectOption<Value, Label extends unknown = string> = {
value: Value; value: Value;
label: Label; label: Label;
@ -6,7 +8,7 @@ export type SelectOption<Value, Label extends unknown = string> = {
export type ExtendedSelectOption = { export type ExtendedSelectOption = {
disabled?: boolean; disabled?: boolean;
key: string; key: string;
label: string; label: ReactNode;
title?: string; title?: string;
value: string; value: string;
}; };