11import React , { useEffect , useMemo , useState } from 'react' ;
2- import { Icon , InlineField , InlineFieldRow , InlineSwitch , Select , stylesFactory , Tooltip , useTheme } from '@grafana/ui' ;
2+ import {
3+ Icon ,
4+ IconButton ,
5+ InlineField ,
6+ InlineFieldRow ,
7+ InlineSwitch ,
8+ Input ,
9+ Select ,
10+ stylesFactory ,
11+ Tooltip ,
12+ useTheme ,
13+ } from '@grafana/ui' ;
314import { GrafanaTheme , QueryEditorProps , SelectableValue } from '@grafana/data' ;
415import { css } from '@emotion/css' ;
516import { DataSource } from '../datasource' ;
@@ -21,6 +32,7 @@ export function QueryEditor({
2132} : QueryEditorProps < DataSource , TinybirdQuery , TinybirdOptions > ) {
2233 const theme = useTheme ( ) ;
2334 const styles = getStyles ( theme ) ;
35+ const [ isOptionsOpen , setIsOptionsOpen ] = useState ( false ) ;
2436 const [ pipes , setPipes ] = useState < TinybirdPipe [ ] > ( [ ] ) ;
2537 const formatAsOptions : Array < SelectableValue < OutputFormat > > = SUPPORTED_OUTPUT_FORMATS . map ( ( f ) => ( {
2638 label : capitalize ( f ) ,
@@ -85,21 +97,19 @@ export function QueryEditor({
8597 return (
8698 < div className = { styles . root } >
8799 < InlineFieldRow >
88- < InlineFieldRow >
89- < InlineField label = "API Endpoint" labelWidth = { 14 } tooltip = "Your published Tinybird API Endpoint" >
90- < Select
91- width = { 50 }
92- options = { pipeNameOptions }
93- value = { query . pipeName }
94- onChange = { ( { value } ) => {
95- if ( value ) {
96- onChange ( { ...query , pipeName : value } ) ;
97- }
98- } }
99- placeholder = "ds"
100- />
101- </ InlineField >
102- </ InlineFieldRow >
100+ < InlineField label = "API Endpoint" labelWidth = { 14 } tooltip = "Your published Tinybird API Endpoint" >
101+ < Select
102+ width = { 50 }
103+ options = { pipeNameOptions }
104+ value = { query . pipeName }
105+ onChange = { ( { value } ) => {
106+ if ( value ) {
107+ onChange ( { ...query , pipeName : value } ) ;
108+ }
109+ } }
110+ placeholder = "ds"
111+ />
112+ </ InlineField >
103113
104114 < InlineField label = "Format as" labelWidth = { 14 } >
105115 < Select
@@ -115,7 +125,21 @@ export function QueryEditor({
115125 />
116126 </ InlineField >
117127
118- { query . format === 'timeseries' && (
128+ < div className = { styles . cogIconWrapper } >
129+ { query . format === 'timeseries' ? (
130+ < IconButton
131+ name = "cog"
132+ variant = { isOptionsOpen ? 'primary' : 'secondary' }
133+ onClick = { ( ) => setIsOptionsOpen ( ( value ) => ! value ) }
134+ />
135+ ) : (
136+ < > </ >
137+ ) }
138+ </ div >
139+ </ InlineFieldRow >
140+
141+ { query . format === 'timeseries' && isOptionsOpen && (
142+ < InlineFieldRow >
119143 < InlineField
120144 label = "Extrapolate"
121145 labelWidth = { 14 }
@@ -126,58 +150,87 @@ export function QueryEditor({
126150 onChange = { ( { currentTarget : { value } } ) => onChange ( { ...query , extrapolate : ! ! value } ) }
127151 />
128152 </ InlineField >
129- ) }
130- </ InlineFieldRow >
153+ < InlineField label = "Time key" labelWidth = { 16 } tooltip = "Time key of the data" >
154+ < Input
155+ value = { query . timeKey }
156+ onChange = { ( { currentTarget : { value } } ) => onChange ( { ...query , timeKey : value } ) }
157+ />
158+ </ InlineField >
159+ < InlineField label = "Data keys" labelWidth = { 16 } tooltip = "Comma-separated keys to access values of the data" >
160+ < Input
161+ value = { query . dataKeys }
162+ onChange = { ( { currentTarget : { value } } ) => onChange ( { ...query , dataKeys : value } ) }
163+ />
164+ </ InlineField >
165+ < InlineField label = "Label keys" labelWidth = { 16 } tooltip = "Comma-separated keys to access labels of the data" >
166+ < Input
167+ value = { query . labelKeys }
168+ onChange = { ( { currentTarget : { value } } ) => onChange ( { ...query , labelKeys : value } ) }
169+ />
170+ </ InlineField >
171+ </ InlineFieldRow >
172+ ) }
131173
132- { Object . keys ( query . paramOptions ?? { } ) . length > 0 && (
133- < table className = { styles . table } >
134- < thead className = { styles . thead } >
135- < tr className = { styles . row } >
136- { [ 'Name' , 'Type' , 'Value' ] . map ( ( _ , key ) => (
137- < th key = { key } className = { styles . th } >
138- { _ }
139- </ th >
140- ) ) }
141- < th className = { styles . th } > </ th >
142- </ tr >
143- </ thead >
144- < tbody className = { styles . tbody } >
145- { Object . entries ( query . paramOptions ) . map ( ( [ name , { type, description, required } ] , rowIdx ) => (
146- < tr key = { rowIdx } className = { styles . row } >
147- < td className = { styles . td } >
148- < div className = { styles . nameCol } >
149- { name }
150- { description && (
151- < Tooltip content = { description } >
152- < Icon name = "info-circle" />
153- </ Tooltip >
154- ) }
155- </ div >
156- </ td >
157- < td className = { styles . td } >
158- { type }
159- { required ? '*' : '' }
160- </ td >
161- < td className = { styles . td } >
162- < input
163- className = { styles . input }
164- value = { query . params [ name ] }
165- onChange = { ( e ) => onChange ( { ...query , params : { ...query . params , [ name ] : e . currentTarget . value } } ) }
166- />
167- </ td >
174+ < div className = { styles . root } >
175+ { Object . keys ( query . paramOptions ?? { } ) . length > 0 && (
176+ < table className = { styles . table } >
177+ < thead className = { styles . thead } >
178+ < tr className = { styles . row } >
179+ { [ 'Name' , 'Type' , 'Value' ] . map ( ( _ , key ) => (
180+ < th key = { key } className = { styles . th } >
181+ { _ }
182+ </ th >
183+ ) ) }
184+ < th className = { styles . th } > </ th >
168185 </ tr >
169- ) ) }
170- </ tbody >
171- </ table >
172- ) }
186+ </ thead >
187+ < tbody className = { styles . tbody } >
188+ { Object . entries ( query . paramOptions ) . map ( ( [ name , { type, description, required } ] , rowIdx ) => (
189+ < tr key = { rowIdx } className = { styles . row } >
190+ < td className = { styles . td } >
191+ < div className = { styles . nameCol } >
192+ { name }
193+ { description && (
194+ < Tooltip content = { description } >
195+ < Icon name = "info-circle" />
196+ </ Tooltip >
197+ ) }
198+ </ div >
199+ </ td >
200+ < td className = { styles . td } >
201+ { type }
202+ { required ? '*' : '' }
203+ </ td >
204+ < td className = { styles . td } >
205+ < input
206+ className = { styles . input }
207+ value = { query . params [ name ] }
208+ onChange = { ( e ) =>
209+ onChange ( { ...query , params : { ...query . params , [ name ] : e . currentTarget . value } } )
210+ }
211+ />
212+ </ td >
213+ </ tr >
214+ ) ) }
215+ </ tbody >
216+ </ table >
217+ ) }
218+ </ div >
173219 </ div >
174220 ) ;
175221}
176222
177223const getStyles = stylesFactory ( ( theme : GrafanaTheme ) => {
178224 return {
179225 root : css `
180- margin-top : 2rem ;
226+ margin-top : 1.5rem ;
227+ ` ,
228+ cogIconWrapper : css `
229+ display : flex;
230+ align-items : center;
231+ position : relative;
232+ flex : 0 0 auto;
233+ margin : 0px 4px 4px 4px ;
181234 ` ,
182235 table : css `
183236 table-layout : auto;
0 commit comments