Welcome to Community Week 2025! Join us to learn, connect, and be recognized as we celebrate the spirit of Community and the power of AI. Get the details  

Process Flow widget Service portal

xif1
Mega Expert

Hello Snow community,

In order to confirm what I noticed,

Do we have a process flow widget ?

I want to display it on this page :

form.png

6 REPLIES 6

robhaas
Tera Contributor

Were you ever able to get this working?


justinruddell
Giga Contributor

Something like this?


process flow example.JPG


I ended up cloning the Ticket Conversations widget and adding our own data from the sys_process_flow table to be displayed within the same panel as the existing ticket details.   It doesn't look too great on the smaller devices so I only make visible for medium to large devices.


Bravo!



Will you consider sharing your Process Flow widget code? That would help some until ServiceNow officially add the feature in a future major release.


This will act as a stand alone widget as long as the page it's on is receiving a ticket reference: nothing fancy but it does the job.  


Feel free to modify as you wish.



Cheers,


Justin



Ticket Process Flow: Widget Details



HTML
CSSServer script

<div>


  <div class="visible-md visible-lg" ng-if="data.flow.length > 0">


      <button ng-repeat="key in data.flow" type="button" class="btn btn-{{key.colour}} btn-arrow-right">{{key.name}}</button>


  </div>


</div>


.btn {


      margin-bottom: 5px;


}


.btn-arrow-right,


.btn-arrow-left {


      position: relative;


      padding-left: 18px;


      padding-right: 18px;


}


.btn-arrow-right {


      padding-left: 36px;


}


.btn-arrow-left {


      padding-right: 36px;


}


.btn-arrow-right:before,


.btn-arrow-right:after,


.btn-arrow-left:before,


.btn-arrow-left:after { /* make two squares (before and after), looking similar to the button */


      content:"";


      position: absolute;


      top: 5px; /* move it down because of rounded corners */


      width: 22px; /* same as height */


      height: 22px; /* button_outer_height / sqrt(2) */


      background: inherit; /* use parent background */


      border: inherit; /* use parent border */


      border-left-color: transparent; /* hide left border */


      border-bottom-color: transparent; /* hide bottom border */


      border-radius: 0px 4px 0px 0px; /* round arrow corner, the shorthand property doesn't accept "inherit" so it is set to 4px */


      -webkit-border-radius: 0px 4px 0px 0px;


      -moz-border-radius: 0px 4px 0px 0px;


}


.btn-arrow-right:before,


.btn-arrow-right:after {


      transform: rotate(45deg); /* rotate right arrow squares 45 deg to point right */


      -webkit-transform: rotate(45deg);


      -moz-transform: rotate(45deg);


      -o-transform: rotate(45deg);


      -ms-transform: rotate(45deg);


}


.btn-arrow-left:before,


.btn-arrow-left:after {


      transform: rotate(225deg); /* rotate left arrow squares 225 deg to point left */


      -webkit-transform: rotate(225deg);


      -moz-transform: rotate(225deg);


      -o-transform: rotate(225deg);


      -ms-transform: rotate(225deg);


}


.btn-arrow-right:before,


.btn-arrow-left:before { /* align the "before" square to the left */


      left: -11px;


}


.btn-arrow-right:after,


.btn-arrow-left:after { /* align the "after" square to the right */


      right: -11px;


}


.btn-arrow-right:after,


.btn-arrow-left:before { /* bring arrow pointers to front */


      z-index: 1;


}


.btn-arrow-right:before,


.btn-arrow-left:after { /* hide arrow tails background */


      background-color: white;


}


(function() {


  var gr = $sp.getRecord();


  data.canRead = gr.canRead();


  if (!data.canRead)


  return;




  // Check the process flow query against the current job to see if the conditions match


  function getCurrentStep(step, table, id) {


  var gnr = new GlideRecord(table);


  gnr.addEncodedQuery(step);


  gnr.addQuery('sys_id', id);


  gnr.query();




  if (gnr.next()) {


  return 'warning';


  } else {


  return 'primary';


  }


  }



  // Set the previous steps in the flow to success if the current step is further down the order


  function retoActiveSuccess(items) {


  var i = 0;


  for (var key in items) {


  var value = items[key];


  if (value.colour == 'warning') {


  var index = i;


  for (var j = 0; j<i; j++) {


  items[j].colour = 'success';


  }


  if (index == items.length) {


  value.colour = 'sucess';


  }


  break;


  }


  i++;


  }


  return items;


  }




  function createProcessFlow() {


  var table = gr.getTableName();


  var id = gr.getUniqueValue();




  var gf = new GlideRecord('sys_process_flow');


  gf.addActiveQuery();


  gf.addQuery('table', table);


  gf.orderBy('order');


  gf.query();




  var items = [];


  while (gf.next()) {


  var item = {};


  item.name = gf.name.toString();


  item.colour = getCurrentStep(gf.condition.toString(), table, id);


  items.push(item);


  }




  items = retoActiveSuccess(items);


  return items;


  }




  data.flow = createProcessFlow();




})();