-
Notifications
You must be signed in to change notification settings - Fork 8
-
"Hi, I'm attempting to create my own work shift selector using this plugin, and I'm wondering if there's any way to modify the dashboard variables 'timeFrom' and 'timeTo'? <a href="https://localhost:3000/d/uid/dashboard?from=1696075200000&to=1696104000000">
<button id="btn"> change interval </button>
</a> |
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment · 7 replies
-
You can use htmlGraphics.locationService.push which is a wrapper around history.pushState. htmlGraphics.locationService.push("https://localhost:3000/d/uid/dashboard?from=1696075200000&to=1696104000000") Example with a button element const btn = htmlNode.querySelector("button");
btn.addEventListener("click", () => {
htmlGraphics.locationService.push("https://localhost:3000/d/uid/dashboard?from=1696075200000&to=1696104000000")
}); |
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
This solution worked, however instead of providing the entire URL as an argument, only the endpoint needs to be specified in the following manner: htmlGraphics.locationService.push("dashboard?from=1696075200000&to=1696104000000") Thank you for the quick response. |
Beta Was this translation helpful? Give feedback.
All reactions
-
I have one more question: Can I somehow trigger the 'Run query' or 'Refresh dashboard' action, or force the panel to retrieve data from the MS SQL database on button click? |
Beta Was this translation helpful? Give feedback.
All reactions
-
You can reload the dashboard with To update a single panel (or the ones with the specified grafana variable), you can use this example: https://gapit-htmlgraphics-panel.gapit.io/docs/examples/update-grafana-variable-example/. Another approach is to retrieve the data manually with fetch commands, but it's a bit complicated. This example shows you how to retrieve data manually: https://gapit-htmlgraphics-panel.gapit.io/docs/examples/export-to-csv/export-to-csv-influx2/.
JSON Model
{
"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": 2,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "grafana",
"uid": "grafana"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 3,
"options": {
"SVGBaseFix": true,
"add100Percentage": true,
"calcsMutation": "standard",
"centerAlignContent": true,
"codeData": "{\n \"testVariable\": \"${testVariable}\"\n}",
"css": "",
"dynamicData": false,
"dynamicFieldDisplayValues": false,
"dynamicHtmlGraphics": false,
"dynamicProps": false,
"html": "<button></button>\n",
"onInit": "// For Grafana v8.3.0+ the variable needs to be wrapped in ${}\nconst { testVariable } = customProperties;\nconst testVariableName = testVariable.replace(/[${}]/g, \"\");\nconst buttonElt = htmlNode.querySelector('button');\n\n/*\n Update a grafana variable\n\n More information in the grafana docs\n https://grafana.com/docs/grafana/v9.1/developers/plugins/add-support-for-variables/\n*/\nfunction updateGrafanaVariable(variableName, value) {\n getLocationSrv().update({\n query: {\n [`var-${variableName}`]: value,\n },\n partial: true, // partial: true makes the update only affect the query parameters listed in query, and leaves the other query parameters unchanged.\n replace: true, // replace: true tells Grafana to update the current URL state, rather than creating a new history entry.\n });\n}\n\nfunction getGrafanaVariableValue(variable) {\n return getTemplateSrv().replace(variable);\n}\n\nfunction updateButtonText() {\n buttonElt.textContent = `${testVariableName}'s current value is: ${getGrafanaVariableValue(testVariable)}`;\n}\n\nbuttonElt.onclick = function () {\n updateGrafanaVariable(testVariableName, getGrafanaVariableValue(testVariable) == 'b' ? 'a' : 'b');\n};\n\n/*\n When the variable changes panelupdate will trigger.\n The panelupdate is used to update the button text so the text is the same as the variable.\n*/\nhtmlNode.addEventListener('panelupdate', () => {\n updateButtonText();\n});\n",
"onInitOnResize": false,
"onRender": "console.log(data.series[0].fields[0].values)",
"overflow": "visible",
"panelupdateOnMount": true,
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"first",
"firstNotNull",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"renderOnMount": true,
"rootCSS": "",
"useGrafanaScrollbar": true
},
"targets": [
{
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"queryType": "randomWalk",
"refId": "A"
}
],
"title": "Panel Title",
"type": "gapit-htmlgraphics-panel"
},
{
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 4,
"options": {
"SVGBaseFix": true,
"add100Percentage": true,
"calcsMutation": "standard",
"centerAlignContent": true,
"codeData": "{\n \"text\": \"Random text\"\n}",
"css": "* {\n font-family: Open Sans;\n}\n\n.box {\n border: solid #555 2px;\n border-radius: 10px;\n padding: 10px 20px;\n}\n",
"dynamicData": false,
"dynamicFieldDisplayValues": false,
"dynamicHtmlGraphics": false,
"dynamicProps": false,
"html": "<div style=\"text-align: center;\">\n <div class=\"box\" id=\"htmlgraphics-text\"></div>\n <br />\n <div class=\"box\" id=\"htmlgraphics-value\"></div>\n</div>\n",
"onInit": "// Sets the text from customProperties\nconst htmlgraphicsText = htmlNode.getElementById('htmlgraphics-text');\n\nif (htmlgraphicsText) {\n htmlgraphicsText.textContent = customProperties.text;\n\n // Change the text color based on the theme\n if (theme.isDark) {\n htmlgraphicsText.style.color = 'green';\n } else {\n htmlgraphicsText.style.color = 'red';\n }\n}\n",
"onInitOnResize": false,
"onRender": "// Sets the value from the first series on every refresh\nconst htmlgraphicsValue = htmlNode.getElementById('htmlgraphics-value');\n\nif (htmlgraphicsValue) {\n const valueField = data.series[0]?.fields[1];\n if (valueField) {\n const length = valueField.values.length;\n htmlgraphicsValue.textContent = valueField.values.get(length - 1);\n } else {\n htmlgraphicsValue.textContent = \"No data\"\n }\n}\n",
"overflow": "visible",
"panelupdateOnMount": true,
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"firstNotNull",
"first",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"renderOnMount": true,
"rootCSS": "",
"useGrafanaScrollbar": true
},
"title": "Contains the test variable: ${testVariable}",
"type": "gapit-htmlgraphics-panel"
},
{
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 8
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"title": "Panel Title",
"type": "timeseries"
},
{
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "d0deb289-5da5-48eb-bce0-00e5decab902"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unitScale": true
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"id": 1,
"options": {
"SVGBaseFix": true,
"add100Percentage": true,
"calcsMutation": "standard",
"centerAlignContent": true,
"codeData": "{\n \"text\": \"Random text\"\n}",
"css": "* {\n font-family: Open Sans;\n}\n\n.box {\n border: solid #555 2px;\n border-radius: 10px;\n padding: 10px 20px;\n}\n",
"dynamicData": false,
"dynamicFieldDisplayValues": false,
"dynamicHtmlGraphics": false,
"dynamicProps": false,
"html": "<div style=\"text-align: center;\">\n <button>Refresh</button>\n <div class=\"box\" id=\"htmlgraphics-text\"></div>\n <br />\n <div class=\"box\" id=\"htmlgraphics-value\"></div>\n</div>\n",
"onInit": "// Sets the text from customProperties\nconst htmlgraphicsText = htmlNode.getElementById('htmlgraphics-text');\n\nif (htmlgraphicsText) {\n htmlgraphicsText.textContent = customProperties.text;\n\n // Change the text color based on the theme\n if (theme.isDark) {\n htmlgraphicsText.style.color = 'green';\n } else {\n htmlgraphicsText.style.color = 'red';\n }\n}\n\nconst btn = htmlNode.querySelector(\"button\");\n\nbtn.addEventListener(\"click\", () => {\n htmlGraphics.locationService.reload();\n});",
"onInitOnResize": false,
"onRender": "// Sets the value from the first series on every refresh\nconst htmlgraphicsValue = htmlNode.getElementById('htmlgraphics-value');\n\nif (htmlgraphicsValue) {\n const valueField = data.series[0]?.fields[1];\n if (valueField) {\n const length = valueField.values.length;\n htmlgraphicsValue.textContent = valueField.values.get(length - 1);\n } else {\n htmlgraphicsValue.textContent = \"No data\"\n }\n}\n",
"overflow": "visible",
"panelupdateOnMount": true,
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"firstNotNull",
"first",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"renderOnMount": true,
"rootCSS": "",
"useGrafanaScrollbar": true
},
"title": "Panel Title",
"type": "gapit-htmlgraphics-panel"
}
],
"refresh": "",
"schemaVersion": 39,
"tags": [],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "b",
"value": "b"
},
"hide": 0,
"includeAll": false,
"multi": false,
"name": "testVariable",
"options": [
{
"selected": false,
"text": "a",
"value": "a"
},
{
"selected": true,
"text": "b",
"value": "b"
}
],
"query": "a,b",
"skipUrlSync": false,
"type": "custom"
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Refresh panel",
"uid": "e3189e12-f321-4cfe-a291-0ffd2e959e4e",
"version": 12,
"weekStart": ""
} |
Beta Was this translation helpful? Give feedback.
All reactions
-
I am trying to fetch data from a Microsoft SQL Server database. The query is correct as I have tested it, but in Grafana, the POST request returns an empty JSON object with status: 200 so there is db connection. I am not sure what I am doing wrong. Could you advise me on this? function main() {
const query = `SELECT * FROM test;`
const refId = "A";
const datasource = {
"type": "mssql",
"uid": "a5daead1-928d-4e7f-9d82-b97174160e56"
};
const { from, to } = data.timeRange;
const body = {
queries: [
{
datasource,
query,
refId,
intervalMs: 0,
maxDataPoints: 1e9, // 1E9 = 1_000_000_000 (Max allowed 1E20)
},
],
from: String(from.valueOf()),
to: String(to.valueOf()),
};
fetch("/api/ds/query", {
headers: {
"cache-control": "no-cache",
"content-type": "application/json",
},
body: JSON.stringify(body),
method: "POST",
})
.then((res) => console.log(res))
.catch(console.error);
} This is my dashboard: {
"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,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "mssql",
"uid": "a5daead1-928d-4e7f-9d82-b97174160e56"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 1,
"links": [],
"options": {
"SVGBaseFix": true,
"add100Percentage": true,
"calcsMutation": "standard",
"centerAlignContent": true,
"codeData": "{\n \"text\": \"Random text\"\n}",
"css": "",
"dynamicData": false,
"dynamicFieldDisplayValues": false,
"dynamicHtmlGraphics": false,
"dynamicProps": false,
"html": "\n\n<div style=\"text-align: center;\">\n <button id=\"btn2\"> button </button>\n</div>\n\n",
"onInit": "\nfunction main() {\n const query = `SELECT * FROM test;`\n const refId = \"A\";\n const datasource = {\n \"type\": \"mssql\",\n \"uid\": \"a5daead1-928d-4e7f-9d82-b97174160e56\"\n };\n const { from, to } = data.timeRange;\n\n const body = {\n queries: [\n {\n datasource,\n query,\n refId,\n intervalMs: 0,\n maxDataPoints: 1e9, // 1E9 = 1_000_000_000 (Max allowed 1E20)\n },\n ],\n from: String(from.valueOf()),\n to: String(to.valueOf()),\n };\n\n fetch(\"/api/ds/query\", {\n headers: {\n \"cache-control\": \"no-cache\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(body),\n method: \"POST\",\n })\n .then((res) => console.log(res))\n .catch(console.error);\n}\n\nvar btn2 = htmlNode.getElementById(\"btn2\")\nbtn2.addEventListener(\"click\", () => {\n main();\n});\n",
"onInitOnResize": false,
"onRender": "",
"overflow": "visible",
"panelupdateOnMount": true,
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"firstNotNull",
"first",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"renderOnMount": true,
"rootCSS": "",
"useGrafanaScrollbar": true
},
"targets": [
{
"dataset": "SQLFromPLC",
"datasource": {
"type": "mssql",
"uid": "a5daead1-928d-4e7f-9d82-b97174160e56"
},
"editorMode": "code",
"format": "table",
"rawQuery": true,
"rawSql": "SELECT * FROM SQLFromPLC.dbo.test ",
"refId": "A",
"sql": {
"columns": [
{
"parameters": [
{
"name": "*",
"type": "functionParameter"
}
],
"type": "function"
},
{
"parameters": [],
"type": "function"
}
],
"groupBy": [
{
"property": {
"type": "string"
},
"type": "groupBy"
}
],
"limit": 50
},
"table": "dbo.test"
}
],
"type": "gapit-htmlgraphics-panel"
}
],
"refresh": "",
"schemaVersion": 38,
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "New dashboard",
"version": 0,
"weekStart": ""
} |
Beta Was this translation helpful? Give feedback.
All reactions
-
Depending on the data source, the query and how the fetch command is made differs.
Take special note of how the URL and body are configured. |
Beta Was this translation helpful? Give feedback.
This solution worked, however instead of providing the entire URL as an argument, only the endpoint needs to be specified in the following manner:
Thank you for the quick response.