mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-10-13 21:01:27 +08:00
feat: support of changing panel type in dashboards (#4759)
* feat: support of changing panel type in dashboards * feat: add handle query change function * feat: last bit of minor change * feat: apply current query updates to superset query * feat: pr cleanup * feat: handle list type change * fix: build issues * fix: changes required due to refactor * fix: handle offset and page size for list queries * feat: handle functions propagation * feat: handle the spaceAggregation value to retain * fix: handle list panel type changes * feat: handle removing the graph list from the side selection in case of metrics * feat: handle list type qb changes * feat: handle page breaking * feat: pick dataSource from newQUeryItem * feat: handle page reload
This commit is contained in:
parent
e9bb05cc5d
commit
6815a96d29
@ -30,7 +30,7 @@ const Items: ItemsProps[] = [
|
||||
},
|
||||
];
|
||||
|
||||
interface ItemsProps {
|
||||
export interface ItemsProps {
|
||||
name: PANEL_TYPES;
|
||||
icon: JSX.Element;
|
||||
display: string;
|
||||
|
@ -64,6 +64,7 @@ function WidgetGraphContainer({
|
||||
selectedWidget={selectedWidget}
|
||||
queryResponse={queryResponse}
|
||||
setRequestData={setRequestData}
|
||||
selectedGraph={selectedGraph}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { QueryParams } from 'constants/query';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import PanelWrapper from 'container/PanelWrapper/PanelWrapper';
|
||||
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
@ -25,6 +26,7 @@ function WidgetGraph({
|
||||
selectedWidget,
|
||||
queryResponse,
|
||||
setRequestData,
|
||||
selectedGraph,
|
||||
}: WidgetGraphProps): JSX.Element {
|
||||
const graphRef = useRef<HTMLDivElement>(null);
|
||||
const dispatch = useDispatch();
|
||||
@ -89,6 +91,7 @@ function WidgetGraph({
|
||||
queryResponse={queryResponse}
|
||||
setRequestData={setRequestData}
|
||||
onDragSelect={onDragSelect}
|
||||
selectedGraph={selectedGraph}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -101,6 +104,7 @@ interface WidgetGraphProps {
|
||||
Error
|
||||
>;
|
||||
setRequestData: Dispatch<SetStateAction<GetQueryResultsProps>>;
|
||||
selectedGraph: PANEL_TYPES;
|
||||
}
|
||||
|
||||
export default WidgetGraph;
|
||||
|
@ -35,10 +35,10 @@ function LeftContainer({
|
||||
>((state) => state.globalTime);
|
||||
|
||||
const [requestData, setRequestData] = useState<GetQueryResultsProps>(() => {
|
||||
if (selectedWidget && selectedWidget.panelTypes !== PANEL_TYPES.LIST) {
|
||||
if (selectedWidget && selectedGraph !== PANEL_TYPES.LIST) {
|
||||
return {
|
||||
selectedTime: selectedWidget?.timePreferance,
|
||||
graphType: getGraphType(selectedWidget.panelTypes),
|
||||
graphType: getGraphType(selectedGraph || selectedWidget.panelTypes),
|
||||
query: stagedQuery || initialQueriesMap.metrics,
|
||||
globalSelectedInterval,
|
||||
variables: getDashboardVariables(selectedDashboard?.data.variables),
|
||||
@ -65,6 +65,7 @@ function LeftContainer({
|
||||
if (stagedQuery) {
|
||||
setRequestData((prev) => ({
|
||||
...prev,
|
||||
graphType: getGraphType(selectedGraph || selectedWidget.panelTypes),
|
||||
query: stagedQuery,
|
||||
}));
|
||||
}
|
||||
|
@ -12,10 +12,20 @@ import {
|
||||
import InputComponent from 'components/Input';
|
||||
import TimePreference from 'components/TimePreferenceDropDown';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import GraphTypes from 'container/NewDashboard/ComponentsSlider/menuItems';
|
||||
import GraphTypes, {
|
||||
ItemsProps,
|
||||
} from 'container/NewDashboard/ComponentsSlider/menuItems';
|
||||
import useCreateAlerts from 'hooks/queryBuilder/useCreateAlerts';
|
||||
import { Dispatch, SetStateAction, useCallback } from 'react';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import {
|
||||
Dispatch,
|
||||
SetStateAction,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Widgets } from 'types/api/dashboard/getAll';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import {
|
||||
panelTypeVsCreateAlert,
|
||||
@ -75,6 +85,24 @@ function RightContainer({
|
||||
const allowPanelTimePreference =
|
||||
panelTypeVsPanelTimePreferences[selectedGraph];
|
||||
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
|
||||
const [graphTypes, setGraphTypes] = useState<ItemsProps[]>(GraphTypes);
|
||||
|
||||
useEffect(() => {
|
||||
const queryContainsMetricsDataSource = currentQuery.builder.queryData.some(
|
||||
(query) => query.dataSource === DataSource.METRICS,
|
||||
);
|
||||
|
||||
if (queryContainsMetricsDataSource) {
|
||||
setGraphTypes((prev) =>
|
||||
prev.filter((graph) => graph.name !== PANEL_TYPES.LIST),
|
||||
);
|
||||
} else {
|
||||
setGraphTypes(GraphTypes);
|
||||
}
|
||||
}, [currentQuery]);
|
||||
|
||||
const softMinHandler = useCallback(
|
||||
(value: number | null) => {
|
||||
setSoftMin(value);
|
||||
@ -95,10 +123,9 @@ function RightContainer({
|
||||
<Select
|
||||
onChange={setGraphHandler}
|
||||
value={selectedGraph}
|
||||
disabled
|
||||
style={{ width: '100%', marginBottom: 24 }}
|
||||
>
|
||||
{GraphTypes.map((item) => (
|
||||
{graphTypes.map((item) => (
|
||||
<Option key={item.name} value={item.name}>
|
||||
{item.display}
|
||||
</Option>
|
||||
|
@ -3,6 +3,7 @@ import { LockFilled, WarningOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal, Space, Tooltip, Typography } from 'antd';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { DashboardShortcuts } from 'constants/shortcuts/DashboardShortcuts';
|
||||
@ -23,7 +24,7 @@ import {
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { generatePath, useLocation, useParams } from 'react-router-dom';
|
||||
import { generatePath, useParams } from 'react-router-dom';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
|
||||
import { IField } from 'types/api/logs/fields';
|
||||
@ -44,7 +45,7 @@ import {
|
||||
RightContainerWrapper,
|
||||
} from './styles';
|
||||
import { NewWidgetProps } from './types';
|
||||
import { getIsQueryModified } from './utils';
|
||||
import { getIsQueryModified, handleQueryChange } from './utils';
|
||||
|
||||
function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
||||
const {
|
||||
@ -57,7 +58,12 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
||||
|
||||
const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys();
|
||||
|
||||
const { currentQuery, stagedQuery } = useQueryBuilder();
|
||||
const {
|
||||
currentQuery,
|
||||
stagedQuery,
|
||||
redirectWithQueryBuilderData,
|
||||
supersetQuery,
|
||||
} = useQueryBuilder();
|
||||
|
||||
const isQueryModified = useMemo(
|
||||
() => getIsQueryModified(currentQuery, stagedQuery),
|
||||
@ -70,8 +76,6 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
||||
|
||||
const { widgets = [] } = selectedDashboard?.data || {};
|
||||
|
||||
const { search } = useLocation();
|
||||
|
||||
const query = useUrlQuery();
|
||||
|
||||
const { dashboardId } = useParams<DashboardWidgetPageParams>();
|
||||
@ -297,9 +301,14 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
||||
}, [dashboardId]);
|
||||
|
||||
const setGraphHandler = (type: PANEL_TYPES): void => {
|
||||
const params = new URLSearchParams(search);
|
||||
params.set('graphType', type);
|
||||
const updatedQuery = handleQueryChange(type as any, supersetQuery);
|
||||
setGraphType(type);
|
||||
redirectWithQueryBuilderData(
|
||||
updatedQuery,
|
||||
{ [QueryParams.graphType]: type },
|
||||
undefined,
|
||||
false,
|
||||
);
|
||||
};
|
||||
|
||||
const onSaveDashboard = useCallback((): void => {
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { omitIdFromQuery } from 'components/ExplorerCard/utils';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import {
|
||||
initialQueryBuilderFormValuesMap,
|
||||
PANEL_TYPES,
|
||||
} from 'constants/queryBuilder';
|
||||
import { isEqual, set, unset } from 'lodash-es';
|
||||
import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
export const getIsQueryModified = (
|
||||
currentQuery: Query,
|
||||
@ -13,3 +18,242 @@ export const getIsQueryModified = (
|
||||
const omitIdFromCurrentQuery = omitIdFromQuery(currentQuery);
|
||||
return !isEqual(omitIdFromStageQuery, omitIdFromCurrentQuery);
|
||||
};
|
||||
|
||||
export type PartialPanelTypes = {
|
||||
[PANEL_TYPES.BAR]: 'bar';
|
||||
[PANEL_TYPES.LIST]: 'list';
|
||||
[PANEL_TYPES.TABLE]: 'table';
|
||||
[PANEL_TYPES.TIME_SERIES]: 'graph';
|
||||
[PANEL_TYPES.VALUE]: 'value';
|
||||
};
|
||||
|
||||
export const panelTypeDataSourceFormValuesMap: Record<
|
||||
keyof PartialPanelTypes,
|
||||
Record<DataSource, any>
|
||||
> = {
|
||||
[PANEL_TYPES.BAR]: {
|
||||
[DataSource.LOGS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
'functions',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.METRICS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
'functions',
|
||||
'spaceAggregation',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.TRACES]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
[PANEL_TYPES.TIME_SERIES]: {
|
||||
[DataSource.LOGS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
'functions',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.METRICS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
'functions',
|
||||
'spaceAggregation',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.TRACES]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
[PANEL_TYPES.TABLE]: {
|
||||
[DataSource.LOGS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
'functions',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.METRICS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
'functions',
|
||||
'spaceAggregation',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.TRACES]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
[PANEL_TYPES.LIST]: {
|
||||
[DataSource.LOGS]: {
|
||||
builder: {
|
||||
queryData: ['filters', 'limit', 'orderBy'],
|
||||
},
|
||||
},
|
||||
[DataSource.METRICS]: {
|
||||
builder: {
|
||||
queryData: [],
|
||||
},
|
||||
},
|
||||
[DataSource.TRACES]: {
|
||||
builder: {
|
||||
queryData: ['filters', 'limit', 'orderBy'],
|
||||
},
|
||||
},
|
||||
},
|
||||
[PANEL_TYPES.VALUE]: {
|
||||
[DataSource.LOGS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'reduceTo',
|
||||
'having',
|
||||
'functions',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.METRICS]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'having',
|
||||
'reduceTo',
|
||||
'functions',
|
||||
'spaceAggregation',
|
||||
],
|
||||
},
|
||||
},
|
||||
[DataSource.TRACES]: {
|
||||
builder: {
|
||||
queryData: [
|
||||
'filters',
|
||||
'aggregateOperator',
|
||||
'aggregateAttribute',
|
||||
'groupBy',
|
||||
'limit',
|
||||
'having',
|
||||
'orderBy',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export function handleQueryChange(
|
||||
newPanelType: keyof PartialPanelTypes,
|
||||
supersetQuery: Query,
|
||||
): Query {
|
||||
return {
|
||||
...supersetQuery,
|
||||
builder: {
|
||||
...supersetQuery.builder,
|
||||
queryData: supersetQuery.builder.queryData.map((query, index) => {
|
||||
const { dataSource } = query;
|
||||
const tempQuery = { ...initialQueryBuilderFormValuesMap[dataSource] };
|
||||
|
||||
const fieldsToSelect =
|
||||
panelTypeDataSourceFormValuesMap[newPanelType][dataSource].builder
|
||||
.queryData;
|
||||
|
||||
fieldsToSelect.forEach((field: keyof IBuilderQuery) => {
|
||||
set(tempQuery, field, supersetQuery.builder.queryData[index][field]);
|
||||
});
|
||||
|
||||
if (newPanelType === PANEL_TYPES.LIST) {
|
||||
set(tempQuery, 'aggregateOperator', 'noop');
|
||||
set(tempQuery, 'offset', 0);
|
||||
set(tempQuery, 'pageSize', 10);
|
||||
} else if (tempQuery.aggregateOperator === 'noop') {
|
||||
set(tempQuery, 'aggregateOperator', 'count');
|
||||
unset(tempQuery, 'offset');
|
||||
unset(tempQuery, 'pageSize');
|
||||
}
|
||||
|
||||
return tempQuery;
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -13,9 +13,10 @@ function PanelWrapper({
|
||||
onToggleModelHandler,
|
||||
onClickHandler,
|
||||
onDragSelect,
|
||||
selectedGraph,
|
||||
}: PanelWrapperProps): JSX.Element {
|
||||
const Component = PanelTypeVsPanelWrapper[
|
||||
widget.panelTypes
|
||||
selectedGraph || widget.panelTypes
|
||||
] as FC<PanelWrapperProps>;
|
||||
|
||||
if (!Component) {
|
||||
@ -33,6 +34,7 @@ function PanelWrapper({
|
||||
onToggleModelHandler={onToggleModelHandler}
|
||||
onClickHandler={onClickHandler}
|
||||
onDragSelect={onDragSelect}
|
||||
selectedGraph={selectedGraph}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ function UplotPanelWrapper({
|
||||
onToggleModelHandler,
|
||||
onClickHandler,
|
||||
onDragSelect,
|
||||
selectedGraph,
|
||||
}: PanelWrapperProps): JSX.Element {
|
||||
const { toScrollWidgetId, setToScrollWidgetId } = useDashboard();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
@ -96,7 +97,7 @@ function UplotPanelWrapper({
|
||||
softMin: widget.softMin === undefined ? null : widget.softMin,
|
||||
graphsVisibilityStates: graphVisibility,
|
||||
setGraphsVisibilityStates: setGraphVisibility,
|
||||
panelType: widget.panelTypes,
|
||||
panelType: selectedGraph || widget.panelTypes,
|
||||
currentQuery,
|
||||
}),
|
||||
[
|
||||
@ -115,6 +116,7 @@ function UplotPanelWrapper({
|
||||
maxTimeScale,
|
||||
graphVisibility,
|
||||
setGraphVisibility,
|
||||
selectedGraph,
|
||||
currentQuery,
|
||||
],
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { WidgetGraphComponentProps } from 'container/GridCardLayout/GridCard/types';
|
||||
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
@ -19,4 +20,5 @@ export type PanelWrapperProps = {
|
||||
setGraphVisibility?: Dispatch<SetStateAction<boolean[]>>;
|
||||
onClickHandler?: OnClickPluginOpts['onClick'];
|
||||
onDragSelect: (start: number, end: number) => void;
|
||||
selectedGraph?: PANEL_TYPES;
|
||||
};
|
||||
|
@ -16,6 +16,10 @@ import {
|
||||
PANEL_TYPES,
|
||||
} from 'constants/queryBuilder';
|
||||
import ROUTES from 'constants/routes';
|
||||
import {
|
||||
panelTypeDataSourceFormValuesMap,
|
||||
PartialPanelTypes,
|
||||
} from 'container/NewWidget/utils';
|
||||
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
|
||||
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
@ -23,7 +27,7 @@ import { createIdFromObjectFields } from 'lib/createIdFromObjectFields';
|
||||
import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName';
|
||||
import { getOperatorsBySourceAndPanelType } from 'lib/newQueryBuilder/getOperatorsBySourceAndPanelType';
|
||||
import { replaceIncorrectObjectFields } from 'lib/replaceIncorrectObjectFields';
|
||||
import { merge } from 'lodash-es';
|
||||
import { get, merge, set } from 'lodash-es';
|
||||
import {
|
||||
createContext,
|
||||
PropsWithChildren,
|
||||
@ -57,6 +61,8 @@ import { v4 as uuid } from 'uuid';
|
||||
|
||||
export const QueryBuilderContext = createContext<QueryBuilderContextType>({
|
||||
currentQuery: initialQueriesMap.metrics,
|
||||
supersetQuery: initialQueriesMap.metrics,
|
||||
setSupersetQuery: () => {},
|
||||
stagedQuery: initialQueriesMap.metrics,
|
||||
initialDataSource: null,
|
||||
panelType: PANEL_TYPES.TIME_SERIES,
|
||||
@ -110,6 +116,7 @@ export function QueryBuilderProvider({
|
||||
);
|
||||
|
||||
const [currentQuery, setCurrentQuery] = useState<QueryState>(queryState);
|
||||
const [supersetQuery, setSupersetQuery] = useState<QueryState>(queryState);
|
||||
const [stagedQuery, setStagedQuery] = useState<Query | null>(null);
|
||||
|
||||
const [queryType, setQueryType] = useState<EQueryType>(queryTypeParam);
|
||||
@ -263,6 +270,21 @@ export function QueryBuilderProvider({
|
||||
|
||||
const filteredArray = currentArray.filter((_, i) => index !== i);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
...prevState.builder,
|
||||
[type]: filteredArray,
|
||||
},
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
const currentArray: (IBuilderQuery | IBuilderFormula)[] =
|
||||
prevState.builder[type];
|
||||
|
||||
const filteredArray = currentArray.filter((_, i) => index !== i);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
@ -284,6 +306,14 @@ export function QueryBuilderProvider({
|
||||
[type]: targetArray.filter((_, i) => index !== i),
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
const targetArray: (IPromQLQuery | IClickHouseQuery)[] = prevState[type];
|
||||
return {
|
||||
...prevState,
|
||||
[type]: targetArray.filter((_, i) => index !== i),
|
||||
};
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
@ -366,6 +396,17 @@ export function QueryBuilderProvider({
|
||||
|
||||
const newQuery = createNewQueryTypeItem(prevState[type], type);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
[type]: [...prevState[type], newQuery],
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
if (prevState[type].length >= MAX_QUERIES) return prevState;
|
||||
|
||||
const newQuery = createNewQueryTypeItem(prevState[type], type);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
[type]: [...prevState[type], newQuery],
|
||||
@ -381,6 +422,20 @@ export function QueryBuilderProvider({
|
||||
|
||||
const newQuery = createNewBuilderQuery(prevState.builder.queryData);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
...prevState.builder,
|
||||
queryData: [...prevState.builder.queryData, newQuery],
|
||||
},
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
if (prevState.builder.queryData.length >= MAX_QUERIES) return prevState;
|
||||
|
||||
const newQuery = createNewBuilderQuery(prevState.builder.queryData);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
@ -401,6 +456,23 @@ export function QueryBuilderProvider({
|
||||
query,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
...prevState.builder,
|
||||
queryData: [...prevState.builder.queryData, clonedQuery],
|
||||
},
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
if (prevState.builder.queryData.length >= MAX_QUERIES) return prevState;
|
||||
|
||||
const clonedQuery = cloneNewBuilderQuery(
|
||||
prevState.builder.queryData,
|
||||
query,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
@ -419,6 +491,20 @@ export function QueryBuilderProvider({
|
||||
|
||||
const newFormula = createNewBuilderFormula(prevState.builder.queryFormulas);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
...prevState.builder,
|
||||
queryFormulas: [...prevState.builder.queryFormulas, newFormula],
|
||||
},
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
if (prevState.builder.queryFormulas.length >= MAX_FORMULAS) return prevState;
|
||||
|
||||
const newFormula = createNewBuilderFormula(prevState.builder.queryFormulas);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
@ -439,6 +525,31 @@ export function QueryBuilderProvider({
|
||||
[],
|
||||
);
|
||||
|
||||
const updateSuperSetQueryBuilderData = useCallback(
|
||||
(arr: IBuilderQuery[], index: number, newQueryItem: IBuilderQuery) =>
|
||||
arr.map((item, idx) => {
|
||||
if (index === idx) {
|
||||
if (!panelType) {
|
||||
return newQueryItem;
|
||||
}
|
||||
const queryItem = item as IBuilderQuery;
|
||||
const propsRequired =
|
||||
panelTypeDataSourceFormValuesMap[panelType as keyof PartialPanelTypes][
|
||||
queryItem.dataSource
|
||||
].builder.queryData;
|
||||
|
||||
propsRequired.push('dataSource');
|
||||
propsRequired.forEach((p: any) => {
|
||||
set(queryItem, p, get(newQueryItem, p));
|
||||
});
|
||||
return queryItem;
|
||||
}
|
||||
|
||||
return item;
|
||||
}),
|
||||
[panelType],
|
||||
);
|
||||
|
||||
const handleSetQueryItemData = useCallback(
|
||||
(
|
||||
index: number,
|
||||
@ -452,6 +563,19 @@ export function QueryBuilderProvider({
|
||||
newQueryData,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
[type]: updatedQueryBuilderData,
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
const updatedQueryBuilderData = updateQueryBuilderData(
|
||||
prevState[type],
|
||||
index,
|
||||
newQueryData,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
[type]: updatedQueryBuilderData,
|
||||
@ -470,6 +594,22 @@ export function QueryBuilderProvider({
|
||||
newQueryData,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
...prevState.builder,
|
||||
queryData: updatedQueryBuilderData,
|
||||
},
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
const updatedQueryBuilderData = updateSuperSetQueryBuilderData(
|
||||
prevState.builder.queryData,
|
||||
index,
|
||||
newQueryData,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
@ -479,7 +619,7 @@ export function QueryBuilderProvider({
|
||||
};
|
||||
});
|
||||
},
|
||||
[updateQueryBuilderData],
|
||||
[updateQueryBuilderData, updateSuperSetQueryBuilderData],
|
||||
);
|
||||
const handleSetFormulaData = useCallback(
|
||||
(index: number, formulaData: IBuilderFormula): void => {
|
||||
@ -490,6 +630,22 @@ export function QueryBuilderProvider({
|
||||
formulaData,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
...prevState.builder,
|
||||
queryFormulas: updatedFormulasBuilderData,
|
||||
},
|
||||
};
|
||||
});
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
setSupersetQuery((prevState) => {
|
||||
const updatedFormulasBuilderData = updateQueryBuilderData(
|
||||
prevState.builder.queryFormulas,
|
||||
index,
|
||||
formulaData,
|
||||
);
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
builder: {
|
||||
@ -518,6 +674,7 @@ export function QueryBuilderProvider({
|
||||
query: Partial<Query>,
|
||||
searchParams?: Record<string, unknown>,
|
||||
redirectingUrl?: typeof ROUTES[keyof typeof ROUTES],
|
||||
shallStringify?: boolean,
|
||||
) => {
|
||||
const queryType =
|
||||
!query.queryType || !Object.values(EQueryType).includes(query.queryType)
|
||||
@ -569,7 +726,12 @@ export function QueryBuilderProvider({
|
||||
|
||||
if (searchParams) {
|
||||
Object.keys(searchParams).forEach((param) =>
|
||||
urlQuery.set(param, JSON.stringify(searchParams[param])),
|
||||
urlQuery.set(
|
||||
param,
|
||||
shallStringify
|
||||
? JSON.stringify(searchParams[param])
|
||||
: (searchParams[param] as string),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -657,6 +819,10 @@ export function QueryBuilderProvider({
|
||||
...prevState,
|
||||
unit,
|
||||
}));
|
||||
setSupersetQuery((prevState) => ({
|
||||
...prevState,
|
||||
unit,
|
||||
}));
|
||||
},
|
||||
[setCurrentQuery],
|
||||
);
|
||||
@ -669,6 +835,14 @@ export function QueryBuilderProvider({
|
||||
[currentQuery, queryType],
|
||||
);
|
||||
|
||||
const superQuery: Query = useMemo(
|
||||
() => ({
|
||||
...supersetQuery,
|
||||
queryType,
|
||||
}),
|
||||
[supersetQuery, queryType],
|
||||
);
|
||||
|
||||
const isEnabledQuery = useMemo(() => !!stagedQuery && !!panelType, [
|
||||
stagedQuery,
|
||||
panelType,
|
||||
@ -677,6 +851,8 @@ export function QueryBuilderProvider({
|
||||
const contextValues: QueryBuilderContextType = useMemo(
|
||||
() => ({
|
||||
currentQuery: query,
|
||||
supersetQuery: superQuery,
|
||||
setSupersetQuery,
|
||||
stagedQuery,
|
||||
initialDataSource,
|
||||
panelType,
|
||||
@ -702,6 +878,7 @@ export function QueryBuilderProvider({
|
||||
}),
|
||||
[
|
||||
query,
|
||||
superQuery,
|
||||
stagedQuery,
|
||||
initialDataSource,
|
||||
panelType,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { Format } from 'container/NewWidget/RightContainer/types';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import {
|
||||
IBuilderFormula,
|
||||
IBuilderQuery,
|
||||
@ -187,6 +188,8 @@ export type QueryBuilderData = {
|
||||
export type QueryBuilderContextType = {
|
||||
currentQuery: Query;
|
||||
stagedQuery: Query | null;
|
||||
supersetQuery: Query;
|
||||
setSupersetQuery: Dispatch<SetStateAction<QueryState>>;
|
||||
initialDataSource: DataSource | null;
|
||||
panelType: PANEL_TYPES | null;
|
||||
isEnabledQuery: boolean;
|
||||
@ -217,6 +220,7 @@ export type QueryBuilderContextType = {
|
||||
query: Query,
|
||||
searchParams?: Record<string, unknown>,
|
||||
redirectToUrl?: typeof ROUTES[keyof typeof ROUTES],
|
||||
shallStringify?: boolean,
|
||||
) => void;
|
||||
handleRunQuery: () => void;
|
||||
resetQuery: (newCurrentQuery?: QueryState) => void;
|
||||
|
Loading…
x
Reference in New Issue
Block a user