Skip to content

Commit 73aa654

Browse files
authored
Merge branch 'main' into hacktoberfest2025-emoji-widget
2 parents 9d8c526 + 2bf7d2a commit 73aa654

File tree

471 files changed

+18245
-109
lines changed

Some content is hidden

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

471 files changed

+18245
-109
lines changed

Check Attachment

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
An onSubmit Client script that checks whether only one file is attached and also file type should be .doc, .pdf or .txt. Otherwise form will not be submitted and required error message will be displayed to user.
2+
3+
Note: Check this property - glide.attachment.extensions

CheckAttachmentFiletypr.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function onSubmit() {
2+
var arr = [];
3+
var extension1 = '.txt';
4+
var extension2 = '.pdf';
5+
var extension3 = '.docx';
6+
var names = this.document.getElementsByClassName('get-attachment ng-binding ng-scope');
7+
for (var i = 0; i < names.length; i++) {
8+
var val = names[i].innerHTML;
9+
arr.push(val.toString());
10+
}
11+
12+
var countRequired = 1;
13+
if (window == null) {
14+
if (this.document.getElementsByClassName('get-attachment').length != countRequired) {
15+
g_form.addErrorMessage('You can add only one attachment');
16+
return false;
17+
}
18+
}
19+
20+
for (var j = 0; j < arr.length; j++) {
21+
if ((arr[j].indexOf(extension1) > -1) || (arr[j].indexOf(extension2) > -1) || (arr[j].indexOf(extension3) > -1)) {
22+
return true;
23+
} else {
24+
g_form.addErrorMessage('Unsupported file format. Please attach files with extensions .txt, .pdf, .doc');
25+
return false;
26+
}
27+
28+
}
29+
30+
}
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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# MRVS - Normalise and Reset Rows on Change
2+
3+
## What this solves
4+
When a controlling variable changes (for example, Environment), existing MRVS rows may no longer be valid. This client script:
5+
- Clears or normalises specific MRVS columns
6+
- Deduplicates rows
7+
- Optionally sorts rows for a cleaner UX
8+
- Works entirely client-side using MRVS JSON
9+
10+
## Where to use
11+
Catalog Item → OnChange client script on your controlling variable.
12+
13+
## How it works
14+
- Reads the MRVS value as JSON via `g_form.getValue('my_mrvs')`
15+
- Applies transforms (clear columns, unique by key, sort)
16+
- Writes back the JSON with `g_form.setValue('my_mrvs', JSON.stringify(rows))`
17+
18+
## Setup
19+
1. Replace `CONTROLLING_VARIABLE` with your variable name.
20+
2. Replace `MY_MRVS` with your MRVS variable name.
21+
3. Adjust `COLUMNS_TO_CLEAR`, `UNIQUE_KEY`, and `SORT_BY` as needed.
22+
23+
## Notes
24+
- To clear the MRVS entirely, set `rows = []` before `setValue`.
25+
- Works with Catalog Client Scripts; no server call required.
26+
27+
## References
28+
- GlideForm API (client): `getValue`, `setValue`, `clearValue`
29+
https://www.servicenow.com/docs/bundle/zurich-api-reference/page/app-store/dev_portal/API_reference/GlideForm/concept/c_GlideFormAPI.html
30+
- Working with MRVS values on the client (community examples)
31+
https://www.servicenow.com/community/developer-articles/accessing-multi-row-variable-set-value-outside-the-multi-row/ta-p/2308876
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
function onChange(control, oldValue, newValue, isLoading) {
2+
if (isLoading) return;
3+
4+
var MRVS_NAME = 'MY_MRVS'; // your MRVS variable name
5+
var COLUMNS_TO_CLEAR = ['env', 'owner']; // MRVS column names to clear
6+
var UNIQUE_KEY = 'hostname'; // MRVS column that should be unique
7+
var SORT_BY = 'hostname'; // MRVS column to sort by
8+
9+
try {
10+
var raw = g_form.getValue(MRVS_NAME);
11+
var rows = raw ? JSON.parse(raw) : [];
12+
if (!Array.isArray(rows)) rows = [];
13+
14+
// Clear specified columns
15+
rows.forEach(function(row) {
16+
COLUMNS_TO_CLEAR.forEach(function(col) { if (row.hasOwnProperty(col)) row[col] = ''; });
17+
});
18+
19+
// Deduplicate by UNIQUE_KEY
20+
if (UNIQUE_KEY) {
21+
var seen = {};
22+
rows = rows.filter(function(row) {
23+
var key = String(row[UNIQUE_KEY] || '').toLowerCase();
24+
if (!key || seen[key]) return false;
25+
seen[key] = true;
26+
return true;
27+
});
28+
}
29+
30+
// Sort (case-insensitive)
31+
if (SORT_BY) {
32+
rows.sort(function(a, b) {
33+
var A = String(a[SORT_BY] || '').toLowerCase();
34+
var B = String(b[SORT_BY] || '').toLowerCase();
35+
if (A < B) return -1;
36+
if (A > B) return 1;
37+
return 0;
38+
});
39+
}
40+
41+
g_form.setValue(MRVS_NAME, JSON.stringify(rows));
42+
} catch (e) {
43+
console.error('MRVS normalise failed', e);
44+
}
45+
}

0 commit comments

Comments
 (0)