Skip to content

Commit 2528aca

Browse files
Merge branch 'ServiceNowDevProgram:main' into feature/prevent-recursive-br
2 parents a8f0795 + b1b1b19 commit 2528aca

File tree

174 files changed

+6053
-33
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+6053
-33
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
var GetRecentRequestValues = Class.create();
2+
GetRecentRequestValues.prototype = Object.extendsObject(AbstractAjaxProcessor, {
3+
getValues: function() {
4+
var userID = this.getParameter('sysparm_user');
5+
var itemID = this.getParameter('sysparm_item');
6+
var result = { found: false, values: {} };
7+
8+
var gr = new GlideRecord('sc_req_item');
9+
gr.addQuery('requested_for', userID);
10+
gr.addQuery('cat_item', itemID);
11+
gr.orderByDesc('sys_created_on');
12+
gr.setLimit(1);
13+
gr.query();
14+
15+
if (gr.next()) {
16+
result.found = true;
17+
18+
19+
var vars = gr.variables;
20+
result.values = {
21+
'requested_for': vars.requested_for + '',
22+
'location': vars.location + '',
23+
'department': vars.department + ''
24+
};
25+
}
26+
27+
return JSON.stringify(result);
28+
}
29+
});
30+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
function onLoad() {
2+
var user = g_user.userID;
3+
var itemID = g_form.getUniqueValue();
4+
5+
var ga = new GlideAjax('GetRecentRequestValues');
6+
ga.addParam('sysparm_name', 'getValues');
7+
ga.addParam('sysparm_user', user);
8+
ga.addParam('sysparm_item', itemID);
9+
ga.getXMLAnswer(function(response) {
10+
var data = JSON.parse(response);
11+
if (data && data.found) {
12+
var confirmFill = confirm("We found a similar request. Do you want to autofill fields?");
13+
if (confirmFill) {
14+
for (var field in data.values) {
15+
if (g_form.getControl(field)) {
16+
g_form.setValue(field, data.values[field]);
17+
console.log("Set " + field + " to " + data.values[field]);
18+
} else {
19+
console.log("Field not found: " + field);
20+
}
21+
}
22+
}
23+
} else {
24+
console.log("No previous request found.");
25+
}
26+
});
27+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Recent Request Autofill for ServiceNow Catalog.it automatically offers to fill in fields based on the user's most recent similar request.
2+
Features
3+
- Detects previous requests for the same catalog item
4+
- Prompts user to reuse values from their last submission
5+
- Autofills fields like location, department, and justification
6+
7+
<img width="878" height="395" alt="image" src="https://github.com/user-attachments/assets/33ceabf5-2bbc-43e3-8792-f1f9a99699d2" />
8+
9+
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var SentimentAnalyzer = Class.create();
2+
SentimentAnalyzer.prototype = Object.extendsObject(AbstractAjaxProcessor, {
3+
getSentiment: function() {
4+
var text = (this.getParameter('sysparm_text') || '').toLowerCase();
5+
var positive = ['thanks', 'great', 'resolved', 'appreciate'];
6+
var negative = ['issue', 'error', 'not working', 'fail', 'problem'];
7+
8+
var score = 0;
9+
positive.forEach(function(word) { if (text.includes(word)) score++; });
10+
negative.forEach(function(word) { if (text.includes(word)) score--; });
11+
12+
if (score > 0) return 'Positive';
13+
if (score < 0) return 'Negative';
14+
return 'Neutral';
15+
}
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function onChange(control, oldValue, newValue, isLoading) {
2+
if (isLoading || !newValue) return;
3+
4+
var ga = new GlideAjax('SentimentAnalyzer');
5+
ga.addParam('sysparm_name', 'getSentiment');
6+
ga.addParam('sysparm_text', newValue);
7+
ga.getXMLAnswer(function(sentiment) {
8+
g_form.addInfoMessage('Sentiment: ' + sentiment);
9+
g_form.setValue('u_sentiment', sentiment);
10+
});
11+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Incident Sentiment Detector (No AI, Pure JavaScript)
2+
3+
A lightweight ServiceNow utility that detects sentiment (Positive / Negative / Neutral) of an Incident’s short description or comments using simple keyword matching — no AI APIs or external libraries required.
4+
5+
Useful for support teams to auto-tag sentiment and analyze user frustration or satisfaction trends without expensive integrations.
6+
7+
🚀 Features
8+
9+
✅ Detects sentiment directly inside ServiceNow ✅ Works without external APIs or ML models ✅ Instant classification on form update ✅ Adds detected sentiment to a custom field (u_sentiment) ✅ Simple to extend — just add more positive/negative keywords
10+
11+
🧩 Architecture Overview
12+
13+
The solution consists of two main scripts:
14+
15+
Component Type Purpose SentimentAnalyzer Script Include Processes text and returns sentiment Client Script (onChange) Client Script Calls SentimentAnalyzer via GlideAjax on short description change 🧱 Setup Instructions 1️⃣ Create Custom Field
16+
17+
Create a new field on the Incident table:
18+
19+
Name: u_sentiment
20+
21+
Type: Choice
22+
23+
Choices: Positive, Neutral, Negative
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
function onChange(control, oldValue, newValue, isLoading) {
2+
if (isLoading) {
3+
return;
4+
}
5+
6+
var maxChars = 100;//count of charaters
7+
var currentLength = newValue.length;
8+
9+
// Clear previous messages
10+
g_form.clearMessages();
11+
12+
// Show info message
13+
g_form.addInfoMessage('Character count: ' + currentLength + ' / ' + maxChars);
14+
15+
if (currentLength > maxChars) {
16+
// Show error message
17+
g_form.addErrorMessage('Character limit exceeded! Please shorten your text.');
18+
g_form.showFieldMsg('short_description', 'Too many characters!', 'error');
19+
20+
// Make field mandatory to block submission
21+
g_form.setMandatory('short_description', true);
22+
} else {
23+
// Remove mandatory if valid
24+
g_form.setMandatory('short_description', false);
25+
}
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This onChange Catalog Client Script displays the current character count for a text field and enforces a maximum limit by showing error messages and making the field mandatory to prevent form submission when exceeded.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
**Set and Lock Variable by Group**
2+
3+
This solution provides a secure and dynamic way to control data entry on a Service Catalog form based on the user's group membership. It is typically used to pre-fill and lock certain justification or approval bypass fields for authorized users (like managers or executive staff), improving their efficiency while maintaining an accurate audit trail.
4+
5+
This functionality requires a combined Client-side (Catalog Client Script) and Server-side (Script Include) approach to ensure the group check is done securely.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// onload Catalog Client Script with Catalog Name
2+
function onLoad() {
3+
var variableName = 'bypass_approval_reason';
4+
var targetGroupName = 'ServiceNow Support'; // The group authorized to skip this step
5+
var ga = new GlideAjax('UserUtils');
6+
ga.addParam('sysparm_name', 'isMemberOf');
7+
ga.addParam('sysparm_group_name', targetGroupName);
8+
ga.getXMLAnswer(checkAndLockVariable);
9+
function checkAndLockVariable(response) {
10+
var isMember = response;
11+
if (isMember == 'true') {
12+
var message = 'Value set and locked due to your ' + targetGroupName + ' membership.';
13+
var setValue = 'Bypassed by authorized ' + targetGroupName + ' member.';
14+
g_form.setValue(variableName, setValue);
15+
g_form.setReadOnly(variableName, true);
16+
g_form.showFieldMsg(variableName, message, 'info');
17+
} else {
18+
g_form.setReadOnly(variableName, false);
19+
}
20+
}
21+
}
22+
23+
//Script Include
24+
var UserUtils = Class.create();
25+
UserUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
26+
isMemberOf: function() {
27+
var groupName = this.getParameter('sysparm_group_name');
28+
var isMember = gs.getUser().isMemberOf(groupName);
29+
return isMember.toString();
30+
},
31+
32+
type: 'UserUtils'
33+
});

0 commit comments

Comments
 (0)