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 to convert a string, into a matching global state item.
|
||||||
function mapStringToState(str) {
|
function mapStringToState(str) {
|
||||||
// Pull all matches out of the string.
|
// 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 regexMatches = [...str.matchAll(regexExp)];
|
||||||
const globalStateMatches = regexMatches.filter(match => {
|
const globalStateMatches = regexMatches.filter(match => {
|
||||||
return match[1] === dynamicStrings.GLOBAL_STATE;
|
return match[1] === dynamicStrings.GLOBAL_STATE;
|
||||||
|
|
@ -93,11 +94,11 @@ function findAndReplaceGlobalStateValues(widgetModel, widgetName) {
|
||||||
function processWidgetItemForReplacement(widgetModel, key) {
|
function processWidgetItemForReplacement(widgetModel, key) {
|
||||||
// If we have a string, and it needs to be replaced.
|
// If we have a string, and it needs to be replaced.
|
||||||
if (typeof widgetModel[key] === "string") {
|
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)) {
|
if (widgetModel[key].includes(dynamicStrings.GLOBAL_STATE)) {
|
||||||
widgetModel[key] = mapStringToState(widgetModel[key]);
|
widgetModel[key] = mapStringToState(widgetModel[key]);
|
||||||
}
|
}
|
||||||
return reconstructPageLevelIfStatements(widgetModel[key]);
|
return widgetModel[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have an object. array, etc
|
// If we have an object. array, etc
|
||||||
|
|
@ -116,75 +117,6 @@ function processWidgetItemForReplacement(widgetModel, key) {
|
||||||
return 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) {
|
function getStoreValueFromString(str) {
|
||||||
let storeOrStateObject = str.includes('getters') ? store :store.state;
|
let storeOrStateObject = str.includes('getters') ? store :store.state;
|
||||||
for (const s of str.split(".")) {
|
for (const s of str.split(".")) {
|
||||||
|
|
@ -197,8 +129,121 @@ function getStoreValueFromString(str) {
|
||||||
return storeOrStateObject;
|
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) {
|
export function doesCopyContainRouterLink(copy) {
|
||||||
return copy.includes(this.dynamicStrings.ROUTER_LINK);
|
return copy.includes(this.dynamicStrings.ROUTER_LINK);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
groupName="CashOrInsuranceQuestion"
|
groupName="CashOrInsuranceQuestion"
|
||||||
/>
|
/>
|
||||||
<servicePackageQuestion
|
<servicePackageQuestion
|
||||||
|
v-if="lineItems"
|
||||||
ref="servicePackage"
|
ref="servicePackage"
|
||||||
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
||||||
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
||||||
|
|
@ -113,37 +114,37 @@ export default {
|
||||||
CanSafeliteRecalibrate: true,
|
CanSafeliteRecalibrate: true,
|
||||||
price : 350.22
|
price : 350.22
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// "partNumber": "SBB16",
|
"partNumber": "SBB16",
|
||||||
// "description": "SAFELITE BEAM BLADE 16",
|
"description": "SAFELITE BEAM BLADE 16",
|
||||||
// "partType": "PASSENGER FRONT WIPER",
|
"partType": "PASSENGER FRONT WIPER",
|
||||||
// "price": 32.64,
|
"price": 32.64,
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// "partNumber": "SBB26",
|
"partNumber": "SBB26",
|
||||||
// "description": "SAFELITE BEAM BLADE 26",
|
"description": "SAFELITE BEAM BLADE 26",
|
||||||
// "partType": "DRIVER FRONT WIPER",
|
"partType": "DRIVER FRONT WIPER",
|
||||||
// "price": 53.04,
|
"price": 53.04,
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// "partNumber": "SBBR12A",
|
"partNumber": "SBBR12A",
|
||||||
// "description": "SAFELITE REAR BLADE 12A",
|
"description": "SAFELITE REAR BLADE 12A",
|
||||||
// "partType": "REAR WIPER",
|
"partType": "REAR WIPER",
|
||||||
// "price": 24.48,
|
"price": 24.48,
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
"partNumber": "RAIN DEFENSE",
|
"partNumber": "RAIN DEFENSE",
|
||||||
"description": null,
|
"description": null,
|
||||||
"partType": "RAIN DEFENSE",
|
"partType": "RAIN DEFENSE",
|
||||||
"price": 35.50,
|
"price": 35.50,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// PartNumber : "005",
|
PartNumber : "005",
|
||||||
// Description : "Recalibration",
|
Description : "Recalibration",
|
||||||
// partType : "recalibration",
|
partType : "recalibration",
|
||||||
// Quantity : "1",
|
Quantity : "1",
|
||||||
// price : 150.00,
|
price : 150.00,
|
||||||
// },
|
},
|
||||||
];
|
];
|
||||||
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue();
|
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 textLink from "@/ux-components/text-link/text-link";
|
||||||
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
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";
|
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -55,11 +55,11 @@ export default {
|
||||||
},
|
},
|
||||||
getBodyTextFromCms(){
|
getBodyTextFromCms(){
|
||||||
const bodyText = this.getCmsContent(this.value, 'BodyText');
|
const bodyText = this.getCmsContent(this.value, 'BodyText');
|
||||||
return this.checkForIfStatements(bodyText, "custom", this.getCustomValueFromString);
|
return this.processIfStatements(bodyText, "custom", this.getCustomValueFromString);
|
||||||
},
|
},
|
||||||
getFooterTextFromCms(){
|
getFooterTextFromCms(){
|
||||||
const footerText = this.getCmsContent(this.value, 'FooterText');
|
const footerText = this.getCmsContent(this.value, 'FooterText');
|
||||||
return this.checkForIfStatements(footerText, "custom", this.getCustomValueFromString);
|
return this.processIfStatements(footerText, "custom", this.getCustomValueFromString);
|
||||||
},
|
},
|
||||||
getPackagePriceString() {
|
getPackagePriceString() {
|
||||||
const formattedPriceFloat = parseFloat(this.getPackagePrice()).toFixed(2);
|
const formattedPriceFloat = parseFloat(this.getPackagePrice()).toFixed(2);
|
||||||
|
|
@ -127,7 +127,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
splitCopyOnCMSPlaceHolder,
|
splitCopyOnCMSPlaceHolder,
|
||||||
checkForIfStatements,
|
processIfStatements,
|
||||||
stripUlTagFromCopy(copy) {
|
stripUlTagFromCopy(copy) {
|
||||||
const regex = /(?:<ul(?:.*?)>)|(?:<\/ul>)/g;
|
const regex = /(?:<ul(?:.*?)>)|(?:<\/ul>)/g;
|
||||||
return copy.replace(regex, '');
|
return copy.replace(regex, '');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue