/vudash-core

Powerful, Flexible, Open Source dashboards for anything

Primary LanguageJavaScript

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, semantic ui, socket.io

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 {

      markup: 'markup.html',
      update: 'update.js',
      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()`
    markup: 'markup.html', // The html for the widget. This is automatically wrapped in a grid cell, so it can be any html you like.
    update: 'update.js', // The method that is triggered when the `job` emits new data. This gets `$widget`, `$id`, and `$data` passed in, as detailed below.
    schedule: 1000, // Put simply, how often the widget sends updates,
    css: 'styles.css', // Or, an array of css filenames. these are rendered to the client.
    clientJs: 'client.js', // or an array of js files. These are rendered to the client.
    job: (emit) => { emit({x: 'y'}) } // The crux of the widget. Does some sort of work or check, and then emits 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.

update.js

The client side code to update the widget. It is wrapped in a function which contains

  • $id: The widget's ID (For avoiding conflicts in the browser - this is in the format widget_ where random is some random chars assigned at load time)
  • $widget: The widget itself, initially contains one property, config, which is the config you gave in widget.js above. You can use it as a store for anything you like, as it is namespaced to the widget you are working on. i.e. $widget.myValue = 'x'
  • $data: Whatever you emit from emit() in your job method. Ideally this is a javascript object.

markup.html

Just html. Use {{id}} to get the ID of the widget mentioned above. Your html should use things like <h1 id="{{id}}-some-thing"/> to avoid conflicts. You can then reference them using $id+'-some-thing' when you need to access them from the clientside javascript.

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.