patricklatella
Mega Sage

Hi Community, 

wanted to share a widget I created that creates a simple record producer.  The original purpose for this widget was for a custom "WalkUp Kiosk" Service Portal that a client needed.  This provides a very simple UX for the user to enter their name and their issue.  The ticket is created and assigned to the designated group...and the user is then told their place in the queue, then redirected to the portal home screen.  Other uses for this could be to enable users to create a ticket from any page in the portal without having to find and fill out a full catalog item.  The goal of this post is just to share the widget configuration, and there a likely improvements that could be made to the script...there are lots of possible variations (for example: maybe you don't need the queue count part), play around with this and see what works for you!

The widget looks like this:

find_real_file.png

 

After submitting the popup modal looks like this:

find_real_file.png

 

Here's the script:

HTML:

<div class="panel panel-default">
<div class="panel-heading">
<button class="btn btn-default m-b" ng-click="c.click()">
Refresh
</button>
<div>

<!-- User Reference field-->
<div class="form-group">
<label>Search for your name:</label>
<sn-record-picker field="data.user"
table="'sys_user'"
display-field="'name'"
value-field="'sys_id'" search-fields="'user_name,name'"
page-size="100">
</sn-record-picker>
</div>

<!--Description String field-->
<div class="form-group">
<label>Description</label>
<input class="form-control" ng-model="c.data.short_description">
</div>

<!--The Submit button-->
<div class="form-group">
<input class="btn btn-primary btn-block" ng-click="c.addItem()" type="submit" value="Enter your information above and click here to Submit">

<!--popup modal-->
<script type="text/ng-template" id="modalTemplate">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Put whatever text you want here</h4>
</div>
<div class="panel-body wrapper-xl">
Thank you {{c.data.name}}, a ticket has been created on your behalf.<p>
<b><font size='4'>You are number {{c.data.count}} in the queue.</font size></b><p>
You will now be redirected to the Service Portal Home page.
</div>
</div>
</div>
</script>
<!--end popup modal-->
</div>
</div>
</div>

 

Client script:

function($scope, $rootScope, spUtil, $window, $uibModal) {

var c = this;
c.data.user = {value:'',displayValue:''};

//Triggered by the "Refresh" button
c.click = function(){
c.data.user.displayValue='';
c.data.user.value='';
c.data.short_description = '';
}

//Triggered by the "Submit" button
c.addItem = function(){
var user = c.data.user.value;
var desc = c.data.short_description;

//Give alert if both fields are not entered
if(user == '' || user == 'undefined' || user == 'null' || desc == 'null' || desc == '' || desc == 'undefined'){
alert('Please enter your name and a description of your issue before submitting.');
return;
}

//this calls the server script
c.server.update().then(function(response){

//popup modal
c.modalInstance = $uibModal.open({
templateUrl: 'modalTemplate',
scope: $scope
});

//Redirect user after submit
setTimeout(myFunction, 9000);
function myFunction(){
$window.location.href = 'https://dev58504.service-now.com/sp';//enter redirect URL
}
})
}
}

 

Server Script:

(function() {
if(!input)
return;

input.requested_by = gs.userID();

//Look how many tickets are ahead in the queue with whatever query you want
data.count = 0;//sets data object as integer
var gaIncCount = new GlideAggregate('incident');
gaIncCount.addQuery('active','true');
gaIncCount.addQuery('assignment_group','sys_id of the assignment group goes here');
gaIncCount.addQuery('contact_type','walk-in');
gaIncCount.addAggregate('COUNT');
gaIncCount.query();

var count = 0;

if(gaIncCount.next()){
count = gaIncCount.getAggregate('COUNT');
var one = 1;
var queueNumber = +count +one;
data.count = queueNumber;//passes value to HTML script
}

//Look up user's name for the popup
var userName = input.user.value;
data.name = '';//sets data object as string
var userGR = new GlideRecord('sys_user');
userGR.addQuery('sys_id',userName);
userGR.query();
var name = '';
if(userGR.next()){
name = userGR.first_name;
var firstName = name;
data.name = name.toString();//passes value to HTML script
}

//create new record and assign values to fields; you can set whatever fields on the INC you want
var newGr = new GlideRecord('incident');
newGr.initialize();
newGr.short_description = input.short_description;
newGr.caller_id = input.requested_by;
newGr.u_affected_user = input.user.value
newGr.assignment_group = 'your assignment group sys_id goes here';
newGr.contact_type = 'walk-in';
newGr.insert()

})();

Comments
Lucas de Carval
Giga Contributor

This will be super useful for me. Thank you for sharing!

patricklatella
Mega Sage

You're welcome Lucas, glad you found this useful!

patricklatella
Mega Sage

Realizing my HTML for the popup is not correct:

Should be:

 

<!--popup modal-->
<script type="text/ng-template" id="modalTemplate">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Put whatever text you want here</h4>
</div>
<div class="panel-body wrapper-xl">
Thank you {{c.data.name}}, a ticket has been created on your behalf.<p>
<b><font size='4'>You are number {{c.data.count}} in the queue.</font size></b><p>
You will now be redirected to the Service Portal Home page.
</div>
</div>
</div>
</script>
<!--end popup modal-->

Brad Warman
Giga Sage

Thank you so much Patrick. This has helped immensely!

patricklatella
Mega Sage

Glad to hear Brad!

anu58
Tera Contributor

Hi, it is more helpful for me. thanks for uploading....

JP-ODU
Tera Guru

This is amazing! Extremely helpful. I did customize to make Name a string field rather than a reference, as I can't expose names to public.  An issue I'm having, though:

When used as an incognito unauthenticated user, it creates a ticket, but the submitted info all becomes "undefined?" How can I get the string entries to transcribe to the incident, correctly?

Body HTML

<div class="panel panel-{{options.color}} b" >
<div class="panel-heading"> <h2 class="h4 panel-title" id="header-{{data.sysId}}">
    <fa ng-if="::options.glyph.length" name="{{::options.glyph}}" class="m-r-sm" ></fa> {{::options.title}}</h2>
  </div>
  <div class="panel-body">

<!-- User String field-->
<div class="form-group">
<label>Please enter your name:</label>
<input class="form-control" ng-model="c.data.user">
</div>
  
<!--Description String field-->
<div class="form-group">
<label>Please enter the best way to contact you</label>
<input class="form-control" ng-model="c.data.description">
</div>

<!--Description String field-->
<div class="form-group">
<label>Please describe your issue</label>
<input class="form-control" ng-model="c.data.short_description">
</div>

<!--The Submit button-->
<div class="form-group">
<input class="btn btn-primary btn-block" ng-click="c.addItem()" type="submit" value="Enter information above and click to Submit">
</div>

<div>
<button class="btn btn-default m-b" ng-click="c.click()">
Refresh
</button>
<div>
  
<!--popup modal-->
<script type="text/ng-template" id="modalTemplate">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Ticket Created</h4>
</div>
<div class="panel-body wrapper-xl">
Thank you. A ticket has been created on your behalf.<p>
<b><font size='4'>You are number {{c.data.count}} in the queue.</font size></b><p>
You will now be redirected to the Service Portal Home page.
</div>
</div>
</div>
</script>
<!--end popup modal-->
</div>
</div>
</div>

Server Script

(function() {
options.title = options.title || gs.getMessage("Report an Issue without Login");

//Look how many tickets are ahead in the queue with whatever query you want
data.count = 0;//sets data object as integer
var gaIncCount = new GlideAggregate('incident');
gaIncCount.addQuery('active','true');
gaIncCount.addQuery('assignment_group','3dc8e951db3e4f0000f438ff9d961943');
gaIncCount.addQuery('contact_type','Self-service');
gaIncCount.addAggregate('COUNT');
gaIncCount.query();

var count = 0;

if(gaIncCount.next()){
count = gaIncCount.getAggregate('COUNT');
var one = 1;
var queueNumber = +count +one;
data.count = queueNumber;//passes value to HTML script
}

//create new record and assign values to fields; you can set whatever fields on the INC you want
var newGr = new GlideRecord('incident');
newGr.initialize();
newGr.short_description = input.short_description;
newGr.description = input.description + " " + input.user.value;
newGr.assignment_group = '3dc8e951db3e4f0000f438ff9d961943';
newGr.contact_type = 'Self-service';
newGr.insert()

})();

Client Control Script

function($scope, $rootScope, spUtil, $window, $uibModal) {

var c = this;
c.data.opened_by = {value:'',displayValue:''};

//Triggered by the "Refresh" button
c.click = function(){
c.data.user='';
c.data.short_description = '';
c.data.description = '';
}

//Triggered by the "Submit" button
c.addItem = function(){
var user = c.data.user;
var desc = c.data.short_description;
var contact = c.data.description;

//Give alert if all fields are not entered
if(user == '' || user == 'undefined' || user == 'null' || desc == 'null' || desc == '' || desc == 'undefined'|| contact == 'null' | contact == ' ' || contact == 'undefined'){
alert('Please enter your name, contact information, and a description of your issue before submitting.');
return;
}

//this calls the server script
c.server.update().then(function(response){

//popup modal
c.modalInstance = $uibModal.open({
templateUrl: 'modalTemplate',
scope: $scope
});

//Redirect user after submit
setTimeout(myFunction, 9000);
function myFunction(){
$window.location.href = 'https://odudev.service-now.com/sp';//enter redirect URL
}
})
}
}

 

patricklatella
Mega Sage

Hi @JP-ODU ,

to clarify, you're asking how to get the user who is submitting the form to be the Caller, Opened by, and Created by?  And you want to use the value from your "Please enter your name:" string field, correct?  It is typically not reliable to use a string value for the name of a user to find their associated User record since it is possible for multiple people to have the same name.  Asking for their email address could give you a unique identifier so long as it matches to a User record.  You could then do a GlideRecord to get the User record which you can then set to the Caller on the INC.  Let me now if that helps.

JP-ODU
Tera Guru

Sorry, I even confuse myself, sometimes. I gave up on matching to a specific user and was leaving it the tech to match user by name and contact info provided (or contact them for more info). To that end, I want to collect string fields for name and email and dump them into the (long) description field.

 

So short description would be the explanation of the issue and description would hold a name and contact. I seem to have gotten that mostly working, except that something in my script seems to turning the entry of the name to "undefined"

 

In this dummy submission, below, the entry of "undefined" in description was submitted as my name on the Widget

inc.png

JP-ODU
Tera Guru

I found it. Line 27 of my server script had "input.user.data;" where it should just say "input.user." With that corrected, I get contact info + name in the incident description.

 

But I seem to have broken something else? It now submits a good incident, and then a second one ~10 seconds later that has *no* short description and a description of "undefined undefined." I don't see anything in my script to account for that. It'd have to be the server side, right?

 

I have:

 

(function() {
options.title = options.title || gs.getMessage("Report an Issue without Login");

//Look how many tickets are ahead in the queue with whatever query you want
data.count = 0;//sets data object as integer
var gaIncCount = new GlideAggregate('incident');
gaIncCount.addQuery('active','true');
gaIncCount.addQuery('assignment_group','3dc8e951db3e4f0000f438ff9d961943');
gaIncCount.addQuery('contact_type','Self-service');
gaIncCount.addAggregate('COUNT');
gaIncCount.query();

var count = 0;

if(gaIncCount.next()){
count = gaIncCount.getAggregate('COUNT');
var one = 1;
var queueNumber = +count +one;
data.count = queueNumber;//passes value to HTML script
}

//create new record and assign values to fields; you can set whatever fields on the INC you want
var newGr = new GlideRecord('incident');
newGr.initialize();
newGr.caller_id = 'Guest';
newGr.short_description = input.short_description;
newGr.description = input.description + " " + input.user;
newGr.assignment_group = '3dc8e951db3e4f0000f438ff9d961943';
newGr.contact_type = 'Self-service';
newGr.insert()

})();

 

 

patricklatella
Mega Sage

Hi JP-ODU,

hard to see what might be causing that issue...have you tried putting in alerts in the client script and console.logs in the server script to help troubleshoot?

Version history
Last update:
‎07-02-2020 05:08 PM
Updated by: