Code Monkey home page Code Monkey logo

handsome's Introduction

Build Status Coverage Status

Handsome Dashboard Framework

What is Handsome?

Handsome is a dashboard framework written in javascript.

It is currently a work-in-progress.

Handsome is a cousin to Dashing.

Getting Started

Prerequisites

You will need node and yarn installed before you can do anything.

You'll also need redis installed. Read the quickstart guide to get going quickly.

Installation and setup

Easy setup with Docker-compose

This will help you to start with handsome, no redis or npm/yarn requirement, you just need docker-compose & docker.

Build service:

$ docker-compose build

Launch the app

$ docker-compose up

Now visit http://localhost:3000 to see the default dashboard!

Hooray! You're running Handsome in docker!!

docker

To run the standalone image, you need to have a redis server running.

Start redis:

$ redis-server --protected-mode no

--protected-mode is disabled to allow container connection. This is NOT recommend for production use.

Now you can build & run the docker image:

$ docker build -t handsome .

$ docker run -d -p 3000:3000 \
    -e REDIS_SERVER_HOST=<redis_ip_address> \
    -v <jobs_folder>:/opt/app/jobs/ \
    -v <dashboards_folder>:/opt/app/dashboards/ \
    handsome

with :

  • <redis_ip_address> : the ip address of a running redis (you can use ip a to show your ip)
  • <jobs_folder> : folder on host where handsome can find the jobs
  • <dashboards_folder> : folder on host where handsome can find the dashboards

Example:

$ docker run -d -p 3000:3000 \
    -e REDIS_SERVER_HOST=192.168.0.1 \
    -v /home/y0an/handsome/jobs/:/opt/app/jobs/ \
    -v /home/y0an/handsome/dashboards/:/opt/app/dashboards/ \
    handsome

Standard without docker

Clone this repository (or fork it and then clone).

Install dependencies:

$ yarn install

This will also build your js bundle and place it in the build directory.

Start redis:

$ redis-server

Start your Handsome server:

$ yarn start

Now visit http://localhost:3000 to see the default dashboard.

Hooray! You're running Handsome.

A bit more detail

Behind the scenes, Handsome runs a simple Express app to serve widget data and repeatedly schedule jobs to generate new widget data. The data is stored in redis.

In development, the app will auto-generate and serve the client-side assets. Changing a source file will cause the relevant bundle to be regenerated on the fly.

Adding your own dashboard

The default dashboard is a bit boring, so let's add a new one.

Create a new JSX file under the dashboards directory:

$ touch dashboards/my_dashboard.jsx

The skeleton of a dashboard is a simple ReactDOM.render call:

// my_dashboard.jsx

ReactDOM.render(
  <div>
    //Widgets go here!
  </div>,
  document.getElementById('content')
);

Now you can populate the dashboard with widgets by simply adding the appropriate React components as children of the existing div.

Each widget needs a name so that it knows where to call for updates. Each widget type can also have its own properties. The text widget, for example, takes a 'title' property.

Add a text widget to your dashboard:

// my_dashboard.jsx

ReactDOM.render(
  <div>
    <TextWidget name="reddit_headline" title="Top Reddit Headline" />
  </div>,
  document.getElementById('content')
);

That's it! You can now navigate to http://localhost:3000/my_dashboard and see your dashboard and widgets.

Adding Data

Your new dashboard is boring. It's got a widget, but there's no data going to it. You can fix that by adding a new job.

Create a new job file:

$ touch jobs/my_job.js

Jobs need to export the following:

  • An interval, which is the period between each run of the job in milliseconds
  • A promise, which is a function that takes two arguments: fulfill and reject. Call fulfill with the widget data on success or reject with an error message if the job fails.

This function is used to create a Promise.

Here's an example to go with our new widget above that fetches the title of the top Reddit post every minute:

import request from "request"
const url = "https://www.reddit.com/subreddits/popular.json";

export const interval = 300000;
export const promise = (fulfill, reject) => {
  request(url, (error, response, body) => {
    if (!error && response.statusCode == 200) {
      var json = JSON.parse(body);
      var subreddit_list = json['data']['children'].slice(0,19).map(function(item) {
        return item['data']['display_name'];
      });
      fulfill({top_subreddits: {list: subreddit_list}});
    } else {
      reject(error);
    }
  });
};

Making Custom Widgets

Create JSX and Sass files for your widget:

$ touch widgets/my_widget.jsx
$ touch widgets/my_widget.scss

The widget itself should be an ES6 class that extends the BaseWidget like so:

import React from 'react';
import BaseWidget from './widget.jsx';

import './my_widget.scss';

export default class MyWidget extends BaseWidget {

  constructor(props) {
    super(props);
    this.state = {title: "init", text: "init"};
  }

  render() {
    return (
      <div className={"my_widget widget w" + this.props.width + " h" + this.props.height}>
        <h1>{this.props.title}</h1>
        <h2>{this.state.text}</h2>
      </div>
    );
  }
}

At a bare minimum it should also implement the render method and set some initial state in the constructor so that it can be drawn and have some default data to be shown while waiting for the server.

The Sass file should import the variables defined in styles/_variables.scss and all styles should be scoped to the widget in question:

@import '../styles/variables';

.widget.my_widget {
  background-color: $color_4;
  .h2 {
    font-size: 500%;
  }
}

Using a different storage engine

Handsome stores widget data in redis by default, but it uses cacheman as an interface.

This means that you can use any storage engine that cacheman supports. Here are the available storage engines

To switch engines, install the corresponding cacheman package (e.g. cacheman-mongo) for MongoDB and then update the storage options in config.js to use the new engine:

var Cacheman = require('cacheman');

var storage_options = {
  engine: 'mongo',
  port: 9999,
  host: '127.0.0.1',
  username: 'user',
  ...
};

exports.getStorage = function() {
  return new Cacheman('handsome', storage_options)
};

How does Handsome differ from Dashing?

Handsome's front-end is powered by React, while Dashing's is powered by Batman.js

Handsome's back-end is a node/express app, while Dashing runs Sinatra.

Handsome uses a polling model to update dashboards, while Dashing streams data using Server Sent Events.

handsome's People

Contributors

adilfulara avatar davefp avatar erikdstock avatar rorpage avatar y0an avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

handsome's Issues

Production bundle generation

The current webpack config is great for development, but not for production.

We need a new config for production that does the following:

  • minifies/uglifies the bundled JS
  • de-dupes the bundles
  • anything else that is commonly done for production bundles

Setup test

Hi.

I am just finding my feet in the world of JS. landed on this project via dashing.io
Been trying to setup mocha & chai and having a hard time due to es6 and stuff

Update:

  • i am able to run a vanilla mocha + chai test. Its just i am not able to run a test when i start to require / import your widget.

Any plans for setting up a testing f/w ?
Thank you

With windows 10

today is my first day with handsome. I am trying to run it from windows 10 with command
handsome-master>docker-compose build
Then got following message

Building handsome_ui
Step 1/10 : FROM node:8.7
8.7: Pulling from library/node
ERROR: Service 'handsome_ui' failed to build: no matching manifest for windows/amd64 in the manifest list entries

Am I missing any thing?

Update dependencies

At the time of writing, the following dependencies are outdated:

Package                 Current  Wanted  Latest  Location
babel-core                6.7.6  6.18.2  6.18.2  handsome
babel-loader              6.2.4   6.2.7   6.2.7  handsome
babel-preset-es2015       6.6.0  6.18.0  6.18.0  handsome
babel-preset-react        6.5.0  6.16.0  6.16.0  handsome
css-loader               0.23.1  0.23.1  0.25.0  handsome
express                  4.13.4  4.14.0  4.14.0  handsome
ignore-styles             2.0.0   2.0.0   5.0.1  handsome
jquery                    2.2.3   2.2.4   3.1.1  handsome
mocha                     2.5.3   2.5.3   3.1.2  handsome
moment                   2.12.0  2.15.2  2.15.2  handsome
node-sass                 3.4.2  3.11.2  3.11.2  handsome
nyc                       6.6.1   6.6.1   8.4.0  handsome
packery                   2.0.0   2.1.1   2.1.1  handsome
react                    15.0.1  15.3.2  15.3.2  handsome
react-dom                15.0.1  15.3.2  15.3.2  handsome
redis                   2.6.0-1   2.6.3   2.6.3  handsome
request                  2.71.0  2.78.0  2.78.0  handsome
sass-loader               3.2.0   3.2.3   4.0.2  handsome
webpack                 1.12.15  1.13.3  1.13.3  handsome
webpack-dev-middleware    1.6.1   1.8.4   1.8.4  handsome

These should be brought up-to-date one by one and tested.

Webpack compilation warning

WARNING in ./~/cacheman/node/index.js 185:19-35 Critical dependency: the request of a dependency is an expression webpack: Compiled with warnings.

This error is coming from this line in cacheman/node/index.js:

Engine = require(_engine);

Move widget-specific scss out of `default.scss`

Currently all styles are defined in default.scss. This poses problems for sharing widgets, and makes it harder to find styles for the widget you're working on.

Instead, widget styles should be moved to an appropriately-named file in the widgets folder.

e.g. Styles for the number widget would go in widgets/number_widget.scss alongside widgets/number_widget.jsx

Consolidate polling requests

Right now each widget instance makes it's own ajax calls for new data.

It would be much better if these update calls were accumulated over a short period (1 second?) and then pushed out in a single HTTP request to the server.

Support for external widgets and jobs

This issue covers adding support for bringing in external widgets and jobs (maybe even dashboards?) using packages.

The desired workflow would be something like this, similar to how external scripts are used in Hubot:

  1. Add the package as a dependency: > yarn add handsome-custom-widget
  2. Add the package name to a file like external.json:
# external.json
[
  'handsome-custom-widget',
  'handsome-another-custom-widget'
]
  1. Any widgets and/or jobs from the package are now available when building dashboards.

Proposed External Package Structure

External packages should have a /widgets folder that contains any widgets they want to add. Similarly, they should have a /jobs folder that contains any jobs they want to add.

Open questions

  • How are external jobs configured (interval, usernames, etc.)?
  • Should all jobs from a package be run automatically once the package is added or should they need to be configured further first?

Mobile friendly touch option

Hi,

Great work on this!

This needs to be more mobile friendly. It isn't possible to use or scroll on mobile.

Would it be possible for it to detect that when the screen is touch- it required a double tap to move?

Keep up the good work

Better js lib management

Currently all third party js is loaded directly using script tags.

This should be updated to use a package manager such as bower, browserify, or something else.

Write asset precompilation job

Assets are currently being served directly through the sprockets environment. This is fine for dev, but in production we should have a precompilation job that generates concatenated/minified assets and serves those instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.