gapitio / gapit-htmlgraphics-panel

Grafana panel for displaying metric sensitive HTML or SVG graphics.
https://gapit-htmlgraphics-panel.gapit.io/
MIT License
64 stars 8 forks source link

How to change colors with SVG #168

Closed plomatheusnunes closed 7 months ago

plomatheusnunes commented 10 months ago

What happened: I'm trying to use a SVG image and change colors with "onRender" based on my values:

image

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"});
    }
}

Console Info: image

Example in SVG: image

How to reproduce it (as minimally and precisely as possible):

Anything else we need to know?:

Environment:

ZuperZee commented 10 months ago

https://grafana.com/grafana/plugins/marcuscalidus-svg-panel/ uses http://snapsvg.io/, which this plugin isn't. To change from Snap to "regular javascript": Change elt.select with elt.querySelector. Example: S.select("#my-id") -> htmlNode.querySelector("#my-id"). Change elt.attr to elt.setAttribute. Example: elt.attr({"opacity": 0}) -> elt.setAttribute("opacity", "0"). Change ctrl to data. There isn't a .stats field in series on the new data object. Here is a little information about the data object https://gapit-htmlgraphics-panel.gapit.io/docs/references/#data and a guide on how to get metrics with it https://gapit-htmlgraphics-panel.gapit.io/docs/guides/how-to-get-metrics/.

plomatheusnunes commented 10 months ago

Cool @ZuperZee !! Thanks for this!!

Now I'm trying to do like this:

const valueField = data.series[0].fields[1];
const length = valueField.values.length;
const value = valueField.values.get(length - 1);

// Select the path element
const pathElement = document.getElementById('linePath');

// Check if the value is equal to 1
if (value === 1) {
    // Change the color when the value is 1
    pathElement.setAttribute('fill', '#43ff64d9');
} else {
    // Reset the color to the default when the value is not 1
    pathElement.removeAttribute('fill');
}

console.log(value);

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>

But I get this error:

image

Like this works:

image

Console:

image

Could you help me?

ZuperZee commented 10 months ago

Change document.getElementById('linePath') to htmlNode.getElementById('linePath')

plomatheusnunes commented 10 months ago

Works!! Thanks @ZuperZee !! Now I'm going to update all my dashboards to HTML Graphics

I hope one day Grafana upgrade 'Canva' and works like this, but easier

ZuperZee commented 7 months ago

Closing as this has been open for a while. Create a new issue if this hasn't been resolved.