diff --git a/.gitignore b/.gitignore index fc42c524..b5400d3e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ pnpm-debug.log* # Misc coverage/* -junit.xml \ No newline at end of file +junit.xml +/.vs diff --git a/src/App.vue b/src/App.vue index 1d64f934..fd4a5b43 100644 --- a/src/App.vue +++ b/src/App.vue @@ -14,5 +14,5 @@ @import "@/styles/common-error-styles.scss"; @import "@/styles/common-animations.scss"; @import "@/styles/shared-input-button-styles.scss"; - @import "@/styles/client-customizations.scss" + @import "@/styles/client-customizations.scss"; diff --git a/src/constants/application-config.js b/src/constants/application-config.js index e0ae8df6..389c15d8 100644 --- a/src/constants/application-config.js +++ b/src/constants/application-config.js @@ -11,6 +11,7 @@ const applicationConfig = { CLIENTTAG_QUERYSTRING: 'CientTag', GOOGLE_PLACES_API_KEY: process.env.VUE_APP_GOOGLE_PLACES_API_KEY, ISS_DEV_CMS_DOMAIN: "https://digitalisscms.dev.safelite.io", + CASH_PARENT_ACCOUNT_NUMBER: 167132 }; export { applicationConfig }; \ No newline at end of file diff --git a/src/constants/damage-custom-labels.js b/src/constants/damage-custom-labels.js index b7ce7608..ca9e5271 100644 --- a/src/constants/damage-custom-labels.js +++ b/src/constants/damage-custom-labels.js @@ -2,7 +2,7 @@ const damageCustomLabels = Object.freeze({ MATCH: 'match', REAR_WINDOW: 'rear window', SIDE_WINDOW: 'side window', - WINDSHIELD: 'windshield', + WINDSHIELD: 'windshield' }); export default damageCustomLabels; diff --git a/src/constants/damage-locations-cms.js b/src/constants/damage-locations-cms.js index 82a43175..1326ef9f 100644 --- a/src/constants/damage-locations-cms.js +++ b/src/constants/damage-locations-cms.js @@ -3,7 +3,7 @@ const damageLocationsCms = { SIDEDOOR: "SIDEDOOR", REARWINDOW: "REARWINDOW", DRIVERSIDE: "DRIVERSIDE", - PASSENGERSIDE: "PASSENGERSIDE", + PASSENGERSIDE: "PASSENGERSIDE" }; export { damageLocationsCms }; diff --git a/src/constants/damage-locations-selected.js b/src/constants/damage-locations-selected.js index 7ede615c..f152e02f 100644 --- a/src/constants/damage-locations-selected.js +++ b/src/constants/damage-locations-selected.js @@ -15,7 +15,7 @@ const damageLocationsSelected = { DRIVERSIDE: "DriverSide", PASSENGERSIDE: "PassengerSide", STATIONARY: "Stationary", - SLIDER: "Slider", + SLIDER: "Slider" }; export { damageLocationsSelected }; diff --git a/src/constants/dynamic-strings.js b/src/constants/dynamic-strings.js index b81c0f30..1cff1d26 100644 --- a/src/constants/dynamic-strings.js +++ b/src/constants/dynamic-strings.js @@ -2,7 +2,8 @@ const dynamicStrings = { GLOBAL_STATE: "globalState", CUSTOM: "custom", ROUTER_LINK: "routerLink:", - MODAL_LINK: "modalLink" + MODAL_LINK: "modalLink", + TEXT_LINK: 'textLink' }; export { dynamicStrings }; \ No newline at end of file diff --git a/src/constants/dynamictext-mapper.js b/src/constants/dynamictext-mapper.js index 9191c878..2e0be064 100644 --- a/src/constants/dynamictext-mapper.js +++ b/src/constants/dynamictext-mapper.js @@ -18,8 +18,8 @@ const customMappings = { { key: "Passenger Back", transformedValue: "passenger side back door" }, { key: "Passenger Vent", transformedValue: "passenger side vent glass" }, { key: "Passenger Quarter", transformedValue: "passenger side quarter panel" }, - { key: "Passenger SlideDoor", transformedValue: "passenger side sliding door" }, - ], + { key: "Passenger SlideDoor", transformedValue: "passenger side sliding door" } + ] }; // Gets an instance of a string where the dynamic portion of the text {custom:KeyName} diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 69da2eae..c9cb6116 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -39,6 +39,10 @@ const endpoints = { url: "/parts/api/v1/parts/parts", method: "POST", }, + GetPriceOrderItems: { + url: '/price/api/v1/price/order-items', + method: 'GET' + }, GetCapabilityQuestions: { url: "/parts/api/v1/parts/capability-questions", method: "GET", @@ -46,7 +50,19 @@ const endpoints = { GetPartFromCapabilityAnswer: { url: "/parts/api/v1/parts/part-from-capability-answer", method: "POST", -}, + }, + GetWipers: { + url: '/parts/api/v1/parts/wipers', + method: 'GET' + }, + GetRainDefense: { + url: '/parts/api/v1/parts/rain-defense', + method: 'GET' + }, + GetSupportingItems: { + url: '/parts/api/v1/parts/supporting-items', + method: 'POST' + }, GetVehicle: { url: "/vehicle/api/v1/vehicle/lookup", method: "GET", @@ -64,20 +80,20 @@ const endpoints = { method: "POST", }, LookupVehicleByVin: { - url: "/vehicle/api/v1/vehicle/lookup", - method: "POST", + url: "/vehicle/api/v1/vehicle/lookup", + method: "POST", }, LookupVinByAddress: { url: "/vehicle/api/v1/vehicle/lookup-vin-by-address", - method: "POST", + method: "POST", }, LookupVinByPlate: { url: "/vehicle/api/v1/vehicle/lookup-vin-by-plate", method: "POST", }, InitializeSession: { - url: "/analytics/api/v1/analytics/initialize", - method: "POST", + url: "/analytics/api/v1/analytics/initialize", + method: "POST", }, GetExperimentsByUser: { url: "/analytics/api/v1/analytics/get-experiments", diff --git a/src/constants/error-messages.js b/src/constants/error-messages.js index f1930ac0..0aeff385 100644 --- a/src/constants/error-messages.js +++ b/src/constants/error-messages.js @@ -36,7 +36,7 @@ const errorMessages = { DAMAGE_OPTION_REQUIRED: "Please select an option", POLICYHOLDER_FIRST_NAME_REQUIRED: "Please enter the policyholder first name", - POLICYHOLDER_LAST_NAME_REQUIRED: "Please enter the policyholder last name", + POLICYHOLDER_LAST_NAME_REQUIRED: "Please enter the policyholder last name" }; diff --git a/src/constants/events.js b/src/constants/events.js index f416eeff..3f3821ae 100644 --- a/src/constants/events.js +++ b/src/constants/events.js @@ -1,17 +1,17 @@ const globalEvents = { Categories: { - GLOBAL_ALERT: "GLOBAL_ALERT", + GLOBAL_ALERT: "GLOBAL_ALERT" }, SubCategories: { - PAGE_NOT_FOUND: "PAGE_NOT_FOUND", - }, + PAGE_NOT_FOUND: "PAGE_NOT_FOUND" + } }; const globalEventTypes = { Success: "alert-success", Warning: "alert-warning", Info: "alert-info", - Danger: "alert-danger", + Danger: "alert-danger" }; export { globalEvents, globalEventTypes }; diff --git a/src/constants/experiments.js b/src/constants/experiments.js index a75c711f..ed110578 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -1,14 +1,14 @@ const experimentUniverses = { - ISS_FUNNEL: "ISSFunnel", + ISS_FUNNEL: "ISSFunnel" }; const experimentSettings = { - GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index", + GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index" }; const experimentTriggers = { SITE_ENTRY: "SiteEntry", - PAGE_ENTRY: "PageEntry", + PAGE_ENTRY: "PageEntry" }; export { experimentUniverses, experimentSettings, experimentTriggers }; diff --git a/src/constants/header-keys.js b/src/constants/header-keys.js index 2cfbba36..a59d7160 100644 --- a/src/constants/header-keys.js +++ b/src/constants/header-keys.js @@ -1,3 +1,3 @@ export const headerKeys = { - EXPERIMENT: "X-Experiment-Data", + EXPERIMENT: "X-Experiment-Data" }; diff --git a/src/constants/mock-endpoints.js b/src/constants/mock-endpoints.js index ca67c3fe..09f54749 100644 --- a/src/constants/mock-endpoints.js +++ b/src/constants/mock-endpoints.js @@ -3,8 +3,8 @@ const endpoints = { GetRouteInfo: { url: "https://mockey.qa.sagaws.net/service/ISS/Content/RouteInfo", - method: "GET", - }, + method: "GET" + } }; diff --git a/src/constants/part-type-strings.js b/src/constants/part-type-strings.js new file mode 100644 index 00000000..8e4a4951 --- /dev/null +++ b/src/constants/part-type-strings.js @@ -0,0 +1,8 @@ +const partTypeStrings = { + FRONT_WIPER: 'FRONT WIPER', + REAR_WIPER: 'REAR WIPER', + RAIN_DEFENSE: 'RAIN DEFENSE', + RECALIBRATION: 'RECALIBRATION' +}; + +export { partTypeStrings }; \ No newline at end of file diff --git a/src/constants/states.js b/src/constants/states.js index 00fb6edd..ba6b5f55 100644 --- a/src/constants/states.js +++ b/src/constants/states.js @@ -49,5 +49,5 @@ export const states = { WA: "Washington", WV: "West Virginia", WI: "Wisconsin", - WY: "Wyoming", + WY: "Wyoming" }; \ No newline at end of file diff --git a/src/constants/tint-mapper.js b/src/constants/tint-mapper.js index 308b9a92..f8f462bb 100644 --- a/src/constants/tint-mapper.js +++ b/src/constants/tint-mapper.js @@ -34,7 +34,7 @@ const tintMap = { { name: "gray tint privacy", src: "Glass-NoShade-GrayTint.svg" }, // No shade or tint - { name: "clear", src: "Glass-NoShade-NoTint.svg" }, + { name: "clear", src: "Glass-NoShade-NoTint.svg" } ], windshield: [ @@ -69,8 +69,8 @@ const tintMap = { { name: "gray tint privacy", src: "Windshield-NoShade-GrayTint.svg" }, // No shade or tint - { name: "clear", src: "Windshield-NoShade-NoTint.svg" }, - ], + { name: "clear", src: "Windshield-NoShade-NoTint.svg" } + ] }; // Gets the tint image source string given the glass location, and the tint description (like 'Green Tint') diff --git a/src/constants/vehicle-categories.js b/src/constants/vehicle-categories.js index 4fab279d..fa3ebb80 100644 --- a/src/constants/vehicle-categories.js +++ b/src/constants/vehicle-categories.js @@ -5,7 +5,7 @@ const vehicleCategories = { COMMERCIALVAN: "COMMERCIAL VAN", SUV: "SUV", MOTORHOME: "MOTOR HOME", - SEMI: "SEMI", + SEMI: "SEMI" }; export { vehicleCategories }; \ No newline at end of file diff --git a/src/constants/vin-lookup-methods.js b/src/constants/vin-lookup-methods.js index ce2f2859..6af7e969 100644 --- a/src/constants/vin-lookup-methods.js +++ b/src/constants/vin-lookup-methods.js @@ -1,7 +1,7 @@ const vinLookupMethodSelections = Object.freeze({ MANUALVIN: 'ManualVin', LICENSEPLATE: 'LicensePlate', - HOMEADDRESS: 'HomeAddress', + HOMEADDRESS: 'HomeAddress' }); export {vinLookupMethodSelections}; diff --git a/src/digital-components/button-question/button-question.vue b/src/digital-components/button-question/button-question.vue index 68653049..d36cac83 100644 --- a/src/digital-components/button-question/button-question.vue +++ b/src/digital-components/button-question/button-question.vue @@ -37,7 +37,7 @@ :buttonLabel="answer.buttonLabel" :buttonLabelSubCopy="answer.buttonLabelSubCopy" :buttonBodyCopy="answer.buttonBodyCopy" - :buttonAuxillaryCopy="answer.buttonAuxillaryCopy" + :buttonAuxiliaryCopy="answer.buttonAuxiliaryCopy" :buttonFooterCopy="answer.buttonFooterCopy" :buttonImage="answer.buttonImage" :buttonImageId="answer.buttonImageId" @@ -194,7 +194,7 @@ export default { altText: answer.altText ?? (answer.Name ? answer.Name : answer), buttonLabelSubCopy: answer.buttonLabelSubCopy ?? answer.SubText, buttonBodyCopy: answer.buttonBodyCopy ?? answer.buttonBodyCopy, - buttonAuxillaryCopy: answer.buttonAuxillaryCopy ?? answer.buttonAuxillaryCopy, + buttonAuxiliaryCopy: answer.buttonAuxiliaryCopy ?? answer.buttonAuxiliaryCopy, buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy, buttonImage: answer.buttonImage ?? answer.AnswerImageUrl, buttonImageId: answer.buttonImageId ?? answer.ImageId, diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index 36b6dd9c..665b9023 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -1,4 +1,4 @@ -import { dynamicStrings } from "@/constants/dynamic-strings"; +import { dynamicStrings } from '@/constants/dynamic-strings'; import { useMainStore } from '@/store'; export function fetchCmsContentForPage(issPage) { @@ -18,7 +18,7 @@ export function fetchCmsContentForPage(issPage) { } else { // Else get the client override page. - const pageName = issPage + "_" + clientName.toLowerCase().replace(/ /g, ""); + const pageName = issPage + '_' + clientName.toLowerCase().replace(/ /g, ''); return store.getPageData(pageName) .then( @@ -26,7 +26,8 @@ export function fetchCmsContentForPage(issPage) { // Process the client override if it exists. return processPageData(baseResponse, clientResponse); }, - (error) => { + (error) => { + console.error(error); // Process the just the base if no client override exists. return processPageData(baseResponse, null); } @@ -44,8 +45,11 @@ function processPageData(baseResponse, clientResponse) { const pageDataFromCms = {}; let widgets = []; - if ( clientResponse === null ) - { + if (!baseResponse?.data?.Result) { + console.error('No result data found'); // Something has gone terribly wrong. + return {} + } + if (!clientResponse?.data?.Result) { widgets = baseResponse.data.Result; } else @@ -89,7 +93,7 @@ function processPageData(baseResponse, clientResponse) { widgets.forEach((widget) => { // Global state value replacement. - let widgetWithReplacements = findAndReplaceGlobalStateValues( + const widgetWithReplacements = findAndReplaceGlobalStateValues( widget.Model, widget.Name ); @@ -103,7 +107,7 @@ function processPageData(baseResponse, clientResponse) { } pageDataFromCms[widgetWithReplacements.Name] = [ - widgetWithReplacements.Model, + widgetWithReplacements.Model ]; }); @@ -121,7 +125,7 @@ function processPageData(baseResponse, clientResponse) { function findAndReplaceGlobalStateValues(widgetModel, widgetName) { const objWithReplacements = { Name: widgetName, - Model: {}, + Model: {} }; Object.keys(widgetModel).forEach((key) => { @@ -140,13 +144,13 @@ function findAndReplaceGlobalStateValues(widgetModel, widgetName) { // This is a recursive function, it will call itself until it runs out of items to iterate on given the object. function processWidgetItemForReplacement(widgetModel, key) { // If we have a string, and it needs to be replaced. - if (typeof widgetModel[key] === "string") { + if (typeof widgetModel[key] === 'string') { widgetModel[key] = processIfStatements( widgetModel[key], dynamicStrings.GLOBAL_STATE, getStoreValueFromString ); - + if (widgetModel[key].includes(dynamicStrings.GLOBAL_STATE)) { widgetModel[key] = mapStringToState(widgetModel[key]); } @@ -158,7 +162,7 @@ function processWidgetItemForReplacement(widgetModel, key) { // If we have an object. array, etc if ( - typeof widgetModel[key] === "object" && + typeof widgetModel[key] === 'object' && Object.keys(widgetModel[key]).length ) { Object.keys(widgetModel[key]).forEach((item) => { @@ -173,47 +177,43 @@ function processWidgetItemForReplacement(widgetModel, key) { } function mapStringToModal(str) { - let startIndex = str.indexOf("{" + dynamicStrings.MODAL_LINK); - let linkToReplace = str.substring(startIndex, str.length); - linkToReplace = linkToReplace.substring(0, linkToReplace.indexOf("}") + 1); + const startIndex = str.indexOf('{' + dynamicStrings.MODAL_LINK); + const linkToReplace = str.substring(startIndex, str.length); + linkToReplace = linkToReplace.substring(0, linkToReplace.indexOf('}') + 1); - let params = linkToReplace.substring((dynamicStrings.MODAL_LINK).length + 2, linkToReplace.length -1); - let splitParams = params.split(","); + const params = linkToReplace.substring((dynamicStrings.MODAL_LINK).length + 2, linkToReplace.length -1) + const splitParams = params.split(','); + + const bodyText = '' + splitParams[1] + ''; - let bodyText = '' + splitParams[1] + ''; let returnVal = str.replace(linkToReplace, bodyText); if (returnVal.includes(dynamicStrings.MODAL_LINK)) { - returnVal = mapStringToModal(returnVal); + returnVal = mapStringToModal(returnVal) } - return returnVal; + return returnVal } // Function to convert a string, into a matching global state item. function mapStringToState(str) { // Pull all matches out of the string. - const regexExp = new RegExp("{(.*?):(.*?)}", "g"); + const regexExp = new RegExp('{([^{}]*?):([^{}]*?)}', 'g'); const regexMatches = [...str.matchAll(regexExp)]; const globalStateMatches = regexMatches.filter(match => { return match[1] === dynamicStrings.GLOBAL_STATE; }); // Our final string value that will be built from the matches. - let stringBuilder = ""; + let stringBuilder = ''; for (const match of globalStateMatches) { // Reset store state for each match. - let storeState = useMainStore(); - - for (const s of match[2].split(".")) { - if (storeState[s] != undefined) { - storeState = storeState[s]; - } else { - return ""; // if we can't map our string to state data, return an empty string. - } + const valueFromStore = getStoreValueFromString(match[2]); + if (!valueFromStore) { + console.warning('Unable to resolve global state data.'); + return '' // if we can't map our string to state data, return an empty string. } - - const stringWithReplacement = str.replace(match[0], storeState); + const stringWithReplacement = str.replace(match[0], valueFromStore); // If we still have values we need to substitute, call this function again. if (stringWithReplacement.includes(dynamicStrings.GLOBAL_STATE)) { @@ -227,18 +227,19 @@ function mapStringToState(str) { return stringBuilder.trimStart(); } - function getStoreValueFromString(str) { - let storeOrStateObject = useMainStore(); - for (const s of str.split('.')) { - if (s === 'getters') continue; - if (storeOrStateObject[s] != undefined) { - storeOrStateObject = storeOrStateObject[s]; - } else { - return '' - } - } - return storeOrStateObject; + if (!str) return ''; + + let storeOrStateObject = useMainStore(); + for (const s of str.split('.')) { + if (s === 'getters') continue; //For backward compatability + if (storeOrStateObject[s] != undefined) { + storeOrStateObject = storeOrStateObject[s]; + } else { + break; + } + } + return storeOrStateObject ?? ''; } /////////////////////////////////// @@ -246,173 +247,179 @@ function getStoreValueFromString(str) { /////////////////////////////////// /** -* Recursive function - replaces all instances of if statements from the CMS that utilize the specified ifConditionKeyword -* @param {*} str string - Input string to be processed -* @param {*} ifConditionKeyword string - Defines which if statements to process ex: 'globalState' -* @param {*} replacePlaceholderCallback function - Callback to replace CMS placeholder values -* @returns The processed string -*/ + * Recursive function - replaces all instances of if statements from the CMS that utilize the specified ifConditionKeyword + * @param {*} str string - Input string to be processed + * @param {*} ifConditionKeyword string - Defines which if statements to process ex: 'globalState' + * @param {*} replacePlaceholderCallback function - Callback to replace CMS placeholder values + * @returns The processed string + */ export function processIfStatements(str, ifConditionKeyword, replacePlaceholderCallback) { - const containsRelevantIfStatement = new RegExp('{if:' + ifConditionKeyword + ':.+?}', 'g').test( - str - ); - //str = str.replace(/\r?\n|\r/g, ''); + const containsRelevantIfStatement = new RegExp('{if:' + ifConditionKeyword + ':.+?}', 'g').test( + str + ); - const hasEmbeddedCrLf = /\r?\n|\r/g.test(str); - if (!containsRelevantIfStatement || hasEmbeddedCrLf) { - return str; - } else { - const ifStatementRegexExpression = getIfStatementRegexExpression(); - const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)]; - const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword( - ifStatementRegexMatches, - ifConditionKeyword - ); - executeIfStatementAndSetProcessedStrings( - completeIfStatementArray, - replacePlaceholderCallback - ); - const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches); - return processIfStatements( - reconstructedPostProcessedString, - ifConditionKeyword, - replacePlaceholderCallback - ); - } + const hasEmbeddedCrLf = /\r?\n|\r/g.test(str); + if (hasEmbeddedCrLf) { + console.warning('Processing of conditional string was skipped. String has embedded carriage return/linefeed.'); + } + if (!containsRelevantIfStatement || hasEmbeddedCrLf) { + return str; + } else { + const ifStatementRegexExpression = getIfStatementRegexExpression(); + const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)]; + const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword( + ifStatementRegexMatches, + ifConditionKeyword + ); + executeIfStatementAndSetProcessedStrings( + completeIfStatementArray, + replacePlaceholderCallback + ); + const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches); + return processIfStatements( + reconstructedPostProcessedString, + ifConditionKeyword, + replacePlaceholderCallback + ); + } } function getAndFlagFirstNonNestedIfStatementWithKeyword(matches, ifConditionKeyword) { - let index = 0; - for (const match of matches) { - if (match.groups.isIfStatement && match.groups.ifConditionType === ifConditionKeyword) { - let interiorIndex = 0; - let nestedLevel = 0; - let elseStatementIndex = null; - for (const interiorMatch of matches.slice(index + 1)) { - if (interiorMatch.groups.isIfStatement) { - if (interiorMatch.groups.ifConditionType === ifConditionKeyword) { - break; - } else { - nestedLevel++; - } - } else if (interiorMatch.groups.isElseStatement) { - if (!nestedLevel) { - elseStatementIndex = interiorIndex + 1; - } - } else if (interiorMatch.groups.isEndStatement) { - if (nestedLevel) { - nestedLevel--; - } else { - const ifStatementArray = matches.slice(index, index + interiorIndex + 2); - flagMatchesForProcessing(ifStatementArray, elseStatementIndex); - return ifStatementArray; - } - } - interiorIndex++; - } - } - index++; - } - console.error('Did not find end in conditional logic'); - return matches; + let index = 0; + for (const match of matches) { + if (match.groups.isIfStatement && match.groups.ifConditionType === ifConditionKeyword) { + let interiorIndex = 0; + let nestedLevel = 0; + let elseStatementIndex = null; + for (const interiorMatch of matches.slice(index + 1)) { + if (interiorMatch.groups.isIfStatement) { + if (interiorMatch.groups.ifConditionType === ifConditionKeyword) { + break; + } else { + nestedLevel++; + } + } else if (interiorMatch.groups.isElseStatement) { + if (!nestedLevel) { + elseStatementIndex = interiorIndex + 1; + } + } else if (interiorMatch.groups.isEndStatement) { + if (nestedLevel) { + nestedLevel--; + } else { + const ifStatementArray = matches.slice(index, index + interiorIndex + 2); + flagMatchesForProcessing(ifStatementArray, elseStatementIndex); + return ifStatementArray; + } + } + interiorIndex++; + } + } + index++; + } + console.error('Did not find end in conditional logic'); + return matches; } function flagMatchesForProcessing(matches, elseStatementIndex) { - matches[0].isFlaggedForProcessing = true; - matches[matches.length - 1].isFlaggedForProcessing = true; - if (elseStatementIndex) { - matches[elseStatementIndex].isFlaggedForProcessing = true; - } + matches[0].isFlaggedForProcessing = true; + matches[matches.length - 1].isFlaggedForProcessing = true; + if (elseStatementIndex) { + matches[elseStatementIndex].isFlaggedForProcessing = true; + } } function joinProcessedRegexArray(regexMatches) { - let processedString = ''; - regexMatches.forEach((match) => { - const rawString = match[0]; - processedString += match.groups.processedString ?? rawString; - }); - return processedString; + let processedString = ''; + regexMatches.forEach((match) => { + const rawString = match[0]; + processedString += match.groups.processedString ?? rawString; + }); + return processedString; } function executeIfStatementAndSetProcessedStrings(ifStatementArray, replacePlaceholderCallback) { - const ifCondition = replacePlaceholderCallback(ifStatementArray[0].groups.ifCondition); - let isInsideDesiredBlock = ifCondition; + const ifCondition = replacePlaceholderCallback(ifStatementArray[0].groups.ifCondition); + let isInsideDesiredBlock = ifCondition; - ifStatementArray.forEach((entry) => { - if (entry.groups.isElseStatement && entry.isFlaggedForProcessing) { - isInsideDesiredBlock = !ifCondition; - } else if (entry.groups.isEndStatement && entry.isFlaggedForProcessing) { - isInsideDesiredBlock = true; - } - setProcessedStringOnEntry(entry, isInsideDesiredBlock); - }); + ifStatementArray.forEach((entry) => { + if (entry.groups.isElseStatement && entry.isFlaggedForProcessing) { + isInsideDesiredBlock = !ifCondition; + } else if (entry.groups.isEndStatement && entry.isFlaggedForProcessing) { + isInsideDesiredBlock = true; + } + setProcessedStringOnEntry(entry, isInsideDesiredBlock); + }); } function setProcessedStringOnEntry(entry, isInsideDesiredBlock) { - if (!isInsideDesiredBlock) { - entry.groups.processedString = ''; - } else { - if (entry.groups.isIfStatement) { - entry.groups.processedString = entry.isFlaggedForProcessing - ? entry.groups.ifTrailingString - : entry[0]; - } else if (entry.groups.isElseStatement) { - entry.groups.processedString = entry.isFlaggedForProcessing - ? entry.groups.elseTrailingString - : entry[0]; - } else { - entry.groups.processedString = entry.isFlaggedForProcessing - ? entry.groups.endTrailingString - : entry[0]; - } - } + if (!isInsideDesiredBlock) { + entry.groups.processedString = ''; + } else { + if (entry.groups.isIfStatement) { + entry.groups.processedString = entry.isFlaggedForProcessing + ? entry.groups.ifTrailingString + : entry[0]; + } else if (entry.groups.isElseStatement) { + entry.groups.processedString = entry.isFlaggedForProcessing + ? entry.groups.elseTrailingString + : entry[0]; + } else { + entry.groups.processedString = entry.isFlaggedForProcessing + ? entry.groups.endTrailingString + : entry[0]; + } + } } function getIfStatementRegexExpression() { - // Matches but does not capture: - // {if:...} or {else} or {end} - const anyLogicOperatorNonCapture = '(?:{(?:end|else|if:.*?)})'; - // NOTE: ? syntax stores the captured match like so: match.groups.variableName - const matchStartOfString = - '(?^.+?)' + // Match and Capture all characters (lazy), cannot be empty - '(?=(?:{if))'; // Looks ahead but does not capture {if - const matchIfOperator = - '(?{if:)' + // Match & Capture {if: - '(?.*?):' + // Match all chars up to and including next ':' - Capture all chars up to ':' - '(?.*?)}' + // Match all chars up to and including next '}' - Capture all chars up to '}' - '(?.*?)' + // Match and Capture all characters (lazy), can be empty - '(?=' + - anyLogicOperatorNonCapture + - ')'; // Looks ahead but does not capture the next logic operator - const matchElseOperator = - '(?{else})' + // Match & Capture {else} - '(?.*?)' + // Match & Capture all characters (lazy), can be empty - '(?=' + - anyLogicOperatorNonCapture + - ')'; // Looks ahead but does not capture the next logic operator - const matchEndOperator = - '(?{end})' + // Match & Capture {end} - '(?.*?)' + // Match & Capture all chracters (lazy), can be empty - '(?=' + - anyLogicOperatorNonCapture + - '|$)'; // Looks ahead but does not capture the next logic operator - // Combine all matching patterns, separated by 'or' pipes - return new RegExp( - matchStartOfString + - '|' + - matchIfOperator + - '|' + - matchElseOperator + - '|' + - matchEndOperator, - 'g' - ); + // Matches but does not capture: + // {if:...} or {else} or {end} + const anyLogicOperatorNonCapture = '(?:{(?:end|else|if:.*?)})'; + // NOTE: ? syntax stores the captured match like so: match.groups.variableName + const matchStartOfString = + '(?^.+?)' + // Match and Capture all characters (lazy), cannot be empty + '(?=(?:{if))'; // Looks ahead but does not capture {if + const matchIfOperator = + '(?{if:)' + // Match & Capture {if: + '(?.*?):' + // Match all chars up to and including next ':' - Capture all chars up to ':' + '(?.*?)}' + // Match all chars up to and including next '}' - Capture all chars up to '}' + '(?.*?)' + // Match and Capture all characters (lazy), can be empty + '(?=' + + anyLogicOperatorNonCapture + + ')'; // Looks ahead but does not capture the next logic operator + const matchElseOperator = + '(?{else})' + // Match & Capture {else} + '(?.*?)' + // Match & Capture all characters (lazy), can be empty + '(?=' + + anyLogicOperatorNonCapture + + ')'; // Looks ahead but does not capture the next logic operator + const matchEndOperator = + '(?{end})' + // Match & Capture {end} + '(?.*?)' + // Match & Capture all chracters (lazy), can be empty + '(?=' + + anyLogicOperatorNonCapture + + '|$)'; // Looks ahead but does not capture the next logic operator + // Combine all matching patterns, separated by 'or' pipes + return new RegExp( + matchStartOfString + + '|' + + matchIfOperator + + '|' + + matchElseOperator + + '|' + + matchEndOperator, + 'g' + ); } ////////////////////////////////////////// // End of If Statement Processing Logic // ////////////////////////////////////////// +export function doesCopyContainTextLink(copy) { + return copy.includes(dynamicStrings.TEXT_LINK); +} + export function setupModalLinks(context) { context.$nextTick(() => { const elements = document.getElementsByClassName("modal-text") @@ -430,23 +437,35 @@ export function doesCopyContainRouterLink(copy) { return copy.includes(this.dynamicStrings.ROUTER_LINK); } +/** + * splits copy on { ... } such as {routerlink: ...} + * @returns array of strings + */ export function splitCopyOnCMSPlaceHolder(copy) { // splits copy on { ... } such as {routerlink: ...} return copy.split(/{(.*?)}/g); } +/** + * Returns string2 of input following this pattern: {string1:string2,string3} + * @returns string + */ export function getRouterLinkRouteFromCopy(copy) { // sample input: {routerLink:estimate,provide your VIN} // first split would return 'estimate,provide your VIN' // second split would return 'estimate' - return copy.split(":")[1].split(",")[0]; + return copy.split(':')[1].split(',')[0]; } +/** + * Returns string3 of input following this pattern: { string1: string2, string3 } + * @returns string + */ export function getRouterLinkDisplayTextFromCopy(copy) { // sample input: {routerLink:estimate,provide your VIN} // first split would return 'estimate,provide your VIN' // second split would return 'provide your VIN' - return copy.split(":")[1].split(",")[1]; + return copy.split(':')[1].split(',')[1]; } // Copy returned from the CMS that has newlines will return blocks wrapped in @@ -455,5 +474,5 @@ export function getRouterLinkDisplayTextFromCopy(copy) { // attributes present export function splitCMSCopyOnParagraphTag(copy) { // filter removes empty strings that are a result of string.split with regex - return copy.split(/(?:)|(?:<\/p>)/g).filter((paragraph) => paragraph !== ""); + return copy.split(/(?:)|(?:<\/p>)/g).filter((paragraph) => paragraph !== ''); } diff --git a/src/iss-components/site-footer/site-footer.vue b/src/iss-components/site-footer/site-footer.vue index b2537703..2ce2c41c 100644 --- a/src/iss-components/site-footer/site-footer.vue +++ b/src/iss-components/site-footer/site-footer.vue @@ -3,7 +3,7 @@