427 lines
No EOL
17 KiB
HTML
427 lines
No EOL
17 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<style>
|
|
|
|
@font-face {
|
|
font-family: Urbanist;
|
|
src: url("/static/assets/Urbanist-Regular.woff") format("woff");
|
|
}
|
|
|
|
@font-face {
|
|
font-family: UrbanistSemiBold;
|
|
src: url("/static/assets/Urbanist-SemiBold.woff") format("woff");
|
|
}
|
|
|
|
body {
|
|
font-family: 'Urbanist', Roboto, Arial, Helvetica, sans-serif;
|
|
}
|
|
|
|
.container {
|
|
max-width: 960px;
|
|
margin: auto;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.header, .copy, .cta {
|
|
margin-bottom: 3rem;
|
|
}
|
|
|
|
.header .header-image {
|
|
width: 165px;
|
|
}
|
|
|
|
.subheader {
|
|
font-weight: normal;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.cta-button {
|
|
padding-top: 0.75rem;
|
|
padding-bottom: 0.75rem;
|
|
padding-left: 2rem;
|
|
padding-right: 2rem;
|
|
border-radius: 50rem;
|
|
background-color: #db0020;
|
|
color: #ffffff;
|
|
font-family: inherit;
|
|
font-size: 1rem;
|
|
border: 0px;
|
|
}
|
|
|
|
.diagnostic-info {
|
|
color: #db0020;
|
|
font-family: 'UrbanistSemiBold', Roboto, Arial, Helvetica, sans-serif;
|
|
word-wrap: break-word;
|
|
}
|
|
</style>
|
|
<title>Error - Safelite</title>
|
|
<link rel="icon" href="/favicon.ico">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<img class="header-image" src="/static/assets/logo.svg" />
|
|
</div>
|
|
<div class="copy">
|
|
<h2 class="subheader">
|
|
We're not able to schedule at this time. We apologize for the inconvenience
|
|
</h2>
|
|
<p>
|
|
We encountered an error while processing your appointment. You can return to our site and try scheduling again at a later time.
|
|
</p>
|
|
</div>
|
|
<div class="diagnostic-info" id="diagnostic-container">
|
|
<hr />
|
|
<h2 class="subheader">
|
|
Bailout Information:
|
|
</h2>
|
|
<div id="bailout-info-container">
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
|
|
// Helpers
|
|
function getCookieValueByName(name) {
|
|
const value = "; " + document.cookie;
|
|
const parts = value.split("; " + name + "=");
|
|
|
|
if (parts.length === 2) {
|
|
return parts.pop().split(";").shift();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function getCurrentEnvironmentData() {
|
|
const environmentData = [
|
|
{
|
|
name: 'Localhost',
|
|
hostName: 'localhost',
|
|
apiHostname: 'digitalapi.dev.safelite.io',
|
|
debug: true,
|
|
},
|
|
{
|
|
name: 'Dev',
|
|
hostName: 'selfservice.dev.glassclaim.com',
|
|
apiHostname: 'digitalapi.dev.safelite.io',
|
|
debug: true,
|
|
},
|
|
{
|
|
name: 'SysTest',
|
|
hostName: 'selfservice.test.glassclaim.com',
|
|
apiHostname: 'digitalapi.test.safelite.io',
|
|
debug: true,
|
|
},
|
|
{
|
|
name: 'QA',
|
|
hostName: 'selfservice.qa.glassclaim.com',
|
|
apiHostname: 'digitalapi.qa.safelite.io',
|
|
debug: false,
|
|
},
|
|
{
|
|
name: 'Prod',
|
|
hostName: 'selfservice.glassclaim.com',
|
|
apiHostname: 'digitalapi.safelite.io',
|
|
debug: false,
|
|
},
|
|
];
|
|
|
|
const hostName = window.location.hostname;
|
|
|
|
const match = environmentData.find(
|
|
data => (data.hostName === hostName)
|
|
);
|
|
|
|
return match;
|
|
}
|
|
|
|
function getExperimentSettingsFromStore(storeData) {
|
|
const experiments = storeData?.applicationUser?.experiments;
|
|
|
|
if(experiments) {
|
|
return experiments
|
|
.filter((e) => !!e.isActive)
|
|
.map((e) => e.settings)
|
|
.reduce((prev, next) => Object.assign(prev, next), {}) ?? {};
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
function extractDataFromStore(mainStore) {
|
|
let bailoutInfo = [];
|
|
let headerInfo = [];
|
|
|
|
try {
|
|
// =============== Collect diagnostic data:
|
|
bailoutInfo = [];
|
|
|
|
// App & Site Name
|
|
bailoutInfo.push({ name: 'App Name', value: 'ISS' });
|
|
bailoutInfo.push({ name: 'Site Name', value: 'ISS 2.0' });
|
|
|
|
// Not included (yet) from heritage:
|
|
// - Site ID
|
|
// - Code
|
|
// - Module
|
|
// - Page
|
|
|
|
bailoutInfo.push({ name: 'Timestamp', value: `${new Date()}` });
|
|
|
|
// - URL
|
|
// - Server
|
|
|
|
const sessionId = getCookieValueByName('sid');
|
|
bailoutInfo.push({ name: 'Session Id', value: sessionId });
|
|
|
|
const userAgent = window.navigator.userAgent;
|
|
bailoutInfo.push({ name: 'User Agent', value: userAgent });
|
|
|
|
// - IP
|
|
// - Session Log Sequence Number
|
|
|
|
bailoutInfo.push({ name: 'Referral Seq Number', value: mainStore.order?.referralSequenceNumber });
|
|
bailoutInfo.push({ name: 'Referral Number', value: mainStore.order?.referralNumber });
|
|
bailoutInfo.push({ name: 'Referral Date', value: mainStore.order?.referralDate });
|
|
bailoutInfo.push({ name: 'Referral Provider Number', value: mainStore.order?.serviceLocation?.provider?.providerNumber });
|
|
bailoutInfo.push({ name: 'Referral CTU', value: mainStore.order?.serviceLocation?.provider?.address?.zipCodeCtu });
|
|
|
|
// - Referral Insured Zip
|
|
// - Referral Insured Service Zip
|
|
|
|
bailoutInfo.push({ name: 'Referral CarID', value: mainStore.order?.vehicle?.carId });
|
|
|
|
const vehicle = mainStore.order?.vehicle;
|
|
const vehicleString = vehicle?.year
|
|
? `${vehicle.year} ${vehicle.make} ${vehicle.model} - ${vehicle.style}`
|
|
: null;
|
|
bailoutInfo.push({ name: 'Referral Vehicle', value: vehicleString });
|
|
bailoutInfo.push({ name: 'Work Order Number', value: mainStore.order?.workOrderNumber });
|
|
bailoutInfo.push({ name: 'Work Order ID', value: mainStore.order?.workOrderId });
|
|
bailoutInfo.push({ name: 'Parent Account Number', value: mainStore.order?.parentAccountNumber });
|
|
|
|
const environmentData = getCurrentEnvironmentData();
|
|
const userIdCookieName = `ISSUserId-${environmentData?.name}`;
|
|
bailoutInfo.push({ name: 'User Id', value: getCookieValueByName(userIdCookieName) });
|
|
|
|
bailoutInfo.push({ name: 'Bailout URL', value: mainStore.applicationUser.pageData['bailout-page']?.url });
|
|
bailoutInfo.push({ name: 'Bailout Code', value: mainStore.applicationUser.pageData['bailout-page']?.bailoutCode });
|
|
bailoutInfo.push({ name: 'Bailout Message', value: mainStore.applicationUser.pageData['bailout-page']?.errorMessage });
|
|
|
|
// - Parent Account Name
|
|
// - Client GUID
|
|
|
|
// =============== Collect header data:
|
|
headerInfo = [];
|
|
|
|
headerInfo.push({ name: 'X-Experiment-Data', value: JSON.stringify(getExperimentSettingsFromStore(mainStore)) });
|
|
headerInfo.push({ name: 'X-Application-Name', value: 'ISS' });
|
|
|
|
const sessionKeyCookieName = `ISSSessionKey-${environmentData?.name}`;
|
|
|
|
headerInfo.push({ name: 'X-Session-Sequence-Number', value: getCookieValueByName(sessionKeyCookieName) });
|
|
headerInfo.push({ name: 'X-Referral-Sequence-Number', value: mainStore.order?.referralSequenceNumber });
|
|
headerInfo.push({ name: 'X-Enterprise-Order-Number', value: mainStore.order?.eon });
|
|
headerInfo.push({ name: 'log-enabled', value: mainStore.applicationUser?.loggingOption ?? false });
|
|
} finally {
|
|
return {
|
|
headerInfo: headerInfo,
|
|
bailoutInfo: bailoutInfo
|
|
};
|
|
}
|
|
}
|
|
|
|
function generateRequestHeader(headerInfo) {
|
|
let headers = {};
|
|
|
|
headerInfo.forEach(
|
|
keyPair => {
|
|
headers[keyPair.name] = keyPair.value;
|
|
}
|
|
);
|
|
|
|
headers['X-Transaction-Id'] = crypto.randomUUID();
|
|
|
|
headers['Content-Type'] = 'application/json';
|
|
|
|
return headers;
|
|
}
|
|
|
|
function getFieldWithName(info, name) {
|
|
const match = info?.find(
|
|
(row) => row.name === name
|
|
);
|
|
|
|
return match?.value;
|
|
}
|
|
|
|
function clearApplicationData() {
|
|
/*
|
|
const environmentData = getCurrentEnvironmentData();
|
|
const cookieNames = [
|
|
`ISSUserId-${environmentData?.name}`,
|
|
`ISSSessionKey-${environmentData?.name}`,
|
|
`ISSSessionInfo-${environmentData?.name}`,
|
|
`sid`,
|
|
`dxdev`,
|
|
];
|
|
|
|
cookieNames.forEach(
|
|
(cookieName) => {
|
|
let cookieToAdd = `${cookieName}=undefined; path=/; domain=${environmentData.hostName}; max-age=0`;
|
|
document.cookie = cookieToAdd;
|
|
}
|
|
)
|
|
*/
|
|
}
|
|
|
|
window.onload = async () => {
|
|
// =============== Check for session info:
|
|
const existingStoreDataJSON = window.sessionStorage.getItem('main');
|
|
const mainStore = existingStoreDataJSON ? JSON.parse(existingStoreDataJSON) : null;
|
|
const bailoutData = mainStore.applicationUser.pageData['bailout-page'];
|
|
|
|
console.log(`================ STORE DATA`);
|
|
console.log(mainStore);
|
|
console.log(`================ PRIOR BAILOUT DATA`);
|
|
console.log(bailoutData);
|
|
|
|
/*
|
|
console.log(`================ PRIOR HEADER DATA`);
|
|
console.log(existingHeaderInfo);
|
|
*/
|
|
let bailoutInfo = null;
|
|
let headerInfo = null;
|
|
|
|
if(mainStore) {
|
|
const results = extractDataFromStore(mainStore);
|
|
bailoutInfo = results.bailoutInfo;
|
|
headerInfo = results.headerInfo;
|
|
|
|
//clearApplicationData();
|
|
|
|
if(bailoutInfo) {
|
|
window.sessionStorage.setItem('bailoutInfo', JSON.stringify(bailoutInfo));
|
|
}
|
|
|
|
if(headerInfo) {
|
|
window.sessionStorage.setItem('headerInfo', JSON.stringify(headerInfo));
|
|
}
|
|
} else {
|
|
bailoutInfo = existingBailoutInfo ?? [];
|
|
headerInfo = existingHeaderInfo ?? [];
|
|
}
|
|
|
|
const environmentInfo = getCurrentEnvironmentData();
|
|
const shouldShowDebugInfo = environmentInfo?.debug;
|
|
|
|
if(bailoutInfo && shouldShowDebugInfo) {
|
|
try {
|
|
// =============== Display diagnostic data:
|
|
// Create display nodes
|
|
const elements = bailoutInfo.map(
|
|
dataPoint => {
|
|
const element = document.createElement('li');
|
|
element.textContent = `${dataPoint.name}: ${dataPoint.value}`;
|
|
|
|
return element;
|
|
}
|
|
);
|
|
|
|
const fragment = new DocumentFragment();
|
|
|
|
elements.forEach(
|
|
(element) => {
|
|
fragment.append(element);
|
|
}
|
|
);
|
|
|
|
// Attach nodes to DOM and render
|
|
const attachNode = document.getElementById('bailout-info-container');
|
|
if(attachNode) {
|
|
const ul = attachNode.appendChild(document.createElement('ul'));
|
|
ul.append(fragment);
|
|
}
|
|
} catch(e) {
|
|
console.error(`=== ERROR DISPLAYING INFO`);
|
|
console.error(e);
|
|
|
|
const diagnosticContainer = document.getElementById('diagnostic-container');
|
|
diagnosticContainer.remove();
|
|
}
|
|
} else {
|
|
const diagnosticContainer = document.getElementById('diagnostic-container');
|
|
diagnosticContainer.remove();
|
|
}
|
|
|
|
// TODO: Re-enable logging after some further testing.
|
|
/*
|
|
const apiHostname = environmentInfo?.apiHostname;
|
|
if(apiHostname) {
|
|
try {
|
|
const endpointUrl = `https://${apiHostname}/analytics/api/v1/logging/log-error`;
|
|
|
|
const infoString = bailoutInfo?.map(
|
|
(entry) => `${entry.name}: ${entry.value}`
|
|
)?.reduce(
|
|
(prev, next) => `${prev}\n${next}`
|
|
);
|
|
const entryString = `User encountered bailout page.\n${new Date()}\n${infoString ?? 'No information recoverable'}`;
|
|
|
|
const headers = generateRequestHeader(headerInfo);
|
|
|
|
const request = new Request(endpointUrl, {
|
|
method: 'POST',
|
|
headers: headers,
|
|
body: JSON.stringify({
|
|
entry: entryString,
|
|
}),
|
|
});
|
|
|
|
const response = await fetch(request);
|
|
// Don't need data from response, but could get it here with:
|
|
// const responseData = await response.json();
|
|
} catch(e) {
|
|
console.error(`=== ERROR SENDING LOGGING`);
|
|
console.error(e);
|
|
}
|
|
|
|
try {
|
|
const endpointUrl = `https://${apiHostname}/analytics/api/v1/analytics/log-page-view`;
|
|
|
|
const headers = generateRequestHeader(headerInfo);
|
|
|
|
const payload = {
|
|
AppName: "ISS",
|
|
action: "",
|
|
applicationName: "ISS",
|
|
event: "ENTRY",
|
|
experimentsForUser: [],
|
|
pageName: "static-error",
|
|
parentAccountNumber: getFieldWithName(bailoutInfo, 'Parent Account Number') ?? 0,
|
|
referralSequenceNumber: getFieldWithName(bailoutInfo, 'Referral Seq Number'),
|
|
sessionId: getFieldWithName(bailoutInfo, 'Session Id'),
|
|
sessionKey: getFieldWithName(headerInfo, 'X-Session-Sequence-Number'),
|
|
shouldUseSessionId: false,
|
|
userId: getFieldWithName(bailoutInfo, 'User Id'),
|
|
};
|
|
|
|
const request = new Request(endpointUrl, {
|
|
method: 'POST',
|
|
headers: headers,
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
const response = await fetch(request);
|
|
} catch(e) {
|
|
console.error(`=== ERROR SENDING PAGEVIEW`);
|
|
console.error(e);
|
|
}
|
|
}
|
|
*/
|
|
};
|
|
</script>
|
|
</body>
|
|
</html> |