March 31, 2021

Popover Dialog using Aura Lightning Component

Primary component:
<aura:component implements="force:appHostable" >
    <aura:attribute name="showBool" type="boolean" default="false"/>
    <lightning:card>
        <a onmouseover="{!c.show}">View</a><br/>
        <aura:if isTrue="{!v.showBool}">
            <section aria-describedby="dialog-body-id-98" aria-labelledby="dialog-heading-id-103" class="slds-popover slds-popover_pane slds-nubbin_top-left" role="dialog">
                <lightning:button class="slds-button slds-button_icon slds-button_icon-small slds-float_right slds-popover__close" title="Close dialog" onclick="{!c.hide}">
                    Close
                </lightning:button>
                <header class="slds-popover__header">
                    <h2 class="slds-text-heading_small" id="dialog-heading-id-103">Header Title</h2>
                </header>
                <div class="slds-popover__body slds-popover__body_small" id="dialog-body-id-98">
                    <c:contentComponent/>
                </div>
                <footer class="slds-popover__footer">
                    <p>Footer Item</p>
                </footer>
            </section>
        </aura:if>
    </lightning:card>
</aura:component>

Primary Component Controller:
({
    
show : function( component, event, helper ) {
        
        component.set( "v.showBool", true );
}, 
    
    hide : function( component, event, helper ) {
        component.set( "v.showBool", false );
}
    
})

contentComponent:
<aura:component >
    <lightning:card>
        <aura:set attribute="title">
            <lightning:icon iconName="standard:knowledge" size="small"/>
            Sample Title
        </aura:set>
        <div class="slds-text-longform">
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
        </div>
    </lightning:card>
</aura:component>

Output:


How to create Messaging End User using Apex in Salesforce?

Sample Code:
MessagingEndUser objMsgUser = new MessagingEndUser();
objMsgUser.ContactId = '<ContactId>';
objMsgUser.MessagingChannelId = '<Messaging Channel Id>';
objMsgUser.MessagingConsentStatus = 'ImplicitlyOptedIn';
objMsgUser.MessageType = 'Text';//For SMS Channel
/*The phone number or Facebook page ID associated with this Messaging end user.*/
objMsgUser.MessagingPlatformKey = '<Platform Key>';
objMsgUser.Name = '<Name>';
insert objMsgUser; 
 
To get the Messaging Channel Id, you can use the below SOQL.
SELECT Id, DeveloperName FROM MessagingChannel 

How to add Knowledge widget in Salesforce Lightning Console?

1. In the Lightning Record Page, use the Knowledge component.


2. When you open a Case record, it will display the relevant Articles.

3. Attach Article can be use to attach the Article to the Case.

4. Once the Articles are attached, it will be available in Articles related list to the Case record.


March 30, 2021

How to create External object and relate it to Salesforce Object using Heroku?

1. Create a Heroku App.

2. Go to Resource Tab. Install Heroku Connect and Heroku Postgres add-ons.

3. Create a table in Heroku Postgres. Make sure to create a column to relate it to Salesforce object. In my example, I have used Account_Number column.

4. Create some data in Heroku Postgres table.

5. In Heroku Connect, go to External Objects tab. Select the table created in Step 3 under Data Sources.

6. Click Show Credentials to get the username and password.

7. Create External Data Source in Salesforce.


8. Click Validate and Sync.

9. Select the table so that it creates External object in Salesforce.

10. Create an External Id field in the object which is going to be the parent. In my Case, I have used Account object as parent Account Number field as External Id field.


11. Update the external object. Don't update API Name and Table Name.


12. Make the Account Number column as Indirect Lookup field to Account object. Don't update API Name and External Column Name.


13. Update the labels of the other fields. Don't update the API Names.


Sample Records:



Using FindOrCreate from Salesforce Chat to link Account to Chat Transcript

Sample Code:
/* Custom detail is to show it to the agent before accepting the Chat and for findOrCreate */
liveagent.addCustomDetail( "Company", "Disney" );
liveagent.addCustomDetail( "First Name", "Mickey" );
liveagent.addCustomDetail( "Last Name", "Mouse" );
liveagent.addCustomDetail( "Email", "mickey.mouse@test.com" );
liveagent.addCustomDetail( "Case Subject", "Test" );
liveagent.addCustomDetail( "Case Status", "New" );

/* FindOrCreate Account and linking to Chat Transcript */
liveagent.findOrCreate( "Account" ).map( "Name", "Company", true, true, true ).saveToTranscript( "AccountId" ).showOnCreate();
 
/*
    This does a non-exact search on cases by the value of the "Case Subject" custom detail.
    If no results are found, it will create a case and set the case's subject and status
    The case that's found or created will be associated to the chat and the case will open in
    the Console for the agent when the chat is accepted
*/
liveagent.findOrCreate( "Case" ).map( "Subject", "Case Subject", true, false, true ).map( "Status", "Case Status", false, false, true ).saveToTranscript( "CaseId" ).showOnCreate();
 
/*
    This searches for a contact whose first name, last name ane email exactly match the values in the custom details for First Name, Last Name and Email.
    If no results are found, it will create a new contact and set it's first name, last name, and Email to the values in the custom details
    
*/
liveagent.findOrCreate( "Contact" ).map( "FirstName", "First Name", true, true, true ).map( "LastName", "Last Name", true, true, true ).map( "Email", "Email", true, true, true );
 
/* The contact that's found or created will be saved or associated to the chat transcript.
The contact will be opened for the agent in the Console and the case is linked to the contact record */
liveagent.findOrCreate( "Contact" ).saveToTranscript( "ContactId" ).showOnCreate().linkToEntity( "Case", "ContactId" );

 
Output:


Using FindOrCreate from Salesforce Chat

Sample code:
        /* Custom detail is to show it to the agent before accepting the Chat and for findOrCreate */
        liveagent.addCustomDetail( "First Name", "Mickey" );
        liveagent.addCustomDetail( "Last Name", "Mouse" );
        liveagent.addCustomDetail( "Email", "mickey.mouse@test.com" );
        liveagent.addCustomDetail( "Case Subject", "Test" );
        liveagent.addCustomDetail( "Case Status", "New" );
         
        /*
            This does a non-exact search on cases by the value of the "Case Subject" custom detail.
            If no results are found, it will create a case and set the case's subject and status
            The case that's found or created will be associated to the chat and the case will open in
            the Console for the agent when the chat is accepted
        */
        liveagent.findOrCreate( "Case" ).map( "Subject", "Case Subject", true, false, true ).map( "Status", "Case Status", false, false, true ).saveToTranscript( "CaseId" ).showOnCreate();
         
        /*
            This searches for a contact whose first name, last name ane email exactly match the values in the custom details for First Name, Last Name and Email.
            If no results are found, it will create a new contact and set it's first name, last name, and Email to the values in the custom details
           
        */
        liveagent.findOrCreate( "Contact" ).map( "FirstName", "First Name", true, true, true ).map( "LastName", "Last Name", true, true, true ).map( "Email", "Email", true, true, true );
         
        /* The contact that's found or created will be saved or associated to the chat transcript.
        The contact will be opened for the agent in the Console and the case is linked to the contact record */
        liveagent.findOrCreate( "Contact" ).saveToTranscript( "ContactId" ).showOnCreate().linkToEntity( "Case", "ContactId" );
 
Code should be placed inside the Chat Button Code:
 

Output:



March 29, 2021

Agent Photo/Agent Avatar in Salesforce Embedded Service Chat

Agent Avatar image in Static Resource:
Store the Avatar image in Salesforce Static Resource.
 
 
Sample Code Change:
embedded_svc.settings.avatarImgURL = '<URL of the Avatar Image>';
 
Output with Agent Avatar:
 

How to show Queue Position in Salesforce Chat?

Visualforce components can be used to customize the appearance and behavior of chat windows. Check the below example

Visualforce Page:
<apex:page showHeader="false">
    <style>
        body { overflow: hidden; width: 100%; height: 100%; padding: 0; margin: 0 }
        #waitingMessage {
            height: 50%;
            width: 50%;
            vertical-align: middle;
            text-align: center;
            display: none;
        }
        #liveAgentClientChat.liveAgentStateWaiting #waitingMessage { display: table; }
        #liveAgentSaveButton, #liveAgentEndButton { z-index: 2; }
        .liveAgentChatInput {
            height: 25px;
            border-width: 1px;
            border-style: solid;
            border-color: #000;
            padding: 2px 0 2px 4px;
            background: #fff;
            display: block;
            width: 99%;
        }
        .liveAgentSendButton {
            display: block;
            width: 60px;
            height: 31px;
            padding: 0 0 3px;
            position: absolute;
            top: 0;
            right: -67px;
        }
        #liveAgentChatLog {
            width: auto;
            height: auto;
            top: 0px;
            position: absolute;
            overflow-y: auto;
            left: 0;
            right: 0;
            bottom: 0;
        }
    </style>
    <div style="top: 0; left: 0; right: 0; bottom: 0; position: absolute;">
        <liveAgent:clientChat >
        <liveAgent:clientChatSaveButton />
        <liveAgent:clientChatEndButton />
        <div style="top: 25px; left: 5px; right: 5px; bottom: 5px; position: absolute; z-index:0;">
            <liveAgent:clientChatAlertMessage />
            <liveAgent:clientChatStatusMessage />
            <table id="waitingMessage" cellpadding="0" cellspacing="0">
                <tr>
                    <td colspan="2">
                        Please wait while you are connected to an available agent.
                    </td>
                </tr>
                <tr>
                    <td>Your current Queue position is</td>
                    <td><liveAgent:clientChatQueuePosition /></td>
                </tr>
            </table>
            <div style="top: 0; right: 0; bottom: 41px; left: 0; padding: 0; position: absolute;word-wrap: break-word; z-index: 0;">
                <liveAgent:clientChatLog />
            </div>
            <div style="position: absolute; height: auto; right: 0; bottom: 0; left: 0; margin-right:67px;">
                <liveagent:clientChatInput /><liveAgent:clientChatSendButton />
            </div>
        </div>
        </liveAgent:clientChat>
    </div>
</apex:page>

Use the Visualforce page in the Custom Chat Page in Chat Button.
 
 
Additional Resources:

 
Output:
 

March 27, 2021

JavaScript Closure

In JavaScript, closures are created every time a function is created, at function creation time.
 
Closure means that an inner function always have access to the variables and parameters of its outer function even after the outer function has returned. This is not common with other programming languages.

Sample Code:
function simpleFunc() {

  let strName = 'Magulan';
 
  function showName() {
 
    alert( strName);
    
  }
 
  return showName;
 
}


var myFunc = simpleFunc();
myFunc();//alerts Magulan which is outer function variable.


It shouldn't alert Magulan since the strName is a variable from outer function. It is alerting because of closures. A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.

Another Sample Code:
function add( x ) {

  return function( y ) {
 
    return x + y;
    
  };
 
}

let obj = add( 2 );
alert( obj( 3 ) );//alerts 5

March 26, 2021

How to end Messaging Session from Salesforce Einstein Bot?

1. Create a Dialog or use the existing End Chat Dialog.

2. Use Rules and select End Chat in the Rule Action.


Output:
 

 


How to show chat image instead of text in Salesforce Chat?

Static Resource for Chat Image:

Chat Button Configuration:


Code Change:


 Output:



Messaging Sessions getting transferred to Agents from Einstein Bot in Salesforce

When an error or exception occurs, Bot immediately transfers the Messaging Session to an agent(Omni-Channel).

Error Handler Dialog can be used to avoid this issue. Using Error Handler Dialog, we can show user-friendly message to the customer. We can avoid transferring it to the agent also.

1. Create a simple Bot.

Welcome Dialog:
 

Close Case Dialog:
 

Error Handler dialog:
 

2. Test by making an exception. I have made my Flow to cause an exception.


March 25, 2021

Custom CSS properties for lightning-tab in Salesforce Lightning Web Component

Sample Code:

HTML:

<template>
    <lightning-card>
        <lightning-tabset>
            <lightning-tab label="Item One">
                First Content
            </lightning-tab>
            <lightning-tab label="Item Two">
                Second Content
            </lightning-tab>
            <lightning-tab label="Item Three">
                Thrird Content
            </lightning-tab>
        </lightning-tabset>
    </lightning-card>
</template>

JavaScript:
import { LightningElement } from 'lwc';

export default class SampleLWC extends LightningElement {

}

CSS:
:host {
  --sds-c-tabs-list-color-border: black;
  --sds-c-tabs-item-color-border-active: red;
  --sds-c-tabs-item-color-border-hover: green;
  --sds-c-tabs-item-text-color: black;
  --sds-c-tabs-item-text-color-active: green;
}

JS-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>51.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>


Output:


March 24, 2021

Monitor Einstein Bot in Salesforce

Option 1:
1. Create a Report Type on Chat Transcripts object.


2. Create a report on the custom report type from step 1. Set "Is Chat Bot Session" to true in the filter.
 

Option 2:
1. Install the below AppExchange Einstein Bot Analytics.

2. Go to Reports tab and select "Einstein Bot Reports" folder.


CSS Updates to SLDS in Lightning Web Component Salesforce

Salesforce Lightning Design System (SLDS) styling hooks make it easy to customize component styling and express your brand. Styling hooks provide CSS custom properties that correspond to SLDS component blueprints and design variations. To customize an SLDS style, declare a corresponding custom property in a component’s style sheet. You can use the custom properties to style base components and custom components.
 
Sample Code:

HTML:

<template>
    <lightning-card>
        <lightning-button
            variant="brand"
            label="Submit">
        </lightning-button>
    </lightning-card>
</template>

JavaScript:
import { LightningElement } from 'lwc';

export default class SampleLWC extends LightningElement {

}

CSS:
:host {
    --sds-c-button-brand-color-background: black;
    --sds-c-button-brand-color-border: white;    
    --sds-c-button-brand-text-color: purple;
    --sds-c-button-brand-text-color-hover: green;
  }

js-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>51.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>


Output:  

When you mouse over.
 


Reference Article:

System.UnexpectedException: Something went wrong getting your credentials in Salesforce

System.UnexpectedException is a run time exception thrown by the system. This exception cannot be caught or thrown.
 
 
If you see any error codes in the error message, then you have to check with Salesforce Support. Else, the issue is on the 3rd party where the API is hosted.
 
So, in this case, we have to check the logs in end point where the call out is made. 

Vote for the below idea

March 23, 2021

How to show parent record information using Related Record componet in Salesforce Lightning?

1. Create a Quick Action on the parent object. In my case, Account is the parent.
 

Use Edit Layout button to add the fields to be added on the page.
 
2. In the lightning record page, use Related Record standard component.
 


Report on Salesforce Classic Users(Toggling between Lightning and Classic)

Use LightningToggleMetrics entity.
 
1. Create a custom Report Type.
 

2. Create a report using the report type from step 1.


March 22, 2021

Simple Quick Action to Email Case Contact in Salesforce

1. Create a Custom Email Template.
 

 2. Create a Quick Action.Make sure Contact Id is added to To Recipients and the Email Template is selected in "Default email Template".


3. Add the quick action to the page layout and test it out.


Send Email in Salesforce Case Object

Email-to-Case should be enabled to use the Send Email quick action on the Cases object.
 
1. Go to Email-to-Case.
 

2. Select "Enable Email-to-Case".