Custom one-to-one messaging service b/w agents using LWC
Chatter is a best way for the users to collaborate with each other in Salesforce, but what if we want to give the user feel of the chat that is provided by whatsapp/messenger ...??The below code developed in LWC to create one's own personalized chatterbox to engage and connect.
chatterLWC.html
<template>
<lightning-card>
<div if:true={isLoading}">
<lightning-spinner alternative-text="Loading...">
</lightning-spinner>
</div>
<div if:false={isLoading}>
<h1 style="color: rgb(110, 41, 41); text-align: center;
font-size: 17px;">
<b>Collaboration chat for <i>{loggedInUser}</i></b>
</h1>
<div>
<template if:true={feeds.length} iterator:it={feed}>
<div class="slds-p-left_xx-large"
if:true={it.value.isSpeaker}
key={it.value.id}>
<lightning-layout multiple-rows key={it.value.id}
class="chatter-comments
slds-m-vertical_xx-small">
<lightning-layout-item size="6"
class="slds-p-left_small">
{it.value.speaker} said...
</lightning-layout-item>
<lightning-layout-item size="6"
class="slds-size_6-of-12 slds-p-right_small"
style="text-align: right;">
{it.value.dateCreated}
</lightning-layout-item>
<lightning-layout-item size="12"
class="slds-p-left_small">
<b><i>{it.value.comment}</i></b>
</lightning-layout-item>
<br/>
</lightning-layout>
</div>
<div class="slds-p-right_xx-large" if:false={it.value.isSpeaker}
key={it.value.id}>
<lightning-layout multiple-rows key={it.value.id}
class="chatter-comments
slds-m-vertical_xx-small"
if:false={it.value.isSpeaker}>
<lightning-layout-item size="6"
class="slds-p-left_small">
{it.value.speaker} said...
</lightning-layout-item>
<lightning-layout-item size="6"
class="slds-size_6-of-12 slds-p-right_small"
style="text-align: right;">
{it.value.dateCreated}
</lightning-layout-item>
<lightning-layout-item size="12"
class="slds-p-left_small">
<b><i>{it.value.comment}</i></b>
</lightning-layout-item>
<br/>
</lightning-layout>
</div>
</template>
</div>
<form onsubmit={handleSendChat}>
<lightning-layout>
<lightning-layout-item size="4"></lightning-layout-item>
<lightning-layout-item size="6">
<lightning-input label="Add a comment"
value={newComment} data-field="comment"
class="slds-m-vertical_x-small">
</lightning-input>
</lightning-layout-item>
<lightning-layout-item size="2">
<div class="slds-p-top_x-large">
<template if:false={sending}>
<lightning-button label="Send"
class="slds-float_left"
onclick={handleSendChat}>
</lightning-button>
</template>
<template if:true={sending}>
<lightning-button disabled
label="Sending..."
class="slds-float_left">
</lightning-button>
</template>
</div>
</lightning-layout-item>
</lightning-layout>
</form>
</div>
</lightning-card>
</template>
chatterLWC.js
import { LightningElement, wire } from 'lwc';
import getFeeds from '@salesforce/apex/chatterClass.getFeeds';
import insertChatterPosts from '@salesforce/apex/chatterClass.
insertChatterPosts';
import getCurrentUser from '@salesforce/apex/chatterClass.getCurrentUser'
export default class ChatterLWC extends LightningElement {
feeds = [];
sending = false;
newComment = '';
leadId = '';
isLoading = true;
loggedInUser = '';
@wire(getCurrentUser)
wiredCurrentUser({error, data}) {
if (error) {
} else if (data) {
this.loggedInUser = data;
}
}
connectedCallback(){
let address = window.location.href;
this.leadId = address.split('Lead/')[1].
split('/')[0];
this.getFeeds(this);
}
getFeeds(self){
this.isLoading = true;
getFeeds({
leadId : this.leadId
})
.then(result => {
this.feeds = result;
this.isLoading = false;
setTimeout(function () {
self.getFeeds(self);
}, 20000);
})
.catch(error => {
this.isLoading = false;
});
}
handleSendChat() {
this.isLoading = true;
this.sending = true;
this.newComment = this.template.querySelector
("[data-field='comment']")
.value;
if (!this.newComment || !this.newComment.trim())
{
this.sending = false;
return;
}
insertChatterPosts({
leadId: this.leadId,
comment: this.newComment
})
.then(result => {
this.feeds = result;
this.sending = false;
this.newComment = '';
this.isLoading = false;
})
.catch(error => {
this.sending = false;
this.isLoading = false;
});
}
}
chatterLWC.css
.chatter-comments {
background-color: #eee;
width: 95%;
}
chatterClass.cls
public without sharing class chatterClass {
@AuraEnabled(cacheable=true)
public static String getCurrentUser(){
return [SELECT Id, Name
FROM User
WHERE Id =:UserInfo.getUserId()
].Name;
}
@AuraEnabled
public static List<chatterPostWrapper> getFeeds(Id leadId) {
List<feedWrapper> feedWrappers = new List<feedWrapper>();
List<FeedItem> feedItems = [SELECT Id, ParentId, Body,
createdById,
createdBy.Name, CreatedDate
FROM FeedItem
WHERE parentId = :leadId
AND Type = 'TextPost'
ORDER BY CreatedDate
DESC ];
if(!feedItems.isEmpty()){
for(FeedItem item: feedItems){
String dateString = getMessageDate(item.createdDate);
String speakerName = item.createdBy.Name;
Boolean isSpeaker = false;
Id userId = UserInfo.getuserId();
if(userId == item.createdById){
isSpeaker = true;
}
feedWrappers.add(new feedWrapper(item.Id,
item.createdById,
speakerName,
dateString,
item.Body
.stripHtmlTags(),
isSpeaker));
}
}
return postWrappers;
}
@AuraEnabled
public static List<feedWrapper> insertChatterPosts(
Id leadId,
String comment) {
try{
FeedItem post = new FeedItem();
post.ParentId = leadId;
post.createdById = UserInfo.getuserId();
post.Body = comment;
post.type = 'TextPost';
INSERT post;
return getFeeds(leadId);
}catch(exception e){
system.debug('Something went wrong '+e.getMessage());
return null;
}
}
private static String getMessageDate(DateTime dTime){
Long dt1Long = dTime.getTime();
Long dt2Long = DateTime.now().getTime();
Long milliseconds = dt2Long - dt1Long;
Long seconds = milliseconds / 1000;
Long minutes = seconds / 60;
Long hours = minutes / 60;
Long days = hours / 24;
if(seconds < 60){
return String.valueOf(seconds + ' seconds ago');
}
if(minutes < 60){
return String.valueOf(minutes + ' minutes ago');
}
if(hours < 24){
return String.valueOf(hours + ' hours ago');
}
if(days < 4){
return String.valueOf(days + ' days ago');
}
else{
return String.valueOf(dTime.format('MMM-d-yyyy'));
}
}
public class feedWrapper{
@AuraEnabled
public String Id;
@AuraEnabled
public String speaker;
@AuraEnabled
public String dateCreated;
@AuraEnabled
public String comment;
@AuraEnabled
public Boolean isSpeaker;
public chatterPostWrapper(String id,
String createdById,
String speaker,
String dateCreated,
String comment,
Boolean isSpeaker){
this.Id = id;
this.speaker = speaker;
this.dateCreated = dateCreated;
this.comment = comment;
this.isSpeaker = isSpeaker;
}
}
}