Created state invalidation

This commit is contained in:
FrankRua 2022-02-01 14:49:21 -05:00
parent 680a2237d9
commit 5ccccc2548
13 changed files with 192 additions and 36 deletions

View file

@ -11,9 +11,12 @@ const storeActions = {
GET_EVOX_IMAGE: "getEvoxImage",
LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms",
LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin",
// EVENT BUS
ADD_EVENT_TO_BUS: "addEventToBus",
REMOVE_EVENT_FROM_BUS: "removeEventFromBus",
// DEPENDENCY MUTATIONS
RESET_VEHICLE_AND_DEPS: "resetVehicleAndDependencies",
RESET_DAMAGE_AND_DEPS: "resetDamageAndDependencies",
RESET_REGISTRATION_AND_DEPS: "resetRegistrationAndDependencies",
RESET_PARTS_AND_DEPS: "resetPartsAndDependencies",
};
export { storeActions };

View file

@ -1,9 +1,24 @@
const storeMutations = {
// VEHICLE MUTATIONS
UPDATE_YEAR: "updateYear",
UPDATE_MAKE: "updateMake",
UPDATE_MODEL: "updateModel",
UPDATE_STYLE: "updateStyle",
UPDATE_CAR_ID: "updateCarId",
UPDATE_VEHICLE_CATEGORY: "updateVehicleCategory",
UPDATE_VEHICLE: "updateVehicle",
// EVENT BUS MUTATIONS
ADD_EVENT_TO_BUS: "addEventToBus",
REMOVE_EVENT_FROM_BUS: "removeEventFromBus",
// DEPENDENCY MUTATIONS
RESET_VEHICLE_AND_DEPS: "resetVehicleAndDependencies",
RESET_DAMAGE_AND_DEPS: "resetDamageAndDependencies",
RESET_REGISTRATION_AND_DEPS: "resetRegistrationAndDependencies",
RESET_PARTS_AND_DEPS: "resetPartsAndDependencies",
};
export { storeMutations };

View file

@ -1,10 +1,10 @@
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import { storeMutations } from "@/constants/store-mutations.js";
export default {
// Adds event to the bus given its category, subcategory, and eventValue;
addEventToBus(category, subCategory, eventValue) {
store.commit(storeActions.ADD_EVENT_TO_BUS, {
store.commit(storeMutations.ADD_EVENT_TO_BUS, {
category: category,
subCategory: subCategory,
eventValue: eventValue,
@ -15,7 +15,7 @@ export default {
readAndPopEventFromBus(category, subCategory) {
const event = store.getters.eventBusItem(category, subCategory);
store.commit(storeActions.REMOVE_EVENT_FROM_BUS, {
store.commit(storeMutations.REMOVE_EVENT_FROM_BUS, {
category: category,
subCategory: subCategory,
});

View file

@ -18,9 +18,10 @@ import replaceOptionsQuestion from"@/layouts/vehicle-damage/replace-options-ques
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
import { storeActions } from "@/constants/store-actions";
export default {
name: "vehicle-damage",
@ -69,6 +70,10 @@ export default {
arePagePrerequisitesValid() {
return store.getters.vehicle.carId !== null;
},
resetDependentState() {
// Invokes
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
},
},
components: {
funnelHeader,

View file

@ -153,7 +153,7 @@ describe("vehicle-make.vue", () => {
pageHeaderWidgetHeaderText: "Select a make to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateForward: jest.fn(),
},
},
});
@ -170,7 +170,7 @@ describe("vehicle-make.vue", () => {
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled();
done();
});
});

View file

@ -25,7 +25,10 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
export default {
name: "vehicle-make",
data() {
@ -75,17 +78,31 @@ export default {
methods: {
backButtonAction() {
// route to move backwards
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateForward(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
arePagePrerequisitesValid() {
return store.getters.vehicle.year !== null;
},
resetDependentState() {
// Set
store.commit(storeMutations.UPDATE_MODEL, null);
store.commit(storeMutations.UPDATE_STYLE, null);
store.commit(storeMutations.UPDATE_CAR_ID, null);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
// Invokes
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
},
},
watch: {
selectedMake(make) {
this.$store.commit(this.storeMutations.UPDATE_MAKE, make);
this.$router.navigate(
this.$router.navigateAfterSave(
this.navigationScenarios.SELECTED_MAKE,
this.$route
);

View file

@ -141,7 +141,7 @@ describe("vehicle-model.vue", () => {
pageHeaderWidgetHeaderText: "Select a model to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateForward: jest.fn(),
},
},
});
@ -156,7 +156,7 @@ describe("vehicle-model.vue", () => {
await nextTick();
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled();
done();
});
});

View file

@ -24,6 +24,8 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
@ -77,17 +79,30 @@ export default {
methods: {
backButtonAction() {
// route to move backwards
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateForward(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
arePagePrerequisitesValid() {
return store.getters.vehicle.make !== null;
},
resetDependentState() {
// Set
store.commit(storeMutations.UPDATE_STYLE, null);
store.commit(storeMutations.UPDATE_CAR_ID, null);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
// Invokes
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
},
},
watch: {
selectedModel(model) {
this.$store.commit(this.storeMutations.UPDATE_MODEL, model);
this.$router.navigate(
this.$router.navigateAfterSave(
this.navigationScenarios.SELECTED_MODEL,
this.$route
);

View file

@ -154,7 +154,7 @@ describe("vehicle-style.vue", () => {
pageHeaderWidgetHeaderText: "Select a style to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateForward: jest.fn(),
},
},
});
@ -171,7 +171,7 @@ describe("vehicle-style.vue", () => {
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.$router.navigateForward).toHaveBeenCalled();
done();
});
});

View file

@ -25,6 +25,7 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
export default {
@ -77,7 +78,10 @@ export default {
methods: {
backButtonAction() {
// route to move backwards
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateForward(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
setVehicle() {
return this.dispatchNonBlockingStoreAction(
@ -93,13 +97,18 @@ export default {
arePagePrerequisitesValid() {
return store.getters.vehicle.model !== null;
},
resetDependentState() {
// Invokes
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
},
},
watch: {
selectedStyle(style) {
this.$store.commit(this.storeMutations.UPDATE_STYLE, style);
this.setVehicle().then(() => {
this.$router.navigate(
this.$router.navigateAfterSave(
this.navigationScenarios.SELECTED_STYLE,
this.$route
);

View file

@ -20,7 +20,9 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import eventBus from "@/helpers/event-bus/event-bus";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
export default {
name: "vehicle-year",
@ -71,8 +73,9 @@ export default {
watch: {
selectedYear(year) {
this.$store.commit(this.storeMutations.UPDATE_YEAR, year);
this.$router.navigate(
this.$router.navigateAfterSave(
this.navigationScenarios.SELECTED_YEAR,
this.$route
);
@ -82,6 +85,19 @@ export default {
arePagePrerequisitesValid() {
return true;
},
resetDependentState() {
// Set
store.commit(storeMutations.UPDATE_MAKE, null);
store.commit(storeMutations.UPDATE_MODEL, null);
store.commit(storeMutations.UPDATE_STYLE, null);
store.commit(storeMutations.UPDATE_CAR_ID, null);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
// Invokes
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
}
},
components: {
yearQuestion,

View file

@ -45,16 +45,16 @@ const routes = [
// If we already have our route, go to it.
if (router.hasRoute(to.query.fmgPage)) {
// Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function.
const arePagePrerequisitesValid = router
const component = router
.getRoutes()
.filter((x) => x.name === to.query.fmgPage)[0]
.components.default.methods.arePagePrerequisitesValid();
.filter((x) => x.name === to.query.fmgPage)[0].components;
if (!arePagePrerequisitesValid) {
if (!arePagePrerequisitesValid(component)) {
await GoToFunnelStartOn404(next);
}
return next({ name: to.query.fmgPage, query: to.query, params: to.params });
return next({ name: to.query.fmgPage, query: to.query, params: to.params });
}
// Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
@ -74,7 +74,7 @@ const routes = [
.filter((x) => x.name === routeData[0].name)[0]
.components.default();
if (!nextComponent.default.methods.arePagePrerequisitesValid()) {
if (!arePagePrerequisitesValid(nextComponent)) {
await GoToFunnelStartOn404(next);
}
@ -102,23 +102,36 @@ const router = createRouter({
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
router.navigateForward = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
navigate(scenario, currentRoute, false, optionalQuery, optionalParams);
}
router.navigateAfterSave = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
navigate(scenario, currentRoute, true, optionalQuery, optionalParams);
}
// PRIVATE FUNCTIONS
// Navigate to the next route, depending on the scenario.
router.navigate = (
scenario,
currentRoute,
optionalQuery = {},
optionalParams = {}
) => {
function navigate(scenario, currentRoute, invalidateOnSave, optionalQuery = {}, optionalParams = {}) {
if (!scenario) {
console.error("No scenario provided. Please review the routing table.");
return;
}
// Match our maps up and navigate if we have a destination.
const matchingScenarioMap = router.getNavigationMap(scenario, currentRoute);
const matchingScenarioMap = getNavigationMap(scenario, currentRoute);
if (matchingScenarioMap.destinationFmgPageValue !== undefined) {
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one.
// If we need to do invalidation
const currentComponent = currentRoute.matched[0].components;
if (invalidateOnSave) {
resetDependentState(currentComponent);
}
router.push({
name: "root",
query: Object.assign(optionalQuery, {
@ -132,7 +145,7 @@ router.navigate = (
};
// Get navigation map depending on the scenario and the current 'page' you're on.
router.getNavigationMap = (scenario, currentRoute) => {
function getNavigationMap(scenario, currentRoute) {
const fmgPageValue = currentRoute.query.fmgPage;
const matchedQueryValue = routingTable
.filter(
@ -197,4 +210,14 @@ async function GoToFunnelStartOn404(next) {
});
}
// Checks arePagePrerequisitesValid on the component passed in.
function arePagePrerequisitesValid(component) {
return component.default.methods.arePagePrerequisitesValid();
}
// Reset dependant state on route change.
function resetDependentState(component) {
return component.default.methods.resetDependentState();
}
export default router;

View file

@ -3,7 +3,7 @@ import { endpoints } from "@/constants/endpoints.js";
import { storeMutations } from "@/constants/store-mutations";
import createPersistedState from "vuex-persistedstate";
import globalMethods from "@/global-methods";
import eventBus from "../helpers/event-bus/event-bus";
export default createStore({
plugins: [createPersistedState()],
@ -35,6 +35,8 @@ export default createStore({
// See IMPORTANT note at top of "state" declaration.
mutations: {
// VEHICLE MUTATIONS
updateYear(state, year) {
state.order.vehicle.year = year;
},
@ -47,10 +49,18 @@ export default createStore({
updateStyle(state, style) {
state.order.vehicle.style = style;
},
updateCarId(state, carId) {
state.order.vehicle.carId = carId;
},
updateVehicleCategory(state, category) {
state.order.vehicle.category = category;
},
updateVehicle(state, data) {
state.order.vehicle.carId = data.carId;
state.order.vehicle.category = data.category;
},
// EVENT BUS MUTATIONS
addEventToBus(state, event) {
state.applicationUser.eventBus.push(event);
},
@ -67,6 +77,31 @@ export default createStore({
state.applicationUser.eventBus.splice(itemIndex, 1);
}
},
// DEPENDENCY MUTATIONS
resetVehicleAndDependencies(state) {
state.order.vehicle.year = null;
state.order.vehicle.make = null;
state.order.vehicle.model = null;
state.order.vehicle.style = null;
state.order.vehicle.carId = null;
state.order.vehicle.category = null;
},
resetDamageAndDependencies(state) {
state.order.vehicle.damage.isRepair = null;
state.order.vehicle.damage.numberOfChips = null;
state.order.vehicle.damage.windshieldGlassToReplace = null;
state.order.vehicle.damage.driverSideGlassToReplace = null;
state.order.vehicle.damage.passengerSideGlassToReplace = null;
state.order.vehicle.damage.rearGlassToReplace = null;
},
resetRegistrationAndDependencies(state) {
},
resetPartsAndDependencies(state) {
}
},
getters: {
vehicle: (state) => state.order.vehicle,
@ -146,6 +181,24 @@ export default createStore({
});
},
// DEPENDENCY ACTIONS
resetVehicleAndDependencies(context) {
context.commit(storeMutations.RESET_VEHICLE_AND_DEPS);
context.commit(storeMutations.RESET_DAMAGE_AND_DEPS);
context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS);
},
resetDamageAndDependencies(context) {
context.commit(storeMutations.RESET_DAMAGE_AND_DEPS);
context.commit(storeMutations.RESET_PARTS_AND_DEPS);
},
resetRegistrationAndDependencies(context) {
context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS);
context.commit(storeMutations.RESET_PARTS_AND_DEPS)
},
resetPartsAndDependencies(context) {
context.commit(storeMutations.RESET_PARTS_AND_DEPS);
},
// Content API Actions
getRouteInfo(context, { pageName }) {
return globalMethods.callHttpClient({