Merge pull request #2552 from Safelite/feature/CASH-426
CASH-426 - Integrated Sierra chat
This commit is contained in:
commit
c53e5d5cbc
5 changed files with 234 additions and 2 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
<funnelFooter />
|
<funnelFooter />
|
||||||
<loadingModal :showLoader="shouldShowLoader" :showTextCarousel="shouldShowTextCarousel" />
|
<loadingModal :showLoader="shouldShowLoader" :showTextCarousel="shouldShowTextCarousel" />
|
||||||
<salesforceWebchat />
|
<salesforceWebchat />
|
||||||
|
<sierra-webchat />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -16,6 +17,7 @@ import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer.vue";
|
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer.vue";
|
||||||
import salesforceWebchat from "./digital-components/salesforce-webchat/salesforce-webchat.vue";
|
import salesforceWebchat from "./digital-components/salesforce-webchat/salesforce-webchat.vue";
|
||||||
|
import sierraWebchat from "./digital-components/sierra-webchat/sierra-webchat.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "app",
|
name: "app",
|
||||||
|
|
@ -38,6 +40,7 @@ export default {
|
||||||
loadingModal,
|
loadingModal,
|
||||||
funnelFooter,
|
funnelFooter,
|
||||||
salesforceWebchat,
|
salesforceWebchat,
|
||||||
|
sierraWebchat,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
showFmgLoadingModal(true);
|
showFmgLoadingModal(true);
|
||||||
|
|
|
||||||
84
src/digital-components/sierra-webchat/sierra-webchat.spec.js
Normal file
84
src/digital-components/sierra-webchat/sierra-webchat.spec.js
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import SierraWebchat from "./sierra-webchat.vue";
|
||||||
|
|
||||||
|
describe("sierraWebchat.vue", () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = shallowMount(SierraWebchat);
|
||||||
|
// Mock global window properties
|
||||||
|
window.sierraChat = { openChatModal: jest.fn(), closeChatModal: jest.fn() };
|
||||||
|
window.sierra = undefined;
|
||||||
|
window.SierraChat = undefined;
|
||||||
|
window.embedded_svc = {
|
||||||
|
bootstrapEmbeddedService: jest.fn(),
|
||||||
|
liveAgentAPI: { startChat: jest.fn() },
|
||||||
|
settings: {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.unmount();
|
||||||
|
jest.clearAllMocks();
|
||||||
|
delete window.sierraChat;
|
||||||
|
delete window.embedded_svc;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should mount the component", () => {
|
||||||
|
expect(wrapper.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls openSierraChatModal when launchSierraChat is called and script is loaded", () => {
|
||||||
|
const spy = jest.spyOn(wrapper.vm, "openSierraChatModal");
|
||||||
|
// Simulate script already loaded
|
||||||
|
document.body.appendChild(document.createElement("script")).id = "sierra-chat-embed";
|
||||||
|
wrapper.vm.launchSierraChat();
|
||||||
|
expect(spy).toHaveBeenCalled();
|
||||||
|
document.getElementById("sierra-chat-embed").remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls closeSierraChat when invoked", () => {
|
||||||
|
wrapper.vm.closeSierraChat();
|
||||||
|
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 = {
|
||||||
|
data: { first_name: "A", last_name: "B", email: "a@b.com", chat_summary: "summary" },
|
||||||
|
};
|
||||||
|
wrapper.vm.createSierraConfig().onTransfer(transfer);
|
||||||
|
expect(eventSpy).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({ type: "sierra-chat-transfer" })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles sierra-chat-transfer event and starts Salesforce chat with prepopulated fields", () => {
|
||||||
|
const transfer = {
|
||||||
|
data: {
|
||||||
|
first_name: "A",
|
||||||
|
last_name: "B",
|
||||||
|
email: "a@b.com",
|
||||||
|
chat_summary: "summary",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const event = new CustomEvent("sierra-chat-transfer", { detail: transfer });
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
expect(window.sierraChat.closeChatModal).toHaveBeenCalled();
|
||||||
|
expect(window.embedded_svc.settings.prepopulatedPrechatFields).toEqual({
|
||||||
|
FirstName: "A",
|
||||||
|
LastName: "B",
|
||||||
|
Email: "a@b.com",
|
||||||
|
Subject: "summary",
|
||||||
|
});
|
||||||
|
expect(window.embedded_svc.liveAgentAPI.startChat).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
115
src/digital-components/sierra-webchat/sierra-webchat.vue
Normal file
115
src/digital-components/sierra-webchat/sierra-webchat.vue
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
<template>
|
||||||
|
<div ref="sierraContainer"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "sierraWebchat",
|
||||||
|
methods: {
|
||||||
|
openSierraChatModal() {
|
||||||
|
const sierra = window.sierraChat || window.sierra || window.SierraChat;
|
||||||
|
if (sierra && typeof sierra.openChatModal === "function") {
|
||||||
|
sierra.openChatModal();
|
||||||
|
} else {
|
||||||
|
const launchLink = document.createElement("a");
|
||||||
|
launchLink.setAttribute("data-sierra-chat", "modal");
|
||||||
|
launchLink.style.display = "none";
|
||||||
|
document.body.appendChild(launchLink);
|
||||||
|
launchLink.click();
|
||||||
|
document.body.removeChild(launchLink);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createSierraConfig() {
|
||||||
|
return {
|
||||||
|
variables: { application: "funnel" },
|
||||||
|
display: "corner",
|
||||||
|
onLoad: () => this.openSierraChatModal(),
|
||||||
|
onOpen: () => {},
|
||||||
|
onClose: () => window.dispatchEvent(new CustomEvent("sierra-chat-closed")),
|
||||||
|
onTransfer: (transfer) =>
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent("sierra-chat-transfer", { detail: transfer })
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
launchSierraChat() {
|
||||||
|
window.sierraConfig = this.createSierraConfig();
|
||||||
|
// Preload CSS if not already present
|
||||||
|
if (!document.getElementById("sierra-chat-embed-css")) {
|
||||||
|
const link = document.createElement("link");
|
||||||
|
link.rel = "preload";
|
||||||
|
link.as = "style";
|
||||||
|
link.href =
|
||||||
|
"https://sierra.chat/agent/OxY5TbsBlJZsHxIBlJZsmCiQdcXfa2rePO38ZwOlx40/embed-css";
|
||||||
|
link.id = "sierra-chat-embed-css";
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
// Load script if not loaded, otherwise open modal directly
|
||||||
|
if (!document.getElementById("sierra-chat-embed")) {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.type = "module";
|
||||||
|
script.id = "sierra-chat-embed";
|
||||||
|
script.src =
|
||||||
|
"https://sierra.chat/agent/OxY5TbsBlJZsHxIBlJZsmCiQdcXfa2rePO38ZwOlx40/embed";
|
||||||
|
document.body.appendChild(script);
|
||||||
|
} else {
|
||||||
|
this.openSierraChatModal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
triggerSierraChat() {
|
||||||
|
this.launchSierraChat();
|
||||||
|
},
|
||||||
|
closeSierraChat() {
|
||||||
|
const sierra = window.sierraChat || window.sierra || window.SierraChat;
|
||||||
|
if (sierra && typeof sierra.closeChatModal === "function") {
|
||||||
|
sierra.closeChatModal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
window.addEventListener("launch-sierra-webchat", this.triggerSierraChat);
|
||||||
|
// Listen for transfer event to close Sierra chat and open Salesforce chat
|
||||||
|
this._handleSierraTransfer = (event) => {
|
||||||
|
const sierra = window.sierraChat || window.sierra || window.SierraChat;
|
||||||
|
if (sierra && typeof sierra.closeChatModal === "function") {
|
||||||
|
sierra.closeChatModal();
|
||||||
|
}
|
||||||
|
// Pass data to Salesforce chat if available
|
||||||
|
const transfer = event.detail;
|
||||||
|
if (
|
||||||
|
window.embedded_svc &&
|
||||||
|
typeof window.embedded_svc.bootstrapEmbeddedService === "function"
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
transfer &&
|
||||||
|
transfer.data &&
|
||||||
|
transfer.data.first_name &&
|
||||||
|
transfer.data.last_name &&
|
||||||
|
transfer.data.email
|
||||||
|
) {
|
||||||
|
window.embedded_svc.settings.prepopulatedPrechatFields = {
|
||||||
|
FirstName: transfer.data.first_name,
|
||||||
|
LastName: transfer.data.last_name,
|
||||||
|
Email: transfer.data.email,
|
||||||
|
Subject: transfer.data.chat_summary, // for now passing in chat_summery in Subject. But this will be changed in future.
|
||||||
|
};
|
||||||
|
// Start chat immediately if required fields are present
|
||||||
|
if (
|
||||||
|
window.embedded_svc.liveAgentAPI &&
|
||||||
|
typeof window.embedded_svc.liveAgentAPI.startChat === "function"
|
||||||
|
) {
|
||||||
|
window.embedded_svc.liveAgentAPI.startChat();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.embedded_svc.bootstrapEmbeddedService();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("sierra-chat-transfer", this._handleSierraTransfer);
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
window.removeEventListener("launch-sierra-webchat", this.triggerSierraChat);
|
||||||
|
window.removeEventListener("sierra-chat-transfer", this._handleSierraTransfer);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -44,6 +44,7 @@ import { globalEvents } from "@/constants/events";
|
||||||
import menuModal from "@/fmg-components/funnel-header/menu-modal/menu-modal";
|
import menuModal from "@/fmg-components/funnel-header/menu-modal/menu-modal";
|
||||||
import progressBar from "@/fmg-components/funnel-header/progress-bar/progress-bar";
|
import progressBar from "@/fmg-components/funnel-header/progress-bar/progress-bar";
|
||||||
import { webchatHelper } from "@/helpers/webchat-helper";
|
import { webchatHelper } from "@/helpers/webchat-helper";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const ALERT_DURATION = 3000; // millisecond time to display alert before dismissal
|
const ALERT_DURATION = 3000; // millisecond time to display alert before dismissal
|
||||||
|
|
@ -53,6 +54,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
globalAlertMessages: [],
|
globalAlertMessages: [],
|
||||||
|
sierraChatOpen: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -71,6 +73,13 @@ export default {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "LogoImage");
|
return this.getCmsContent(this.cmsWidgetName, "LogoImage");
|
||||||
},
|
},
|
||||||
shouldShowWebchatButton() {
|
shouldShowWebchatButton() {
|
||||||
|
// Always update experiment flag before computing visibility
|
||||||
|
this.syncSierraExperimentFlag();
|
||||||
|
// Show if Sierra experiment is active and chat is not open
|
||||||
|
if (this.webchatGlobalNonpersistedState.shouldLaunchSierra) {
|
||||||
|
return !this.sierraChatOpen;
|
||||||
|
}
|
||||||
|
// Otherwise, use Salesforce logic
|
||||||
return (
|
return (
|
||||||
!this.shouldHideWebchatButtonOnPage &&
|
!this.shouldHideWebchatButtonOnPage &&
|
||||||
this.webchatGlobalNonpersistedState.showWebchatButton
|
this.webchatGlobalNonpersistedState.showWebchatButton
|
||||||
|
|
@ -91,8 +100,21 @@ export default {
|
||||||
this.globalAlertMessages.push(alertToPush);
|
this.globalAlertMessages.push(alertToPush);
|
||||||
},
|
},
|
||||||
webchatClicked(event) {
|
webchatClicked(event) {
|
||||||
event.preventDefault(); // avoid validation firing
|
event.preventDefault();
|
||||||
this.launchWebchat();
|
this.launchWebchat();
|
||||||
|
// Only set sierraChatOpen if Sierra experiment is active
|
||||||
|
if (this.webchatGlobalNonpersistedState.shouldLaunchSierra) {
|
||||||
|
this.sierraChatOpen = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
syncSierraExperimentFlag() {
|
||||||
|
const experiments = store.getters.applicationUser.experiments;
|
||||||
|
const sierraExp = experiments?.find(
|
||||||
|
(exp) =>
|
||||||
|
exp.universeName === "CONTENT_FMG_SierraWebchat" &&
|
||||||
|
exp.settings?.UseSierraChat === "true"
|
||||||
|
);
|
||||||
|
this.webchatGlobalNonpersistedState.shouldLaunchSierra = !!sierraExp;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -122,6 +144,14 @@ export default {
|
||||||
unknownAlertEvent.displayAlert = true;
|
unknownAlertEvent.displayAlert = true;
|
||||||
this.globalAlertMessages.push(unknownAlertEvent);
|
this.globalAlertMessages.push(unknownAlertEvent);
|
||||||
}
|
}
|
||||||
|
// Listen for Sierra chat close event to re-enable the chat button if needed
|
||||||
|
this._handleSierraChatClosed = () => {
|
||||||
|
this.sierraChatOpen = false;
|
||||||
|
};
|
||||||
|
window.addEventListener("sierra-chat-closed", this._handleSierraChatClosed);
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
window.removeEventListener("sierra-chat-closed", this._handleSierraChatClosed);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ const webchatGlobalNonpersistedState = reactive({
|
||||||
export const webchatHelper = () => {
|
export const webchatHelper = () => {
|
||||||
function launchWebchat() {
|
function launchWebchat() {
|
||||||
if (webchatGlobalNonpersistedState.shouldLaunchSierra) {
|
if (webchatGlobalNonpersistedState.shouldLaunchSierra) {
|
||||||
// do sierra logic here
|
window.dispatchEvent(new CustomEvent("launch-sierra-webchat")); // launches the sierra chat
|
||||||
} else {
|
} else {
|
||||||
window.embedded_svc.bootstrapEmbeddedService(); // launches the salesForce prechat form
|
window.embedded_svc.bootstrapEmbeddedService(); // launches the salesForce prechat form
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue