UI macro is a powerful way to add custom information, scripted reusable component to the user interface. In this post, I will talk about how you can create a UI macro to display related tasks (other incidents, changes, problems) that have the same affected CI’s. If you are not familiar with how to create a UI macro, please refer to this ServiceNow documentation. Take a look at the XML script below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | <?xml version="1.0" encoding="utf-8" ?> <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css"></link> <style> .noflow { max-width: 100%; overflow: hidden; padding-left: 22px; } </style> <g2:evaluate object="true" jelly="true"> var affectedCI = []; var result = []; var grAffectedCI = new GlideRecord('task_ci'); grAffectedCI.addQuery('task', current.sys_id); grAffectedCI.query(); while(grAffectedCI.next()){ affectedCI.push(grAffectedCI.ci_item.toString()); } var queryStr = 'task.active=true^task!=' + current.sys_id + '^ci_itemIN' + affectedCI.join(); var gaCount =new GlideAggregate('task_ci'); gaCount.addEncodedQuery(queryStr); gaCount.addAggregate('count(distinct','task'); gaCount.groupBy('task.sys_class_name'); gaCount.query(); while(gaCount.next()){ var tableName = gaCount.getDisplayValue('task.sys_class_name'); var sysClassName = gaCount.getValue('task.sys_class_name'); var taskCount = gaCount.getAggregate('count(distinct','task'); result.push({ "number" : [], "taskType" : sysClassName, "tableName" : tableName, "count" : taskCount, "url" : "" }); } for(var i=0; i<result.length; i++){ var taskCi = new GlideRecord('task_ci'); taskCi.addEncodedQuery(queryStr); taskCi.addQuery('task.sys_class_name', result[i].taskType); taskCi.query(); while(taskCi.next()){ var number = taskCi.task.number.toString(); if(result[i].number.indexOf(number) == -1) result[i].number.push(number); } result[i].url = '/nav_to.do?uri=' + result[i].taskType + '_list.do?sysparm_query=active=true^numberIN' + result[i].number.join(); } result.sort(compare); function compare(a, b) { var countA = parseInt(a.count); var countB = parseInt(b.count); var comparison = 0; if (countA > countB) { comparison = 1; } else if (countA < countB) { comparison = -1; } return comparison; } </g2:evaluate> <j2:if test="$[result.length>0]"> <div class="row noflow"> <div class="col-xs-12 col-md-3 col-lg-4 control-label"></div> <div id="infoDiv" class="col-xs-10 col-sm-9 col-md-6 col-lg-5 input_controls animated zoomInRight slow delay-1s"> <div> <span><strong>Open Tasks related to the environment of the affected CIs:</strong></span> </div> </div> <div class="col-xs-2 col-sm-3 col-lg-2 form-field-addons"></div> </div> <j2:forEach items="$[result]" var="jvar_task"> <div class="row noflow"> <div class="col-xs-12 col-md-3 col-lg-4 control-label"></div> <div class="col-xs-10 col-sm-9 col-md-6 col-lg-5 input_controls animated zoomInLeft slow delay-2s"> <span class="bounce slow delay-3s" style="color: red">$[jvar_task.count]</span><a href='$[jvar_task.url]' target='_blank' rel="noopener noreferrer"> Active $[jvar_task.tableName](s)</a> </div> <div class="col-xs-2 col-sm-3 col-lg-2 form-field-addons"></div> </div> </j2:forEach> </j2:if> </j:jelly> |
I included a library called animate.css that does the fancy animation for the html elements. I then query the affected Ci table to get the sys_id of the Cis associated with the current record, then constructed a query to use GlideAggregate to get the count base on task type (incident, change, problem, etc…), saving the values I want along the way.
For every task type, I query the table to get the number and build the appropriate URL for easy viewing of each task type, sort the result array with count a-z. At this point, I get all the data I need and it just a matter of displaying them. Depending on if you want to display this UI macro in a 1 or 2 columns lay out, you will need to build the HTML template accordingly. In this example, I chose the two columns lay out.
Using the jelly if syntax to check if my result is empty or not as well as for each logic to loop through and duplicate the html template for each item.
Now, all you have left to do is creating a formatter and add it to a form and voila, the result is a beautiful, animated information in a two column layout that you can add to any task form! I hope you like this little customization. Check it out in the below GIF.