marcuscalidus-svg-panel
marcuscalidus-svg-panel copied to clipboard
Custom CSS
Could you add an editor to add static CSS to the panel ? Also, it could be nice to load js files from url (aka CDN, jquery-ui, bootstrap, or other things) Thanks for your good work
that's an interesting idea. I'll give thought to that. Thank you.
You can load any js library you like via following script during onInit()
like so:
//this example loads the moment.js library and prints the current timestamp into the browser's console
function injectScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.async = true;
script.src = src;
script.addEventListener('load', resolve);
script.addEventListener('error', () => reject('Error loading script.'));
script.addEventListener('abort', () => reject('Script loading aborted.'));
document.head.appendChild(script);
});
}
injectScript('https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js')
.then(() => {
console.log('Script loaded!');
console.log(moment().format());
}).catch(error => {
console.log(error);
});
to inject custom css you can do the following inside onInit()
function addCss(rule) {
let css = document.createElement('style');
css.type = 'text/css';
if (css.styleSheet) css.styleSheet.cssText = rule; // Support for IE
else css.appendChild(document.createTextNode(rule)); // Support for the rest
document.getElementsByTagName("head")[0].appendChild(css);
}
// CSS rules
let rule = '.red {background-color: red}';
rule += '.blue {background-color: blue}';
addCss(rule);
be aware though, that the above script will add the css node multiple times. One time for every created control. You could tweak the routine to detect if the given node was already added by maybe setting a global variable in window or similar hack.
Thanks for your response. I currently use the init function to put all shared generic code between panels, that way I can copy-paste it. Ex : open modals, tooltips, etc. I use the same trick as you to add custom CSS.
(function() {
"use strict";
// generic code (lib)
// All temporary data should be stored in the controller to be able to display multiple panel.
// Moreover, the front is an SPA, we don't want to share data between pages
let lib = {};
ctrl.companyscope = { lib: lib };
lib.isLightColor = function(color) {
let ctx = document.createElement("canvas").getContext("2d");
ctx.fillStyle = color;
let hexColor = ctx.fillStyle.replace("#", "");
let r = parseInt(hexColor.substr(0,2),16);
let g = parseInt(hexColor.substr(2,2),16);
let b = parseInt(hexColor.substr(4,2),16);
let yiq = ((r*299)+(g*587)+(b*114))/1000;
return (yiq >= 128);
};
lib.showModal = function(title, description) {
// Grafana uses SystemJs to share it's typescript SDK : https://grafana.com/docs/plugins/developing/development/#buildscript
// We use appEvents pour display a modal : https://github.com/grafana/grafana/blob/e9d5e037e817b57303c4497b42b28ee9403dd65f/public/app/features/alerting/alert_list_ctrl.ts#L64
System.import('app/core/core').then(function(core) {
// https://github.com/grafana/grafana/blob/master/public/app/features/alerting/partials/alert_howto.html
const modalHtml = `
<div class="modal-body">
<div class="modal-header">
<h2 class="modal-header-title">
<i class="fa fa-info-circle"></i>
<span class="p-l-1">${title}</span>
</h2>
<a class="modal-header-close" ng-click="dismiss();">
<i class="fa fa-remove"></i>
</a>
</div>
<div class="modal-content">
<p class="p-a-2 text-center offset-lg-1 col-lg-10">
${description}
</p>
</div>
</div>
`;
core.appEvents.emit('show-modal', {
modalClass: 'modal--narrow',
templateHtml: modalHtml,
model: {}
});
});
};
lib.zabbixSeverityToColor = function(severity) {
if (severity === 'Not classified') {
return 'YellowGreen';
}
if (severity === 'Information') {
return 'MediumTurquoise';
}
else if (severity === 'Warning') {
return 'orange';
}
else if (severity === 'Average') {
return 'gold';
}
else if (severity === 'High' || severity == 'Disaster') {
return 'red';
}
else {
return 'green';
}
};
lib.$tooltip = $('<div class="graph-tooltip">');
lib.bindTooltipOnSvgHover = function(svgnode, genTooltipHTMLCallback) {
svgnode.hover(function(e) {
let html = genTooltipHTMLCallback(e);
if (html !== null && html !== '') {
lib.$tooltip
.html(html)
.place_tt(e.clientX + 20, e.clientY);
}
}, function(e) {
lib.$tooltip.detach();
});
};
lib.makeTooltipsFollowMouse = function() {
svgnode.onmousemove = function(e) {
if (document.contains(lib.$tooltip[0])) {
lib.$tooltip.place_tt(e.clientX + 20, e.clientY);
}
};
};
})();
I see... so you still think it is necessary to add CSS and 3rdParty Library support inputs?
I think it would be great addition. With 3rd party JS support, I could host a lib somewhere and when I update it every panel would be updated as well. CSS panel/file is just to separate contents, though for big stylesheets it would improve readability.
acknowledged ... I'll see what I can do.