Skip to main content

Data Manipulation Panel

Grafana 9 YouTube CI codecov Language grade: JavaScript

Introduction

The Data Manipulation Form Panel is a plugin for Grafana that can be used to insert, update application data, and modify configuration directly from your Grafana dashboard.

Requirements

  • Grafana 8.5+, Grafana 9.0+ is required for version 2.X.
  • Grafana 8.0+ is required for version 1.X.

Getting Started

Data Manipulation panel can be installed from the Grafana repository or use the grafana-cli tool to install from the command line:

grafana-cli plugins install volkovlabs-form-panel

Features

  • Provides functionality to create customizable forms with elements:
    • Code Editor
    • Date and Time
    • Read-only (Disabled)
    • Number Input
    • Number Slider
    • Password Input
    • Radio Group with Boolean options
    • Radio Group with Custom options
    • Select with Custom options
    • String Input
    • Text Area
  • Supports the Custom Code for Initial and Update requests.
  • Allows to specify GET request to get initial values and POST, PUT, PATCH request to send values updated in the form.
  • Allows to add Header fields to Initial and Update requests.
  • Allows to customize Submit, Reset buttons and form layout.
  • Allows to split form elements into sections.
  • Allows to request confirmation before update request.

Architecture

Diagram

API

Custom Code

The custom code has access to the Panel options, the response from the REST API call, form elements, various Grafana services and will be executed after the Initial and Update requests.

Available Parameters:

  • options - Panels' options.
  • data - Result set of panel queries.
  • response - Request's response.
  • json - Parsed JSON from the Initial Request.
  • elements - Form Elements.
  • locationService - Grafana's locationService to work with browser location and history.
  • templateService - Grafana's templateService provides access to variables and allows to update Time Range.
  • onOptionsChange() - Panel options Change handler to refresh panel.
  • initialRequest() - Perform the Initial Request to reload panel.

Panel

To learn more about parameters you can log them in the Browser Console:

console.log(
options,
data,
response,
elements,
locationService,
templateService
);

Reload page after update request or show error

if (response && response.ok) {
location.reload();
} else {
alert(`Error: ${response.status}`);
}

Perform Initial Request after update request or show error

if (response && response.ok) {
initialRequest();
} else {
alert(`Error: ${response.status}`);
}

Clear elements' values after Submit or on Reset button click

elements.map((element) => {
if (element.id === "name") {
element.value = "";
}
});

onOptionsChange(options);

onOptionsChange handler is required to update the panel.

Dashboard Variables

Dashboard and Global variables will be replaced automatically in:

  • URL for Initial and Update requests
  • Header Parameters' values
  • Request body, which contains elements' values

You can find global built-in variables in the Grafana documentation.

Dynamic form elements

Using the custom code you can update elements or element's value and options from any data source.

Fill options of the icon element from series icons with icon_id and title columns

const icons = data.series.find((serie) => serie.refId === "icons");
const iconSelect = elements.find((element) => element.id === "icon");

if (icons?.fields.length) {
const ids = icons.fields.find((f) => f.name === "icon_id").values.buffer;
const titles = icons.fields.find((f) => f.name === "title").values.buffer;

iconSelect.options = titles.map((value, index) => {
return { label: value, value: ids[index] };
});
}

onOptionsChange(options);

Update all form elements from data sources

const feedback = data.series.find((serie) => serie.refId === "Feedback");
const typeOptions = data.series.find((serie) => serie.refId === "Types");

if (feedback?.fields.length) {
const ids = feedback.fields.find((f) => f.name === "id").values.buffer;
const titles = feedback.fields.find((f) => f.name === "title").values.buffer;
const types = feedback.fields.find((f) => f.name === "type").values.buffer;

/**
* Set Elements
*/
elements = ids.map((id, index) => {
return { id, title: titles[index], type: types[index] };
});

/**
* Find Type element
*/
const typeSelect = elements.find((element) => element.id === "type");
if (typeSelect && typeOptions?.fields.length) {
const labels = typeOptions.fields.find((f) => f.name === "label").values
.buffer;
const values = typeOptions.fields.find((f) => f.name === "value").values
.buffer;

/**
* Update Types
*/
typeSelect.options = labels.map((label, index) => {
return { label, value: values[index] };
});
}

/**
* Update Panel Options
*/
onOptionsChange({ ...options, elements });
}

Custom Requests

Data Manipulation panel allows to create your own Initial and Update requests using Custom Code.

Initial Request

Select Initial Request as - and set Custom Code:

const bucketsSelect = elements.find((element) => element.id === "buckets");

/**
* Set URL
*/
const url = `http://localhost:3001/test`;

/**
* Fetch
*/
const resp = fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
"PRIVATE-TOKEN": "$token",
},
})
.catch((error) => {
console.error(error);
})
.then(async (resp) => {
const body = await resp.json();

bucketsSelect.options = body.buckets.map((value) => {
return { label: value, value };
});

onOptionsChange(options);
});

Update Request

Select Update Request as - and set Custom Code:

/**
* Set body
*/
const body = {};
options.elements.forEach((element) => {
body[element.id] = element.value;
});

/**
* Set URL
*/
const url = `http://localhost:3001/${body["name"]}`;

/**
* Fetch
*/
const resp = fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"PRIVATE-TOKEN": "$token",
},
body: JSON.stringify(body),
})
.catch((error) => {
console.error(error);
})
.then((resp) => {
console.log(resp);
});

NGINX

We recommend running Grafana behind NGINX reverse proxy for an additional security layer. The reverse proxy also allows us to expose additional API endpoints and static files in the same domain, which makes it CORS-ready.

NGINX

Read more in How to connect the Data Manipulation plugin for Grafana to API Server.

Feedback

We love to hear from users, developers, and the whole community interested in this plugin. These are various ways to get in touch with us:

  • Ask a question, request a new feature, and file a bug with GitHub issues.
  • Star the repository to show your support.

License

  • Apache License Version 2.0, see LICENSE.