Joao Gameiro

Viz-SVG

Blog Post created by Joao Gameiro Employee on Dec 22, 2017

Introduction

 

Charts are a good way to visualize our data, but in some cases they are not enough.

Imagine you need to show a vehicle current status, based on his sensor data, don't you think the image below is more suitable than a table or chart?

 

 

  

The intention is to expose in the easiest way the information needed to support future actions.

 

Despite all possibilities to do this using the available methods, the idea of using an SVG image, which could be changed according to the data being received, sounded really cool.

 

As you might know, SVG images are basically XML files with four interesting characteristics (at least the ones that matter for this component):

  • are scalable,
  • normally end up with file sizes shorter than similar image formats,
  • can have identifiable elements on their structure,
  • modifiable once injected into the HTML DOM, via javascript.

 

Merging the approach used on SVG component and VIZ-APIVIZ-SVG was born.

 

Requirements

  • Javascript knowledge
  • Pentaho 8.0
  • npm

If you don’t have the node.js (npm) already installed follow this instruction:

https://docs.npmjs.com/getting-started/installing-node

How to build your own visualization using Viz-SVG project

 

Download the git folder example.

 

Extract the zip file, the necessary files are already there:

  • SVG image – circle.svg
  • The Model – yourmodel.js
  • Dummy data – data.json

 

circle.svg

 

<g>
  <title>SVG Example</title>
  <rect fill="#fff" id="canvas_background" height="402" width="582" y="-1" x="-1"/>
  <g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
   <rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
  </g>
 </g>
 <g>
  <title>Circle</title>
  <ellipse id="Sales" fill="lightgray" stroke="black" ry="70" rx="70"  cy="195" cx="281" stroke-width="5" />
 </g>
</svg>

 

data.json
  • svgElementID - the element name on circle.svg
  • value - bussines data

 

{
  "model": [
         {"name": "svgElementID", "type": "string", "label": "svg Element ID"},
         {"name": "value", "type": "number", "label": "Value"}
  ],
  "rows": [
         {"c": [ "Sales",  11000000]}
  ]
}
yourmodel.js

 

var SvgModel = BaseModel.extend({
     $type: {
          // SVG Label and Class
          styleClass: "pentaho-visual-samples-svg",
          label: "SVG Circle"
     },

     getSvgPath: function() {
          return "./circle.svg"; 
     },

     getSvgPartforDataID: function(dataId){
          return ["Stroke", "Fill"];
     },

     toSvgId: function(dataId, prop){
          return dataId ;
     },

     toSvgAttribute: function(dataId, prop, dataValue) {
          switch(prop){
               case "Stroke": return "stroke";
               case "Fill": return "fill";
          }
          return prop;
     },

     toSvgValue: function(dataId, prop, dataValue) {
          switch(prop){
               case "Stroke": return dataValue > 11000000 ? "red" : "green";
               case "Fill": return dataValue > 11000000? "green" : "red";
          }
     }
});






 

Pay attention to:

  • Label, this is the name that will appear in the list of available visualizations in Analyzer
label: "SVG Circle"

 

  • Path to your image
getSvgPath: function() {
     return "./circle.svg"; 
},

 

  • Properties that will be changed for each SVG element, (Stroke and Fill)
getSvgPartforDataID: function(dataId){
     return ["Stroke", "Fill"];
},

 

  • SVG id - if you need to change the SVG element id add some logic to this function
    • Take a look at the other example (modelProductLine.js)
toSvgId: function(dataId, prop){
     return dataId ;
},

 

  • Mapping between properties defined previous and SVG style properties
toSvgAttribute: function(dataId, prop, dataValue) {
     switch(prop){
          case "Stroke": return "stroke";
          case "Fill": return "fill";
     }
     return prop;
},

 

  • Define your business logic
toSvgValue: function(dataId, prop, dataValue) {
     switch(prop){
          case "Stroke": return dataValue > 11000000 ? "red" : "green";
          case "Fill": return dataValue > 11000000? "green" : "red";
     }
}

 

 

Now it's time to test our visualization

Register our files on index.html (Index.html purpose is to render our code on the browser.)

  • data.json is our dummy data
  • yourModel is our configuration

 

require([
        "pentaho/type/Context",
        "pentaho/data/Table",
        "json!./sales-by-product-family.json"
      ], function (Context, Table, dataSpec) {


        // Setup up a VizAPI context.
        Context.createAsync({ application: "viz-api-sandbox" })
          .then(function (context) {
            // Get the model and base view types
            return context.getDependencyAsync({
              BarModel: "pentaho/visual/samples/bar/modelProductLine",
              BaseView: "pentaho/visual/base/view"
            });
          })



 

Change:

line 04 - "json!./sales-by-product-family.json"   to    "json!./data.json"   and

 

line 13 - BarModel: "pentaho/visual/samples/bar/modelProductLine",  to   BarModel: "pentaho/visual/samples/bar/yourModel",

 

Let’s open index.html on browser.

Attention: directly opening the file through the filesystem will not work when using Google Chrome (and possibly other browsers), because of security restrictions that disallow the loading of local resources using XHR — a functionality that is required by the VIZ-SVG to load localization bundles and other resources.

To overcome this limitation we will use Node.js to serve the project files through an HTTP server.

 

Node:

npm install -g node-static

static -p 8001

 

Now you can open http://127.0.0.1:8001/index.html in the browser and test.

 

Change the values of data.json to modify colors

Edit data.json and change 11000000 to -> 11000001.

 

Refresh your browser

Colors should change (if not, clear browser cache).

 

Edit your model until your visualization is OK.

 

Create the Pentaho Web Package

Register your model on config.js and package.json

  • Config.js
    •      add the following line: module.id.replace(/(\w+)$/, "yourModel")(\w+)$/, "yourModel")
select: {
          type: [
               module.id.replace(/(\w+)$/, "modelGeneric"),
               module.id.replace(/(\w+)$/, "modelProductLine"),
               module.id.replace(/(\w+)$/, "yourModel")
  ],

 

  • package.json
    • add the following line: "pentaho-visual-samples-svg/yourModel": {"base": "pentaho/visual/base/model"}
 "pentaho/typeInfo": {
      "pentaho-visual-samples-svg/modelProductLine": {"base": "pentaho/visual/base/model"},
      "pentaho-visual-samples-svg/yourModel": {"base": "pentaho/visual/base/model"}
    },

 

Let's create our .tgz file

 

Note: By using the npm pack command you ensure only your files and bundled dependencies are compressed in the resulting tgz file.

 

Run npm pack on viz-svg-sandbox folder.

 

Deploy on Pentaho server and PDI

 

Copy the pentaho-visual-samples-svg-0.0.1.tgz to

  • pentaho-solutions/system/karaf/deploy/ (Pentaho Server)
  • data-integration/system/karaf/deploy   (PDI)

 

See the visualization on Pentaho BA server and PDI

 

Create a new Analysis Report using SampleData

  • Choose
    • Measure - Actual
    • Category – Department

 

Pick on the list, right side, our SVG Circle visualization.

 

 

 

Do the same on PDI (DET)

  • Choose
    • Measure - Actual
    • Category – Department

 

 

 

 

Our .tgz has another extra visualization: SVG Product Line.

 

 

 

 

Marketplace

You can find more examples in Pentaho Marketplace, search by VIZ-SVG, and install both.

 

 

 

Why use Viz-SVG

 

Viz-SVG can be a good way to visualize your IoT data during all pipeline process, PDI, Analyzer and CTools dashboards.

Example: you may need to check the occupancy on your office floor, what best than an SVG office layout.

 

 

Enjoy and share your visualizations.

Outcomes