Merge branch 'develop' into CASH-631
This commit is contained in:
commit
821108e755
9 changed files with 263 additions and 16 deletions
|
|
@ -8,6 +8,7 @@
|
|||
<funnelFooter />
|
||||
<loadingModal :showLoader="shouldShowLoader" :showTextCarousel="shouldShowTextCarousel" />
|
||||
<salesforceWebchat />
|
||||
<sierra-webchat />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -16,6 +17,7 @@ import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
|||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer.vue";
|
||||
import salesforceWebchat from "./digital-components/salesforce-webchat/salesforce-webchat.vue";
|
||||
import sierraWebchat from "./digital-components/sierra-webchat/sierra-webchat.vue";
|
||||
|
||||
export default {
|
||||
name: "app",
|
||||
|
|
@ -38,6 +40,7 @@ export default {
|
|||
loadingModal,
|
||||
funnelFooter,
|
||||
salesforceWebchat,
|
||||
sierraWebchat,
|
||||
},
|
||||
mounted() {
|
||||
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 progressBar from "@/fmg-components/funnel-header/progress-bar/progress-bar";
|
||||
import { webchatHelper } from "@/helpers/webchat-helper";
|
||||
import store from "@/store";
|
||||
|
||||
// Constants
|
||||
const ALERT_DURATION = 3000; // millisecond time to display alert before dismissal
|
||||
|
|
@ -53,6 +54,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
globalAlertMessages: [],
|
||||
sierraChatOpen: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
|
|
@ -71,6 +73,13 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, "LogoImage");
|
||||
},
|
||||
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 (
|
||||
!this.shouldHideWebchatButtonOnPage &&
|
||||
this.webchatGlobalNonpersistedState.showWebchatButton
|
||||
|
|
@ -91,8 +100,21 @@ export default {
|
|||
this.globalAlertMessages.push(alertToPush);
|
||||
},
|
||||
webchatClicked(event) {
|
||||
event.preventDefault(); // avoid validation firing
|
||||
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;
|
||||
const sierraExp = experiments?.find(
|
||||
(exp) =>
|
||||
exp.universeName === "CONTENT_FMG_SierraWebchat" &&
|
||||
exp.settings?.UseSierraChat === "true"
|
||||
);
|
||||
this.webchatGlobalNonpersistedState.shouldLaunchSierra = !!sierraExp;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
|
@ -122,6 +144,14 @@ export default {
|
|||
unknownAlertEvent.displayAlert = true;
|
||||
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>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const webchatGlobalNonpersistedState = reactive({
|
|||
export const webchatHelper = () => {
|
||||
function launchWebchat() {
|
||||
if (webchatGlobalNonpersistedState.shouldLaunchSierra) {
|
||||
// do sierra logic here
|
||||
window.dispatchEvent(new CustomEvent("launch-sierra-webchat")); // launches the sierra chat
|
||||
} else {
|
||||
window.embedded_svc.bootstrapEmbeddedService(); // launches the salesForce prechat form
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
@ForwardClicked="forwardButtonAction" />
|
||||
|
||||
<textBlock
|
||||
class="mb-5"
|
||||
class="mb-5 disclaimer-block"
|
||||
cmsWidgetName="DisclaimerCopyWidget"
|
||||
typeStyle="caption" />
|
||||
</div>
|
||||
|
|
@ -212,3 +212,10 @@ export default {
|
|||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.disclaimer-block {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div class="alert fade show my-2 py-2 border-0 alert-info" role="alert">
|
||||
<component :is="'script'" src="https://js.afterpay.com/afterpay-1.x.js" async></component>
|
||||
<component
|
||||
:is="'script'"
|
||||
src="https://js.squarecdn.com/square-marketplace.js"
|
||||
async></component>
|
||||
<div class="my-4 alert-heading text-center">
|
||||
<span v-html="afterpayHeaderCopy" />
|
||||
<span class="afterpay-amount">{{ this.afterpayPrice }}</span>
|
||||
|
|
@ -10,7 +13,7 @@
|
|||
<a
|
||||
id="afterpay-learnmore"
|
||||
href="#"
|
||||
data-afterpay-modal="en_US-safelite"
|
||||
data-afterpay-modal="en_US"
|
||||
data-bind="click:afterpayLearnMore"
|
||||
class="afterpay-learn-more">
|
||||
<img :src="infoIcon" alt="Info Icon" class="info-icon" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div class="alert fade show my-2 py-2 border-0 alert-info" role="alert">
|
||||
<component :is="'script'" src="https://js.afterpay.com/afterpay-1.x.js" async></component>
|
||||
<component
|
||||
:is="'script'"
|
||||
src="https://js.squarecdn.com/square-marketplace.js"
|
||||
async></component>
|
||||
|
||||
<div
|
||||
class="mx-4 my-0 alert-heading text-center"
|
||||
|
|
@ -17,7 +20,7 @@
|
|||
<a
|
||||
id="afterpay-learnmore"
|
||||
href="#"
|
||||
data-afterpay-modal="en_US-safelite"
|
||||
data-afterpay-modal="en_US"
|
||||
data-bind="click:afterpayLearnMore">
|
||||
{{ modalCopy }}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import router from "@/router";
|
||||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||
|
||||
export async function bailout(errorPayload, forceRestart = false) {
|
||||
if (forceRestart) {
|
||||
await store.dispatch(storeActions.RESET_STATE);
|
||||
deleteFunnelCookie();
|
||||
}
|
||||
|
||||
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
|
||||
|
||||
if (forceRestart) {
|
||||
router.push({
|
||||
name: routeData.RESTART.name,
|
||||
});
|
||||
} else {
|
||||
router.push({
|
||||
name: routeData.ERROR.name,
|
||||
});
|
||||
}
|
||||
router.push({
|
||||
name: routeData.ERROR.name,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue