Workspace Restriction Banner Shows on Next List Transaction (Using GlideTransaction)

Sruthi2512
Tera Contributor

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.

Sruthi2512_0-1756578126440.png

 

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);
}

Sruthi2512_1-1756578157091.png

 

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;

Sruthi2512_2-1756578177885.png

 

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!

5 REPLIES 5

RaghavSh
Kilo Patron

@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

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.

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

But in my case, if I use it in server script section, I am getting a button

Sruthi2512_0-1756725984655.png


If I use it in script condition, I am getting the message banner alone [which is required]

Sruthi2512_1-1756726150529.png


Problem is:
With this setup, the UI message does appear, but the issue is that the response is delayed.