Sample Code:
Apex:
public class QueueAssignmentController {
@AuraEnabled( cacheable=true )
public static QueuePublicGroupWrapper fetchQueueAssignments( String strUserId ) {
QueuePublicGroupWrapper objQW = new QueuePublicGroupWrapper();
Set < String > setAssignedQueueIds = new Set < String >();
List < OptionWrapper > allQueues = new List < OptionWrapper >();
Set < String > setAssignedPublicGroupIds = new Set < String >();
List < OptionWrapper > allPublicGroups = new List < OptionWrapper >();
Set < String > groupTypes = new Set < String > { 'Queue', 'Regular' };
Set < Id > setGroupIds = new Set < Id >();
for ( GroupMember objGM : [ SELECT Id, Group.Name, GroupId, Group.Type FROM GroupMember WHERE UserOrGroupId =: strUserId AND Group.Type IN: groupTypes ] ) {
if ( objGM.Group.Type == 'Queue' ) {
setAssignedQueueIds.add( objGM.GroupId );
OptionWrapper objOW = new OptionWrapper();
objOW.label = objGM.Group.Name;
objOW.value = objGM.GroupId;
allQueues.add( objOW );
} else {
setAssignedPublicGroupIds.add( objGM.GroupId );
OptionWrapper objOW = new OptionWrapper();
objOW.label = objGM.Group.Name;
objOW.value = objGM.GroupId;
allPublicGroups.add( objOW );
}
setGroupIds.add( objGM.GroupId );
}
for ( Group objGroup : [ SELECT Id, Name, Type FROM Group WHERE Id NOT IN:setGroupIds AND Type IN: groupTypes ] ) {
if ( objGroup.Type == 'Queue' ) {
OptionWrapper objOW = new OptionWrapper();
objOW.label = objGroup.Name;
objOW.value = objGroup.Id;
allQueues.add( objOW );
} else {
OptionWrapper objOW = new OptionWrapper();
objOW.label = objGroup.Name;
objOW.value = objGroup.Id;
allPublicGroups.add( objOW );
}
}
objQW.availableQueues = allQueues;
objQW.availablePublicGroups = allPublicGroups;
objQW.selectedQueues = new List < String >();
objQW.selectedPublicGroups = new List < String >();
if ( setAssignedQueueIds.size() > 0 ) {
objQW.selectedQueues.addAll( setAssignedQueueIds );
}
if ( setAssignedPublicGroupIds.size() > 0 ) {
objQW.selectedPublicGroups.addAll( setAssignedPublicGroupIds );
}
return objQW;
}
@AuraEnabled
public static String addRemoveQueues( String strUserId, List < String > selectedQueues, List < String > updatedQueues,
List < String > selectedPublicGroups, List < String > updatedPublicGroups,
Boolean queuesUpdatedBool, Boolean publicGroupsUpdatedBool
) {
List < GroupMember > listGroupMembersForInsert = new List < GroupMember >();
Set < String > setGroupIds = new Set < String >();
try {
Set < String > setSelectedQueues = new Set < String >();
Set < String > setUpdatedQueues = new Set < String >();
Set < String > setSelectedPublicGroups = new Set < String >();
Set < String > setUpdatedPublicGroups = new Set < String >();
setSelectedQueues.addAll( selectedQueues );
setUpdatedQueues.addAll( updatedQueues );
setSelectedPublicGroups.addAll( selectedPublicGroups );
setUpdatedPublicGroups.addAll( updatedPublicGroups );
if ( queuesUpdatedBool ) {
for ( String strQueue : setUpdatedQueues ) {
if ( !setSelectedQueues.contains( strQueue ) ) {
GroupMember objGM = new GroupMember();
objGM.UserOrGroupId = strUserId;
objGM.GroupId = strqueue;
listGroupMembersForInsert.add( objGM );
}
}
for ( String strQueue : setSelectedQueues ) {
if ( !setUpdatedQueues.contains( strQueue ) ) {
setGroupIds.add( strQueue );
}
}
}
if ( publicGroupsUpdatedBool ) {
for ( String strPublicGroup : setUpdatedPublicGroups ) {
if ( !setSelectedPublicGroups.contains( strPublicGroup ) ) {
GroupMember objGM = new GroupMember();
objGM.UserOrGroupId = strUserId;
objGM.GroupId = strPublicGroup;
listGroupMembersForInsert.add( objGM );
}
}
}
for ( String strPublicGroup : setSelectedPublicGroups ) {
if ( !setUpdatedPublicGroups.contains( strPublicGroup ) ) {
setGroupIds.add( strPublicGroup );
}
}
if ( setGroupIds.size() > 0 ) {
delete [ SELECT Id FROM GroupMember WHERE UserOrGroupId =: strUserId AND GroupId IN: setGroupIds ];
}
if ( listGroupMembersForInsert.size() > 0 ) {
insert listGroupMembersForInsert;
}
return 'Successful';
} catch ( Exception e ) {
throw new AuraHandledException( e.getMessage() );
}
}
public class QueuePublicGroupWrapper {
@AuraEnabled
public List < OptionWrapper > availableQueues;
@AuraEnabled
public List < String > selectedQueues;
@AuraEnabled
public List < OptionWrapper > availablePublicGroups;
@AuraEnabled
public List < String > selectedPublicGroups;
}
public class OptionWrapper {
@AuraEnabled
public String value;
@AuraEnabled
public String label;
}
}
HTML:
<template>
<div class="slds-box slds-theme--default">
<lightning-record-edit-form object-api-name="Account">
<lightning-input-field field-name="User__c" onchange={handleUserChange}></lightning-input-field>
</lightning-record-edit-form>
<template if:true={showBool}>
<lightning-card>
<lightning-dual-listbox
label="Select/Remove Queues"
source-label="Available Queues"
selected-label="Selected Queues"
options={availableQueues}
value={selectedQueues}
onchange={handleQueuesChange}
class="slds-m-around_medium">
</lightning-dual-listbox><br/><br/>
<lightning-dual-listbox
label="Select/Remove Public Groups"
source-label="Available Public Groups"
selected-label="Selected Public Groups"
options={availablePublicGroups}
value={selectedPublicGroups}
onchange={handlePublicGroupsChange}
class="slds-m-around_medium">
</lightning-dual-listbox>
<p slot="footer">
<lightning-button
variant="brand"
label="Save"
onclick={saveChanges}
disabled={buttonBool}>
</lightning-button>
</p>
</lightning-card>
</template>
</div>
</template>
JavaScript:
import { LightningElement } from 'lwc';
import fetchQueueAssignments from '@salesforce/apex/QueueAssignmentController.fetchQueueAssignments';
import addRemoveQueues from '@salesforce/apex/QueueAssignmentController.addRemoveQueues';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class QueueAssignment extends LightningElement {
availableQueues;
selectedQueues;
updatedQueues;
availablePublicGroups;
selectedPublicGroups;
updatedPublicGroups;
showBool = false;
buttonBool = false;
userId;
handleUserChange( event ) {
let selectedUserId = event.target.value;
console.log( 'Selected User Id is ' + selectedUserId );
if ( selectedUserId ) {
this.userId = selectedUserId;
this.showBool = true;
} else {
this.showBool = false;
}
fetchQueueAssignments( { strUserId : this.userId } )
.then( data => {
console.log( 'Data ===> ' + data );
console.log( 'Records are ' + JSON.stringify( data ) );
this.availableQueues = data.availableQueues;
this.selectedQueues = data.selectedQueues;
this.updatedQueues = data.selectedQueues;
this.availablePublicGroups = data.availablePublicGroups;
this.selectedPublicGroups = data.selectedPublicGroups;
this.updatedPublicGroups = data.selectedPublicGroups;
})
.catch( error => {
this.dispatchEvent(
new ShowToastEvent( {
title: 'Error!!',
message: 'Some error occured. Please reach out to your Salesforce Admin for help!',
variant: 'error',
mode: 'sticky'
} ),
);
} )
}
handleQueuesChange( event ) {
const selectedOptionsList = event.detail.value;
console.log( 'Selected Options are ' + JSON.stringify( selectedOptionsList ) );
this.updatedQueues = selectedOptionsList;
console.log( 'Updated Selected Queues are ' + JSON.stringify( this.selectedQueues ) );
}
handlePublicGroupsChange( event ) {
const selectedOptionsList = event.detail.value;
console.log( 'Selected Options are ' + JSON.stringify( selectedOptionsList ) );
this.updatedPublicGroups = selectedOptionsList;
console.log( 'Updated Selected Public Groups are ' + JSON.stringify( this.selectedPublicGroups ) );
}
saveChanges() {
let queuesUpdatedBool = false;
let publicGroupsUpdatedBool = false;
console.log( 'selectedQueues is ' + JSON.stringify( this.selectedQueues ) );
console.log( 'updatedQueues is ' + JSON.stringify( this.updatedQueues ) );
console.log( 'selectedPublicGroups is ' + JSON.stringify( this.selectedPublicGroups ) );
console.log( 'updatedPublicGroups is ' + JSON.stringify( this.updatedPublicGroups ) );
if ( JSON.stringify( this.selectedQueues ) != JSON.stringify( this.updatedQueues ) ) {
queuesUpdatedBool = true;
}
if ( JSON.stringify( this.selectedPublicGroups ) != JSON.stringify( this.updatedPublicGroups ) ) {
publicGroupsUpdatedBool = true;
}
console.log( 'queuesUpdatedBool is ' + queuesUpdatedBool );
console.log( 'queuesUpdatedBool is ' + publicGroupsUpdatedBool );
if ( queuesUpdatedBool || publicGroupsUpdatedBool ) {
addRemoveQueues( { strUserId : this.userId,
selectedQueues : this.selectedQueues, updatedQueues : this.updatedQueues,
selectedPublicGroups : this.selectedPublicGroups, updatedPublicGroups : this.updatedPublicGroups,
queuesUpdatedBool : queuesUpdatedBool, publicGroupsUpdatedBool : publicGroupsUpdatedBool } )
.then( result => {
console.log( 'Result ' + JSON.stringify( result ) );
let message;
let variant;
if ( result === 'Successful' ) {
message = 'Successfully Processed!';
variant = 'success';
} else {
message = 'Some error occured. Please reach out to your Salesforce Admin for help!';
variant = 'error';
}
const toastEvent = new ShowToastEvent( {
title: 'Queue(s) and Public Group(s) Assignment',
message: message,
variant: variant
} );
this.dispatchEvent( toastEvent );
} )
.catch( error => {
console.log( 'Error ' + JSON.stringify( error ) );
} );
this.buttonBool = true;
} else {
alert( "No changes made!!!" );
}
}
}
Meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>52.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Output: