diff --git a/src/common-components/button-question/button-question.vue b/src/common-components/button-question/button-question.vue index 653aa0d24..b95fd3afb 100644 --- a/src/common-components/button-question/button-question.vue +++ b/src/common-components/button-question/button-question.vue @@ -40,6 +40,9 @@ :is="buttonType" :buttonLabel="answer.buttonLabel" :buttonLabelSubCopy="answer.buttonLabelSubCopy" + :buttonBodyCopy="answer.buttonBodyCopy" + :buttonAuxillaryCopy="answer.buttonAuxillaryCopy" + :buttonFooterCopy="answer.buttonFooterCopy" :buttonImage="answer.buttonImage" :buttonImageId="answer.buttonImageId" :groupName="answer.groupName" @@ -49,7 +52,7 @@ :isWide="isWide" :validationRules="validationRules" :textPosition="textPosition" - :additionalData="additionalData" /> + :additionalData="additionalData" :lastValuePushedToGa="lastValuePushedToGa" :setLastValuePushedToGa="setLastValuePushedToGa" v-model="selectedValues" @@ -187,6 +190,9 @@ export default { answer.altText ?? (answer.Name ? answer.Name : answer), buttonLabelSubCopy: answer.buttonLabelSubCopy ?? answer.SubText, + buttonBodyCopy: answer.buttonBodyCopy ?? answer.buttonBodyCopy, + buttonAuxillaryCopy: answer.buttonAuxillaryCopy ?? answer.buttonAuxillaryCopy, + buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy, buttonImage: answer.buttonImage ?? answer.AnswerImageUrl, buttonImageId: answer.buttonImageId ?? answer.ImageId, groupName: this.formatString(this.groupName), diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index aff7586d1..8d17c8aa6 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -40,7 +40,6 @@ export function fetchCmsContentForPage(fmgPage) { // 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 => { @@ -147,32 +146,38 @@ export function processIfStatements(str, ifConditionKeyword, replacePlaceholderC } else { const ifStatementRegexExpression = getIfStatementRegexExpression(); const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)]; - const completeIfStatementArray = getFirstNonNestedIfStatement(ifStatementRegexMatches, ifConditionKeyword); - const processedIfStatementString = executeIfStatementAndGetProcessedString(completeIfStatementArray, replacePlaceholderCallback); - replaceIfStatementWithProcessedString(completeIfStatementArray, processedIfStatementString); + const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword(ifStatementRegexMatches, ifConditionKeyword); + executeIfStatementAndSetProcessedStrings(completeIfStatementArray, replacePlaceholderCallback); const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches); return processIfStatements(reconstructedPostProcessedString, ifConditionKeyword, replacePlaceholderCallback); } } -function getFirstNonNestedIfStatement(matches, ifConditionKeyword) { +function getAndFlagFirstNonNestedIfStatementWithKeyword(matches, ifConditionKeyword) { let index = 0; for(const match of matches) { - if (match.groups.ifOperator && match.groups.ifConditionType === ifConditionKeyword) { + 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.ifOperator) { + if (interiorMatch.groups.isIfStatement) { if(interiorMatch.groups.ifConditionType === ifConditionKeyword) { break; } else { nestedLevel++; } - } else if (interiorMatch.groups.endOperator) { + } else if(interiorMatch.groups.isElseStatement) { + if (!nestedLevel) { + elseStatementIndex = interiorIndex+1; + } + } else if (interiorMatch.groups.isEndStatement) { if (nestedLevel) { nestedLevel--; } else { - return matches.slice(index, index + interiorIndex+2); + const ifStatementArray = matches.slice(index, index + interiorIndex+2); + flagMatchesForProcessing(ifStatementArray, elseStatementIndex); + return ifStatementArray; } } interiorIndex++; @@ -182,33 +187,51 @@ function getFirstNonNestedIfStatement(matches, ifConditionKeyword) { } } + + +function flagMatchesForProcessing(matches, elseStatementIndex) { + matches[0].isFlaggedForProcessing = true; + matches[matches.length-1].isFlaggedForProcessing = true; + if (elseStatementIndex) { + matches[elseStatementIndex].isFlaggedForProcessing = true; + } +} + function joinProcessedRegexArray(regexMatches) { let processedString = ""; regexMatches.forEach((match) => { - processedString += match.groups.cleanString ?? match[0]; + const rawString = match[0]; + processedString += match.groups.processedString ?? rawString; }); return processedString; } -function executeIfStatementAndGetProcessedString(ifStatementArray, replacePlaceholderCallback) { +function executeIfStatementAndSetProcessedStrings(ifStatementArray, replacePlaceholderCallback) { const ifCondition = replacePlaceholderCallback(ifStatementArray[0].groups.ifCondition); - if (ifCondition) { - return ifStatementArray[0].groups.ifTrailingString; - } else { - return ifStatementArray[1].groups.elseTrailingString ?? ""; - } + 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); + }); } -function replaceIfStatementWithProcessedString(ifStatementArray, processedIfStatementString) { - ifStatementArray.forEach((entry) => { - if (entry.groups.ifOperator) { - entry.groups.cleanString = processedIfStatementString; - } else if (entry.groups.endOperator) { - entry.groups.cleanString = entry.groups.endTrailingString; +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.cleanString = ""; + entry.groups.processedString = entry.isFlaggedForProcessing ? entry.groups.endTrailingString : entry[0]; } - }) + } } function getIfStatementRegexExpression() { @@ -217,23 +240,23 @@ function getIfStatementRegexExpression() { 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 + "(?^.+?)" + // Match and Capture all characters (lazy), cannot be empty "(?=(?:{if))" // Looks ahead but does not capture {if ); const matchIfOperator = ( - "(?{if:)" + // Match & Capture {if: + "(?{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} + "(?{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} + "(?{end})" + // Match & Capture {end} "(?.*?)" + // Match & Capture all chracters (lazy), can be empty "(?="+ anyLogicOperatorNonCapture + "|$)" // Looks ahead but does not capture the next logic operator ); @@ -249,19 +272,23 @@ export function doesCopyContainRouterLink(copy) { return copy.includes(this.dynamicStrings.ROUTER_LINK); } +export function doesCopyContainTextLink(copy) { + return copy.includes(dynamicStrings.TEXT_LINK); +} + export function splitCopyOnCMSPlaceHolder(copy){ // splits copy on { ... } such as {routerlink: ...} return copy.split(/{(.*?)}/g); } -export function getRouterLinkRouteFromCopy(copy){ +export function getLinkTargetFromCopy(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]; } -export function getRouterLinkDisplayTextFromCopy(copy){ +export function getLinkDisplayTextFromCopy(copy){ // sample input: {routerLink:estimate,provide your VIN} // first split would return 'estimate,provide your VIN' // second split would return 'provide your VIN' diff --git a/src/layouts/address-vehicles/address-vehicles.vue b/src/layouts/address-vehicles/address-vehicles.vue index a0edf876f..2249ba2ab 100644 --- a/src/layouts/address-vehicles/address-vehicles.vue +++ b/src/layouts/address-vehicles/address-vehicles.vue @@ -29,7 +29,7 @@
- {{ getRouterLinkDisplayTextFromCopy(copy) }} + {{ getLinkDisplayTextFromCopy(copy) }} @@ -67,8 +67,8 @@ import { Form, defineRule } from "vee-validate"; import { isGlassAvailableForCarId } from "@/helpers/damage-helper"; import { doesCopyContainRouterLink, splitCopyOnCMSPlaceHolder, - getRouterLinkRouteFromCopy, - getRouterLinkDisplayTextFromCopy, } from "@/helpers/cms-content-helper"; + getLinkTargetFromCopy, + getLinkDisplayTextFromCopy, } from "@/helpers/cms-content-helper"; import { routerParams } from "@/router/router-constants/router-params"; import vinPagesMixin from "@/mixins/vin-pages-mixin"; @@ -148,8 +148,8 @@ export default { methods: { doesCopyContainRouterLink, splitCopyOnCMSPlaceHolder, - getRouterLinkRouteFromCopy, - getRouterLinkDisplayTextFromCopy, + getLinkTargetFromCopy, + getLinkDisplayTextFromCopy, arePagePrerequisitesValid() { if ( store.getters.order.vehicle.carId diff --git a/src/layouts/quote/service-package-question/service-package-question.vue b/src/layouts/quote/service-package-question/service-package-question.vue index 0e527856d..6c40c73c4 100644 --- a/src/layouts/quote/service-package-question/service-package-question.vue +++ b/src/layouts/quote/service-package-question/service-package-question.vue @@ -1,26 +1,18 @@ diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js index f7d046bf7..93488e26f 100644 --- a/src/mixins/base-mixin.js +++ b/src/mixins/base-mixin.js @@ -62,11 +62,13 @@ export default { }; }, getEconomyPackagePrice(lineItems) { - const nonVapsItems = lineItems.filter((lineItem) => { - return lineItem.PartType != "frontWiper" && lineItem.PartType != "rearWiper" && lineItem.PartType != "rainDefense"; - }); let totalPrice = 0; - nonVapsItems.forEach(item => totalPrice += item.price); + lineItems.forEach((lineItem) => { + const partType = lineItem.partType.toUpperCase(); + if (!partType.includes("FRONT WIPER") && !partType.includes("REAR WIPER") && !partType.includes("RAIN DEFENSE")) { + totalPrice += lineItem.price; + } + }); return totalPrice; } }, diff --git a/src/mixins/input-button-wrapper-mixin.js b/src/mixins/input-button-wrapper-mixin.js index ddc7c4583..af2cc91af 100644 --- a/src/mixins/input-button-wrapper-mixin.js +++ b/src/mixins/input-button-wrapper-mixin.js @@ -9,6 +9,9 @@ export default { ...inputButtonProps, buttonLabel: [Number, String], buttonLabelSubCopy: String, + buttonBodyCopy: String, + buttonAuxillaryCopy: String, + buttonFooterCopy: String, buttonImage: String, altText: { type: String, @@ -17,7 +20,6 @@ export default { textPosition: String, screenReaderOnlyText: String, isWide: Boolean, - additionalData: null, }, computed: { selectedValue: { diff --git a/src/ux-components/alert/alert.vue b/src/ux-components/alert/alert.vue index 8462e4436..2b6e8cda8 100644 --- a/src/ux-components/alert/alert.vue +++ b/src/ux-components/alert/alert.vue @@ -11,7 +11,7 @@

@@ -38,8 +38,8 @@