Sankey diagram. Help needed to execute javascript in HABPanel custom widget

Power consumption in your home:


(Dummy data above)

I’ve finally worked out what the diagram was that I have been looking for - it’s called a Sankey Diagram :slight_smile:

Well, I am trying to write another widget to display this based on your measurement items. I have the rules and items working and get it to build the correct data format to populate the diagram.

What I can’t work out is how to execute the existing JS within the HABPanel widget.
I have:

  • A js file with the library in html folder
  • A file called cp.js which is my data file

The html has a div, which is in the widget, and there is a call to the .create method which makes magic happen. I understand that js cannot be execute like normal but cannot fathom how, if at all, I can get it to start.

Example is here: https://codepen.io/plotly/pen/OvywBa

My widget is


  <div id="myDiv" oc-lazy-load="['/static/cps/cp.js', '/static/cps/plotly-latest.min.js']"><!-- Plotly chart will be drawn inside this DIV --></div>

and, well, the cp.js contains rubbish as this point. All the examples I have copied don’t work when I put the code below in


var data = {
  type: "sankey",
  orientation: "h",
  node: {
    pad: 15,
    thickness: 30,
    line: {
      color: "black",
      width: 0.5
    },
   label: ["A1", "A2", "B1", "B2", "C1", "C2"],
   color: ["blue", "blue", "blue", "blue", "blue", "blue"]
      },

  link: {
    source: [0,1,0,2,3,3],
    target: [5,3,3,4,4,5],
    value:  [8,4,2,8,4,2]
  }
}

var data = [data]

var layout = {
  title: "Basic Sankey",
  font: {
    size: 10
  }
}

Plotly.react('myDiv', data, layout, {showSendToCloud:false})

What I want to do:
I have a string items which build up the data in the same shape as as that needed to populate the graph but don’t know where to start to get the graph to draw on the widget.

Google has another version but it requires an online-library. Maybe easier?
https://developers.google.com/chart/interactive/docs/gallery/sankey

Help :slight_smile:

nobody has any ideas on how to get this working? :frowning:
I’ve been messing around with it for a while and don’t grasp what is needed to get your own code working here :frowning:

Plotly makes unsafe evaluations in its code, this is blocked by the restrictive CSP put in place in HABPanel’s code (which you cannot change unless you fork it). See: https://github.com/plotly/plotly.js/issues/897

But you can use another library like ECharts: https://www.echartsjs.com/examples/en/#chart-type-sankey

Download echarts-en.min.js from https://github.com/apache/incubator-echarts/tree/4.5.0/dist (actually https://raw.githubusercontent.com/apache/incubator-echarts/4.5.0/dist/echarts-en.min.js).
Then make an AngularJS directive like this:

angular
  .module('app.widgets')
  .directive('sankeyDiagram', ['OHService', function (OHService) {
    return {
      restrict: 'E',
      scope: {
        // optionally add attributes here
        // orientation: '=',
        // ...
      },
      link: function (scope, elem, attrs) {
        var myChart = echarts.init(elem[0].parentElement, 'dark');
        // mainly taken from https://www.echartsjs.com/examples/en/editor.html?c=sankey-simple
        myChart.setOption(option = {
          color: [
            '#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'
          ],
          tooltip: {
            trigger: 'item',
            triggerOn: 'mousemove'
          },
          animation: false,
          series: {
            type: 'sankey',
            layout: 'none',
            data: [{
              name: 'a'
            }, {
              name: 'b'
            }, {
              name: 'a1'
            }, {
              name: 'a2'
            }, {
              name: 'b1'
            }, {
              name: 'c'
            }],
            links: [{
              source: 'a',
              target: 'a1',
              value: 5
            }, {
              source: 'a',
              target: 'a2',
              value: 3
            }, {
              source: 'b',
              target: 'b1',
              value: 8
            }, {
              source: 'a',
              target: 'b1',
              value: 3
            }, {
              source: 'b1',
              target: 'a1',
              value: 1
            }, {
              source: 'b1',
              target: 'c',
              value: 2
            }]
          }
        });
      }
    };
  }]);

Your template will then be:

<div style="width:800px;height:600px"
     oc-lazy-load="{ serie: true, files: ['/static/cps/echarts-en.min.js', '/static/cps/cp.js']}">
  <sankey-diagram></sankey-diagram>
</div>

note the serie: true ocLazyLoad option to load the JS files in a sequence (first ECharts then your code).

If you can have this working you’re on the right path, look in the ECharts docs to customize options and search here on how to use the OHService injected in the directive to retrieve data from your items.

1 Like

well, there’s my evening out the window :smiley:

Thanks!I will mess around with this tonight