Grafana panel for displaying metric sensitive HTML and SVG graphics.
Full documentation for the plugin is available on the website.
This plugin is highly inspired by marcuscalidus-svg-panel, aidanmountford-html-panel, and aceiot-svg-panel.
Grafana panel for displaying metric sensitive HTML or SVG graphics.
Home Page: https://gapit-htmlgraphics-panel.gapit.io/
License: MIT License
Grafana panel for displaying metric sensitive HTML and SVG graphics.
Full documentation for the plugin is available on the website.
This plugin is highly inspired by marcuscalidus-svg-panel, aidanmountford-html-panel, and aceiot-svg-panel.
What would you like to be added:
The code editors in the panel options should be collapsible.
Why is this needed:
Using htmlgraphics panel, from grafana10.4 to 11 several js script, even loaded locally, are yes correctly loaded but then the object itself is not recognized. The problem is that this is happening with several script, pdf-lib.min.js just to name one.
You can reproduce it by loading this script https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js into the oninit section and check for the PDFLib object. It will be undefined
What happened: I'm using the HTML graphics plugin, at first the component enables the encoding option normally, after a few accesses the configuration screen is locked in "loading".
What you expected to happen: I expected the components to render correctly and the code option to be enabled.
How to reproduce it (as minimally and precisely as possible): When entering the panel and entering the HTML graphical plugin configuration screen, the code inputs are not rendered and are "loading" infinitely.
Anything else we need to know?: I already cleared the page cache and the problem persisted.
Environment:
Not wok so far.(both with grafana-cli and docker)
Originally posted by @n-arakawa in #50 (comment)
What happened:
Creating a setInterval in onRender and logging the value shows an updated value if the panel is refreshed with new data.
Image below shows logs from 3 refreshes.
But the 1. section has the data value as 52.55294827227271
What you expected to happen:
The data object shouldn't be dynamic in onRender.
How to reproduce it (as minimally and precisely as possible):
Panel options
{
"calcsMutation": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"first",
"firstNotNull",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"add100Percentage": true,
"centerAlignContent": true,
"overflow": "visible",
"SVGBaseFix": true,
"codeData": "{\n \"text\": \"Random text\"\n}",
"rootCSS": "",
"css": "",
"html": "",
"renderOnMount": true,
"onRender": "console.log(\"RELOAD\");\n\nconst calcs = data.series[0].fields[1].state.calcs\n\nconst interval = setInterval(() => {\n console.log(\"---\");\n console.log(\"Data value\", data.series[0].fields[1].state.calcs.last);\n console.log(\"Correct value\", calcs.last);\n}, 1000);\n\nhtmlNode.onpanelwillunmount = () => {\n clearInterval(interval);\n}\n",
"dynamicData": true,
"dynamicHtmlGraphics": false,
"dynamicFieldDisplayValues": false,
"dynamicProps": false,
"panelupdateOnMount": true,
"onInitOnResize": false,
"onInit": ""
}
Refresh a few times.
Open the console.
Anything else we need to know?:
Environment:
What happened:
The default onRender code causes error if it can't find the metric value
What you expected to happen:
The onRender code should check if the metric exists before retrieving the value.
How to reproduce it (as minimally and precisely as possible):
Make a panel
Remove the metric ("Remove query")
Anything else we need to know?:
Environment:
What happened:
Writing code in onRender or onInit makes variables show in the other as references.
The code crashes if they are used.
What you expected to happen:
The editors shouldn't reference each other.
How to reproduce it (as minimally and precisely as possible):
ctrl + space
(doesn't have to be the full variable name)Panel options
{
"onRender": "otherFile",
"onInit": "const otherFile = \"Hey\";"
}
Anything else we need to know?:
Environment:
Hi! I tried to add some code with sheetjs to my html-panel and found out that it doesn't allow to import dependencies in <script> tag.
I looked at other issues and understood that I need to use bundler to add dependencies. But when I look on the page of bundlers I see few bundlers for popular frameworks and libraries and nothing about how to create own.
Please, any instructions to how to add own dependencies to a panel. Thanks in advance!
What happened:
After installing the plugin and selecting the HTML graphics, an exception is thrown immediately:
An unexpected error happened
Detail:
Error: Illegal value for token color: #fff
at me (http://localhost:3000/public/build/react-monaco-editor.fb13e4673cc0c41043f4.js:1:15930)
at Ps (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:2162:3757)
at div
at Ls (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:2162:5745)
at WithTheme(undefined)
at div
at w (http://localhost:3000/public/plugins/gapit-htmlgraphics-panel/module.js:1:16459)
at _ (http://localhost:3000/public/plugins/gapit-htmlgraphics-panel/module.js:1:19510)
at div
at div
at p (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:422:27)
at div
at div
at http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:199:2304
at div
at div
at div
at t (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:775078)
at u (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:290:968)
at div
at div
at zn (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:275:590)
at div
at div
at tr (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:393:507)
at div
at t (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:426:3209)
at div
at t (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:426:5160)
at _r (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:426:10770)
at div
at div
at ia (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:486:6031)
at g (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1083974)
at div
at Mi (http://localhost:3000/public/build/DashboardPage.fb13e4673cc0c41043f4.js:574:3583)
at DashboardPage
at g (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1083974)
at n (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1053444)
at so (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:6608:181)
at t (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1101712)
at t (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1103733)
at main
at t (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1098330)
at div
at Qs (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:2171:1055)
at d (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:4495:26220)
at _l (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:2883:467)
at Nl (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:2883:1023)
at l (http://localhost:3000/public/build/2256.fb13e4673cc0c41043f4.js:2:1081540)
at Ho (http://localhost:3000/public/build/467.fb13e4673cc0c41043f4.js:6688:384)
What you expected to happen:
Show the panel edit page.
How to reproduce it (as minimally and precisely as possible):
grafana-cli --pluginsDir "/Users/lyh/dev/src/grafana/plugins" plugins install gapit-htmlgraphics-panel
Anything else we need to know?:
Environment:
What happened:
Installed the plugin via CLI. Went to add a new panel and selected the HTML panel. The error in the preview immediately shows: "Error loading: gapit-htmlgraphics-panel". The properties pane shows none of the expected settings either.
What you expected to happen:
Expected the panel to load with defaults.
How to reproduce it (as minimally and precisely as possible):
Install it via CLI on Grafana Enterprise v8.3.4
Create new dashboard
Add new panel
Select Html
Anything else we need to know?:
Using Grafana Enterprise is that maybe not supported?
Environment:
K8, Linux
What happened:
When changing the panel options in "Import/export" then saving (clicking outside or ctrl+s), the options doesn't update. This also happens when you import as a file.
Seems like the panel options values change, but not the options on the side.
What you expected to happen:
The options should update when panel options in "Import/export" has been changed.
How to reproduce it (as minimally and precisely as possible):
Anything else we need to know?:
Saving twice updates the options.
Environment:
What would you like to be added:
The interfaces in /src/components/CodeEditor/declarations are copied from the grafana library.
Why is this needed:
Is this possible in principle?
What happened:
I'm trying to use a SVG image and change colors with "onRender" based on my values:
SVG:
<svg xmlns="http://www.w3.org/2000/svg" id="Outline" viewBox="0 0 24 24" width="512" height="512">
<path id="linePath" d="M23.121,9.069,15.536,1.483a5.008,5.008,0,0,0-7.072,0L0.879,9.069A2.978,2.978,0,0,0,0,11.19v9.817a3,3,0,0,0,3,3H21a3,3,0,0,0,3-3V11.19A2.978,2.978,0,0,0,23.121,9.069ZM15,22.007H9V18.073a3,3,0,0,1,6,0Zm7-1a1,1,0,0,1-1,1H17V18.073a5,5,0,0,0-10,0v3.934H3a1,1,0,0,1-1-1V11.19a1.008,1.008,0,0,1,.293-.707L9.878,2.9a3.008,3.008,0,0,1,4.244,0l7.585,7.586A1.008,1.008,0,0,1,22,11.19Z"/>
</svg>
What you expected to happen:
I use this in SVG plugin and I'm trying to migrate to HTML Graphics
Javascript code that I use in SVG Plugin:
console.clear();
var S = Snap(svgnode);
serviceAlert();
function serviceAlert(){
var n;
var pn;
n=1;
pn=2;
console.log(ctrl)
for (var i=1;i<=ctrl.series.length;i++){
var dados;
server = ctrl.series[i-1].alias.replace(/:.*/,"").replaceAll(/[-\(\)']+/g, '').replaceAll(/ +/g, "-").replace(/[\u0300-\u036f]/g, '');
item = ctrl.series[i-1].alias.replace(/.*: /,"").replaceAll(/( %|[\(\),]|\/)+/g, '').replaceAll(/ +/g, "-").replace(/[\u0300-\u036f]/g, '');
alias = ctrl.series[i-1].alias.replace(/.*: /,"").replaceAll(/( %|[\(\)]|\/)+/g, '');
serviceName = '#trg_'+server+'_'+item.replaceAll("-in","");
tdataName = '#srv_'+server+'_'+item.replaceAll("-in","");
service = S.select(serviceName);
tdata = S.select(tdataName);
zbxItem = /^(Zabbix busy|Utilization)/.test(alias);
console.log(serviceName);
console.log(tdataName);
if (alias == "Replication Seconds Behind Master"){
dados = (ctrl.series[i-1].stats.current);
mysqlRep = S.select('#mysqlrep');
p_mysqlRep = S.select('#p_mysqlrep');
if (dados > 1800){
mysqlRep.attr({"stroke": "#E02F44"});
p_mysqlRep.attr({"stroke": "#E02F44"});
}else if(dados > 180){
mysqlRep.attr({"stroke": "#ED8128"});
p_mysqlRep.attr({"stroke": "#ED8128"});
}else if((dados >= 0) && (dados < 180) ){
mysqlRep.attr({"stroke": "#00e5b5"});
p_mysqlRep.attr({"stroke": "#00e5b5"});
}else{
mysqlRep.attr({"stroke": "#aca793"});
p_mysqlRep.attr({"stroke": "#aca793"});
}
} else if (alias == "Zabbix busy housekeeper processes, in"){
dados = (ctrl.series[i-1].stats.current);
if (dados == "100"){
value = 0;
}
dados = dados.toFixed(value);
dados=dados+'%';
tdata.attr({"#text": dados });
service.attr({"fill": "#299c46"});
else {
dados = (ctrl.series[i-1].stats.current);
if (dados === null){
dados = 9999999999;
}
dados = dados.toFixed(2);
threshold(dados,'menor',20,10);
dados=dados+'%';
tdata.attr({"#text": dados });
}
}
}
function threshold(data, criterio,warning, critical) {
if(criterio == "maior"){
if (data >= critical){
return service.attr({"fill": "#E02F44"});
}else if(data >= warning){
return service.attr({"fill": "#ED8128"});
}else if((data >= 0) && (data < warning) ){
return service.attr({"fill": "#299c46"});
}else{
return service.attr({"fill": "#aca793"});
}
}else if(criterio == "menor"){
if(data <= warning){
return service.attr({"fill": "#ED8128"});
}else if (data <= critical){
return service.attr({"fill": "#E02F44"});
}
else if(data > warning) {
return service.attr({"fill": "#299c46"});
}else{
return service.attr({"fill": "#aca793"});
}
}else{
return service.attr({"fill": "#aca793"});
}
}
How to reproduce it (as minimally and precisely as possible):
Anything else we need to know?:
Environment:
What would you like to be added:
A toggle to disable updating of fieldDisplayValues.
Why is this needed:
Performance.
If a lot of metrics are used fieldDisplayValues takes a while to update.
What would you like to be added:
locationService
should be added to the available Elements in the code blocks and getLocationSrv
should be removed
Why is this needed:
getLocationSrv
is deprecated.
What would you like to be added:
Execute script tags in the html
Why is this needed:
Makes it easier to add external dependencies and below code would work
<script>
function test() {
// Something
}
</script>
<button onclick="test">Click me</button>
I use "setInterval" in "OnInit".
Hope to have a chance to "clearInterval" just befor the panel will be destroyed.
On the same time, I want to know how to share timerid between "OnInit" and other code.
please help me to use HTML Graphic in Graphana version 6.2
Originally posted by tillsteinbach February 23, 2022
I can throw new Error()
but it will display something like "error in onRender". Would be great if there is a real interface to show errors to the user.
What would you like to be added:
I would like the ability to load a SVG from a file or url.
The ability to load different svg files based on a user variable. (This could be a follow on.) Would like a single file first.
Why is this needed:
I've been creating some very large svg files and it would be helpful to load from a file instead of cut and paste.
Also sharing dashboards could be made easier.
Dynamic dashboards which could pull up different svg based on a user variable.
This plugin has been a great help for what I've been doing. Thanks.
What happened:
htmlGraphics.fieldDisplayValues
returns undefined
What you expected to happen:
htmlGraphics.fieldDisplayValues
should retrieve the values.
How to reproduce it (as minimally and precisely as possible):
Set Dynamic htmlGraphics
to true.
Add the following onInit
code
console.log(htmlGraphics.fieldDisplayValues)
Reload the page.
Anything else we need to know?:
Environment:
What happened:
When Grafana is served from sub path the font files are not served from the sub path.
What you expected to happen:
The fonts should be served from the sub path.
How to reproduce it (as minimally and precisely as possible):
Dockerfile
version: '2'
services:
grafana:
image: grafana/grafana:8.0.3
container_name: grafana
restart: always
networks:
- grafana
ports:
- 3000:3000
environment:
- GF_INSTALL_PLUGINS=gapit-htmlgraphics-panel
- GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s:%(http_port)s/grafana/
- GF_SERVER_SERVE_FROM_SUB_PATH=true
networks:
grafana:
external:
name: grafana
Anything else we need to know?:
Environment:
Hope to have a way to access props to get attributes such as :
What happened:
We have an HTML Graphics panel used as the main header for all of our dashboards. It just displays a banner, but under the covers runs some complex queries that are beyond what is supported through the Query variable definition interfaces and stores the values into Constant variables that are then available to other panels (essentially externally loaded Query variables).
The banner displays the currently selected time range, retrieving it from the Grafana global variables, formatting it and updating the HTML. The JavaScript for this is contained in the onRender section, which, as we understand it, should execute whenever new data is available, such as a change in the time range selection. However, the panel does NOT refresh the majority of the time when the time range changes (meaning the variables are not being updated to reflect the range change). I even added a panelupdate event listener in the JS to try to force it, but it is still not executing.
What you expected to happen:
When the time range is changes, the panel should execute the JS in the onRender, which would refresh the variables and the displayed time.
How to reproduce it (as minimally and precisely as possible):
I have attached an importable dashboard with a stripped-down version of the panel which still includes the time refresh code (but without the queries or variable updates).
Header Not Refreshing Issue-1713546520774.json
Anything else we need to know?:
Nothing I can think of pending any questions.
Environment:
What happened:
Using v8.4.0 makes the "cutstom" code editor suggestions not show
What you expected to happen:
Suggestions to work like in v8.3.6 and below
How to reproduce it (as minimally and precisely as possible):
Type html in the onRender or onInit code editor
Anything else we need to know?:
This was working in v8.3.6, most likely a change from Grafana.
Environment:
What would you like to be added:
Don't save importedPanelOptions
. Just use the options already in use.
Why is this needed:
This halves the size of the settings stored. Making the payload smaller for the users.
What would you like to be added:
Only load declarations when they are needed.
Why is this needed:
Currently the declarations are bundled into the module.js file which causes the file size to be ~3 times larger.
With declarations: ~73 KB
Without declarations: ~27 KB
What would you like to be added:
Call initialize(or onInit) after resizing the panel.
Why is this needed:
I change HTML according to the aspect of the panel.
For example
vertical slider for portrait,
horizontal one for landscape view.
However I need to save and reload the dashboard to take effect after resizing the panel.
On the same time. I hope to have the recent version of this plugin in the official panel repository!
When change value of variable via LocationSrv, PanelUpdate event is invoked.
However, when modifying variable via GUI(top most part of the dashboard) ,
PanelUpdate event is not invoked.
What would you like to be added:
Props should be dynamic like data (in onInit).
Why is this needed:
props like width and height doesn't update when the panel is resized.
What happened:
Pressing download as json file doesn't work after v2.0.0 update.
What you expected to happen:
The json file should download
How to reproduce it (as minimally and precisely as possible):
Click "Download as JSON file" in the Panel options Import/export section.
Anything else we need to know?:
Environment:
What would you like to be added:
Add CSS that will be loaded outside the shadowroot to be able to use @import
and @font-face
Why is this needed:
@import
and @font-face
will be able to be loaded and custom fonts and icons can be used.
Hi i have a neo4j graph using neovis.js library in an html file. And i was looking to visualize this graph in grafana. Is possible to do this with html graphics plugin?
I have an SVG (made in draw.io) that contains custom font "Roboto":
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
width="65px" height="32px" viewBox="-0.5 -0.5 65 32" style="background-color: rgb(24, 27, 31);">
<defs>
<style type="text/css">@import
url(https://fonts.googleapis.com/css2?family=Roboto:wght@400;500);
</style>
</defs>
<g>
<g id="cell-1xWRqdkjeC1Q69flhg9z-545"
content="<object label="-%" name="one_a_src_fill_text"/>"
data-label="-%" data-name="one_a_src_fill_text">
<rect x="0" y="-0.38" width="64.84" height="31.21" fill="none" stroke="none"
pointer-events="all" />
<g transform="translate(-0.5 -0.5)">
<switch>
<foreignObject pointer-events="none" width="100%" height="100%"
requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"
style="overflow: visible; text-align: left;">
<div xmlns="http://www.w3.org/1999/xhtml"
style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 63px; height: 1px; padding-top: 15px; margin-left: 1px;">
<div data-drawio-colors="color: #FBFBFA; "
style="box-sizing: border-box; font-size: 0px; text-align: center;">
<div
style="display: inline-block; font-size: 22px; font-family: Roboto; color: rgb(251, 251, 250); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
-%</div>
</div>
</div>
</foreignObject>
<text x="32" y="22" fill="#FBFBFA" font-family="Roboto" font-size="22px"
text-anchor="middle">-%</text>
</switch>
</g>
</g>
</g>
<switch>
<g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" />
<a transform="translate(0,-5)"
xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank">
<text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot
display</text>
</a>
</switch>
</svg>
When rendering with the htmlgraphics visual, it falls back to another default font.
Am I doing something wrong, is this a bug, or is this simply not supported yet?
Thanks for the help!
Best,
Sander
A button to export all javascript and html/svg data. Can be downloaded as several files into a local computer.
This is needed to speed up moving data from one instance to another. F.ex if testing and development is done on a local computer but the finished version should be transferred to a server
tried running the example
https://gapit-htmlgraphics-panel.gapit.io/docs/examples/communicate-between-panels/
but not working
What would you like to be added: Support for handbar js to display data
Why is this needed: helps interpolate html with dynamic display part similar to https://grafana.com/grafana/plugins/marcusolsson-dynamictext-panel/
Can we include external js or /and css ?
If we want to create a interactive form using this panel , it will be of immense help to include external css and js files
What happened:
When first creating a HTMLGraphics panel the default calcs is wrong. It says standard, but last is the only one added.
What you expected to happen:
All the standard calcs should be added.
How to reproduce it (as minimally and precisely as possible):
Create a HTMLGraphics panel.
log htmlGraphics.fieldDisplayValues
onRender
console.log(htmlGraphics.fieldDisplayValues);
Anything else we need to know?:
Environment:
What happened:
Going in and out of edit mode doesn't trigger the non edit panel's onpanelunmount event.
What you expected to happen:
The edit and the non edit panel should trigger the onpanelunmount event.
How to reproduce it (as minimally and precisely as possible):
Create a new panel will below panel options
{
"calcsMutation": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"first",
"firstNotNull",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"add100Percentage": true,
"centerAlignContent": true,
"overflow": "visible",
"SVGBaseFix": true,
"codeData": "{\n \"text\": \"Random text\"\n}",
"rootCSS": "",
"css": "* {\n font-family: Open Sans;\n}\n",
"html": "<button>Dispatch event</button>\n",
"renderOnMount": true,
"onRender": "",
"dynamicData": false,
"dynamicHtmlGraphics": false,
"dynamicFieldDisplayValues": false,
"dynamicProps": false,
"panelupdateOnMount": true,
"onInit": "const buttonElt = htmlNode.querySelector('button');\n\nbuttonElt.onclick = () => document.dispatchEvent(htmlGraphicsEvent);\n\nconst doSomething = () => {\n console.log(\"Event dispatched\");\n}\n\nhtmlGraphicsEvent = new CustomEvent('htmlgraphics');\ndocument.addEventListener('htmlgraphics', doSomething);\n\nhtmlNode.onpanelwillunmount = () => {\n document.removeEventListener('htmlgraphics', doSomething);\n}\n"
}
Press e on the panel a few times and check the console.
It should only log "Event dispatched" once
Anything else we need to know?:
Edit panel is the panel where you can see the options.
The non edit panel is the one without the options on the side.
Environment:
What happened:
An error in the code didn't get logged in the console.
What you expected to happen:
The error should be logged in the console.
How to reproduce it (as minimally and precisely as possible):
Create an error in onRender or onInit.
onRender:
a
Anything else we need to know?:
Environment:
I've made some changes to your html example but for SVG, I don't know if it would be helpful for anyone - am happy for it to be added to the website if you think it would be useful
HTML/SVG document:
<button id="testButton" style="background:green;color:white;"></button>
<svg width="100" height="100">
<circle id = "testSVG" cx="50" cy="50" r="40" stroke="green" stroke-width="4" style="fill:red;" />
</svg>
onInit
// For Grafana v8.3.0+ the variable needs to be wrapped in ${}
const { testVariable } = customProperties;
const testVariableName = testVariable.replace(/[${}]/g, "");
const buttonElt = htmlNode.querySelector('button');
const buttonID = htmlNode.querySelector('#testButton');
const svgID = htmlNode.querySelector('#testSVG');
/*
Update a grafana variable
More information in the grafana docs
https://grafana.com/docs/grafana/v9.1/developers/plugins/add-support-for-variables/
*/
function updateGrafanaVariable(variableName, value) {
getLocationSrv().update({
query: {
[`var-${variableName}`]: value,
},
partial: true, // partial: true makes the update only affect the query parameters listed in query, and leaves the other query parameters unchanged.
replace: true, // replace: true tells Grafana to update the current URL state, rather than creating a new history entry.
});
}
function getGrafanaVariableValue(variable) {
return getTemplateSrv().replace(variable);
}
function updateButtonText() {
buttonElt.textContent = `${testVariableName}'s current value is: ${getGrafanaVariableValue(testVariable)}`;
}
buttonElt.onclick = function () {
updateGrafanaVariable(testVariableName, getGrafanaVariableValue(testVariable) == 'b' ? 'a' : 'b');
};
/*
When the variable changes panelupdate will trigger.
The panelupdate is used to update the button text so the text is the same as the variable.
Call updateButtonText() when the variable changes
*/
htmlNode.addEventListener('panelupdate', () => {
updateButtonText();
if (getGrafanaVariableValue(testVariable) == 'a'){
svgID.style.fill = 'Blue';
} else {
svgID.style.fill = 'Green';
}
if (getGrafanaVariableValue(testVariable) == 'a'){
buttonID.style.background = 'Blue';
} else {
buttonID.style.background = 'Red';
}
});
testVariable
${testVariable}
Panel Options
{
"calcsMutation": "standard",
"reduceOptions": {
"calcs": [
"lastNotNull",
"last",
"first",
"firstNotNull",
"min",
"max",
"mean",
"sum",
"count",
"range",
"delta",
"step",
"diff",
"logmin",
"allIsZero",
"allIsNull",
"diffperc"
]
},
"add100Percentage": true,
"centerAlignContent": true,
"overflow": "visible",
"useGrafanaScrollbar": true,
"SVGBaseFix": true,
"codeData": "{\n \"testVariable\": \"${testVariable}\"\n}",
"rootCSS": "",
"css": "",
"html": "<button id=\"testButton\" style=\"background:green;color:white;\"></button>\n\n<svg width=\"100\" height=\"100\">\n <circle id = \"testSVG\" cx=\"50\" cy=\"50\" r=\"40\" stroke=\"green\" stroke-width=\"4\" style=\"fill:red;\" />\n</svg>\n",
"renderOnMount": true,
"onRender": "",
"panelupdateOnMount": true,
"dynamicHtmlGraphics": false,
"dynamicData": false,
"dynamicFieldDisplayValues": false,
"dynamicProps": false,
"onInitOnResize": false,
"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');\nconst buttonID = htmlNode.querySelector('#testButton');\nconst svgID = htmlNode.querySelector('#testSVG');\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 Call updateButtonText() when the variable changes\n*/\nhtmlNode.addEventListener('panelupdate', () => {\n updateButtonText();\n if (getGrafanaVariableValue(testVariable) == 'a'){\n svgID.style.fill = 'Blue';\n } else {\n svgID.style.fill = 'Green';\n }\n if (getGrafanaVariableValue(testVariable) == 'a'){\n buttonID.style.background = 'Blue';\n } else {\n buttonID.style.background = 'Red';\n }\n});\n"
}
What would you like to be added:
Why is this needed:
What would you like to be added:Import external js resources
Why is this needed:When using grafana, I need to insert live video surveillance, the native tag <video> does not support this
E.g:<script src=“http: //vjs.zencdn.net/5.8.8/video.js”></script>
var json = JSON.parse(xhr.responseText);
var selected_eport = htmlNode.getElementById("select_report");
selected_eport.innerHTML = "";
var option = htmlNode.createElement("option");
option.text = "== SELECT REPORT ==";
selected_eport.add(option);
for (var i = 0; i < json.length; i++) {
var option = htmlNode.createElement("option");
option.text = json[i].REPORT_NAME;
option.value = json[i].REPORT_ID;
selected_eport.add(option);
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.