jacebenson / jace.pro Goto Github PK
View Code? Open in Web Editor NEWA blog about servicenow and other technology
Home Page: https://jace.pro
A blog about servicenow and other technology
Home Page: https://jace.pro
Is your feature request related to a problem? Please describe.
I want the search to not have ads.
Describe the solution you'd like
Implement Algolia Search
Describe alternatives you've considered
No change or remove search.
What is the post about?
Cancelling Workflows
What things would help with writing the post
Something almost always asked for and rarely delivered is the ability to cancel a requested item. I’ll try to explain why this is so difficult and how I’ve suggested implementing this.
Why is this difficult? The problem is not with the actual canceling the requested item. It’s because asking groups to undo what they did is not a simple statement.
Take for example the following workflow. There’s an approval and two tasks.
graph LR
Begin --> Approval
Approval --> Create AD account
Create AD account --> Create email
Create email --> End
Say this item gets cancelled before “Create email” is complete. Do we assume someone needs to check if the email was created but not activated, or just make a task to remove the AD account. Do we need to inform the approval chain?
This is a pretty simple example, but should show some of the issues with trying to cancel an item. I’m of the opinion that I think there are two ways to broadly address this, and one way to specifically address it.
The first option will require less involvement from each group to set up, but may find some tasks don’t make sense. Imagine you have a request to make a doctors account in Epic. Sometimes the folks who make the account don’t give the roles. So if you had two tasks one to create the account and another to give the roles. If the group who made the account got a task to “undo” the account, the roles couldn’t be removed.
The second option requires you to identify a single group who is primary owner for the group (which has other great benefits but I’m not going to go into those now). That has some office politics attached and more often then not if this is done I’ll bet a number of non service now items are owners of automated or complex items.
The third option would only work for items where the cancelling was thought through at the time the item was sized or after a conversation came up to clear up questions. Where this is different from the first option is this will create very specific tasks per the workflow. The first option would always make “undo” tasks.
What is the post about?
A post about asking why to understand reasons customers want changes.
What things would help with writing the post
What is the post about?
Project to make activity formatter
What things would help with writing the post
<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<g:evaluate>
var documentId = RP.getParameterValue('sys_id');// would return url r= value
var referringURL = RP.getReferringURL();
var table = referringURL.split('.')[0];
var sys_journal_field = new GlideRecord('sys_journal_field');
sys_journal_field.addQuery('element_id', documentId);
sys_journal_field.orderByDesc('sys_created_on');
sys_journal_field.query();
var entries = [];
while(sys_journal_field.next()){
entries.push({
value: sys_journal_field.getValue('value'),
element: sys_journal_field.getValue('element'),
elementDisplay: sys_journal_field.element.getDisplayValue(),
createdOn: sys_journal_field.sys_created_on.getDisplayValue(),
createdBy: sys_journal_field.getValue('sys_created_by'),
createdByDisplay: (function(){
var sys_user = new GlideRecord('sys_user');
sys_user.addQuery('user_name', sys_journal_field.getValue('sys_created_by'));
sys_user.query();
if(sys_user.next()){
return sys_user.getDisplayValue();
} else {
return 'unknown';
}
})()
});
}
var x = 0;
</g:evaluate>
<p>${documentId}</p>
<p>${referringURL}</p>
${entries.length}
<j:while test="${parseInt(x,10)!=parseInt(entries.length,10)}">
<blockquote class="blockquote">
<p class="mb-0">${entries[x].value}</p>
<footer class="blockquote-footer">${entries[x].createdByDisplay} (
<cite title="Source Title">${entries[x].createdOn}</cite>
)
</footer>
</blockquote>
<g:evaluate>
x = x + 1;
</g:evaluate>
</j:while>
</j:jelly>
What is the post about?
Order Confirmation Dialog in SP
What things would help with writing the post
What is the post about?
What things would help with writing the post
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://community.servicenow.com/*
// @grant none
// ==/UserScript==
/* global $ */
(function() {
'use strict';
var checkExist = setInterval(function() {
if ($('sp-page-row').length) {
console.log("Exists!");
$($('sp-page-row > .row >.col-md-9')[0]).attr('class','col-md-12');
$($('sp-page-row > .row >.col-md-3')[0]).attr('class','hide');
clearInterval(checkExist);
}
}, 100); // check every 100ms
})($);
What is the post about?
Calculating Date Time based on user's TZ and Schedule's TZ
What things would help with writing the post
Prayer.
Script include
var maintenanceWindowUtil = Class.create();
maintenanceWindowUtil.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getDateThings: function (startDateStr, endDateStr) {
try {
var rObj = {};
var start_unformatted_date = startDateStr.split('T')[0];
var start_formatted_date = [start_unformatted_date.substring(0, 4), start_unformatted_date.substring(4, 6), start_unformatted_date.substring(6, 8)].join('-');
var start_unformatted_time = startDateStr.split('T')[1];
var start_formatted_time = [start_unformatted_time.substring(0, 2), start_unformatted_time.substring(2, 4), '00'].join(':');
var end_unformatted_date = endDateStr.split('T')[0];
var end_formatted_date = [end_unformatted_date.substring(0, 4), end_unformatted_date.substring(4, 6), end_unformatted_date.substring(6, 8)].join('-');
var end_unformatted_time = endDateStr.split('T')[1];
var end_formatted_time = [end_unformatted_time.substring(0, 2), end_unformatted_time.substring(2, 4), '00'].join(':');
rObj.formatted = {
start_date: start_formatted_date,
start_time: start_formatted_time,
end_date: end_formatted_date,
end_time: end_formatted_time
};
rObj.start = start_formatted_time;
rObj.start_date_time = [start_formatted_date, start_formatted_time].join(' ');
rObj.end_date_time = [end_formatted_date, end_formatted_time].join(' ');
rObj.start_gdt = new GlideDateTime(rObj.start_date_time);
rObj.end_gdt = new GlideDateTime(rObj.end_date_time);
rObj.durationMS = rObj.end_gdt.getNumericValue() - rObj.start_gdt.getNumericValue();
return rObj;
} catch (e) {
rObj.error = e;
return rObj;
}
},
getNextWindow: function () {
try {
var iObj = JSON.parse(this.getParameter('sysparm_obj'));
var rObj = {
from: "server",
input: iObj,
output: {}
};
var now = new GlideDateTime();
if(iObj.startDate != ""){
iObj.start_date_gdt = new GlideDateTime();
iObj.start_date_gdt.setDisplayValue(iObj.startDate);
} else {
iObj.start_date_gdt = new GlideDateTime().addDaysUTC(3);
}
if(iObj.endDate != ""){
iObj.end_date_gdt = new GlideDateTime();
iObj.end_date_gdt.setDisplayValue(iObj.endDate);
} else {
iObj.end_date_gdt = new GlideDateTime().addDaysUTC(3);
}
rObj.output.schedule = {};
rObj.output.span = {};
rObj.output.user = {};
var user = new GlideRecord('sys_user');
if (user.get(gs.getUserID())) {
rObj.output.user.tz = user.getValue('time_zone') || gs.getProperty('glide.sys.default.tz');
}
// get the selected schedule
var schedule = new GlideRecord('cmn_schedule_maintenance');
schedule.addQuery('sys_id', iObj.maintenance_window);
schedule.query();
if (schedule.next()) {
rObj.output.schedule.time_zone = schedule.getValue('time_zone') || gs.getProperty('glide.sys.default.tz');
// get the first span
var span = new GlideRecord('cmn_schedule_span');
span.addQuery('schedule', iObj.maintenance_window);
span.query();
if (span.next()) {
// return the span (if theres more than one span we will have issues)
rObj.output.span = this.getDateThings(span.getValue('start_date_time'), span.getValue('end_date_time'));
}
}
var nowStr = iObj.start_date_gdt.toString().split(' ')[0] + ' ' + rObj.output.span.start;
var nextSpan = new GlideDateTime();//the GDT for the next span on the maintenance window
nextSpan.setValue(nowStr);//set this to date given or 3 days from now and at the hour of the span
nextSpan.addSeconds(nextSpan.getDSTOffset() * -1);//add/subtract time for DST Offset
while (nextSpan.getNumericValue() < now.getNumericValue()) {//if nextspan is in the past, move it up a day
nextSpan.addDaysUTC(1);
}
var glideSchedule = new GlideSchedule(iObj.maintenance_window, rObj.output.schedule.time_zone);
var ms = glideSchedule.whenNext(nextSpan);//the milleseconds until the next span
if (ms === -1) {//if the ms is -1, there is no next span
rObj.whenNext.error = "Schedule never has a 'whenNext'";
} else {
nextSpan.addSeconds(glideSchedule.whenNext(nextSpan) / 1000);//move nextspan to the beg of next span
rObj.start_date = nextSpan.getDisplayValue();//returns beg next span in user format
nextSpan.addSeconds(rObj.output.span.durationMS / 1000);//move nextspan to the end of next span
rObj.end_date = nextSpan.getDisplayValue();//returns end next span in user format
nextSpan.setTZ(Packages.java.util.TimeZone.getTimeZone(rObj.output.user.tz));
rObj.output.user.DSTOffset = nextSpan.getDSTOffset();
rObj.output.user.isDST = nextSpan.isDST();
}
return JSON.stringify(rObj);
} catch(e) {
rObj.error = e;
return JSON.stringify(rObj);
}
},
type: 'maintenanceWindowUtil'
});
Client Script
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var ga = new GlideAjax('global.maintenanceWindowUtil');
ga.addParam('sysparm_name', 'getNextWindow');
ga.addParam('sysparm_obj', JSON.stringify({
"start_date":g_form.getValue('start_date'),
"end_date": g_form.getValue('end_date'),
"maintenance_window": newValue
}));
ga.getXML(function(response){
var responseDocument = response.responseXML.documentElement;
var answer = responseDocument.getAttribute('answer');
var serverObj = JSON.parse(answer);
console.log(serverObj);
g_form.setValue('start_date',serverObj.start_date);
g_form.setValue('end_date',serverObj.end_date);
});
}
This assumes you make a field on Change called u_maintenance_window
that is a reference to cmn_schedule_maintenance
What is the post about?
What things would help with writing the post
What is the post about?
DB Views and measuring the lack of something
What things would help with writing the post
So DB views, ive realised achieve alot
they have their flaws
but.. they are pretty powerful
but ive been at work and thought "Dam yeah, cant do that with reports...." so many times.
My mind has blanked, ill try recall a use case
Yeah, like finding the inverse of querys is cool
like, "How many KBs havent been viewed?"
"What user doesnt have an asset?"
i mean, choosing what table you put "left join = true" on still baffles me. Its like the inverse of what i'd expect
reporting on the absence of things is tough, and yea db views help solve that.
What is the post about?
What this is and how its different then Jim C's
What things would help with writing the post
https://github.com/jacebenson/x_8821_dev_toolbox
https://developer.servicenow.com/app.do#!/share/contents/7375176_developer_toolbox3?v=1&t=PRODUCT_DETAILS
What is the post about?
When to Scope
What things would help with writing the post
According to the community;
When should you build an app under global scope versus private application scope?
There are two use cases when considering application scope: extending an existing app or creating a custom app from scratch. If you are extending or modifying an existing global scope application and the changes are having a high impact on other applications, then leave the change in the global scope. However, if the changes are going to have less impact to other applications, then the modifications can be done as a scoped app.
When you are creating a new application from scratch, you should be creating it as a scoped app. ServiceNow’s product strategy is to develop more and more scoped apps to make it easier for customers to deploy the application and to simplify future upgrades. Also, backing out changes to scoped apps is much simpler and can be done with a single push of a button.
Generally it looks like Servicenow has broken up things in the scoped applications by function or business unit, e.g.
That's the precident Servicenow has set.
The pro's and cons of by function and business unit are such
Pro | Con |
---|---|
Easy to tell what needs to be updated based on the ask | Hard to expand to othre area's if some functionality needs to be shared. |
Having | -- |
Our dev team is a little gun-shy when it comes to scoped apps. Do you have a written policy about what goes in a new scoped app?
e.g. Our team is concerned about a future state where our drop-down of scoped apps is 200-items long. (edited)
I'm looking for a decision matrix of when to go scope, when to stay global.
Like if you're extendingincident
, stay Global because it's already in global. - Jarod Mtaht line i think is everyones question
sn's done it at a business unit with HR
I'd follow suit w/ SN where you make an app per unit, if all units are going to use said table add it to some core app - JaceWe're leaning towards our IT solution hierarchy. if it's a separate product, then it's separated in the CMDB.
that's our current draft policy - Jarod Mim so confused - jace
We have SN as a Business Service.
We also have SN-Incident as a Business Service that is amodule of
the root SN. This has separate ownership, etc...
so if we're going to track something as a new product (e.g. "Advanced Reporting App") as a Business Service (in the CMDB), we will make it a new scoped app. (edited)
That, or if there's a security/performance concern, it can be in a scope.
That's our draft policy. I was curious how other teams decide when to put enhancement (new functionality) requests in scope - Jarod Mright but, where is the line drawn, is an application considered just a form on the catalog, or a net new table? what if the catalog item needs data from a net new table? - Jace
Me and @Rolf were talking about the other side of this issue too, When to use great discussion to have but then a few of us have made them and still struggling on how to maintain . clone ect. So maybe these questions would be a great addition to the TechNow were were hoping for over in #lchh - kcimpulse
i guess if you looking for how others are doing it. we have no process around it. we have a "marketing" app scope, and some weirdly named other unit scope - jace
https://community.servicenow.com/docs/DOC-7746
When should you build an app under global scope versus private application scope?
There are two use cases when considering application scope: extending an existing app or creating a custom app from scratch. If you are extending or modifying an existing global scope application and the changes are having a high impact on other applications, then leave the change in the global scope. However, if the changes are going to have less impact to other applications, then the modifications can be done as a scoped app.
When you are creating a new application from scratch, you should be creating it as a scoped app. ServiceNow's product strategy is to develop more and more scoped apps to make it easier for customers to deploy the application and to simplify future upgrades. Also, backing out changes to scoped apps is much simpler and can be done with a single push of a button. - Jarod MWe are using them pretty liberally here. When we upgraded to Istanbul earlier this year we decided to prioritize developing in scoped apps. Our main motivation was to make the upgrade process smoother (less conflicts on upgrade!) - rolf
Do you have a naming convention (so they are sorted in the dropdown)? - Jarod M
Only for Scoped Apps in which we're creating a Service Catalog Category, where we preface it with an SC
other than that it's just search, but we only have around 35 apps right now so it's not a huge deal - rolfWe are doing the Abvr for the team name - Because the OCD in me hates the scope being in the same long table name as the name of the table. Like We made an Investment application. So I might have made it INV but didnt want the table name being INV_Investment (edited) - kcimpulse
Even with 200 apps though I don't think we'd be running into any naming conflicts. The list is sorted by creation date so most of the time the stuff you want to work on is on top
While there's definitely some confusing aspects at first with scoped app dev, it's been worth it for our team to make the switch to primarily working out of global. Making a large scale application while knowing that you can always uninstall and be back to PDI functionality is really nice. I think it'll help us as we scale... right now we are a small team of 4 (3 devs and a manager). - rolfGreat video@chrismaloy very appreciated and good timing on a few discussions we have been having - https://www.youtube.com/watch?v=DLqkDxGVLbE - kcimpulse
Thanks @kcimpulse! The video is a little old but still relevant. Thank you for the shout out. - chrismaloy
What is "Application Scoping"?
What does the the Scoped Application Model do for me?
Easy Migration Tools to move things from Global.
What is the post about?
What things would help with writing the post
Promoting code all the ways to do it
https://docs.servicenow.com/bundle/london-application-development/page/build/applications/reference/r_AvailableSourceControlOperations.html
https://docs.servicenow.com/bundle/london-application-development/page/build/system-update-sets/reference/update-set-administration.html
https://docs.servicenow.com/bundle/london-application-development/page/build/team-development/concept/c_TeamDevelopment.html
What is the post about?
Implementing chargebacks
What things would help with writing the post
Talk in terms that you're providing these forms, and customizations at your business's cost but talk about things in a way to be clear, there is a cost.
E.g.
We will customize that form, it will take ~ x points or ~ x hours.
Today we don't charge other units for this work.
In time these requests will need to provide a return of investment greator than the cost of development
Once you start talking that way, determine what the cost actually is.
Identify Rate of pay per hour or per point based on average of staff or some arbitrary number
Use estimated points/hours to show estimated cost, use actual points/hours to actual cost.
Continue to provide work even if it's at a loss during this time.
Now that this work has been shown to have cost and what a return on investment would be.
Start using that data.
What is the post about?
How to use Import sets for both Inbound Integrations, and Integrations where you get data and write it back to Sn.
What things would help with writing the post
Matt rose: Yes, populating an import set table with an outbound REST call and running a transform map is the best way to do this. I have done this once before at a previous employer and wish that I had documented it better. With that said, here is a community thread on the topic with some guidance: https://community.servicenow.com/community?id=community_question&sys_id=4f808325db98dbc01dcaf3231f961925
Pok
var importSetTransformer = new GlideImportSetTransformer(); importSetTransformer.setMapID(sys_transform_map_Gr.sys_id); importSetTransformer.transformAllMaps(sys_import_set_row_Gr);
What is the post about?
Activating plugins via script
What things would help with writing the post
//Partial Version
//you can check following URL to see if the work is finished. It is finished when the completion time is set and the percent complete is 100.
//<instance>/sys_execution_tracker_list.do?sysparm_query=name%3DPlugin%20Installer
var plugins = [];
plugins.push('com.snc.pa.change');
plugins.push('com.snc.pa.problem');
plugins.push('com.snc.pa.premium');
plugins.push('com.snc.pa.solution.library');
var main = new GlideMultiPluginManagerWorker();
main.setPluginIds(plugins);
main.setProgressName("Plugin Installer");
main.setBackground(true);
main.start();
What is the post about?
Test driven development
What things would help with writing the post
See: https://greg-grabowski.com/how-to-start-with-tdd-in-servicenow/
What is the post about?
Email Examples
What things would help with writing the post
Subject: ServiceNow Customer Satification Survey for [RECORD]
We would like to thank you again for being our customer.
Customer satisfaction is our priority, and we hope the solution to incident [RECORD] has met your expectations.
Please grade our performance by clicking the link below to complete a short survey. Every survey is acted upon and your input is vital.
Customer Satisfaction Survey
Thank you for your input.
[Person's name]
[Role, Department]
[Company]Resolved by: [Resolvers Name]
Short description: [Short Description]
Subject: Survey invitation: New Survey on Customer Satisfaction Survey
You have been invited to take the survey: Customer Satisfaction Survey.
Click here to take your survey:
[Link to survey]Unsubscribe | Notification Preferences
Subject: [Priority] Record Class Commented - [Company] - [Record]: [Short Description]
[Record Updated]
[Priority] Record Class: [Record]Hi
Record Class [Record] has been updated.Priority:
[Priority]
Short Description:
[Short Description]
Comments[Comments]
Steps to reproduce:
[Steps to reproduce]
Business Cricality: [Imact]
Affected Users: [Quantity of users]
Start Date: [Start Date]
End Date: [End Date]Click here to view Record Class [Record]
Sincerely,
ServiceNow Customer Support
What is the post about?
Showing Barcodes on forms.
What things would help with writing the post
What is the post about?
Step away from emails a step by step guide
What things would help with writing the post
An easy way to start is to have inbound emails use the new call application.
TL; DR Record Producers created specific to your most commonly reported incidents that gather the data needed to resolve those incidents (including optional data based on answers in the RP) can greatly reduce your TTR and cause overall greater customer satisfaction despite the bigger hurdle to incident submission.
careful pushing of folks to these Structured Record Producers can be handled in many ways, including closing incidents submitted improperly and pointing them to the new RP
ajb [< 1 minute ago]
Emails & SP:
Emails created entries cost more, introduce delay for most interactions, initial send is quicker for user to send, slower to help them in general case
Structured data and clear services via SP are a large difference - cuts down on back and forth, aids in automation, helps routing and fulfillment expectations, transparency and prioritization. Better expectations and up front data collection leads to happier users quickly.
Phased Approach is recommended Show incentive to go to no inbound email with Time to resolved Time to resolved is lessened by less categorizing, less back and forth to/from the customer.
Some organizations saw a 25%-75% better resolution time after disallowing email.
Ensure you offer specific services that handle most the calls to allow the faster resolution.
I asked The other day in the sndevs slack channel what do people's companies stopped incoming emails doing;
User Generation: 9
Ticket Generation: 5
Ticket Updates: 4
Approvals: 2
Company lives on email: 3
Pros | Cons |
---|---|
Faster to send the email then fill out the form | Email missing required data in structured format |
Required data needs to evaluated in the new record |
Pros | Cons |
---|---|
What is the post about?
What things would help with writing the post
https://community.servicenow.com/community?id=community_question&sys_id=3ae007a5db98dbc01dcaf3231f9619de&anchor=answer_e49aafe9dbd41fc01dcaf3231f96196e
What is the post about?
Best Practices
What things would help with writing the post
Source: https://community.servicenow.com/community?id=community_blog&sys_id=6e7d6269dbd0dbc01dcaf3231f9619c0
Behind the scenes here at ServiceNow, the Knowledge Management and Multimedia teams work closely with subject matter experts to dis-seminate critical information to our customers. We've found that certain topics come up frequently, in the form of best practices that can help you keep your ServiceNow instances running smoothly. This series targets those topics so that you and your organization can benefit from our collective expertise. If you have a best practices topic you'd like us to cover in this series, please let us know in the comments below.
Best practices for using ATF 9/26/17
How to avoid ATF testing failures 5/30/17
Best practices for using the Flow Designer 2/22/18
Dictionary overrides—what they are and how to use them 7/24/17
When running business rules, timing is everything 7/11/17
Six ways to Improve the Performance of Client Scripts 6/21/17
Properly deploy changes using Team Development 5/23/17
How to keep variables from stepping on each other 3/17/17
User account or service account? What to use for web service tasks 3/10/17
Outsmart fickle networks, firewall changes, and down servers in your web services integration 2/24/17
Why you should never use external iFrames - and the one exception to this rule 2/15/17
How to clone to a target instance that has in-development applications 2/14/17
Why you shouldn't develop on your production instance 1/17/17
Annotate scripts and customizations with comments 12/20/16
Requesting assistance with quarterly patching or version upgrade changes 5/17/17
The high importance of managing your company contacts on HI 5/1/17
Adding new users in HI—the how and the why 4/24/17
The basics of integrating with SuccessFactors and other HR management systems 4/27/18
[Agile 101—What is Agile development and why do you need it?](community?id=community_blog&sys_id=e300ac23dbf69bc09d612926ca961977" target="_blank) 6/28/18
PPM 101
What is PPM, and why do you need it? 6/18/18
CMDB 101
[](community?id=community_blog&sys_id=e300ac23dbf69bc09d612926ca961977" target="_blank)—
What is a configuration management database, and why do you need one? 4/13/18
ITOM 101
[](community?id=community_blog&sys_id=e300ac23dbf69bc09d612926ca961977" target="_blank)—
What is ITOM and why do I need it? 3/30/18
Tips for implementing and troubleshooting Cloud Management - 3/2/18
Best practices for setting up Discovery schedulesBest practices for setting up Discovery schedules 12/14/17
Best practices for MID Server setup and tuning 11/9/17
ITSM 101
[](community?id=community_blog&sys_id=e300ac23dbf69bc09d612926ca961977" target="_blank)—
What is ITSM and why do you need it? 6/1/18
Service Catalog in Kingston—podcast and best practices 2/8/18
Best practices for a successful ITSM implementation 1/18/18
Best practices for implementing the Problem Management application 1/11/18
Best practice: Make the most of standard changes 12/18/17
Best practices for implementing the Incident Management application 10/26/17
Best practices for implementing the Change Management application 10/11/17
Tips for streamlining ServiceNow upgrades - podcast and best practices 3/16/18
Why you should give each of your sub-production instances its own unique look 4/12/17
Set up currency properties correctly 4/6/17
How do you plug in a plugin? The ins and outs of plugin activation 3/3/17
Limit the Number of Users with the Admin Role 1/5/17
Best practices for creating and editing forms 8/24/17
Choosing the correct field type when building a form 6/9/17
Best practices for configuring lists 9/11/17
Where to avoid linking to a reference field when configuring a list 1/12/17
Avoid issues when modifying shared fields in extended tables 3/29/17
When to Create a New Table vs. When to Extend 1/28/17
Best practices for creating responsive dashboards 12/8/17
Best practices for creating and sharing reports 8/11/17
Vulnerability Response 101
[](community?id=community_blog&sys_id=e300ac23dbf69bc09d612926ca961977" target="_blank)—
Understanding Vulnerability Response with ServiceNow 5/18/18
Links to all NOWsupport resources
ServiceNow Customer Success Center
if describe is only avaiable in the global scope....how in the world do I unit test in a scoped application?
What is the post about?
Dates and times
What things would help with writing the post
https://community.servicenow.com/community?id=community_blog&sys_id=467c62e1dbd0dbc01dcaf3231f9619ad
What is the post about?
Debugging Service Portal Widgets
What things would help with writing the post
This article sets out a standard set of Service Portal Widget debugging techniques and is intended both for informational and training purposes. For many incidents, an understanding of the "Basic Techniques" section will suffice. For higher priority incidents on heavily customized instances, a firm grasp of the "Advanced Techniques" may be required. The techniques in this article are a compilation of techniques gathered from currently available ServiceNow resources and new techniques which are documented for the first time.
All examples in this article are run on a widget called "Global Objects Demo Widget". To run the examples in the article you will need to see section "Running the Example Tests" at the end of the article to get setup.
The console.log() function will log data to the JavaScript console in the browser. This technique will work in the Client Script of the widget and also in the Server Script.
Example
If you look at line 3 and line 16 of the Server Script of the Global Objects Demo Widget, you'll notice that the "input" and "data" objects are logged to the console.
Open the JavaScript console in Chrome developer tools. Refresh the preview pane and you'll notice the following result in the console:
The input object is undefined and the data object is printed to the console.
The debugger function can be used in the Client Script of the widget but not the Server Script. Adding the debugger function is like inserting a break point into your code allowing you to step through the code line by line.
Example
In the Client Script of the widget, add the code debugger; at line 23.
Open Chrome Developer Tools. Save the widget and refresh the preview pane. Press the "server.get({collectionName: "presidents"})" button. The JavaScript execution will stop at the word debugger. To see the "response" object contents, hover your mouse over the word "response" in line 14 of the code in devtools.
To step into the next line in the code use the down arrow button. To allow the JavaScript execution to proceed without stopping, press the "Resume script execution" button.
Hold down the control key and right-click on the widget. Choose "Log to console: $scope.data" or "Log to console: $scope". The only difference is whether you want to log the entire scope object to the console or only the data property of the scope object.
Example
Navigate the to the following URL: https://.service-now.com/sp?id=demo_widget_example
Hold down the control key and right-click on the widget. Choose "Log to console $scope.data". Open Chrome Developer Tools and expand the object dumped to the console and verify that the value of $scope.data.prop1 is "Apple".
Advanced Techniques
The advanced debugging techniques described below can be highly affective when troubleshooting on a production instance where it is not possible to make any changes. All the techniques below are run through Chrome Developer Tools.
You can think of this technique as an analogy to a puppet show. The puppeteer activates and manipulates the puppets (widgets) with a set of strings. In this case we are creating a second set of strings to the puppet so that we can activate and manipulate the widget from the JavaScript console!
This technique allows you to:
Change the widget's scope data
Run widget scope function
Re-run the widget Server Script
Steps to get a reference to the widget's scope in the JavaScript console:
Right-click on the widget and choose "Inspect"
In devtools Elements tab, click on the element with attribute widget=”widget”. It should be a few elements above the currently inspected element. This points the $0 scripting tool at the widget.
In the Javascript console, run the following code:
var scopeRef = angular.element($0).scope();
Changing the widget's scope data:
Once you have a reference to the widget in the JavaScript console, you can take any piece of data in the widget's scope and just change it. After changing a value, run the AngularJS $apply() function on the scope to apply your changes to the page.
Example
After getting a reference to the Global Objects Demo Widget in the console, run the following code:
scopeRef.data.prop1 = "Pear";
scopeRef.$apply();
Running the widget's Client Controller functions from the console
Any function that is defined in the Client Scipt (client controller) of the widget is available from the widget's scope. This means that once you have a reference to a widget's scope in the console you will not only be able to change data in the scope object but you can also run any of the client controller functions!
Example
The getPrettyData() function is defined in the Client Script of the Global Objects Demo Widget. Now that we have a reference to the widget's scope in the console, we can run the function directly from the JavaScript console.
Re-run the widget's Server Script
Let's say that we've made some changes to the scope of the widget with the techniques above, we've got our reference to the widget in the console, and we want to see what happens when the server refreshes the data sent to the client controller. We can re-run the widget's Server Script from the console as per below:
scopeRef.server.refresh();
The client controller scripts for all widgets on the page can be found in the "Sources" panel of Chrome Developer Tools. If you look at the screen capture below, you'll notice that they are all listed under the "top" window then under the "(no domain)" section. Clicking on the script will open it in the Sources panel code editor window. Most of the widget client controller scripts are listed as <widget_id>.js, others will be listed by the id attribute value of the top level HTML element of the widget.
Once the client controller script is open in devtools you can begin debugging directly from there.
Making local changes to the client controller code from devtools
Example
Navigate the to the following URL: https://.service-now.com/sp?id=demo_widget_example.
Open Chrome developer tools.
Click on the "Sources" panel in devtools.
Open the global-objects-demo-widget.js file
Between lines 7 and 8 add the following line of code:
alert("Server script now refreshed");
Right-click in the script editor window and Save. Do not refresh the page.
Click the "server.refresh()" button in the widget.
Notice the alert window pops up showing that you've been able to alter the widget directly from devtools! This is a powerful technique when debugging production instances.
Adding break points to widget client controllers from within devtools
Another great thing about having access to the client controller code from within devtools is that you can add in break points. Break points can be added to the code by clicking on the line numbers in the code editor window of the "Sources" panel.
Example
Navigate the to the following URL: https://.service-now.com/sp?id=demo_widget_example
Open Chrome developer tools.
Click on the "Sources" panel in devtools.
Open the global-objects-demo-widget.js
Click on line number 15 to add in a break point.
Click on the "server.get({collectionName: "presidents"})" button.
Notice that JavaScript execution stops directly at line 15.
Hover the mouse over the "data" in line 15 to inspect the response.
Resume JavaScript execution with the button to the right of the code editor window.
Running the example tests
Attached to this KB article you'll find a update set which contains one Service Portal widget called "Global Objects Demo Widget" and one Service Portal page called "demo_widget_example". The demo page contains one instance of the demo widget.
To import the update set to your test instance:
1. Click on "Retrieved Update Sets" in the Application Navigator.
1. Click on the Related Link "Import Update Set from XML" at the bottom of the page.
1. Click "Choose File", location the downloaded update set from the KB article and press the "Upload" button
1. Click on the newly uploaded update set in the list of Retrieved Update Sets. The name will be "Service Portal Global Objects Demo"
1. Click the Preview Update Set button in the header.
1. Click on Commit Update Set.
To run the tests, it's good to have two browser tabs open; one with the widget's code and preview pane and the other with the demo page showing.
Tab 1: https://.service-now.com/sp_config?id=widget_editor&sys_id=072cfcbc4f04130050d128201310c7d7&spa=1
Tab 2: https://.service-now.com/sp?id=demo_page
In the widget editor, you can enable a preview pane to test any changes that you've made to the widget. To do this click on the hamburger menu at the top right of the editor and select "Enable Preview". Then just use the eye button toggle the widget preview on and off.
After every test remember to remove any changes made and resave the widget.
What is the post about?
Debugging Performance issues
What things would help with writing the post
What is the post about?
ACLs vs Query Business Rules
There are opinions on using (Access Controls) ACLs or (Query Business Rules) QBRs. So lets look at this in more depth; ServiceNow seems to recommend using ACLs as they only use QBRs sparingly, the only one I can think of is on sys_user for active users. However the more I think about this, the more I think it makes more sense to manage any row level access in QBRs.
Query Business Rules
Pros
Cons
Access Controls
Pros
Cons
What is the post about?
Notification Dialogs
What things would help with writing the post
To figure out what to use and when really is going to come down to each specific situation, but I'll go through my thoughts on what these are, how to use them, and why I favor one over another. To do this lets introduce our contenders. On the left we have the quick and dirty, to the point, not always clean UI Notifications. On the right we have the attention grabbing, mouse-taking, extensions exist to block Notification Dialogs.
By on the left I mean first. So UI Notifications for me have been a progression for debugging. I almost always use some sort of logging of UI Notification to test some problematic script. Way back when I used alerts because Internet Explorer didn't support console log for debugging but that was a long time ago. Then I used started using gs.addInfoMessage because it wasn't as "In your face." Then Servicenow was nice enough to g_form.showFieldMsg. They had error and information styles.
The only UI Notifications in Servicenow are the following and are used these ways;
Using the right type of notification dialog is important to convey the message to your users. Most the time I believe these are just a distraction or waste of a click, however sometimes they are necessary to inform the user. There are a log of these and you can make them look nice. The issue with the
I also have used GlideDialogWindow, GlideWindow, and GlideModal in place of the alerts and confirmation messagebut they are all essentially the same except they work slightly differently.
Available notification dialogs today.
Examples of the notification dialogs.
Using the right type of dialog window is important to convey the message to your users. Most the time I believe any distraction or waste of a click. However sometimes as much as you recommend against sometimes you got to do things you don't like. Like making a pop up window. Might as well make it look nice.
/scripts/classes/doctype/GlideModal.js
Any client-side library the browser needs -has to be shipped to the browser-. Now, by default ServiceNow will bundle these into -includes files and send them down all appended together, but we _also- put a marker in that gives you the original filename and where you can access it directly when we do that.
So you can use the 'search all files' feature of Chrome (or the equivalent in other browsers) to find references to what you're interested in. When you find the definition of said thing, see if it's in an _includes.js file
If so, scroll up to the closest Resources tag, and it should tell you where to go find that file by itself.
In this case, I loaded the Incident form, and found the definition in js_includes_last_doctype.js
(edited)
So I just scrolled up a tiny bit and got the direct URL out of the _includes file
If the modal is just going to submit to an existing form, you could use GlideModalForm instead (that takes a title, a table name, and a callback for when the submit is successful) and that handles closing the modal and whatnot for you.
What is the post about?
for waht we do
... it is probably a great thing to use it in almost all cases
What things would help with writing the post
https://stackoverflow.com/questions/12609527/why-isnt-try-catch-used-more-often-in-javascript
What is the post about?
Upgrades and patching
What things would help with writing the post
What is the post about?
What things would help with writing the post
////where current is a task record with a workflow context
var id = '3452d5259f2002002920bde8132e7028';
var current = new GlideRecord('std_change_proposal');
current.get('8e119a99db6b03c8d9ca72ec0f9619be');
var w = new Workflow();
var context = w.startFlow(id, current, 'insert', {});
What is the post about?
Inbound Action debugging
Inbound Email debugging
What things would help with writing the post
Source
Youtube
If emails are not received or processed as expected,
it is important to identify the root cause. The following
steps help understand the inbound email process as well
as guide you through troubleshooting common issues.
What is the post about?
What things would help with writing the post
What is the post about?
GlideScriptEditorManager (api for apis)
This is a way to get the apis listed in the text editors. Below I include a script on how to get the data, it seems to come back in some malformed JSON. So i have to copy the JSON out and paste into something like JSON Editor Online and correct it.
var tables = [
'sys_script_include',
'sys_script_email',
'catalog_client_script'
];
tables.map(function(table){
try {
var gsem = new GlideScriptEditorManager();
var si = new GlideRecord(tables);
si.newRecord();
var api = gsem.getApis(table, "script", si).toString();
gs.info(table);
gs.info(api);
} catch(e) {
// gs.info(e);
}
});
I've used this code in the past to generate markdown tables for these things in the past;
for(var thing in api){
getThings(thing)
}
function getThings(thing){
var output = ['---','---','# ?','','| Property/Method | Description |','| --- | --- |'];
for (var prop in thing){
output.push('| ' + prop + ' | ' + thing[prop]['!doc'] + ' |');
}
console.log(output.join('\n'));
}
What is the post about?
What things would help with writing the post
c.openModal = function(action) {
c.modalInstance = $uibModal.open({
templateUrl: 'ticket-modal.html',
controllerAs: 'modalC',
scope: $scope,
controller: function() {
var modalC = this;
modalC.modalInstance = c.modalInstance;
modalC.action = action;
modalC.messages = c.getMessages(action);
modalC.data = c.data;
modalC.record = c.data.recordId;
modalC.action_reason = '';
//modalC.fnSubmit = c.submitModal(action,modalC.record,modalC.action_reason);
}
});
}
What is the post about?
This post is about 3rd party libraries;
What things would help with writing the post
What is the post about?
I didn't want what happened to the SNUG's happening to this event so I
volunteered to start a Developer Meetup. That was two years ago. The
meetups main purpose, have some ad-hoc labs and have happy hours.
I'll go over what it takes to run these events. Attendees will learn
how to:
- Identify how often and about what the meetup should meet.
- Finding content to use for labs and / or for happy hour.
- Finding hosting locations in your area.
What things would help with writing the post
Timeline
What is the post about?
https://servicenowthink.wordpress.com/tag/service-portal-unsupported-mobile/
What things would help with writing the post
What is the post about?
Exposed Data on the community
What things would help with writing the post
var companies = {};
var endpoint = document.location.origin + "/api/now/table/sn_communities_profile?";
// endpoint += "sysparm_query=nameLIKE@^state=MN&";
// endpoint += "sysparm_fields=name,company&";
// endpoint += "sysparm_limit=100"
var client=new XMLHttpRequest();
client.open("get", endpoint);
client.setRequestHeader('Accept','application/json');
client.setRequestHeader('Content-Type','application/json');
client.setRequestHeader('X-UserToken', g_ck);
client.onreadystatechange = function() {
if(this.readyState == this.DONE) {
var responseObj = JSON.parse(this.response);
responseObj.result.map(function(user){
if(companies[user.company]){
companies[user.company].push(user);
} else {
companies[user.company] = [user];
}
});
console.log(companies);
}
};
client.send("");
What is the post about?
Integrate repeatably faster by following these steps
What things would help with writing the post
https://blog.jacebenson.com/post/2018-12-02-k19-proposals/#integrate-repeatably-faster-by-following-these-steps
What is the post about?
Exporting to a custom CSV format
What things would help with writing the post
// Export to CSV
var attachment = new GlideSysAttachment();
var data = "Number,Name\n"
var gr = new GlideRecord('incident');
gr.addQuery('active', 'true');
gr.query();
while(gr.next()){
data += gr.number + "," + gr.caller_id.name + "\n";
}
incident = new GlideRecord('incident');
incident.get('85071a1347c12200e0ef563dbb9a71c1'); //Gets the record I want to attach the file too
var newFile = attachment.write(incident, 'Incidents.csv', 'text/csv', data);
What is the post about?
Approvals for Knowledge and how there is a unused event, kb_knowledge.approval.inserted
That event is not registered in the event registry.
There is no notification tied to the event.
What things would help with writing the post
https://community.servicenow.com/community?id=community_question&sys_id=28a84f21db5cdbc01dcaf3231f961994
What things would help with writing the post
Describe the bug
Missing g_form.addToCart and g_form.orderNow
To Reproduce
Steps to reproduce the behavior:
What is the post about?
Using MJML for emails.
What things would help with writing the post
What is the post about?
What things would help with writing the post
What is the post about?
Dumb vendor video;s
Sia Mongodb: https://youtu.be/0vPt7GI-2kc?t=24
Opensuse uptown funk: https://youtu.be/SYRlTISvjww
Winsongs: https://youtu.be/W--13mBc788
What things would help with writing the post
What is the post about?
About this share: https://developer.servicenow.com/app.do#!/share/contents/9824957_simple_record_separation?v=1.08&t=PRODUCT_DETAILS
What things would help with writing the post
Try it out write your thoughts on it.
What is the post about?
Multirow variable sets
What things would help with writing the post
What is the post about?
About using the Upgrade Modal
What things would help with writing the post
This is for either the oob sn upgrade modal
overview_help.visited.helsinki
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.