+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchController.js b/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchController.js
index 669865a2f..e4f9d7cf4 100755
--- a/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchController.js
+++ b/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchController.js
@@ -1,4 +1,10 @@
({
+ /**
+ * Initializes the component by setting up the field list for recordData to watch
+ * @param {Component} component - The component instance
+ * @param {Object} event - The init event
+ * @param {Object} helper - The component helper
+ */
doInit: function(component, event, helper) {
// By Default set the Id field as this is required
var tempFieldList = ['Id'];
@@ -13,16 +19,34 @@
component.set("v.fieldNameList", tempFieldList);
},
+ /**
+ * Opens the modal dialog for flow execution
+ * @param {Component} component - The component instance
+ * @param {Object} event - The event that triggered this action
+ * @param {Object} helper - The component helper
+ */
openModal : function(component, event, helper) {
component.set('v.openModal',true);
},
+ /**
+ * Closes the modal dialog
+ * @param {Component} component - The component instance
+ * @param {Object} event - The event that triggered this action
+ * @param {Object} helper - The component helper
+ */
closeModal : function(component, event, helper) {
component.set('v.openModal',false);
},
+ /**
+ * Handles flow status change events and closes modal when flow finishes
+ * @param {Component} component - The component instance
+ * @param {Object} event - The flow status change event
+ * @param {Object} helper - The component helper
+ */
flowStatusChange : function( component, event, helper ) {
if ( event.getParam( "status" ).indexOf( "FINISHED" ) !== -1 ) {
component.set( "v.openModal", false );
@@ -30,33 +54,44 @@
}
},
+ /**
+ * Handles record update events from force:recordData
+ * Determines which flow to launch based on change type and field conditions
+ * @param {Component} component - The component instance
+ * @param {Object} event - The record update event from force:recordData
+ * @param {Object} helper - The component helper
+ */
recordUpdated: function(component, event, helper) {
- console.log('entering recordUpdate');
+ helper.debugLog(component, 'entering recordUpdate');
var eventParams = event.getParams();
- // If both Field Change and Field Value are not null then set to isChangedRecord to true
- // This will then populate the users field value within the fields list
- if(component.get("v.fieldChange") != null && component.get("v.fieldValue") != null ){
- component.set("v.isChangedRecord", true);
- console.log('fieldChange',component.get("v.fieldChange"));
- console.log('fieldValue',component.get("v.fieldValue"));
- // Make sure there was an edited field and we just edited a record
- if ( eventParams.changedFields && eventParams.changeType === "CHANGED") {
- console.log('eventParams.changedFields', eventParams.changedFields);
- var changed = JSON.parse(JSON.stringify(eventParams.changedFields));
- //console.log('changed', changed);
- //console.log('changed.dynamic', changed[component.get("v.fieldCompare")]);
- if (changed[component.get("v.fieldCompare")]) {
- console.log('changed.dynamic.value', changed[component.get("v.fieldCompare")].value);
- if ( changed[component.get("v.fieldCompare")].value.toString() === component.get("v.fieldValue") ) {
- //console.log('hit');
- component.set("v.targetFlowName", component.get("v.editFlowName"));
- helper.processChangeEvent(component, eventParams);
- }
- }
+ // Check if field conditions are configured
+ var fieldChange = component.get("v.fieldChange");
+ var fieldValue = component.get("v.fieldValue");
+ var fieldConditionsConfigured = (fieldChange !== null && fieldChange !== undefined &&
+ fieldValue !== null && fieldValue !== undefined);
+
+ // Field conditions only apply to CHANGED events
+ // For REMOVED and LOADED events, proceed with normal flow launching logic
+ if (fieldConditionsConfigured && eventParams.changeType === "CHANGED") {
+ // Field conditions are configured and this is a CHANGED event - check if value matches
+ if (helper.checkFieldValueMatch(component, eventParams)) {
+ component.set("v.isChangedRecord", true);
+ helper.debugLog(component, 'fieldChange', fieldChange);
+ helper.debugLog(component, 'fieldValue', fieldValue);
+ helper.debugLog(component, 'eventParams.changedFields', eventParams.changedFields);
+
+ // Field value matches, launch the edit flow
+ component.set("v.targetFlowName", component.get("v.editFlowName"));
+ helper.processChangeEvent(component, eventParams);
+ } else {
+ // Field conditions are configured but value doesn't match - don't launch any flow
+ helper.debugLog(component, 'Field conditions configured but value does not match - skipping flow launch');
+ return;
}
} else {
- console.log('changeType: ' + eventParams.changeType);
+ // No field conditions configured OR this is REMOVED/LOADED event - proceed with normal flow launching logic
+ helper.debugLog(component, `changeType: ${eventParams.changeType}`);
// Get Flow To Use
if(eventParams.changeType === "CHANGED") {
component.set("v.targetFlowName", component.get("v.editFlowName"));
@@ -66,15 +101,15 @@
component.set("v.targetFlowName", component.get("v.loadFlowName"));
}
-
// Launch Flow
if(eventParams.changeType === "CHANGED" || eventParams.changeType === "REMOVED") {
helper.processChangeEvent(component, eventParams);
} else if( eventParams.changeType === "LOADED") {
helper.processChangeEvent(component, eventParams);
} else if(eventParams.changeType === "ERROR") {
- console.log(eventParams);
- console.log('Update event received Error: ' + component.get("v.error"));
+ // Show error toast to user
+ var errorMessage = component.get("v.error") || component.get("v.recordError") || 'An error occurred while loading the record.';
+ helper.showErrorToast(component, 'Record Error', errorMessage);
}
}
}
diff --git a/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchHelper.js b/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchHelper.js
index 3af16e436..d9905261f 100755
--- a/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchHelper.js
+++ b/lightning_page_components/DetectAndLaunch/force-app/main/default/aura/detectAndLaunch/detectAndLaunchHelper.js
@@ -1,38 +1,131 @@
({
+ /**
+ * Debug logging helper - only logs if debugMode is enabled
+ * @param {Component} component - The component instance
+ * @param {String} message - Message to log
+ * @param {*} data - Optional data to log
+ */
+ debugLog: function(component, message, data) {
+ if (component.get("v.debugMode")) {
+ if (data !== undefined) {
+ console.log(message, data);
+ } else {
+ console.log(message);
+ }
+ }
+ },
+
+ /**
+ * Shows an error toast notification to the user
+ * @param {Component} component - The component instance
+ * @param {String} title - Title of the error toast
+ * @param {String} message - Error message to display
+ */
+ showErrorToast: function(component, title, message) {
+ var notifLib = component.find("notifLib");
+ if (notifLib) {
+ notifLib.showToast({
+ "title": title || "Error",
+ "message": message,
+ "variant": "error",
+ "mode": "sticky"
+ });
+ }
+ // Also log to console for debugging
+ console.error(title + ":", message);
+ },
+
+ /**
+ * Checks if a field value matches the expected value when a record is changed
+ * @param {Component} component - The component instance
+ * @param {Object} eventParams - Event parameters from force:recordData
+ * @returns {Boolean} - True if field value matches, false otherwise
+ */
+ checkFieldValueMatch: function(component, eventParams) {
+ var fieldChange = component.get("v.fieldChange");
+ var fieldValue = component.get("v.fieldValue");
+
+ // Check if both fieldChange and fieldValue are configured
+ if (fieldChange === null || fieldChange === undefined ||
+ fieldValue === null || fieldValue === undefined) {
+ return false;
+ }
+
+ // Only check field values on CHANGED events
+ if (eventParams.changeType !== "CHANGED") {
+ return false;
+ }
+
+ // Check if changedFields exists
+ if (!eventParams.changedFields) {
+ return false;
+ }
+
+ // Get the field data from changed fields
+ var changed = JSON.parse(JSON.stringify(eventParams.changedFields));
+ var fieldKey = component.get("v.fieldCompare");
+ var fieldData = changed[fieldKey];
+
+ // Check if field exists and has a non-null, non-undefined value
+ if (!fieldData || fieldData.value === null || fieldData.value === undefined) {
+ return false;
+ }
+
+ // Compare the field value
+ var newValue = fieldData.value.toString();
+ this.debugLog(component, 'changed.dynamic.value', newValue);
+
+ return newValue === fieldValue;
+ },
+
+ /**
+ * Processes record change events and launches appropriate flows
+ * Prevents execution in page builder mode and routes to appropriate launch method
+ * @param {Component} component - The component instance
+ * @param {Object} eventParams - Event parameters from force:recordData
+ * @param {String} eventParams.changeType - Type of change: CHANGED, REMOVED, or LOADED
+ */
processChangeEvent : function(component, eventParams) {
- console.log('entering processChangeEvent');
+ this.debugLog(component, 'entering processChangeEvent');
// Get current URL
// If URL contains flexipageEditor do nothing
var currentUrl = window.location.href;
- console.log('currentUrl is: ' + currentUrl);
+ this.debugLog(component, `currentUrl is: ${currentUrl}`);
if (currentUrl.includes('flexipageEditor')) {
- console.log('currentUrl includes flexipageEditor');
+ this.debugLog(component, 'currentUrl includes flexipageEditor');
return;
} else {
if(eventParams.changeType === "CHANGED") {
- console.log ('changeType is: ' + eventParams.changeType);
+ this.debugLog(component, `changeType is: ${eventParams.changeType}`);
this.callFlow(component, eventParams);
} else if(eventParams.changeType === "REMOVED") {
- console.log('record is being deleted');
+ this.debugLog(component, 'record is being deleted');
//the other launch paths don't work well when the underlying page is deleted
- var targetUrl = '/flow/' + component.get("v.targetFlowName") + '?recordId=' + component.get("v.recordId"); //added input variable
- console.log('targetURL is: ' + targetUrl);
+ var targetUrl = `/flow/${component.get("v.targetFlowName")}?recordId=${component.get("v.recordId")}`;
+ this.debugLog(component, `targetURL is: ${targetUrl}`);
window.open(targetUrl);
} else if(eventParams.changeType === "LOADED") {
- console.log ('changeType is: ' + eventParams.changeType);
+ this.debugLog(component, `changeType is: ${eventParams.changeType}`);
this.callFlow(component, eventParams);
}
}
},
+ /**
+ * Launches a flow in either modal or modeless mode based on launchMode setting
+ * Handles both console and standard UI navigation
+ * @param {Component} component - The component instance
+ * @param {Object} eventParams - Event parameters from force:recordData
+ * @param {String} eventParams.changeType - Type of change: CHANGED, REMOVED, or LOADED
+ */
callFlow : function(component, eventParams) {
- console.log('entering callFlow');
- console.log ('changeType is: ' + eventParams.changeType);
+ this.debugLog(component, 'entering callFlow');
+ this.debugLog(component, `changeType is: ${eventParams.changeType}`);
var flowApiName = component.get("v.targetFlowName");
- if (flowApiName == null || flowApiName == undefined) {
- console.log('flowApiName is null or undefined');
+ if (!flowApiName) {
+ this.debugLog(component, 'flowApiName is null or undefined');
} else {
- if(component.get("v.launchMode") == 'Modal') {
+ if(component.get("v.launchMode") === 'Modal') {
component.set('v.openModal',true);
//Set input variable
@@ -45,24 +138,44 @@
];
var flow = component.find("flow");
- // Check to see if flow is not null before calling startFlow
- if (flowApiName != null && flowApiName != undefined) {
- console.log('flow is not null', flowApiName);
- flow.startFlow(flowApiName, inputVariable); //added input variable
+ // Check to see if flow component exists and flowApiName is valid before calling startFlow
+ if (flow && flowApiName) {
+ this.debugLog(component, 'Starting flow:', flowApiName);
+ try {
+ flow.startFlow(flowApiName, inputVariable);
+ } catch (error) {
+ // Show error toast to user
+ var errorMessage = error.message || 'An error occurred while starting the flow.';
+ this.showErrorToast(component, 'Flow Error',
+ `Unable to start flow "${flowApiName}". ${errorMessage}`);
+ // Close modal if flow fails to start
+ component.set('v.openModal', false);
+ }
} else {
- console.log('flow is null', flow);
+ // Show error toast to user
+ if (!flow) {
+ this.showErrorToast(component, 'Configuration Error',
+ 'Flow component not found. Please contact your administrator.');
+ }
+ if (!flowApiName) {
+ this.showErrorToast(component, 'Configuration Error',
+ 'Flow name is missing or invalid. Please check the component configuration.');
+ }
+ // Close modal if we can't start the flow
+ component.set('v.openModal', false);
}
} else {
//launch modelessly in a tab or browser window
var workspaceAPI = component.find("workspace");
+ var self = this;
workspaceAPI.isConsoleNavigation().then(function(response) {
- console.log('current workspace is console? : ' + response);
+ self.debugLog(component, `current workspace is console? : ${response}`);
if (response) {
//we are in console mode
workspaceAPI.getFocusedTabInfo()
.then(function(response) {
- var targetUrl = '/flow/' + component.get("v.targetFlowName") + '?recordId=' + component.get("v.recordId"); //added input variable;
+ var targetUrl = `/flow/${component.get("v.targetFlowName")}?recordId=${component.get("v.recordId")}`;
workspaceAPI.openSubtab({
parentTabId: response.tabId,
url: targetUrl,
@@ -71,12 +184,14 @@
})
.catch(function(error) {
- console.log(error);
+ // Show error toast to user
+ self.showErrorToast(component, 'Navigation Error',
+ 'Unable to open flow in console. Please try again.');
});
} else {
- console.log('need to launch flow a different way');
- var targetUrl = '/flow/' + component.get("v.targetFlowName") + '?recordId=' + component.get("v.recordId"); //added input variable;
- console.log('targetURL is: ' + targetUrl);
+ self.debugLog(component, 'need to launch flow a different way');
+ var targetUrl = `/flow/${component.get("v.targetFlowName")}?recordId=${component.get("v.recordId")}`;
+ self.debugLog(component, `targetURL is: ${targetUrl}`);
window.open(targetUrl);
}
})