Badge count my incidents, RITMS and approvals

RforNewbie
Tera Guru

Hello everyone,

In the Service Portal I have 3 widgets "Data table from instance definition" one for RITMS, one for Incidents and one for REQS (example below).

 

RforNewbie_1-1686309915485.png

And I want the badge count of the incidents, RITMs and REQs to appear on the menu label (My actions), is there any way to make this happen?

RforNewbie_2-1686310325377.png

 

Thanks a lot!

 

 

 

1 ACCEPTED SOLUTION

RforNewbie
Tera Guru

Hello everyone,

I finally got it, thanks to all who helped.
My solution was as follows:

 

// only show 30 in header menu dropdown
var max = 30;

var t = data;
t.items = [];
t.count = 0;

var u = gs.getUserID();

// Retrieve incidents assigned to the current user
var incidentGr = new GlideRecord('incident');
incidentGr.addQuery('assigned_to', u);
incidentGr.addQuery('active', true);
incidentGr.orderByDesc('sys_updated_on');
incidentGr.setLimit(max);
incidentGr.query();

var incidentLink = {};
incidentLink.title = gs.getMessage('View all actions');
incidentLink.type = 'link';
incidentLink.href = '?id=view_all_actions';
incidentLink.items = [];
t.items.push(incidentLink);

while (incidentGr.next()) {
  var incident = {};
  incident.short_description = incidentGr.short_description + "";
  $sp.getRecordValues(incident, incidentGr, 'sys_id,sys_updated_on');
  incident.number = incidentGr.number;
  incident.__table = incidentGr.getRecordClassName();
  incident.type = 'incident';
  t.items.push(incident);
  t.count++;
}

// Retrieve sc_req_item records assigned to the current user
var scReqItemGr = new GlideRecord('sc_req_item');
scReqItemGr.addQuery('assigned_to', u);
scReqItemGr.addQuery('active', true);
scReqItemGr.orderByDesc('sys_updated_on');
scReqItemGr.setLimit(max - t.count); // Adjust the limit based on the count of incidents
scReqItemGr.query();


while (scReqItemGr.next()) {
  var scReqItem = {};
  scReqItem.short_description = scReqItemGr.short_description + "";
  $sp.getRecordValues(scReqItem, scReqItemGr, 'sys_id,sys_updated_on');
  scReqItem.number = scReqItemGr.number;
  scReqItem.__table = scReqItemGr.getRecordClassName();
  scReqItem.type = 'sc_req_item';
  t.items.push(scReqItem);
  t.count++;
}

// Retrieve sc_request records assigned to the current user
var scRequestGr = new GlideRecord('sc_request');
scRequestGr.addQuery('assigned_to', u);
scRequestGr.addQuery('active', true);
scRequestGr.orderByDesc('sys_updated_on');
scRequestGr.setLimit(max - t.count); // Adjust the limit based on the count of incidents and sc_req_items
scRequestGr.query();


while (scRequestGr.next()) {
  var scRequest = {};
  scRequest.short_description = scRequestGr.short_description + "";
  $sp.getRecordValues(scRequest, scRequestGr, 'sys_id,sys_updated_on');
  scRequest.number = scRequestGr.number;
  scRequest.__table = scRequestGr.getRecordClassName();
  scRequest.type = 'sc_request';
  t.items.push(scRequest);
  t.count++;
}

// Calculate badge count
var incidentCount = t.items.filter(function(item) {
  return item.type === 'incident';
}).length;

var scReqItemCount = t.items.filter(function(item) {
  return item.type === 'sc_req_item';
}).length;

var scRequestCount = t.items.filter(function(item) {
  return item.type === 'sc_request';
}).length;

if (t.count === 1) {
  data.badgeHint = gs.getMessage(
    '{0} open incident, {1} requested item, {2} requested',
    [incidentCount, scReqItemCount, scRequestCount]
  );
} else if (t.count > 1) {
  data.badgeHint = gs.getMessage(
    '{0} open incidents, {1} requested items, {2} requested',
    [t.count, incidentCount, scReqItemCount, scRequestCount]
  );
} else {
  data.badgeHint = gs.getMessage('No open incidents, requested items, or requests');
}

Best regards,

View solution in original post

4 REPLIES 4

ChrisBurks
Mega Sage

You haven't removed/deleted the out-of-box Menu Item "Approvals" for the SP Service Portal, take a look at that. It should give you an idea on how to do it.
approvals_badge.png

ChrisBurks
Mega Sage

In case you wanted a more in depth explanation the following will be two ways to set this up.

The menu item is a "Scripted List" type for both ways. The explanation of what is going on is in the code comments

First way:

Display links that go to the page. The links will have a title plus the count of how many records

  • In the server script field

 

//Since this is server side it uses "data" object in Widget. Here d is equivalent to the widget server data object
var d = data;

//Adds items as a property that is an array
d.items = [];

//This count is what is going to be placed in the badge
d.count = 0;

// use record watchers to tell header when to update dropdown counts. This will update the badge
// when a listed table is updated matching the filter
d.record_watchers = [];


//Since your widgets have data tables looking at incidents, RITMS, and requests, those are the table to be watched
 Array.prototype.push.apply(d.record_watchers,[
  {'table':'incident','filter':'active=true^caller_idDYNAMIC90d1921e5f510100a9ad2572f2b477fe'},
  {'table':'sc_req_item','filter':'request.requested_forDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true'},
  {'table':'sc_request','filter':'requested_forDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true'}
  ]);

//Depending upon what you want listed in your drop down those objects would be pushed into the t.items array.
//For simplicity we'll just make it point to the list of different pages depending upon the record type

/*** basic model based on the Out-of-box setup
***  {
***   	 title: "",
***   	 type: "",
***   	 href: "",
***   	 items: [] (if it's has subdropdown
***  }
***/

//Incidents link
var inc = {};
inc.title = "My Incidents";
inc.type = "link";
inc.href = "?inc_data";
inc.target = "_blank";
inc.items = [];

//ritm link
var ritm = {};
ritm.title = "My RITMS";
ritm.type = "link";
ritm.href = "?ritm_data";
ritm.items = [];

//reqs link
var reqs = {};
reqs.title = "My Requests";
reqs.type = "link";
reqs.href = "?req_data";
reqs.items = [];
//Push each link into the items. These are the links that will display
Array.prototype.push.apply(d.items, [inc, ritm, reqs]);
 
 d.count = d.record_watchers.reduce(getCounts, 0);

//callback function for the reduce. This will add all the records together to get the total count
function getCounts(acc, item){
  var rec = new GlideAggregate(item.table);
  rec.addEncodedQuery(item.filter);
  rec.addAggregate('COUNT');
  rec.query();
 
  if(rec.next()){
  	var count = rec.getAggregate('COUNT');
  	if(item.table == "incident")
    	inc.title += " ( " + count + " )";
 	 
  	if(item.table == "sc_req_item")
    	ritm.title += " ( " + count + " )";
   
  	if(item.table == "sc_request")
    	reqs.title += " ( " + count + " )";

  	acc += Number(count);
  }
	return acc;
}
​

 

  • Example:
    example1.png

Second Way: Very similar but this time display the types and list the records under

  • Server Script

 

//Since this is server side it uses "data" object in Widget. Here d is equivalent to the widget server data object
var d = data;

//Adds items as a property that is an array
d.items = [];

//This count is what is going to be placed in the badge
d.count = 0;

// use record watchers to tell header when to update dropdown counts. This will update the badge
// when a listed table is updated matching the filter
d.record_watchers = [];


//Since your widgets have data tables looking at incidents, RITMS, and requests, those are the table to be watched
 Array.prototype.push.apply(d.record_watchers,[ 
  {'table':'incident','filter':'active=true^caller_idDYNAMIC90d1921e5f510100a9ad2572f2b477fe'},
  {'table':'sc_req_item','filter':'request.requested_forDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true'},
  {'table':'sc_request','filter':'requested_forDYNAMIC90d1921e5f510100a9ad2572f2b477fe^active=true'}
  ]);

//Depending upon what you want listed in your drop down those objects would be pushed into the t.items array. 
//For simplicity we'll just make it point to the list of different pages depending upon the record type

/*** basic model based on the Out-of-box setup
***  {
***		title: "",
***		type: "",
***		href: "",
***		items: [] (if it's has subdropdown
***  }
***/

//Incidents link
var inc = {};
inc.title = "My Incidents";
//set type to menu so that it acts like a label instead of a clickable link
inc.type = "menu";
inc.href = "?inc_data";
inc.target = "_blank";
inc.items = [];
d.items.push(inc);
//pushes records to display as links and to make the "menu" for incs render
getRecords(d.record_watchers[0].table, d.record_watchers[0].filter);

//ritm link
var ritm = {};
ritm.title = "My RITMS";
//set type to menu so that it acts like a label instead of a clickable link
ritm.type = "menu";
ritm.href = "?ritm_data";
ritm.items = [];
d.items.push(ritm);
//pushes records to display as links and to make the "menu" for ritms render
getRecords(d.record_watchers[1].table, d.record_watchers[1].filter);
//reqs link
var reqs = {};
reqs.title = "My Requests";
//set type to menu so that it acts like a label instead of a clickable link
reqs.type = "menu";
reqs.href = "?req_data";
reqs.items = [];
d.items.push(reqs);
//pushes records to display as links and to make the "menu" for reqs render
getRecords(d.record_watchers[2].table, d.record_watchers[2].filter);


function getRecords (table, filter){
    var rec = new GlideRecord(table);
    rec.addEncodedQuery(filter);
    rec.query();
    var recList = [];
    while(rec.next()){
    	var obj = {};
        $sp.getRecordValues(obj, rec, 'sys_id,sys_updated_on');
      obj.number = "  " + rec.number.toString();
        obj.__table = rec.getRecordClassName();
        obj.type = "record";
        obj.__page = table == "sc_request" ? "order_status": "ticket";
      
      if(table == "incident")
        inc.items.push(obj);
      
      if(table == "sc_req_item")
        ritm.items.push(obj);
      
      if(table == "sc_request")
        reqs.items.push(obj);
      
      d.items.push(obj);
      d.count++;
    }
    return recList;
}
​

 

  • Example:
    example2.png

I'm sure there is a more elegant way of doing this but this was just an example to describe how it works.

I hope this helps.

jaheerhattiwale
Mega Sage
Mega Sage

@RforNewbie Open your portal record and open main menu

 

jaheerhattiwale_0-1686637051783.png

 

Update the menu you have added to "Filtered List" or "Scripted List" type. In below image i have added a filtered list.

jaheerhattiwale_1-1686637121455.png

 

jaheerhattiwale_2-1686637139327.png

 

 

Please mark as correct answer if this solves your issue.

Please mark the answer as correct or helpful based on impact
ServiceNow Community Rising Star, Class of 2023

RforNewbie
Tera Guru

Hello everyone,

I finally got it, thanks to all who helped.
My solution was as follows:

 

// only show 30 in header menu dropdown
var max = 30;

var t = data;
t.items = [];
t.count = 0;

var u = gs.getUserID();

// Retrieve incidents assigned to the current user
var incidentGr = new GlideRecord('incident');
incidentGr.addQuery('assigned_to', u);
incidentGr.addQuery('active', true);
incidentGr.orderByDesc('sys_updated_on');
incidentGr.setLimit(max);
incidentGr.query();

var incidentLink = {};
incidentLink.title = gs.getMessage('View all actions');
incidentLink.type = 'link';
incidentLink.href = '?id=view_all_actions';
incidentLink.items = [];
t.items.push(incidentLink);

while (incidentGr.next()) {
  var incident = {};
  incident.short_description = incidentGr.short_description + "";
  $sp.getRecordValues(incident, incidentGr, 'sys_id,sys_updated_on');
  incident.number = incidentGr.number;
  incident.__table = incidentGr.getRecordClassName();
  incident.type = 'incident';
  t.items.push(incident);
  t.count++;
}

// Retrieve sc_req_item records assigned to the current user
var scReqItemGr = new GlideRecord('sc_req_item');
scReqItemGr.addQuery('assigned_to', u);
scReqItemGr.addQuery('active', true);
scReqItemGr.orderByDesc('sys_updated_on');
scReqItemGr.setLimit(max - t.count); // Adjust the limit based on the count of incidents
scReqItemGr.query();


while (scReqItemGr.next()) {
  var scReqItem = {};
  scReqItem.short_description = scReqItemGr.short_description + "";
  $sp.getRecordValues(scReqItem, scReqItemGr, 'sys_id,sys_updated_on');
  scReqItem.number = scReqItemGr.number;
  scReqItem.__table = scReqItemGr.getRecordClassName();
  scReqItem.type = 'sc_req_item';
  t.items.push(scReqItem);
  t.count++;
}

// Retrieve sc_request records assigned to the current user
var scRequestGr = new GlideRecord('sc_request');
scRequestGr.addQuery('assigned_to', u);
scRequestGr.addQuery('active', true);
scRequestGr.orderByDesc('sys_updated_on');
scRequestGr.setLimit(max - t.count); // Adjust the limit based on the count of incidents and sc_req_items
scRequestGr.query();


while (scRequestGr.next()) {
  var scRequest = {};
  scRequest.short_description = scRequestGr.short_description + "";
  $sp.getRecordValues(scRequest, scRequestGr, 'sys_id,sys_updated_on');
  scRequest.number = scRequestGr.number;
  scRequest.__table = scRequestGr.getRecordClassName();
  scRequest.type = 'sc_request';
  t.items.push(scRequest);
  t.count++;
}

// Calculate badge count
var incidentCount = t.items.filter(function(item) {
  return item.type === 'incident';
}).length;

var scReqItemCount = t.items.filter(function(item) {
  return item.type === 'sc_req_item';
}).length;

var scRequestCount = t.items.filter(function(item) {
  return item.type === 'sc_request';
}).length;

if (t.count === 1) {
  data.badgeHint = gs.getMessage(
    '{0} open incident, {1} requested item, {2} requested',
    [incidentCount, scReqItemCount, scRequestCount]
  );
} else if (t.count > 1) {
  data.badgeHint = gs.getMessage(
    '{0} open incidents, {1} requested items, {2} requested',
    [t.count, incidentCount, scReqItemCount, scRequestCount]
  );
} else {
  data.badgeHint = gs.getMessage('No open incidents, requested items, or requests');
}

Best regards,