Hi Developers,
In the last article, we have seen, how to make use of the out of the box related links on task records to make a conference call or send a message. In this article we will be creating a custom icon using UI Macro on incident form that will allow an Resolver to directly make a conference call with the Incident Caller. Seems interesting? it is!
UI macros are discrete scripted components administrators can add to the user interface. Wonder what does it mean? You might have seen little action icons next to fields on forms, for example :
This little user (Add me) icon next to the 'Assigned to' field, when clicked, adds currently logged in user to the Assigned to field.
You can visit SNGuru or check out TechNow Episode 3 video on ServiceNow Jelly Scripting by none other than
UI macros are typically controls that provide inputs or information not provided by existing field types. Let us understand this by means of an example :
The Show Related Incidents icon is a reference icon that appears beside the Caller field on the default incident form, when the field is populated. When clicked, it opens a browser window displaying a list of other incidents for same caller.
Now if you have got an idea about what UI Macros are and what it does, let us proceed with the development of our business requirement. Here, we will be making use of some Jelly, do not worry if you are not familiar with Jelly yet.
Step 1) Navigate to System UI > UI Macros and click 'New'
Step 2) Give it a unique name
Step 3) Replace the existing code of XML field by the following snippet :
<?xml version="1.0" encoding="utf-8" ?> <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null"> <style> .hide_icon { visibility: hidden; } .show_icon { visibility: visible; } </style> <g2:evaluate var="jvar_show_hide_icon" object="true" jelly="true"> var r=new myNotifyHandler().macroVisibility(); r; </g2:evaluate> <j:set var="jvar_n" value="Make a Call ${ref}" /> <a id="${jvar_n}" onclick="makeCall('${ref}')" class="$[jvar_show_hide_icon]"> <span class="glyphicon glyphicon-headphones" style="font-size:25px;color:black;text-shadow:2px 2px 4px #000000;"></span> </a> <script> function makeCall(reference){ var a=reference.split('.'); var referenceField=a[1]; var c=g_form.getValue(referenceField); var createRes = new GlideAjax('myNotifyHandler'); createRes.addParam('sysparm_name', 'callCaller'); createRes.addParam('sysparm_c', c); createRes.getXML(); } </script> </j:jelly>
Now let us understand the above code.
<j:set var="jvar_n" value="Make a Call ${ref}" />
In the above code Jelly tag 'set' sets a variable 'jvar_n' to the value returned from value attribute. in this particular case it will be 'Make a Call ${ref}' where '${ref}' will be replaced by the referenced field as 'incident.caller_id' and the final value will become 'Make a Call incident.caller_id'.
<a id="${jvar_n}" onclick="makeCall('${ref}')" class="$[jvar_show_hide_icon]"> <span class="glyphicon glyphicon-headphones" style="font-size:25px;color:black;text-shadow:2px 2px 4px #000000;"></span> </a>
In the above code 'a' tag will create a link to our bootstrap icon specified in 'span' tag. The onclick attribute onclick="makeCall('${ref}')" fires on a mouse click on the element and Execute a JavaScript code written in 'makeCall' function when an icon is clicked.
<g2:evaluate var="jvar_show_hide_icon" object="true" jelly="true"> var r=new myNotifyHandler().macroVisibility(); r; </g2:evaluate>
The evaluate tag evaluates JavaScript code (server side), and makes variables visible to future code. Unlike other tags, the evaluate tag evaluates the content that is inside the tag as server side JavaScript. In the above code we will be calling a script include named 'myNotifyHandler' and it's function 'macroVisibility' to check whether macro should be visible to the currently logged in user or not. We will see how to write this Script Include in later steps. This function will return a class value to be set in our anchor tag later.
<style> .hide_icon { visibility: hidden; } .show_icon { visibility: visible; } </style>
The 'style' tag specifies styles to be applied to an element for a specified class. In our case. it will hide the icon if class is be hide_icon or will display the icon if it is show_icon.
<script> function makeCall(reference){ var a=reference.split('.'); var referenceField=a[1]; var c=g_form.getValue(referenceField); var createRes = new GlideAjax('myNotifyHandler'); createRes.addParam('sysparm_name', 'callCaller'); createRes.addParam('sysparm_c', c); createRes.getXML(); } </script>
The 'script' tag is used to embed a client-side script (JavaScript). Whenever the icon is clicked this script will be executed. The parameter 'reference', in this case, will have field name as 'incident.caller_id'. Our code will retrieve the field name 'caller_id' by splitting the value and then it will call g_form method to retrieve field Caller's sys_id. Then we are calling 'callCaller' function and passing the caller sys_id to it for further processing.
I would suggest you to go through ServiceNow documentation for learning more about Jelly Tags and https://www.w3schools.com/ for HTML, CSS, Bootstrap or XML.
Step 4) Click 'Submit'
Step 5) Navigate to System UI > Script Includes and click 'New'
Step 6) Give it a (unique) name as 'myNotifyHandler' (Since, we have used the same script include name to be called in our macro).
Step 7) Make it accessible from 'All application scopes'
Step 8) Make it 'Client callable'
Step 9) Replace the existing 'Script' by the following code snippet :
var myNotifyHandler = Class.create(); myNotifyHandler.prototype = Object.extendsObject(AbstractAjaxProcessor, { callCaller: function() { var c = this.getParameter('sysparm_c'); var gc = new GlideRecord('sys_user'); gc.get(c); var cm = gc.getValue('mobile_phone'); var r = gs.getUserID(); var gr = new GlideRecord('sys_user'); gr.get(r); var rm = gr.getValue('mobile_phone'); var notify = new SNC.Notify(); var from = gs.getProperty('glide.notify.task.phone_number'); var participants = [cm.toString(), rm.toString()]; // set up a conference call var conferenceCall = notify.conferenceCall(); // set up the outbound calls for all conference call participants for (var i in participants) { var to = participants[i]; notify.call(from, to, conferenceCall); } }, macroVisibility: function() { if(gs.hasRole('itil')){ return 'show_icon'; }else{ return 'hide_icon'; } }, type: 'myNotifyHandler' });
Let us understand what this script does. let us first look at the function 'macroVisibility' :
macroVisibility: function() { if(gs.hasRole('itil')){ return 'show_icon'; }else{ return 'hide_icon'; } },
here, gs.hasRole('itil') will return true only if currently logged in user will have an role 'itil', in which case it will return 'show_icon' and tell our macro to be visible. If user doesn't have the role we will be returning 'hide_icon' and will hide the macro. Thereby we will be controlling the icon to be visible to only Resolvers or users having ITIL role in other words.
The GlideSystem (referred to by the variable name 'gs' in any server-side JavaScript) API provides a number of convenient methods to get information about the system, the current logged in user, etc. hasRole(String roleName) method determines if the current user has at least one of the passed-in roles. You can read more about it here.
Now let us take a look at our other function 'callCaller' :
callCaller: function() { var c = this.getParameter('sysparm_c'); var gc = new GlideRecord('sys_user'); gc.get(c); var cm = gc.getValue('mobile_phone'); var r = gs.getUserID(); var gr = new GlideRecord('sys_user'); gr.get(r); var rm = gr.getValue('mobile_phone'); var notify = new SNC.Notify(); var from = gs.getProperty('glide.notify.task.phone_number'); var participants = [cm.toString(), rm.toString()]; // set up a conference call var conferenceCall = notify.conferenceCall(); // set up the outbound calls for all conference call participants for (var i in participants) { var to = participants[i]; notify.call(from, to, conferenceCall); } },
here, In the following lines of code we will be getting mobile numbers of caller of the incident and the resolver who clicked the icon :
var c = this.getParameter('sysparm_c'); var gc = new GlideRecord('sys_user'); gc.get(c); var cm = gc.getValue('mobile_phone'); var r = gs.getUserID(); var gr = new GlideRecord('sys_user'); gr.get(r); var rm = gr.getValue('mobile_phone');
In the ServiceNow documentation here, you will find all the scripts that you can use with Notify to interact with calls and SMS messages, or to provide a custom client interface.
Notify - conferenceCall() Creates a new conference call. We have copied the code snippet available here and modified it for our purpose :
If you compare both the codes, you will realize,
var from = '+14041234567'; var participants = ['+31612345678', '+31623456789', '+31687654321'];
the above code from example snippet has been changed in our code to :
var from = gs.getProperty('glide.notify.task.phone_number'); var participants = [cm.toString(), rm.toString()];
The system property 'glide.notify.task.phone_number' stores Notify phone number used for sending SMS-s and starting conference calls from any record that belongs to the task table (or table that extends task table).
Step 10) Click 'Submit'
Step 11) Navigate to Incident > All and open any incident record
Step 12) Right click the 'Caller' field and select 'Configure Dictionary'
Step 13) Add the attribute ref_contributions=ui_macro_name to the Attributes field and click 'Update'
Dictionary attributes alter the behavior of the table or element that the dictionary record describes.
Dictionary attribute ref_contributions displays an icon for a reference field and when the field renders on a form, it invokes the named UI macro. If there are more than one macro like in this case, they are separated by semicolons (;).
Step 14) Navigate back to your incident form and you'll see an icon next to Caller field if you will have 'itil' role.
Step 15) Click the new icon we added and you'll be added to the conference call with the caller of the current incident.
So we have created an icon next to caller that, when clicked, will allow a user with ITIL role to connect with the incident caller directly in conference call.
In next article, we will solve another business requirement. Till the time, I would recommend you to visit the sources that I have mentioned in the article to have better idea about UI Macros :
- Dictionary attributes
- Show related incidents
- UI Macros
- Jelly tags
- Scripting Notify
- ‘Add Me’ UI macro for User and Group Fields
- TechNow Episode 3 | ServiceNow Jelly Scripting Part 3 of 3
Also there is an awesome and short similar community article 'Integrating ServiceNow with Twilio Services with the help of Notify API' written by
If you have any queries regarding, UI Page, UI Macro, Jelly, or Twilio, Please mention in the comments or post a question to the ServiceNow Community. We would love to help.
Thank you.
Vishal Ingle
ServiceNow Certified System Administrator
DxSherpa Technologies Pvt. Ltd.
Pune, MH, IN.
No comments:
Post a Comment