Skip to content

Commit f7ac0a3

Browse files
Merge pull request #38 from NeedleInAJayStack/feature/id-var-dis
Ref Variable Display Improvements
2 parents 721a1d8 + be6fa2d commit f7ac0a3

File tree

5 files changed

+62
-68
lines changed

5 files changed

+62
-68
lines changed

pkg/plugin/datasource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ func (datasource *Datasource) CheckHealth(_ context.Context, req *backend.CheckH
284284
if err != nil {
285285
return &backend.CheckHealthResult{
286286
Status: backend.HealthStatusError,
287-
Message: "Uh oh, something's wrong with the connection",
287+
Message: err.Error(),
288288
}, err
289289
}
290290

src/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ To use them, simply enter the value in the input string. Below is an example of
6666
### Query Variables
6767

6868
You can use the Haystack connector to source new variables. Create a query and then enter the name of the column that
69-
contains the variable values. If no column is specified, the first one is used.
69+
contains the variable values. If no column is specified, `id` is used if present. Otherwise, the first column is used.
7070

71-
The value injected by the variable exactly matches the displayed value, with the exception of Ref types, where the
72-
injected value is only the ID portion (i.e. the dis name is not included in the interpolation). Multiple-select values
73-
are combined with commas, (`red,blue`), but this may be customized using the
74-
[advanced variable format options](https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/#advanced-variable-format-options).
71+
The value injected by the variable exactly matches the displayed value, with the exception of Ref types. Instead, Ref
72+
types display the "display" portion and inject only the "ID" portion (i.e. `@abc "Site A"` will be displayed as `Site A`
73+
and provide `@abc` when injected). Multiple-select values are combined with commas, (`red,blue`), but this may be
74+
customized using the [advanced variable format options](https://grafana.com/docs/grafana/latest/dashboards/variables/variable-syntax/#advanced-variable-format-options).
7575

7676
### Alerting
7777

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,80 @@
11
import React, { useState } from 'react';
2-
import { HaystackQuery, HaystackVariableQuery } from '../types';
2+
import { HaystackVariableQuery } from '../types';
33
import { HaystackQueryTypeSelector } from './HaystackQueryTypeSelector';
44
import { HaystackQueryInput } from './HaystackQueryInput';
5+
import { InlineField, Input } from '@grafana/ui';
56

67
interface VariableQueryProps {
78
query: HaystackVariableQuery;
89
onChange: (query: HaystackVariableQuery, definition: string) => void;
910
}
1011

11-
const blankQuery: Partial<HaystackQuery> = {
12-
refId: "variable",
13-
type: '',
14-
eval: '',
15-
hisRead: '',
16-
read: '',
17-
};
12+
const refId = "variable";
1813

1914
export const VariableQueryEditor: React.FC<VariableQueryProps> = ({ onChange, query: variableQuery }) => {
20-
const [state, setState] = useState(variableQuery);
15+
const [query, setState] = useState(variableQuery);
2116

2217
const saveQuery = () => {
23-
let query = state.query ?? blankQuery
18+
// refId must match but doesn't get set originally so set should set it on every change
19+
setState({ ...query, refId: refId});
20+
2421
let type = query.type;
2522
let queryCmd = "";
26-
if (query.type === "hisRead") {
27-
queryCmd = query.hisRead
28-
} else if (query.type === "eval") {
23+
if (query.type === "eval") {
2924
queryCmd = query.eval
25+
} else if (query.type === "hisRead") {
26+
queryCmd = query.hisRead
27+
} else if (query.type === "hisReadFilter") {
28+
queryCmd = query.hisReadFilter
3029
} else if (query.type === "read") {
3130
queryCmd = query.read
3231
}
3332
let column = "none";
34-
if (state.column !== undefined && state.column !== '') {
35-
column = `'${state.column}'`;
33+
if (query.column !== undefined && query.column !== '') {
34+
column = `'${query.column}'`;
3635
}
37-
onChange(state, `Type: '${type}' Query: '${queryCmd}' Column: ${column}`);
36+
let displayString = `${type}: '${queryCmd}', Column: ${column}`
37+
onChange(query, displayString);
3838
};
3939

4040
const onTypeChange = (newType: string) => {
41-
let query = {...state.query ?? blankQuery};
42-
query.type = newType;
43-
setState({ ...state, query: query});
41+
setState({ ...query, type: newType});
4442
};
4543

4644
const onQueryChange = (newQuery: string) => {
47-
let query = {...state.query ?? blankQuery};
48-
if (state.query.type === "hisRead") {
49-
query.hisRead = newQuery
50-
} else if (state.query.type === "eval") {
51-
query.eval = newQuery
52-
} else if (state.query.type === "read") {
53-
query.read = newQuery
45+
if (query.type === "eval") {
46+
setState({ ...query, eval: newQuery });
47+
} else if (query.type === "hisRead") {
48+
setState({ ...query, hisRead: newQuery });
49+
} else if (query.type === "hisReadFilter") {
50+
setState({ ...query, hisReadFilter: newQuery });
51+
} else if (query.type === "read") {
52+
setState({ ...query, read: newQuery });
5453
}
55-
setState({ ...state, query: query});
5654
};
5755

5856
const onColumnChange = (event: React.FormEvent<HTMLInputElement>) => {
59-
setState({...state, column: event.currentTarget.value,});
57+
setState({...query, column: event.currentTarget.value,});
6058
};
6159

6260
return (
6361
<div onBlur={saveQuery}>
6462
<HaystackQueryTypeSelector
6563
datasource={null}
66-
type={state.query?.type ?? blankQuery.type}
67-
refId={state.query?.refId ?? blankQuery.refId}
64+
type={query.type}
65+
refId={query.refId ?? refId}
6866
onChange={onTypeChange}
6967
/>
7068
<HaystackQueryInput
71-
query={state.query ?? blankQuery}
69+
query={query}
7270
onChange={onQueryChange}
7371
/>
74-
<div className="gf-form">
75-
<span className="gf-form-label width-10">Column</span>
76-
<input
77-
name="column"
78-
className="gf-form-input"
72+
<InlineField label="Column">
73+
<Input
7974
onChange={onColumnChange}
80-
value={state.column}
75+
value={query.column}
8176
/>
82-
</div>
77+
</InlineField>
8378
</div>
8479
);
8580
};

src/datasource.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
import {
22
DataSourceInstanceSettings,
3-
CoreApp,
43
ScopedVars,
54
DataQueryRequest,
65
DataFrame,
76
Field,
87
MetricFindValue,
98
getDefaultTimeRange,
9+
FieldType,
1010
} from '@grafana/data';
1111
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
1212

13-
import {
14-
HaystackQuery,
15-
OpsQuery,
16-
HaystackDataSourceOptions,
17-
DEFAULT_QUERY,
18-
HaystackVariableQuery,
19-
QueryType,
20-
} from './types';
13+
import { HaystackQuery, OpsQuery, HaystackDataSourceOptions, HaystackVariableQuery, QueryType } from './types';
2114
import { firstValueFrom } from 'rxjs';
2215

2316
export const queryTypes: QueryType[] = [
@@ -97,7 +90,7 @@ export class DataSource extends DataSourceWithBackend<HaystackQuery, HaystackDat
9790

9891
// This is called when the user is selecting a variable value
9992
async metricFindQuery(variableQuery: HaystackVariableQuery, options?: any) {
100-
let request: HaystackQuery = variableQuery.query;
93+
let request: HaystackQuery = variableQuery;
10194
let observable = this.query({ targets: [request] } as DataQueryRequest<HaystackQuery>);
10295
let response = await firstValueFrom(observable);
10396

@@ -106,31 +99,37 @@ export class DataSource extends DataSourceWithBackend<HaystackQuery, HaystackDat
10699
}
107100

108101
return response.data.reduce((acc: MetricFindValue[], frame: DataFrame) => {
102+
// Default to the first field
109103
let field = frame.fields[0];
110104
if (variableQuery.column !== undefined && variableQuery.column !== '') {
111105
// If a column was input, match the column name
112106
field = frame.fields.find((field: Field) => field.name === variableQuery.column) ?? field;
107+
} else if (frame.fields.some((field: Field) => field.name === 'id')) {
108+
// If there is an id column, use that
109+
field = frame.fields.find((field: Field) => field.name === 'id') ?? field;
113110
}
114111

115112
let fieldVals = field.values.map((value) => {
116-
if (value.startsWith('@')) {
117-
// Detect ref using @ prefix, and adjust value to just the Ref
118-
let spaceIndex = value.indexOf(' ');
119-
let id = value.substring(0, spaceIndex);
120-
return { text: value, value: id };
121-
} else {
122-
// Otherwise, just use the value directly
123-
return { text: value, value: value };
113+
switch (field.type) {
114+
case FieldType.string:
115+
if (value.startsWith('@')) {
116+
// Detect ref using @ prefix, and adjust value to just the Ref
117+
let spaceIndex = value.indexOf(' ');
118+
let id = value.substring(0, spaceIndex);
119+
let dis = value.substring(spaceIndex + 2, value.length - 1);
120+
return { text: dis, value: id };
121+
} else {
122+
// Otherwise, just use the value directly
123+
return { text: value, value: value };
124+
}
125+
default:
126+
return { text: value, value: value };
124127
}
125128
});
126129
return acc.concat(fieldVals);
127130
}, []);
128131
}
129132

130-
getDefaultQuery(_: CoreApp): Partial<HaystackQuery> {
131-
return DEFAULT_QUERY;
132-
}
133-
134133
// Returns a DataQueryRequest that gets the available ops from the datasource
135134
// This applies a bunch of defaults because it's not a time series query
136135
private opsRequest(refId: string): DataQueryRequest<HaystackQuery> {

src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ export interface QueryType extends SelectableValue<string> {
2828
apiRequirements: string[];
2929
}
3030

31-
export interface HaystackVariableQuery {
32-
query: HaystackQuery;
31+
export interface HaystackVariableQuery extends HaystackQuery {
3332
column: string;
33+
refId: string;
3434
}
3535

3636
export const DEFAULT_QUERY: Partial<HaystackQuery> = {

0 commit comments

Comments
 (0)