Friday, 31 March 2017

TACTIC Javascript API Start-up

Using the TACTIC 4.6 API from javascript is very simple.  You just have to reference
a single javascript file.  You can either reference a local copy of this file:

<script src="js/tactic.js"> </script>

Or you can reference it from TACTIC server itself:

<script src="http://<server>/context/spt_js/tactic.js"> </script>

Replace <server> with your own server IP or domain name running TACTIC.  This
will import all the necessary javascript libraries and functions to interact with
the TACTIC server.

Next you will need to generate an API ticket.  This key is a long unique alpha-numeric string of characters.  This ticket is added to the API key, which has the form:

http<s>://<server>/<site>/<project>/ticket/<ticket>

So, for example, you would set up the server with the following:

<script>
tactic = TACTIC.get();
var key = http://<server>/workflow/workflow/ticket/571be6bb09142c4c6b883e0c9f310f57");
tactic.set_key(key);
</script>

If you wish to build tickets dynamically, then this can be done from a custom login
screen that captures a login and password.  For there, you would execute the following:

tactic = TACTIC.get();
tactic.set_server(server);
var ticket = tactic.get_ticket(name, password);
tactic.set_ticket(ticket);

where "server" is the IP or domain name of your TACTIC Server and name and password
are user entered fields.  Once you have a ticket, this can be used until the ticket
expires on the server.

You are all ready to access any of TACTIC API functionality.  To check if you can access the server, simple run the ping method:

alert( tactic.ping() )

If it returns "OK", you have successfully accessed the TACTIC server with proper credentials.

At this point, you have the full API at your disposal.  As an example, you could run a query for tasks completed assigned to Fred:

tasks = tactic.query("sthpw/task", {
    filter: [['status','Complete'],['assigned','fred']],
} );


If you wish to run this asynchronously, you would add an on_complete callback:

tactic.query("sthpw/task", {
    filter: [['status','Complete'],['assigned','fred']],
    on_complete: (tasks) => {
        console.log(tasks)
    }
} );


Or if you wish to use promises:

tactic.p_query("sthpw/task", {
    filter: [['status','Complete'],['assigned','fred']],
} )
.then( (tasks) => {
    console.log(tasks)
} );


Or we could use an expression to get the same result:

var expression = "@SOBJECT(sthpw/task['status','Complete']['assigned','fred'])"
tactic.p_eval(expression)
.then( (tasks) => {
    console.log(tasks)
} );



The javascript implementation is a fully featured TACTIC API.  This is useful for
many applications such as server side javascript such as NodeJS, Mobile apps that
run on javascript.  It can also be used in WordPress or Drupal applications on the
browser.


Thursday, 16 March 2017

Executing server side scripts from browser


TACTIC provides a number of mechanism to Python code on the server. We can start with a widget in the Custom Layout Editor with the HTML definition:


<div>
 <input type=”button press_me” name=”Press Me”/>
</div>


In the behaviors:


<behavior class=”press_me”>
 var script_path = “my_scripts/press_me”;
 var kwargs = {};
 var server = TacticServerStub.get();
 server.execute_python_script(path, kwargs);
</behavior>


In the Script Editor, you can create a script with the folder “my_scripts” and title “press_me”.


print “Button is pressed”


This simple example prints “Button is pressed” to the console.  Of course, this script can contain any Python code.  In this example, the script is blocking.  This is not usually desirable because blocking scripts cause the Javascript engine to wait until the full execution of the script.  Except for very fast and small scripts, this will negatively influence the user experience.  In order to run the script asynchronously, you could run the following call instead:


server.execute_python_script(path, kwargs, {
   on_complete: function() {
       spt.alert(“Script Complete”);
   }
} )


This works well for simple scripts that need to be executed on the server.  It is often desirable to use full python classes to execute scripts on the server side.  To execute a class on the server, you need to derive the class from the TACTIC Command class and override the execute function.


from pyasm.command import Command


class MyCmd(Command):
   def exectute(self):
       print “Running ....”
       print “kwargs: “, self.kwargs


      my.info = {
         test: 456
      }


Instead of “server.execute_python_script” in the behavior, you would have:


var cmd = “foo.MyCmd”
var kwargs = {
   test: 123
}
var server = TacticServerStub.get()
var ret_val = server.execute_cmd(cmd, kwargs);


The kwargs for the command will be the dictionary with key “test” and value “123”.  The returned value is a dictionary that will contain any error information as well as an “info” dictionary that will contained any returned data from the command itself.  In the example above, it would return the dictionary with the key “test” and value “456”.

This method allows you to create interface elements and then run custom scripts on the server based on interaction with those interface elements.  The HTML code is connected to the behaviors which run Javascript code.  The javascript uses the TACTIC API to execute commands directly on the TACTIC Server and provides a clear mechanism to send information to the command as well as receive information from the command.