node package manager

vudash

Easy to use, flexible dashboard software for monitoring, analytics, and more.

Join the chat at https://gitter.im/vudash/vudash-core Build Status js-standard-style

Vudash

A dashboard, like dashing, but written in NodeJS.

vudash-core

Vudash open source component Writen using hapijs, lab, material ui, socket.io, and svelte

What does it look like?

dashboard graph

Demo

http://vudash.herokuapp.com/demo.dashboard

Why?

  • I'll get to the point. I like dashing, but I don't like ruby.
  • Both Dashing and Dashing-js are stellar efforts, but abandoned.
  • Jade is an abomination.
  • Coffeescript is an uneccessary abstraction.
  • dashing-js has a lot of bugs

Features

  • will happily run on a free heroku instance
  • es6
  • all cross-origin requests done server side
  • websockets rather than polling
  • websocket fallback to long-poll when sockets aren't available
  • Custom widgets
  • Custom dashboards
  • Simple row-by-row layout
  • Dashboard arrangement is simply the config order (see below)
  • Super simple widget structure

Tests

Clone me and run npm test

Project Status

Status: Rewrote entire original 'vudash' application as a core-component of a bigger project. Now fully tested, with a handful of example widgets.

Usage

Install as a global module npm install -g vudash and use vudash create to create an example dashboard. Add new widgets under /widgets and add them to your dashboard under /dashboards.

You can visit your created dashboard by visiting http://localhost:3000/.dashboard - where <dashboard> is the name of a JSON file within the /dashboards directory.

Visiting the root of the application will yield a list of all available dashboards, unless the environment variable DEFAULT_DASHBOARD is set, in which case that dashboard will be loaded instead. Other dashboards will still be available via the normal methods.

Quick start

In so few lines:

  npm install -g vudash
  vudash create
  vudash

Dashboards

A dashboard is a collection of widgets separated into rows and columns.

Dashboards are in JSON format and take the form:

{
  "name": "Happy",
  "layout": {
    "columns": 5,
    "rows": 4
  },
  "shared-config": {
    "google-config": {
      "email": "you@example.net"
    }
  }
  "widgets": [
    { "position": {"x": 0, "y": 0, "w": 1, "h": 1}, "widget": "./widgets/random" },
    { "position": {"x": 3, "y": 0, "w": 2, "h": 1}, "widget": "vudash-widget-time" },
    { "position": {"x": 4, "y": 1, "w": 1, "h": 1}, "widget": "./widgets/github" },
    { "position": {"x": 0, "y": 1, "w": 2, "h": 1},
      "widget": "vudash-widget-pluck",
      "options": {
        "_extends": "google-config",
        "path": "rates.GBP", "description": "EUR -> GBP"
      }
    },
    { "position": {"x": 4, "y": 2, "w": 1, "h": 1},
      "widget": "vudash-widget-travis",
      "options": {
        "user": "vudash",
        "repo": "vudash-widget-travis"
      }
    }
  ]
}
 

Where 'widgets' is an array of widgets. The position in the grid (specified by layout) is indicated by the widget's x and y position values.

The values for position.w and position.h are the number of grid units the widget occupies in width and height, respectively.

Widgets can be either a path to a directory containing a widget (see below), or an npm module of the same. If the widget is a npm module, you would need to npm install --save <widget-name> first.

Widgets can share configuration by using shared-config which is a key-values map of config names to config objects. You can then use _extends in the options block of a widget config, and only override the widget properties that you wish to change.

Widgets

Widgets are configured in the dashboard.json file, in the format:

{
  "widget": "./widgets/pluck", // widget file path, node module name, or class definition 
  "position": {
    "x": 1, // x position (row number) of widget 
    "y": 1, // y position (column number) of widget 
    "w": 1, // widget width in columns 
    "h": 1  // widget height in columns 
  },
  "options": { // widget specific config 
    "your" : "config"
  }
}

Widgets have some optional properties:

property name description example
background css for "background" style attribute #ffffff

Creating a widget

A widget is a visible indicator of some sort of statistic or other monitor, which emits new data using websockets, and updates its display in the dashboard based on the information given in this data.

A widget is packaged as a node module, but a node module can simply be a folder with a package.json file. It can then contain a number of files:

Predefined widgets

There are a series of pre-defined widgets available. These widgets are npm packages beginning with 'vudash-widget' Generally the widget's major version number should match the vudash instance's major version number to guarantee compatiblity.

package.json

{ "name": "vudash-widget-example", "main": "widget.js" }

The main js file above should reference your main module class, in this example we call it widget.js

widget.js

'use strict'
 
const moment = require('moment')
 
class TimeWidget {
 
  register (options, emit) {
    return {
      schedule: 1000,
 
      job: () => {
        const now = moment()
        return Promise.resolve({
          time: now.format('HH:mm:ss'),
          date: now.format('MMMM Do YYYY')
        })
      }
 
    }
  }
 
}
 
module.exports = TimeWidget

The main widget file. The crux of this file is to export a class with a single method, register, which returns a widget configuration, which is:

  {
    config: {abc: 'def'}, // configuration to pass to the client and server side widget. Available in the client as `$widget.config` and `options` parameter of `register()` 
    schedule: 1000, // Put simply, how often the widget sends updates, 
    job: () => { return Promise.resolve({some: 'result'}) } // The crux of the widget. Does some sort of work or check, and then resolves with the results. 
  }

To pass configuration, you can use the options parameter of register()

The second parameter to register is the optional parameter emit which can be used to emit events (at any time) to the dashboard. See Events below for more information about this.

Writing a client side component

Client side components are defined using svelte which allows you to build framework-independent client side components with ease.

There are two ways to define components, either:

  1. Multi-part: Define vudash.markup, vudash.script and vudash.styles in your widget's package.json and put your html, svelte component, and css into them respectively.
  2. Single-part: Just define vudash.component in your widget's package.json, and place all your svelte component's code there.
Example of a single part component:

package.json

{
  "name": "vudash-widget-health",
  "main": "widget.js",
  "vudash": {
    "component": "./component.html"
  }
}

component.html

<h1 class="vudash-hello">{{ greeting }}</h1>
<style>
  .vudash-hello {
    text-align: right;
  }
</style> 
<script>
  export default {
    data () {
      return {
        greeting: 'hello'
      }
    },
 
    methods: {
      /**
      * This is the really important bit. This update method is called whenever the widget emits data.
      **/
      update (data) {
        this.set(data)
      }
    }
  }
</script> 

See the Svelte Documentation for information on how to build svelte components.

Events

Events can be emitted using the event emitter which is passed into the register method. These events will cause dashboard-wide actions to happen.

emit('audio:play', {data: data})

The current list of events that can be triggered are:

Event Data Description
audio:play { data: data} Plays an audio clip (once). data is a data-uri of the audio file.

Troubleshooting

  • Q. The console shows that the websocket is failing to connect, and my widgets aren't updating.
  • A. Your hosting provider might not be correctly reporting the external vhost of the server. Add an environment variable SERVER_URL with the full url to your server, i.e: http://www.example.com/

Roadmap

  • Heroku easy deploy
  • You, sending Pull Requests.