In this tutorial we will create a new widget for the Serverboards Dashboard.
This simple plugin will show the state of all services in the current Serverboard, with some extra goodies, as hover to see the state description, and click to go to the service.
Source code can be obtained at: https://github.com/serverboards/serverboards-plugin-serviceheatmap
Set up the project
Running it will give an output as this one:
$ ./serverboards-template.py rollup ~/src/serverboards-plugins/service-heatmap Please answer how to fill these placeholders: author-email> email@example.com author-name> David Moreno component-type> widget description> Show status of all services in this Serverboard in one heatmap. plugin-id> serverboards.plugin.serviceheatmap plugin-name> Service Heatmap url> https://serverboards.io Postinst OK Ready at /home/dmoreno/src/serverboards-plugins/service-heatmap $
Here we are using the rollup template, and install it at my current plugin working directory.
Serverboards can have several plugin directories; they can be set at
serverboards.ini, and normally, if unconfigured, can be found at
rollup template is currently prepared to be used on both screens and
widgets. As for our plugin we just want a widget, I will remove the parts that
talk about screens.
Its a good momento to review what constitutes a plugin.
A plugin is
In serverboards the only minimum required element for plugins is the
manifest.yaml plugin description file. Each plugin has some data about
creator, name, id… and one or several components. Each component has a type,
cmd, and so on. Check the documentation for the full
In our case we will only do a
widget, so there is only one component.
At runtime Serverboards will get this
manifest.yaml and as it has a widget
type will show it to the user to be used in the Dashboard. When it is used
Serverboards loads the files at
static/COMPONENTID.html. If one of them does not exist its ok; for example we
will not have an html file.
Had it have an html file it will rewritten to use the proper paths for its own data (images, js…) and be inserted into the plugin slot.
A JS Widget
For JS its a bit more complicated. There is a global object Serverboards that allow access to Serverboard functionalities, and to many components.
The idea is that as Serverboard is quite complex and needs libraries as React, jQuery, momentjs, and had developed many many utility functions, as rpc access, React components, its a good idea to share this code. For parts as the rpc module this is required to be able to comunicate with the backend.
main receives the DOM element on which the widget has to mount, and the config
data as stated in the component in the
manifest.yaml, and set up by the user
at the widget settings dialog.
Back to our plugin
As we are using the rollup template we can use React, ES2016, and JSX.
The default view is jsut a JSONinzed version of the config. Lets just change it to something more interesting… a list of our services statuses.
This returns an object and usign the inspector we can easily navigate through
it. Of special interest for this plugin is the
This is a list of all the services in the current Serverboard. To get the status we can use a list mapping:
Actually we will not use this as we more data than jsut the status, for example to which service it belongs, but for that we need to start coding our React components.
Our React components
We will create a container component, that stores the state of our plugin and a view component, that shows this data to the user.
The container component will be fairly easy: jsut the list of services on our current serverboard. As we saw this is just a property on our store, so we will use it as is. Our first version will not deal with state changes, but we will get there later.
Out initial implementation for the container model will be something like this:
For the view component will be:
With that this we have a working plugin!
But we need something more, we need to know when the state changes, and change acordingly. This encompases several dificulties: first we need to be told when the services have changed, and then, when we stop needing this advices we need to unsubscribe from this.
For subscribing we will use the redux subscribe method, that will just ping us on every change on the store. This may look overkill, but in practive there is no problem to recalculate our state (as its just a pointer), and then React will figure out it the DOM has to be changed.
Finally to unsubscribe we just unsubscribe from the redux store.
So we will change out model slightly to be like this.