Display who a request is waiting approval from

Gary Chan
Kilo Contributor

Hello,

In the service portal, it only shows the stage of approval for a request.  Is it possible to add the name of approver who is waiting approval from ?

find_real_file.png

Regards,

Gary Chan

 

6 REPLIES 6

SanjivMeher
Kilo Patron
Kilo Patron

Yes. You can clone this wizard and add logic to get the approver and display it in your new widget. Then replace the new widget with old widget in your page.


Please mark this response as correct or helpful if it assisted you with your question.

Is the name of widget called "Requested item" ? Do you have sample code for this logic ?

I didn't find the widget in my Personal Dev Instance. I think the one you have is already a customized one.

You can get the page name from the URL. It will be id=page_id. Take the page id and search for the page in Service Portal->Pages. 

And the open the page and on the bottom you will see the widgets you have on the form. Search for the one which you shown in the screenshot. You will have to modify that.

 

 

Or you can add you own widget and add it to your page.

The server script on your new widget will be

(function() {

var gr = $sp.getRecord();
data.sysid = gr.getValue('sys_id');

var approvers = '';
var approversEmail = '';
var appr = new GlideRecord('sysapproval_approver');
appr.addQuery('state','requested');
appr.addQuery('sysapproval',gr.getValue('sys_id'));
appr.query();

while (appr.next())
{
if (approvers=='')
{
approvers = appr.getDisplayValue('approver');
approversEmail = appr.approver.email;
}
else
{
approvers = approvers+', '+appr.getDisplayValue('approver');
approversEmail = approversEmail+';'+appr.approver.email;
}
}

if (approvers!='')
data.content = 'Your request is now pending for approval with <a href="mailto:'+approversEmail+'"target="_top">'+approvers+'</a>';

})();

 

And HTML will be

<div class="panel panel-default b">
<div class="panel-heading" >
<h4 class="panel-title">Approvals</h4>
</div>
<div ng-controller='addHTML'>
<p class = 'cont' ng-bind-html="data.content"></p>
</div>
</div>


Please mark this response as correct or helpful if it assisted you with your question.

Hi,

I found the widget and the existing server script and HTML are captured below, where should I insert your codes there ?  Thanks

 

Server script :

------------------------------------------------------------------------

(function() {
 var rec = $sp.getRecord();
  
 
 if (rec != null && rec.isValid())
  data.conversation_title = rec.getDisplayValue();
 if (!data.conversation_title)
  data.conversation_title = gs.getMessage("Request");
 
 data.title = options.title || gs.getMessage("Requested Items");
 var gr = new GlideRecord("sc_req_item"); // does ACL checking for us
 gr.addQuery("request", $sp.getParameter("sys_id"));

 options.secondary_fields = options.secondary_fields || "number";
 options.secondary_fields = options.secondary_fields.split(",");

 if (options.order_direction == "asc")
  gr.orderBy(options.order_by);
 else
  gr.orderByDesc(options.order_by);

 if (options.maximum_entries > 0)
  gr.setLimit(options.maximum_entries);
 gr.query();

 data.actions = [];
 data.list = [];
 while (gr.next()) {
  if (!gr.canRead())
   continue;
     
  if (gr.getRowCount() == 1)
   data.conversation_title = gr.request.getDisplayValue() + " - " + gr.getValue("short_description");

  var record = {};

  record.sys_id = gr.sys_id.getDisplayValue();
  if (options.image_field) {
   record.image_field = gr.getDisplayValue(options.image_field);
   if (!record.image_field)
    record.image_field = "/noimage.pngx";
  }
  if (options.display_field)
   record.display_field = gr.getDisplayValue(options.display_field);
  record.secondary_fields = [];
  options.secondary_fields.forEach(function(f) {
   var secondaryField = getField(gr, f);
   if (secondaryField != null)
    record.secondary_fields.push(secondaryField);
  });

  if (options.sp_page_dv)
   record.url = "?id="+options.sp_page_dv+"&table="+options.table+"&sys_id="+record.sys_id+"&view=sp";
  else
   record.url = "";

  record.stage = gr.getValue("stage");

  // get appropriate Stage choices for this requested item
  var cl = new GlideChoiceList();
  GlideController.putGlobal("answer", cl);
  GlideController.putGlobal("current", gr);
  sc_req_item_stageGetChoices();
  
  // de-duplicate if sequential stages are identical
  var cl2 = new GlideChoiceList();
  cl2.add(cl.getChoice(0));
  for (var i = 1; i < cl.getSize(); i++) {
   if (cl.getChoice(i).value != cl.getChoice(i-1).value)
    cl2.add(cl.getChoice(i));
  }
  record.cl = JSON.parse(cl2.toJSON());

  data.list.push(record);
 }
 
 if (gr.getRowCount() > 1)
  data.conversation_title = gr.request.getDisplayValue() + " - " + gr.getRowCount() + " items";

 function getField(gr, name) {
  var f = {};
  f.display_value = gr.getDisplayValue(name);
  f.value = gr.getValue(name);
  var ge = gr.getElement(name);
  if (ge == null)
   return null;

  f.type = ge.getED().getInternalType()
  f.label = ge.getLabel();
  return f;
 }

})();

---------------------------------------------------------------------

 

HTML :

<div class="panel panel-{{c.options.color}} b" ng-if="always_show || data.list.length">
  <div class="panel-heading">
    <h2 class="panel-title">{{::c.data.title}}</h2>
  </div>
  <div class="list-group">
    <div ng-repeat="item in data.list" class="block list-group-item" >
      <a ng-click="onClick($event, item, item.url, {})" href="javascript:void(0)" >
        <span ng-if="data.image_field" class="pull-left thumb-sm avatar m-r">
          <img ng-src="{{item.image_field}}" alt="..." class="img-circle">
        </span>
        <div >
          <div ng-class="{'l-h-40': !item.secondary_fields.length}">{{item.display_field}}</div>
          <small class="block text-muted m-b-xs" ng-repeat="f in item.secondary_fields">
            <span ng-if="!$first"> • </span>
            <span ng-switch="f.type" title="{{::f.label}}">
              <span ng-switch-when="glide_date"><sn-time-ago timestamp="::f.value" /></span>
              <span ng-switch-when="glide_date_time"><sn-time-ago timestamp="::f.value" /></span>
              <span ng-switch-default="">{{f.display_value}}</span>
            </span>
          </small>
        </div>
      </a>
      <div ng-if="item.cl.length > 0" class="requested-items-flex-container">
        <button class="flex-item" role="button" ng-click="toggle($event, item)" aria-expanded="{{item.expand}}" aria-label="${collapse state of request}">
          <img ng-if="item.expand" src="images/filter_hide16.gifx"  alt="${Expand state of request}"/>
         <img ng-if="!item.expand" src="images/filter_reveal16.gifx" alt="${Expand state of request}"/>
        </button>
        <div class="flex-item" ng-if="!item.expand">
         <span ng-repeat="stage in item.cl">
            <span ng-if="stage.value == item.stage">
              <img src="/images/sp-icon-check-circle.png" data-toggle="tooltip" data-placement="top" ng-attr-title="{{stage.label}}" />
            </span>
            <span ng-if="stage.value != item.stage">
              <img src="/images/sp-icon-empty-circle.png" data-toggle="tooltip" data-placement="top" ng-attr-title="{{stage.label}}" />
            </span>
          </span>
        </div>
        <div class="flex-item" ng-if="item.expand">
          <div ng-repeat="stage in item.cl">
            <div ng-if="stage.value == item.stage" class="stage-on">
              <img src="/images/sp-icon-check-circle.png" alt="{{stage.label}} ${checked}" role="image"/>
              <span aria-hidden="true">{{stage.label}}</span>
            </div>
            <div ng-if="stage.value != item.stage" class="stage-off text-muted">
              <img src="/images/sp-icon-empty-circle.png" alt="{{stage.label}} ${un-checked}" role="image"/>
              <span aria-hidden="true">{{stage.label}}</span>
            </div>
          </div>
    </div>
  </div>
</div>