Collaboration in Next Experience (Sidebar) - Part 2

Table of Contents

Collaboration in the Next Experience - Programmatic Generation and Usage:

This is the second article of a short run regarding the Next Experience collaboration tool, Sidebar, and my experience with investigating, implementing, and extending the application and related feature sets.

In Part 1, I discussed a lot about the history of Conversational Interfaces for agent to agent (AtA) communication, as well as how the Sidebar capability can be configured. I then took a dive into how it is all put together from a data record perspective within the Now platform.

In this article I’ll discuss the accessible scripted components of the Sidebar application, and then showcase a method of generating a Sidebar conversation programatically and some reasons why.

Lastly, I’ll share an update set containing a utility Script Include and example Record Producer (reusing the chat_queue_entry task extension from the deprecated Connect Support) that empowers you to go about genering conversations for varying audiences.


Scripted Sidebar

Sidebar functionality is closely tied to the Polaris (Next Experience) UI and the associated web component-based UI framework - indeed, a lot of criteria for allowing the visibility of Sidebar validates both the Sidebar enabled and the Polaris enabled system properties. The UX Components I’ve identified the code for so far have been partly minified, but I hope to understand more about these soon and to feed that information back into this series if it would generate value. However, from what I am able to determine, the UI passes back generation and management of the Collaboration records to the instance.

The main associated JavaScript classes in play for Sidebar are:

  • sn_oe_sfs.CollabChatScriptObject*: Primary utility functions for Sidebar creation, management, and system controls
  • sn_oe_sfs.CollabChatRecordTableChoices: Responsible for returning Table Choices for the Table name fields in the application
  • sn_oe_sfs.CollabChatUtils: Contains two functions: for validating chat membership (used by ACL for messages) and read access to the Associated Record (see an associated property in Part 1)
  • global.CollabChatGlobalUtils: Used to perform Global scoped activities: sequencing messages, determining the language of the chat creator, and executing sysauto records

* This Script Object is not publicly visible - however, some sleuthing with Xplore indicates a variety of utility functions, some of which are used in Business rules, and others align to function names referenced in UX Components for Sidebar

Of the above, the CollabChatScriptObject provides the most utility, but is not documented insofar as I have seen. I hope this is something we see change in future.


Bake your own Sidebar

A proud baker of Sidebars - this may be you, after this article

In Part 1, we identified the core Sidebar tables, and towards the end we distilled the 4 tables that store the stub chat generated when using the Discuss UX Action. With this, we have all our ingredients together. But first…

Why not just generate a Sidebar manually?

This is a question I considered while starting this series, and have been developing an answer for throughout.

An initial justification, and perceived differentiator from Connect Chat, was the lack of ‘ad-hoc’ conversation capabilities. This primarily is required in cases where collaboration desired between users who do not use other enterprise collaboration platforms, or are split across federation or organisational lines. This doubled into a Business Continuity use case, during times where other collaboration technologies are experiencing degradation. These cases revolve less around a current Task record, but could take advantage of this same framework.

Additionally, I perceive a lot of merit in augmenting both Change and Incident Management processes, particularly Major Incident Management processes, with a generated chat including pertinent parties to facilitate ease of communication and support pushing to the Activity Stream. Moving to a CSM use case, internal account teams and agents could collaborate about escalations, amongst other things.

There are many more options, but I digress. A recommendation and topic for a future article is to ensure you manage lifecycling your Sidebar conversations, particularly in these cases. But enough about solutioning and service strategy, let us talk code!

My First Sidebar

Knowing the tables in play, we now need to work out the order of creation. The order I ended up with is:

  1. Create Chat (sys_cs_collab_chat)
  2. Create Associated Record (sys_cs_collab_record)
  3. Add your Chat Members (sys_cs_collab_member)
  4. Optional Write a Message (sys_cs_collab_message)

In a Discuss-generated Sidebar, the initial message is a CollabRecordCard sent by the System, followed by a bulk membership message that is also added by the System. In my initial foray where I leveraged the user context, an ACL blocked the creation of a message from a user that is not a member. As such, the creator is added first to send the Record Card.

This could potentially be bypassed by leveraging the system context, and optionally by not generating the record card. I will investigate the former in future versions of my Script Include and update set, while the latter is already supported by my initial version. From a review of the CollabChatScriptObject, this could likely be invoked to produce these outcomes, but I chose to build my own to not depend on undocumented functionality.

Another callout is that my code is developed in the Sidebar scope. This is to avoid cross-scope issues and reconfiguring table permissions.

Time to whip through the code!

1. Creating a Chat

This is the base tier of our Sidebar cake, and is a rather simple record insert:

/**
 * Create root Conversation record
 * @param {string} title - Title of conversation
 * @returns {Object} Object containing conversation Sys ID
 */
createConversation: function(title) {
	var grConversation = new global.GlideQuery('sys_cs_collab_chat')
		.insert({
			state: 'open',
			title: title
		},['sys_id'])
		.get();

	return grConversation;
}

This could be done with GlideRecord too.

2. Creating an associated record

Time for our second tier! The Associated Record and Chat are the two core components our conversations need at minimum to be accessible.

/**
 * Create Conversation's Associated Record reference
 * @param {Object} objRecord - Object containing details of source record
 * @param {string} objRecord.table - Class name of source record
 * @param {string} objRecord.document - Sys ID of source record
 * @param {string} conversationId - Sys ID of conversation record
 * @returns {Object} Object containing Associated record document, table, and Sys ID
 */
createAssociatedRecord: function(objRecord, conversationId) {
	var grAssocRec = new global.GlideQuery('sys_cs_collab_record')
		.insert({
			collab_chat: conversationId,
			table: objRecord.table,
			document: objRecord.document
		},['document','table','sys_id'])
		.get();

	return grAssocRec;
}

From here, our cake is structurally ready, but we have members and messaging (or icing and garnishes) to go.

3. Creating chat members

For the sake of brevity, I’ll replace our code snippet here with a brief run-theough of these steps in pseudo-(baking)-code:

for each member
	check if they are already a member (i.e group memberships)
		while checking membership, look for their Channel User Profile and create if not present
	
	if member, continue to next
	if not member, create member record with Channel User Profile

The ingredients list for that process will be found in the Gist below.

4. Creating Chat Message

Garnish time! Presently I have only implemented support for sending a Collab Record Card, but this function can be leveraged as a template.

/**
 * Create a message containing a CollabRecordCard for Sidebar
 * @param {GlideRecord} objRecord - GlideRecord of the task requiring this message
 * @param {string} conversationId - Sys ID of the sys_cs_collab_chat record
 * @returns {Object} Object containing the Sys ID and status value of the message
 */
createTaskCardMessage: function(objRecord, conversationId) {
	var objPayload = this.RECORD_CARD_JSON;
	objPayload.uiMetadata.data.sys_id = objRecord.getUniqueValue();
	objPayload.uiMetadata.data.table_name = objRecord.getRecordClassName();
		
	var grMessageRec = new global.GlideQuery('sys_cs_collab_message')
		.insert({
			collab_chat: conversationId,
			collab_chat_id: conversationId,
			status: 'received',
			message_type: 'rich',
			payload: JSON.stringify(objPayload)
		},['status','sys_id'])
		.get();

	return grMessageRec;
}

And there we have it, a Sidebar chat ready to serve!


For those that have joined me on the journey to this point, I hope you found this informative - and for those who like to get to the point…

tl;dr: Show me the goods!

As this is my first publicly shared update set, I’m still working on the best ways to share. For now, please reference the below table:

Source SI or US Link
Gist Script Include Link
GitHub Update Set Link
Share Update Set Link

Thank you for reading, and I hope you enjoyed/found value in this article. As always, I am open to feedback and can be reached via Slack, LinkedIn, or email. I look forward to picking back up with you in the next installment.

Posts in this series