CSR-731 | Refactor cms-content-helper.js
Also fixed a looping issue
This commit is contained in:
parent
be9f6a008c
commit
8e2e5eb5bd
3 changed files with 147 additions and 101 deletions
|
|
@ -40,7 +40,8 @@ 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 regexExp = new RegExp("{([^{}]*?):([^{}]*?)}", "g");
|
||||
const regexMatches = [...str.matchAll(regexExp)];
|
||||
const globalStateMatches = regexMatches.filter(match => {
|
||||
return match[1] === dynamicStrings.GLOBAL_STATE;
|
||||
|
|
@ -93,11 +94,11 @@ function findAndReplaceGlobalStateValues(widgetModel, widgetName) {
|
|||
function processWidgetItemForReplacement(widgetModel, key) {
|
||||
// If we have a string, and it needs to be replaced.
|
||||
if (typeof widgetModel[key] === "string") {
|
||||
widgetModel[key] = checkForIfStatements(widgetModel[key], dynamicStrings.GLOBAL_STATE, getStoreValueFromString);
|
||||
widgetModel[key] = processIfStatements(widgetModel[key], dynamicStrings.GLOBAL_STATE, getStoreValueFromString);
|
||||
if (widgetModel[key].includes(dynamicStrings.GLOBAL_STATE)) {
|
||||
widgetModel[key] = mapStringToState(widgetModel[key]);
|
||||
}
|
||||
return reconstructPageLevelIfStatements(widgetModel[key]);
|
||||
return widgetModel[key];
|
||||
}
|
||||
|
||||
// If we have an object. array, etc
|
||||
|
|
@ -116,75 +117,6 @@ function processWidgetItemForReplacement(widgetModel, key) {
|
|||
return widgetModel[key];
|
||||
}
|
||||
|
||||
export function checkForIfStatements(str, ifConditionString, replaceStringCallback) {
|
||||
// Pattern to split off each {if:...}, {else}, {end} and their trailing strings
|
||||
const regexExp = new RegExp("(?<cleanString>^.+?)(?=(?:{if))|(?<ifOperator>{if:)(?<ifConditionType>.*?:)(?<ifCondition>.*?)}(?<ifTrailingString>.*?)(?=(?:{(?:end|else|if:.*?)}))|(?<elseOperator>{else})(?<elseTrailingString>.*?)(?=(?:{(?:end|else|if:.*?)}))|(?<endOperator>{end})(?<endTrailingString>.*?)(?=(?:{(?:end|else|if:.*?)})|$)", "g");
|
||||
const regexMatches = [...str.matchAll(regexExp)];
|
||||
// Find and evaluate full globalState if statements
|
||||
if (regexMatches.length) {
|
||||
regexMatches.forEach((match, index) => {
|
||||
if(match.groups.ifOperator) {
|
||||
if(regexMatches[index+1].groups.endOperator) {
|
||||
processIfStatement(regexMatches.slice(index, index+2), ifConditionString, replaceStringCallback) + regexMatches[index+1].groups.endTrailingString;
|
||||
}
|
||||
else if(regexMatches[index+2].groups.endOperator) {
|
||||
processIfStatement(regexMatches.slice(index, index+3), ifConditionString, replaceStringCallback)+ regexMatches[index+2].groups.endTrailingString;
|
||||
}
|
||||
}
|
||||
});
|
||||
const processedString = joinProcessedRegexArray(regexMatches);
|
||||
return checkForIfStatements(processedString, ifConditionString, replaceStringCallback);
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
function reconstructPageLevelIfStatements(str) {
|
||||
return str.replaceAll("(((", "{").replaceAll(")))","}");
|
||||
}
|
||||
|
||||
function joinProcessedRegexArray(regexMatches) {
|
||||
let processedString = "";
|
||||
regexMatches.forEach((match) => {
|
||||
processedString += match.groups.cleanString ?? match[0];
|
||||
});
|
||||
return processedString;
|
||||
}
|
||||
|
||||
function processIfStatement(ifStatementArray, ifConditionString, replaceStringCallback) {
|
||||
if(ifStatementArray[0].groups.ifConditionType.includes(ifConditionString)) {
|
||||
//replace the if condition with a real value
|
||||
const ifCondition = replaceStringCallback(ifStatementArray[0].groups.ifCondition);
|
||||
//convert the entire if statement
|
||||
let processedIfStatementString;
|
||||
if (ifCondition) {
|
||||
processedIfStatementString = ifStatementArray[0].groups.ifTrailingString;
|
||||
} else {
|
||||
processedIfStatementString = ifStatementArray[1].groups.elseTrailingString ?? "";
|
||||
}
|
||||
ifStatementArray.forEach((entry) => {
|
||||
if (entry.groups.ifOperator) {
|
||||
entry.groups.cleanString = processedIfStatementString;
|
||||
} else if (entry.groups.endOperator) {
|
||||
entry.groups.cleanString = entry.groups.endTrailingString;
|
||||
} else {
|
||||
entry.groups.cleanString = "";
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// stow the if statement to reconstruct later when passing to the page
|
||||
ifStatementArray.forEach((entry) => {
|
||||
const groups = entry.groups;
|
||||
if (groups.ifOperator)
|
||||
groups.cleanString = "(((if:" + groups.ifConditionType + groups.ifCondition + ")))" + groups.ifTrailingString;
|
||||
else if (groups.elseOperator)
|
||||
groups.cleanString = "(((else)))" + groups.elseTrailingString;
|
||||
else
|
||||
groups.cleanString = "(((end)))" + groups.endTrailingString;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getStoreValueFromString(str) {
|
||||
let storeOrStateObject = str.includes('getters') ? store :store.state;
|
||||
for (const s of str.split(".")) {
|
||||
|
|
@ -197,8 +129,121 @@ function getStoreValueFromString(str) {
|
|||
return storeOrStateObject;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// If Statement Processing Logic //
|
||||
///////////////////////////////////
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if(!containsRelevantIfStatement) {
|
||||
return str;
|
||||
} else {
|
||||
const ifStatementRegexExpression = getIfStatementRegexExpression();
|
||||
const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)];
|
||||
const completeIfStatementArray = getFirstNonNestedIfStatement(ifStatementRegexMatches, ifConditionKeyword);
|
||||
const processedIfStatementString = executeIfStatementAndGetProcessedString(completeIfStatementArray, replacePlaceholderCallback);
|
||||
replaceIfStatementWithProcessedString(completeIfStatementArray, processedIfStatementString);
|
||||
const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches);
|
||||
return processIfStatements(reconstructedPostProcessedString, ifConditionKeyword, replacePlaceholderCallback);
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstNonNestedIfStatement(matches, ifConditionKeyword) {
|
||||
let index = 0;
|
||||
for(const match of matches) {
|
||||
if (match.groups.ifOperator && match.groups.ifConditionType === ifConditionKeyword) {
|
||||
let interiorIndex = 0;
|
||||
let nestedLevel = 0;
|
||||
for (const interiorMatch of matches.slice(index+1)) {
|
||||
if (interiorMatch.groups.ifOperator) {
|
||||
if(interiorMatch.groups.ifConditionType === ifConditionKeyword) {
|
||||
break;
|
||||
} else {
|
||||
nestedLevel++;
|
||||
}
|
||||
} else if (interiorMatch.groups.endOperator) {
|
||||
if (nestedLevel) {
|
||||
nestedLevel--;
|
||||
} else {
|
||||
return matches.slice(index, index + interiorIndex+2);
|
||||
}
|
||||
}
|
||||
interiorIndex++;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
function joinProcessedRegexArray(regexMatches) {
|
||||
let processedString = "";
|
||||
regexMatches.forEach((match) => {
|
||||
processedString += match.groups.cleanString ?? match[0];
|
||||
});
|
||||
return processedString;
|
||||
}
|
||||
|
||||
function executeIfStatementAndGetProcessedString(ifStatementArray, replacePlaceholderCallback) {
|
||||
const ifCondition = replacePlaceholderCallback(ifStatementArray[0].groups.ifCondition);
|
||||
if (ifCondition) {
|
||||
return ifStatementArray[0].groups.ifTrailingString;
|
||||
} else {
|
||||
return ifStatementArray[1].groups.elseTrailingString ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
entry.groups.cleanString = "";
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getIfStatementRegexExpression() {
|
||||
// Matches but does not capture:
|
||||
// {if:...} or {else} or {end}
|
||||
const anyLogicOperatorNonCapture = "(?:{(?:end|else|if:.*?)})";
|
||||
// NOTE: ?<variableName> syntax stores the captured match like so: match.groups.variableName
|
||||
const matchStartOfString = (
|
||||
"(?<cleanString>^.+?)" + // Match and Capture all characters (lazy), cannot be empty
|
||||
"(?=(?:{if))" // Looks ahead but does not capture {if
|
||||
);
|
||||
const matchIfOperator = (
|
||||
"(?<ifOperator>{if:)" + // Match & Capture {if:
|
||||
"(?<ifConditionType>.*?):" + // Match all chars up to and including next ":" - Capture all chars up to ":"
|
||||
"(?<ifCondition>.*?)}" + // Match all chars up to and including next "}" - Capture all chars up to "}"
|
||||
"(?<ifTrailingString>.*?)" + // Match and Capture all characters (lazy), can be empty
|
||||
"(?=" + anyLogicOperatorNonCapture + ")" // Looks ahead but does not capture the next logic operator
|
||||
);
|
||||
const matchElseOperator = (
|
||||
"(?<elseOperator>{else})" + // Match & Capture {else}
|
||||
"(?<elseTrailingString>.*?)" + // Match & Capture all characters (lazy), can be empty
|
||||
"(?=" + anyLogicOperatorNonCapture + ")" // Looks ahead but does not capture the next logic operator
|
||||
);
|
||||
const matchEndOperator = (
|
||||
"(?<endOperator>{end})" + // Match & Capture {end}
|
||||
"(?<endTrailingString>.*?)" + // 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 doesCopyContainRouterLink(copy) {
|
||||
return copy.includes(this.dynamicStrings.ROUTER_LINK);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
groupName="CashOrInsuranceQuestion"
|
||||
/>
|
||||
<servicePackageQuestion
|
||||
v-if="lineItems"
|
||||
ref="servicePackage"
|
||||
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
||||
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
||||
|
|
@ -113,37 +114,37 @@ export default {
|
|||
CanSafeliteRecalibrate: true,
|
||||
price : 350.22
|
||||
},
|
||||
// {
|
||||
// "partNumber": "SBB16",
|
||||
// "description": "SAFELITE BEAM BLADE 16",
|
||||
// "partType": "PASSENGER FRONT WIPER",
|
||||
// "price": 32.64,
|
||||
// },
|
||||
// {
|
||||
// "partNumber": "SBB26",
|
||||
// "description": "SAFELITE BEAM BLADE 26",
|
||||
// "partType": "DRIVER FRONT WIPER",
|
||||
// "price": 53.04,
|
||||
// },
|
||||
// {
|
||||
// "partNumber": "SBBR12A",
|
||||
// "description": "SAFELITE REAR BLADE 12A",
|
||||
// "partType": "REAR WIPER",
|
||||
// "price": 24.48,
|
||||
// },
|
||||
{
|
||||
"partNumber": "SBB16",
|
||||
"description": "SAFELITE BEAM BLADE 16",
|
||||
"partType": "PASSENGER FRONT WIPER",
|
||||
"price": 32.64,
|
||||
},
|
||||
{
|
||||
"partNumber": "SBB26",
|
||||
"description": "SAFELITE BEAM BLADE 26",
|
||||
"partType": "DRIVER FRONT WIPER",
|
||||
"price": 53.04,
|
||||
},
|
||||
{
|
||||
"partNumber": "SBBR12A",
|
||||
"description": "SAFELITE REAR BLADE 12A",
|
||||
"partType": "REAR WIPER",
|
||||
"price": 24.48,
|
||||
},
|
||||
{
|
||||
"partNumber": "RAIN DEFENSE",
|
||||
"description": null,
|
||||
"partType": "RAIN DEFENSE",
|
||||
"price": 35.50,
|
||||
},
|
||||
// {
|
||||
// PartNumber : "005",
|
||||
// Description : "Recalibration",
|
||||
// partType : "recalibration",
|
||||
// Quantity : "1",
|
||||
// price : 150.00,
|
||||
// },
|
||||
{
|
||||
PartNumber : "005",
|
||||
Description : "Recalibration",
|
||||
partType : "recalibration",
|
||||
Quantity : "1",
|
||||
price : 150.00,
|
||||
},
|
||||
];
|
||||
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import baseInputButton from "@/common-components/base-input-button/base-input-bu
|
|||
import textLink from "@/ux-components/text-link/text-link";
|
||||
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import { splitCopyOnCMSPlaceHolder, checkForIfStatements } from "@/helpers/cms-content-helper";
|
||||
import { splitCopyOnCMSPlaceHolder, processIfStatements } from "@/helpers/cms-content-helper";
|
||||
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||
|
||||
export default {
|
||||
|
|
@ -55,11 +55,11 @@ export default {
|
|||
},
|
||||
getBodyTextFromCms(){
|
||||
const bodyText = this.getCmsContent(this.value, 'BodyText');
|
||||
return this.checkForIfStatements(bodyText, "custom", this.getCustomValueFromString);
|
||||
return this.processIfStatements(bodyText, "custom", this.getCustomValueFromString);
|
||||
},
|
||||
getFooterTextFromCms(){
|
||||
const footerText = this.getCmsContent(this.value, 'FooterText');
|
||||
return this.checkForIfStatements(footerText, "custom", this.getCustomValueFromString);
|
||||
return this.processIfStatements(footerText, "custom", this.getCustomValueFromString);
|
||||
},
|
||||
getPackagePriceString() {
|
||||
const formattedPriceFloat = parseFloat(this.getPackagePrice()).toFixed(2);
|
||||
|
|
@ -127,7 +127,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
checkForIfStatements,
|
||||
processIfStatements,
|
||||
stripUlTagFromCopy(copy) {
|
||||
const regex = /(?:<ul(?:.*?)>)|(?:<\/ul>)/g;
|
||||
return copy.replace(regex, '');
|
||||
|
|
|
|||
Loading…
Reference in a new issue