• Matt Brown 71
  • NEWBIE
  • 35 Points
  • Member since 2017

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 6
    Questions
  • 13
    Replies
I'm facing an issue implementing snap-ins (embedded service) to our external website.  Everything is working OK, but I notice that "slds-scope" get's automatically added to the <body> tag of our website.  Watching the site load, you can see the class get added <body class="slds-scope"> when the prechat from the snap-ins are loaded.

This is not desired as it is mixing with our websites own CSS.  We very much do not want to apply the slds styles to our entire site.  I've seen online that you can set "applyBodyTag" to false, but this is only applicable to Visualforce Pages (<apex:page>).

Is there any known way to use embedded service on a website without applying the slds styles to the entire site?  Surely there must be a setting to prevent this, but I cannot seem to find it.

Any help would be appreciated.
I'm using lightning dataTable component.  But the sortedDirection only ever sorts one direction.  The sortDirection param never updates properly. Here is some code:
 
<aura:component implements="flexipage:availableForAllPageTypes" 
                controller="CrossSellActivityController"
                access="global">

  <!-- Attributes -->
  <aura:attribute name="activities" type="Array" />
  <aura:attribute type="String" name="sortedDirection" default="asc" />
  <aura:attribute name="columns" type="List" />

  <!-- Component DOM -->
  <div>
    <lightning:datatable keyField="id"
                         data="{!v.activities}"
                         columns="{!v.columns}"
                         sortedDirection="{!v.sortedDirection}"
                         onsort="{!c.updateColumnSorting}"
                         hideCheckboxColumn="true" />
  </div>

</aura:component>
Here is the column definition:
var columns = [
  { label: 'Program Key', fieldName: 'Program_Key__c', type: 'text', sortable: true },
  { label: 'Status', fieldName: 'Disposition__c', type: 'text', sortable: true },
  { label: 'User', fieldName: 'Username', type: 'text', sortable: true },
  { label: 'Asset', fieldName: 'Asset', type: 'text', sortable: true },
  { 
    label: 'Timestamp', 
    fieldName: 'CreatedDate', 
    type: 'date', 
    typeAttributes: {
      day: 'numeric',
      month: 'short',
      year: 'numeric',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: true
    },
    sortable: true
  }
];
component.set("v.columns", columns);
And where I console.log out the sortedDirection variable:
updateColumnSorting : function(component, event, helper) {
  var sortDirection = event.getParam('sortDirection');        
  component.set("v.sortedDirection", sortDirection);
  console.log('sortDirection: ', sortDirection);
},
The console.log always outputs 'asc' never flips to 'desc'.  I've even tried changing the definition to Boolean with no luck.
<aura:attribute type="Boolean" name="sortedDirection" default="false" />
I've also tried flipping it myself with a truthy check and setting it back on the sortedDirection attribute, but that doesn't work either.  Am I doing something wrong?


 
I haven't been able to find anything on this, and surely I can't be the only one but is there any way to show a date and time timestamp in dataTable?  I only see the type 'date'.  Am i just blind or missing something?  I feel like there should be a way to show a formatted date AND time stamp, is there not?
I've been tasked with adding a "Create Ticket from Chat Transcript" feature.  My org no longer wants automatic case creation from prechat survey, we only want it to be done manually, via a button - no big deal.

Here is the issue, I've created a simple lightning component that displays a button on the LiveChatTranscript record page.  When the agent clicks the button: this code is executed:
 
// Show Create Ticket Page Layout For LiveChatCase Type.
var createTicketEvent = $A.get("e.force:createRecord");
createTicketEvent.setParams({
    "entityApiName": "Case",
    "recordTypeId" : recordType,
    "defaultFieldValues": {
        "Priority" : "Normal",
        "Status": "New",
        "Origin": "LiveChat",
        "Authentication_Status__c": transcript.Authentication_Status__c,
        "Description": transcript.Body,
        "AccountId": transcript.AccountId,
        "ContactId": transcript.ContactId,
        "LeadId": transcript.LeadId,
        "SuppliedEmail": transcript.Visitor_s_Email__c
    }
});

createTicketEvent.fire();

So essentially we just call the create ticket page layout and pass it some default values.  The issue is that I also want the relationship from LiveChatTranscript to Case to be made - but the relationship is a lookup field on the transcript.  Obviously I don't have the Case ID yet as the record hasn't been created.  I don't have control over the record creation since we're just calling the createTicketEvent.fire(); salesforce takes over at that point, otherwise I'd just pass the transcript Id with the data to the Apex controller.

My question, is there anyway to pass the Transcript ID through with the case creation so that I can at least, in a trigger, set the new Case ID on the relationship field for the Transcript ID given?  One solution I thought of was to create a field on the case that gets populated with the Transcript ID, then in the trigger - I take that ID, grab the transcript and set the Case relationship on the Transcript.  But this feels dirty, and a waste of a field.

For reasons - we need to keep the relationship of these 2 objects as they are.  I thought of putting the relationship on the case instead of the transcript, but that wouldn't work since a case can have multiple transcripts, and not vice versa.

Any helpful solutions would be most appreciated!
Is there a way to detect in realtime (or near realtime) when a chat routed in omni (lightning) ends?

Current solutions we've explored / tried:
  1. Leveraging the Live Agent API, there is no method to get the current status of a chat or anything for us to see if chat has ended.
  2. Looking at LiveChatTranscript Status field, this doesn't get updated until after the agent closes the chat tab.
  3. Looking at LiveChatTranscriptEvent object, this too doesn't get written until after the chat tab is closed.
  4. Looking at tab info, we noticed a blue asterisk that appears in the tab when a chat is in progress, that goes away after it ends.  We thought to look in tab info for a boolean that gets flipped, but that turned up nothing.  There was no changes in the tab info from during the chat, to after it ended.  Nothing we could use here.
In case it was missed above, we're using omni routing in the "lightning experience", which pretty much wipes out all of the normal methods we'd use to tackle this, such as the `onChatEnd` method for classic console.  Can't use any of that in lightning.

You may be asking yourself "why don't you just wait until agent closes their tab".  Well, we'd love to, but the requirement is for us to leverage the omni api (specifically closeAgentWork) to clear the chat work item from omni BEFORE they cose their tab.  We have issues with agents leaving their tabs open by mistake and not getting routed new chats because of it.  So we need to clear omni work items for them as soon as the chat ends, but before they close their tab.

We've got the clearing of agent work worked out OK, we just need to automate it to a chat ending now.  Our organizations switch to lightning is depending on getting this sorted, so any ideas (even the obtuse ones) would be genuinely appreciated.
I am getting the following error when a submit button is clicked from a visual force page that triggers a method that disables a community user:

INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []

For some reference, here is the bit of code that triggers it
 
// ... User selected earlier, verified good selection, etc. 

users[0].IsActive = false; 
users[0].IsPortalEnabled = false; 

Database.DMLOptions options = new Database.DMLOptions(); 
updateUserResult = Database.update(users[0], options); 

if (updateUserResult.isSuccess()) { 
    // I do some other stuff, like create user 
} else { 
    // I output error here. (where I'm getting this error) 
} 

// ... Truncated

I do not get the error when I comment out the IsPortalEnabled line.  Now I have read that this can occur when you literally just don't have access, but I have full CRED access to all objects in our org. I have also read that this could be from referencing an Id which is invalid - but I'm not doing any of that, I'm literally just flipping a boolean here and getting this error.

Does anyone have some insight on things I can check to hunt down this issue?  It's also worth noting that I am able to "disable community user" from interface and when running the following in an anonymous execute:
 
List<User> users = [SELECT Id, Username, Profile.Name, Profile.Id, IsPortalEnabled, IsActive, ContactId, ProfileId FROM User WHERE ContactId = '<theContactId>']; 
users[0].IsPortalEnabled = false; 
users[0].IsActive = false; 
update users[0];
This above not give me an error in anonymous window in dev console.

Any ideas?  I have been researching solutions to this for a few days now and have come up empty.
 
I am just trying to replace a field in a controller extension

There is quite a bit of code which is attached to a custom button that generates a report. 

No matter how i put the field in __c __r I am getting an error



 
I'm using lightning dataTable component.  But the sortedDirection only ever sorts one direction.  The sortDirection param never updates properly. Here is some code:
 
<aura:component implements="flexipage:availableForAllPageTypes" 
                controller="CrossSellActivityController"
                access="global">

  <!-- Attributes -->
  <aura:attribute name="activities" type="Array" />
  <aura:attribute type="String" name="sortedDirection" default="asc" />
  <aura:attribute name="columns" type="List" />

  <!-- Component DOM -->
  <div>
    <lightning:datatable keyField="id"
                         data="{!v.activities}"
                         columns="{!v.columns}"
                         sortedDirection="{!v.sortedDirection}"
                         onsort="{!c.updateColumnSorting}"
                         hideCheckboxColumn="true" />
  </div>

</aura:component>
Here is the column definition:
var columns = [
  { label: 'Program Key', fieldName: 'Program_Key__c', type: 'text', sortable: true },
  { label: 'Status', fieldName: 'Disposition__c', type: 'text', sortable: true },
  { label: 'User', fieldName: 'Username', type: 'text', sortable: true },
  { label: 'Asset', fieldName: 'Asset', type: 'text', sortable: true },
  { 
    label: 'Timestamp', 
    fieldName: 'CreatedDate', 
    type: 'date', 
    typeAttributes: {
      day: 'numeric',
      month: 'short',
      year: 'numeric',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: true
    },
    sortable: true
  }
];
component.set("v.columns", columns);
And where I console.log out the sortedDirection variable:
updateColumnSorting : function(component, event, helper) {
  var sortDirection = event.getParam('sortDirection');        
  component.set("v.sortedDirection", sortDirection);
  console.log('sortDirection: ', sortDirection);
},
The console.log always outputs 'asc' never flips to 'desc'.  I've even tried changing the definition to Boolean with no luck.
<aura:attribute type="Boolean" name="sortedDirection" default="false" />
I've also tried flipping it myself with a truthy check and setting it back on the sortedDirection attribute, but that doesn't work either.  Am I doing something wrong?


 
I haven't been able to find anything on this, and surely I can't be the only one but is there any way to show a date and time timestamp in dataTable?  I only see the type 'date'.  Am i just blind or missing something?  I feel like there should be a way to show a formatted date AND time stamp, is there not?
I've been trying to add more criteria to pass the code coverage to move a trigger to production but my test class doesn't pass the the coverage test. I don't know how much more criteria I can add.  Any help with this would be greatly appreciated. 

 
@IsTest
public class TestAfterPOLogUpdateTest {

    static testMethod void myUnitTest() {
        // TO DO: implement unit test
        
        test.startTest();
        
        Map<String, Schema.RecordTypeInfo> recordTypes = Schema.SObjectType.Yushin_Product__c.getRecordTypeInfosByName();
        List<String> recordTypeNames = new List<String>(recordTypes.keyset());
        
        
        
        PageReference pageRef = Page.OppTabDetailinsidesales2;
        
          
          
        Contact c= new Contact();
        
        c.FirstName ='Bob';
        c.LastName = 'Poliquin';
        c.Email = 'Acme@aol.com';
        c.Phone = '5088084748';
        
        insert c;
        
        
           
        Account a = new Account();
         a.Name = 'Test';
         a.Industry = 'Retail';
         a.Territory_Code__c='KY';
         a.Sales_Agency__c='Five Nines - Plastics Division';
         insert a;
        
        Opportunity o = new Opportunity();
         o.name = 'Test';
         o.AccountId = a.Id;
         o.StageName = 'Closed Won';
         o.CloseDate = date.today();
         o.Type = 'New Customers';
         o.Product_Type__c = 'Robot';
         
        
         insert o;
         
                
        
         Product2 prod = new Product2(Name = 'HOP Five 900X', 
                                     Robot_Category__c = 'Hardware',Standard_Price__c=12345);
        insert prod;
        
        Id pricebookId = Test.getStandardPricebookId();
        
        PricebookEntry standardPrice = new PricebookEntry(
            Pricebook2Id = pricebookId, Product2Id = prod.Id,
            UnitPrice = 10000, IsActive = true);
        
         insert standardPrice;
         
         Request_for_Special_Payment__c rsp = new Request_for_Special_Payment__c ();  

         rsp.Opportunity_Name__c = o.Id;
         rsp.Account__c = a.Id;
         rsp.Requestor_Submit_for_Approval__c = true;
         rsp.Request_Submitted_By__c = 'Bob Poliquin';
         rsp.Requestor_Date_Submitted__c=date.today();
            
         insert rsp;
            
            
         rsp.Opportunity_Name__c = o.Id;
         rsp.Supervisor_Approved__c = true;
         rsp.Rejected_By__c='Chris Parillo';
         rsp.Supervisor_Approval_Date__c=date.today();
            
         update rsp;
            
            

        PO_Log__c p = new PO_Log__c();
	
         p.Customer__c=a.Id;
         p.Opportunity__c=o.Id;
	     p.Order_Type__c='EOAT'; 
         insert p;
      
         p.Opportunity__c= o.Id;
         p.PO__c = '1223';
         p.Sales_Order_Number__c = '12453';
         p.Order_Type__c = 'Robot';
         p.Notes__c= 'text';
         p.Order_Configuration__c = 'ATC';
         p.Sales_Order_Number__c = '189345';
         p.AddPLogOpps__c = true;
      
         update p;
         
                 
       

        Yushin_Product__c ypd = new Yushin_Product__c(Discharge_Direction__c='Clamp Traverse');
        
         ypd.Opportunity__c=o.id;
         ypd.Account__c =a.Id; 
         ypd.Discharge_Direction__c='Clamp Traverse';
         ypd.IMM_Mfr__c='Arburg';
         ypd.IMM_Model__c='NT450';
         ypd.Plant_Voltage__c='110';
         ypd.Interface_Voltage__c='110 VDC';
         ypd.Equipment_Type__c = 'Robot';
         ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
         
        
         insert ypd;
        
       
         ypd.Account__c =a.Id ; 
         ypd.Discharge_Direction__c='Clamp Traverse';
         ypd.IMM_Mfr__c='Engel';
         ypd.IMM_Model__c='110t';
         ypd.Plant_Voltage__c='110';
         ypd.Interface_Voltage__c='110 VDC';
         ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
        
        update ypd;
        
        
        ypd.Equipment_Type__c = 'Other';
          ypd.Product_Detail_Report__c = 'Misc. Item';
          ypd.SPI_Reported__c=false;
          ypd.Date_Booked__c = Date.newInstance(2016, 12, 9);
          ypd.Date_Entered__c = Date.newInstance(2016, 12, 8);
          ypd.Sales_Order_Number__c = '1910678';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
         
          
          update ypd;
        
        
          ypd.Equipment_Type__c = 'Installation';
          ypd.Product_Detail_Report__c = 'Installation';
          ypd.SPI_Reported__c=false;
          ypd.Date_Booked__c = Date.newInstance(2016, 12, 9);
          ypd.Date_Entered__c = Date.newInstance(2016, 12, 8);
          ypd.Sales_Order_Number__c = '1910678';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
         
          
          update ypd;
          
          ypd.Equipment_Type__c = 'EOAT';
          ypd.Price__c = 499;
          ypd.Model__c='HOP 750';
          ypd.Status__c ='Quoted';
          ypd.Date_Booked__c = Date.newInstance(2016, 12, 9);
          ypd.Date_Entered__c = Date.newInstance(2016, 12, 8);
          
          
         
         
          update ypd;
           
          
          ypd.Equipment_Type__c = 'Safety Guarding';
          ypd.Product_Detail_Report__c = 'AUTO-SM';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
          
         
          update ypd;
          
          
          ypd.Equipment_Type__c = 'Conveyor';
          ypd.Price__c =45080;
          ypd.Status__c ='Sold';
          ypd.Date_Booked__c = Date.newInstance(2016, 12, 9);
          ypd.Date_Entered__c = Date.newInstance(2016, 12, 8);
          ypd.Quantity__c= 1;
          ypd.Product_Detail_Report__c = 'AUTO-SM';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
          
          
          update ypd;
           
          ypd.Price__c =45080;
          ypd.Equipment_Type__c = 'Servo Trav over 600';
          ypd.Model__c='FRA-1530S-22-11-C1  ';
          ypd.Status__c ='Sold';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
          
          
          update ypd;
           
         
          ypd.Price__c =45080;
          ypd.Equipment_Type__c = 'Adapter Plate';
          ypd.Product_Detail_Report__c='Misc. Item';
          ypd.Status__c ='Sold';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
          
          update ypd;
           
          ypd.Price__c =45080;
          ypd.Equipment_Type__c = 'A-Axis';
          ypd.Product_Detail_Report__c='EOAT-SM';
          ypd.RecordTypeId = recordTypes.get(recordTypeNames[0]).getRecordTypeId();
          ypd.Status__c ='Sold';
         
          update ypd;
          
          ypd.Price__c =45080;
          ypd.Equipment_Type__c = 'B-Axis';
          
          ypd.Status__c ='Sold';
         
          update ypd;
           
          ypd.Price__c =45080;
          ypd.Equipment_Type__c = 'Freight';
          ypd.Product_Detail_Report__c='Freight';
          
          update ypd;
           
          ypd.Price__c =45080;
          ypd.Equipment_Type__c = 'Degating Station';
          ypd.Product_Detail_Report__c='AUTO-SM';
          ypd.Status__c ='Sold';
           
          
          update ypd;
           
          ypd.Equipment_Type__c = 'Installation';
          ypd.Product_Detail_Report__c='Installation';
          ypd.Status__c ='Sold';
           
         
          update ypd;
           
          ypd.Equipment_Type__c = 'Hybrid';
          ypd.Product_Detail_Report__c='SM-Hybrid';
          
          ypd.Status__c ='Sold';
         
          
          update ypd;
           
          ypd.Equipment_Type__c = 'Software';
          ypd.Product_Detail_Report__c='Software';
          ypd.Status__c ='Sold';
           
         
          update ypd;
           
          ypd.Equipment_Type__c = 'Servo Traverse Super Large 1300 and greater';
          ypd.Model__c='RAII-a-3000SL';
          
          ypd.Status__c ='Sold';
          
          update ypd;
           
          ypd.Equipment_Type__c = 'Spacer';
          ypd.Product_Detail_Report__c='Misc. Item';
          ypd.Status__c ='Sold';
           
         
          update ypd;
           
          ypd.Equipment_Type__c = 'Stanchion';
          ypd.Status__c ='Quoted';
           
          
          update ypd;
          
          ypd.Equipment_Type__c = 'Servo Trav over 600';
          ypd.Model__c='YCII-800D-30-18';
          ypd.Product_Detail_Report__c='LG-YC';
          
          ypd.Status__c ='Sold';
          
          update ypd;
           
          ypd.Equipment_Type__c = 'System - SMALL';
          ypd.Product_Detail_Report__c='AUTO-SM';
          ypd.Status__c ='Sold';
          
         
          update ypd;
           
          ypd.Equipment_Type__c = 'Collaborative robot';
          ypd.Model__c='OB7';
          ypd.Product_Detail_Report__c='SPECIAL';
          ypd.Status__c ='Sold';
           
          
          update ypd;
           
          ypd.Equipment_Type__c = 'Side-entry (horz)';
          ypd.Model__c='SVR B50';
          ypd.Product_Detail_Report__c='SM-SE';
          
          update ypd;
           
          ypd.Equipment_Type__c = 'Side-entry (Vert)';
          ypd.Product_Detail_Report__c='SM-SE';
          
          ypd.Status__c ='Sold';
      
          update ypd;
           
          ypd.Equipment_Type__c = 'Parts';
          ypd.Product_Detail_Report__c='Misc. Item';
          ypd.Status__c ='Sold';
           
        
          update ypd;
          
          ypd.Equipment_Type__c = 'Safety Guarding';
          ypd.Product_Detail_Report__c='AUTO-SM';
          
          ypd.Status__c ='Sold';
         
          update ypd;
          
          ypd.Equipment_Type__c = 'System - MEDIUM';
          ypd.Product_Detail_Report__c='AUTO-SM';
          
          ypd.Status__c ='Quoted';
          ypd.Order_Config__c = 'Systems';
          ypd.Order_Type__c = 'Systems';
         
          update ypd;
               
          
           
                  
          

      

      test.stopTest();
    }
}




 
  • September 24, 2018
  • Like
  • 0
Let’s say you’re helping someone run the errands of daily life.  A trip may contain the following segments…each is its own record in an object that are all children of an umbrella trip object
  1. pick them up
  2. go to the doctor
  3. stop at the drug store
  4. get groceries
  5. return them home
Each segment includes driving directions between the specific addresses, so #3 includes the directions from the doctor’s office to the drug store and #4 starts at the drug store’s address.
 
Let’s say #3 changes because you have to go to a different drug store, then #4 will also need updating since its origin changed.
 
Typically, you’d update #3 using a before trigger.  No problem.  The trigger’s scope is naturally limited to the updated record (#3) and doesn’t include #4 which also needs updating since its origin changed.  As you’d expect, doing all of the updates in an after trigger causes trigger recursion.
 
Here’re the questions…
  1. How do I structure my trigger so it updates the changed record and related records without causing trigger recursion?
  2. Is it possible to expand the scope of the before trigger to include the related records?
For a bit of extra fun… Above includes mention driving directions.  Those are being populated by an @future call out to Google Maps, which also needs to update the same records without causing trigger recursion.
 
Note:  I've left out the code since issue is more about patterns and coding strategy.
 
Thanks for your help…
 
I have an angular application using salesforce to save data and allowing users to Authenticate. I am currently building a salesforce lightning application and I want to be able to use SSO to seemlessly log into the angular application without out having to authenticate.

If this is possible can you point me into the right direction with materials or examples that I can reference. Its a new concept for me.
  • September 24, 2018
  • Like
  • 0
Is there a way to detect in realtime (or near realtime) when a chat routed in omni (lightning) ends?

Current solutions we've explored / tried:
  1. Leveraging the Live Agent API, there is no method to get the current status of a chat or anything for us to see if chat has ended.
  2. Looking at LiveChatTranscript Status field, this doesn't get updated until after the agent closes the chat tab.
  3. Looking at LiveChatTranscriptEvent object, this too doesn't get written until after the chat tab is closed.
  4. Looking at tab info, we noticed a blue asterisk that appears in the tab when a chat is in progress, that goes away after it ends.  We thought to look in tab info for a boolean that gets flipped, but that turned up nothing.  There was no changes in the tab info from during the chat, to after it ended.  Nothing we could use here.
In case it was missed above, we're using omni routing in the "lightning experience", which pretty much wipes out all of the normal methods we'd use to tackle this, such as the `onChatEnd` method for classic console.  Can't use any of that in lightning.

You may be asking yourself "why don't you just wait until agent closes their tab".  Well, we'd love to, but the requirement is for us to leverage the omni api (specifically closeAgentWork) to clear the chat work item from omni BEFORE they cose their tab.  We have issues with agents leaving their tabs open by mistake and not getting routed new chats because of it.  So we need to clear omni work items for them as soon as the chat ends, but before they close their tab.

We've got the clearing of agent work worked out OK, we just need to automate it to a chat ending now.  Our organizations switch to lightning is depending on getting this sorted, so any ideas (even the obtuse ones) would be genuinely appreciated.
We have identified an issue where Cache.Session get() method does NOT return data stored in cache intermittently. We have put together a very tiny sample VisualForce page to demonstrate the problem. This sample page demonstrates that Cache.Session.getPartition(partitionName).get(KEY) returns NULL even if the data exists in cache for the given KEY. The page performs 100 Visualforce.remoting.Manager.invokeAction calls to a controller remote action. If the Apex code is not able to retrieve the data from cache it returns "Not Found" otherwise it returns "Found". Case # created with Salesforce.com 14311948.

See code and output sample below:

VisualForce Page:
<apex:page controller="CacheTestController" showChat="false" showHeader="false">

<div style="margin: 10px; font-size: 14px">
    <pre id="put">In progress ...</pre>
    <pre id="get"></pre>
</div>
 
<script>
    Visualforce.remoting.Manager.invokeAction(
        'CacheTestController.putCache', function(result, event) {
            document.getElementById('put').innerHTML = result;
        }, 
        { escape: false }
    );
 
    var tentative = 1;
 
    var timer = setInterval(function () {
 
        if (tentative == 100) clearInterval(timer);
 
        Visualforce.remoting.Manager.invokeAction(
            'CacheTestController.getCache', tentative, function (result, event) {
                document.getElementById('get').innerHTML += result + '<br/>';
            }, 
            { escape: false }
        );
 
        tentative++;
 
    }, 1000);
</script>
</apex:page>



Controller:
public class CacheTestController {
 
    private static final String PARTITION_NAME = 'FinancialServices';
    private static final String KEY = 'STAGE';
    private static final String VALUE = 'Any value';
      
    @RemoteAction
    public static String putCache() {
 
        Cache.Partition partition = Cache.Session.getPartition(PARTITION_NAME);
 
        partition.put(KEY, VALUE);
 
        return 'ok';
    }
 
    @RemoteAction
    public static String getCache(String tentative) {
 
        String found = 'Found: ' + tentative;
 
        Cache.Partition partition = Cache.Session.getPartition(PARTITION_NAME);
       
        String cacheValue = (String) partition.get(KEY);
       
        if (cacheValue == null) {
            found = 'Not Found: ' + tentative;
        }
       
        return found;
    }
}

Output:
Found: 1
Found: 2
Found: 3
Found: 4
Found: 5
Found: 6
Found: 7
Found: 8
Found: 9
Found: 10
Found: 11
Found: 12
Found: 13
Found: 14
Found: 15
Not Found: 16
Found: 17
Found: 18
Found: 19
Found: 20
Found: 21
Found: 22
Not Found: 23
Found: 24
Found: 25
Found: 26
Found: 27
Found: 28
Not Found: 29
Not Found: 30
Found: 31
Found: 32
Found: 33
Found: 34
Found: 35
Found: 36
Found: 37
Found: 38
Found: 39
Found: 40
Found: 41
Found: 42
Found: 43
Not Found: 44
Found: 45
Not Found: 46
Found: 47
Found: 48
Found: 49
Found: 50
Found: 51
Found: 52
Found: 53
Found: 54
Not Found: 55
Found: 56
Found: 57
Found: 58
Found: 59
Found: 60
Found: 61
Found: 62
Found: 63
Not Found: 64
Found: 65
Found: 66
Found: 67
Found: 68
Found: 69
Found: 70
Found: 71
Found: 72
Not Found: 73
Found: 74
Found: 75
Found: 76
Found: 77
Not Found: 78
Found: 79
Found: 80
Found: 81
Found: 82
Found: 83
Not Found: 84
Found: 85
Found: 86
Found: 87
Found: 88
Found: 89
Found: 90
Found: 91
Found: 92
Found: 93
Found: 94
Found: 95
Not Found: 96
Found: 97
Found: 98
Found: 99
Found: 100

 
Good afternoon, guys.
I'm realizing that my transcript of the live agent is taking too long to save, delay of the several minutes.
Is there any problem regarding this? Not all are saved the moment I close the chat.
someone help please?