mirror of https://github.com/grafana/grafana
Templating: Introduce macros to simplify and optimize some scopedVars (#65317)
* Templating: Introduce macros to simplify and optimize some scopedVars * Fixing tests * fix test * minor fix * refactoring so macros work with formatting * remove breaking change and keep current inconsistency * Rename valueIndex to rowIndex * Minor fixes * Added test dashboard * Added tags to dashboard * Update * Added test to check it returns match * Update * Fixed dashboard * fixpull/65475/head
parent
2b73f8cfd5
commit
b7b608418d
@ -0,0 +1,871 @@ |
|||||||
|
{ |
||||||
|
"annotations": { |
||||||
|
"list": [ |
||||||
|
{ |
||||||
|
"builtIn": 1, |
||||||
|
"datasource": { |
||||||
|
"type": "grafana", |
||||||
|
"uid": "-- Grafana --" |
||||||
|
}, |
||||||
|
"enable": true, |
||||||
|
"hide": true, |
||||||
|
"iconColor": "rgba(0, 211, 255, 1)", |
||||||
|
"name": "Annotations & Alerts", |
||||||
|
"type": "dashboard" |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"editable": true, |
||||||
|
"fiscalYearStartMonth": 0, |
||||||
|
"graphTooltip": 0, |
||||||
|
"id": 1267, |
||||||
|
"links": [], |
||||||
|
"liveNow": false, |
||||||
|
"panels": [ |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 3, |
||||||
|
"w": 24, |
||||||
|
"x": 0, |
||||||
|
"y": 0 |
||||||
|
}, |
||||||
|
"id": 8, |
||||||
|
"options": { |
||||||
|
"code": { |
||||||
|
"language": "plaintext", |
||||||
|
"showLineNumbers": false, |
||||||
|
"showMiniMap": false |
||||||
|
}, |
||||||
|
"content": "* `__all_variables`=${__all_variables}\n* `__url_time_range`=${__url_time_range}", |
||||||
|
"mode": "markdown" |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"title": "Panel Title", |
||||||
|
"type": "text" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"custom": { |
||||||
|
"align": "auto", |
||||||
|
"cellOptions": { |
||||||
|
"type": "auto" |
||||||
|
}, |
||||||
|
"inspect": false |
||||||
|
}, |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"targetBlank": true, |
||||||
|
"title": "value=${__value.raw}&time=${__value.time}&__value:percentencode=${__value:percentencode}&text=${__value.text}", |
||||||
|
"url": "value=${__value.raw}&time=${__value.time}justvalue=${__value:percentencode}&text=${__value.text}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"unit": "percent" |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 0, |
||||||
|
"y": 3 |
||||||
|
}, |
||||||
|
"id": 2, |
||||||
|
"options": { |
||||||
|
"cellHeight": "sm", |
||||||
|
"footer": { |
||||||
|
"countRows": false, |
||||||
|
"fields": "", |
||||||
|
"reducer": [ |
||||||
|
"sum" |
||||||
|
], |
||||||
|
"show": false |
||||||
|
}, |
||||||
|
"showHeader": true, |
||||||
|
"showRowNums": false |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"title": "DataLink: with __value.raw=&__value.time=&__value:percentencode=", |
||||||
|
"type": "table" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"targetBlank": true, |
||||||
|
"title": "Value link", |
||||||
|
"url": "value=${__value.raw}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 12, |
||||||
|
"y": 3 |
||||||
|
}, |
||||||
|
"id": 3, |
||||||
|
"options": { |
||||||
|
"colorMode": "value", |
||||||
|
"graphMode": "area", |
||||||
|
"justifyMode": "auto", |
||||||
|
"orientation": "auto", |
||||||
|
"reduceOptions": { |
||||||
|
"calcs": [ |
||||||
|
"lastNotNull" |
||||||
|
], |
||||||
|
"fields": "", |
||||||
|
"values": false |
||||||
|
}, |
||||||
|
"textMode": "auto" |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "random_walk", |
||||||
|
"seriesCount": 5 |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "Stat panel with __value.raw ", |
||||||
|
"type": "stat" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "continuous-GrYlRd" |
||||||
|
}, |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"title": "${__value.raw}", |
||||||
|
"url": "${__value.raw}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 0, |
||||||
|
"y": 10 |
||||||
|
}, |
||||||
|
"id": 6, |
||||||
|
"options": { |
||||||
|
"displayMode": "basic", |
||||||
|
"minVizHeight": 10, |
||||||
|
"minVizWidth": 0, |
||||||
|
"orientation": "horizontal", |
||||||
|
"reduceOptions": { |
||||||
|
"calcs": [], |
||||||
|
"fields": "", |
||||||
|
"values": true |
||||||
|
}, |
||||||
|
"showUnfilled": true, |
||||||
|
"valueMode": "color" |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"csvFileName": "browser_marketshare.csv", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "csv_file" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "data link __value.raw", |
||||||
|
"transformations": [ |
||||||
|
{ |
||||||
|
"id": "limit", |
||||||
|
"options": { |
||||||
|
"limitField": 5 |
||||||
|
} |
||||||
|
} |
||||||
|
], |
||||||
|
"type": "bargauge" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"description": "Since this is using getFrameDisplayName it works kind badly (especially with testdata) and only returns the `Series (refId)`. \n\nSo this should show:\n* Series (Query1)\n* Series (Query2)", |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"displayName": "${__series.name}", |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"targetBlank": true, |
||||||
|
"title": "Value link", |
||||||
|
"url": "value=${__calc}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 12, |
||||||
|
"y": 10 |
||||||
|
}, |
||||||
|
"id": 12, |
||||||
|
"options": { |
||||||
|
"colorMode": "value", |
||||||
|
"graphMode": "area", |
||||||
|
"justifyMode": "auto", |
||||||
|
"orientation": "auto", |
||||||
|
"reduceOptions": { |
||||||
|
"calcs": [ |
||||||
|
"lastNotNull" |
||||||
|
], |
||||||
|
"fields": "", |
||||||
|
"values": false |
||||||
|
}, |
||||||
|
"textMode": "auto" |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"alias": "", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "Query1", |
||||||
|
"scenarioId": "random_walk", |
||||||
|
"seriesCount": 1 |
||||||
|
}, |
||||||
|
{ |
||||||
|
"alias": "", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"hide": false, |
||||||
|
"refId": "Query2", |
||||||
|
"scenarioId": "random_walk", |
||||||
|
"seriesCount": 1 |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "${series.name} in display name", |
||||||
|
"type": "stat" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"custom": { |
||||||
|
"align": "auto", |
||||||
|
"cellOptions": { |
||||||
|
"type": "auto" |
||||||
|
}, |
||||||
|
"inspect": false |
||||||
|
}, |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"title": "__data.refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}", |
||||||
|
"url": "refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"unit": "percent" |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 0, |
||||||
|
"y": 17 |
||||||
|
}, |
||||||
|
"id": 11, |
||||||
|
"options": { |
||||||
|
"cellHeight": "sm", |
||||||
|
"footer": { |
||||||
|
"countRows": false, |
||||||
|
"fields": "", |
||||||
|
"reducer": [ |
||||||
|
"sum" |
||||||
|
], |
||||||
|
"show": false |
||||||
|
}, |
||||||
|
"showHeader": true, |
||||||
|
"showRowNums": false |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"labels": "cluster=US", |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "random_walk" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "DataLink: refId=${__data.refId}&__data.fields[0]=${__data.fields[0]}&cluster=${__field.labels.cluster}", |
||||||
|
"type": "table" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "palette-classic" |
||||||
|
}, |
||||||
|
"custom": { |
||||||
|
"axisCenteredZero": false, |
||||||
|
"axisColorMode": "text", |
||||||
|
"axisLabel": "", |
||||||
|
"axisPlacement": "auto", |
||||||
|
"barAlignment": 0, |
||||||
|
"drawStyle": "line", |
||||||
|
"fillOpacity": 0, |
||||||
|
"gradientMode": "none", |
||||||
|
"hideFrom": { |
||||||
|
"legend": false, |
||||||
|
"tooltip": false, |
||||||
|
"viz": false |
||||||
|
}, |
||||||
|
"lineInterpolation": "linear", |
||||||
|
"lineWidth": 1, |
||||||
|
"pointSize": 5, |
||||||
|
"scaleDistribution": { |
||||||
|
"type": "linear" |
||||||
|
}, |
||||||
|
"showPoints": "auto", |
||||||
|
"spanNulls": false, |
||||||
|
"stacking": { |
||||||
|
"group": "A", |
||||||
|
"mode": "none" |
||||||
|
}, |
||||||
|
"thresholdsStyle": { |
||||||
|
"mode": "off" |
||||||
|
} |
||||||
|
}, |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"title": "${__value.raw}", |
||||||
|
"url": "${__value.raw}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 12, |
||||||
|
"y": 17 |
||||||
|
}, |
||||||
|
"id": 10, |
||||||
|
"options": { |
||||||
|
"legend": { |
||||||
|
"calcs": [], |
||||||
|
"displayMode": "list", |
||||||
|
"placement": "bottom", |
||||||
|
"showLegend": true |
||||||
|
}, |
||||||
|
"tooltip": { |
||||||
|
"mode": "single", |
||||||
|
"sort": "none" |
||||||
|
} |
||||||
|
}, |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"alias": "10,20,30,40", |
||||||
|
"csvContent": "Time, value, test\n\"2023-03-24T17:12:12.347Z\", 10,hello\n\"2023-03-24T17:22:12.347Z\", 20,asd\n\"2023-03-24T17:32:12.347Z\", 30,asd2\n\"2023-03-24T17:42:12.347Z\", 40,as34\n", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "csv_content" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"alias": "5,6,7", |
||||||
|
"csvContent": "Time, value, test\n\"2023-03-24T17:12:12.347Z\", 5,hello\n\"2023-03-24T17:22:12.347Z\", 6,asd\n\"2023-03-24T17:42:12.347Z\", 7,as34\n", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "B", |
||||||
|
"scenarioId": "csv_content" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "Data links with ${__value.raw}", |
||||||
|
"transformations": [ |
||||||
|
{ |
||||||
|
"id": "joinByField", |
||||||
|
"options": {} |
||||||
|
} |
||||||
|
], |
||||||
|
"type": "timeseries" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"custom": { |
||||||
|
"align": "auto", |
||||||
|
"cellOptions": { |
||||||
|
"type": "auto" |
||||||
|
}, |
||||||
|
"inspect": false |
||||||
|
}, |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"title": "__field.name=${__field.name}&__field.labels.cluster=${__field.labels.cluster}", |
||||||
|
"url": "__field.name=${__field.name}&__field.labels.cluster=${__field.labels.cluster}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"unit": "percent" |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 0, |
||||||
|
"y": 24 |
||||||
|
}, |
||||||
|
"id": 13, |
||||||
|
"options": { |
||||||
|
"cellHeight": "sm", |
||||||
|
"footer": { |
||||||
|
"countRows": false, |
||||||
|
"fields": "", |
||||||
|
"reducer": [ |
||||||
|
"sum" |
||||||
|
], |
||||||
|
"show": false |
||||||
|
}, |
||||||
|
"showHeader": true, |
||||||
|
"showRowNums": false |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"labels": "cluster=US", |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "random_walk" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "DataLink: __field.name=&__field.labels.cluster", |
||||||
|
"type": "table" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"displayName": "$__cell_0 = $__cell_2", |
||||||
|
"links": [], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 12, |
||||||
|
"y": 24 |
||||||
|
}, |
||||||
|
"id": 14, |
||||||
|
"options": { |
||||||
|
"colorMode": "value", |
||||||
|
"graphMode": "area", |
||||||
|
"justifyMode": "auto", |
||||||
|
"orientation": "auto", |
||||||
|
"reduceOptions": { |
||||||
|
"calcs": [ |
||||||
|
"lastNotNull" |
||||||
|
], |
||||||
|
"fields": "", |
||||||
|
"values": true |
||||||
|
}, |
||||||
|
"textMode": "auto" |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"alias": "", |
||||||
|
"csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "csv_content" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "DisplayName with __cell_0 = __cell_2", |
||||||
|
"type": "stat" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"custom": { |
||||||
|
"align": "auto", |
||||||
|
"cellOptions": { |
||||||
|
"type": "auto" |
||||||
|
}, |
||||||
|
"inspect": false |
||||||
|
}, |
||||||
|
"displayName": "${__field.name}", |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"targetBlank": true, |
||||||
|
"title": "Value link", |
||||||
|
"url": "value=${__calc}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 0, |
||||||
|
"y": 31 |
||||||
|
}, |
||||||
|
"id": 15, |
||||||
|
"options": { |
||||||
|
"cellHeight": "sm", |
||||||
|
"footer": { |
||||||
|
"countRows": false, |
||||||
|
"fields": "", |
||||||
|
"reducer": [ |
||||||
|
"sum" |
||||||
|
], |
||||||
|
"show": false |
||||||
|
}, |
||||||
|
"showHeader": true, |
||||||
|
"showRowNums": false |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"alias": "", |
||||||
|
"csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "csv_content" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "DisplayName: __field.name", |
||||||
|
"type": "table" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"description": "The stat display names should be \n* Stockholm = Bad\n* New York = Good \n", |
||||||
|
"fieldConfig": { |
||||||
|
"defaults": { |
||||||
|
"color": { |
||||||
|
"mode": "thresholds" |
||||||
|
}, |
||||||
|
"displayName": "${__data.fields[0]} = ${__data.fields[2]}", |
||||||
|
"links": [ |
||||||
|
{ |
||||||
|
"targetBlank": true, |
||||||
|
"title": "__data.fields[0] = ${__data.fields[0]} = __value.raw = ${__value.raw}", |
||||||
|
"url": "__data.fields[0] = ${__data.fields[0]} = __value.raw = ${__value.raw}" |
||||||
|
} |
||||||
|
], |
||||||
|
"mappings": [], |
||||||
|
"thresholds": { |
||||||
|
"mode": "absolute", |
||||||
|
"steps": [ |
||||||
|
{ |
||||||
|
"color": "green" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"color": "red", |
||||||
|
"value": 80 |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
"overrides": [] |
||||||
|
}, |
||||||
|
"gridPos": { |
||||||
|
"h": 7, |
||||||
|
"w": 12, |
||||||
|
"x": 12, |
||||||
|
"y": 31 |
||||||
|
}, |
||||||
|
"id": 16, |
||||||
|
"options": { |
||||||
|
"colorMode": "value", |
||||||
|
"graphMode": "area", |
||||||
|
"justifyMode": "auto", |
||||||
|
"orientation": "auto", |
||||||
|
"reduceOptions": { |
||||||
|
"calcs": [ |
||||||
|
"lastNotNull" |
||||||
|
], |
||||||
|
"fields": "", |
||||||
|
"values": true |
||||||
|
}, |
||||||
|
"textMode": "auto" |
||||||
|
}, |
||||||
|
"pluginVersion": "9.5.0-pre", |
||||||
|
"targets": [ |
||||||
|
{ |
||||||
|
"alias": "", |
||||||
|
"csvContent": "name, value, name2\nStockholm, 10, Good\nNew York, 15, Bad", |
||||||
|
"datasource": { |
||||||
|
"type": "testdata", |
||||||
|
"uid": "PD8C576611E62080A" |
||||||
|
}, |
||||||
|
"refId": "A", |
||||||
|
"scenarioId": "csv_content" |
||||||
|
} |
||||||
|
], |
||||||
|
"title": "$__data.fields[0] = $__data.fields[2] with datalinks", |
||||||
|
"type": "stat" |
||||||
|
} |
||||||
|
], |
||||||
|
"refresh": "", |
||||||
|
"schemaVersion": 38, |
||||||
|
"style": "dark", |
||||||
|
"tags": ["gdev", "templating"], |
||||||
|
"templating": { |
||||||
|
"list": [ |
||||||
|
{ |
||||||
|
"current": { |
||||||
|
"selected": false, |
||||||
|
"text": "A", |
||||||
|
"value": "A" |
||||||
|
}, |
||||||
|
"hide": 0, |
||||||
|
"includeAll": false, |
||||||
|
"multi": false, |
||||||
|
"name": "customVar", |
||||||
|
"options": [ |
||||||
|
{ |
||||||
|
"selected": true, |
||||||
|
"text": "A", |
||||||
|
"value": "A" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"selected": false, |
||||||
|
"text": "B", |
||||||
|
"value": "B" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"selected": false, |
||||||
|
"text": "C", |
||||||
|
"value": "C" |
||||||
|
} |
||||||
|
], |
||||||
|
"query": "A,B,C", |
||||||
|
"queryValue": "", |
||||||
|
"skipUrlSync": false, |
||||||
|
"type": "custom" |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
"time": { |
||||||
|
"from": "2023-03-24T17:12:12.347Z", |
||||||
|
"to": "2023-03-24T17:42:12.347Z" |
||||||
|
}, |
||||||
|
"timepicker": {}, |
||||||
|
"timezone": "", |
||||||
|
"title": "Templating - Macros", |
||||||
|
"uid": "e7c29343-6d1e-4167-9c13-803fe5be8c46", |
||||||
|
"version": 48, |
||||||
|
"weekStart": "" |
||||||
|
} |
||||||
@ -1,8 +1,24 @@ |
|||||||
|
import { DataFrame, Field } from './dataFrame'; |
||||||
|
import { DisplayValue } from './displayValue'; |
||||||
|
|
||||||
export interface ScopedVar<T = any> { |
export interface ScopedVar<T = any> { |
||||||
text?: any; |
text?: any; |
||||||
value: T; |
value: T; |
||||||
skipUrlSync?: boolean; |
|
||||||
skipFormat?: boolean; |
|
||||||
} |
} |
||||||
|
|
||||||
export interface ScopedVars extends Record<string, ScopedVar> {} |
export interface ScopedVars { |
||||||
|
__dataContext?: DataContextScopedVar; |
||||||
|
[key: string]: ScopedVar | undefined; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Used by data link macros |
||||||
|
*/ |
||||||
|
export interface DataContextScopedVar { |
||||||
|
value: { |
||||||
|
frame: DataFrame; |
||||||
|
field: Field; |
||||||
|
rowIndex?: number; |
||||||
|
calculatedValue?: DisplayValue; |
||||||
|
}; |
||||||
|
} |
||||||
|
|||||||
@ -0,0 +1,86 @@ |
|||||||
|
import { initTemplateSrv } from 'test/helpers/initTemplateSrv'; |
||||||
|
|
||||||
|
import { DataContextScopedVar, FieldType, toDataFrame } from '@grafana/data'; |
||||||
|
import { TemplateSrv } from '@grafana/runtime'; |
||||||
|
|
||||||
|
describe('templateSrv', () => { |
||||||
|
let _templateSrv: TemplateSrv; |
||||||
|
|
||||||
|
beforeEach(() => { |
||||||
|
_templateSrv = initTemplateSrv('hello', []); |
||||||
|
}); |
||||||
|
|
||||||
|
const data = toDataFrame({ |
||||||
|
name: 'A', |
||||||
|
fields: [ |
||||||
|
{ |
||||||
|
name: 'number', |
||||||
|
type: FieldType.number, |
||||||
|
values: [5, 10], |
||||||
|
display: (value: number) => { |
||||||
|
return { text: value.toString(), numeric: value, suffix: '%' }; |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'time', |
||||||
|
type: FieldType.time, |
||||||
|
values: [5000, 10000], |
||||||
|
}, |
||||||
|
], |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should interpolate __value.* expressions with dataContext in scopedVars', () => { |
||||||
|
const dataContext: DataContextScopedVar = { |
||||||
|
value: { |
||||||
|
frame: data, |
||||||
|
field: data.fields[0], |
||||||
|
rowIndex: 1, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
const scopedVars = { __dataContext: dataContext }; |
||||||
|
|
||||||
|
expect(_templateSrv.replace('${__value.raw}', scopedVars)).toBe('10'); |
||||||
|
expect(_templateSrv.replace('${__value.numeric}', scopedVars)).toBe('10'); |
||||||
|
expect(_templateSrv.replace('${__value}', scopedVars)).toBe('10%'); |
||||||
|
expect(_templateSrv.replace('${__value.text}', scopedVars)).toBe('10'); |
||||||
|
expect(_templateSrv.replace('${__value.time}', scopedVars)).toBe('10000'); |
||||||
|
// can apply format as well
|
||||||
|
expect(_templateSrv.replace('${__value:percentencode}', scopedVars)).toBe('10%25'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should interpolate __value.* with calculatedValue', () => { |
||||||
|
const dataContext: DataContextScopedVar = { |
||||||
|
value: { |
||||||
|
frame: data, |
||||||
|
field: data.fields[0], |
||||||
|
calculatedValue: { |
||||||
|
text: '15', |
||||||
|
numeric: 15, |
||||||
|
suffix: '%', |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
const scopedVars = { __dataContext: dataContext }; |
||||||
|
|
||||||
|
expect(_templateSrv.replace('${__value.raw}', scopedVars)).toBe('15'); |
||||||
|
expect(_templateSrv.replace('${__value.numeric}', scopedVars)).toBe('15'); |
||||||
|
expect(_templateSrv.replace('${__value}', scopedVars)).toBe('15%'); |
||||||
|
expect(_templateSrv.replace('${__value.text}', scopedVars)).toBe('15%'); |
||||||
|
expect(_templateSrv.replace('${__value.time}', scopedVars)).toBe(''); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should return match when ${__value.*} is used and no dataContext or rowIndex is found', () => { |
||||||
|
const dataContext: DataContextScopedVar = { |
||||||
|
value: { |
||||||
|
frame: data, |
||||||
|
field: data.fields[0], |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
const scopedVars = { __dataContext: dataContext }; |
||||||
|
|
||||||
|
expect(_templateSrv.replace('${__value.raw}', scopedVars)).toBe('${__value.raw}'); |
||||||
|
}); |
||||||
|
}); |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
import { DisplayProcessor, FieldType, formattedValueToString, getDisplayProcessor, ScopedVars } from '@grafana/data'; |
||||||
|
import { VariableCustomFormatterFn } from '@grafana/scenes'; |
||||||
|
|
||||||
|
import { formatVariableValue } from './formatVariableValue'; |
||||||
|
|
||||||
|
/** |
||||||
|
* ${__value.raw/nummeric/text/time} macro |
||||||
|
*/ |
||||||
|
export function valueMacro( |
||||||
|
match: string, |
||||||
|
fieldPath?: string, |
||||||
|
scopedVars?: ScopedVars, |
||||||
|
format?: string | VariableCustomFormatterFn |
||||||
|
) { |
||||||
|
const value = getValueForValueMacro(match, fieldPath, scopedVars); |
||||||
|
return formatVariableValue(value, format); |
||||||
|
} |
||||||
|
|
||||||
|
function getValueForValueMacro(match: string, fieldPath?: string, scopedVars?: ScopedVars) { |
||||||
|
const dataContext = scopedVars?.__dataContext; |
||||||
|
if (!dataContext) { |
||||||
|
return match; |
||||||
|
} |
||||||
|
|
||||||
|
const { frame, rowIndex, field, calculatedValue } = dataContext.value; |
||||||
|
|
||||||
|
if (calculatedValue) { |
||||||
|
switch (fieldPath) { |
||||||
|
case 'numeric': |
||||||
|
return calculatedValue.numeric.toString(); |
||||||
|
case 'raw': |
||||||
|
return calculatedValue.numeric; |
||||||
|
case 'time': |
||||||
|
return ''; |
||||||
|
case 'text': |
||||||
|
default: |
||||||
|
return formattedValueToString(calculatedValue); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (rowIndex === undefined) { |
||||||
|
return match; |
||||||
|
} |
||||||
|
|
||||||
|
if (fieldPath === 'time') { |
||||||
|
const timeField = frame.fields.find((f) => f.type === FieldType.time); |
||||||
|
return timeField ? timeField.values.get(rowIndex) : undefined; |
||||||
|
} |
||||||
|
|
||||||
|
const value = field.values.get(rowIndex); |
||||||
|
if (fieldPath === 'raw') { |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
const displayProcessor = field.display ?? getFallbackDisplayProcessor(); |
||||||
|
const result = displayProcessor(value); |
||||||
|
|
||||||
|
switch (fieldPath) { |
||||||
|
case 'numeric': |
||||||
|
return result.numeric; |
||||||
|
case 'text': |
||||||
|
return result.text; |
||||||
|
default: |
||||||
|
return formattedValueToString(result); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let fallbackDisplayProcessor: DisplayProcessor | undefined; |
||||||
|
|
||||||
|
function getFallbackDisplayProcessor() { |
||||||
|
if (!fallbackDisplayProcessor) { |
||||||
|
fallbackDisplayProcessor = getDisplayProcessor(); |
||||||
|
} |
||||||
|
|
||||||
|
return fallbackDisplayProcessor; |
||||||
|
} |
||||||
@ -0,0 +1,105 @@ |
|||||||
|
import { silenceConsoleOutput } from 'test/core/utils/silenceConsoleOutput'; |
||||||
|
|
||||||
|
import { VariableFormatID } from '@grafana/schema'; |
||||||
|
|
||||||
|
import { formatVariableValue } from './formatVariableValue'; |
||||||
|
|
||||||
|
describe('format variable to string values', () => { |
||||||
|
silenceConsoleOutput(); |
||||||
|
|
||||||
|
it('single value should return value', () => { |
||||||
|
const result = formatVariableValue('test'); |
||||||
|
expect(result).toBe('test'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should use glob format when unknown format provided', () => { |
||||||
|
let result = formatVariableValue('test', 'nonexistentformat'); |
||||||
|
expect(result).toBe('test'); |
||||||
|
result = formatVariableValue(['test', 'test1'], 'nonexistentformat'); |
||||||
|
expect(result).toBe('{test,test1}'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and glob format should render glob string', () => { |
||||||
|
const result = formatVariableValue(['test', 'test2'], 'glob'); |
||||||
|
expect(result).toBe('{test,test2}'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and lucene should render as lucene expr', () => { |
||||||
|
const result = formatVariableValue(['test', 'test2'], 'lucene'); |
||||||
|
expect(result).toBe('("test" OR "test2")'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and regex format should render regex string', () => { |
||||||
|
const result = formatVariableValue(['test.', 'test2'], 'regex'); |
||||||
|
expect(result).toBe('(test\\.|test2)'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and pipe should render pipe string', () => { |
||||||
|
const result = formatVariableValue(['test', 'test2'], 'pipe'); |
||||||
|
expect(result).toBe('test|test2'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and distributed should render distributed string', () => { |
||||||
|
const result = formatVariableValue(['test', 'test2'], 'distributed', { |
||||||
|
name: 'build', |
||||||
|
}); |
||||||
|
expect(result).toBe('test,build=test2'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and distributed should render when not string', () => { |
||||||
|
const result = formatVariableValue(['test'], 'distributed', { |
||||||
|
name: 'build', |
||||||
|
}); |
||||||
|
expect(result).toBe('test'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and csv format should render csv string', () => { |
||||||
|
const result = formatVariableValue(['test', 'test2'], VariableFormatID.CSV); |
||||||
|
expect(result).toBe('test,test2'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and percentencode format should render percent-encoded string', () => { |
||||||
|
const result = formatVariableValue(['foo()bar BAZ', 'test2'], VariableFormatID.PercentEncode); |
||||||
|
expect(result).toBe('%7Bfoo%28%29bar%20BAZ%2Ctest2%7D'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('slash should be properly escaped in regex format', () => { |
||||||
|
const result = formatVariableValue('Gi3/14', 'regex'); |
||||||
|
expect(result).toBe('Gi3\\/14'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('single value and singlequote format should render string with value enclosed in single quotes', () => { |
||||||
|
const result = formatVariableValue('test', 'singlequote'); |
||||||
|
expect(result).toBe("'test'"); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and singlequote format should render string with values enclosed in single quotes', () => { |
||||||
|
const result = formatVariableValue(['test', "test'2"], 'singlequote'); |
||||||
|
expect(result).toBe("'test','test\\'2'"); |
||||||
|
}); |
||||||
|
|
||||||
|
it('single value and doublequote format should render string with value enclosed in double quotes', () => { |
||||||
|
const result = formatVariableValue('test', 'doublequote'); |
||||||
|
expect(result).toBe('"test"'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and doublequote format should render string with values enclosed in double quotes', () => { |
||||||
|
const result = formatVariableValue(['test', 'test"2'], 'doublequote'); |
||||||
|
expect(result).toBe('"test","test\\"2"'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('single value and sqlstring format should render string with value enclosed in single quotes', () => { |
||||||
|
const result = formatVariableValue("test'value", 'sqlstring'); |
||||||
|
expect(result).toBe(`'test''value'`); |
||||||
|
}); |
||||||
|
|
||||||
|
it('multi value and sqlstring format should render string with values enclosed in single quotes', () => { |
||||||
|
const result = formatVariableValue(['test', "test'value2"], 'sqlstring'); |
||||||
|
expect(result).toBe(`'test','test''value2'`); |
||||||
|
}); |
||||||
|
|
||||||
|
it('raw format should leave value intact and do no escaping', () => { |
||||||
|
const result = formatVariableValue("'test\n", 'raw'); |
||||||
|
expect(result).toBe("'test\n"); |
||||||
|
}); |
||||||
|
}); |
||||||
@ -0,0 +1,50 @@ |
|||||||
|
import { formatRegistry, FormatRegistryID } from '@grafana/scenes'; |
||||||
|
|
||||||
|
import { isAdHoc } from '../variables/guard'; |
||||||
|
|
||||||
|
import { getVariableWrapper } from './LegacyVariableWrapper'; |
||||||
|
|
||||||
|
export function formatVariableValue(value: any, format?: any, variable?: any, text?: string): string { |
||||||
|
// for some scopedVars there is no variable
|
||||||
|
variable = variable || {}; |
||||||
|
|
||||||
|
if (value === null || value === undefined) { |
||||||
|
return ''; |
||||||
|
} |
||||||
|
|
||||||
|
if (isAdHoc(variable) && format !== FormatRegistryID.queryParam) { |
||||||
|
return ''; |
||||||
|
} |
||||||
|
|
||||||
|
// if it's an object transform value to string
|
||||||
|
if (!Array.isArray(value) && typeof value === 'object') { |
||||||
|
value = `${value}`; |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof format === 'function') { |
||||||
|
return format(value, variable, formatVariableValue); |
||||||
|
} |
||||||
|
|
||||||
|
if (!format) { |
||||||
|
format = FormatRegistryID.glob; |
||||||
|
} |
||||||
|
|
||||||
|
// some formats have arguments that come after ':' character
|
||||||
|
let args = format.split(':'); |
||||||
|
if (args.length > 1) { |
||||||
|
format = args[0]; |
||||||
|
args = args.slice(1); |
||||||
|
} else { |
||||||
|
args = []; |
||||||
|
} |
||||||
|
|
||||||
|
let formatItem = formatRegistry.getIfExists(format); |
||||||
|
|
||||||
|
if (!formatItem) { |
||||||
|
console.error(`Variable format ${format} not found. Using glob format as fallback.`); |
||||||
|
formatItem = formatRegistry.get(FormatRegistryID.glob); |
||||||
|
} |
||||||
|
|
||||||
|
const formatVariable = getVariableWrapper(variable, value, text ?? value); |
||||||
|
return formatItem.formatter(value, args, formatVariable); |
||||||
|
} |
||||||
@ -0,0 +1,54 @@ |
|||||||
|
import { initTemplateSrv } from 'test/helpers/initTemplateSrv'; |
||||||
|
|
||||||
|
import { DataLinkBuiltInVars } from '@grafana/data'; |
||||||
|
import { getTemplateSrv, setTemplateSrv } from '@grafana/runtime'; |
||||||
|
|
||||||
|
import { setTimeSrv } from '../dashboard/services/TimeSrv'; |
||||||
|
import { variableAdapters } from '../variables/adapters'; |
||||||
|
import { createQueryVariableAdapter } from '../variables/query/adapter'; |
||||||
|
|
||||||
|
describe('__all_variables', () => { |
||||||
|
beforeAll(() => { |
||||||
|
variableAdapters.register(createQueryVariableAdapter()); |
||||||
|
|
||||||
|
setTemplateSrv( |
||||||
|
initTemplateSrv('hello', [ |
||||||
|
{ |
||||||
|
type: 'query', |
||||||
|
name: 'test', |
||||||
|
rootStateKey: 'hello', |
||||||
|
current: { value: ['val1', 'val2'] }, |
||||||
|
getValueForUrl: function () { |
||||||
|
return this.current.value; |
||||||
|
}, |
||||||
|
}, |
||||||
|
]) |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should interpolate correctly', () => { |
||||||
|
const out = getTemplateSrv().replace(`/d/1?$${DataLinkBuiltInVars.includeVars}`); |
||||||
|
expect(out).toBe('/d/1?var-test=val1&var-test=val2'); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should interpolate and take scopedVars into account', () => { |
||||||
|
const out = getTemplateSrv().replace(`/d/1?$${DataLinkBuiltInVars.includeVars}`, { test: { value: 'val3' } }); |
||||||
|
expect(out).toBe('/d/1?var-test=val3'); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
describe('__url_time_range', () => { |
||||||
|
beforeAll(() => { |
||||||
|
setTimeSrv({ |
||||||
|
timeRangeForUrl: () => ({ |
||||||
|
from: 1607687293000, |
||||||
|
to: 1607687293100, |
||||||
|
}), |
||||||
|
} as any); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should interpolate to url params', () => { |
||||||
|
const out = getTemplateSrv().replace(`/d/1?$${DataLinkBuiltInVars.keepTime}`); |
||||||
|
expect(out).toBe('/d/1?from=1607687293000&to=1607687293100'); |
||||||
|
}); |
||||||
|
}); |
||||||
@ -0,0 +1,22 @@ |
|||||||
|
import { DataLinkBuiltInVars, ScopedVars, urlUtil } from '@grafana/data'; |
||||||
|
|
||||||
|
import { getTimeSrv } from '../dashboard/services/TimeSrv'; |
||||||
|
import { getVariablesUrlParams } from '../variables/getAllVariableValuesForUrl'; |
||||||
|
|
||||||
|
import { valueMacro } from './dataMacros'; |
||||||
|
import { MacroHandler } from './types'; |
||||||
|
|
||||||
|
export const macroRegistry: Record<string, MacroHandler> = { |
||||||
|
['__value']: valueMacro, |
||||||
|
[DataLinkBuiltInVars.includeVars]: includeVarsMacro, |
||||||
|
[DataLinkBuiltInVars.keepTime]: urlTimeRangeMacro, |
||||||
|
}; |
||||||
|
|
||||||
|
function includeVarsMacro(match: string, fieldPath?: string, scopedVars?: ScopedVars) { |
||||||
|
const allVariablesParams = getVariablesUrlParams(scopedVars); |
||||||
|
return urlUtil.toUrlParams(allVariablesParams); |
||||||
|
} |
||||||
|
|
||||||
|
function urlTimeRangeMacro() { |
||||||
|
return urlUtil.toUrlParams(getTimeSrv().timeRangeForUrl()); |
||||||
|
} |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
import { ScopedVars } from '@grafana/data'; |
||||||
|
import { VariableCustomFormatterFn } from '@grafana/scenes'; |
||||||
|
|
||||||
|
export interface MacroHandler { |
||||||
|
( |
||||||
|
match: string, |
||||||
|
fieldPath: string | undefined, |
||||||
|
scopedVars: ScopedVars | undefined, |
||||||
|
format: string | VariableCustomFormatterFn | undefined |
||||||
|
): string; |
||||||
|
} |
||||||
Loading…
Reference in new issue