feat: [5038] enable list view - add to dashboard (#5268)

* feat: [5038] enable list view - add to dashboard

* feat: pass page size for list view export
This commit is contained in:
Yunus M 2024-06-20 17:05:18 +05:30 committed by GitHub
parent 64e06ab3f9
commit 38b1de5ccc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 119 additions and 94 deletions

View File

@ -40,4 +40,5 @@ export const getComponentForPanelType = (
export const AVAILABLE_EXPORT_PANEL_TYPES = [ export const AVAILABLE_EXPORT_PANEL_TYPES = [
PANEL_TYPES.TIME_SERIES, PANEL_TYPES.TIME_SERIES,
PANEL_TYPES.TABLE, PANEL_TYPES.TABLE,
PANEL_TYPES.LIST,
]; ];

View File

@ -37,7 +37,7 @@ import { useNotifications } from 'hooks/useNotifications';
import useUrlQueryData from 'hooks/useUrlQueryData'; import useUrlQueryData from 'hooks/useUrlQueryData';
import { FlatLogData } from 'lib/logs/flatLogData'; import { FlatLogData } from 'lib/logs/flatLogData';
import { getPaginationQueryData } from 'lib/newQueryBuilder/getPaginationQueryData'; import { getPaginationQueryData } from 'lib/newQueryBuilder/getPaginationQueryData';
import { defaultTo, isEmpty, omit } from 'lodash-es'; import { cloneDeep, defaultTo, isEmpty, omit, set } from 'lodash-es';
import { Sliders } from 'lucide-react'; import { Sliders } from 'lucide-react';
import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils'; import { SELECTED_VIEWS } from 'pages/LogsExplorer/utils';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
@ -117,6 +117,12 @@ function LogsExplorerViews({
return stagedQuery.builder.queryData.find((item) => !item.disabled) || null; return stagedQuery.builder.queryData.find((item) => !item.disabled) || null;
}, [stagedQuery]); }, [stagedQuery]);
const { options, config } = useOptionsMenu({
storageKey: LOCALSTORAGE.LOGS_LIST_OPTIONS,
dataSource: initialDataSource || DataSource.LOGS,
aggregateOperator: listQuery?.aggregateOperator || StringOperators.NOOP,
});
const orderByTimestamp: OrderByPayload | null = useMemo(() => { const orderByTimestamp: OrderByPayload | null = useMemo(() => {
const timestampOrderBy = listQuery?.orderBy.find( const timestampOrderBy = listQuery?.orderBy.find(
(item) => item.columnName === 'timestamp', (item) => item.columnName === 'timestamp',
@ -174,10 +180,10 @@ function LogsExplorerViews({
() => () =>
updateAllQueriesOperators( updateAllQueriesOperators(
currentQuery || initialQueriesMap.logs, currentQuery || initialQueriesMap.logs,
PANEL_TYPES.TIME_SERIES, selectedPanelType,
DataSource.LOGS, DataSource.LOGS,
), ),
[currentQuery, updateAllQueriesOperators], [currentQuery, selectedPanelType, updateAllQueriesOperators],
); );
const handleModeChange = (panelType: PANEL_TYPES): void => { const handleModeChange = (panelType: PANEL_TYPES): void => {
@ -309,6 +315,14 @@ function LogsExplorerViews({
isLoading: isUpdateDashboardLoading, isLoading: isUpdateDashboardLoading,
} = useUpdateDashboard(); } = useUpdateDashboard();
const getUpdatedQueryForExport = useCallback((): Query => {
const updatedQuery = cloneDeep(currentQuery);
set(updatedQuery, 'builder.queryData[0].pageSize', 10);
return updatedQuery;
}, [currentQuery]);
const handleExport = useCallback( const handleExport = useCallback(
(dashboard: Dashboard | null): void => { (dashboard: Dashboard | null): void => {
if (!dashboard || !panelType) return; if (!dashboard || !panelType) return;
@ -319,11 +333,17 @@ function LogsExplorerViews({
const widgetId = v4(); const widgetId = v4();
const query =
panelType === PANEL_TYPES.LIST
? getUpdatedQueryForExport()
: exportDefaultQuery;
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
dashboard, dashboard,
exportDefaultQuery, query,
widgetId, widgetId,
panelTypeParam, panelTypeParam,
options.selectColumns,
); );
updateDashboard(updatedDashboard, { updateDashboard(updatedDashboard, {
@ -353,7 +373,7 @@ function LogsExplorerViews({
} }
const dashboardEditView = generateExportToDashboardLink({ const dashboardEditView = generateExportToDashboardLink({
query: exportDefaultQuery, query,
panelType: panelTypeParam, panelType: panelTypeParam,
dashboardId: data.payload?.uuid || '', dashboardId: data.payload?.uuid || '',
widgetId, widgetId,
@ -365,7 +385,9 @@ function LogsExplorerViews({
}); });
}, },
[ [
getUpdatedQueryForExport,
exportDefaultQuery, exportDefaultQuery,
options.selectColumns,
history, history,
notifications, notifications,
panelType, panelType,
@ -460,12 +482,6 @@ function LogsExplorerViews({
selectedView, selectedView,
]); ]);
const { options, config } = useOptionsMenu({
storageKey: LOCALSTORAGE.LOGS_LIST_OPTIONS,
dataSource: initialDataSource || DataSource.METRICS,
aggregateOperator: listQuery?.aggregateOperator || StringOperators.NOOP,
});
const chartData = useMemo(() => { const chartData = useMemo(() => {
if (!stagedQuery) return []; if (!stagedQuery) return [];

View File

@ -5,7 +5,7 @@
height: 100%; height: 100%;
.resize-table { .resize-table {
height: calc(100% - 40px); height: calc(100% - 70px);
overflow: scroll; overflow: scroll;
overflow-x: hidden; overflow-x: hidden;

View File

@ -189,50 +189,6 @@ export const panelTypeDataSourceFormValuesMap: Record<
}, },
}, },
}, },
[PANEL_TYPES.HISTOGRAM]: {
[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]: { [PANEL_TYPES.TABLE]: {
[DataSource.LOGS]: { [DataSource.LOGS]: {
builder: { builder: {

View File

@ -5,7 +5,7 @@
height: 100%; height: 100%;
.resize-table { .resize-table {
height: calc(100% - 40px); height: calc(100% - 70px);
overflow: scroll; overflow: scroll;
overflow-x: hidden; overflow-x: hidden;

View File

@ -1,13 +1,28 @@
import { PANEL_TYPES } from 'constants/queryBuilder'; import { PANEL_TYPES } from 'constants/queryBuilder';
import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils';
import { Dashboard } from 'types/api/dashboard/getAll'; import { Dashboard } from 'types/api/dashboard/getAll';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';
const baseLogsSelectedColumns = {
dataType: 'string',
type: '',
name: 'timestamp',
};
export const addEmptyWidgetInDashboardJSONWithQuery = ( export const addEmptyWidgetInDashboardJSONWithQuery = (
dashboard: Dashboard, dashboard: Dashboard,
query: Query, query: Query,
widgetId: string, widgetId: string,
panelTypes?: PANEL_TYPES, panelType?: PANEL_TYPES,
): Dashboard => ({ selectedColumns?: BaseAutocompleteData[] | null,
): Dashboard => {
const logsSelectedColumns = [
baseLogsSelectedColumns,
...convertKeysToColumnFields(selectedColumns || []),
];
return {
...dashboard, ...dashboard,
data: { data: {
...dashboard.data, ...dashboard.data,
@ -32,12 +47,15 @@ export const addEmptyWidgetInDashboardJSONWithQuery = (
opacity: '', opacity: '',
title: '', title: '',
timePreferance: 'GLOBAL_TIME', timePreferance: 'GLOBAL_TIME',
panelTypes: panelTypes || PANEL_TYPES.TIME_SERIES, panelTypes: panelType || PANEL_TYPES.TIME_SERIES,
softMax: null, softMax: null,
softMin: null, softMin: null,
selectedLogFields: [], selectedLogFields:
selectedTracesFields: [], panelType === PANEL_TYPES.LIST ? logsSelectedColumns : [],
selectedTracesFields:
panelType === PANEL_TYPES.LIST ? selectedColumns || [] : [],
}, },
], ],
}, },
}); };
};

View File

@ -5,12 +5,15 @@ import * as Sentry from '@sentry/react';
import { Button, Card, Tabs, Tooltip } from 'antd'; import { Button, Card, Tabs, Tooltip } from 'antd';
import axios from 'axios'; import axios from 'axios';
import ExplorerCard from 'components/ExplorerCard/ExplorerCard'; import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
import { LOCALSTORAGE } from 'constants/localStorage';
import { AVAILABLE_EXPORT_PANEL_TYPES } from 'constants/panelTypes'; import { AVAILABLE_EXPORT_PANEL_TYPES } from 'constants/panelTypes';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper'; import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper';
import ExportPanel from 'container/ExportPanel'; import ExportPanel from 'container/ExportPanel';
import { useOptionsMenu } from 'container/OptionsMenu';
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions'; import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2'; import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
import { defaultSelectedColumns } from 'container/TracesExplorer/ListView/configs';
import QuerySection from 'container/TracesExplorer/QuerySection'; import QuerySection from 'container/TracesExplorer/QuerySection';
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard'; import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils'; import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
@ -20,9 +23,11 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import history from 'lib/history';
import { cloneDeep, set } from 'lodash-es';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { Dashboard } from 'types/api/dashboard/getAll'; import { Dashboard } from 'types/api/dashboard/getAll';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink'; import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
@ -42,6 +47,15 @@ function TracesExplorer(): JSX.Element {
stagedQuery, stagedQuery,
} = useQueryBuilder(); } = useQueryBuilder();
const { options } = useOptionsMenu({
storageKey: LOCALSTORAGE.TRACES_LIST_OPTIONS,
dataSource: DataSource.TRACES,
aggregateOperator: 'noop',
initialOptions: {
selectColumns: defaultSelectedColumns,
},
});
const currentPanelType = useGetPanelTypesQueryParam(); const currentPanelType = useGetPanelTypesQueryParam();
const { handleExplorerTabChange } = useHandleExplorerTabChange(); const { handleExplorerTabChange } = useHandleExplorerTabChange();
@ -101,6 +115,18 @@ function TracesExplorer(): JSX.Element {
const { mutate: updateDashboard, isLoading } = useUpdateDashboard(); const { mutate: updateDashboard, isLoading } = useUpdateDashboard();
const getUpdatedQueryForExport = (): Query => {
const updatedQuery = cloneDeep(currentQuery);
set(
updatedQuery,
'builder.queryData[0].selectColumns',
options.selectColumns,
);
return updatedQuery;
};
const handleExport = useCallback( const handleExport = useCallback(
(dashboard: Dashboard | null): void => { (dashboard: Dashboard | null): void => {
if (!dashboard || !panelType) return; if (!dashboard || !panelType) return;
@ -111,11 +137,17 @@ function TracesExplorer(): JSX.Element {
const widgetId = v4(); const widgetId = v4();
const query =
panelType === PANEL_TYPES.LIST
? getUpdatedQueryForExport()
: exportDefaultQuery;
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
dashboard, dashboard,
exportDefaultQuery, query,
widgetId, widgetId,
panelTypeParam, panelTypeParam,
options.selectColumns,
); );
updateDashboard(updatedDashboard, { updateDashboard(updatedDashboard, {
@ -144,7 +176,7 @@ function TracesExplorer(): JSX.Element {
return; return;
} }
const dashboardEditView = generateExportToDashboardLink({ const dashboardEditView = generateExportToDashboardLink({
query: exportDefaultQuery, query,
panelType: panelTypeParam, panelType: panelTypeParam,
dashboardId: data.payload?.uuid || '', dashboardId: data.payload?.uuid || '',
widgetId, widgetId,
@ -161,6 +193,7 @@ function TracesExplorer(): JSX.Element {
}, },
}); });
}, },
// eslint-disable-next-line react-hooks/exhaustive-deps
[exportDefaultQuery, notifications, panelType, updateDashboard], [exportDefaultQuery, notifications, panelType, updateDashboard],
); );

View File

@ -74,6 +74,7 @@ export type IBuilderQuery = {
legend: string; legend: string;
pageSize?: number; pageSize?: number;
offset?: number; offset?: number;
selectColumns?: BaseAutocompleteData[];
}; };
export interface IClickHouseQuery { export interface IClickHouseQuery {