Skip to main content

Customize Service Console Standard Feeds using Salesforce.com Chatter ConnectApi

Salesforce Service Console feeds gives a holistic view of all the actions happening on cases which your agents can refer for quick summary of all that is happening on that case. It is also useful when the cases are transferred to some other support agent.

There is some limitations in the feed we see on service console which might require you to customize Since not all feed actions are in detail. For example if you see an email feed , it contains whole body of the email , where as a feed on a new case related object created will contain only the record name or auto-number by default. Though you can add a compact layout for the object which will allow you to add more fields in the feed but here we have a limit of 255 character on each field.

Customize Service Console Standard Feeds using Salesforce.com Chatter ConnectApi

Example : Suppose you add these fields in case compact layout then these will appear in the feed where each field e.g Subject can contain maximum of 255 characters
  • Case Number
  • Subject
  • Status
Customize Service Console Standard Feeds using Salesforce.com Chatter ConnectApi

Customize Service Console Standard Feeds using Salesforce.com Chatter ConnectApi

These standard feeds are not writable in trigger hence can't be modified if you want to add more details (more than 255 characters) . In this case an alternate option is to add the feed comment to same feed post where you can add up to 10,000 characters in feed comment.

The way standard feed post is added in Salesforce is asynchronous hence , if you will try to access the standard feed in After trigger of the object then the following query will return no rows.

SELECT Id, ParentId ,Type, Body FROM <Your Object>__Feed WHERE ParentId ='<Your Object>' 
ORDER BY CreatedDate DESC

The only way to access the Feed object is to run this query in a future call. Here is the sample code for adding feed comment with details to system generated feed.

<Your Object> Trigger Code

trigger afterinsert_<Your Object> on <Your Object> (after insert) {
       
         Set<Id> ObjectIds = new Set<Id>();
         for(<Your Object> obj: Trigger.New){          
            ObjectIds .add(obj.Id); 
         }
           
         if(ObjectIds !=null && !ObjectIds .isEmpty() ){      
            <Your Object>_TriggerHelperCalss.Add_FeedItemComment(ObjectIds );
         }
}

<Your Object> TriggerHelper Class Code

public class <Your Object>_TriggerHelper{
    @future
    public static void Add_FeedItemComment(Set<Id> ObjectIdSet){
        
        Map<Id, <Your Object>> feedMap = new Map<Id, <Your Object>>([Select id ,Body__c 
                                                        from <Your Object> 
                                                        where id IN :ObjectIdSet]);
        String communityId = null;      
    
        for(<Your Object>__Feed feed : [SELECT Id, ParentId , Type, Body 
                                          FROM <Your Object>__Feed 
                                          WHERE ParentId IN :ObjectIdSet ORDER BY CreatedDate DESC] ){  
                                    
            String targetUserOrGroupOrRecordId  = feed.Id; 
            if(feedMap!=null && feedMap.containsKey(feed.ParentId)){    
                ConnectApi.CommentInput input = addDetailComment(feedMap.get(feed.ParentId));          
                ConnectApi.Comment comment = ConnectApi.ChatterFeeds.postCommentToFeedElement(communityId, targetUserOrGroupOrRecordId, input , null );
            }
        } 
    }
private static ConnectApi.CommentInput addDetailComment(<Your Object> object){ 
        
        ConnectApi.CommentInput input = new ConnectApi.CommentInput();
        ConnectApi.MessageBodyInput messageInput = new ConnectApi.MessageBodyInput();
        messageInput.messageSegments = new List<ConnectApi.MessageSegmentInput>();
       
    ConnectApi.MarkupBeginSegmentInput  beginSegment = new ConnectApi.MarkupBeginSegmentInput();
        beginSegment.markupType = ConnectApi.MarkupType.Bold;
        messageInput.messageSegments.add(beginSegment);
        ConnectApi.TextSegmentInput textSegment = new ConnectApi.TextSegmentInput();
        textSegment.text = 'Detail Body';
        messageInput.messageSegments.add(textSegment);        
ConnectApi.MarkupEndSegmentInput endSegment = new ConnectApi.MarkupEndSegmentInput();
        endSegment.markupType = ConnectApi.MarkupType.Bold;
        messageInput.messageSegments.add(endSegment); 
input.body = messageInput;
        return input;
    }
}
}

Comments

Popular posts from this blog

Einstein Bot user authentication

Using Bot for data manipulation use case in your company requires need of implementing some extra security layer to make it spoof proof. One of exciting salesforce feature we have is the well known Einstein Bot which many companies have implemented. I am going to cover detail step-by-step implementation of User validation use case using encrypted token. STEP-1: Create a Site & Site User go to setup > Sites & Domains > Sites Create a Site and make your user as "Site Contact". This is a prerequisites for live agent or Embedded Service setup. STEP-2 : Create a Embedded Service(formerly snap-ins) go to Service setup > Embedded Service Create a new Embedded Service Deployment record and copy the embedded service code snipped generated in a notepad. STEP-3  : Create a Visualforce page to test the chatbot (it will simulate the actual web portal which is going to consume the embedded service snipped.) BotController.apxc public class BotControlle...

Dynamically populate lightning:combobox

In order to dynamically populate values in lightning:combobox using javascript we can create a list variable and push the values. We also require the values like ids associated to the particular option for back-end logic. For example  : If we want to show the list of contacts using lightning:combobox component where the option should display the contact name but the value should be the contact id which will be used for back-end logic For this we can create a temporary Map variable in our lightning component and set the value and label parameters of the lightning:combobox. Here is the code for this component Combo.app <aura:application extends="force:slds" access="global" description="Lightning Combo Demo"> <c:Combo_Cmpt/> </aura:application> Combo_Cmpt.cmp <aura:component implements="flexipage:availableForAllPageTypes" access="global" controller="ComboController"> <!-- ...

Use of wrapper class in lightning:datatable

As you guys know the wrapper class concept in visualforce pages , we generally use it to create a data-table which fetches data from different objects or if we want to redirect user to some other page on click of a link as one of the column of data-table.        For example we want a column "Account Name" on the data-table which is a link and once user clicks it should redirect respective account record. Or , suppose we want to display a column with some images or icons as a visual indicator Or what not. These requirements require us to use a wrapper on the lighting data-table (lightning:datatable) I am going to use my previous account search example ( Account Search Lightning Component ) and explain the use of wrapper. AccountSearchWrapper.app <aura:application extends="force:slds" access="global" >     <c:AccountSearchWrapper /> </aura:application> AccountSearchWrapper.cmp <aura:component controller="...