diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42a380b..b560f81 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@ Fixes x-scaling ratio when the SVG x-dimension is smaller than the available
window. Now it scales with the window whereas before it scaled at twice the rate
resulting in it being much smaller than necessary.
+Adds the ability to drive the SVG background. New panelConfig terms:
+- background.darkThemeColor
+- background.lightThemeColor
+Can be used with the normal color-names, rbg, hex values. When the relevant term is
+undefined the background color is not driven.
+
## 1.5.0
Fixes the grafana variable threshold matching to break out on first rule
match for a given variable/cell tuple. Before it was continuing through
diff --git a/provisioning/dashboardData/backgroundColor.svg b/provisioning/dashboardData/backgroundColor.svg
new file mode 100644
index 0000000..a88a39b
--- /dev/null
+++ b/provisioning/dashboardData/backgroundColor.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/provisioning/dashboards/backgroundColor.json b/provisioning/dashboards/backgroundColor.json
new file mode 100644
index 0000000..842ce3e
--- /dev/null
+++ b/provisioning/dashboards/backgroundColor.json
@@ -0,0 +1,182 @@
+{
+ "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": 6,
+ "links": [],
+ "liveNow": false,
+ "panels": [
+ {
+ "datasource": {
+ "type": "datasource",
+ "uid": "grafana"
+ },
+ "gridPos": {
+ "h": 4,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 4,
+ "options": {
+ "code": {
+ "language": "plaintext",
+ "showLineNumbers": false,
+ "showMiniMap": false
+ },
+ "content": "# Background\n\nBackground is normally left untouched but the panel yaml can define a darkTheme and a lightTheme color.\nIf the yaml field is present the background color is driven. Go to user -> profile to change the theme from dark to light.",
+ "mode": "markdown"
+ },
+ "pluginVersion": "10.0.0",
+ "title": "Panel Title",
+ "type": "text"
+ },
+ {
+ "datasource": {
+ "type": "datasource",
+ "uid": "grafana"
+ },
+ "gridPos": {
+ "h": 9,
+ "w": 12,
+ "x": 0,
+ "y": 4
+ },
+ "id": 5,
+ "options": {
+ "debuggingCtr": {
+ "colorsCtr": 0,
+ "dataCtr": 0,
+ "displaySvgCtr": 0,
+ "mappingsCtr": 0,
+ "timingsCtr": 0
+ },
+ "siteConfig": "",
+ "svg": "\n\n\n",
+ "testDataEnabled": true,
+ "timeSliderEnabled": true
+ },
+ "title": "Background Not driven",
+ "type": "andrewbmchugh-flow-panel"
+ },
+ {
+ "datasource": {
+ "type": "datasource",
+ "uid": "grafana"
+ },
+ "gridPos": {
+ "h": 9,
+ "w": 12,
+ "x": 12,
+ "y": 4
+ },
+ "id": 2,
+ "options": {
+ "debuggingCtr": {
+ "colorsCtr": 0,
+ "dataCtr": 0,
+ "displaySvgCtr": 0,
+ "mappingsCtr": 0,
+ "timingsCtr": 0
+ },
+ "panelConfig": "---\n\nbackground:\n darkThemeColor: \"yellow\"\n lightThemeColor: \"green\"",
+ "siteConfig": "",
+ "svg": "\n\n\n",
+ "testDataEnabled": true,
+ "timeSliderEnabled": true
+ },
+ "title": "Background - darkTheme=yellow, lightTheme=green",
+ "type": "andrewbmchugh-flow-panel"
+ },
+ {
+ "datasource": {
+ "type": "datasource",
+ "uid": "grafana"
+ },
+ "gridPos": {
+ "h": 9,
+ "w": 12,
+ "x": 0,
+ "y": 13
+ },
+ "id": 7,
+ "options": {
+ "debuggingCtr": {
+ "colorsCtr": 0,
+ "dataCtr": 0,
+ "displaySvgCtr": 0,
+ "mappingsCtr": 0,
+ "timingsCtr": 0
+ },
+ "panelConfig": "---\n\nbackground:\n darkThemeColor: \"#0000ff\"\n lightThemeColor: \"#ff0000\"",
+ "siteConfig": "",
+ "svg": "\n\n\n",
+ "testDataEnabled": true,
+ "timeSliderEnabled": true
+ },
+ "title": "Background - darkTheme=#0000ff, lightTheme=#ff0000",
+ "type": "andrewbmchugh-flow-panel"
+ },
+ {
+ "datasource": {
+ "type": "datasource",
+ "uid": "grafana"
+ },
+ "gridPos": {
+ "h": 9,
+ "w": 12,
+ "x": 12,
+ "y": 13
+ },
+ "id": 6,
+ "options": {
+ "debuggingCtr": {
+ "colorsCtr": 0,
+ "dataCtr": 0,
+ "displaySvgCtr": 0,
+ "mappingsCtr": 0,
+ "timingsCtr": 0
+ },
+ "panelConfig": "---\n\nbackground:\n darkThemeColor: \"rgb(0,0,255)\"\n lightThemeColor: \"rgb(255,0,0)\"",
+ "siteConfig": "",
+ "svg": "\n\n\n",
+ "testDataEnabled": true,
+ "timeSliderEnabled": true
+ },
+ "title": "Background - darkTheme=rgb(0,0,255), lightTheme=rgb(255,0,0)",
+ "type": "andrewbmchugh-flow-panel"
+ }
+ ],
+ "refresh": "",
+ "schemaVersion": 38,
+ "style": "dark",
+ "tags": [],
+ "templating": {
+ "list": []
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {},
+ "timezone": "",
+ "title": "Background Color",
+ "version": 12,
+ "weekStart": ""
+ }
\ No newline at end of file
diff --git a/src/components/Config.tsx b/src/components/Config.tsx
index 20fc3d0..101394f 100644
--- a/src/components/Config.tsx
+++ b/src/components/Config.tsx
@@ -18,6 +18,11 @@ export type Link = {
params: LinkUrlParams;
};
+export type Background = {
+ darkThemeColor: string | undefined;
+ lightThemeColor: string | undefined;
+}
+
export type PanelConfigCellLabel = {
dataRef: string | undefined;
separator: LabelSeparator;
@@ -49,6 +54,7 @@ export type SiteConfig = {
};
export type PanelConfig = {
+ background: Background;
variableThresholdScalars: Map;
gradientMode: ColorGradientMode;
cellIdPreamble: string;
@@ -60,6 +66,7 @@ export type PanelConfig = {
export function panelConfigFactory(config: any) {
config = config || {};
return {
+ background: config.background || {},
variableThresholdScalars: new Map(Object.entries(config.variableThresholdScalars || {})),
gradientMode: config.gradientMode || 'none',
cellIdPreamble: config.cellIdPreamble || '',
diff --git a/src/components/FlowPanel.tsx b/src/components/FlowPanel.tsx
index ed2a58e..21b6ee1 100644
--- a/src/components/FlowPanel.tsx
+++ b/src/components/FlowPanel.tsx
@@ -10,7 +10,7 @@ import { svgInit, svgUpdate, SvgHolder } from 'components/SvgUpdater';
import { seriesExtend, seriesInterpolate , seriesTransform } from 'components/TimeSeries';
import { TimeSliderFactory } from 'components/TimeSlider';
import { displayColorsInner, displayDataInner, displayMappingsInner, displaySvgInner } from 'components/DebuggingEditor';
-import { primeColorCache, appendUrlParams, getInstrumenter } from 'components/Utils';
+import { appendUrlParams, getInstrumenter } from 'components/Utils';
import { addHook, sanitize } from 'dompurify';
interface Props extends PanelProps {}
@@ -133,8 +133,7 @@ export const FlowPanel: React.FC = ({ options, data, width, height, timeZ
configInit(siteConfig, panelConfig);
const svgDoc = new DOMParser().parseFromString(sanitizeSvgStr(svgStr), "text/xml");
- const svgAttribs = svgInit(svgDoc, panelConfig, siteConfig);
- primeColorCache(grafanaTheme.current, svgAttribs);
+ const svgAttribs = svgInit(svgDoc, grafanaTheme.current, panelConfig, siteConfig);
svgHolderRef.current = {
doc: svgDoc,
attribs: svgAttribs,
diff --git a/src/components/SvgUpdater.tsx b/src/components/SvgUpdater.tsx
index 24ef6da..30d8ea8 100644
--- a/src/components/SvgUpdater.tsx
+++ b/src/components/SvgUpdater.tsx
@@ -1,11 +1,12 @@
-import { getValueFormatterIndex, formattedValueToString } from '@grafana/data';
+import { getValueFormatterIndex, formattedValueToString, GrafanaTheme2 } from '@grafana/data';
import {
LabelSeparator, Link,
PanelConfig, PanelConfigCell, PanelConfigCellColor, PanelConfigCellLabel,
SiteConfig, VariableThresholdScalars } from 'components/Config';
import { TimeSeriesData } from 'components/TimeSeries';
import {
- cellIdFactory, CellIdMaker, getColor,
+ cellIdFactory, CellIdMaker, colorLookup, getColor,
+ primeColorCache,
variableThresholdScalarsInit, variableThresholdScaleValue } from 'components/Utils';
// Defines the metadata stored against each drivable svg cell
@@ -109,7 +110,7 @@ function recurseElements(el: HTMLElement, cellData: SvgCell, cellIdMaker: CellId
return false;
}
-export function svgInit(doc: Document, panelConfig: PanelConfig, siteConfig: SiteConfig): SvgAttribs {
+export function svgInit(doc: Document, grafanaTheme: GrafanaTheme2, panelConfig: PanelConfig, siteConfig: SiteConfig): SvgAttribs {
let cells = new Map();
const cellIdPreamble = panelConfig.cellIdPreamble;
panelConfig.cells.forEach((cellProps, cellIdShort) => {
@@ -155,7 +156,9 @@ export function svgInit(doc: Document, panelConfig: PanelConfig, siteConfig: Sit
// image won't scale and center corrently
let dimensions = dimensionCoherence(doc);
- return {
+
+
+ const svgAttribs = {
width: dimensions.width,
height: dimensions.height,
scaleDrive: dimensions.scaleDrive,
@@ -163,6 +166,17 @@ export function svgInit(doc: Document, panelConfig: PanelConfig, siteConfig: Sit
elementLinks: elementLinks,
variableValues: variableValues,
};
+
+ // Initialie the color cache and setup the background
+ primeColorCache(grafanaTheme, svgAttribs, panelConfig.background);
+
+ // Set background according to theme if defined in config
+ const bgColor = grafanaTheme.isDark ? panelConfig.background.darkThemeColor : panelConfig.background.lightThemeColor;
+ if (bgColor) {
+ doc.documentElement.style.backgroundColor = colorLookup(bgColor);
+ }
+
+ return svgAttribs;
}
function getCellValue(tsName: string, tsData: TimeSeriesData) {
diff --git a/src/components/Utils.tsx b/src/components/Utils.tsx
index 76e749d..f6025e5 100644
--- a/src/components/Utils.tsx
+++ b/src/components/Utils.tsx
@@ -1,6 +1,6 @@
import { GrafanaTheme2, colorManipulator } from '@grafana/data';
import { SvgAttribs, SvgCell } from 'components/SvgUpdater'
-import { PanelConfigCellColor, Threshold ,VariableThresholdScalars } from 'components/Config';
+import { Background, PanelConfigCellColor, Threshold ,VariableThresholdScalars } from 'components/Config';
@@ -66,7 +66,7 @@ function rgbToString(rgb: number[]) {
return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
}
-export function primeColorCache(theme: GrafanaTheme2, svgAttribs: SvgAttribs) {
+export function primeColorCache(theme: GrafanaTheme2, svgAttribs: SvgAttribs, background: Background) {
function initCache(thresholds: Threshold[] | undefined) {
if (thresholds) {
thresholds.forEach(function(threshold) {
@@ -79,6 +79,13 @@ export function primeColorCache(theme: GrafanaTheme2, svgAttribs: SvgAttribs) {
initCache(cellData.cellProps.fillColor && cellData.cellProps.fillColor.thresholds);
initCache(cellData.cellProps.labelColor && cellData.cellProps.labelColor.thresholds);
});
+
+ if (background.darkThemeColor) {
+ colorStringToRgb(theme, background.darkThemeColor);
+ }
+ if (background.lightThemeColor) {
+ colorStringToRgb(theme, background.lightThemeColor);
+ }
}
export function colorStringToRgb(theme: GrafanaTheme2, colorStr: string) {
diff --git a/yaml_defs/panelConfig.yaml b/yaml_defs/panelConfig.yaml
index 9d3dece..2e6aaf0 100644
--- a/yaml_defs/panelConfig.yaml
+++ b/yaml_defs/panelConfig.yaml
@@ -30,6 +30,12 @@ variableThresholdScalars:
#------------------------------------------------------------------------------
# Panel Config
+# 1.6.0 onwards: When undefined the background color is not driven. When defined the color for
+# the current theme is used. Colors can be entered in all the normal ways of name, hex, hsl, etc.
+background:
+ darkThemeColor: "yellow"
+ lightThemeColor: "green"
+
# This defines the default color gradientMode. It defines the default value on cell labelColor.gradientMode
# and fillColor.gradientMode for when the field is undefined. Values are "hue" and "none" with
# "none" being the default when undefined.