mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 09:56:03 +08:00
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:
parent
b1c1a95e29
commit
8363dadd8d
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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[],
|
||||
|
@ -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>
|
||||
);
|
||||
});
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -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],
|
||||
|
@ -21,7 +21,7 @@ function TimeSeriesView({
|
||||
},
|
||||
],
|
||||
}),
|
||||
[data],
|
||||
[data?.payload?.data?.result],
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -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,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
`;
|
||||
|
@ -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>;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user