Scripted List on SP Header Menu

ben510
Giga Contributor

I am trying to create a button on the Service Portal Header Menu that will display contract records (ast_contract) opened by the logged in user.  I am having problems filtering the records using the value form u_requested for.  I also cannot get the field value from u_vendor_name to appear in the displayed list.  I started with adding the following code to the out of the box Angular ng-template spDropdownTreeTemplate.  

<!-- Start Contracts Update -->
<a ng-if="mi.type == 'contract'" title="{{mi.short_description}}" href="?id=idea_form&table={{mi.__table}}&sys_id={{mi.sys_id}}">
  <span>{{mi.short_description | characters:60}}</span>
  <span class="block color-primary text-muted">
    <span class="block" style="float: right">
      <sn-time-ago timestamp="mi.sys_updated_on" />
    </span>
    {{mi.number}}
  </span>
</a>
<!-- End Contracts Update -->

I created a Scripted List Menu Item for Contracts with the Server Script below

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

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

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

// use record watchers to tell header when to update dropdown counts
t.record_watchers = [];
t.record_watchers.push({'table':'ast_contract','filter':'active=true^submitter=' + u});
//t.record_watchers.push({'table':'ast_contract','filter':'active=true'});



var z = new GlideRecord('ast_contract');
z.addActiveQuery();
z.addQuery('active', '=','true');
z.addQuery('submitter', gs.getUserID());
z.orderByDesc('sys_updated_on');
z.setLimit(max);
z.query();
while (z.next()) {
  var a = {};
  $sp.getRecordValues(a, z, 'u_vendor_name,sys_id,number,sys_updated_on');
  if (z.u_vendor_name.nil())
    a.u_vendor_name = "(No Vendor Name)";
  a.__table = z.getTableName();
  a.type = 'contract';
  a.sortOrder = z.sys_updated_on.getGlideObject().getNumericValue();
  t.items.push(a);
}

var z = new GlideRecord('ast_contract');
z.addActiveQuery();
z.addQuery('active', '=','true');
z.addQuery('u_contact_name', gs.getUserID());
z.addQuery('submitter','!=', gs.getUserID());
z.orderByDesc('sys_updated_on');
z.setLimit(max);
z.query();
while (z.next()) {
  var a = {};
  $sp.getRecordValues(a, z, 'u_vendor_name,sys_id,number,sys_updated_on');
  if (z.u_vendor_name.nil())
    a.u_vendor_name = "(No Vendor Name)";
  a.__table = z.getTableName();
  a.type = 'contract';
  a.sortOrder = z.sys_updated_on.getGlideObject().getNumericValue();
  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 30
t.count = t.items.length;

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

 

 

The new Contracts button should be similar to the out of the box Ideas button where the filter is applied and field values are displayed with the record.

find_real_file.png 

 

find_real_file.png

6 REPLIES 6

Prateek kumar
Mega Sage

Can we try something like this?

var max = 30;

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

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

// use record watchers to tell header when to update dropdown counts
t.record_watchers = [];
t.record_watchers.push({'table':'ast_contract','filter':'active=true^u_submitter=' + u});


var st = new GlideRecord('ast_contract');
if (st.isValid()) {
  st.addQuery('active','true');
  st.addQuery('u_submitter', gs.getUserID());
  st.addQuery('u_contact_name', gs.getUserID());
  st.orderByDesc('sys_updated_on');
  st.setLimit(max);
  st.query();
  while (st.next()) {
    var a = {};
    $sp.getRecordValues(a, st, 'u_vendor_name,sys_id,number,sys_updated_on');
    if (st.u_vendor_name.nil())
      a.u_vendor_name = "(No Vendor Name)";
    a.__table = st.getTableName();
    a.type = 'record';
    a.sortOrder = st.sys_updated_on.getGlideObject().getNumericValue();
    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 30
t.count = t.items.length;

Please mark my response as correct and helpful if it helped solved your question.
-Thanks

Hi Prateek, 

I tried you code to create my request header menu, it is working fine but the button is not visible when there is no request raised by the logged in person. I need that button should be visible even when there is no request to display. Thank you.

ben510
Giga Contributor

I tried your code.  The filters for u_submitter and u_contact_name are not working and the Vendor Name is not appearing in the list.  Thank you

find_real_file.png

Replace this part of your code:

while (z.next()) {
  var a = {};
  $sp.getRecordValues(a, z, 'u_vendor_name,sys_id,number,sys_updated_on');
  if (z.u_vendor_name.nil())
    a.u_vendor_name = "(No Vendor Name)";
  a.__table = z.getTableName();
  a.type = 'contract';
  a.sortOrder = z.sys_updated_on.getGlideObject().getNumericValue();
  t.items.push(a);
}

With the following:

while (z.next()) {
  var a = {};  
  $sp.getRecordValues(a, z, 'u_vendor_name,sys_id,number,sys_updated_on');
  a.short_description = z.u_vendor_name.getDisplayValue(); // title
  a.number = z.number.getDisplayValue(); // sub-heading - can change to whatever field you like
  a.__table = z.getTableName();
  a.type = 'contract'; // Must update Angular ng-template "spDropdownTreeTemplate" to allow for this type, but leave all other settings the same as 'record' type
  a.sortOrder = z.sys_updated_on.getGlideObject().getNumericValue();
  t.items.push(a);
}

What's great about this, is you can adopt the OOTB list view settings for a typical record and then co-op those fields with whatever fields you want.  Here's what I used for a survey item scripted list:

while (z.next()) {
  var a = {};  
  $sp.getRecordValues(a, z, 'metric_type,state,sys_id,sys_updated_on');
  a.short_description = z.metric_type.getDisplayValue(); // title
  a.number = z.state.getDisplayValue(); // sub-heading
  a.type = 'survey'; // must update Angular ng-template "spDropdownTreeTemplate" to allow for this type or else the link will not work
  a.sortOrder = new Date(z.sys_updated_on.getDisplayValue()).getTime();
  t.items.push(a);
}

As long as you copy the ng-template for a 'record' type within the "spDropdownTreeTemplate" code, you should be golden.  It doesn't seem to work if you try to update all the field options with your custom fields.  Just use short_description in place of the main title of the list item and number in place of your sub-heading info.  If you do it that way, both fields will show whatever you want them to show.  The only thing left to do is update the link portion (ng-href=) to point to the correct spot you want.  

Here's my template entry for surveys as an example:

<a ng-if="mi.type == 'survey' && !mi.__page" aria-label="${Open} {{::mi.number}} : {{::mi.short_description}}" aria-describedby="id_{{::mi.unique_number}}" ng-href="?id=take_survey&instance_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>

I copied a 'record' type and just added it to the end of the template area.  Then I only updated two things:  I changed the type to survey and updated the ng-href to the correct link path.  That was it. 

Hope this helps!