Adding string replace methods to alert widget

This commit is contained in:
Max 2022-04-15 16:21:57 -04:00
parent 4e7debe2fb
commit b41db74fd4
5 changed files with 174 additions and 24 deletions

View file

@ -40,12 +40,15 @@ export function fetchCmsContentForPage(fmgPage) {
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 matches = [...str.matchAll(regexExp)]; const regexMatches = [...str.matchAll(regexExp)];
const globalStateMatches = regexMatches.filter(match => {
return match[1] === "globalState";
})
// Our final string value that will be built from the matches. // Our final string value that will be built from the matches.
let stringBuilder = ""; let stringBuilder = "";
for (const match of matches) { for (const match of globalStateMatches) {
// Reset store state for each match. // Reset store state for each match.
let storeState = store.state; let storeState = store.state;

View file

@ -46,7 +46,7 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHerita
return 'vehicle-damage'; return 'vehicle-damage';
//return "vin-lookup"; (uncomment) //return "vin-lookup"; (uncomment)
} else { } else {
return 'license-plate-lookup'; return 'vehicle-damage';
//return "estimate" (uncomment) //return "estimate" (uncomment)
} }
} }

View file

@ -27,18 +27,21 @@
<alert <alert
class="my-3" class="my-3"
cmsWidgetName="NoServiceZipWidget" cmsWidgetName="NoServiceZipWidget"
v-model="customAlertData"
v-if="newServiceZipRequired" v-if="newServiceZipRequired"
alertClass="alert-danger" alertClass="alert-danger"
/> />
<alert <alert
class="my-3" class="my-3"
cmsWidgetName="NoMatchAlertWidget" cmsWidgetName="NoMatchAlertWidget"
v-model="customAlertData"
v-if="vinNotValid" v-if="vinNotValid"
alertClass="alert-danger" alertClass="alert-danger"
/> />
<alert <alert
class="my-3" class="my-3"
cmsWidgetName="MatchedDifferentVehicleAlertWidget" cmsWidgetName="MatchedDifferentVehicleAlertWidget"
v-model="customAlertData"
v-if="vinDoesNotMatchCarId" v-if="vinDoesNotMatchCarId"
alertClass="alert-warning" alertClass="alert-warning"
/> />
@ -105,7 +108,6 @@ export default {
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
console.log(resultMap.cmsContent)
}); });
}, },
props: { props: {
@ -120,6 +122,7 @@ export default {
zip: '', zip: '',
email: '', email: '',
serviceZip: '', serviceZip: '',
customAlertData: {}
}; };
}, },
methods: { methods: {
@ -139,6 +142,7 @@ export default {
async forwardButtonAction() { async forwardButtonAction() {
const zipValidation = this.serviceZip ? await this.validateZip(this.serviceZip) : await this.validateZip(this.zip); const zipValidation = this.serviceZip ? await this.validateZip(this.serviceZip) : await this.validateZip(this.zip);
if (!zipValidation.data.isServiceable) { if (!zipValidation.data.isServiceable) {
this.customAlertData.zip = this.zip;
this.$refs.funnelFooter.removeLoader(); this.$refs.funnelFooter.removeLoader();
this.newServiceZipRequired = true; this.newServiceZipRequired = true;
return; return;
@ -149,6 +153,7 @@ export default {
return; return;
}); });
if (vinLookup.data.vehicle.carId !== store.getters.vehicle.carId && !this.vinDoesNotMatchCarId) { if (vinLookup.data.vehicle.carId !== store.getters.vehicle.carId && !this.vinDoesNotMatchCarId) {
this.customAlertData.vehicleInfo = vinLookup.data.vehicle;
this.$refs.funnelFooter.updateButtonText(`Continue with ${vinLookup.data.vin} ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`); this.$refs.funnelFooter.updateButtonText(`Continue with ${vinLookup.data.vin} ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`);
this.$refs.funnelFooter.removeLoader(); this.$refs.funnelFooter.removeLoader();
this.vinDoesNotMatchCarId = true; this.vinDoesNotMatchCarId = true;
@ -156,22 +161,22 @@ export default {
} }
let vin; let vin;
let carInfo; let vehicleInfo;
if(this.vinDoesNotMatchCarId) { if(this.vinDoesNotMatchCarId) {
vin = vinLookup.data.vin; vin = vinLookup.data.vin;
carInfo = vinLookup.data.vehicle; vehicleInfo = vinLookup.data.vehicle;
} else { } else {
vin = store.getters.vehicle.vin; vin = store.getters.vehicle.vin;
carInfo = store.getters.vehicle; vehicleInfo = store.getters.vehicle;
} }
this.updateStore(vin, carInfo, zipValidation.data.state); this.updateStore(vin, vehicleInfo, zipValidation.data.state);
const partsData = await baseMixin.methods.dispatchNonBlockingStoreAction( const partsData = await baseMixin.methods.dispatchNonBlockingStoreAction(
this.storeActions.GET_PARTS_OR_QUESTIONS, this.storeActions.GET_PARTS_OR_QUESTIONS,
{ {
carId: carInfo.carId, carId: vehicleInfo.carId,
glassArray: store.getters.damage.glassToReplace, glassArray: store.getters.damage.glassToReplace,
zipCode: this.serviceZip ? this.serviceZip : this.zip, zipCode: this.serviceZip ? this.serviceZip : this.zip,
vin: vin vin: vin
@ -204,20 +209,20 @@ export default {
{ licensePlate: plate, licenseState: state } { licensePlate: plate, licenseState: state }
); );
}, },
updateStore(vin, carInfo, registrationState) { updateStore(vin, vehicleInfo, registrationState) {
// if(vehicleDamage){ // if(vehicleDamage){
// store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); // store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
// } // }
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin); store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
store.commit(storeMutations.UPDATE_YEAR, carInfo.year); store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
store.commit(storeMutations.UPDATE_MAKE, carInfo.make); store.commit(storeMutations.UPDATE_MAKE, vehicleInfo.make);
store.commit(storeMutations.UPDATE_MODEL, carInfo.model); store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
store.commit(storeMutations.UPDATE_STYLE, carInfo.style); store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
store.commit(storeMutations.UPDATE_CAR_ID, carInfo.carId); store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, carInfo.category); store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicleInfo.category);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, carInfo.imageUrl); store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicleInfo.imageUrl);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, carInfo.imageVifNumber); store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicleInfo.imageVifNumber);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, carInfo.imageColor); store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageColor);
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, this.licensePlate); store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, this.licensePlate);
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState); store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.zip); store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.zip);

View file

@ -1,4 +1,5 @@
import { shallowMount } from "@vue/test-utils"; import { shallowMount } from "@vue/test-utils";
import { createStore } from 'vuex'
import alert from "./alert"; import alert from "./alert";
describe("alert.vue", () => { describe("alert.vue", () => {
@ -9,6 +10,13 @@ describe("alert.vue", () => {
propsData: { propsData: {
isDismissible: true isDismissible: true
}, },
computed: {
alertCopy: {
get() {
return "TEST";
},
}
},
mixins: [mockMixin] mixins: [mockMixin]
}); });
@ -24,6 +32,13 @@ describe("alert.vue", () => {
propsData: { propsData: {
alertClass: 'warning' alertClass: 'warning'
}, },
computed: {
alertCopy: {
get() {
return "TEST";
},
}
},
mixins: [mockMixin] mixins: [mockMixin]
}); });
@ -33,6 +48,84 @@ describe("alert.vue", () => {
expect(wrapperDiv.classes()).toContain('warning') expect(wrapperDiv.classes()).toContain('warning')
}); });
it("Should return original string if no custom string notations added", async () => {
// Arrange
const wrapper = shallowMount(alert, {
computed: {
alertCopy: {
get() {
return "TEST";
},
}
},
mixins: [mockMixin]
});
const stringWithNoCustomAtrributes = wrapper.vm.checkForCustomStrings("Test string")
// Assert
expect(stringWithNoCustomAtrributes).toEqual("Test string")
});
it("Should return link when custom string notation with 'routerLink' included", async () => {
// Arrange
const wrapper = shallowMount(alert, {
computed: {
alertCopy: {
get() {
return "TEST";
},
}
},
mixins: [mockMixin]
});
const stringWithNoCustomAtrributes = wrapper.vm.checkForCustomStrings("{routerLink:clickedChangeVinLookupMethod,provide your VIN}")
// Assert
expect(stringWithNoCustomAtrributes).toEqual("{routerLink:clickedChangeVinLookupMethod,provide your VIN}")
});
it("Should return zip when custom string notation with 'custom' for zip is called.", async () => {
// Arrange
const wrapper = shallowMount(alert, {
propsData: {modelValue: {zip: "12345"}},
computed: {
alertCopy: {
get() {
return "TEST";
},
}
},
mixins: [mockMixin]
});
const stringWithNoCustomAtrributes = wrapper.vm.checkForCustomStrings("{custom:zip}")
// Assert
expect(stringWithNoCustomAtrributes).toEqual("12345")
});
it("Should return custom datum specified when custom string notation with 'custom' for lookup is called.", async () => {
// Arrange
const wrapper = shallowMount(alert, {
propsData: {modelValue: {vehicleInfo: {year: "2020"}}},
computed: {
alertCopy: {
get() {
return "TEST";
},
}
},
mixins: [mockMixin]
});
const stringWithNoCustomAtrributes = wrapper.vm.checkForCustomStrings("{custom:plateLookupYear}")
// Assert
expect(stringWithNoCustomAtrributes).toEqual("2020")
});
}); });
const mockMixin = { const mockMixin = {

View file

@ -4,8 +4,16 @@
role="alert" role="alert"
:class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]" :class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]"
> >
<p class="m-0 fw-bold small alert-heading">{{ alertHeadline }}</p> <p class="m-0 fw-bold small alert-heading" v-html="alertHeadline"></p>
<p class="m-0 text-body small">{{ alertCopy }}</p> <p v-if="alertCopy.includes('routerLink:')">
<template v-for="copy in alertCopy.split(/{(.*?)}/g)" :key="copy">
<span v-if="copy.includes('routerLink:')" class="m-0 text-body small">
<router-link :to="{query: {fmgPage: `${copy.split(':')[1].split(',')[0]}`}, name: 'root'}">{{ copy.split(':')[1].split(',')[1] }}</router-link>
</span>
<span v-else class="m-0 text-body small">{{ copy }}</span>
</template>
</p>
<p v-else class="m-0 text-body small">{{ alertCopy }}</p>
<button <button
type="button" type="button"
class="btn-close p-2" class="btn-close p-2"
@ -26,6 +34,8 @@
</template> </template>
<script> <script>
import store from "@/store";
export default { export default {
name: "alert", name: "alert",
props: { props: {
@ -41,15 +51,54 @@ export default {
cmsWidgetName: String, cmsWidgetName: String,
manualHeadline: String, manualHeadline: String,
manualCopy: String, manualCopy: String,
modelValue: {}
}, },
computed: { computed: {
alertHeadline(){ alertHeadline(){
return this.cmsWidgetName ? this.getCmsContent(this.cmsWidgetName, 'HeadlineText') : this.manualHeadline; return this.cmsWidgetName ? this.checkForCustomStrings(this.getCmsContent(this.cmsWidgetName, 'HeadlineText')) : this.manualHeadline;
}, },
alertCopy(){ alertCopy(){
return this.cmsWidgetName ? this.getCmsContent(this.cmsWidgetName, 'BodyText') : this.manualCopy; return this.cmsWidgetName ? this.checkForCustomStrings(this.getCmsContent(this.cmsWidgetName, 'BodyText')) : this.manualCopy;
}, },
}, },
methods: {
checkForCustomStrings(str){
let returnElement = "";
if(str.includes("{custom:")){
const regexExp = new RegExp("{(.*?)}", "g");
const splitOnSpecialData = str.split(regexExp);
for(const item of splitOnSpecialData){
let itemToAdd;
if(item.includes("custom:")){
const splitItem = item.split(":");
const customDataAttribute = splitItem[1].includes("plateLookup") ? splitItem[1].split("plateLookup")[1].toLowerCase() : splitItem[1];
switch(customDataAttribute){
case "damage":
itemToAdd = store.getters.damage.glassToReplace.length > 1 ? "match" : store.getters.damage.glassToReplace[0].location;
break;
case "zip":
itemToAdd = this.modelValue.zip;
break;
default:
itemToAdd = this.modelValue.vehicleInfo[customDataAttribute];
}
} else if(item.includes("routerLink:")){
itemToAdd = `{${item}}`;
}
else {
itemToAdd = item;
}
returnElement += itemToAdd;
}
} else {
returnElement = str;
}
return returnElement;
}
},
}; };
</script> </script>