diff --git a/frontend/src/constants/panelTypes.ts b/frontend/src/constants/panelTypes.ts index 7476b20783..8892f0fcbe 100644 --- a/frontend/src/constants/panelTypes.ts +++ b/frontend/src/constants/panelTypes.ts @@ -40,4 +40,5 @@ export const getComponentForPanelType = ( export const AVAILABLE_EXPORT_PANEL_TYPES = [ PANEL_TYPES.TIME_SERIES, PANEL_TYPES.TABLE, + PANEL_TYPES.LIST, ]; diff --git a/frontend/src/container/LogsExplorerViews/index.tsx b/frontend/src/container/LogsExplorerViews/index.tsx index 28e199066a..ced6556f44 100644 --- a/frontend/src/container/LogsExplorerViews/index.tsx +++ b/frontend/src/container/LogsExplorerViews/index.tsx @@ -37,7 +37,7 @@ import { useNotifications } from 'hooks/useNotifications'; import useUrlQueryData from 'hooks/useUrlQueryData'; import { FlatLogData } from 'lib/logs/flatLogData'; 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 { SELECTED_VIEWS } from 'pages/LogsExplorer/utils'; import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; @@ -117,6 +117,12 @@ function LogsExplorerViews({ return stagedQuery.builder.queryData.find((item) => !item.disabled) || null; }, [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 timestampOrderBy = listQuery?.orderBy.find( (item) => item.columnName === 'timestamp', @@ -174,10 +180,10 @@ function LogsExplorerViews({ () => updateAllQueriesOperators( currentQuery || initialQueriesMap.logs, - PANEL_TYPES.TIME_SERIES, + selectedPanelType, DataSource.LOGS, ), - [currentQuery, updateAllQueriesOperators], + [currentQuery, selectedPanelType, updateAllQueriesOperators], ); const handleModeChange = (panelType: PANEL_TYPES): void => { @@ -309,6 +315,14 @@ function LogsExplorerViews({ isLoading: isUpdateDashboardLoading, } = useUpdateDashboard(); + const getUpdatedQueryForExport = useCallback((): Query => { + const updatedQuery = cloneDeep(currentQuery); + + set(updatedQuery, 'builder.queryData[0].pageSize', 10); + + return updatedQuery; + }, [currentQuery]); + const handleExport = useCallback( (dashboard: Dashboard | null): void => { if (!dashboard || !panelType) return; @@ -319,11 +333,17 @@ function LogsExplorerViews({ const widgetId = v4(); + const query = + panelType === PANEL_TYPES.LIST + ? getUpdatedQueryForExport() + : exportDefaultQuery; + const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( dashboard, - exportDefaultQuery, + query, widgetId, panelTypeParam, + options.selectColumns, ); updateDashboard(updatedDashboard, { @@ -353,7 +373,7 @@ function LogsExplorerViews({ } const dashboardEditView = generateExportToDashboardLink({ - query: exportDefaultQuery, + query, panelType: panelTypeParam, dashboardId: data.payload?.uuid || '', widgetId, @@ -365,7 +385,9 @@ function LogsExplorerViews({ }); }, [ + getUpdatedQueryForExport, exportDefaultQuery, + options.selectColumns, history, notifications, panelType, @@ -460,12 +482,6 @@ function LogsExplorerViews({ selectedView, ]); - const { options, config } = useOptionsMenu({ - storageKey: LOCALSTORAGE.LOGS_LIST_OPTIONS, - dataSource: initialDataSource || DataSource.METRICS, - aggregateOperator: listQuery?.aggregateOperator || StringOperators.NOOP, - }); - const chartData = useMemo(() => { if (!stagedQuery) return []; diff --git a/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss b/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss index 5fa4ce0cda..6317ea2134 100644 --- a/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss +++ b/frontend/src/container/LogsPanelTable/LogsPanelComponent.styles.scss @@ -5,7 +5,7 @@ height: 100%; .resize-table { - height: calc(100% - 40px); + height: calc(100% - 70px); overflow: scroll; overflow-x: hidden; diff --git a/frontend/src/container/NewWidget/utils.ts b/frontend/src/container/NewWidget/utils.ts index a8ac095d1e..b840d6e71a 100644 --- a/frontend/src/container/NewWidget/utils.ts +++ b/frontend/src/container/NewWidget/utils.ts @@ -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]: { [DataSource.LOGS]: { builder: { diff --git a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss index 0787972eec..74e80f8764 100644 --- a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss +++ b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss @@ -5,7 +5,7 @@ height: 100%; .resize-table { - height: calc(100% - 40px); + height: calc(100% - 70px); overflow: scroll; overflow-x: hidden; diff --git a/frontend/src/hooks/dashboard/utils.ts b/frontend/src/hooks/dashboard/utils.ts index ad3fadd8b9..ed61e25581 100644 --- a/frontend/src/hooks/dashboard/utils.ts +++ b/frontend/src/hooks/dashboard/utils.ts @@ -1,43 +1,61 @@ import { PANEL_TYPES } from 'constants/queryBuilder'; +import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils'; import { Dashboard } from 'types/api/dashboard/getAll'; +import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { Query } from 'types/api/queryBuilder/queryBuilderData'; +const baseLogsSelectedColumns = { + dataType: 'string', + type: '', + name: 'timestamp', +}; + export const addEmptyWidgetInDashboardJSONWithQuery = ( dashboard: Dashboard, query: Query, widgetId: string, - panelTypes?: PANEL_TYPES, -): Dashboard => ({ - ...dashboard, - data: { - ...dashboard.data, - layout: [ - { - i: widgetId, - w: 6, - x: 0, - h: 6, - y: 0, - }, - ...(dashboard?.data?.layout || []), - ], - widgets: [ - ...(dashboard?.data?.widgets || []), - { - id: widgetId, - query, - description: '', - isStacked: false, - nullZeroValues: '', - opacity: '', - title: '', - timePreferance: 'GLOBAL_TIME', - panelTypes: panelTypes || PANEL_TYPES.TIME_SERIES, - softMax: null, - softMin: null, - selectedLogFields: [], - selectedTracesFields: [], - }, - ], - }, -}); + panelType?: PANEL_TYPES, + selectedColumns?: BaseAutocompleteData[] | null, +): Dashboard => { + const logsSelectedColumns = [ + baseLogsSelectedColumns, + ...convertKeysToColumnFields(selectedColumns || []), + ]; + + return { + ...dashboard, + data: { + ...dashboard.data, + layout: [ + { + i: widgetId, + w: 6, + x: 0, + h: 6, + y: 0, + }, + ...(dashboard?.data?.layout || []), + ], + widgets: [ + ...(dashboard?.data?.widgets || []), + { + id: widgetId, + query, + description: '', + isStacked: false, + nullZeroValues: '', + opacity: '', + title: '', + timePreferance: 'GLOBAL_TIME', + panelTypes: panelType || PANEL_TYPES.TIME_SERIES, + softMax: null, + softMin: null, + selectedLogFields: + panelType === PANEL_TYPES.LIST ? logsSelectedColumns : [], + selectedTracesFields: + panelType === PANEL_TYPES.LIST ? selectedColumns || [] : [], + }, + ], + }, + }; +}; diff --git a/frontend/src/pages/TracesExplorer/index.tsx b/frontend/src/pages/TracesExplorer/index.tsx index 30dc747345..ab022bfeee 100644 --- a/frontend/src/pages/TracesExplorer/index.tsx +++ b/frontend/src/pages/TracesExplorer/index.tsx @@ -5,12 +5,15 @@ import * as Sentry from '@sentry/react'; import { Button, Card, Tabs, Tooltip } from 'antd'; import axios from 'axios'; import ExplorerCard from 'components/ExplorerCard/ExplorerCard'; +import { LOCALSTORAGE } from 'constants/localStorage'; import { AVAILABLE_EXPORT_PANEL_TYPES } from 'constants/panelTypes'; import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper'; import ExportPanel from 'container/ExportPanel'; +import { useOptionsMenu } from 'container/OptionsMenu'; import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions'; import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2'; +import { defaultSelectedColumns } from 'container/TracesExplorer/ListView/configs'; import QuerySection from 'container/TracesExplorer/QuerySection'; import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard'; import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils'; @@ -20,9 +23,11 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; +import { cloneDeep, set } from 'lodash-es'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Dashboard } from 'types/api/dashboard/getAll'; +import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { DataSource } from 'types/common/queryBuilder'; import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink'; import { v4 } from 'uuid'; @@ -42,6 +47,15 @@ function TracesExplorer(): JSX.Element { stagedQuery, } = useQueryBuilder(); + const { options } = useOptionsMenu({ + storageKey: LOCALSTORAGE.TRACES_LIST_OPTIONS, + dataSource: DataSource.TRACES, + aggregateOperator: 'noop', + initialOptions: { + selectColumns: defaultSelectedColumns, + }, + }); + const currentPanelType = useGetPanelTypesQueryParam(); const { handleExplorerTabChange } = useHandleExplorerTabChange(); @@ -101,6 +115,18 @@ function TracesExplorer(): JSX.Element { 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( (dashboard: Dashboard | null): void => { if (!dashboard || !panelType) return; @@ -111,11 +137,17 @@ function TracesExplorer(): JSX.Element { const widgetId = v4(); + const query = + panelType === PANEL_TYPES.LIST + ? getUpdatedQueryForExport() + : exportDefaultQuery; + const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery( dashboard, - exportDefaultQuery, + query, widgetId, panelTypeParam, + options.selectColumns, ); updateDashboard(updatedDashboard, { @@ -144,7 +176,7 @@ function TracesExplorer(): JSX.Element { return; } const dashboardEditView = generateExportToDashboardLink({ - query: exportDefaultQuery, + query, panelType: panelTypeParam, dashboardId: data.payload?.uuid || '', widgetId, @@ -161,6 +193,7 @@ function TracesExplorer(): JSX.Element { }, }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [exportDefaultQuery, notifications, panelType, updateDashboard], ); diff --git a/frontend/src/types/api/queryBuilder/queryBuilderData.ts b/frontend/src/types/api/queryBuilder/queryBuilderData.ts index 6a54254617..832bd09411 100644 --- a/frontend/src/types/api/queryBuilder/queryBuilderData.ts +++ b/frontend/src/types/api/queryBuilder/queryBuilderData.ts @@ -74,6 +74,7 @@ export type IBuilderQuery = { legend: string; pageSize?: number; offset?: number; + selectColumns?: BaseAutocompleteData[]; }; export interface IClickHouseQuery {