Highlight VIP users in a colour when @mentioned in a journal field

Daniel A--C
Mega Guru
Mega Guru

I was asked to find a solution to a requirement that I didn't like (and still don't). Nothing new there right?!

"When a user is @mentioned in a journal field, if that user is a VIP, we want their name to be highlighted in red"

 

Customer had been given this as a customisation in an old instance (which I don't have access to) and had become used to having it. Obviously I challenged the requirement in terms of its ultimate business value vs the customisation cost but I also said I'd investigate to find the least impacting way to do it.


Business Rules weren't firing directly on sys_audit or sys_journal_field when I tried it and I wasn't comfortable with how many times it would be fired, even if one was placed there, so I needed another solution. I share the working solution with you below.

 

This solution:
  • avoids the need for regex (always a win!)
  • avoids having to look up the VIP users
  • hinges on the platform's built-in behaviour for @mentions which splits each out into separate records per user in the live_notification table.
  • works well for multiple mentions in a single comment
  • negates the need for manipulating the sys_history_set and sys_history_line auto-generated data (other solutions have tried to tackle this)
  • works for classic forms and workspace views of journal data
  • doesn't require business rules added to each task table, just one BR does it all
  • works anywhere that @mentions is enabled

    Note: this would need to be updated for a multi-language environment due to the BR condition looking for the specific message 'You have been mentioned'.
See images below. Jerrod and Alejandra are VIPs in my instance.
 
Classic form:
DanielAldousC_0-1693514966799.jpeg
Workspace:
DanielAldousC_1-1693514980999.jpeg

 

I hope someone else finds this useful!

 

 

Solution

 

 

Create a new Business Rule
Name: Highlight VIP @ in journal entry
Table: Notification [live_notification]
Active: True
Advanced: True
When: After
Order: 1000
Insert: True
Filter Conditions: Message is 'You have been mentioned' AND User.VIP is True
Script as below:

 

(function executeRule(current, previous /*null when async*/ ) {

    /* Note: 
             - Classic forms activity formatter reads entries from
               sys_history_line which is generated from sys_audit.
             - Workspace activity list reads from sys_journal_field
               entries. So both need to be updated with changes. */

    //get targets
    var targetRecordTable = current.getValue('table');
    var targetRecordId = current.getValue('document');
    var targetFieldName = current.getValue('field_name');
    var targetUserName = '@' + current.user.name;

    //find audit for latest journal entry containing @User's name
    var grAudit = new GlideRecord('sys_audit');
    grAudit.addQuery('tablename', targetRecordTable);
    grAudit.addQuery('documentkey', targetRecordId);
    grAudit.addQuery('fieldname', targetFieldName);
    grAudit.addQuery('oldvalue','JOURNAL FIELD ADDITION');
    grAudit.addQuery('newvalue','CONTAINS', targetUserName);
    grAudit.orderByDesc('sys_created_on');
    grAudit.setLimit(1);
    grAudit.query();
    if (!grAudit.next()) {
        return;
    }

    //define formatting
    var wrapStart = '[code]<span style="color:red">';
    var wrapEnd = '</span>[/code]';

    //get journal content and manipulate it
    var journalContent = grAudit.getValue('newvalue');
    var contentParts = journalContent.split(targetUserName);
    var updatedJournalContent = contentParts.join(wrapStart + targetUserName + wrapEnd);

    //write it back to the audit record
    grAudit.setValue('newvalue', updatedJournalContent);
    grAudit.setUseEngines(false);
    grAudit.setWorkflow(false);
    grAudit.autoSysFields(false);
    grAudit.update();

    //fetch and update equivalent sys_journal_field record
    var grJournal = new GlideRecord('sys_journal_field');
    grJournal.addQuery('name', targetRecordTable);
    grJournal.addQuery('element_id', targetRecordId);
    grJournal.addQuery('element', targetFieldName);
    grJournal.addQuery('value', journalContent);
    grJournal.orderByDesc('sys_created_on');
    grJournal.setLimit(1);
    grJournal.query();
    if (!grJournal.next()) {
        return;
    }

    //write it back to the sys_journal_field record
    grJournal.setValue('value', updatedJournalContent);
    grJournal.setUseEngines(false);
    grJournal.setWorkflow(false);
    grJournal.autoSysFields(false);
    grJournal.update();

})(current, previous);

 

Self-confessed ServiceNow SuperFan and mentor. You'll find me most active on LinkedIn and YouTube with occasional binge spells in the SNDevs slack and discord. I've had many ServiceNow community profiles over the years, each stacked with loads of useful content. Happy hunting! 😉
1 ACCEPTED SOLUTION

Daniel A--C
Mega Guru
Mega Guru
Solution is in the question above.
 
My last word on this. Just going to repeat that whilst the solution is ok, I'd still want this to be challenged and hopefully rejected as an unnecessary, pointless customisation. It would help me sleep at night!
 
A big downside to help the argument against is that if any notifications are sent containing the journal field content, it will show the markup. E.g....
 
"Last note for [code]<span style="color:red">@Jerrod Bennett</span>[/code] and @Abel Tuter to finish"
 
... also any logic that ever relies on the GlideRecord.getJournalEntry() method (some integrations often use this) will return the markup included as well.
Self-confessed ServiceNow SuperFan and mentor. You'll find me most active on LinkedIn and YouTube with occasional binge spells in the SNDevs slack and discord. I've had many ServiceNow community profiles over the years, each stacked with loads of useful content. Happy hunting! 😉

View solution in original post

1 REPLY 1

Daniel A--C
Mega Guru
Mega Guru
Solution is in the question above.
 
My last word on this. Just going to repeat that whilst the solution is ok, I'd still want this to be challenged and hopefully rejected as an unnecessary, pointless customisation. It would help me sleep at night!
 
A big downside to help the argument against is that if any notifications are sent containing the journal field content, it will show the markup. E.g....
 
"Last note for [code]<span style="color:red">@Jerrod Bennett</span>[/code] and @Abel Tuter to finish"
 
... also any logic that ever relies on the GlideRecord.getJournalEntry() method (some integrations often use this) will return the markup included as well.
Self-confessed ServiceNow SuperFan and mentor. You'll find me most active on LinkedIn and YouTube with occasional binge spells in the SNDevs slack and discord. I've had many ServiceNow community profiles over the years, each stacked with loads of useful content. Happy hunting! 😉