diff --git a/public/app/features/expressions/ExpressionQueryEditor.tsx b/public/app/features/expressions/ExpressionQueryEditor.tsx index f8e3ad50abb..538aa2e52f6 100644 --- a/public/app/features/expressions/ExpressionQueryEditor.tsx +++ b/public/app/features/expressions/ExpressionQueryEditor.tsx @@ -1,10 +1,10 @@ import { css } from '@emotion/css'; import { useCallback, useEffect, useRef } from 'react'; -import { DataSourceApi, GrafanaTheme2, QueryEditorProps } from '@grafana/data'; +import { DataSourceApi, FeatureState, GrafanaTheme2, QueryEditorProps } from '@grafana/data'; import { t, Trans } from '@grafana/i18n'; import { reportInteraction } from '@grafana/runtime'; -import { Button, IconButton, InlineField, PopoverContent, useStyles2 } from '@grafana/ui'; +import { Button, FeatureBadge, IconButton, InlineField, PopoverContent, useStyles2 } from '@grafana/ui'; import { ClassicConditions } from './components/ClassicConditions'; import { ExpressionTypeDropdown } from './components/ExpressionTypeDropdown'; @@ -23,21 +23,33 @@ const labelWidth = 15; type NonClassicExpressionType = Exclude; type ExpressionTypeConfigStorage = Partial>; -// Help text for each expression type - can be expanded with more detailed content -const getExpressionHelpText = (type: ExpressionQueryType): PopoverContent | string => { +/** + * Get the configuration for an expression type (helper text and feature state). + * @param type - The expression type. + * @returns The configuration for the expression type. + */ +const getExpressionTypeConfig = ( + type: ExpressionQueryType +): { helperText: PopoverContent; featureState: FeatureState | undefined } => { const description = expressionTypes.find(({ value }) => value === type)?.description; switch (type) { case ExpressionQueryType.sql: - return ( - - Run MySQL-dialect SQL against the tables returned from your data sources. Data source queries (ie - "A", "B") are available as tables and referenced by query-name. Fields are available as - columns, as returned from the data source. - - ); + return { + helperText: ( + + Run MySQL-dialect SQL against the tables returned from your data sources. Data source queries (ie + "A", "B") are available as tables and referenced by query-name. Fields are available as + columns, as returned from the data source. + + ), + featureState: FeatureState.preview, + }; default: - return description ?? ''; + return { + helperText: description ?? '', + featureState: undefined, + }; } }; @@ -148,7 +160,7 @@ export function ExpressionQueryEditor(props: ExpressionQueryEditorProps) { } }; - const helperText = getExpressionHelpText(query.type); + const { helperText, featureState } = getExpressionTypeConfig(query.type); return (
@@ -163,7 +175,10 @@ export function ExpressionQueryEditor(props: ExpressionQueryEditorProps) { - {helperText && } +
+ {featureState && } + {helperText && } +
{renderExpressionType()} @@ -176,7 +191,10 @@ const getStyles = (theme: GrafanaTheme2) => ({ alignItems: 'center', gap: theme.spacing(1), }), - infoIcon: css({ + fieldContainer: css({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing(1), marginBottom: theme.spacing(0.5), // Align with the select field }), }); diff --git a/public/app/features/expressions/components/ExpressionTypeDropdown.tsx b/public/app/features/expressions/components/ExpressionTypeDropdown.tsx index 2fc78ba53d2..bb84dcd076c 100644 --- a/public/app/features/expressions/components/ExpressionTypeDropdown.tsx +++ b/public/app/features/expressions/components/ExpressionTypeDropdown.tsx @@ -37,7 +37,7 @@ const ExpressionMenuItem = memo(({ item, onSelect }) =>