X

Best Practices from Oracle Development's A‑Team

Using Process Cloud Service REST API Part 2

John Featherly
Cloud Native Architect

Introduction

In Part 1 we looked at using the Process Cloud Service REST API and making REST calls from an HTML page using jQuery/AJAX. In Part 2 we’ll take the next step by using and presenting data retrieved from PCS. We started out stuffing the string representation of the JSON data into an HTML <div> on the page. Now let's present interesting bits of the data in a clear and appealing user interface. Building presentation structure separate from data and code is a fundamental graphical user interface application architecture. The declarative “view” in HTML, the “model” JSON data from the REST calls and the "controller" JavaScript is a classic Model-View-Controller, MVC architecture. In our case we'll be using a "view model" instead of a controller, resulting in an MVVM Model-View-ViewModel architecture. Building on the tiny bit of CSS started in Part 1, we'll use CSS to create the look and feel of the HTML view.

Organizing Source Files

Bundling CSS and JavaScript in with the HTML was convenient for our small start in Part 1 but now let's organize CSS in a separate file style.css and JavaScript in a file pcs-api.js. Let's also take advantage of a development environment. There are a number to choose from, I like NetBeans so we'll use it.

Create a new HTML5/JS Application project, name it PCSrestDemo accepting the new project wizard defaults.

NetBeams-HTML5-project

We'll be leveraging parts of the APITest1.html file from Part 1 so copy and paste from it where convenient. Edit the HTML <head> and first <div> for process definitions replacing the contents of the project auto generated index.html with the HTML shown below.

<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
        <title>PCS REST API Demo</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <h1>PCS REST API Demo</h1>
        <h2>Part 1</h2>
        <p>Use the process-definitions call to get a list of registered process names and definition IDs</p>
        <input type="button" value="Get Process List" onClick="getProcessList()">
        <br><br>
        <div id="proclist">
            <h3>Registered Processes</h3>
        </div>
        <br><br>
    </body>
</html>

We've changed the <div> id to proclist and we'll place process definition response data there on the page. Without any styling the bare HTML will look like below.
bare-htmlIn Part 1 we had a tiny bit of CSS to set the button width and h1 color.

input {width:300px;}
h1    {color: blue;}

We're not looking to win a design contest, but the CSS code below is a good start at getting control over the style elements of the application. Create a folder css and file style.css with the contents as shown. A real designer would make something a bit more elegant but we're mainly interested in the mechanics of using CSS in an application.

input {
    width: 200px;
    height: 50px;
    border-radius: 5px;
    color: DarkBlue;
    background-color: White;
    border: 3px solid DeepSkyBlue;
    cursor: pointer;
    font-size: 20px;
    font-family: Tahoma, Verdana, Arial;
    -webkit-transition: width 1s, height 1s;
    transition: width 1s, height 1s;
}
input:hover {
    width: 250px;
    height: 62px;
    background-color: DeepSkyBlue;
    box-shadow: 8px 8px 4px Grey;
}
input:active {
    box-shadow: 8px 4px 4px Grey;
    transform: translateY(4px);
}
h1, h2, h3 {
    color: DeepSkyBlue;
    text-align: Center;
    font-family: Tahoma, Verdana, Arial;
}
h2, h3 {
    text-align: Left;
}
ul {
    list-style: none;
}

also add the CSS link to the <head> section of index.html

        <link rel="stylesheet" href="css/style.css" type="text/css"/>

This will change the appearance from the bare HTML show above to that below

Create another folder named js and a file pcs-api.js with contents shown below.

 function getProcessList()
 {
   $.ajax(
       {
         type: "GET",
         url: "http://pcshost:7003/bpm/api/4.0/process-definitions",
         headers: {'Authorization': "Basic d2VibG9naWM6d2VibG9naWMx"},
         contentType: "application/json",
         dataType: "json",
         success: function(json){
                     $("#response").html(JSON.stringify(json));
         },
         failure: function(errMsg) {
              alert(errMsg);
         },
         error: function(xhr){
              alert("An error occured: " + xhr.status + " " + xhr.statusTextt);
         }
       });
 }

This is the same REST call we had in Part 1. The stringify(json) string blob was placed on the page in the #response <div> now we want to extract process names from the json object and place them in a list in the <div> we're now calling #proclist. Add the script file reference to the <head> section of index.html.

        <script src="js/pcs-api.js"></script>

vue.js

Taking the minimalist, clean, simple approach started in Part 1 we’ll use vue.js for the JavaScript framework. There are other bigger, fancier frameworks like Angular.js but vue.js is lightweight, easy to use and a good starting point. In Part 3 of this series we’ll look at heavy duty JavaScript frameworks like Angular.js, node.js and Oracle JET.

The declaration of what we want is an unordered list of process names

<ul>
   <li>process name 1</li>
   <li>process name 2</li>
   <li>etc ...</li>
</ul>

so that's what we'll put in the #proclist <div>, a <ul> containing a declared list of process name, revision and defId items

<ul>
    <li v-for="proc in procItems">
        {{ proc.processName }} version {{ proc.revision }} -- <b>defId:</b> {{ proc.processDefId }}
    </li>
</ul>

"v-for" is the vue.js for-loop binding and the double brace notation "{{ }}" is the data reference.

In pcs-api.js make the connection between the JSON response data from the REST call and the <ul> on the HTML page. Looking at the PCS REST API documentation (or the JSON response from Postman as we did in Part 1) we see the process definition information is in a JSON array with the key name "items". The vue.js vm (view-model) is created and used as shown

var appProcList = new Vue({
    el: '#proclist',
    data: {
        procItems: json.items
    }
})

The view-model is a new Vue variable named appProcList, connected to the DOM element #proclist. The data defined by an array named procItems. Replace the stringify bit in the AJAX success function with the vue.js code above. Also load vue.js from the unpkg CDN by adding the line

<script src="https://unpkg.com/vue@2.1.10/dist/vue.js"></script>

in the <head> section of index.html. The results from a PCS instance with five registered processes looks like:

Process Instance and Task List

Duplicating the approach with process definitions let's do the process instance call from Part 1 next. Add the HTML code to index.html

        <h2>Part 2</h2>
        <p>Retrieve a Process Instance</p>
        <input type="button" value="Get Process Instance" onClick="getProcessInstance()">
        <br><br>
        <div id="procinstance">
            <h3>Process Instance</h3>
            <ul>
                <li><b>Title:</b> {{ title }}</li>
                <li><b>ID:</b> {{ processId }}</li>
                <li><b>Name:</b> {{ name }}</li>
                <li><b>Owned By:</b> {{ ownedBy }}</li>
                <li><b>Priority:</b> {{ priority }}</li>
                <li><b>State:</b> {{ state }}</li>
            </ul>
        </div>
        <br><br>

We'll need a corresponding view-model, in pcs-api.js update and add the getProcessInstance() function.

function getProcessInstance()
{
  $.ajax(
      {
        type: "GET",
        url: "http://pcshost:7003/bpm/api/4.0/processes/10003",
        headers: {'Authorization': "Basic d2VibG9naWM6d2VibG9naWMx"},
        contentType: "application/json",
        dataType: "json",
        success: function(json){
            var appProcInstance = new Vue({
                el: '#procinstance',
                data: {
                    title: json.title,
                    processId: json.processId,
                    name: json.processName,
                    ownedBy: json.ownedBy,
                    priority: json.priority,
                    state: json.state
                }
            })
        },
        failure: function(errMsg) {
             alert(errMsg);
        },
        error: function(xhr){
             alert("An error occured: " + xhr.status + " " + xhr.statusTextt);
        }
      });
}

The view-model appProcInstance connects to the #procinstance <div> id and the data items are mapped individually. The result looks like

process-instance-result

Similarly for the Task List call, update and add the <div> to index.html and getTaskList() function to pcs-api.js. The <div> looks like

        <h2>Part 3</h2>
        <p>Retrieve Task List</p>
        <input type="button" value="Get Task List" onClick="getTaskList()">
        <br><br>
        <div id="tasklist">
            <h3>Task List</h3>
            <ul>
                <li v-for="task in taskItems">
                    {{ task.title }} <b>summary:</b> {{ task.shortSummary }} <b>created:</b> {{ task.createdDate }} - {{ task.state }}
                </li>
            </ul>
        </div>
        <br><br>

and the JavaScript looks like

function getTaskList()
{
  $.ajax(
      {
        type: "GET",
        url: "http://pcshost:7003/bpm/api/4.0/tasks?status=ASSIGNED&assignment=MY_AND_GROUP",
        headers: {'Authorization': "Basic d2VibG9naWM6d2VibG9naWMx"},
        contentType: "application/json",
        dataType: "json",
        success: function(json){
            var appTaskList = new Vue({
                el: '#tasklist',
                data: {
                    taskItems: json.items
                }
            })
        },
        failure: function(errMsg) {
             alert(errMsg);
        },
        error: function(xhr){
             alert("An error occured: " + xhr.status + " " + xhr.statusTextt);
        }
      });
}

the view-model appTaskList connects to the #tasklist <div> and data comes from the json.items JSON array response data. The Task List results look like

tasklist-results

Audit Diagram

Let's do something a bit flashy with the audit diagram. Retrieving binary image data with the REST call as we did in Part 1, let's open a modal overlay and show the diagram there and back on the main page after closing the modal. This approach and code is from a sample in the CSS section of w3schools (the modal sample is at the bottom of the page on images). The first thing to do is setup the CSS code. Create a file img-modal.css in the css folder of the application and insert the following

#clickMe {
    border-radius: 5px;
    cursor: pointer;
    transition: 0.3s;
}
#clickMe:hover {opacity: 0.5;}
/* The Modal (background) */
.modal {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    padding-top: 100px; /* Location of the box */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100%; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0,0,0); /* Fallback color */
    background-color: rgba(0,0,0,0.9); /* Black w/ opacity */
}
/* Modal Content (image) */
.modal-content {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
}
/* Caption of Modal Image */
#caption {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
    text-align: center;
    color: #ccc;
    padding: 10px 0;
    height: 150px;
}
/* Add Animation */
.modal-content, #caption {
    -webkit-animation-name: zoom;
    -webkit-animation-duration: 0.6s;
    animation-name: zoom;
    animation-duration: 0.6s;
}
@-webkit-keyframes zoom {
    from {-webkit-transform: scale(0)}
    to {-webkit-transform: scale(1)}
}
@keyframes zoom {
    from {transform: scale(0.1)}
    to {transform: scale(1)}
}
/* The Close Button */
.close {
    position: absolute;
    top: 15px;
    right: 35px;
    color: #f1f1f1;
    font-size: 40px;
    font-weight: bold;
    transition: 0.3s;
}
.close:hover,
.close:focus {
    color: #bbb;
    text-decoration: none;
    cursor: pointer;
}
/* 100% Image Width on Smaller Screens */
@media only screen and (max-width: 700px){
    .modal-content {
        width: 100%;
    }
}

also add the CSS link in the <head> section of index.html

        <link rel="stylesheet" href="css/img-modal.css" type="text/css"/>

Add the audit diagram section to index.html.

        <h2>Part 4</h2>
        <p>Retrieve Audit Diagram</p>
        <h3>Audit Diagram</h3>
        <img id="clickMe" src="images/GoGetIt.png" alt="Audit Diagram for Process" onClick="getAndShowAudit()" width="300" height="200">
        <!-- Audit Diagram Modal -->
        <div id="auditModal" class="modal">
            <span class="close">×</span>
            <img class="modal-content" id="imgFromPCS">
            <div id="caption"></div>
        </div>

The clickMe image file GoGetIt.png has been added to a folder images in the project. You can create your own .png or download the completed NetBeans project attached to this blog. The getAndShowAudit() function needs to be added to pcs-api.js

function getAndShowAudit()
{
    var modal = document.getElementById('auditModal');
    var clickMeImg = document.getElementById('clickMe');
    var modalImg = document.getElementById('imgFromPCS');
    var auditCaption = document.getElementById('caption');
    var oReq = new XMLHttpRequest();
    oReq.open("GET", "http://pcshost:7003/bpm/api/4.0/processes/10003/audit", true);
    oReq.responseType = "blob";
    oReq.setRequestHeader("Authorization", "Basic d2VibG9naWM6d2VibG9naWMx");
    oReq.onreadystatechange = function () {
                                if (oReq.readyState == oReq.DONE) {
                                  modalImg.src = window.URL.createObjectURL(oReq.response);
                                  clickMeImg.src = window.URL.createObjectURL(oReq.response);
                                }
                              }
    oReq.send();
    modal.style.display = "block";
    auditCaption.innerHTML = clickMeImg.alt + " 10003";
    var span = document.getElementsByClassName("close")[0];
    span.onclick = function() { modal.style.display = "none"; }
}

The REST call is the same as we had in Part 1, code to open and close the modal has been added. The section of the page before retrieving the audit diagram

audit-diagram-go

the diagram is displayed in an overlay

audit-diagram-modal

Use the x in the upper right to close the overlay. The retrieved diagram also replaces the clickMe image.

Summary

A modern HTML/CSS application using the Process Cloud Service REST API is a convenient and straight forward approach to developing a custom user interface for PCS based workflow applications.In Part 3 we'll take a look at components in vue.js and other JavaScript frameworks like Oracle JET and Angular.js.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha

Recent Content