Service Portal Menu Widget using 'spDropdownTreeTemplate' is not populating the redirect URL correct

Liam Rhodes
Kilo Guru

Hi all,

I very recently updated one of our Service Portal's menu items called "My Tickets" to include Incidents as well as Requests. Below is the updated script.

 

// maximum number of entries in this Menu
var max = 40;

var t = data;  // shortcut
t.items = [];

var u = gs.getUser().getID();

// use record watchers to tell header when to update dropdown counts
// updated by Francis C SJP to include 60 days of historic records
//updated by MH to show sc_req_item instead of sc_request
t.record_watchers = [];
t.record_watchers.push({'table':'service_task','filter':'opened_by=' + u + '^active=true^ORclosed_atRELATIVEGE@dayofweek@ago@60'});
t.record_watchers.push({'table':'incident','filter':'caller_id=' + u + '^active=true^ORresolved_atRELATIVEGE@dayofweek@ago@60'});
t.record_watchers.push({'table':'sc_req_item','filter':'request.requested_for=' + u + '^ORopened_by=' + u + '^active=true^ORclosed_atRELATIVEGE@dayofweek@ago@60'});

//queries back service task records where user is opened by and record is active - ammended to st1 instead of st by Francis C SJP
var st1 = new GlideRecord('service_task');
if (st1.isValid()) {
  //st1.addActiveQuery(); //commented out to introduce OR query by Francis C SJP to
  st1.addQuery('active',true).addOrCondition('closed_at','>=','javascript:gs.daysAgoStart(60)');  // added to introduce a grouped OR and a relative query
  st1.addQuery('opened_by', gs.getUserID());
  st1.orderByDesc('sys_updated_on');
  st1.setLimit(max);
  st1.query();
  while (st1.next()) {
    var a = {};
    $sp.getRecordValues(a, st1, 'short_description,sys_id,number,sys_updated_on,state'); // added state Francis C SJP
    if (st1.short_description.nil())
      a.short_description = "(No description)";
    a.__table = st1.getTableName();
    a.type = 'record';
    a.sortOrder = st1.sys_updated_on.getGlideObject().getNumericValue();
    t.items.push(a);
  }
}


//queries back service request records where user is requested for and record is active - ammended to z1 instead of z by Francis C SJP
var z1 = new GlideRecord('sc_req_item');
// z1.addActiveQuery(); //commented out to introduce OR query by Francis C SJP to
z1.addQuery('active',true).addOrCondition('closed_at','>=','javascript:gs.daysAgoStart(60)');  // added to introduce a grouped OR and a relative query
z1.addQuery('request.requested_for', gs.getUserID());
z1.orderByDesc('sys_updated_on');
z1.setLimit(max);
z1.query();
while (z1.next()) {
  var ritm = new GlideRecord('sc_req_item');
  ritm.addQuery('sys_id', z1.getUniqueValue());
  ritm.query();
  if (!ritm.next())
    continue;

  var a = {};
  $sp.getRecordValues(a, z1, 'sys_id,number,sys_updated_on,state'); // added state Francis C SJP
  if (ritm.hasNext())
    a.short_description = ritm.getRowCount() + ' requested items';
  else
    a.short_description = ritm.cat_item.getDisplayValue() || ritm.getDisplayValue("short_description");
  a.__table = z1.getTableName();
  a.type = 'request';
  a.sortOrder = z1.sys_updated_on.getGlideObject().getNumericValue();
  t.items.push(a);
}

var inc1 = new GlideRecord('incident');
//inc1.addActiveQuery();
inc1.addQuery('active',true)
inc1.addQuery('caller_id', gs.getUserID());
inc1.orderByDesc('sys_updated_on');
inc1.setLimit(max);
inc1.query();
while (inc1.next()){
  if (!inc1.canRead())
    continue;
  
  var a = {};
  $sp.getRecordValues(a, inc1, 'short_description,sys_id,number,sys_updated_on');
  if (inc1.short_description.nil())
    a.short_description = "(No description)";
  a._table = inc1.getTableName();
  a.type = 'record';
  a.sortOrder = inc1.sys_updated_on.getGlideObject().getNumbericValue();
  t.items.push(a);
}


t.items.sort(function(a, b) {
  return b.sortOrder - a.sortOrder;
});
t.items = t.items.slice(0, max); // only want first 20
t.count = t.items.length;

var link = {title: gs.getMessage('View all tickets'), type: 'link', href: '?id=sjp_my_tickets', items: []};
t.items.unshift(link); // put 'View all requests' first	

 

And this of course displays perfect fine on the Service Portal showing both Incidents and Requests - no problem there.

LiamRhodes_0-1668594881175.png

My problem is that although the redirect links for the RITM records work fine, those for Incidents do not. When clicking on them I instead get a "Record not found" error, and the URL is not what I want.

 

LiamRhodes_1-1668594952636.png

/sp?id=ticket&table=&sys_id=23a441611b035d1403890ed0f54bcb20

As you can see, the ticket&table part of the URL is not populating correctly.

I have narrowed it down that the issue is in the spDropdownTreeTemplate angular template and can see that when I click on the Incident's link it is triggering the below part of the template so mi.type must == 'record'. From what I can see my problem is that {{::mi.__table}} is not populating with "Incident".

<a ng-if="mi.type == 'record' && !mi.__page" aria-label="${Open} {{::mi.number}} : {{::mi.short_description}}" aria-describedby="id_{{::mi.unique_number}}" ng-href="?id=ticket&table={{::mi.__table}}&sys_id={{::mi.sys_id}}" ng-click="collapse()" role="menuitem">
  <span>{{::mi.short_description | characters:60}}</span>
  <span class="block color-primary text-muted">
    <span class="block" style="float: right" id="id_{{::mi.unique_number}}">
      <sn-time-ago timestamp="::mi.sys_updated_on" />
    </span>
    {{mi.number}}
  </span>
</a>

My question is - anyone know where the "Incident" data gets passed through for {{::mi__table}}? I could just hardcode it in as Incident but don't want it to impact other features in the future. Perhaps I could create a new mi.type for Incidents.. if so what would be the correct way to do this? Thank you in advance!

0 REPLIES 0