Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Converting Jupyter Notebook rendered JavaScript Graph to htmlwidget: issue with dependency dependencies .... #411

Open
DyfanJones opened this issue May 19, 2021 · 0 comments

Comments

@DyfanJones
Copy link

DyfanJones commented May 19, 2021

Hi all,

I am currently developing a package for AWS Stepfunctions: (https://github.com/DyfanJones/aws-step-functions-data-science-sdk-r). The package has been developed from the Python version (https://github.com/aws/aws-step-functions-data-science-sdk-python).

I wish to render the JavaScript graphs within RStudio. I am coming across the following javascript error: sfn.min.js:60 Uncaught TypeError: Cannot read property 'getBBox' of null. However the jupyter notebook version renders successfully. (I believe it due to my lack of understanding of how the htmlwidget package works).

Jupyter Notebook rendering code example:

IRdisplay::display_html('<link rel="stylesheet" type="text/css" href="https://do0of8uwbahzz.cloudfront.net/graph.css">
  <div id="graph-966" class="workflowgraph">
    
    <svg></svg>
    
    </div>
    <script type="text/javascript">
      
      require.config({
        paths: {
          sfn: "https://do0of8uwbahzz.cloudfront.net/sfn",
        }
      });
    require([\'sfn\'], function(sfn) {
      var element = document.getElementById(\'graph-966\')
      var options = {
        width: parseFloat(getComputedStyle(element, null).width.replace("px", "")),
        height: 600,
        layout: \'LR\',
        resizeHeight: true
      };
      var definition = {"StartAt":"MyPassState","States":{"MyPassState":{"Type":"Pass","Next":"Wait for 3 seconds"},"Wait for 3 seconds":{"Seconds":3,"Type":"Wait","Next":"Convert HelloWorld to Base64"},"Convert HelloWorld to Base64":{"Parameters":{"FunctionName":"MyLambda","Payload":{"input":"HelloWorld"}},"Resource":"arn:aws:states:::lambda:invoke","Type":"Task","End":true,"Retry":[{"Error_equals":["States.TaskFailed"],"Interval_seconds":15,"Max_attempts":2,"Backoff_rate":4}],"Catch":[{"Error_equals":"States.TaskFailed","Next":"LambdaTaskFailed"}]},"LambdaTaskFailed":{"Type":"Fail"}}};
      var elementId = \'#graph-966\';
      var graph = new sfn.StateMachineGraph(definition, elementId, options);
      graph.render();
    });
    
    </script>')

Screenshot 2021-05-19 at 21 09 18pm

Htmlwidget version

R binding:

sfn_flow_graph <- function(definition, portrait = FALSE,  width = NULL, height = 600) {

  if (isFALSE(portrait))
    layout = 'LR'
  else
    layout = 'TB'

  # forward options using params
  params = list(
    definition = definition,
    layout = layout
  )
  # create widget
  htmlwidgets::createWidget(
    name = 'sfn_flow_graph',
    params,
    width = width,
    height = height,
    package = 'stepfunctions',
    elementId = sprintf('graph-%d', as.integer(stats::runif(1, 0, 999)))
  )
}

JavaScript binding:

HTMLWidgets.widget({

  name: "sfn_flow_graph",

  type: "output",

  factory: function(el, width, height) {

    return {

      renderValue: function(x) {
          // Commmented out code from jupyter notebook rendering: workflow_widgets_graph.R
          // var element = document.getElementById(el.id);
          // parseFloat(getComputedStyle(element, null).width.replace("px", ""))
          var options = {
              width: width,
              height: height,
              layout: x.layout,
              resizeHeight: true
          };
          var definition = x.definition;

          var graph = new sfn.StateMachineGraph(definition, '#'+el.id, options);
          graph.render();

      },

      resize: function(width, height) {
      }
    };
  }
});

yaml Dependencies:

dependencies:
 - name: d3
   version: 4.13.0
   src: "htmlwidgets/lib/d3"
   script: "d3.min.js"
 - name: dagre
   version: 0.6.3
   src: "htmlwidgets/lib/dagre-d3"
   script: "dagre-d3.min.js"
 - name: sfn
   version: 0.1.5
   src: "htmlwidgets/lib/sfn_graph"
   script: "sfn.min.js"
   stylesheet: "sfn.css"

Example of running code:

state_def <- "{\"StartAt\":\"MyPassState\",\"States\":{\"MyPassState\":{\"Type\":\"Pass\",\"Next\":\"Wait for 3 seconds\"},\"Wait for 3 seconds\":{\"Seconds\":3,\"Type\":\"Wait\",\"Next\":\"Convert HelloWorld to Base64\"},\"Convert HelloWorld to Base64\":{\"Parameters\":{\"FunctionName\":\"MyLambda\",\"Payload\":{\"input\":\"HelloWorld\"}},\"Resource\":\"arn:aws:states:::lambda:invoke\",\"Type\":\"Task\",\"End\":true,\"Retry\":[{\"Error_equals\":[\"States.TaskFailed\"],\"Interval_seconds\":15,\"Max_attempts\":2,\"Backoff_rate\":4}],\"Catch\":[{\"Error_equals\":\"States.TaskFailed\",\"Next\":\"LambdaTaskFailed\"}]},\"LambdaTaskFailed\":{\"Type\":\"Fail\"}}}"
state_list = jsonlite::fromJSON(state_def)

sfn_flow_graph(
  definition = jsonlite::toJSON(state_list, auto_unbox= T)
)

This returns an error:

sfn.min.js:60 Uncaught TypeError: Cannot read property 'getBBox' of null
    at width (sfn.min.js:60)
    at t.value (sfn.min.js:60)
    at Object.renderValue (sfn_flow_graph.js:24)
    at Object.renderValue (htmlwidgets.js:886)
    at htmlwidgets.js:653
    at Array.forEach (<anonymous>)
    at forEach (htmlwidgets.js:55)
    at htmlwidgets.js:576
    at Array.forEach (<anonymous>)
    at forEach (htmlwidgets.js:55)

The error seems to be coming from aws javascript dependency "sfn.min.js" however I think it is because the dependencies of "sfn.min.js" (d3, dagre-d3) not being picked up.

My code is currently on the branch "htmlwidget" of repo.
aws-step-functions-data-science-sdk-r

Any help with this would be greatly appreciated.

Many thanks,
Dyfan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant