TACTIC Open Source
JSX process in Custom Widget - Printable Version

+- TACTIC Open Source (http://forum.southpawtech.com)
+-- Forum: TACTIC Open Source (http://forum.southpawtech.com/forumdisplay.php?fid=3)
+--- Forum: TACTIC Discussion (http://forum.southpawtech.com/forumdisplay.php?fid=4)
+--- Thread: JSX process in Custom Widget (/showthread.php?tid=219)

Pages: 1 2


JSX process in Custom Widget - remkonoteboom - 06-18-2021

I just commit an experimental feature which takes the javascript in a custom widget and process it as JSX.  

https://github.com/Southpaw-TACTIC/TACTIC/commit/9c3951dcceb77cca1dc5e702935b4920deb4ab7a

What I am trying to do is have the ability to use React within a TACTIC widget so it is easier and more familiar to build better interfaces.  While you could build a standalone React App and interact with TACTIC through the API (which is perfectly valid way to deploy), this will allow you to integrate React behavior inside TACTIC widgets in a single deployment.  This means that you can put in a component such as this:


Code:
class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = { liked: false };
  }
 
  button_press = () => {
      this.setState( {liked: true} )
  }
 
 
  render() {
    if (this.state.liked) {
      return 'You liked this.';
    }
    return (
      <div class="display: flex">
        <div class="button" onClick={ () => {this.button_press() } }
            className="btn btn-primary">Like</div>
      </div>
    );
  }
}
ReactDOM.render(React.createElement(LikeButton), bvr.src_el);




I won't get into too much detail in this post.  Suffice to say that this seems to work.  I will try building some real widgets with this and see if having hybrid TACTIC React widgets work well.


RE: JSX process in Custom Widget - listy - 06-25-2021

Awesome!


RE: JSX process in Custom Widget - listy - 08-18-2021

Hi, Remoko!
I would really like to ask when we could test this functionality?
Does it have any progress, or something (except time of course) stops from begin testing?

Thanks!


RE: JSX process in Custom Widget - remkonoteboom - 08-18-2021

I have been trying this out over the last couple of weeks.  It does work pretty well to build widgets using JSX.

The caveat is that in order to build a JSX widget, you need a JSX processor.  At the moment, the location of this processor is hard coded in TACTIC.
The class that executes the JSX processor is in src/tactic/ui/tools/jsx_processor.py.  Currently, it is hard coded to use the npm installation of babel in a specific folder because that happens to be where I installed it.  It should be more flexible, I know.  I don't know if there are any other JSX processors around.

However, this JSX processor is only required for developing a JSX widget, not actually using it.  TACTIC will just use the transpiled pure javascript code.

I have made this work natively in the custom layout editor, so if you put this in to the html

Code:
<div class="spt_react_top card"></div>


And then in the behavior section, you put in a "load" behavior on the at element:


Code:
'use strict';

const e = React.createElement;

class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = { liked: false };
  }
 
  button_press = () => {
      this.setState( {liked: true} )
  }


  render() {
    if (this.state.liked) {
      return 'You liked this.';
    }

    return e( 'div', {},
      e( 'button',
        { onClick: () => { this.button_press() },
          className: "btn btn-primary" 
        },
        'Like'
      )
    );
  }
}

ReactDOM.render(e(LikeButton), bvr.src_el);


If you have the process set up, this should work.


RE: JSX process in Custom Widget - listy - 08-19-2021

(08-18-2021, 06:34 PM)remkonoteboom Wrote: Currently, it is hard coded to use the npm installation of babel in a specific folder because that happens to be where I installed it.  It should be more flexible, I know.  I don't know if there are any other JSX processors around.
Where i can get npm and babel?

To place it here:
/home/tactic/npm/babel


I installed npm and babel for ubuntu, and changed the hardcoded path to:
dirname = "/usr/share/npm/babel"

But your example is still not showing anything.

This warning i get when try to execute your example

WARNING: b"You have mistakenly installed the `babel` package, which is a no-op in Babel 6.
Babel's CLI commands have been moved from the `babel` package to the `babel-cli` package.

npm uninstall -g babel
npm install --save-dev babel-cli

See http://babeljs.io/docs/usage/cli/ for setup instructions."


RE: JSX process in Custom Widget - remkonoteboom - 08-19-2021

That is the document that followed, so, yes, maybe it was the babel-cli that I sued.

Here is my package.json


Code:
{
  "name": "babel",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.14.5",
    "@babel/core": "^7.14.6"
  },
  "dependencies": {
    "@babel/preset-env": "^7.14.5",
    "@babel/preset-react": "^7.14.5"
  },
  "browserslist": "> 25%, not dead"
}



RE: JSX process in Custom Widget - listy - 08-19-2021

This is what i am get tryin to execute your example:

Code:
WARNING:
'SyntaxError: temp: Unexpected token (12:15)
  10 |   }
  11 | 
> 12 |   button_press = () => {
     |                ^
  13 |       this.setState( {liked: true} )
  14 |   }
  15 |'')



RE: JSX process in Custom Widget - remkonoteboom - 08-19-2021

I just looked at the program I listed above and it doesn't use JSX at all.  I copied the output which is pure javascript and not dependent on any JSX processor.  I am not sure why that javascript wouldn't run unless the React.js files didn't load.

This is the javascript using JSX


Code:
class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = { liked: false };
  }
 
  button_press = () => {
      this.setState( {liked: true} )
  }

 
  render() {
    if (this.state.liked) {
      return 'You liked this.';
    }
    return (
        <div class="button" onClick={ () => {this.button_press() } }
            className="btn btn-primary">Like</div>
    );
  }
}
ReactDOM.render(React.createElement(LikeButton), bvr.src_el);



RE: JSX process in Custom Widget - listy - 08-19-2021

I don't know, may be my setup of npm and babel is wrong, but i can't get this to work, same errors
even with simple examples from react JS


RE: JSX process in Custom Widget - remkonoteboom - 08-20-2021

Here is my full widget_config entry. Note that the view name is test/react/example01


Code:
<config>
<test.react.example01>
<mako>
<![CDATA[
from pyasm.search import Search

from pyasm.security import Site
from pyasm.biz import Project


search = Search("workflow/asset")
assets = search.get_sobjects()

assets_dict = []
for asset in assets:
    asset_dict = asset.get_sobject_dict();
    assets_dict.append(asset_dict)
   
kwargs['assets'] = assets_dict
]]>
</mako>
<html>
<div class="react_container" style="margin: 20px"/>
</html>
<jsx class="react_container" event="load"><![CDATA[




class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = { liked: false };
  }
 
  button_press = () => {
      this.setState( {liked: true} )
  }

 
  render() {
    if (this.state.liked) {
      return 'You liked this.';
    }
    return (
        <div class="button" onClick={ () => {this.button_press() } }
            className="btn btn-primary">Like</div>
    );
  }
}
ReactDOM.render(React.createElement(LikeButton), bvr.src_el);


]]></jsx>
<behavior class="react_container" event="load"><![CDATA[
"use strict";

class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      liked: false
    };
  }

  button_press = () => {
    this.setState({
      liked: true
    });
  };

  render() {
    if (this.state.liked) {
      return 'You liked this.';
    }

    return React.createElement("div", {
      class: "button",
      onClick: () => {
        this.button_press();
      },
      className: "btn btn-primary"
    }, "Like");
  }

}

ReactDOM.render(React.createElement(LikeButton), bvr.src_el);
]]></behavior>
</test.react.example01>
</config>