diff --git a/dlrs/main/classes/LookupRollupStatusCheckController.cls b/dlrs/main/classes/LookupRollupStatusCheckController.cls
index 79828cd9..88f53eec 100644
--- a/dlrs/main/classes/LookupRollupStatusCheckController.cls
+++ b/dlrs/main/classes/LookupRollupStatusCheckController.cls
@@ -40,6 +40,19 @@ public with sharing class LookupRollupStatusCheckController {
];
}
+ /**
+ * Get count of scheduled items older than yesterday
+ * The assumption is that normal processing should have handled these
+ */
+ @AuraEnabled(Cacheable=true)
+ public static Integer getOutstandingScheduledItemsForLookup(String lookupID) {
+ return [
+ SELECT COUNT()
+ FROM LookupRollupSummaryScheduleItems__c
+ WHERE LookupRollupSummary2__c = :lookupID AND LastModifiedDate < YESTERDAY
+ ];
+ }
+
/**
* Check if the rollup has a Full Calculate schedule
*/
diff --git a/dlrs/main/lwc/flexiblePath/flexiblePath.html b/dlrs/main/lwc/flexiblePath/flexiblePath.html
index 9a677ba6..dc6d209f 100644
--- a/dlrs/main/lwc/flexiblePath/flexiblePath.html
+++ b/dlrs/main/lwc/flexiblePath/flexiblePath.html
@@ -90,9 +90,7 @@
-
Next Action: {nextActionLabel}
+
s.status === "current")?.label;
- if (!nextLabel) {
- nextLabel = this.steps.find((s) => s.status === "incomplete")?.label;
- }
- return nextLabel;
+ let nextCurrent = this.nextAction;
+ return nextCurrent?.nextActionLabel ?? nextCurrent?.label;
+ }
+
+ get nextAction() {
+ return (
+ this.steps.find((s) => s.status === "current") ??
+ this.steps.find((s) => s.status === "incomplete")
+ );
}
handleNextActionClick() {
+ const nextAction = this.nextAction;
this.dispatchEvent(
new CustomEvent("nextactionclick", {
detail: {
- label: this.nextActionLabel
+ label: nextAction.label,
+ name: nextAction.name
}
})
);
diff --git a/dlrs/main/lwc/manageRollups/manageRollups.js b/dlrs/main/lwc/manageRollups/manageRollups.js
index 6dbb84cf..fdcfa1bf 100644
--- a/dlrs/main/lwc/manageRollups/manageRollups.js
+++ b/dlrs/main/lwc/manageRollups/manageRollups.js
@@ -1,10 +1,12 @@
-import { LightningElement } from "lwc";
+import { LightningElement, wire } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import LightningConfirm from "lightning/confirm";
+import { NavigationMixin, CurrentPageReference } from "lightning/navigation";
+
import getAllRollupConfigs from "@salesforce/apex/RollupEditorController.getAllRollupConfigs";
import deleteRollupConfig from "@salesforce/apex/RollupEditorController.deleteRollupConfig";
import USER_ID from "@salesforce/user/Id";
-import RollupEditorModal from "c/rollupEditorModal";
+import RollupEditor from "c/rollupEditor";
import {
subscribe,
@@ -13,7 +15,7 @@ import {
isEmpEnabled
} from "lightning/empApi";
-export default class ManageRollups extends LightningElement {
+export default class ManageRollups extends NavigationMixin(LightningElement) {
dtColumns = [
{
type: "button",
@@ -29,21 +31,21 @@ export default class ManageRollups extends LightningElement {
}
},
{
- label: "Parent",
- fieldName: "ParentObject__c"
+ label: "Child",
+ fieldName: "ChildObject__c"
},
{
label: "Field To Aggregate",
fieldName: "FieldToAggregate__c"
},
- {
- label: "Child",
- fieldName: "ChildObject__c"
- },
{
label: "Relationship Field",
fieldName: "RelationshipField__c"
},
+ {
+ label: "Parent",
+ fieldName: "ParentObject__c"
+ },
{
label: "Operation",
fieldName: "AggregateOperation__c"
@@ -54,7 +56,8 @@ export default class ManageRollups extends LightningElement {
},
{
label: "Active",
- fieldName: "Active__c"
+ fieldName: "Active__c",
+ type: "boolean"
},
{
type: "button-icon",
@@ -67,6 +70,9 @@ export default class ManageRollups extends LightningElement {
}
];
+ @wire(CurrentPageReference)
+ pageRef;
+
// We only want events for which we've been assigned as the recipient
channelName = `/event/UserNotification__e?Recipient__c='${USER_ID.substring(
1,
@@ -125,15 +131,32 @@ export default class ManageRollups extends LightningElement {
}
async openEditor(rollupName) {
- const result = await RollupEditorModal.open({
- // `label` is not included here in this example.
- // it is set on lightning-modal-header instead
+ const result = await RollupEditor.open({
size: "large",
description: "Rollup Config Editor",
rollupName
});
- if (result?.action === "delete") {
- this.requestDelete(result.rollupName);
+
+ switch (result?.action) {
+ case "delete":
+ this.requestDelete(result.rollupName);
+ break;
+ case "deloyStart":
+ // const rollupName = result.rollupName;
+ this.dispatchEvent(
+ new ShowToastEvent({
+ title: "Deployment Started",
+ message:
+ "Started Metadata Record Upates in Deployment " + result.jobId,
+ variant: "info"
+ })
+ );
+ break;
+ case "navigate":
+ this[NavigationMixin.Navigate](result.config);
+ break;
+ default:
+ break;
}
}
diff --git a/dlrs/main/lwc/rollupEditor/rollupEditor.html b/dlrs/main/lwc/rollupEditor/rollupEditor.html
index 34745302..f44f6743 100644
--- a/dlrs/main/lwc/rollupEditor/rollupEditor.html
+++ b/dlrs/main/lwc/rollupEditor/rollupEditor.html
@@ -1,482 +1,496 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Pick the child object, the field that holds your data, and the
- field that holds the reference to the parent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Pick the child object, the field that holds your data, and the
+ field that holds the reference to the parent.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- Pick the parent object you want to roll up to and the field that
- will hold the resulting value
-
-
-
-
-
-
-
-
+
+
+
+
+ Pick the parent object you want to roll up to and the field that
+ will hold the resulting value
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
- Define how child records will be qualified for the rollup
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Select the type and configuration of the rollup action
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ Define how child records will be qualified for the rollup
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Select the type and configuration of the rollup action
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dlrs/main/lwc/rollupEditor/rollupEditor.js b/dlrs/main/lwc/rollupEditor/rollupEditor.js
index 58be3623..09524e70 100644
--- a/dlrs/main/lwc/rollupEditor/rollupEditor.js
+++ b/dlrs/main/lwc/rollupEditor/rollupEditor.js
@@ -1,5 +1,9 @@
-import { api, LightningElement, track, wire } from "lwc";
-import { ShowToastEvent } from "lightning/platformShowToastEvent";
+import { api, track, wire } from "lwc";
+
+import LightningModal from "lightning/modal";
+
+import { PATH_STATES } from "c/flexiblePath";
+
import getRollupConfig from "@salesforce/apex/RollupEditorController.getRollupConfig";
import validateRollupConfig from "@salesforce/apex/RollupEditorController.validateRollupConfig";
import saveRollupConfig from "@salesforce/apex/RollupEditorController.saveRollupConfig";
@@ -9,13 +13,8 @@ import getFullCalculatePageUrl from "@salesforce/apex/RollupEditorController.get
import getScheduleCalculatePageUrl from "@salesforce/apex/RollupEditorController.getScheduleCalculatePageUrl";
import hasChildTriggerDeployed from "@salesforce/apex/LookupRollupStatusCheckController.hasChildTriggerDeployed";
import getScheduledJobs from "@salesforce/apex/LookupRollupStatusCheckController.getScheduledJobs";
+import getOutstandingScheduledItemsForLookup from "@salesforce/apex/LookupRollupStatusCheckController.getOutstandingScheduledItemsForLookup";
-import { NavigationMixin } from "lightning/navigation";
-const PATH_VALUES = {
- complete: "complete",
- current: "current",
- incomplete: "incomplete"
-};
const DEFAULT_ROLLUP_VALUES = Object.freeze({
Active__c: false,
CalculationMode__c: "Scheduled",
@@ -24,33 +23,71 @@ const DEFAULT_ROLLUP_VALUES = Object.freeze({
const STEP_TEMPLATES = Object.freeze({
default: [
- { label: "Configure", status: PATH_VALUES.current },
- { label: "...", status: PATH_VALUES.incomplete }
+ {
+ label: "Configure",
+ name: "save",
+ nextActionLabel: "Save",
+ status: PATH_STATES.current
+ },
+ { label: "...", status: PATH_STATES.incomplete }
],
Realtime: [
- { label: "Configure", status: PATH_VALUES.complete },
- { label: "Deploy Trigger", status: PATH_VALUES.incomplete },
- { label: "Activate", status: PATH_VALUES.incomplete }
+ {
+ label: "Configure",
+ name: "save",
+ nextActionLabel: "Save",
+ status: PATH_STATES.complete
+ },
+ {
+ label: "Deploy Trigger",
+ name: "deployTrigger",
+ nextActionLabel: "Manage Triggers",
+ status: PATH_STATES.incomplete
+ },
+ { label: "Activate", name: "activate", status: PATH_STATES.incomplete }
],
Scheduled: [
- { label: "Configure", status: PATH_VALUES.complete },
- { label: "Schedule Job", status: PATH_VALUES.incomplete },
- { label: "Deploy Trigger", status: PATH_VALUES.incomplete },
- { label: "Activate", status: PATH_VALUES.incomplete }
+ {
+ label: "Configure",
+ name: "save",
+ nextActionLabel: "Save",
+ status: PATH_STATES.complete
+ },
+ {
+ label: "Schedule Job",
+ name: "scheduleJob",
+ nextActionLabel: "Schedule",
+ status: PATH_STATES.incomplete
+ },
+ {
+ label: "Deploy Trigger",
+ name: "deployTrigger",
+ nextActionLabel: "Manage Triggers",
+ status: PATH_STATES.incomplete
+ },
+ { label: "Activate", name: "activate", status: PATH_STATES.incomplete }
],
other: [
- { label: "Configure", status: PATH_VALUES.complete },
- { label: "Activate", status: PATH_VALUES.incomplete }
+ {
+ label: "Configure",
+ name: "save",
+ nextActionLabel: "Save",
+ status: PATH_STATES.complete
+ },
+ { label: "Activate", name: "activate", status: PATH_STATES.incomplete }
]
});
-export default class RollupEditor extends NavigationMixin(LightningElement) {
+export default class RollupEditor extends LightningModal {
isLoading = false;
-
childTriggerIsDeployed = false;
+ rollupId;
@wire(getScheduledJobs)
scheduledJobCount;
+ @wire(getOutstandingScheduledItemsForLookup, { lookupID: "$rollupId" })
+ outstandingScheduledItems;
+
openAccordianSections = [
"Information",
"ChildObject",
@@ -84,9 +121,7 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
}
get cardHeader() {
- return this.rollup.DeveloperName
- ? this.rollup.DeveloperName
- : "Lookup Rollup Summary Creation Wizard";
+ return this.rollup.Id ? `Edit ${this.rollup.Label}` : "Create Rollup";
}
get saveButtonLabel() {
@@ -105,6 +140,21 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
return this.rollup.Id && this.rollup.Active__c;
}
+ get scheduledItemsError() {
+ if (
+ !this.outstandingScheduledItems ||
+ !this.outstandingScheduledItems?.data
+ ) {
+ return null;
+ }
+
+ return `This rollup has ${this.outstandingScheduledItems} outstanding scheduled items`;
+ }
+
+ get relationshipCriteriaPlaceholder() {
+ return "Status__c\r\nDays__c";
+ }
+
async getRollup() {
if (!this.rollupName) {
this.rollup = { ...DEFAULT_ROLLUP_VALUES };
@@ -113,6 +163,7 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
this.rollup = await getRollupConfig({
rollupName: this.rollupName
});
+ this.rollupId = this.rollup.Id;
} catch (error) {
this.errors.record = [error.message];
}
@@ -151,21 +202,21 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
});
for (let s of STEP_TEMPLATES[this.rollup.CalculationMode__c] ||
STEP_TEMPLATES.other) {
- if (s.label === "Deploy Trigger") {
+ if (s.name === "deployTrigger") {
s.status = this.childTriggerIsDeployed
- ? PATH_VALUES.complete
- : PATH_VALUES.incomplete;
+ ? PATH_STATES.complete
+ : PATH_STATES.incomplete;
}
- if (s.label === "Schedule Job") {
+ if (s.name === "scheduleJob") {
s.status =
this.scheduledJobCount.data > 0
- ? PATH_VALUES.complete
- : PATH_VALUES.incomplete;
+ ? PATH_STATES.complete
+ : PATH_STATES.incomplete;
}
- if (s.label === "Activate") {
+ if (s.name === "activate") {
s.status = this.rollup.Active__c
- ? PATH_VALUES.complete
- : PATH_VALUES.incomplete;
+ ? PATH_STATES.complete
+ : PATH_STATES.incomplete;
}
newSteps.push(s);
}
@@ -193,8 +244,7 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
}
cancelClickHandler() {
- const evt = new CustomEvent("cancel");
- this.dispatchEvent(evt);
+ this.close();
}
cloneClickHandler() {
@@ -203,10 +253,7 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
}
deleteClickHandler() {
- const evt = new CustomEvent("requestdelete", {
- detail: { rollupName: this.rollup.DeveloperName }
- });
- this.dispatchEvent(evt);
+ this.close({ action: "delete", rollupName: this.rollup.DeveloperName });
}
activateClickHandler() {
@@ -219,19 +266,25 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
this.runSave();
}
+ rollupTypeChangeHandler(event) {
+ this.rollup.AggregateOperation__c = event.detail.value;
+ }
+
pathClickHandler(event) {
console.log("Path clicked", event.detail.label);
- switch (event.detail.label) {
- case "Deploy Trigger":
+ switch (event.detail.name) {
+ case "deployTrigger":
this.manageTriggerHandler();
break;
-
- case "Activate":
+ case "activate":
this.activateClickHandler();
break;
- case "Schedule Job":
+ case "scheduleJob":
console.error("Job Schedule UI not implemented");
break;
+ case "save":
+ this.runSave();
+ break;
default:
console.error("Unexpected action", event.detail.label);
break;
@@ -239,34 +292,40 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
}
async manageTriggerHandler() {
- // TODO: return to this page, maybe to this rollup??
const url = await getManageTriggerPageUrl({ rollupId: this.rollup.Id });
- this[NavigationMixin.Navigate]({
- type: "standard__webPage",
- attributes: {
- url
+ this.close({
+ action: "navigate",
+ config: {
+ type: "standard__webPage",
+ attributes: {
+ url
+ }
}
});
}
async recalculateNowHandler() {
- // TODO: return to this page, maybe to this rollup??
const url = await getFullCalculatePageUrl({ rollupId: this.rollup.Id });
- this[NavigationMixin.Navigate]({
- type: "standard__webPage",
- attributes: {
- url
+ this.close({
+ action: "navigate",
+ config: {
+ type: "standard__webPage",
+ attributes: {
+ url
+ }
}
});
}
async schedulRecalculateHandler() {
- // TODO: return to this page, maybe to this rollup??
const url = await getScheduleCalculatePageUrl({ rollupId: this.rollup.Id });
- this[NavigationMixin.Navigate]({
- type: "standard__webPage",
- attributes: {
- url
+ this.close({
+ action: "navigate",
+ config: {
+ type: "standard__webPage",
+ attributes: {
+ url
+ }
}
});
}
@@ -306,20 +365,12 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
const jobId = await saveRollupConfig({
rollup: JSON.stringify(this.rollup)
});
- const evt = new ShowToastEvent({
- title: "Deployment Started",
- message: "Started Metadata Record Upates in Deployment " + jobId,
- variant: "info"
+
+ this.close({
+ action: "deloyStart",
+ jobId,
+ rollupName: this.rollup.DeveloperName
});
- this.dispatchEvent(evt);
- this.dispatchEvent(
- new CustomEvent("deploystarted", {
- detail: {
- rollup: this.rollup,
- jobId
- }
- })
- );
this.isLoading = false;
}
@@ -392,7 +443,7 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
{ label: "Count", value: "Count" },
{ label: "Count Distinct", value: "Count Distinct" },
{ label: "Concatenate", value: "Concatenate" },
- { label: "Concatenate Distinct", value: " Concatenate Distinct" },
+ { label: "Concatenate Distinct", value: "Concatenate Distinct" },
{ label: "First", value: "First" },
{ label: "Last", value: "Last" }
];
@@ -413,4 +464,22 @@ export default class RollupEditor extends NavigationMixin(LightningElement) {
{ label: "System", value: "System" }
];
}
+
+ get shouldDisableConcatDelim() {
+ return !["Concatenate", "Concatenate Distinct"].includes(
+ this.rollup.AggregateOperation__c
+ );
+ }
+
+ get shouldDisableFieldToOrderBy() {
+ return !["Concatenate", "Concatenate Distinct", "First", "Last"].includes(
+ this.rollup.AggregateOperation__c
+ );
+ }
+
+ get shouldDisableRowLimit() {
+ return !["Concatenate", "Concatenate Distinct", "Last"].includes(
+ this.rollup.AggregateOperation__c
+ );
+ }
}
diff --git a/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.html b/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.html
deleted file mode 100644
index 13f82f7b..00000000
--- a/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
diff --git a/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.js b/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.js
deleted file mode 100644
index b1b0f402..00000000
--- a/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { api } from "lwc";
-import LightningModal from "lightning/modal";
-
-export default class RollupEditorModal extends LightningModal {
- @api rollupName;
-
- handleCancelRequest() {
- this.close();
- }
-
- handleRequestDelete() {
- this.close({ action: "delete", rollupName: this.rollupName });
- }
-}
diff --git a/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.js-meta.xml b/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.js-meta.xml
deleted file mode 100644
index 6127d855..00000000
--- a/dlrs/main/lwc/rollupEditorModal/rollupEditorModal.js-meta.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- 59.0
- false
-
\ No newline at end of file