Writing React Plugins
-
In this blog post we will go through how you can create plugins for Grafana using ReactJS. This presumes you have some basic knowledge about writing components in React.
(complete code for the example used in this post can be found here).
In Grafana 6.0 we started the migration to using React in Grafana. This allows you to write plugins using React instead of AngularJS. We are making it easier to write React plugins by releasing a Grafana component library - the new @grafana/ui npm package.
Let’s take a look at how you can build your own plugin, using React and TypeScript.
Setup
There are a few things to consider when writing a new plugin. With Grafana 6.0, we need to move our plugins directory outside of the Grafana project directory. Feel free to put your plugins directory where you usually store code on your computer. Next, we need to tell Grafana where it should look for plugins. Grafana comes with a
defaults.ini
file ingrafana/conf/
, and we can overwrite this by creating and modifying acustom.ini
. So put yourself in thegrafana/conf
directory andcp defaults.ini custom.ini
.Open
custom.ini
with your file editor of choice and search for this phrase:Directory where grafana will automatically scan and look for plugins
Modify the line under that to:
plugins = <path to your plugins directory>
Restart your grafana-server after this.
Now we’re ready to move on!
The Structure
Grafana needs some basic project structure in your plugin. Grafana will look for a
plugin.json
located in asrc
directory. Theplugin.json
should contain some information about your plugin; you can read more about it here.Also within the
src
directory we need amodule.tsx
file. In this file, we will introduce the first magic from our newly-released@grafana/ui
package.import { ReactPanelPlugin } from '@grafana/ui'; import { RssPanel } from './components/RssPanel'; import { RssPanelEditor } from './components/RssPanelEditor'; import { defaults, RssOptions } from './types'; export const reactPanel = new ReactPanelPlugin<RssOptions>(RssPanel); reactPanel.setEditor(RssPanelEditor); reactPanel.setDefaults(defaults);
Let’s go through this and figure out what this file does:
First off, we’re creating a new instance of a
ReactPanelPlugin
, which is a class imported from @grafana/ui. We’re sending in our option type (in this case RssOptions, which we’ll get to later).Next up we’re setting the editor component for our plugin with the
setEditor()
function.Lastly we’re setting any default options that we might have.
That’s it!
The Panel
Now we’re at the fun part. This is where you can let your creativity flow. In this example we’re building an Rss-panel, and what we’re going to need is some kind of table to display our result. We’re going to use an interface exported by
@grafana/ui
calledPanelProps
. This will provide us with the props we need, such as height and width. I won’t go into any specifics about writing React components, but I will highlight some things that we do to make our panels written in React work.Basic setup of a panel class:
interface Props extends PanelProps<RssOptions> {} interface State {} export class RssPanel extends PureComponent<Props, State> {}
It’s important to use React’s life cycle methods to make sure your component updates when the props change. We do this by invoking
componentDidUpdate
in our Rss-panel example. So when our user updates the url to the rss feed, we will update the panel to fetch an rss feed from the new url. In this example we’re using a library calledrss-to-json
to fetch and transform the rss feed to javascript objects.The Panel editor
For adding options to Plugins, we’re using a concept called Editors. In this example we’ll create a component called
<RssPanelEditor />
. We have an interface for Editors in@grafana/ui
as well, calledPanelEditorProps
. If we provide our options type to this interface, we will have theonChange
method available for updating our panel when we change the options.export class RssPanelEditor extends PureComponent<PanelEditorProps<RssOptions> { onUpdatePanel = () => this.props.onChange({ ...this.props.options, feedUrl: 'this new rss feed url' }); }
Types
We strongly encourage you to use types in your panel. This makes it easier for you and others to spot potential bugs. In this example we’ve added some types for
RssFeed
,RssFeedItem
, andRssOptions
. These are located insrc/types.ts
.Building
To be able to load the plugin, Grafana expects the code to be in plain JavaScript. We’re using webpack for the build step to transpile TypeScript to JavaScript in our RSS-plugin example.
Testing
Start your grafana-server again, and make sure that your plugin is registered.
Registering plugin logger=plugins name="Rss Panel"
Add a new panel to a dashboard, and locate your new panel in the visualization picker.
/blog/2019/03/26/writing-react-plugins/
© Lightnetics 2024