fix: resolve the list view issues (#3020)

* feat: add dynamic table based on query

* feat: add the list view for the traces explorer

* fix: fix the options menu

* feat: update the list view columns config for the traces explorer

* feat: fix columns for the list view for the traces explorer page

* feat: update customization columns for the list view from the traces explorer

* feat: add error msg for the list view, fix creating data for the table

* fix: resolve the list view issues

* fix: update the date column for the list view

* fix: remove additional filter title for the list view

* fix: add initial orderBy filter for the list view

---------

Co-authored-by: Yevhen Shevchenko <y.shevchenko@seedium.io>
Co-authored-by: Nazarenko19 <danil.nazarenko2000@gmail.com>
Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
This commit is contained in:
dnazarenkoo 2023-07-05 13:50:20 +03:00 committed by GitHub
parent b1c1a95e29
commit 8363dadd8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 108 additions and 77 deletions

View File

@ -38,20 +38,12 @@ function AddColumnField({ config }: AddColumnFieldProps): JSX.Element | null {
</SearchIconWrapper>
</Input.Group>
{config.value.map((selectedValue: string) => {
const option = config?.options?.find(
({ value }) => value === selectedValue,
);
return (
<AddColumnItem direction="horizontal" key={option?.value}>
<Typography>{option?.label}</Typography>
<DeleteOutlinedIcon
onClick={(): void => config.onRemove(selectedValue)}
/>
</AddColumnItem>
);
})}
{config.value?.map(({ key, id }) => (
<AddColumnItem direction="horizontal" key={id}>
<Typography>{key}</Typography>
<DeleteOutlinedIcon onClick={(): void => config.onRemove(id as string)} />
</AddColumnItem>
))}
</AddColumnWrapper>
);
}

View File

@ -15,7 +15,8 @@ export interface InitialOptions
export type OptionsMenuConfig = {
format?: Pick<RadioProps, 'value' | 'onChange'>;
maxLines?: Pick<InputNumberProps, 'value' | 'onChange'>;
addColumn?: Pick<SelectProps, 'options' | 'value' | 'onChange'> & {
addColumn?: Pick<SelectProps, 'options' | 'onChange'> & {
value: BaseAutocompleteData[];
onRemove: (key: string) => void;
};
};

View File

@ -63,15 +63,16 @@ const useOptionsMenu = ({
[initialOptions, attributeKeys],
);
const options = useMemo(() => getOptionsFromKeys(attributeKeys), [
attributeKeys,
]);
const selectedColumnKeys = useMemo(
() => optionsQueryData?.selectColumns?.map(({ id }) => id) || [],
[optionsQueryData],
);
const addColumnOptions = useMemo(
() => getOptionsFromKeys(attributeKeys, selectedColumnKeys),
[attributeKeys, selectedColumnKeys],
);
const handleSelectedColumnsChange = useCallback(
(value: string[]) => {
const newSelectedColumnKeys = [
@ -135,8 +136,8 @@ const useOptionsMenu = ({
const optionsMenuConfig: Required<OptionsMenuConfig> = useMemo(
() => ({
addColumn: {
value: selectedColumnKeys || defaultOptionsQuery.selectColumns,
options: options || [],
value: optionsQueryData?.selectColumns || defaultOptionsQuery.selectColumns,
options: addColumnOptions || [],
onChange: handleSelectedColumnsChange,
onRemove: handleRemoveSelectedColumn,
},
@ -150,10 +151,10 @@ const useOptionsMenu = ({
},
}),
[
options,
selectedColumnKeys,
addColumnOptions,
optionsQueryData?.maxLines,
optionsQueryData?.format,
optionsQueryData?.selectColumns,
handleSelectedColumnsChange,
handleRemoveSelectedColumn,
handleFormatChange,

View File

@ -3,12 +3,18 @@ import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteRe
export const getOptionsFromKeys = (
keys: BaseAutocompleteData[],
): SelectProps['options'] =>
keys.map(({ id, key }) => ({
selectedKeys: (string | undefined)[],
): SelectProps['options'] => {
const options = keys.map(({ id, key }) => ({
label: key,
value: id,
}));
return options.filter(
({ value }) => !selectedKeys.find((key) => key === value),
);
};
export const getInitialColumns = (
initialColumnTitles: string[],
attributeKeys: BaseAutocompleteData[],

View File

@ -230,19 +230,21 @@ export const Query = memo(function Query({
</Row>
</Col>
<Col span={11}>
<Row gutter={[11, 5]}>
<Col flex="5.93rem">
<FilterLabel label="Aggregate Every" />
</Col>
<Col flex="1 1 6rem">
<AggregateEveryFilter
query={query}
onChange={handleChangeAggregateEvery}
/>
</Col>
</Row>
</Col>
{panelType !== PANEL_TYPES.LIST && (
<Col span={11}>
<Row gutter={[11, 5]}>
<Col flex="5.93rem">
<FilterLabel label="Aggregate Every" />
</Col>
<Col flex="1 1 6rem">
<AggregateEveryFilter
query={query}
onChange={handleChangeAggregateEvery}
/>
</Col>
</Row>
</Col>
)}
</>
);
}
@ -326,8 +328,11 @@ export const Query = memo(function Query({
</Col>
<Col flex="1 1 12.5rem">
<AggregatorFilter
onChange={handleChangeAggregatorAttribute}
query={query}
onChange={handleChangeAggregatorAttribute}
disabled={
panelType === PANEL_TYPES.LIST || panelType === PANEL_TYPES.TRACE
}
/>
</Col>
</Row>
@ -362,14 +367,16 @@ export const Query = memo(function Query({
</AdditionalFiltersToggler>
</Col>
)}
<Row style={{ width: '100%' }}>
<Input
onChange={handleChangeQueryLegend}
size="middle"
value={query.legend}
addonBefore="Legend Format"
/>
</Row>
{panelType !== PANEL_TYPES.LIST && panelType !== PANEL_TYPES.TRACE && (
<Row style={{ width: '100%' }}>
<Input
onChange={handleChangeQueryLegend}
size="middle"
value={query.legend}
addonBefore="Legend Format"
/>
</Row>
)}
</ListItemWrapper>
);
});

View File

@ -1,7 +1,8 @@
import { AutoCompleteProps } from 'antd';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
export type AgregatorFilterProps = {
onChange: (value: BaseAutocompleteData) => void;
export type AgregatorFilterProps = Pick<AutoCompleteProps, 'disabled'> & {
query: IBuilderQuery;
onChange: (value: BaseAutocompleteData) => void;
};

View File

@ -28,8 +28,9 @@ import { selectStyle } from '../QueryBuilderSearch/config';
import { AgregatorFilterProps } from './AggregatorFilter.intefaces';
export const AggregatorFilter = memo(function AggregatorFilter({
onChange,
query,
disabled,
onChange,
}: AgregatorFilterProps): JSX.Element {
const [optionsData, setOptionsData] = useState<ExtendedSelectOption[]>([]);
const debouncedValue = useDebounce(query.aggregateAttribute.key, 300);
@ -119,6 +120,7 @@ export const AggregatorFilter = memo(function AggregatorFilter({
options={optionsData}
value={value}
onChange={handleChangeAttribute}
disabled={disabled}
/>
);
});

View File

@ -18,6 +18,7 @@ import {
getLabelFromValue,
mapLabelValuePairs,
orderByValueDelimiter,
transformToOrderByStringValues,
} from './utils';
export function OrderByFilter({
@ -25,7 +26,9 @@ export function OrderByFilter({
onChange,
}: OrderByFilterProps): JSX.Element {
const [searchText, setSearchText] = useState<string>('');
const [selectedValue, setSelectedValue] = useState<IOption[]>([]);
const [selectedValue, setSelectedValue] = useState<IOption[]>(
transformToOrderByStringValues(query.orderBy) || [],
);
const { data, isFetching } = useQuery(
[QueryBuilderKeys.GET_AGGREGATE_KEYS, searchText],

View File

@ -21,7 +21,7 @@ function TimeSeriesView({
},
],
}),
[data],
[data?.payload?.data?.result],
);
return (

View File

@ -1,10 +1,7 @@
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import { PANEL_TYPES_QUERY } from 'constants/queryBuilderQueryNames';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import useUrlQueryData from 'hooks/useUrlQueryData';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { DataSource } from 'types/common/queryBuilder';
@ -15,22 +12,17 @@ import TimeSeriesView from './TimeSeriesView';
function TimeSeriesViewContainer({
dataSource = DataSource.TRACES,
}: TimeSeriesViewProps): JSX.Element {
const { stagedQuery } = useQueryBuilder();
const { stagedQuery, panelType } = useQueryBuilder();
const { selectedTime: globalSelectedTime, maxTime, minTime } = useSelector<
AppState,
GlobalReducer
>((state) => state.globalTime);
const { queryData: panelTypeParam } = useUrlQueryData<GRAPH_TYPES>(
PANEL_TYPES_QUERY,
PANEL_TYPES.TIME_SERIES,
);
const { data, isLoading, isError } = useGetQueryRange(
{
query: stagedQuery || initialQueriesMap[dataSource],
graphType: panelTypeParam,
graphType: panelType || PANEL_TYPES.TIME_SERIES,
selectedTime: 'GLOBAL_TIME',
globalSelectedInterval: globalSelectedTime,
params: {
@ -45,7 +37,7 @@ function TimeSeriesViewContainer({
minTime,
stagedQuery,
],
enabled: !!stagedQuery && panelTypeParam === PANEL_TYPES.TIME_SERIES,
enabled: !!stagedQuery && panelType === PANEL_TYPES.TIME_SERIES,
},
);

View File

@ -65,7 +65,8 @@ function ListView(): JSX.Element {
paginationQueryData,
options?.selectColumns,
],
enabled: !!stagedQuery && panelType === PANEL_TYPES.LIST,
enabled:
!!stagedQuery && panelType === PANEL_TYPES.LIST && !!options?.selectColumns,
},
);

View File

@ -15,3 +15,7 @@ export const Container = styled.div`
export const ErrorText = styled(Typography)`
text-align: center;
`;
export const DateText = styled(Typography)`
min-width: 145px;
`;

View File

@ -9,6 +9,8 @@ import { RowData } from 'lib/query/createTableColumnsFromQuery';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { QueryDataV3 } from 'types/api/widgets/getQuery';
import { DateText } from './styles';
export const transformDataWithDate = (data: QueryDataV3[]): QueryDataV3[] =>
data.map((query) => ({
...query,
@ -78,9 +80,10 @@ export const modifyColumns = (
if (key === 'date') {
return {
...column,
width: 145,
render: (date: string): JSX.Element => {
const day = dayjs(date);
return <Typography>{day.format('YYYY/MM/DD HH:mm:ss')}</Typography>;
return <DateText>{day.format('YYYY/MM/DD HH:mm:ss')}</DateText>;
},
};
}

View File

@ -57,9 +57,16 @@ export const useQueryOperations: UseQueryOperations = ({ query, index }) => {
);
const getNewListOfAdditionalFilters = useCallback(
(dataSource: DataSource): string[] =>
mapOfFilters[dataSource].map((item) => item.text),
[],
(dataSource: DataSource): string[] => {
const listOfFilters = mapOfFilters[dataSource].map((item) => item.text);
if (panelType === PANEL_TYPES.LIST) {
return listOfFilters.filter((filter) => filter !== 'Aggregation interval');
}
return listOfFilters;
},
[panelType],
);
const handleChangeAggregatorAttribute = useCallback(

View File

@ -52,15 +52,26 @@ function TracesExplorer(): JSX.Element {
return groupByCount > 0;
}, [currentQuery]);
const defaultQuery = useMemo(
() =>
updateAllQueriesOperators(
initialQueriesMap.traces,
PANEL_TYPES.LIST,
DataSource.TRACES,
),
[updateAllQueriesOperators],
);
const defaultQuery = useMemo(() => {
const query = updateAllQueriesOperators(
initialQueriesMap.traces,
PANEL_TYPES.LIST,
DataSource.TRACES,
);
return {
...query,
builder: {
...query.builder,
queryData: [
{
...query.builder.queryData[0],
orderBy: [{ columnName: 'timestamp', order: 'desc' }],
},
],
},
};
}, [updateAllQueriesOperators]);
const tabsItems = getTabsItems({
isListViewDisabled: isMultipleQueries || isGroupByExist,