June 30, 2020

Digital Engagement Messaging in Salesforce

Digital Engagement Messaging allows customers to start conversations by sending texts to your designated phone number or sending Facebook Messenger messages to your Facebook page. Incoming messages are displayed in the Omni-Channel utility in the Service Console, where agents can accept a message and start chatting with a visitor.

Conversations can be initiated directly with customers within Salesforce through outbound message notifications in Process Builder. When a customer wants to respond, their incoming responses are routed directly to the Service Console where agents can continue the conversation.

LOA form is used if the customer wants use their number instead of Salesforce generated number.

Area code can be shared to Salesforce to get a number starting with the Area code.

Facebook Channel Setup - https://www.infallibletechie.com/2020/04/facebook-channel-setup-in-digital.html

To know more about Carrier Filtering and Best Practices, please check the below link
https://help.salesforce.com/articleView?id=000352415&language=en_US&type=1&mode=1

June 28, 2020

How to display parent field value in lightning:datatable in Salesforce Lightning Component

Component:

<aura:component implements="force:appHostable"
                controller="ContactController">
               
    <aura:attribute type="Contact[]" name="contactList"/>
    <aura:attribute name="mycolumns" type="List"/>
   
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
   
    <lightning:datatable data="{! v.contactList }"
                         columns="{! v.mycolumns }"
                         keyField="Id"
                         hideCheckboxColumn="true"
                         onrowaction="{!c.handleRowAction}"/>
   

</aura:component>


JavaScript Controller:

({
   
    init: function ( cmp, event, helper ) {
       
        var actions = [
            { label: 'Edit', name: 'edit' },
            { label: 'View', name: 'view' } ];


        cmp.set( 'v.mycolumns', [
            { label: 'Name', fieldName: 'Name', type: 'text' },
            { label: 'Account Name', fieldName: 'AccountName', type: 'text' },
            { label: 'Created By', fieldName: 'CreatedBy', type: 'text' },
            { type: 'action', typeAttributes: { rowActions: actions } } ] );

        var action = cmp.get( "c.fetchContacts" );
        /*action.setParams({
        });*/
        action.setCallback(this, function( response ) {
           
            var state = response.getState();
           
            if ( state === "SUCCESS" ) {
               
                var rows = response.getReturnValue();
               
                for ( var i = 0; i < rows.length; i++ ) {
                   
                    var row = rows[i];
                   
                    if ( row.Account ) {
                        row.AccountName = row.Account.Name;
                    }
                   
                    if ( row.CreatedBy ) {
                        row.CreatedBy = row.CreatedBy.Name;
                    }
                   
                }
               
                cmp.set( "v.contactList", rows );
                console.log( 'Contacts are ' + cmp.get( "v.contactList" ) );
               
            }
           
        });
        $A.enqueueAction( action );
       
    },

    handleRowAction: function ( cmp, event, helper ) {
       
        var action = event.getParam( 'action' );
        var row = event.getParam( 'row' );
        var recId = row.Id;

        switch ( action.name ) {
            case 'edit':
                var editRecordEvent = $A.get("e.force:editRecord");
                editRecordEvent.setParams({
                    "recordId": recId
                });
                editRecordEvent.fire();
                break;
            case 'view':
                var viewRecordEvent = $A.get("e.force:navigateToURL");
                viewRecordEvent.setParams({
                    "url": "/" + recId
                });
                viewRecordEvent.fire();
                break;
        }
    }
   
})


Apex Class:

public class ContactController {
   
    @AuraEnabled
    public static List < Contact > fetchContacts() {
        return [ SELECT Id, Name, Account.Name, CreatedBy.Name FROM Contact LIMIT 10 ];
    }

}


Output:


June 27, 2020

Adoption of Chatter in Salesforce

Collaboration Group Feed Posts Report Type


Chatter Group Usage Report:




Use Cases:

1. Announcements
2. Sharing Files
3. Discussion Forums

June 24, 2020

Salesforce Interview Questions with Answers Part 64

1. Ten Minute Build
The 10-minute build practice is an extreme programming practice where the code base is designed by the developer to be built automatically.
Having a simple build is important because it is easy to build up from that. Most developers hurry and develop a build that is intended to cover all possible outcomes from the first stage of the build; this causes complications as the project develops.

2. Callout from Salesforce Flow
If Salesforce creates, updates, or deletes data in your org and then accesses external data in the same transaction, an error occurs. In your flow, we recommend using a separate transaction to access data in an external system. To do so, end the prior transaction by adding a screen or local action to a screen flow or a Pause element to an autolaunched flow. If you use a Pause element, don't use a record-based resume time. For example, a screen flow creates a contact and then displays a confirmation screen. Next, the flow updates the contact in the external system. The flow doesn’t fail because it uses a separate transaction to access the external data.

https://help.salesforce.com/articleView?id=flow_prep_bestpractices.htm&type=5

3. Maximum execution time for each Apex transaction
10 minutes.
Transaction may synchronous or Asynchronous. The limit is 10 minutes.
https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/salesforce_app_limits_platform_apexgov.htm

4. Bulk API 2.0
Bulk API 2.0 provides a simple interface to quickly load large amounts of data into your Salesforce org and to perform bulk queries on your org data.

1. Support for OAuth 2.0
Bulk API 2.0 supports all OAuth flows supported by other Salesforce REST APIs.
2. Automatic File Batching
Bulk API 2.0 simplifies uploading large amounts of data by breaking the data into batches automatically. All you have to do is upload a CSV file with your record data and check back when the results are ready.
3. Daily Limits Based on Number of Records
Instead of limiting the amount of data uploaded daily by the quantity of jobs, Bulk API 2.0 uses a limit of total records uploaded. The limit is 100 million records per 24-hour period.

Limit:
Salesforce automatically chunks the data for your job into multiple internal batches to improve performance while processing the job. Salesforce creates a separate batch for each 10,000 records in your job data, up to a daily maximum of 100 million records.

https://developer.salesforce.com/docs/atlas.en-us.api_bulk_v2.meta/api_bulk_v2/introduction_bulk_api_2.htm

5.What Is DMARC?
Domain-based Message Authentication, Reporting, and Conformance (DMARC) is an email authentication, policy, and reporting protocol. It’s built on top of Sender Policy Framework (SPF) and DomainKeys Identified Mail (DKIM) protocols. If neither of those authentication methods passes, the DMARC policy determines what to do with the message. Salesforce supports and recommends DMARC. It’s up to you to determine whether you implement it for your domain.

DMARC is a second layer of authentication after DKIM and SPF. If an email doesn't pass DKIM and SPF authentication, DMARC policy tells the receiver what to do with the message. For example, it can reject some email messages and quarantine others.

Reference Link - https://help.salesforce.com/articleView?id=emailadmin_dmarc.htm&type=5

6. Work Item Size and Agent Capacity Salesforce Chat
Omni-Channel is a work routing system.
Omni-Channel works on the concept of Work Items. Each time a case is assigned to a queue, a work item is created and pushed to the agents. Omni-Channel tracks the number of work items assigned to an agent based on number of primary tabs related to the work items are open.
Set how much work your agents can handle at once. Size your chats relative to agent capacity so that agents can handle multiple chats, but aren't overworked.
In Work Item Size, set the amount of an agent’s capacity that one work item consumes.
In Agent Capacity, set the agent’s total capacity.
Units of Capacity indicates the amount of an agent’s overall capacity that’s consumed when the agent is assigned a work item from queues that are associated with this configuration.

The Capacity setting in the presence configuration the agent is assigned to determines the agent’s overall capacity. When the agent is assigned a work item from the queue that’s associated with this configuration, the Capacity Weight is subtracted from the agent’s overall capacity. Agents can be assigned work items until their overall capacity reaches 0.

You can select a Capacity Weight or a Capacity Percentage, but not both.

https://help.salesforce.com/articleView?id=000338278&type=1&mode=1

7. Arrow Function in JavaScript
Arrow functions also called “fat arrow” functions are a more concise syntax for writing function expressions.
Arrow functions were introduced with ES6 as a new syntax for writing JavaScript functions.
fat arrow symbol ( => ).

Without Arrow Function:
testFunc = function() {
  return "Welcome to InfallibleTechie";
}


With Arrow Function:
testFunc = () => {
  return "Welcome to InfallibleTechie";
}


With Arrow Function with Parameters:
<p id="test"></p>
<script>
var hello;
hello = (val1, val2) => val1 + val2;
document.getElementById( "test" ).innerHTML = hello( 3, 2 );
</script>


Output is 5.

this keyword impact:
Arrow functions allow you to retain the scope of the caller inside the function.
The value of "this" inside a function can’t be changed. It will be the same value as when the function was called.
If you need to bind to a different value, you’ll need to use a function expression.

8. Entitlement Templates in Salesforce 
Entitlement templates let you predefine terms of support that users can add to products. If Entitlement template is assigned to ProductA and if Asset is created with the ProductA, Entitlement Process from the Entitlement Template is automatically linked. You can see the Entitlements from the Asset Related List.

http://www.infallibletechie.com/2020/05/entitlement-templates-in-salesforce.html

9. Perform Synchronous Compile on Deploy
This feature is enabled automatically for production orgs but it's an opt-in feature for sandboxes.

Previously, installation and upgrades with large packages resulted in all classes not being compiled.  This causes serious app performance issues until all classes are compiled.

Each org’s Apex code is now automatically recompiled before completing a metadata deploy, package install, or package upgrade. This change in behavior improves performance following metadata deploys and package updates. Previously, a deploy, install, or upgrade could leave an org with invalidated code, causing reduced performance while Apex was recompiled.

This feature causes deployments to the org to invoke the Apex compiler and save the resulting bytecode as part of the deployment. A minimal increase in deployment times can occur, but Apex doesn’t need to be recompiled on first run. So the slight increase in deployment time can prevent performance issues on first run.

1) Go to Setup --> Apex Settings
2) Enable "Perform Synchronous Compile on Deploy"

10. ConnectedAppPlugin Class
Contains methods for extending the behavior of a connected app, for example, customizing how a connected app is invoked depending on the protocol used.
This class gives you more control over the interaction between Salesforce and your connected app.

When you create a connected app, you specify general information about the app and settings for OAuth, web apps, mobile apps, and canvas apps. To customize how the app is invoked, create a connected app handler with this ConnectedAppPlugin Apex class. For example, use this class to support new authentication protocols or respond to user attributes in a way that benefits a business process.

The class runs on behalf of the current user of the connected app. But the user must have permission to use the connected app for the plug-in to work. If the user isn’t authorized for the connected app, use the authorize method.

11. GitHub and Git

GitHub

GitHub is where people build software.

1. Create a Repository.
2. Write code in your local.
3. Commit changes($git push -u origin master.
4. Make a pull request.

Git
Git is a distributed version-control system for tracking changes in source code during software development.

1. Write code. Initialize the git($git initialize).
2. Store the changes in your local($git add).
3. Commit the changes($git commit).
4. Push the changes($git push).
5. Make a pull request.

12. getObjectInfo

Use this wire adapter to get metadata about a specific object. The response includes metadata describing fields, child relationships, record type, and theme.

Sample Use Case:
Use getObjectInfo to return the object’s fields. All wire adapters in the lightning/ui*Api modules respect object CRUD rules, field-level security, and sharing. If a user doesn’t have access to a field, it isn’t included in the response.

13. Experienced Page Time in Salesforce Lightning Experience

Experienced Page Time is to add an EPT counter directly to Lightning Experience, which displays in the header. EPT is the time it takes to download and display the entire content of a webpage in a browser window.

1. Add ?eptVisible=1 to the end of the URL.To turn off after testing, use ?eptVisible=0.
2. Enable Lightning Component Debug Mode from Setup.

System exception 'ConcurrentUiRequests Limit exceeded' will be raised when you exceed governor limitations for your Salesforce organization. By default this is typically set to 25 long running UI requests for 10 seconds. This may vary depending on your Salesforce edition (displayed in the title bar of your browser).

14. Enhanced Email in Salesforce

Enhanced Email elevates email to a standard Salesforce object, with customization options and an API. Emails are no longer stored as tasks, but as full-featured records, complete with details, related lists, and collaboration tools. On email records, users can view their messages exactly as their customers do, complete with formatting.

With Enhanced Email, emails are stored using the standard Salesforce object, EmailMessage. The EmailMessage object gets you all the conveniences that come with standard objects, including custom fields, customized layouts, and a better record detail page.

15. Send Email to Members in Salesforce Queue

If you want to send an email notification to all queue members individually when a new case gets added to the queue.

The Send Email to queue members alert will only work if you are using Case Assignment Rules and Active Assignment checkbox to move Case to a Queue. If you are moving the case Manually to a Queue or using a Workflow, it does not trigger the Email alert.

Reference Link - https://help.salesforce.com/articleView?id=000323036&type=1&mode=1

June 23, 2020

Scheduled Reports in Salesforce

We can set up a report to run itself daily, weekly, or monthly and send the results automatically to the people who need to see them, so that we don’t have to remember to log in and do it.

Troubleshooting
1. Make sure the running user have access to the report folder. Else, the report won't be sent.
2. Classic - https://help.salesforce.com/articleView?id=000321705&language=en_US&type=1&mode=1
3. Lightning - https://help.salesforce.com/articleView?id=reports_subscribe_lex.htm&type=5
4. Timezone is based on the user's timezone who is scheduling it.
5. Check email log.
6. Check email deliverability if the emails are not sent.
7. Use Test Deliverability to check whether emails are receiving from Salesforce.
8. Results are based on the running the user's permissions.
9. Max limit is 10 MB.

June 22, 2020

External Account Hierarchy in Salesforce Community

Now users with Partner Community and Customer Community Plus licenses can view the records of other external users within their account hierarchy. External account hierarchies take the complexity out of sharing data with external users.

Role Hierarchy can be set using "Number of partner roles" under Community Settings.
Note: Maximum Number of partner roles can be set to 3. Executive, Manager and Worker roles.
With External Account Hierarchy, this will change. Check the difference below

Without External Account Hierarchy:
Worker reports to Manager.
Manager reports to Executive.
Executive reports to Account Owner(Internal User) role.

With External Account Hierarchy:
EAH records are required.
Worker reports to Manager.
Manager reports to Executive.
Executive reports to
1. To account owner(internal user) role if the account doesn't have parent account(EAH Record).
2. To Parent account's(EAH Record) highest role(Executive if 3 roles are set in Community Settings, Manager if 2 and Worker if 1).

External Account Hierarchy Entity:
Entity to store the hierarchies. Fields are
a. Account
b. Parent - Parent EAH records(self reference to EAH entity)
c. IsActive
d. IsAccessible
e. Hierarchy Type - Partner or Customer

Note:
1. Account merge is blocked for accounts participating EAHs.
2. Person Account is not supported.
3. If IsActive is false, then re-parenting won't happen. Nodes below the Inactive node will also don't do the re-parenting.
4. An Account cannot actively participate in multiple active EAHs of same Hierarchy Type.

IsAccessibleParent field in External Account Hierarchy
If false, it breaks the chain from current node to parent node. If Account A node is parent and B node is child and IsAccessibleParent is set to false in B node, then node A won't get access to Account B.
Default is true.

If records are not visible to the users, check the below
1. Check whether all the nodes are active.
2. Check whether IsAccessibleParent is true.
3. Check Role Reparenting status.
4. Check whether the confirmation email is received.

June 20, 2020

How to get query parameters or URL parameters using LWC in Salefsorce?

Sample Code:

import { LightningElement, wire } from 'lwc';
import { CurrentPageReference } from 'lightning/navigation';

export default class Sample extends LightningElement {

    @wire(CurrentPageReference)
    currentPageReference;

    connectedCallback() {
       
        console.log( 'Param ' + this.currentPageReference.state.recId );
   
    }

}

Output:


June 19, 2020

Fetching Validation Rule from tooling API in Salesforce

Single Validation Rule
/services/data/v48.0/tooling/sobjects/ValidationRule/03d5w0000006lVW


Multiple Validation Rule Tooling API Salesforce
/services/data/v48.0/tooling/query/?q=select+Id,Active,ValidationName+from+validationrule+where+id+in+('03d5w0000006lVW','03d5w0000006lVR')


Sample Trigger to update Account after Lead Conversion in Salesforce

Below trigger fetches all the Accounts when the Leads are converted. It sets the Record Type Id to External Account Record Type Id if the Account's Record Type Id is not External Account Record Type Id.

Sample code:

trigger LeadTrigger on Lead ( after update ) {

    Set < Id > setAccountIds = new Set < Id >();
   
    for ( Lead objLead : trigger.new ) {
       
        /* Getting Account Ids from the Lead after conversion .
           ConvertedAccountId in Lead contains the Account Id to which the Lead is converted.
        */
        if ( objLead.IsConverted && objLead.IsConverted != trigger.oldMap.get( objLead.Id ).IsConverted )
            setAccountIds.add( objLead.ConvertedAccountId );
   
    }
   
    if ( setAccountIds.size() > 0 ) {
   
        Id extRecordTypeId = Schema.SObjectType.Account.getRecordTypeInfosByName().get( 'External' ).getRecordTypeId();
        List < Account > listAcctForUpdate = new List < Account >();
       
        /* Fetching the accounts which are created as part of lead conversion and record type is not External */
        for ( Account objAccount : [ SELECT Id, RecordTypeId FROM Account WHERE Id IN: setAccountIds AND RecordTypeId !=: extRecordTypeId ] ) {
           
            /* Setting the Record Type Id to Account's External Record Type Id */
            listAcctForUpdate.add( new Account( Id = objAccount.Id, RecordTypeId = extRecordTypeId ) );
       
        }
       
        if ( listAcctForUpdate.size() > 0 )
            update listAcctForUpdate;
   
    }

}

June 18, 2020

Setting up Channel-Object Linking in Salesforce for SMS Channel

Channel-Object Linking in Salesforce
Create rules to quickly link channel interactions to objects such as contacts. You can fine-tune these rules so that linking happens automatically, or so that your agents are prompted with suggested records. Linking occurs from within the Lightning console.


1. Go to Channel-Object Linking Salesforce setup.


2. Enable Channel-Object Linking and click New Linking Rule.


3. Select Text channel.


4. Set the Linking Logic.


5. Save the Rule.


6. Open the existing messaging session or initiate a new messaging session with your SMS Channel. Make sure the phone number you are using for testing have a matching Contact.

7. You will see a notification.

8. Click the "Review and Link" link


9. Select the record and click Link button to link it to the Messaging Session record.


Einstein Bot getting multiple values from Apex Class

Sample Code:

Apex Class:

public class EinsteinChatBotController { 
 
    public class CaseOutput { 
     
        @InvocableVariable( required=true ) 
        public String sCaseNumber; 
        @InvocableVariable( required=true ) 
        public String sStatus; 
    } 
     
    public class CaseInput { 
     
        @InvocableVariable( required=true ) 
        public String caseSubject; 
         
    } 
 
    @InvocableMethod(label='Get Case Status') 
    public static List < CaseOutput > fetchCaseStatus( List < CaseInput > listCaseInputs ) { 
     
        List < CaseOutput > objOutputs = new List < CaseOutput >();
        Set < String > listSubjects = new Set < String >(); 
        CaseOutput objOutput = new CaseOutput(); 
       
        for ( CaseInput objCaseInput : listCaseInputs )
            listSubjects.add( objCaseInput.caseSubject );
       
        for ( Case objCase : [ SELECT Status, CaseNumber FROM Case WHERE Subject IN: listSubjects ] ) {
           
            objOutput.sStatus = objOutput.sStatus == null ? objCase.Status : ( objOutput.sStatus + ', ' + objCase.Status ) ;
            objOutput.sCaseNumber = objOutput.sCaseNumber == null ? objCase.CaseNumber : ( objOutput.sCaseNumber + ', ' + objCase.CaseNumber ) ; 
           
        }
                  
        objOutputs.add( objOutput );                     
        return objOutputs; 
     
    } 
 
}


Bot Configuration:



Output:


June 17, 2020

How to test Salesforce Embedded Service Chat Code?

1. Create a Repository in GitHub.

2. Add an existing file with the Embedded Service Code(HTML).

3. Use https://htmlpreview.github.io/? to preview the HTML file.

4. Go to CORS and add the above URL.



Salesforce Chat button showing offline when agents are online

1. Check the below article.


2. Make sure the user is Service Cloud user.

3. Make sure the user is Chat User.


4. Also, use the Supervisor tab(very handy) to check the Agent's capacity and availability.

June 15, 2020

How to enable Configure Messaging Permission in Salesforce for an user?

To enable Configure Messaging Permission, follow the below steps.

1. Create a new permission set
2. Select App Permissions.
3. Click Edit, then enable Configure Messaging.
4. Click Save.
5. Assign the Permission Set to you.


lightning:datatable with row actions in Salesforce

Sample Code:

AccountListController.apex:


public class AccountListController {
   
    @AuraEnabled
    public static List < Account > fetchAccts() {
        return [ SELECT Id, Name, Industry, Type FROM Account LIMIT 10 ];
    }
   

}

AccountList.cmp:

<aura:component implements="force:appHostable"
                controller="AccountListController">
               
    <aura:attribute type="Account[]" name="acctList"/>
    <aura:attribute name="mycolumns" type="List"/>
   
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
   
    <lightning:datatable data="{! v.acctList }"
                         columns="{! v.mycolumns }"
                         keyField="Id"
                         hideCheckboxColumn="true"
                         onrowaction="{!c.handleRowAction}"/>
   

</aura:component>

AccountListController.js:

({
   
    init: function ( cmp, event, helper ) {
       
        var actions = [
            { label: 'Edit', name: 'edit' },
            { label: 'View', name: 'view' } ];


        cmp.set( 'v.mycolumns', [
            { label: 'Name', fieldName: 'Name', type: 'text' },
            { label: 'Industry', fieldName: 'Industry', type: 'text' },
            { label: 'Type State', fieldName: 'Type', type: 'text' },
            { type: 'action', typeAttributes: { rowActions: actions } } ] );

        var action = cmp.get( "c.fetchAccts" );
        action.setParams({
        });
        action.setCallback(this, function( response ) {
            var state = response.getState();
            if ( state === "SUCCESS" ) {
                cmp.set( "v.acctList", response.getReturnValue() );
            }
        });
        $A.enqueueAction( action );
       
    },

    handleRowAction: function ( cmp, event, helper ) {
       
        var action = event.getParam( 'action' );
        var row = event.getParam( 'row' );
        var recId = row.Id;

        switch ( action.name ) {
            case 'edit':
                var editRecordEvent = $A.get("e.force:editRecord");
                editRecordEvent.setParams({
                    "recordId": recId
                });
                editRecordEvent.fire();
                break;
            case 'view':
                var viewRecordEvent = $A.get("e.force:navigateToURL");
                viewRecordEvent.setParams({
                    "url": "/" + recId
                });
                viewRecordEvent.fire();
                break;
        }
    }
   
})


Output:


lightning-tree-grid with filter in LWC in Salesforce

Sample Code:

LWC HTML:

<template>
      
    <lightning-tree-grid columns = {gridColumns}
                            data = {gridData}
                            key-field = "Id"
                            hide-checkbox-column = true
                            onheaderaction = {handleHeaderAction}>
    </lightning-tree-grid>
  
</template>


LWC JavaScript:

import { LightningElement, track, wire } from 'lwc';
import fetchAccounts from '@salesforce/apex/AccountListController.fetchAccounts';

export default class Example extends LightningElement {

    @track gridColumns = [{
        type: 'text',
        fieldName: 'Name',
        label: 'Name'
    },
    {
        type: 'text',
        fieldName: 'Industry',
        label: 'Industry'
    },
    {
        type: 'text',
        fieldName: 'Active__c',
        label: 'Active',
        actions: [
            { label: 'All', checked: true, name: 'All' },
            { label: 'Yes', checked: false, name: 'Yes' },
            { label: 'No', checked: false, name: 'No' }
        ]
    },
    {
        type: 'text',
        fieldName: 'FirstName',
        label: 'FirstName'
    },
    {
        type: 'text',
        fieldName: 'LastName',
        label: 'LastName'
    }];
    @track gridData;
    @track activeFilter = 'All';
    @track allRows;

    @wire(fetchAccounts)
    accountTreeData({ error, data }) {

        if ( data ) {

            var tempData = JSON.parse( JSON.stringify( data ) );
            /*var tempjson = JSON.parse( JSON.stringify( data ).split( 'Contacts' ).join( '_children' ) );
            console.log( 'Temp JSON is ' + tempjson );*/
            for ( var i = 0; i < tempData.length; i++ ) {

                var cons = tempData[ i ][ 'Contacts' ];

                if ( cons ) {

                    tempData[ i ]._children = cons;
                    delete tempData[ i ].Contacts;

                }

            }
            this.gridData = tempData;
            this.allRows = tempData;

        } else if ( error ) {
         
            if ( Array.isArray( error.body ) )
                console.log( 'Error is ' + error.body.map( e => e.message ).join( ', ' ) );
            else if ( typeof error.body.message === 'string' )
                console.log( 'Error is ' + error.body.message );

        }

    }

    handleHeaderAction( event ) {

        const actionName = event.detail.action.name;
        let columns = this.gridColumns;
        const activeFilter = this.activeFilter;
   
        if ( actionName !== activeFilter ) {

            var actions = columns[ 2 ].actions;
            actions.forEach((action) => {
                action.checked = action.name === actionName;
            });
            columns[ 2 ].actions = actions;
            this.activeFilter = actionName;
            this.gridColumns = columns;
            this.updateRows();

        }

    }

    updateRows() {

        const rows = this.allRows;
        let filteredRows = rows;
        const activeFilter = this.activeFilter;

        if (activeFilter !== 'All') {
            filteredRows = rows.filter(function (row) {
                return ( activeFilter === row.Active__c );
            });
        }

        this.gridData = filteredRows;   

    }

}


Apex Class:

public class AccountListController {

    @AuraEnabled(cacheable=true)
    public static List < Account > fetchAccounts() {
        return [ SELECT Id, Name, Industry, Active__c,
                ( SELECT Id, FirstName, LastName FROM Contacts )
                FROM Account LIMIT 100 ];
    }
   

}



Output:
Filter: All


Filter: No


Filter: Yes


June 12, 2020

How to end a Messaging Session in Salesforce?

There are two ways you can end a Messaging session

1. Ending it directly from the Messaging session when the conversation is over.
2. Messaging Sessions list view.

From the list view, check the below



To end Messaging sessions, "End Messaging Session" permission is required.
Before Summer ’20, users could end ongoing Messaging sessions with the “Configure Messaging” user permission. Starting in Summer ’20, this permission can’t be used to end Messaging sessions. To allow agents and supervisors to end sessions, update your user permission sets to include the “End Messaging Session” permission.


Update your Messaging permission set. Edit the App Permissions for your users, and select End Messaging Session.


June 11, 2020

openSubtab() for Lightning Experience in Salesforce

Sample Code:

Aura Component:


<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
   
    <lightning:workspaceAPI aura:id="workspace" />
    <lightning:button label="Open Tab with Subtab" onclick="{! c.openTabWithSubtab }" />
   
 </aura:component>
 
JavaScript Controller:

({
   
    openTabWithSubtab : function(component, event, helper) {
       
        var workspaceAPI = component.find("workspace");
        workspaceAPI.openTab({
            recordId: '0015w0000298JM7AAM',
            focus: true
        }).then(function(response) {
            workspaceAPI.openSubtab({
                parentTabId: response,
                recordId: '0035w000034EYn1AAG',
                focus: true
            });
        })
        .catch(function(error) {
            console.log( 'Error is ' + error );
        });
       
    }
   
})

Output:


June 9, 2020

Route Chats via Skills-Based Routing for Omni-Channel in Salesforce

Skills-based routing allows work items to be routed using more sophisticated and dynamic criteria than queue-based routing.

1. Enable "Enable Skills-Based Routing".


2. Add Skills in the setup.


3. Routing Type should be Omni-Channel Skills in Chat Buttons and Invitations setup.


4. Create Service Resource record. Make sure Active checkbox is enabled.


5. Add the Skills to the Service Resource record.


June 4, 2020

Joined Report in Salesforce

A joined report can contain data from multiple standard or custom report types. You can add report types to a joined report if they have relationships with the same object or objects. For example, if you have a joined report that contains the Opportunities report type, you can add the Cases report type as well because both have a relationship with the Accounts object.

A joined report consists of up to five report blocks, which you add to the report to create multiple views of your data.

Each joined report has a principal report type. By default, the principal type is the first one added to the report. For example, if you create the joined report by selecting the Opportunities report type, and then add the Cases type, the Opportunities type is the principal report type. The principal report type controls how common fields are named. Some common fields have different names or appear in different sections in different report types.

When a joined report contains multiple report types, some fields are identified as common fields. A field is a common field if it’s shared by all report types or if all report types share a lookup relationship to the field. Common fields can be used to group report blocks. In Lightning Experience, common fields are identified by the Common Fields Icon icon. In Salesforce Classic, common fields appear in the Common Fields area in the Fields pane.

For example, check the below link

http://www.infallibletechie.com/2019/08/how-to-create-joined-report-in.html

June 3, 2020

How to find why users are getting access to records they are not supposed to see in Salesforce?

1. Switch to Classic.

2. Click Sharing button.


3. Click Expand List button.


4. Find the user.

5. Click "Why?" before User name.

June 1, 2020

New Task button is missing issue in Lightning Experience Record Page in Salesforce

Add the New Task button to the Salesforce Mobile and Lightning Experience Actions section of page layouts.


Salesforce Feature Retirements

Check the below link for Salesforce Feature Retirements schedule

https://help.salesforce.com/articleView?id=000313062&language=en_US&type=1&mode=1

For each release, go to the release notes and search retire keyword.