“No matter how good you get you can always get better, and that’s the exciting part.”
— Tiger Woods
The other day I was out on the ServiceNow Developers site and noticed that this project was highlighted on the home page of the Share site as an Editor’s Choice.
This project is quite interesting to me because it is basically an alternative approach to something that I had attempted to accomplish with the My Delegates Widget a while back. I’m always curious to see how other folks address things, so I downloaded it and checked it out. As you would assume from the 5 star rating, it’s pretty nice. In fact, it has a feature that I had not even considered back when I had put mine together: in addition to being able to manage your own delegates, you can also see who has delegated authority to you. I like that. In fact, I liked it so much that I decided to see if I could add that feature to my own slant on building this widget.
The first thing I did was to dust off my old widget, bring it up, and refresh my memory as to how it was that I put it together. This one has been out there for a while, so in addition to adding this new feature, I’m also going to have to clean it up a bit. For one thing, this was built before I read in one our HealthScans that using the name gr for variables that represent a GlideRecord is considered bad form. I think I originally copied that technique from some internal ServiceNow code, so I thought it was a little disingenuous for them to be complaining about that at the time. Still, I’ve stopped doing that ever since, and I’ve been fixing it whenever I come across it in my older stuff.
All that aside, it was a pretty simple addition. I copied the block of code that generated the list of delegates (once I cleaned it up a bit) to make a second one to build a list of the delegations of others. The modification to the query was basically to switch from searching for delegates where user is the current user to searching for users where the delegate is the current user. Also, since this data is not editable (delegation is controlled by the person doing the delegating), I decided to format it as plain English rather than put it in a data table. The final product turned out like this:
function fetchList2() {
var list = [];
var today = new Date();
var delegationGR = new GlideRecord('sys_user_delegate');
delegationGR.addQuery('delegate', data.userID);
delegationGR.orderBy('user.name');
delegationGR.query();
while (delegationGR.next()) {
var stillActive = true;
var endDate = '';
if (delegationGR.getValue('ends')) {
endDate = new GlideDate();
endDate.setValue(delegationGR.getValue('ends'));
endDate = endDate.getByFormat('M/d/yyyy');
if (today.after(new Date(endDate))) {
stillActive = false;
} else {
if (new Date(endDate).getFullYear() == 2100) {
endDate = '';
}
}
}
if (stillActive) {
var thisDelegation = {};
var delegations = [];
if (delegationGR.getValue('approvals') == 1) {
delegations.push('Approvals');
}
if (delegationGR.getValue('assignments') == 1) {
delegations.push('Assignments');
}
if (delegationGR.getValue('notifications') == 1) {
delegations.push('CC on Notifications');
}
if (delegationGR.getValue('invitations') == 1) {
delegations.push('Meeting Invitations');
}
if (delegations.length > 0) {
thisDelegation.sys_id = delegationGR.getValue('sys_id');
thisDelegation.id = delegationGR.getValue('user');
thisDelegation.user = delegationGR.getDisplayValue('user');
thisDelegation.ends = endDate;
thisDelegation.delegations = '';
var separator = '';
for (var i=0; i<delegations.length; i++) {
thisDelegation.delegations += separator;
thisDelegation.delegations += delegations[i];
if (delegations.length > 2) {
separator = ', ';
if (i == (delegations.length - 2)) {
separator = ', and ';
}
} else {
separator = ' and ';
}
}
list.push(thisDelegation);
}
}
}
return list;
}
I also built this widget before I created my Dynamic Service Portal Breadcrumbs widget, so at the time I was always hesitant to leave the page without having a way back. I added that widget to the top of my test page, and then I converted all of the user names on the page to links out to the User Profile page for that person, which adds another nice little feature. The final HTML that formatted the delegations turned out like this:
<div style="width: 100%; padding: 5px 50px;" ng-show="data.list2Items.length>0">
<b>I am a Delegate for:</b>
<div ng-repeat="item in c.data.list2Items track by item.id | orderBy: 'user'" style="padding: 5px;">
<sn-avatar class="avatar-small-medium" primary="item.id" show-presence="true"/>
<a href="?id=user_profile&table=sys_user&sys_id={{item.id}}" title="{{item.user}}">{{item.user}}</a>
for {{item.delegations}}
<span ng-show="item.ends"> until {{item.ends}}</span>
</div>
All in all, putting this together was a fairly straightforward operation that added a nice new feature to the widget, and gave me a chance to do a little tidying up of some older code. Here’s what it ended up looking like in practice:
Much thanks to Fredrik Larsson for the work he did on his version of a Service Portal delegate widget, and for giving me the idea to make my own a little better. For those of you who like to play along at home, here is an Update Set with all of the latest parts and pieces.