1import { SelectableValue } from '@grafana/data'; 2import { Alert, InlineField, Input, Select } from '@grafana/ui'; 3import React, { ChangeEvent, useCallback, useEffect, useState } from 'react'; 4import { AzureMonitorQuery, AzureQueryType } from '../../types'; 5import LogsQueryEditor from '../LogsQueryEditor'; 6import DataSource from '../../datasource'; 7import useLastError from '../../utils/useLastError'; 8import { Space } from '../Space'; 9import { migrateStringQueriesToObjectQueries } from '../../grafanaTemplateVariableFns'; 10 11const AZURE_QUERY_VARIABLE_TYPE_OPTIONS = [ 12 { label: 'Grafana Query Function', value: AzureQueryType.GrafanaTemplateVariableFn }, 13 { label: 'Logs', value: AzureQueryType.LogAnalytics }, 14]; 15 16const GrafanaTemplateVariableFnInput = ({ 17 query, 18 updateQuery, 19 datasource, 20}: { 21 query: AzureMonitorQuery; 22 updateQuery: (val: AzureMonitorQuery) => void; 23 datasource: DataSource; 24}) => { 25 const [inputVal, setInputVal] = useState(''); 26 useEffect(() => { 27 setInputVal(query.grafanaTemplateVariableFn?.rawQuery || ''); 28 }, [query.grafanaTemplateVariableFn?.rawQuery]); 29 30 const onRunQuery = useCallback( 31 (newQuery: string) => { 32 migrateStringQueriesToObjectQueries(newQuery, { datasource }).then((updatedQuery) => { 33 if (updatedQuery.queryType === AzureQueryType.GrafanaTemplateVariableFn) { 34 updateQuery(updatedQuery); 35 } else { 36 updateQuery({ 37 ...query, 38 grafanaTemplateVariableFn: { 39 kind: 'UnknownQuery', 40 rawQuery: newQuery, 41 }, 42 }); 43 } 44 }); 45 }, 46 [datasource, query, updateQuery] 47 ); 48 49 const onChange = (event: ChangeEvent<HTMLInputElement>) => { 50 setInputVal(event.target.value); 51 }; 52 53 return ( 54 <InlineField label="Grafana template variable function"> 55 <Input 56 placeholder={'type a grafana template variable function, ex: Subscriptions()'} 57 value={inputVal} 58 onChange={onChange} 59 onBlur={() => onRunQuery(inputVal)} 60 /> 61 </InlineField> 62 ); 63}; 64 65type Props = { 66 query: AzureMonitorQuery | string; 67 onChange: (query: AzureMonitorQuery) => void; 68 datasource: DataSource; 69}; 70 71const VariableEditor = (props: Props) => { 72 const defaultQuery: AzureMonitorQuery = { 73 refId: 'A', 74 queryType: AzureQueryType.GrafanaTemplateVariableFn, 75 }; 76 const [query, setQuery] = useState(defaultQuery); 77 78 useEffect(() => { 79 migrateStringQueriesToObjectQueries(props.query, { datasource: props.datasource }).then((migratedQuery) => { 80 setQuery(migratedQuery); 81 }); 82 }, [props.query, props.datasource]); 83 84 const onQueryTypeChange = (selectableValue: SelectableValue) => { 85 if (selectableValue.value) { 86 setQuery({ 87 ...query, 88 queryType: selectableValue.value, 89 }); 90 } 91 }; 92 const onLogsQueryChange = (queryChange: AzureMonitorQuery) => { 93 setQuery(queryChange); 94 95 // only hit backend if there's something to query (prevents error when selecting the resource before pinging a query) 96 if (queryChange.azureLogAnalytics?.query) { 97 props.onChange(queryChange); 98 } 99 }; 100 101 const [errorMessage, setError] = useLastError(); 102 103 const variableOptionGroup = { 104 label: 'Template Variables', 105 // TODO: figure out a way to filter out the current variable from the variables list 106 // options: props.datasource.getVariables().map((v) => ({ label: v, value: v })), 107 options: [], 108 }; 109 110 return ( 111 <> 112 <InlineField label="Select query type"> 113 <Select 114 aria-label="select query type" 115 onChange={onQueryTypeChange} 116 options={AZURE_QUERY_VARIABLE_TYPE_OPTIONS} 117 width={25} 118 value={query.queryType} 119 /> 120 </InlineField> 121 {query.queryType === AzureQueryType.LogAnalytics && ( 122 <> 123 <LogsQueryEditor 124 subscriptionId={query.subscription} 125 query={query} 126 datasource={props.datasource} 127 onChange={onLogsQueryChange} 128 variableOptionGroup={variableOptionGroup} 129 setError={setError} 130 hideFormatAs={true} 131 /> 132 {errorMessage && ( 133 <> 134 <Space v={2} /> 135 <Alert severity="error" title="An error occurred while requesting metadata from Azure Monitor"> 136 {errorMessage} 137 </Alert> 138 </> 139 )} 140 </> 141 )} 142 {query.queryType === AzureQueryType.GrafanaTemplateVariableFn && ( 143 <GrafanaTemplateVariableFnInput query={query} updateQuery={props.onChange} datasource={props.datasource} /> 144 )} 145 </> 146 ); 147}; 148 149export default VariableEditor; 150