Skip to content

Commit 5821362

Browse files
authored
Configurable timePath and timeFormat (#49)
1 parent 05a5ace commit 5821362

9 files changed

Lines changed: 269 additions & 55 deletions

File tree

dist/README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ annotations, and dashboard variables.
2929
![DeutscheBahn Arrivals Table](https://user-images.githubusercontent.com/1627510/90258294-f1bf2b00-de0d-11ea-8768-34b4ef37c125.png)
3030
![DeutscheBahn Arrivals Annotations](https://user-images.githubusercontent.com/1627510/90258316-f8e63900-de0d-11ea-91eb-d40532d5b768.png)
3131
![GitHub Security Advisories](https://user-images.githubusercontent.com/1627510/90258319-fbe12980-de0d-11ea-8ea2-c97bbc398aa4.png)
32+
![DeutscheBahn Station Variable](https://user-images.githubusercontent.com/1627510/110505565-e1c9aa00-80c3-11eb-85bb-10e5471fb151.png)
3233

3334
# Examples
3435

@@ -83,7 +84,7 @@ In the above example, "Group by" and "Alias by" are defined. "Group by" allows
8384
you to split up an array of data into multiple data points. "Alias by" is used
8485
as the name of the data point. You can make alias use text from the query or
8586
even the field name by using `$field_<your.field.name>` for the value of the
86-
field, or `$fieldName` for the name of the field. For instance, if `$fieldName`
87+
field,
8788
was used, it would be replaced by "batteryVoltage" because that's the name of
8889
the field. If `$field_identityInfo.displayName` was used, it would be replaced
8990
with the value of displayName. Using `$fieldName` can be useful if you're
@@ -126,3 +127,24 @@ The above example has two tags: "tag1" and "tag2". If a `TimeEnd` field is
126127
present, the annotation will be shown over a period of time. You can also
127128
separate the data path with commas to provide multiple data paths as shown with
128129
both server1 and server2.
130+
131+
## Dashboard Variable Queries
132+
133+
Dashboard variables can be populated by a GraphQL query that returns an array of
134+
objects. If the objects contain both `__text` and `__value` fields then they
135+
will be used (the `__text` field will be displayed, the `__value` field will be
136+
used in substitutions). Otherwise the values of all fields will be appended to
137+
the variable value list.
138+
139+
```graphql
140+
query {
141+
search(searchTerm: "$query") {
142+
stations {
143+
__value: primaryEvaId
144+
__text: name
145+
}
146+
}
147+
}
148+
```
149+
150+
- Data path: `search.stations`

dist/module.js

Lines changed: 62 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/module.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,74 @@
1-
<div class="gf-form-group">
2-
<div class="gf-form">
3-
<textarea type="text" class="gf-form-input" ng-model='ctrl.annotation.queryText' placeholder="GraphQL Query">
1+
<html>
2+
<head>
3+
<title></title>
4+
</head>
5+
6+
<body>
7+
<div class="gf-form-group">
8+
<div class="gf-form">
9+
<textarea type="text" class="gf-form-input" ng-model=
10+
'ctrl.annotation.queryText' placeholder="GraphQL Query">
411
query {
512
data:submissions(user:"$user", from:"$timeFrom", to:"$timeTo"){
613
Time:submitTime
714
idle running completed
815
}
916
}
1017
</textarea>
18+
</div>
19+
20+
<div class="gf-form">
21+
<label class="gf-form-label width-7" title=
22+
"Data path (comma separated for multiple data paths)">Data
23+
Path</label> <input type="text" class="gf-form-input"
24+
ng-model='ctrl.annotation.dataPath' placeholder="data" value=
25+
"data">
26+
</div>
27+
28+
<div class="gf-form">
29+
<label class="gf-form-label width-7" title=
30+
"Time path under data path">Time Path</label> <input type=
31+
"text" class="gf-form-input" ng-model=
32+
'ctrl.annotation.timePath' placeholder="Time" value="Time">
33+
</div>
34+
35+
<div class="gf-form">
36+
<label class="gf-form-label width-7" title=
37+
"Optional end time path under data path">End Time
38+
Path</label> <input type="text" class="gf-form-input"
39+
ng-model='ctrl.annotation.endTimePath' placeholder="TimeEnd"
40+
value="TimeEnd">
41+
</div>
42+
43+
<div class="gf-form">
44+
<label class="gf-form-label width-7" title=
45+
"Optional time format">Time Format</label> <input type="text"
46+
class="gf-form-input" ng-model='ctrl.annotation.timeFormat'
47+
value="">
48+
</div>
49+
50+
<div class="gf-form">
51+
<label class="gf-form-label width-7" title=
52+
"Annotation title. Include fields like $field_&lt;field name&gt;">
53+
Title</label> <input type="text" class="gf-form-input"
54+
ng-model='ctrl.annotation.annotationTitle' placeholder=
55+
"Title" value="">
56+
</div>
57+
58+
<div class="gf-form">
59+
<label class="gf-form-label width-7" title=
60+
"Annotation text. Include fields like $field_&lt;field name&gt;">
61+
Text</label> <input type="text" class="gf-form-input"
62+
ng-model='ctrl.annotation.annotationText' placeholder="Text"
63+
value="">
64+
</div>
65+
66+
<div class="gf-form">
67+
<label class="gf-form-label width-7" title=
68+
"Tags (comma-separated)">Tags</label> <input type="text"
69+
class="gf-form-input" ng-model=
70+
'ctrl.annotation.annotationTags' placeholder="Tags" value="">
71+
</div>
1172
</div>
12-
<div class="gf-form">
13-
<input type="text" class="gf-form-input" ng-model='ctrl.annotation.dataPath' placeholder="Data path (comma separated for multiple data paths)" value="data"/>
14-
</div>
15-
<div class="gf-form">
16-
<input type="text" class="gf-form-input" ng-model='ctrl.annotation.annotationTitle' placeholder="Title" value=""/>
17-
</div>
18-
<div class="gf-form">
19-
<input type="text" class="gf-form-input" ng-model='ctrl.annotation.annotationText' placeholder="Text" value=""/>
20-
</div>
21-
<div class="gf-form">
22-
<input type="text" class="gf-form-input" ng-model='ctrl.annotation.annotationTags' placeholder="Tags (Comma separated)" value=""/>
23-
</div>
24-
</div>
73+
</body>
74+
</html>

dist/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
{ "name": "GitHub Security Advisories", "path": "img/github_security_advisories.png"}
2626
],
2727
"version": "1.2.0",
28-
"updated": "2021-03-09"
28+
"updated": "2021-03-16"
2929
},
3030

3131
"dependencies": {

src/DataSource.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
146146
const dataFrameArray: DataFrame[] = [];
147147
for (let res of results) {
148148
const dataPathArray: string[] = DataSource.getDataPathArray(res.query.dataPath);
149-
const { groupBy, aliasBy } = res.query;
149+
const { timePath, timeFormat, groupBy, aliasBy } = res.query;
150150
const split = groupBy.split(',');
151151
const groupByList: string[] = [];
152152
for (const element of split) {
@@ -160,8 +160,8 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
160160

161161
const dataFrameMap = new Map<string, MutableDataFrame>();
162162
for (const doc of docs) {
163-
if (doc.Time) {
164-
doc.Time = dateTime(doc.Time);
163+
if (timePath in doc) {
164+
doc[timePath] = dateTime(doc[timePath], timeFormat);
165165
}
166166
const identifiers: string[] = [];
167167
for (const groupByElement of groupByList) {
@@ -178,7 +178,7 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
178178
}
179179
for (const fieldName in doc) {
180180
let t: FieldType = FieldType.string;
181-
if (fieldName === 'Time' || isRFC3339_ISO6801(String(doc[fieldName]))) {
181+
if (fieldName === timePath || isRFC3339_ISO6801(String(doc[fieldName]))) {
182182
t = FieldType.time;
183183
} else if (_.isNumber(doc[fieldName])) {
184184
t = FieldType.number;
@@ -227,17 +227,18 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
227227
return Promise.all([this.createQuery(query, options.range)]).then((results: any) => {
228228
const r: AnnotationEvent[] = [];
229229
for (const res of results) {
230+
const { timePath, endTimePath, timeFormat } = res.query;
230231
const dataPathArray: string[] = DataSource.getDataPathArray(res.query.dataPath);
231232
for (const dataPath of dataPathArray) {
232233
const docs: any[] = DataSource.getDocs(res.results.data, dataPath);
233234
for (const doc of docs) {
234235
const annotation: AnnotationEvent = {};
235-
if (doc.Time) {
236-
annotation.time = dateTime(doc.Time).valueOf();
236+
if (timePath in doc) {
237+
annotation.time = dateTime(doc[timePath], timeFormat).valueOf();
237238
}
238-
if (doc.TimeEnd) {
239+
if (endTimePath in doc) {
239240
annotation.isRegion = true;
240-
annotation.timeEnd = dateTime(doc.TimeEnd).valueOf();
241+
annotation.timeEnd = dateTime(doc[endTimePath], timeFormat).valueOf();
241242
}
242243
let title = query.annotationTitle;
243244
let text = query.annotationText;

0 commit comments

Comments
 (0)