Skip to main content

External JS and CSS resources, status field, and increased test coverage in Business Text 4.1.0

Mikhail Volkov
Founder at Volkov Labs, Grafana Champion

We're excited to announce the release of the Business Text panel 4.1.0. This feature release includes the following updates:

  • Added support for external JavaScript and CSS resources.
  • Added the status field to display a background color.
  • Increased test coverage up to 99%.
Grafana Catalog

The plugin was updated in the Grafana Plugins catalog on July 18, 2023.

Business Text panel 4.1.0 for Grafana.

External JavaScript and CSS resources

The Business Text panel plugin enables the loading of additional JavaScript and CSS resources from external URLs like CDN (Content Delivery Network). To prevent the loading of third-party URLs, you can store CSS and JS files on your Grafana instance in the public folder.

Sanitization

You need to disable sanitization in your Grafana instance to see external resources in the panel options.

Loading Google Material CSS and JS files from an external resource.
Loading Google Material CSS and JS files from an external resource.

You can use external CSS and JS files to include additional visual elements and execute JavaScript functions from the JavaScript code editor.

Status field

The statusColor variable can be used to set a background or foreground color of any HTML element based on the threshold ranges for the selected status field.

Status field allows you to dynamically set a background or foreground color.
Status field allows you to dynamically set a background or foreground color.

Example

<div style="background-color: {{statusColor}}">{{A-series}}</div>

Sophisticated solution from the community

Business Text panel enables the creation of the most comprehensive solutions without building additional panels.

Register the aggr_val Handlebars helper to aggregate values returned from a data source.

handlebars.registerHelper(
"aggr_val",
(
data = my_data,
key_value,
aggr,
key_to_filter1,
val_to_filter1,
key_to_filter2,
val_to_filter2
) =>
((numbers) => {
const result =
numbers.length === 0
? 0
: aggr === "sum"
? numbers.reduce((total, num) => total + num, 0)
: aggr === "avg"
? numbers.reduce(
(total, num, _, { length }) => total + num / length,
0
)
: aggr === "min"
? numbers.reduce((min, num) => (num < min ? num : min), numbers[0])
: aggr === "max"
? numbers.reduce((max, num) => (num > max ? num : max), numbers[0])
: aggr === "first"
? numbers[0]
: aggr === "last"
? numbers[numbers.length - 1]
: (() => {
throw new Error(
"Invalid aggr. Supported aggr are: sum, avg, min, max, first, last"
);
})();
return Number.isInteger(result) ? result : result.toFixed(2);
})(
data
.filter(
(item) =>
item[key_to_filter1] === val_to_filter1 &&
item[key_to_filter2] === val_to_filter2
)
.map((item) => item[key_value])
)
);

handlebars.registerHelper(
"sel_val",
(
data = my_data,
key_value,
key_to_filter1,
val_to_filter1,
key_to_filter2,
val_to_filter2
) => {
return data
.filter(
(item) =>
item[key_to_filter1] === val_to_filter1 &&
item[key_to_filter2] === val_to_filter2
)
.map((item) => item[key_value]);
}
);

Display aggregated values based on any rules, which the native Grafana transformations do not support.

# ### sel_val data "value"

{{sel_val data "value"}}

- sum:
{{aggr_val data "value" "sum"}}, avg:
{{aggr_val data "value" "avg"}}, min:
{{aggr_val data "value" "min"}}, max:
{{aggr_val data "value" "max"}}, first:
{{aggr_val data "value" "first"}}, last:
{{aggr_val data "value" "last"}}, # ### sel_val data "value" "category" "A"
{{sel_val data "value" "category" "A"}}
- sum:
{{aggr_val data "value" "sum" "category" "A"}}, avg:
{{aggr_val data "value" "avg" "category" "A"}}, min:
{{aggr_val data "value" "min" "category" "A"}}, max:
{{aggr_val data "value" "max" "category" "A"}}, first:
{{aggr_val data "value" "first" "category" "A"}}, last:
{{aggr_val data "value" "last" "category" "A"}}, # ### sel_val data "value"
"category" "A" "type" "T1"
{{sel_val data "value" "category" "A" "type" "T1"}}

sum:
{{aggr_val data "value" "sum" "category" "A" "type" "T1"}}, avg:
{{aggr_val data "value" "avg" "category" "A" "type" "T1"}}, min:
{{aggr_val data "value" "min" "category" "A" "type" "T1"}}, max:
{{aggr_val data "value" "max" "category" "A" "type" "T1"}}, first:
{{aggr_val data "value" "first" "category" "A" "type" "T1"}}, last:
{{aggr_val data "value" "last" "category" "A" "type" "T1"}},

Code Coverage

With our plugins installed on thousands of Grafana instances, we recognize that our users do not experience any unexpected changes, thus we increased Business Text panel's test coverage up to 99% and refactored its legacy components.

For all of our Grafana plugins, we aim for greater than 90% test coverage.
For all of our Grafana plugins, we aim for greater than 90% test coverage.

Getting Started

You can install the Business Text panel from the Grafana Plugins catalog or using the Grafana command line tool.

Install Business Suite plugins in Cloud, OSS, Enterprise. Getting started with the Business Suite.

For the latter, please use the following command:

grafana cli plugins install marcusolsson-dynamictext-panel

Tutorial

The video reviews the major latest release including the data flow, predefined helpers and numerous examples of the external JavaScript libraries.

The Business Text panel for Grafana. Main features overview in 5.0.0

We have many other tutorials that you can find helpful. You can review all related to this plugin tutorials here.

Release Notes

Features / Enhancements

  • Updated ESLint configuration (#192).
  • Increased test coverage for the plugin's functionality (#194).
  • Added the status field (#196).
  • Added support for external JavaScript and CSS resources (#197).
  • Added compatibility with Grafana 10.0.2 (#201).

Always happy to hear from you

  Enroll in Business Suite Enterprise