Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# LWCTaskChecklist
# LWCTaskChecklist

Need to update this

![Example of LWC](img/demo.png)
62 changes: 62 additions & 0 deletions force-app/main/default/classes/TaskChecklistPanelController.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
*
*/
public with sharing class TaskChecklistPanelController {
public class TaskChecklistPanelControllerException extends Exception {
}

/**
*
*/
public static List<Task> getTasksByCaseId(Id caseId) {
Case caseInfo = [
SELECT
Id,
(
SELECT Id, Subject, IsCompleted__c, CompletedDateTime, Type
FROM Tasks
WHERE Type = 'Checklist_Item'
ORDER BY Subject ASC
)
FROM Case
WHERE Id = :caseId
];

return caseInfo.Tasks;
}

/**
*
*/
public static List<Task> updateTaskStatusById(
String caseId,
Set<String> idsToUpdate
) {
List<Task> toUpdate = new List<Task>();
for (String taskId : idsToUpdate) {
toUpdate.add(new Task(Id = taskId, Status = 'Completed'));
}

List<Database.SaveResult> updateResults = Database.update(
toUpdate,
true
);

String errorString = '';
Boolean hasErrors = false;
for (Database.SaveResult sr : updateResults) {
if (!sr.isSuccess()) {
hasErrors = true;
for (Database.Error de : sr.getErrors()) {
errorString += de.getMessage() + '\n';
}
}
}

if (hasErrors) {
throw new TaskChecklistPanelControllerException(errorString);
}

return getTasksByCaseId(caseId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@isTest
private class TaskChecklistPanelControllerTest {
// Placeholder
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<status>Active</status>
</ApexClass>
31 changes: 31 additions & 0 deletions force-app/main/default/classes/TaskChecklistPanelLWCController.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
*
*/
public with sharing class TaskChecklistPanelLWCController {
/**
*
*/
@AuraEnabled
public static List<Task> updateTaskStatuses(String caseId, String taskIds) {
try {
return TaskChecklistPanelController.updateTaskStatusById(
caseId,
(Set<String>) JSON.deserialize(taskIds, Set<String>.class)
);
} catch (Exception e) {
throw new AuraHandledException(e.getMessage());
}
}

/**
*
*/
@AuraEnabled
public static List<Task> getTasksForChecklist(Id caseId) {
try {
return TaskChecklistPanelController.getTasksByCaseId(caseId);
} catch (Exception e) {
throw new AuraHandledException(e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.clearfix::after {
content: "";
clear: both;
display: table;
}

.checklist-border {
border-radius: 3px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<div
class="slds-theme_default slds-p-around_x-small checklist-border clearfix"
>
<div id="header">
<h2
class="slds-text-heading_medium slds-text-align_center slds-m-bottom_small"
>
Task Checklist
</h2>
</div>
<div id="progress-bar" class="slds-m-bottom_small">
<lightning-progress-bar
value="{progress}"
size="large"
variant="circular"
></lightning-progress-bar>
</div>
<div id="checklist" class="slds-grid slds-wrap">
<template for:each="{taskList}" for:item="task">
<div key="{task}" class="slds-col slds-size_1-of-2">
<lightning-input
type="checkbox"
label="{task.Label}"
name="{task.Id}"
checked="{task.IsCompleted__c}"
onchange="{handleCheckboxChange}"
disabled="{task.IsCompleted__c}"
></lightning-input>
</div>
</template>
</div>
<div id="submit" class="slds-button slds-float_right">
<lightning-button
label="Update"
onclick="{handleUpdateTaskStatuses}"
disabled="{isSubmitBtnDisabled}"
></lightning-button>
</div>
</div>
</template>
109 changes: 109 additions & 0 deletions force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeated logic could be abstracted to another function:

updateTaskListAndProgress(result) {
  this.taskList = result;
  this.calculateProgress();
  this.taskIdsToUpdate = [];
  this.isSubmitBtnDisabled = false;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also order the functions as You would read them?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also also, where is Your test? 🧐

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still gotta learn the skill of Jest

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { LightningElement, api, track } from "lwc";
import getChecklistData from "@salesforce/apex/TaskChecklistPanelLWCController.getTasksForChecklist";
import updateChecklist from "@salesforce/apex/TaskChecklistPanelLWCController.updateTaskStatuses";

export default class TaskChecklistPanel extends LightningElement {
@api recordId; // Case record Id

@track taskList = []; // List of Tasks to be passed to the template for-loop
@track progress = 0; // Value to be fed to the progress bar
@track isSubmitBtnDisabled = false; // Used to disable the submit button while data is updated

taskIdsToUpdate = [];

/**
* On load, get our lists of Tasks realted to the Case
*/
connectedCallback() {
getChecklistData({ caseId: this.recordId })
.then((data) => {
this.processData(data);
})
.catch((error) => {
console.error("Error fetching data:", error);
});
}

/**
* Process data as it comes in. Update Labels with the completed date if completed
* Updates the progress bar
*/
processData(data) {
this.taskList = data;

// If Task is completed, show the completion date from formula field
for (const task of this.taskList) {
task.Label = task.Subject;

// Add completed date to label, can look silly with longer Subject string lengths
if (task.IsCompleted__c) {
task.Label += " (" + task.CompletedDateFormula__c + ")";
}
}

this.calculateProgress();
}

/**
* Calcaulates the value to assign to the progress bar
*/
calculateProgress() {
const totalTasksCompleted = this.taskList.filter(
(task) => task.IsCompleted__c
).length;

this.progress =
this.taskList.length === 0
? 0
: (totalTasksCompleted / this.taskList.length) * 100;
}

/**
* Called from a lightning-input: checkbox. If the box is now checked, adds the 'name' value (Task.Id)
* to the taskIdsToUpdate stack. If the box is now unchecked, removes the 'name' value (Task.Id) from
* the stack
* @param {*} event
*/
handleCheckboxChange(event) {
const checkbox = event.target;

if (checkbox.checked) {
// Add TaskId to list
this.taskIdsToUpdate.push(checkbox.name);
return;
}

// Remove TaskId from list
this.taskIdsToUpdate = this.taskIdsToUpdate.filter(
(taskId) => taskId !== checkbox.name
);
}

/**
* If there are values to update, submit them to be set to Completed
* then repopulate our data
*/
handleUpdateTaskStatuses() {
// Nothing is selected, so don't do anything
if (this.taskIdsToUpdate.length === 0) {
return;
}

this.isSubmitBtnDisabled = true;

updateChecklist({
caseId: this.recordId,
taskIds: JSON.stringify(this.taskIdsToUpdate),
})
.then((data) => {
this.processData(data);
// We did the things, enable the Submit button and empty the update list
this.isSubmitBtnDisabled = false;
this.taskIdsToUpdate = [];
})
.catch((error) => {
console.error("Error updating and fetching data:", error);
this.isSubmitBtnDisabled = false;
Comment on lines +105 to +106

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a global error handler and UI alert class these should be passed to?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet

});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>63.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
</targets>
</LightningComponentBundle>
Binary file added img/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions manifest/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>TaskChecklistPanelController</members>
<members>TaskChecklistPanelLWCController</members>
<members>TaskChecklistPanelControllerTest</members>
<name>ApexClass</name>
</types>
<types>
<members>taskChecklistPanel</members>
<name>LightningComponentBundle</name>
</types>
<version>63.0</version>
</Package>