Skip to content

Commit ebf28a7

Browse files
Merge pull request #47 from NeedleInAJayStack/fix/issue-46
Sets variable query refId manually
2 parents edcb23f + 03ad6cc commit ebf28a7

File tree

3 files changed

+113
-100
lines changed

3 files changed

+113
-100
lines changed

src/HaystackVariableSupport.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import {
2+
CustomVariableSupport,
3+
DataQueryRequest,
4+
DataQueryResponse,
5+
DataFrame,
6+
Field,
7+
FieldType,
8+
MetricFindValue,
9+
} from '@grafana/data';
10+
11+
import { Observable } from 'rxjs';
12+
import { map } from 'rxjs/operators';
13+
14+
import { HaystackVariableQueryEditor } from './components/HaystackVariableQueryEditor';
15+
import { DataSource } from './datasource';
16+
import { isRef, parseRef } from 'haystack';
17+
import { HaystackVariableQuery } from './types';
18+
19+
export class HaystackVariableSupport extends CustomVariableSupport<DataSource, HaystackVariableQuery> {
20+
editor = HaystackVariableQueryEditor;
21+
22+
constructor(private datasource: DataSource) {
23+
super();
24+
}
25+
26+
query(request: DataQueryRequest<HaystackVariableQuery>): Observable<DataQueryResponse> {
27+
let variableQuery = request.targets[0];
28+
let observable = this.datasource.query(request);
29+
return observable.pipe(
30+
map((response) => {
31+
if (response === undefined || response.errors !== undefined || response.data === undefined) {
32+
return response;
33+
}
34+
35+
let variableValues = response.data.reduce((acc: MetricFindValue[], frame: DataFrame) => {
36+
// Default to the first field
37+
let column = frame.fields[0];
38+
if (variableQuery.column !== undefined && variableQuery.column !== '') {
39+
// If a column was input, match the column name
40+
column = frame.fields.find((field: Field) => field.name === variableQuery.column) ?? column;
41+
} else if (frame.fields.some((field: Field) => field.name === 'id')) {
42+
// If there is an id column, use that
43+
column = frame.fields.find((field: Field) => field.name === 'id') ?? column;
44+
}
45+
46+
// Default to the selected column
47+
let displayColumn = column;
48+
if (variableQuery.displayColumn !== undefined && variableQuery.displayColumn !== '') {
49+
// If a column was input, match the column name
50+
displayColumn =
51+
frame.fields.find((field: Field) => {
52+
return field.name === variableQuery.displayColumn;
53+
}) ?? displayColumn;
54+
}
55+
56+
let variableValues = column.values.map((value, index) => {
57+
let variableValue = variableValueFromCell(value, column.type);
58+
59+
let displayValue = displayColumn.values[index];
60+
let variableText = variableTextFromCell(displayValue, displayColumn.type);
61+
62+
return { text: variableText, value: variableValue };
63+
});
64+
return acc.concat(variableValues);
65+
}, []);
66+
return { ...response, data: variableValues };
67+
})
68+
);
69+
}
70+
}
71+
72+
function variableValueFromCell(value: string, columnType: FieldType): string {
73+
switch (columnType) {
74+
case FieldType.string:
75+
if (isRef(value)) {
76+
return parseRef(value).id;
77+
}
78+
}
79+
return value;
80+
}
81+
82+
function variableTextFromCell(value: string, columnType: FieldType): string {
83+
switch (columnType) {
84+
case FieldType.string:
85+
if (isRef(value)) {
86+
let ref = parseRef(value);
87+
return ref.dis ?? ref.id;
88+
}
89+
}
90+
return value;
91+
}

src/components/VariableQueryEditor.tsx renamed to src/components/HaystackVariableQueryEditor.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import { QueryEditorProps } from '@grafana/data';
66
import { InlineField, Input, Stack } from '@grafana/ui';
77
import { DataSource } from 'datasource';
88

9-
type Props = QueryEditorProps<DataSource, HaystackQuery, HaystackDataSourceOptions, HaystackVariableQuery>;
9+
export type Props = QueryEditorProps<DataSource, HaystackQuery, HaystackDataSourceOptions, HaystackVariableQuery>;
1010

11-
export const VariableQueryEditor = ({ onChange, query }: Props) => {
11+
const refId = 'HaystackVariableQueryEditor-VariableQuery';
12+
13+
export const HaystackVariableQueryEditor = ({ onChange, query }: Props) => {
1214
let variableInputWidth = 30;
1315

1416
// Computes the query string and calls the onChange function. Should be used instead of onChange for all mutating functions.
@@ -42,22 +44,28 @@ export const VariableQueryEditor = ({ onChange, query }: Props) => {
4244

4345
const onQueryChange = (newQuery: string) => {
4446
if (query.type === "eval") {
45-
onChangeAndSave({ ...query, eval: newQuery });
47+
onChangeAndSave({ ...query, refId: refId, eval: newQuery });
4648
} else if (query.type === "hisRead") {
47-
onChangeAndSave({ ...query, hisRead: newQuery });
49+
onChangeAndSave({ ...query, refId: refId, hisRead: newQuery });
4850
} else if (query.type === "hisReadFilter") {
49-
onChangeAndSave({ ...query, hisReadFilter: newQuery });
51+
onChangeAndSave({ ...query, refId: refId, hisReadFilter: newQuery });
5052
} else if (query.type === "read") {
51-
onChangeAndSave({ ...query, read: newQuery });
53+
onChangeAndSave({ ...query, refId: refId, read: newQuery });
5254
}
5355
};
5456

5557
const onColumnChange = (event: React.FormEvent<HTMLInputElement>) => {
56-
onChangeAndSave({...query, column: event.currentTarget.value,});
58+
onChangeAndSave({...query, column: event.currentTarget.value });
5759
};
5860

5961
const onDisplayColumnChange = (event: React.FormEvent<HTMLInputElement>) => {
60-
onChangeAndSave({...query, displayColumn: event.currentTarget.value,});
62+
onChangeAndSave({...query, displayColumn: event.currentTarget.value });
63+
};
64+
65+
const handleBlur = () => {
66+
if (query.query !== undefined && query.query !== "") {
67+
onChange({ ...query, refId: refId });
68+
}
6169
};
6270

6371
return (
@@ -78,6 +86,7 @@ export const VariableQueryEditor = ({ onChange, query }: Props) => {
7886
<InlineField label="Column">
7987
<Input
8088
width={variableInputWidth}
89+
onBlur={handleBlur}
8190
onChange={onColumnChange}
8291
value={query.column}
8392
placeholder="Defaults to 'id' or first column"
@@ -86,6 +95,7 @@ export const VariableQueryEditor = ({ onChange, query }: Props) => {
8695
<InlineField label="Display Column">
8796
<Input
8897
width={variableInputWidth}
98+
onBlur={handleBlur}
8999
onChange={onDisplayColumnChange}
90100
value={query.displayColumn}
91101
placeholder="Defaults to 'Column'"

src/datasource.ts

Lines changed: 4 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,13 @@ import {
44
DataQueryRequest,
55
DataFrame,
66
Field,
7-
MetricFindValue,
87
getDefaultTimeRange,
9-
FieldType,
10-
CustomVariableSupport,
11-
DataQueryResponse,
12-
QueryEditorProps,
138
} from '@grafana/data';
149
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
1510

16-
import { HaystackQuery, OpsQuery, HaystackDataSourceOptions, HaystackVariableQuery, QueryType } from './types';
17-
import { firstValueFrom, map, Observable } from 'rxjs';
18-
import { isRef, parseRef } from 'haystack';
19-
import { ComponentType } from 'react';
20-
import { VariableQueryEditor } from 'components/VariableQueryEditor';
11+
import { HaystackQuery, OpsQuery, HaystackDataSourceOptions, QueryType } from './types';
12+
import { firstValueFrom } from 'rxjs';
13+
import { HaystackVariableSupport } from 'HaystackVariableSupport';
2114

2215
export const queryTypes: QueryType[] = [
2316
{ label: 'Eval', value: 'eval', apiRequirements: ['eval'], description: 'Evaluate an Axon expression' },
@@ -34,9 +27,7 @@ export const queryTypes: QueryType[] = [
3427
export class DataSource extends DataSourceWithBackend<HaystackQuery, HaystackDataSourceOptions> {
3528
constructor(instanceSettings: DataSourceInstanceSettings<HaystackDataSourceOptions>) {
3629
super(instanceSettings);
37-
this.variables = new HaystackVariableSupport((request) => {
38-
return this.query(request)
39-
});
30+
this.variables = new HaystackVariableSupport(this);
4031
}
4132

4233
// Queries the available ops from the datasource and returns the queryTypes that are supported.
@@ -115,82 +106,3 @@ export class DataSource extends DataSourceWithBackend<HaystackQuery, HaystackDat
115106
};
116107
}
117108
}
118-
119-
export class HaystackVariableSupport extends CustomVariableSupport<DataSource, HaystackVariableQuery, HaystackQuery, HaystackDataSourceOptions> {
120-
editor: ComponentType<QueryEditorProps<DataSource, HaystackQuery, HaystackDataSourceOptions, HaystackVariableQuery>>;
121-
122-
// Requests data from the backend. This allows this class to reuse the DataSource.query method to get data.
123-
onQuery: (request: DataQueryRequest<HaystackVariableQuery>) => Observable<DataQueryResponse>;
124-
125-
constructor(onQuery: (request: DataQueryRequest<HaystackVariableQuery>) => Observable<DataQueryResponse>) {
126-
super();
127-
this.editor = VariableQueryEditor;
128-
this.onQuery = onQuery;
129-
}
130-
131-
query(request: DataQueryRequest<HaystackVariableQuery>): Observable<DataQueryResponse> {
132-
let variableQuery = request.targets[0];
133-
let observable = this.onQuery(request);
134-
return observable.pipe(
135-
map((response) => {
136-
if (response === undefined || response.errors !== undefined || response.data === undefined) {
137-
return response
138-
}
139-
140-
let variableValues = response.data.reduce((acc: MetricFindValue[], frame: DataFrame) => {
141-
// Default to the first field
142-
let column = frame.fields[0];
143-
if (variableQuery.column !== undefined && variableQuery.column !== '') {
144-
// If a column was input, match the column name
145-
column = frame.fields.find((field: Field) => field.name === variableQuery.column) ?? column;
146-
} else if (frame.fields.some((field: Field) => field.name === 'id')) {
147-
// If there is an id column, use that
148-
column = frame.fields.find((field: Field) => field.name === 'id') ?? column;
149-
}
150-
151-
// Default to the selected column
152-
let displayColumn = column;
153-
if (variableQuery.displayColumn !== undefined && variableQuery.displayColumn !== '') {
154-
// If a column was input, match the column name
155-
displayColumn = frame.fields.find((field: Field) => {
156-
return field.name === variableQuery.displayColumn
157-
}) ?? displayColumn;
158-
}
159-
160-
let variableValues = column.values.map((value, index) => {
161-
let variableValue = variableValueFromCell(value, column.type);
162-
163-
let displayValue = displayColumn.values[index];
164-
let variableText = variableTextFromCell(displayValue, displayColumn.type);
165-
166-
return { text: variableText, value: variableValue };
167-
});
168-
return acc.concat(variableValues);
169-
}, []);
170-
return { ...response, data: variableValues };
171-
})
172-
);
173-
}
174-
}
175-
176-
177-
function variableValueFromCell(value: string, columnType: FieldType): string {
178-
switch (columnType) {
179-
case FieldType.string:
180-
if (isRef(value)) {
181-
return parseRef(value).id;
182-
}
183-
}
184-
return value;
185-
}
186-
187-
function variableTextFromCell(value: string, columnType: FieldType): string {
188-
switch (columnType) {
189-
case FieldType.string:
190-
if (isRef(value)) {
191-
let ref = parseRef(value);
192-
return ref.dis ?? ref.id;
193-
}
194-
}
195-
return value;
196-
}

0 commit comments

Comments
 (0)