From fac3a8258b1c1e663cfa9321e1fa9a0ff9419b08 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 5 Feb 2026 09:52:04 -0500 Subject: [PATCH 1/7] CASH-2262 | Fix for the button showing up when it shouldn't --- .../sierra-webchat/sierra-webchat.vue | 15 +++++++-------- src/helpers/webchat-helper.js | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/digital-components/sierra-webchat/sierra-webchat.vue b/src/digital-components/sierra-webchat/sierra-webchat.vue index 2ba74b33a..b01755432 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.vue +++ b/src/digital-components/sierra-webchat/sierra-webchat.vue @@ -7,10 +7,15 @@ import analyticsMixin from "@/mixins/analytics-mixin"; import store from "@/store"; import { routeData } from "@/router/constants/routes"; import { deepClone } from "@/helpers/object-helper"; +import { webchatHelper } from "@/helpers/webchat-helper"; export default { name: "sierraWebchat", mixins: [analyticsMixin], + setup() { + const { webchatGlobalNonpersistedState, launchWebchat } = webchatHelper(); + return { webchatGlobalNonpersistedState, launchWebchat }; + }, methods: { openSierraChatModal() { const sierra = window.sierraChat || window.sierra || window.SierraChat; @@ -152,15 +157,9 @@ export default { LastName: transfer.data.last_name, Email: transfer.data.email, }); - if ( - window.embeddedservice_bootstrap.utilAPI && - typeof window.embeddedservice_bootstrap.utilAPI.launchChat === "function" - ) { - window.embeddedservice_bootstrap.utilAPI.launchChat(); - return; - } } - window.embeddedservice_bootstrap.utilAPI.launchChat(); + this.webchatGlobalNonpersistedState.shouldLaunchSierra = false; + this.launchWebchat(); } }; window.addEventListener("sierra-chat-transfer", this._handleSierraTransfer); diff --git a/src/helpers/webchat-helper.js b/src/helpers/webchat-helper.js index e5254d08d..1317f3341 100644 --- a/src/helpers/webchat-helper.js +++ b/src/helpers/webchat-helper.js @@ -8,6 +8,7 @@ const webchatGlobalNonpersistedState = reactive({ export const webchatHelper = () => { function launchWebchat() { + webchatGlobalNonpersistedState.showWebchatButton = false; if (webchatGlobalNonpersistedState.shouldLaunchSierra) { window.dispatchEvent(new CustomEvent("launch-sierra-webchat")); // launches the sierra chat } else { From 4704faca8882e74aa866dd1da904726e07fcf9d2 Mon Sep 17 00:00:00 2001 From: CarlNation <32103961+CarlNation@users.noreply.github.com> Date: Thu, 5 Feb 2026 10:22:19 -0500 Subject: [PATCH 2/7] Revert "CASH-1949 - Fixed email validation to accept multiple dots in domain" --- .../save-progress-question/save-progress-question.vue | 2 +- src/layouts/customer-details/customer-details.vue | 2 +- src/layouts/estimate/estimate.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fmg-components/save-progress-modal-question/save-progress-question/save-progress-question.vue b/src/fmg-components/save-progress-modal-question/save-progress-question/save-progress-question.vue index 9e22f5a80..221aa3415 100644 --- a/src/fmg-components/save-progress-modal-question/save-progress-question/save-progress-question.vue +++ b/src/fmg-components/save-progress-modal-question/save-progress-question/save-progress-question.vue @@ -25,7 +25,7 @@ defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIR defineRule( "email-address-format", regex( - /^([a-zA-Z0-9_.+]+)@([a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.)+([a-zA-Z]{2,})$/, + /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT ) ); diff --git a/src/layouts/customer-details/customer-details.vue b/src/layouts/customer-details/customer-details.vue index 0ee884825..f5a7e1ac7 100644 --- a/src/layouts/customer-details/customer-details.vue +++ b/src/layouts/customer-details/customer-details.vue @@ -91,7 +91,7 @@ defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIR defineRule( "email-address-format", regex( - /^([a-zA-Z0-9_.+]+)@([a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.)+([a-zA-Z]{2,})$/, + /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT ) ); diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue index 60d050d73..5e2ff4e15 100644 --- a/src/layouts/estimate/estimate.vue +++ b/src/layouts/estimate/estimate.vue @@ -70,7 +70,7 @@ defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIR defineRule( "email-address-format", regex( - /^([a-zA-Z0-9_.+]+)@([a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*\.)+([a-zA-Z]{2,})$/, + /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT ) ); From 7958f99523251803e9609f68895c9c212ed167db Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 5 Feb 2026 10:31:12 -0500 Subject: [PATCH 3/7] Simplify sierra's interaction with button visibility The webchathelper already contained the ability to communicate between classes without events --- .../salesforce-webchat/salesforce-webchat.vue | 3 -- .../sierra-webchat/sierra-webchat.spec.js | 8 ----- .../sierra-webchat/sierra-webchat.vue | 29 +++++++------------ .../funnel-header/funnel-header.vue | 22 +------------- 4 files changed, 11 insertions(+), 51 deletions(-) diff --git a/src/digital-components/salesforce-webchat/salesforce-webchat.vue b/src/digital-components/salesforce-webchat/salesforce-webchat.vue index da11702e3..db4f2e3b1 100644 --- a/src/digital-components/salesforce-webchat/salesforce-webchat.vue +++ b/src/digital-components/salesforce-webchat/salesforce-webchat.vue @@ -41,9 +41,6 @@ export default { beforeUnmount() { // Clean up event listeners and observers window.removeEventListener("sierra-chat-transfer", this._handleSierraToSalesforceTransfer); - if (this._salesforceChatOpenObserver) { - this._salesforceChatOpenObserver.disconnect(); - } }, methods: { initializeSalesforceWebchat() { diff --git a/src/digital-components/sierra-webchat/sierra-webchat.spec.js b/src/digital-components/sierra-webchat/sierra-webchat.spec.js index 964a4f52e..2fd3bd3a3 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.spec.js +++ b/src/digital-components/sierra-webchat/sierra-webchat.spec.js @@ -59,14 +59,6 @@ describe("sierraWebchat.vue", () => { expect(window.sierraChat.closeChatModal).toHaveBeenCalled(); }); - it("dispatches sierra-chat-closed on handleSierraOnClose", () => { - const eventSpy = jest.spyOn(window, "dispatchEvent"); - wrapper.vm.createSierraConfig().onClose(); - expect(eventSpy).toHaveBeenCalledWith( - expect.objectContaining({ type: "sierra-chat-closed" }) - ); - }); - it("dispatches sierra-chat-transfer on handleSierraOnTransfer", () => { const eventSpy = jest.spyOn(window, "dispatchEvent"); const transfer = { diff --git a/src/digital-components/sierra-webchat/sierra-webchat.vue b/src/digital-components/sierra-webchat/sierra-webchat.vue index b01755432..9383efe37 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.vue +++ b/src/digital-components/sierra-webchat/sierra-webchat.vue @@ -12,6 +12,11 @@ import { webchatHelper } from "@/helpers/webchat-helper"; export default { name: "sierraWebchat", mixins: [analyticsMixin], + data() { + return { + transferInProgress: false, + }; + }, setup() { const { webchatGlobalNonpersistedState, launchWebchat } = webchatHelper(); return { webchatGlobalNonpersistedState, launchWebchat }; @@ -40,11 +45,12 @@ export default { display: "corner", onLoad: () => this.openSierraChatModal(), onOpen: () => {}, - onClose: () => window.dispatchEvent(new CustomEvent("sierra-chat-closed")), - onTransfer: (transfer) => + onClose: () => {if (!this.transferInProgress) {this.webchatGlobalNonpersistedState.showWebchatButton = true; this.transferInProgress = false;}}, + onTransfer: (transfer) => {this.transferInProgress = true; window.dispatchEvent( - new CustomEvent("sierra-chat-transfer", { detail: transfer }) - ), + new CustomEvent("sierra-chat-transfer", { detail: transfer }) + ); + }, }; }, getSierraContext() { @@ -163,25 +169,10 @@ export default { } }; window.addEventListener("sierra-chat-transfer", this._handleSierraTransfer); - - // Notify funnel-header about Sierra chat open/close state - this._sierraChatContainerObserver = new MutationObserver(() => { - const isOpen = !!document.querySelector("[data-sierra-chat-container]"); - window.dispatchEvent( - new CustomEvent("sierra-chat-visibility", { detail: { open: isOpen } }) - ); - }); - this._sierraChatContainerObserver.observe(document.body, { - childList: true, - subtree: true, - }); }, beforeUnmount() { window.removeEventListener("launch-sierra-webchat", this.triggerSierraChat); window.removeEventListener("sierra-chat-transfer", this._handleSierraTransfer); - if (this._sierraChatContainerObserver) { - this._sierraChatContainerObserver.disconnect(); - } }, }; diff --git a/src/fmg-components/funnel-header/funnel-header.vue b/src/fmg-components/funnel-header/funnel-header.vue index 00df5db87..7bfa3eef6 100644 --- a/src/fmg-components/funnel-header/funnel-header.vue +++ b/src/fmg-components/funnel-header/funnel-header.vue @@ -79,16 +79,7 @@ export default { return this.getCmsContent(this.cmsWidgetName, "LogoImage"); }, shouldShowWebchatButton() { - // Hide the chat icon if Sierra chat is open - if (this.sierraChatOpen) { - return false; - } - // Show if either Sierra is enabled or Salesforce button is available and not hidden by page - return ( - (this.webchatGlobalNonpersistedState.shouldLaunchSierra || - this.webchatGlobalNonpersistedState.showWebchatButton) && - !this.shouldHideWebchatButtonOnPage - ); + return this.webchatGlobalNonpersistedState.showWebchatButton; }, }, methods: { @@ -116,10 +107,6 @@ export default { webchatClicked(event) { event.preventDefault(); this.launchWebchat(); - // Only set sierraChatOpen if Sierra experiment is active - if (this.webchatGlobalNonpersistedState.shouldLaunchSierra) { - this.sierraChatOpen = true; - } }, syncSierraExperimentFlag() { const experiments = store.getters.applicationUser.experiments; @@ -159,11 +146,6 @@ export default { unknownAlertEvent.displayAlert = true; this.globalAlertMessages.push(unknownAlertEvent); } - // Listen for Sierra chat open/close events from sierra-webchat - this._handleSierraChatVisibility = (event) => { - this.sierraChatOpen = !!(event.detail && event.detail.open); - }; - window.addEventListener("sierra-chat-visibility", this._handleSierraChatVisibility); // Add scroll listener for header shadow effect this._handleScroll = () => { @@ -172,8 +154,6 @@ export default { window.addEventListener("scroll", this._handleScroll); }, beforeUnmount() { - window.removeEventListener("sierra-chat-closed", this._handleSierraChatClosed); - window.removeEventListener("sierra-chat-visibility", this._handleSierraChatVisibility); window.removeEventListener("sierra-chat-transfer", this._handleSierraToSalesforceTransfer); window.removeEventListener("scroll", this._handleScroll); }, From f2385c16f780241997620f575a4054b34f78ef85 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 5 Feb 2026 09:52:04 -0500 Subject: [PATCH 4/7] CASH-2262 | Fix for the button showing up when it shouldn't --- .../sierra-webchat/sierra-webchat.vue | 15 +++++++-------- src/helpers/webchat-helper.js | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/digital-components/sierra-webchat/sierra-webchat.vue b/src/digital-components/sierra-webchat/sierra-webchat.vue index 2ba74b33a..b01755432 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.vue +++ b/src/digital-components/sierra-webchat/sierra-webchat.vue @@ -7,10 +7,15 @@ import analyticsMixin from "@/mixins/analytics-mixin"; import store from "@/store"; import { routeData } from "@/router/constants/routes"; import { deepClone } from "@/helpers/object-helper"; +import { webchatHelper } from "@/helpers/webchat-helper"; export default { name: "sierraWebchat", mixins: [analyticsMixin], + setup() { + const { webchatGlobalNonpersistedState, launchWebchat } = webchatHelper(); + return { webchatGlobalNonpersistedState, launchWebchat }; + }, methods: { openSierraChatModal() { const sierra = window.sierraChat || window.sierra || window.SierraChat; @@ -152,15 +157,9 @@ export default { LastName: transfer.data.last_name, Email: transfer.data.email, }); - if ( - window.embeddedservice_bootstrap.utilAPI && - typeof window.embeddedservice_bootstrap.utilAPI.launchChat === "function" - ) { - window.embeddedservice_bootstrap.utilAPI.launchChat(); - return; - } } - window.embeddedservice_bootstrap.utilAPI.launchChat(); + this.webchatGlobalNonpersistedState.shouldLaunchSierra = false; + this.launchWebchat(); } }; window.addEventListener("sierra-chat-transfer", this._handleSierraTransfer); diff --git a/src/helpers/webchat-helper.js b/src/helpers/webchat-helper.js index e5254d08d..1317f3341 100644 --- a/src/helpers/webchat-helper.js +++ b/src/helpers/webchat-helper.js @@ -8,6 +8,7 @@ const webchatGlobalNonpersistedState = reactive({ export const webchatHelper = () => { function launchWebchat() { + webchatGlobalNonpersistedState.showWebchatButton = false; if (webchatGlobalNonpersistedState.shouldLaunchSierra) { window.dispatchEvent(new CustomEvent("launch-sierra-webchat")); // launches the sierra chat } else { From 6893aee1556b462f0636c31bcd3389faf66db692 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 5 Feb 2026 10:31:12 -0500 Subject: [PATCH 5/7] Simplify sierra's interaction with button visibility The webchathelper already contained the ability to communicate between classes without events --- .../salesforce-webchat/salesforce-webchat.vue | 3 -- .../sierra-webchat/sierra-webchat.spec.js | 8 ----- .../sierra-webchat/sierra-webchat.vue | 29 +++++++------------ .../funnel-header/funnel-header.vue | 22 +------------- 4 files changed, 11 insertions(+), 51 deletions(-) diff --git a/src/digital-components/salesforce-webchat/salesforce-webchat.vue b/src/digital-components/salesforce-webchat/salesforce-webchat.vue index da11702e3..db4f2e3b1 100644 --- a/src/digital-components/salesforce-webchat/salesforce-webchat.vue +++ b/src/digital-components/salesforce-webchat/salesforce-webchat.vue @@ -41,9 +41,6 @@ export default { beforeUnmount() { // Clean up event listeners and observers window.removeEventListener("sierra-chat-transfer", this._handleSierraToSalesforceTransfer); - if (this._salesforceChatOpenObserver) { - this._salesforceChatOpenObserver.disconnect(); - } }, methods: { initializeSalesforceWebchat() { diff --git a/src/digital-components/sierra-webchat/sierra-webchat.spec.js b/src/digital-components/sierra-webchat/sierra-webchat.spec.js index 964a4f52e..2fd3bd3a3 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.spec.js +++ b/src/digital-components/sierra-webchat/sierra-webchat.spec.js @@ -59,14 +59,6 @@ describe("sierraWebchat.vue", () => { expect(window.sierraChat.closeChatModal).toHaveBeenCalled(); }); - it("dispatches sierra-chat-closed on handleSierraOnClose", () => { - const eventSpy = jest.spyOn(window, "dispatchEvent"); - wrapper.vm.createSierraConfig().onClose(); - expect(eventSpy).toHaveBeenCalledWith( - expect.objectContaining({ type: "sierra-chat-closed" }) - ); - }); - it("dispatches sierra-chat-transfer on handleSierraOnTransfer", () => { const eventSpy = jest.spyOn(window, "dispatchEvent"); const transfer = { diff --git a/src/digital-components/sierra-webchat/sierra-webchat.vue b/src/digital-components/sierra-webchat/sierra-webchat.vue index b01755432..9383efe37 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.vue +++ b/src/digital-components/sierra-webchat/sierra-webchat.vue @@ -12,6 +12,11 @@ import { webchatHelper } from "@/helpers/webchat-helper"; export default { name: "sierraWebchat", mixins: [analyticsMixin], + data() { + return { + transferInProgress: false, + }; + }, setup() { const { webchatGlobalNonpersistedState, launchWebchat } = webchatHelper(); return { webchatGlobalNonpersistedState, launchWebchat }; @@ -40,11 +45,12 @@ export default { display: "corner", onLoad: () => this.openSierraChatModal(), onOpen: () => {}, - onClose: () => window.dispatchEvent(new CustomEvent("sierra-chat-closed")), - onTransfer: (transfer) => + onClose: () => {if (!this.transferInProgress) {this.webchatGlobalNonpersistedState.showWebchatButton = true; this.transferInProgress = false;}}, + onTransfer: (transfer) => {this.transferInProgress = true; window.dispatchEvent( - new CustomEvent("sierra-chat-transfer", { detail: transfer }) - ), + new CustomEvent("sierra-chat-transfer", { detail: transfer }) + ); + }, }; }, getSierraContext() { @@ -163,25 +169,10 @@ export default { } }; window.addEventListener("sierra-chat-transfer", this._handleSierraTransfer); - - // Notify funnel-header about Sierra chat open/close state - this._sierraChatContainerObserver = new MutationObserver(() => { - const isOpen = !!document.querySelector("[data-sierra-chat-container]"); - window.dispatchEvent( - new CustomEvent("sierra-chat-visibility", { detail: { open: isOpen } }) - ); - }); - this._sierraChatContainerObserver.observe(document.body, { - childList: true, - subtree: true, - }); }, beforeUnmount() { window.removeEventListener("launch-sierra-webchat", this.triggerSierraChat); window.removeEventListener("sierra-chat-transfer", this._handleSierraTransfer); - if (this._sierraChatContainerObserver) { - this._sierraChatContainerObserver.disconnect(); - } }, }; diff --git a/src/fmg-components/funnel-header/funnel-header.vue b/src/fmg-components/funnel-header/funnel-header.vue index 00df5db87..7bfa3eef6 100644 --- a/src/fmg-components/funnel-header/funnel-header.vue +++ b/src/fmg-components/funnel-header/funnel-header.vue @@ -79,16 +79,7 @@ export default { return this.getCmsContent(this.cmsWidgetName, "LogoImage"); }, shouldShowWebchatButton() { - // Hide the chat icon if Sierra chat is open - if (this.sierraChatOpen) { - return false; - } - // Show if either Sierra is enabled or Salesforce button is available and not hidden by page - return ( - (this.webchatGlobalNonpersistedState.shouldLaunchSierra || - this.webchatGlobalNonpersistedState.showWebchatButton) && - !this.shouldHideWebchatButtonOnPage - ); + return this.webchatGlobalNonpersistedState.showWebchatButton; }, }, methods: { @@ -116,10 +107,6 @@ export default { webchatClicked(event) { event.preventDefault(); this.launchWebchat(); - // Only set sierraChatOpen if Sierra experiment is active - if (this.webchatGlobalNonpersistedState.shouldLaunchSierra) { - this.sierraChatOpen = true; - } }, syncSierraExperimentFlag() { const experiments = store.getters.applicationUser.experiments; @@ -159,11 +146,6 @@ export default { unknownAlertEvent.displayAlert = true; this.globalAlertMessages.push(unknownAlertEvent); } - // Listen for Sierra chat open/close events from sierra-webchat - this._handleSierraChatVisibility = (event) => { - this.sierraChatOpen = !!(event.detail && event.detail.open); - }; - window.addEventListener("sierra-chat-visibility", this._handleSierraChatVisibility); // Add scroll listener for header shadow effect this._handleScroll = () => { @@ -172,8 +154,6 @@ export default { window.addEventListener("scroll", this._handleScroll); }, beforeUnmount() { - window.removeEventListener("sierra-chat-closed", this._handleSierraChatClosed); - window.removeEventListener("sierra-chat-visibility", this._handleSierraChatVisibility); window.removeEventListener("sierra-chat-transfer", this._handleSierraToSalesforceTransfer); window.removeEventListener("scroll", this._handleScroll); }, From 3f43c4e6eb019e6ac2e504c310ffac74283113b5 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 5 Feb 2026 10:40:13 -0500 Subject: [PATCH 6/7] Formatting --- .../sierra-webchat/sierra-webchat.vue | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/digital-components/sierra-webchat/sierra-webchat.vue b/src/digital-components/sierra-webchat/sierra-webchat.vue index 9383efe37..0b4381411 100644 --- a/src/digital-components/sierra-webchat/sierra-webchat.vue +++ b/src/digital-components/sierra-webchat/sierra-webchat.vue @@ -45,12 +45,18 @@ export default { display: "corner", onLoad: () => this.openSierraChatModal(), onOpen: () => {}, - onClose: () => {if (!this.transferInProgress) {this.webchatGlobalNonpersistedState.showWebchatButton = true; this.transferInProgress = false;}}, - onTransfer: (transfer) => {this.transferInProgress = true; + onClose: () => { + if (!this.transferInProgress) { + this.webchatGlobalNonpersistedState.showWebchatButton = true; + this.transferInProgress = false; + } + }, + onTransfer: (transfer) => { + this.transferInProgress = true; window.dispatchEvent( - new CustomEvent("sierra-chat-transfer", { detail: transfer }) - ); - }, + new CustomEvent("sierra-chat-transfer", { detail: transfer }) + ); + }, }; }, getSierraContext() { From bfe395d307c34e3a6b40ef7e9408596ec39b9d5d Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Thu, 5 Feb 2026 14:46:47 -0500 Subject: [PATCH 7/7] Fix the webchat sitting under our components --- .../salesforce-webchat/salesforce-webchat.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/digital-components/salesforce-webchat/salesforce-webchat.vue b/src/digital-components/salesforce-webchat/salesforce-webchat.vue index db4f2e3b1..85d9d891d 100644 --- a/src/digital-components/salesforce-webchat/salesforce-webchat.vue +++ b/src/digital-components/salesforce-webchat/salesforce-webchat.vue @@ -130,6 +130,9 @@ export default {