Workspace Restriction Banner Shows on Next List Transaction (Using GlideTransaction)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-30-2025 11:25 AM
Hi All,
I have an existing functionality in classic UI which displays a UI message in list view when there are restricted records that an itil user should not see.
Problem:
In classic UI, it is working fine.
In workspace list view I am facing the below issue:
If I open Incident > Assigned to me list (which has restricted records), the restriction UI message does not show immediately. But when I switch to another list tab (e.g., Incident > Opened by me, which has no restriction), the restriction message from the previous list pops up.
It seems like the message is always getting displayed on the next transaction/tab click, instead of the current list I am viewing.
Scripts that I have used
Script Include: c_RestrictedUtils (non-client callable)
var c_RestrictedUtils = Class.create();
c_RestrictedUtils.prototype = {
initialize: function() {
this.groupNamesToContact = '';
this.isSingleRecord = false;
this.amountRestricted = 0;
this.allRecordsRestricted = false;
},
hasRestrictions: function(grListOrRecord, queryRP) {
var showMessage = false;
var isGroupedList = false;
var listAmount = 0;
var listQuery = '';
var tableName = '';
this.groupNamesToContact = ': ';
if (typeof grListOrRecord == 'object' && typeof queryRP == 'object' && gs.getUser().hasRole('itil')) {
isGroupedList = (grListOrRecord.getRowNumber() == -1);
tableName = grListOrRecord.getTableName();
listAmount = grListOrRecord.getRowCount(); // either the record amount or the grouped amount
if (queryRP != null) { // only for Lists, null for Forms
listQuery = queryRP.toString();
}
switch (true) {
case (listAmount == 0):
// no additional actions
showMessage = false;
break;
case (listAmount == 1 && !isGroupedList):
// non grouped list with one record or form of the record
this.isSingleRecord = true;
showMessage = this._checkCanReadOneRecord(grListOrRecord);
break;
case (listAmount > 1 && !isGroupedList):
if (this._checkAccess(listAmount)) {
// 100 or less loop through records to determine access
showMessage = this._checkCanReadMultipleRecords(tableName, listQuery);
this.allRecordsRestricted = (listAmount == this.amountRestricted);
}
break;
case (isGroupedList):
// list is grouped, need actual amount of records
listQuery = this._cleanQuery(listQuery);
if (listQuery != '') {
recordAmount = this._getRealAmount(tableName, listQuery);
if (this._checkAccess(recordAmount)) {
showMessage = this._checkCanReadMultipleRecords(tableName, listQuery);
this.allRecordsRestricted = (recordAmount == this.amountRestricted);
}
}
break;
default:
showMessage = false;
}
}
return showMessage;
},
bannerMessage: function() {
var msgParameters = [];
this.groupNamesToContact = this.groupNamesToContact.replace(": , ", ": ");
msgParameters.push(this.groupNamesToContact);
msgParameters.push(this.amountRestricted.toString());
var returnMessage = '';
switch (true) {
case (this.isSingleRecord):
returnMessage = gs.getMessage('ui_action_restricted_ticket_message_single', msgParameters);
break;
case (this.allRecordsRestricted):
returnMessage = gs.getMessage('ui_action_restricted_ticket_message_multiple_all', msgParameters);
break;
default:
returnMessage = gs.getMessage('ui_action_restricted_ticket_message_multiple', msgParameters);
}
return returnMessage;
},
_checkCanReadOneRecord: function(grTicket) {
var isRestricted = false;
var grpName = grTicket.assignment_group.getDisplayValue();
if (!grTicket.canRead()) {
isRestricted = true;
this.isSingleRecord = true;
this.groupNamesToContact += grpName;
}
return isRestricted;
},
_checkCanReadMultipleRecords: function(tableName, encodedQuery) {
var hasRestricted = false;
var grRecords = new GlideRecord(tableName);
grRecords.addEncodedQuery(encodedQuery);
grRecords.query();
while (grRecords.next()) {
if (!grRecords.canRead()) {
this.amountRestricted++;
var grpName = grRecords.assignment_group.getDisplayValue();
if (!this.groupNamesToContact.includes(grpName)) {
this.groupNamesToContact += ', ' + grpName;
}
}
}
hasRestricted = (this.amountRestricted != 0);
return hasRestricted;
},
_getRealAmount: function(tableName, encodedListQuery) {
var recordCount = 0;
gaRecords = new GlideAggregate(tableName);
gaRecords.addAggregate('COUNT');
gaRecords.addEncodedQuery(encodedListQuery);
gaRecords.query();
if (gaRecords.next()) {
recordCount = gaRecords.getAggregate('COUNT');
}
return recordCount;
},
_cleanQuery: function(queryString) {
var qry = '';
if (queryString) {
qry = queryString;
if (qry.includes('^ORDERBY')) {
qry = qry.substring(0, qry.indexOf('^ORDERBY'));
}
if (qry.includes('ORDERBY')) {
qry = qry.substring(0, qry.indexOf('ORDERBY'));
}
if (qry.includes('^GROUPBY')) {
qry = qry.substring(0, qry.indexOf('^GROUPBY'));
}
if (qry.includes('GROUPBY')) {
qry = qry.substring(0, qry.indexOf('GROUPBY'));
}
}
return qry;
},
_checkAccess: function(amount) {
var continueCheck = false;
if (amount) {
switch (true) {
case (amount == 0):
continueCheck = false;
break;
case (amount == 1):
this.isSingleRecord = true;
continueCheck = true;
break;
case (amount <= 100):
this.isSingleRecord = false;
continueCheck = true;
break;
default:
// no action needed
}
}
return continueCheck;
},
type: 'c_RestrictedUtils'
};UI Action Condition
var msgUtil = new c_RestrictedUtils();
if (!RP.isRelatedList() && RP.isInteractive() && msgUtil.hasRestrictions(current ,RP.getEncodedQuery()) && gs.getUser().hasRole('itil')) {
var msg = msgUtil.bannerMessage();
gs.addInfoMessage(msg);
}
This works as expected in classic UI.
Replicating in Workspace
I created a wrapper Script Include: RestrictedUtilsDLA (non-client callable), which calls the same logic of c_RestrictedUtils and does URL check:
var RestrictedUtilsDLA = Class.create();
RestrictedUtilsDLA.prototype = {
initialize: function() {
// No initialization needed for now
},
evaluateRestriction: function(current) {
if (!gs.getSession().isInteractive()) {
gs.info('RestrictedUtilsDLA: Non-interactive session, skipping restriction.');
}
gs.clearInfoMessages();
var transaction = GlideTransaction.get();
var referer = '';
if (transaction && transaction.getRequest()) {
referer = transaction.getRequest().getHeader('Referer') || '';
gs.info('RestrictedUtilsDLA: Current transaction referer header: ' + referer);
gs.getSession().putProperty('referer', referer);
} else {
referer = gs.getSession().getProperty('referer') || '';
gs.info('RestrictedUtilsDLA: Retrieved referer from session property: ' + referer);
}
var listIdMatch = referer.match(/list-id\/([a-z0-9]+)/i);
var list_id = listIdMatch ? listIdMatch[1] : '';
if (!list_id) {
gs.info('RestrictedUtilsDLA: No list_id found in referer.');
return false;
}
var grList = new GlideRecord('sys_ux_list');
if (!grList.get(list_id)) {
gs.info('RestrictedUtilsDLA: sys_ux_list record not found for list_id: ' + list_id);
return false;
}
var listTable = grList.getValue('table');
gs.info("RestrictedUtilsDLA: list ID : " + list_id + " | table : " + listTable);
if (listTable !== current.getTableName()) {
gs.info(
'RestrictedUtilsDLA: List table "' + listTable +
'" does not match current table "' + current.getTableName() + '", skipping restriction.'
);
return false;
}
var encodedCondition = grList.getValue('condition') || '';
gs.info('RestrictedUtilsDLA: List encoded condition: ' + encodedCondition);
var grCheck = new GlideRecord(listTable);
if (encodedCondition) {
grCheck.addEncodedQuery(encodedCondition);
}
grCheck.query();
var util = new c_RestrictedUtils();
util.groupNamesToContact = '';
util.isSingleRecord = false;
util.amountRestricted = 0;
util.allRecordsRestricted = false;
var restricted = util.hasRestrictions(grCheck, encodedCondition);
gs.info('RestrictedUtilsDLA: hasRestrictions result: ' + restricted);
if (restricted && gs.getUser().hasRole('itil')) {
var bannerMsg = util.bannerMessage();
gs.info('RestrictedUtilsDLA: Adding banner message: ' + bannerMsg);
gs.addInfoMessage('[BR_TABLE:' + current.getTableName() + '] ' + bannerMsg);
return true;
}
return false;
},
type: 'RestrictedUtilsDLA'
};Declarative Action – List Action
In the Advanced condition script of the Declarative Action, I added:
new global.RestrictedUtilsDLA().evaluateRestriction(current) && false;
Issue:
With this setup, the UI message does appear, but the issue is that the response is delayed.
If I open Incident > Assigned to me list (which has restricted records), the restriction UI message does not show immediately. But when I switch to another list tab (e.g., Incident > Opened by me, which has no restriction), the restriction message from the previous list pops up.
It seems like the message is always getting displayed on the next transaction/tab click, instead of the current list I am viewing.
Has anyone faced this delayed UI message issue in Workspace declarative actions?
Is there a way to make the restriction message display immediately for the current list transaction?
Any suggestions are appreciated.
Thanks in advance!
- Labels:
-
CSM Configurable Workspace
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-30-2025 11:48 PM
@Sruthi2512 Any reason you have added it in script condition and not server script section?
I believe you need to call it in server script and see if it shows any error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-01-2025 02:53 AM
Hi @RaghavSh, If I add the script in server script condition, I am getting the button in workspace but when I added it as script condition, I was able to get the banner not the button.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-01-2025 03:48 AM
The documentation says, the script to be executed has to be in "server script":
Refer : https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB2008082
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-01-2025 04:32 AM
But in my case, if I use it in server script section, I am getting a button
If I use it in script condition, I am getting the message banner alone [which is required]
Problem is:
With this setup, the UI message does appear, but the issue is that the response is delayed.
