diff --git a/frontend/src/components/QueryBuilderV2/QueryBuilderV2.styles.scss b/frontend/src/components/QueryBuilderV2/QueryBuilderV2.styles.scss index 5cff9d7006d4..03b4a57a6c4a 100644 --- a/frontend/src/components/QueryBuilderV2/QueryBuilderV2.styles.scss +++ b/frontend/src/components/QueryBuilderV2/QueryBuilderV2.styles.scss @@ -5,10 +5,12 @@ width: 100%; + border-bottom: 1px solid var(--bg-slate-400); + border-top: 1px solid var(--bg-slate-400); + font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif; - border: 1px solid var(--bg-slate-400); border-right: none; border-left: none; @@ -90,6 +92,27 @@ } } + .where-clause-view { + .qb-content-section { + .qb-elements-container { + margin-left: 0px; + + .code-mirror-where-clause, + .query-aggregation-container, + .query-add-ons, + .metrics-aggregation-section-content { + &::before { + display: none; + } + + &::after { + display: none; + } + } + } + } + } + .query-names-section { display: flex; flex-direction: column; diff --git a/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx b/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx index c2b6b7c738c2..7093b0d3bffc 100644 --- a/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryBuilderV2.tsx @@ -18,6 +18,7 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({ queryComponents, isListViewPanel = false, showFunctions = false, + showOnlyWhereClause = false, version, }: QueryBuilderProps): JSX.Element { const { @@ -67,12 +68,13 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({ queryComponents={queryComponents} version={version} isAvailableToDisable={false} - showSpanScopeSelector + showSpanScopeSelector={initialDataSource === DataSource.TRACES} queryVariant={config?.queryVariant || 'dropdown'} + showOnlyWhereClause={showOnlyWhereClause} /> ))} - {currentQuery.builder.queryFormulas.length > 0 && ( + {!showOnlyWhereClause && currentQuery.builder.queryFormulas.length > 0 && (
{currentQuery.builder.queryFormulas.map((formula, index) => { const query = @@ -94,25 +96,29 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({
)} - + {!showOnlyWhereClause && ( + + )} -
- {currentQuery.builder.queryData.map((query) => ( -
- {query.queryName} -
- ))} + {!showOnlyWhereClause && ( +
+ {currentQuery.builder.queryData.map((query) => ( +
+ {query.queryName} +
+ ))} - {currentQuery.builder.queryFormulas.map((formula) => ( -
- {formula.queryName} -
- ))} -
+ {currentQuery.builder.queryFormulas.map((formula) => ( +
+ {formula.queryName} +
+ ))} +
+ )} ); diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx index 3ccfb5f34c9d..7e06c98b368a 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QueryAddOns/QueryAddOns.tsx @@ -4,6 +4,7 @@ import { Button, Radio, RadioChangeEvent } from 'antd'; import InputWithLabel from 'components/InputWithLabel/InputWithLabel'; import { GroupByFilter } from 'container/QueryBuilder/filters/GroupByFilter/GroupByFilter'; import { OrderByFilter } from 'container/QueryBuilder/filters/OrderByFilter/OrderByFilter'; +import { ReduceToFilter } from 'container/QueryBuilder/filters/ReduceToFilter/ReduceToFilter'; import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations'; import { BarChart2, ScrollText, X } from 'lucide-react'; import { useCallback, useState } from 'react'; @@ -44,16 +45,23 @@ const ADD_ONS: Record = { label: 'Legend format', key: 'legend_format', }, + REDUCE_TO: { + icon: , + label: 'Reduce to', + key: 'reduce_to', + }, }; function QueryAddOns({ query, version, isListViewPanel, + showReduceTo, }: { query: IBuilderQuery; version: string; isListViewPanel: boolean; + showReduceTo: boolean; }): JSX.Element { const [selectedViews, setSelectedViews] = useState([]); @@ -87,6 +95,13 @@ function QueryAddOns({ [handleChangeQueryData], ); + const handleChangeReduceTo = useCallback( + (value: IBuilderQuery['reduceTo']) => { + handleChangeQueryData('reduceTo', value); + }, + [handleChangeQueryData], + ); + const handleRemoveView = useCallback( (key: string): void => { setSelectedViews(selectedViews.filter((view) => view.key !== key)); @@ -139,7 +154,7 @@ function QueryAddOns({ {selectedViews.find((view) => view.key === 'limit') && (
{ setSelectedViews(selectedViews.filter((view) => view.key !== 'limit')); @@ -167,10 +182,28 @@ function QueryAddOns({
)} + + {selectedViews.find((view) => view.key === 'reduce_to') && showReduceTo && ( +
+
+
Reduce to
+
+ +
+ +
+
+ )} + {selectedViews.find((view) => view.key === 'legend_format') && (
{ setSelectedViews( @@ -189,22 +222,24 @@ function QueryAddOns({ onChange={handleOptionClick} value={selectedViews} > - {Object.values(ADD_ONS).map((addOn) => ( - view.key === addOn.key) - ? 'selected-view tab' - : 'tab' - } - value={addOn} - > -
- {addOn.icon} - {addOn.label} -
-
- ))} + {Object.values(ADD_ONS) + .filter((addOn) => addOn.key !== 'reduce_to' || showReduceTo) + .map((addOn) => ( + view.key === addOn.key) + ? 'selected-view tab' + : 'tab' + } + value={addOn} + > +
+ {addOn.icon} + {addOn.label} +
+
+ ))}
@@ -212,60 +247,3 @@ function QueryAddOns({ } export default QueryAddOns; - -/* - - -
- - {selectedView.label} -
-
- -
- - {selectedView.label} -
-
- -
- - {selectedView.label} -
-
- -
- - {selectedView.label} -
-
- -
- - {selectedView.label} -
-
- -*/ diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QueryAggregation/QueryAggregation.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QueryAggregation/QueryAggregation.tsx index af710ac80eaf..3e4ced461143 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QueryAggregation/QueryAggregation.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QueryAggregation/QueryAggregation.tsx @@ -1,17 +1,10 @@ import './QueryAggregation.styles.scss'; import InputWithLabel from 'components/InputWithLabel/InputWithLabel'; -import { DataSource } from 'types/common/queryBuilder'; import QueryAggregationSelect from './QueryAggregationSelect'; -function QueryAggregationOptions({ - source, -}: { - source: DataSource; -}): JSX.Element { - console.log('source', source); - +function QueryAggregationOptions(): JSX.Element { return (
diff --git a/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx b/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx index 56d7c3e28b3a..1db915371d23 100644 --- a/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx +++ b/frontend/src/components/QueryBuilderV2/QueryV2/QueryV2.tsx @@ -1,12 +1,14 @@ import { Dropdown } from 'antd'; +import cx from 'classnames'; import { ENTITY_VERSION_V4 } from 'constants/app'; +import { PANEL_TYPES } from 'constants/queryBuilder'; import QBEntityOptions from 'container/QueryBuilder/components/QBEntityOptions/QBEntityOptions'; import { QueryProps } from 'container/QueryBuilder/components/Query/Query.interfaces'; import SpanScopeSelector from 'container/QueryBuilder/filters/QueryBuilderSearchV2/SpanScopeSelector'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations'; import { Copy, Ellipsis, Trash } from 'lucide-react'; -import { memo, useCallback, useState } from 'react'; +import { memo, useCallback, useMemo, useState } from 'react'; import { DataSource } from 'types/common/queryBuilder'; import MetricsAggregateSection from './MerticsAggregateSection/MetricsAggregateSection'; @@ -20,18 +22,16 @@ export const QueryV2 = memo(function QueryV2({ queryVariant, query, filterConfigs, - queryComponents, isListViewPanel = false, version, showSpanScopeSelector = false, + showOnlyWhereClause = false, }: QueryProps): JSX.Element { - const { cloneQuery } = useQueryBuilder(); + const { cloneQuery, panelType } = useQueryBuilder(); const showFunctions = query?.functions?.length > 0; const { dataSource } = query; - console.log('queryComponents', queryComponents); - const [isCollapsed, setIsCollapsed] = useState(false); const { @@ -59,62 +59,73 @@ export const QueryV2 = memo(function QueryV2({ cloneQuery('query', query); }; - return ( -
-
-
-
-
- -
+ const showReduceTo = useMemo( + () => + dataSource === DataSource.METRICS && + (panelType === PANEL_TYPES.TABLE || + panelType === PANEL_TYPES.PIE || + panelType === PANEL_TYPES.VALUE), + [dataSource, panelType], + ); - , - onClick: handleCloneEntity, - }, - { - label: 'Delete', - key: 'delete-query', - icon: , - onClick: handleDeleteQuery, - }, - ], - }} - placement="bottomRight" - > - - + return ( +
+
+ {!showOnlyWhereClause && ( +
+
+
+ +
+ + , + onClick: handleCloneEntity, + }, + { + label: 'Delete', + key: 'delete-query', + icon: , + onClick: handleDeleteQuery, + }, + ], + }} + placement="bottomRight" + > + + +
-
+ )}
@@ -136,13 +147,20 @@ export const QueryV2 = memo(function QueryV2({
- + {!showOnlyWhereClause && } - {dataSource === DataSource.METRICS && ( + {!showOnlyWhereClause && dataSource === DataSource.METRICS && ( )} - + {!showOnlyWhereClause && ( + + )}
diff --git a/frontend/src/container/DownloadV2/DownloadV2.tsx b/frontend/src/container/DownloadV2/DownloadV2.tsx index 95630efcb992..c1dc9182dd63 100644 --- a/frontend/src/container/DownloadV2/DownloadV2.tsx +++ b/frontend/src/container/DownloadV2/DownloadV2.tsx @@ -69,7 +69,7 @@ function Download({ data, isLoading, fileName }: DownloadProps): JSX.Element { } > + /> ); return ( } - > - Add to Dashboard - + /> ); }, [disabled, isOneChartPerQuery, onAddToDashboard, splitedQueries]); @@ -797,41 +744,31 @@ function ExplorerOptions({ >
)} {!isExplorerOptionHidden && ( -
+
showSearch @@ -872,49 +809,23 @@ function ExplorerOptions({
-
-
{alertButton} {dashboardButton}
-
- {/* Hide the info icon for metrics explorer until we get the docs link */} - {!isMetricsExplorer && ( - - {infoIconText} - - {' '} - here - {' '} -
- } - > - - - )} - -
)} ( - {t('alert_form_step2', { step: step2Label })} - +
{renderTabs(alertType)}
{renderQuerySection(currentTab)}
diff --git a/frontend/src/container/LogExplorerQuerySection/LogsExplorerQuerySection.styles.scss b/frontend/src/container/LogExplorerQuerySection/LogsExplorerQuerySection.styles.scss index db79557a712b..9dac004f81a6 100644 --- a/frontend/src/container/LogExplorerQuerySection/LogsExplorerQuerySection.styles.scss +++ b/frontend/src/container/LogExplorerQuerySection/LogsExplorerQuerySection.styles.scss @@ -1,7 +1,5 @@ .qb-search-view-container { padding: 8px 16px; - border-top: 1px solid var(--bg-slate-400, #1d212d); - border-bottom: 1px solid var(--bg-slate-400, #1d212d); .ant-select-selector { border-radius: 2px; @@ -20,9 +18,6 @@ .lightMode { .qb-search-view-container { - border-top: 1px solid var(--bg-vanilla-300); - border-bottom: 1px solid var(--bg-vanilla-300); - .ant-select-selector { border-color: var(--bg-vanilla-300) !important; background-color: var(--bg-vanilla-100) !important; diff --git a/frontend/src/container/LogExplorerQuerySection/index.tsx b/frontend/src/container/LogExplorerQuerySection/index.tsx index 8b8418c745be..b491af6d6a83 100644 --- a/frontend/src/container/LogExplorerQuerySection/index.tsx +++ b/frontend/src/container/LogExplorerQuerySection/index.tsx @@ -8,18 +8,15 @@ import { } from 'constants/queryBuilder'; import ExplorerOrderBy from 'container/ExplorerOrderBy'; import { OrderByFilterProps } from 'container/QueryBuilder/filters/OrderByFilter/OrderByFilter.interfaces'; -import QueryBuilderSearchV2 from 'container/QueryBuilder/filters/QueryBuilderSearchV2/QueryBuilderSearchV2'; import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces'; import { useGetPanelTypesQueryParam } from 'hooks/queryBuilder/useGetPanelTypesQueryParam'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; -import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations'; import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { ExplorerViews, prepareQueryWithDefaultTimestamp, } from 'pages/LogsExplorer/utils'; import { memo, useCallback, useMemo } from 'react'; -import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { DataSource } from 'types/common/queryBuilder'; function LogExplorerQuerySection({ @@ -27,9 +24,7 @@ function LogExplorerQuerySection({ }: { selectedView: ExplorerViews; }): JSX.Element { - const { currentQuery, updateAllQueriesOperators } = useQueryBuilder(); - - const query = currentQuery?.builder?.queryData[0] || null; + const { updateAllQueriesOperators } = useQueryBuilder(); const panelTypes = useGetPanelTypesQueryParam(PANEL_TYPES.LIST); const defaultValue = useMemo(() => { @@ -58,13 +53,6 @@ function LogExplorerQuerySection({ return config; }, [panelTypes]); - const { handleChangeQueryData } = useQueryOperations({ - index: 0, - query, - filterConfigs, - entityVersion: '', - }); - const renderOrderBy = useCallback( ({ query, onChange }: OrderByFilterProps): JSX.Element => ( @@ -79,38 +67,16 @@ function LogExplorerQuerySection({ [panelTypes, renderOrderBy], ); - const handleChangeTagFilters = useCallback( - (value: IBuilderQuery['filters']) => { - handleChangeQueryData('filters', value); - }, - [handleChangeQueryData], - ); - return ( - <> - {selectedView === ExplorerViews.LIST && ( -
- -
- )} - - {(selectedView === ExplorerViews.TABLE || - selectedView === ExplorerViews.TIMESERIES || - selectedView === ExplorerViews.CLICKHOUSE) && ( - - )} - + ); } diff --git a/frontend/src/container/LogsExplorerViews/LogsExplorerViews.styles.scss b/frontend/src/container/LogsExplorerViews/LogsExplorerViews.styles.scss index b81b327301d4..6944bba6f089 100644 --- a/frontend/src/container/LogsExplorerViews/LogsExplorerViews.styles.scss +++ b/frontend/src/container/LogsExplorerViews/LogsExplorerViews.styles.scss @@ -76,6 +76,12 @@ border: 1px solid var(--bg-slate-400); } + .order-by-container { + display: flex; + align-items: center; + gap: 8px; + } + .format-options-container { position: relative; } @@ -111,7 +117,35 @@ .tab-options-right { display: flex; align-items: center; - gap: 8px; + gap: 4px; + + .order-by-container { + display: flex; + align-items: center; + gap: 8px; + + .order-by-label { + color: var(--text-vanilla-400); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; /* 133.333% */ + + display: flex; + align-items: center; + gap: 4px; + } + + .order-by-select { + width: 100px; + + .ant-select-selector { + border: none; + box-shadow: none; + background-color: transparent; + } + } + } } .frequency-chart-view-controller { diff --git a/frontend/src/container/LogsExplorerViews/index.tsx b/frontend/src/container/LogsExplorerViews/index.tsx index 73dffb34150e..6120f0674694 100644 --- a/frontend/src/container/LogsExplorerViews/index.tsx +++ b/frontend/src/container/LogsExplorerViews/index.tsx @@ -1,7 +1,7 @@ /* eslint-disable sonarjs/cognitive-complexity */ import './LogsExplorerViews.styles.scss'; -import { Button, Switch, Typography } from 'antd'; +import { Button, Select, Switch, Typography } from 'antd'; import { getQueryStats, WsDataEvent } from 'api/common/getQueryStats'; import logEvent from 'api/common/logEvent'; import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig'; @@ -46,7 +46,7 @@ import { omit, set, } from 'lodash-es'; -import { Sliders } from 'lucide-react'; +import { ArrowUp10, Minus, Sliders } from 'lucide-react'; import { ExplorerViews } from 'pages/LogsExplorer/utils'; import { useTimezone } from 'providers/Timezone'; import { @@ -138,6 +138,8 @@ function LogsExplorerViewsContainer({ const [queryStats, setQueryStats] = useState(); const [listChartQuery, setListChartQuery] = useState(null); + const [orderDirection, setOrderDirection] = useState('asc'); + const listQuery = useMemo(() => { if (!stagedQuery || stagedQuery.builder.queryData.length < 1) return null; @@ -656,6 +658,23 @@ function LogsExplorerViewsContainer({
{selectedPanelType === PANEL_TYPES.LIST && ( <> +
+
+ Order by +
+ + setOrderDirection(value)} + options={[ + { label: 'Ascending', value: 'asc' }, + { label: 'Descending', value: 'desc' }, + ]} + /> +
+ { @@ -50,30 +39,19 @@ function QuerySection({ }; }, [panelTypes, renderOrderBy]); - console.log('query - section - selectedView', selectedView); - return ( - {/* {(selectedView === 'list' || selectedView === 'trace') && ( -
- - -
in
- - -
- )} - - {(selectedView === 'graph' || selectedView === 'table') && ( */} - {/* )} */}
); } diff --git a/frontend/src/container/TracesExplorer/TracesView/index.tsx b/frontend/src/container/TracesExplorer/TracesView/index.tsx index 0eafd11832df..cbae025191bc 100644 --- a/frontend/src/container/TracesExplorer/TracesView/index.tsx +++ b/frontend/src/container/TracesExplorer/TracesView/index.tsx @@ -1,4 +1,4 @@ -import { Typography } from 'antd'; +import { Select, Typography } from 'antd'; import logEvent from 'api/common/logEvent'; import { ResizeTable } from 'components/ResizeTable'; import { ENTITY_VERSION_V4 } from 'constants/app'; @@ -11,7 +11,8 @@ import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { Pagination } from 'hooks/queryPagination'; import useUrlQueryData from 'hooks/useUrlQueryData'; -import { memo, useEffect, useMemo } from 'react'; +import { ArrowUp10, Minus } from 'lucide-react'; +import { memo, useEffect, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; import { DataSource } from 'types/common/queryBuilder'; @@ -29,6 +30,7 @@ interface TracesViewProps { function TracesView({ isFilterApplied }: TracesViewProps): JSX.Element { const { stagedQuery, panelType } = useQueryBuilder(); + const [orderDirection, setOrderDirection] = useState('asc'); const { selectedTime: globalSelectedTime, maxTime, minTime } = useSelector< AppState, @@ -92,11 +94,32 @@ function TracesView({ isFilterApplied }: TracesViewProps): JSX.Element { here - + +
+
+
+ Order by +
+ +