diff --git a/packages/grafana-sql/src/SQLVariableSupport.tsx b/packages/grafana-sql/src/SQLVariableSupport.tsx index 83d4d44b330..c88b910067c 100644 --- a/packages/grafana-sql/src/SQLVariableSupport.tsx +++ b/packages/grafana-sql/src/SQLVariableSupport.tsx @@ -1,3 +1,4 @@ +import { useEffect, useState } from 'react'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -9,12 +10,14 @@ import { Field, DataFrame, } from '@grafana/data'; -import { EditorMode } from '@grafana/plugin-ui'; +import { t } from '@grafana/i18n'; +import { EditorMode, EditorRows, EditorRow, EditorField } from '@grafana/plugin-ui'; +import { Combobox, ComboboxOption } from '@grafana/ui'; import { SqlQueryEditorLazy } from './components/QueryEditorLazy'; import { SqlDatasource } from './datasource/SqlDatasource'; import { applyQueryDefaults } from './defaults'; -import { type SQLQuery, type SQLOptions, QueryFormat } from './types'; +import { QueryFormat, type SQLQuery, type SQLOptions, type SQLQueryMeta } from './types'; type SQLVariableQuery = { query: string } & SQLQuery; @@ -36,7 +39,7 @@ export class SQLVariableSupport extends CustomVariableSupport ({ ...frame, - fields: convertOriginalFieldsToVariableFields(frame.fields), + fields: convertOriginalFieldsToVariableFields(frame.fields, updatedQuery.meta), })), }; }) @@ -47,8 +50,74 @@ export class SQLVariableSupport extends CustomVariableSupport) => { - return ; +type SQLVariableQueryEditorProps = QueryEditorProps; + +const SQLVariablesQueryEditor = (props: SQLVariableQueryEditorProps) => { + const query = migrateVariableQuery(props.query); + return ( + <> + + + + ); +}; + +const FieldMapping = (props: SQLVariableQueryEditorProps) => { + const { query, datasource, onChange } = props; + const [choices, setChoices] = useState([]); + useEffect(() => { + let isActive = true; + // eslint-disable-next-line + const subscription = datasource.query({ targets: [query] } as DataQueryRequest).subscribe({ + next: (response) => { + if (!isActive) { + return; + } + const fieldNames = (response.data[0] || { fields: [] }).fields.map((f: Field) => f.name); + setChoices(fieldNames.map((f: Field) => ({ value: f, label: f }))); + }, + error: () => { + if (isActive) { + setChoices([]); + } + }, + }); + return () => { + isActive = false; + subscription.unsubscribe(); + }; + }, [datasource, query]); + const onMetaPropChange = ( + key: Key, + value: Value, + meta = query.meta || {} + ) => { + onChange({ ...query, meta: { ...meta, [key]: value } }); + }; + return ( + + + + onMetaPropChange('valueField', e?.value)} + width={40} + options={choices} + /> + + + onMetaPropChange('textField', e?.value)} + width={40} + options={choices} + /> + + + + ); }; const migrateVariableQuery = (rawQuery: string | SQLQuery): SQLVariableQuery => { @@ -69,12 +138,16 @@ const migrateVariableQuery = (rawQuery: string | SQLQuery): SQLVariableQuery => }; }; -const convertOriginalFieldsToVariableFields = (original_fields: Field[]): Field[] => { +const convertOriginalFieldsToVariableFields = (original_fields: Field[], meta?: SQLQueryMeta): Field[] => { if (original_fields.length < 1) { throw new Error('at least one field expected for variable'); } let tf = original_fields.find((f) => f.name === '__text'); let vf = original_fields.find((f) => f.name === '__value'); + if (meta) { + tf = meta.textField ? original_fields.find((f) => f.name === meta.textField) : undefined; + vf = meta.valueField ? original_fields.find((f) => f.name === meta.valueField) : undefined; + } const textField = tf || vf || original_fields[0]; const valueField = vf || tf || original_fields[0]; return [ diff --git a/packages/grafana-sql/src/locales/en-US/grafana-sql.json b/packages/grafana-sql/src/locales/en-US/grafana-sql.json index f9572756abd..5120ef8d4e8 100644 --- a/packages/grafana-sql/src/locales/en-US/grafana-sql.json +++ b/packages/grafana-sql/src/locales/en-US/grafana-sql.json @@ -69,6 +69,12 @@ "placeholder-select-format": "Select format", "run-query": "Run query" }, + "query-meta": { + "variables": { + "textField": "Text Field", + "valueField": "Value Field" + } + }, "query-toolbox": { "content-hit-ctrlcmdreturn-to-run-query": "Hit CTRL/CMD+Return to run query", "tooltip-collapse": "Collapse editor", diff --git a/packages/grafana-sql/src/types.ts b/packages/grafana-sql/src/types.ts index 00c1a6e0456..1945e69afaa 100644 --- a/packages/grafana-sql/src/types.ts +++ b/packages/grafana-sql/src/types.ts @@ -50,6 +50,8 @@ export enum QueryFormat { Table = 'table', } +export type SQLQueryMeta = { valueField?: string; textField?: string }; + export interface SQLQuery extends DataQuery { alias?: string; format?: QueryFormat; @@ -59,6 +61,7 @@ export interface SQLQuery extends DataQuery { sql?: SQLExpression; editorMode?: EditorMode; rawQuery?: boolean; + meta?: SQLQueryMeta; } export interface NameValue {