Lightning Data Services

08:02 2 Comments A+ a-


Lightning Data Services

What is LDS :
                        LDS is Lightning Component that display the data on Page in Salesforce  Lightning. Using LDS we don’t need any apex  controller to perform CRUD operation. using LDS we can increase the performance. It also provide the way to cache the data to work offline in case user is not connected to network. Once the connection is restored data will sync.
LDS also handle Field Level Security and sharing rules security. Record loaded in Lightning Data Services are stored in cache and shared between all components.Using LDS all component performance is increase because data is loaded once and used by many component, no need to make separate request from different-different components . when any of the component  updates  a record then other component will  automatically updated with new value.

force:recordData :
                                    This tag is must be used to load the data in component  using LDS.
Attributes of force:recordData : 
recordId : Id of current page record that will be load
      mode : (Edit,View) its depend on what operation we are performing. If we want to update,create then Mode=’Edit’ else Mode=’View’
layoutType : specify the layout type to display record and its determine what field are included in component. 
          fields : specifies which fields in the record to query.

Target Attribute :
1.      targetRecord  : populate with loaded record.
2.      targetField      : view of loaded record.
3.     targetError      :  populate with error.    

Methods :
1.      saveRecord() : insert of update the current record in force:recordData.
2.      deleteRecord() : delete the current record in force:recordData.
3.      getNewRecord() :  load the new record instance to insert the record of that object from force:recordData.
4.      reloadRecord() : reload the current record with new data.

Keep In Mind When Using It :
i.                LDS is simple but it’s not complete replacement of apex controller.
ii.              LDS is not supported in lightning out and visualforce page. Its only for lightning.
iii.            LDS perform CRUD only on single record. It’s not supported for bulk data.
iv.             In Summer 17, release LDS used force:recordPreview component.But now it’s completely replaced by force:recordData. Difference between force:recordPreview  and force:recordData  is force:recordData  returns record in new shape using UI API and targetfield is added in parameter.
v.               To update from force:recordPreview  to force:recordData is to change reference from targetRecord to targetField.
vi.              If you want to query multiple operations in one transaction then use apex controller @AuraEnabled.


Example :
            Here we are creating a component that is added on Account detail page. It will create a new contact for current account record.


1. Create a new Record :

    Lightning Component :
    <aura:component implements="flexipage:availableForRecordHome, force:hasRecordId">
<aura:attribute name="newContact" type="Object"/>
<aura:attribute name="createContact" type="Object"/>
<aura:attribute name="newContactError" type="String"/>
<force:recordData aura:id="contactRecordCreator"
    layoutType="FULL"
    targetRecord="{!v.newContact}"
    targetFields ="{!v.createContact}"
    targetError="{!v.newContactError}"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
            <div class="Create Contact">
                        <lightning:card iconName="action:new_contact" title="Create Contact">
                                                <div class="slds-p-horizontal--small">
<lightning:input aura:id="contactField" label="First Name" value="{!v.createContact.FirstName}"/>
<lightning:input aura:id="contactField" label="Last Name" value="{!v.createContact.LastName}"/>
<lightning:button label="Save Contact" variant="brand" onclick="{!c.handleSaveContact}"/>
                                    </div>
</lightning:card>
            </div>
    <aura:if isTrue="{!not(empty(v.newContactError))}">
        <div class="recordError">
            {!v.newContactError}</div>
    </aura:if>
    </aura:component>

   Lightning Controller :
   ({
    doInit: function(component, event, helper) {
        console.log('changes');
        component.find("contactRecordCreator").getNewRecord(
            "Contact", // sObject type (entityAPIName)
            null,      // recordTypeId
            false,     // skip cache?
            $A.getCallback(function() {
                var rec = component.get("v.newContact");
                var error = component.get("v.newContactError");
                if(error || (rec === null)) {
                    console.log("Error initializing record template: " + error);
                }
                else {
                    console.log("Record template initialized: " + rec.sobjectType);
                }
            })
        );
    },
    SaveContact: function(component, event, helper) {
        component.set("v.createContact.AccountId", component.get("v.recordId"));
        component.find("contactRecordCreator").saveRecord(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                var resultsToast = $A.get("e.force:showToast");
                resultsToast.setParams({
                    "title": "Saved",
                    "message": "New Contact ."
                });
                resultsToast.fire();
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
            } else if (saveResult.state === "ERROR") {
                console.log(JSON.stringify(saveResult.error));
            } else {
                console.log('Unknown problem, state: ' + saveResult.state);
            }
        });
    }
    })
Result :


2. Delete A record :
            Here we added Delete Component on Account Detail Page. It will Delete Current Account when we click on Delete Button in below component.

Lightning Component :
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">
    <aura:attribute name="recordError" type="String" access="private"/>
    <force:recordData aura:id="dataRecord"
            recordId="{!v.recordId}"
            fields="Id"
            targetError="{!v.recordError}"
            recordUpdated="{!c.handleRecordUpdated}"/>
     <div class="Delete Record">
            <lightning:card iconName="delete" title="Delete Record">
                                    <div class="slds-p-horizontal--small">
<lightning:button label="Delete Record" variant="destructive" onclick="{!c.handleDeleteRecord}"/>
                                    </div>
            </lightning:card>
       </div>
    <aura:if isTrue="{!not(empty(v.recordError))}">
        <div class="recordError"> {!v.recordError}</div>
     </aura:if>
</aura:component>

Lightning Controller :
({
handleDeleteRecord: function(component, event, helper) {
             component.find("dataRecord").deleteRecord($A.getCallback(function(deleteResult) {
            if (deleteResult.state === "SUCCESS" || deleteResult.state === "DRAFT") {
                console.log("Record is deleted.");
            } else if (deleteResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
            } else if (deleteResult.state === "ERROR") {
                console.log('Problem deleting record, error: ');
            } else {
                console.log('Unknown problem, state: ');
            }
        }));
    },
 handleRecordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
        } else if(eventParams.changeType === "LOADED") {
        } else if(eventParams.changeType === "REMOVED") {
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Deleted",
                "message": "The record was deleted."
            });
            resultsToast.fire();

        } else if(eventParams.changeType === "ERROR") { }
    }
})

Result :


3. Update a Record :
            Here We create a component that will update the account detail on Account Detail page on click of save Button in component.

Lightning Component :
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">
    <aura:attribute name="record" type="Object"/>
    <aura:attribute name="accRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>
    <force:recordData aura:id="recordHandler"
      recordId="{!v.recordId}"
      layoutType="FULL"
      targetRecord="{!v.record}"
      targetFields="{!v.accRecord}"
      targetError="{!v.recordError}"
      mode="EDIT"
      />
    <div class="Record Details">
        <lightning:card iconName="action:edit" title="Edit Account">
            <div class="slds-p-horizontal--small">
               <lightning:input label="Account Name" value="{!v.accRecord.Name}"/>
               <br/>
               <lightning:button label="Save Account" variant="brand" onclick="{!c.SaveRecord}" />
            </div>
        </lightning:card>
    </div>
    <aura:if isTrue="{!not(empty(v.recordError))}">
        <div class="recordError">
            {!v.recordError}</div>
    </aura:if>
</aura:component>

Lightning Controller :
({
    SaveRecord: function(component, event, helper) {
        component.find("recordHandler").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("User drafts.");
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
            } else if (saveResult.state === "ERROR") {
                console.log('Problem saving record, error: ' + JSON.stringify(saveResult.error));
            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
            }
        }));
    }
})

Result :

Fitness Tracker for Salesforce Health Cloud

06:32 3 Comments A+ a-

Hi All,
As you know Health Cloud product from Salesforce is a great patient management and care software/package. Its a leading product in healthcare industry. As this is widely used all over world, I started making something useful around it.

As todays life daily exercise is very important. Almost all doctors recommend patients to have a walk, run daily and track their activity. For tracking this, people use different tracking tools and devices like Fitness Band is most popular. Fitness Band comes from various companies. In my demo, I am going to use MI Fitness Band integration. Thanks MI for making this beautiful stuff.


Case Study

John is a Care Taker at iBS healthcare organization. He maintains 50+ patients daily. His mainly job to keep track of patients daily fitness activity like
Steps
Distance Covered
Calories Burned
Duration (Spent on activity)

He generally ask his patients to send their daily fitness activity by WhatsApp on mobile. Then John arranges them, read values, fill in system. Sometimes he forget the sequence and sometimes patients forget to send that data to him. This is becoming very hectic job for John.

Solution Proposed

Isn't it very useful if John get all the fitness activity details on the Patient Timeline for each patient he manages? Sounds fantastic! Now, John simply needs to open patient detail screen and go to Timeline, and he can see the patient related Fitness Activity like Steps, Distance, Calories, Duration at one place and all updated instantly. This is second major feature for which John is exited about. He does not need to wait till end of day to get all patient fitness data. Whenever he wants the patient Fitness Data, he simply go to Timeline and check it. Its so simple. John life is easy :)


How It Works

As a Salesforce Architect, working at iBirds , Me and my team have developed many tools around salesforce echo system for helping industry and community. Here is how we developed this, step by step.

Using Google Fit Connector for Salesforce

ibirds has recently developed one Google Fit Connector for Salesforce App. We are going to launch it shortly. This connector periodically fetch google fit data from user's account and store in a fitness activity object in Health Cloud. We can schedule the fetch mechanism or refresh manually as well. Thanks Google for this great application which helps users to keep up to date with their fitness data.





Enable MI Fitness Band Sync to Google Fit

This is a manual step. There is config settings in MI App, that you can send fitness data sync to external system like Google Fit.




Health Cloud Timeline setup for Fitness Activity

There is a great tutorial on trailhead about adding your custom patient data (object) on patient timeline. Check here

We used our Fitness Activity custom object which having MI Fitness band data. It keeps all patient data up to date. We are having a patient/account relationship already in that so that health cloud timeline supports it.

We can also show Fitness Card like this on left side under patient info.




Or we can show this on dashboard as a scrollable timeline plugin using Timeline View Configuration as below



Or we can show this under patient card as data using Patient Card Configuration as below



Or on Fitness Activity Detail screen like this


So, once all setup, now John easily navigate to their patients records in Health Cloud and open their record. And all info related to his patient fitness, he can see easily at single glance.

Checkout a small screencast.


Thanks for Salesforce, for making such good products which helps people on a daily basis.


Email/Tweet me for any clarification needed and enhancement suggestions here.

Thanks
Aslam Bari













Salesforce Einstein Chatbot - Setup

07:39 1 Comments A+ a-


We all know that world is changing faster than we can think. There are lots of new technologies which are emerging and used in daily life. This is new era where things are becoming smarter. 

Einstein chatbot is one of them, before configuring the Einstein chatbot, the first question which comes in our mind is,

What’s the chatbot?

Chatbot is an automated computer program that holds a conversation with a person via written communications, with the aim of helping that person achieve a desired result. This is very complex definition of chatbot. In simple words, Chatbot is a technology in which a person can chat with computer instead of human, conversation looks like a human chat that can help you to achieve your aim.

Another question arises here, why we need chatbots?

Here are few reasons we need chatbots

1. 24/7 Availability
    Chatbots are never going to leave your office. They are available 24/7 to interact with your customers.

2. Immediate Response
    Chatbot response time is very fast. They can immediately reply to the questions and provide solutions for their queries, which provide higher customer satisfaction.

     3.    Scalability
     A customer care executive can talk with one person at a time. So, if we have lots of customers than we need more executives, which means more money.
Chatbot can chat with multiple customers at the same time.
It comes with scalability feature, so you can scale your customer service at any level you want.

    4.    Cost Effective
     Instead of increasing your customer care staff, you can save lot of money by using chatbots.
The infrastructure that your bot needs to work is already there, and it’s FREE thanks to messenger services like Facebook, Einstein Chatbot.

    5.    People prefer chat instead of call
   In today’s world, people are more addicted to the messenger service instead of calling, reason behind this it helps them to do multi-tasking at the same time.

Now we are familiar with chatbots and why we need them.

Einstein Chatbot

In market several bots are available like Microsoft Bot Platform, Amazon Lex, Google Dialogflow, Alibaba Intelligent Service Robot, and many more.
Einstein Chatbot is different from those bots, they are fully integrated with salesforce platform. They can access the salesforce data and can transfer conversation to the real live agent without any integration.
Chatbots can configured using wizard-based interface instead of code. It also has functionality to invoke Apex methods when we need them.



Setup Einstein Chatbot in your salesforce org

It requires to two licenses
  • ·       Service Cloud license
  • ·       Live Agent license

By following these easy you can setup Einstein bot in your org-

Step 1. Enable Live User agent

Setup | Live Agent Settings | Enable



Step 2. Switch to lightning experience

In this step, first enable the Einstein Chatbot

Setup | Einstein Bots | Settings | Einstein Bot





After that, go to the deployment channels and enable the live agent

Setup | Einstein Bots | Settings | Deployment Channels




Step 3. Einstein AI. Key Management and Permission set

After completing 2 steps, behind the scenes a new account is established on Einstein Platform Services. This is required because Einstein Bots needs to call into the Einstein Platform Services for NLP-related tasks. You will receive an email shortly after enabling Einstein Bots to let you know the account has been created.





Click on production users and setup the self-signed certificate. If you don’t have certificate you have to create one.

Setup | Security | Certificate and Key Management | create a Self-Signed Certificate




Another things happen behind the scenes, an permission set sfdc.chatbot.service.permset is generated inside org. This permission set controls the objects, apex classes which are being used by the chat bot.







Step 4. Create an Einstein Bot
Setup | Einstein Bots | click New
It opens an wizard to setup the Einstein bot. It will walk you through a few screens to gather basic information about this bot, including bot name, greeting message, and main menu options.






After completing the wizard, your bot is created.
Step 5. Setup Live Agent
     a)   Create Skill
     Setup | Live Agent | Skill | New 

b)   Create Chat Button
    Setup | Live Agent | Chat Button and Automated Invitations | New
   


   c)  If you have setup Live Agent chat button before, you notice there is new Einstein Bot settings section.


Edit and set the Einstein Bots Configuration to the new bot we just built. When this attribute is populated and pointed to an active bot, chat users will be connected to our bot first, instead of going to an agent directly.

Step 6. Add a Snap In Deployment for Preview

Einstein Bot preview function uses the Snap In chat component to load.
For Setting Up the Snap In Deployment it require site or community. Also setup the community or site. I also setup the Demo Community.

Setup | Channels | Snap Ins | New Deployment

You should notice the process of setting up a Snap-in Chat deployment is the exactly the same with or without an Einstein Bot

Step 7. Preview your bot

Now your basic bot is ready. For preview the bot you have activate it first.