Workspace Restriction Banner Shows on Next List Transaction (Using GlideTransaction)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Saturday
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
Saturday
@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.
Raghav
MVP 2023
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Monday
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
Monday
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
Raghav
MVP 2023
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Monday
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.