My Delegates Widget
I recently took on the task of fixing an open-source ServiceNow widget called "My Delegates," originally created by snhackery. This widget, designed to fetch and display data from the Delegate table, faced issues with data retrieval and image display, leading to a suboptimal user experience.
Download the widget update set (whole page) :
https://snhackery.com/2020/04/21/my-delegates-widget-enhanced/
The code was not working for everyone, and if it was working, data and images were not populating. I have seen many people concerned about this widget in the ServiceNow community so I gave it a try and completed it.
full working code here "this will add names and all also properly" and all credits and special thanks to snhackery.
HTML:-
<snh-panel title="'${My Delegates}'" class="panel panel-primary">
<!-- level 1 -->
<div style="width: 100%; padding: 5px 50px;">
<table class="table table-hover table-condensed">
<thead>
<tr>
<th style="text-align: center;">Delegate</th>
<th style="text-align: center;">Approvals</th>
<th style="text-align: center;">Assignments</th>
<th style="text-align: center;">CC on Notifications</th>
<th style="text-align: center;">Meeting Invitations</th>
<th style="text-align: center;">Start Date</th>
<th style="text-align: center;">End Date</th>
<th style="text-align: center;">Remove</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in c.data.listItems" ng-hide="item.removed">
<td data-th="Delegate">
<span class="navbar-avatar">
<sn-avatar class="avatar-small-medium" primary="item.id" show-presence="true"/>
</span>
<a href="?id=user_profile&table=sys_user&sys_id={{item.id}}" title="{{item.delegate}}">{{item.delegate}}</a>
</td>
<p>
{{item.start_date}}
</p>
<td data-th="Approvals" style="text-align: center;"><input type="checkbox" ng-model="item.approvals"/></td>
<td data-th="Assignments" style="text-align: center;"><input type="checkbox" ng-model="item.assignments"/></td>
<td data-th="CC on Notifications" style="text-align: center;"><input type="checkbox" ng-model="item.notifications"/></td>
<td data-th="Meeting Invitations" style="text-align: center;"><input type="checkbox" ng-model="item.invitations"/></td>
<td data-th="Start Date" style="text-align: center;"><sp-date-picker field="item.starts" ng-model="item.starts" sn-change="" sn-include-time="true"/></td>
<td data-th="End Date" style="text-align: center;"><sp-date-picker field="item.ends" ng-model="item.ends" sn-change="" sn-include-time="true"/></td>
<td data-th="Remove" style="text-align: center;"><img src="/images/delete_row.gif" ng-click="removePerson($index)" alt="Click here to remove this person as a delegate" title="Click here to remove this person from the list" style="cursor: pointer;"/></td>
</tr>
</tbody>
</table>
<!-- level 1 end -->
<!-- level 2 start-> gaurav kumar -->
<p>To add a delegate to the list, select a person from below:</p>
<sn-record-picker id="snrp" field="data.personToAdd" ng-change="addSelected()" table="'sys_user'" display-field="'name'" display-fields="'title,department,location,email'" value-field="'sys_id'" search-fields="'name'" page-size="20" default-query="'active=true^emailISNOTEMPTY^nameISNOTEMPTY'"></sn-record-picker>
<br/>
<p>To remove a delegate from the list, click on the Remove icon.</p>
</div>
<div style="width: 100%; padding: 5px 50px; text-align: center;">
<button ng-click="saveDelegates()" class="btn btn-primary ng-binding ng-scope" role="button" title="Click here to save your changes">Save</button>
<button ng-click="returnToProfile()" class="btn ng-binding ng-scope" role="button" title="Click here to cancel your changes">Cancel</button>
</div>
<!-- level 2 end -->
<!-- level 3 start -->
<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;">
<span class="navbar-avatar">
<sn-avatar class="avatar-small-medium" primary="item.id" show-presence="true"/>
</span>
<!-- <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>
</div>
<!-- level 3 end -->
</snh-panel>
Server script:
(function() {
data.userID = gs.getUser().getID();
data.listItems = data.listItems || fetchList();
data.list2Items = data.list2Items || fetchList2();
if (input) {
data.listItems = input.listItems || fetchList();
if (input.personToAdd && input.personToAdd.value > '') {
addPersonToList(input.personToAdd.value);
}
if (input.button == 'save') {
saveList();
}
}
function fetchList() {
var gdt = new GlideDateTime();
var list = [];
var delegateGR = new GlideRecord('sys_user_delegate');
delegateGR.addQuery('user', data.userID);
delegateGR.orderBy('delegate.name');
delegateGR.query();
while (delegateGR.next()) {
var thisDelegate = {};
thisDelegate.sys_id = delegateGR.getValue('sys_id');
thisDelegate.id = delegateGR.getValue('delegate');
thisDelegate.delegate = delegateGR.getDisplayValue('delegate');
thisDelegate.approvals = (delegateGR.getValue('approvals') == 1);
thisDelegate.assignments = (delegateGR.getValue('assignments') == 1);
thisDelegate.notifications = (delegateGR.getValue('notifications') == 1);
thisDelegate.invitations = (delegateGR.getValue('invitations') == 1);
thisDelegate.starts = delegateGR.getDisplayValue('starts');
thisDelegate.ends = delegateGR.getDisplayValue('ends');
list.push(thisDelegate);
}
return list;
}
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('dd/MM/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;
}
function saveList() {
for (var i=0; i<data.listItems.length; i++) {
var thisDelegate = data.listItems[i];
if (thisDelegate.removed) {
if (thisDelegate.sys_id != 'new') {
var gr = new GlideRecord('sys_user_delegate');
gr.get(thisDelegate.sys_id);
gr.deleteRecord();
}
} else {
var delegateGR = new GlideRecord('sys_user_delegate');
if (thisDelegate.sys_id != 'new') {
delegateGR.get(thisDelegate.sys_id);
} else {
delegateGR.initialize();
delegateGR.user = data.userID;
delegateGR.delegate = thisDelegate.id;
delegateGR.starts = thisDelegate.starts;
delegateGR.ends = thisDelegate.ends;
}
delegateGR.approvals = thisDelegate.approvals;
delegateGR.assignments = thisDelegate.assignments;
delegateGR.notifications = thisDelegate.notifications;
delegateGR.invitations = thisDelegate.invitations;
delegateGR.update();
}
}
gs.addInfoMessage('Your Delegate information has been updated.');
}
function addPersonToList(selected) {
var existing = -1;
for (var i=0; i<data.listItems.length && existing == -1; i++) {
if (data.listItems[i].id == selected) {
existing = i;
}
}
if (existing == -1) {
var thisDelegate = {};
thisDelegate.sys_id = 'new';
thisDelegate.id = selected;
var userGR = new GlideRecord('sys_user');
userGR.get(selected);
thisDelegate.delegate = userGR.getDisplayValue('name');
thisDelegate.approvals = true;
thisDelegate.assignments = true;
thisDelegate.notifications = true;
thisDelegate.invitations = true;
thisDelegate.starts = true;
thisDelegate.ends = true;
data.listItems.push(thisDelegate);
} else {
data.listItems[existing].removed = false;
}
input.personToAdd = {};
}
})();
Client controller:-
function MyDelegates($scope, $window) {
var c = this;
$scope.addSelected = function() {
$scope.server.update().then(function(response) {
$('#snrp').select2("val","");
});
};
$scope.removePerson = function(i) {
c.data.listItems[i].removed = true;
};
$scope.saveDelegates = function() {
c.data.button = 'save';
$scope.server.update().then(function(response) {
reloadPage();
});
};
$scope.returnToProfile = function() {
reloadPage();
};
function reloadPage() {
$window.location.reload();
}
}
Here is the link for my reply in ServiceNow community for some help.
0 Comments