diff --git a/README.md b/README.md index 22be0f3..05da54c 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# LWCTaskChecklist \ No newline at end of file +# LWCTaskChecklist + +Need to update this + +![Example of LWC](img/demo.png) diff --git a/force-app/main/default/classes/TaskChecklistPanelController.cls b/force-app/main/default/classes/TaskChecklistPanelController.cls new file mode 100644 index 0000000..11c9a0b --- /dev/null +++ b/force-app/main/default/classes/TaskChecklistPanelController.cls @@ -0,0 +1,62 @@ +/** + * + */ +public with sharing class TaskChecklistPanelController { + public class TaskChecklistPanelControllerException extends Exception { + } + + /** + * + */ + public static List 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 updateTaskStatusById( + String caseId, + Set idsToUpdate + ) { + List toUpdate = new List(); + for (String taskId : idsToUpdate) { + toUpdate.add(new Task(Id = taskId, Status = 'Completed')); + } + + List 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); + } +} diff --git a/force-app/main/default/classes/TaskChecklistPanelController.cls-meta.xml b/force-app/main/default/classes/TaskChecklistPanelController.cls-meta.xml new file mode 100644 index 0000000..5f399c3 --- /dev/null +++ b/force-app/main/default/classes/TaskChecklistPanelController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 63.0 + Active + diff --git a/force-app/main/default/classes/TaskChecklistPanelControllerTest.cls b/force-app/main/default/classes/TaskChecklistPanelControllerTest.cls new file mode 100644 index 0000000..76fd03a --- /dev/null +++ b/force-app/main/default/classes/TaskChecklistPanelControllerTest.cls @@ -0,0 +1,4 @@ +@isTest +private class TaskChecklistPanelControllerTest { + // Placeholder +} diff --git a/force-app/main/default/classes/TaskChecklistPanelControllerTest.cls-meta.xml b/force-app/main/default/classes/TaskChecklistPanelControllerTest.cls-meta.xml new file mode 100644 index 0000000..5f399c3 --- /dev/null +++ b/force-app/main/default/classes/TaskChecklistPanelControllerTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 63.0 + Active + diff --git a/force-app/main/default/classes/TaskChecklistPanelLWCController.cls b/force-app/main/default/classes/TaskChecklistPanelLWCController.cls new file mode 100644 index 0000000..fbaa7fc --- /dev/null +++ b/force-app/main/default/classes/TaskChecklistPanelLWCController.cls @@ -0,0 +1,31 @@ +/** + * + */ +public with sharing class TaskChecklistPanelLWCController { + /** + * + */ + @AuraEnabled + public static List updateTaskStatuses(String caseId, String taskIds) { + try { + return TaskChecklistPanelController.updateTaskStatusById( + caseId, + (Set) JSON.deserialize(taskIds, Set.class) + ); + } catch (Exception e) { + throw new AuraHandledException(e.getMessage()); + } + } + + /** + * + */ + @AuraEnabled + public static List getTasksForChecklist(Id caseId) { + try { + return TaskChecklistPanelController.getTasksByCaseId(caseId); + } catch (Exception e) { + throw new AuraHandledException(e.getMessage()); + } + } +} diff --git a/force-app/main/default/classes/TaskChecklistPanelLWCController.cls-meta.xml b/force-app/main/default/classes/TaskChecklistPanelLWCController.cls-meta.xml new file mode 100644 index 0000000..5f399c3 --- /dev/null +++ b/force-app/main/default/classes/TaskChecklistPanelLWCController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 63.0 + Active + diff --git a/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.css b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.css new file mode 100644 index 0000000..ec3e046 --- /dev/null +++ b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.css @@ -0,0 +1,9 @@ +.clearfix::after { + content: ""; + clear: both; + display: table; +} + +.checklist-border { + border-radius: 3px; +} diff --git a/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.html b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.html new file mode 100644 index 0000000..be6be54 --- /dev/null +++ b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.html @@ -0,0 +1,41 @@ + diff --git a/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js new file mode 100644 index 0000000..13a25c1 --- /dev/null +++ b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js @@ -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; + }); + } +} diff --git a/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js-meta.xml b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js-meta.xml new file mode 100644 index 0000000..c9afdbd --- /dev/null +++ b/force-app/main/default/lwc/taskChecklistPanel/taskChecklistPanel.js-meta.xml @@ -0,0 +1,8 @@ + + + 63.0 + true + + lightning__RecordPage + + \ No newline at end of file diff --git a/img/demo.png b/img/demo.png new file mode 100644 index 0000000..625c5b3 Binary files /dev/null and b/img/demo.png differ diff --git a/manifest/package.xml b/manifest/package.xml new file mode 100644 index 0000000..a542b74 --- /dev/null +++ b/manifest/package.xml @@ -0,0 +1,14 @@ + + + + TaskChecklistPanelController + TaskChecklistPanelLWCController + TaskChecklistPanelControllerTest + ApexClass + + + taskChecklistPanel + LightningComponentBundle + + 63.0 +