Merge pull request #3 from Safelite/feature/Digital/SSR-11
Initial set up.
This commit is contained in:
commit
ad5ff8e0a4
26 changed files with 578 additions and 13474 deletions
|
|
@ -1,3 +1,23 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
preset: '@vue/cli-plugin-unit-jest/presets/no-babel'
|
verbose: true,
|
||||||
}
|
coverageReporters: ["html", "text", "jest-junit", "cobertura"],
|
||||||
|
testResultsProcessor: "jest-junit",
|
||||||
|
preset: "@vue/cli-plugin-unit-jest",
|
||||||
|
transform: { "^.+\\.vue$": "vue-jest" },
|
||||||
|
moduleFileExtensions: ["js", "vue"],
|
||||||
|
modulePathIgnorePatterns: ["vin-lookup"],
|
||||||
|
collectCoverageFrom: [
|
||||||
|
"src/**/*.{js,vue}",
|
||||||
|
"!src/main.js",
|
||||||
|
"!src/constants/*.js",
|
||||||
|
"!src/router/**/*.js",
|
||||||
|
"!src/helpers/unit-test-helper.js"
|
||||||
|
// END
|
||||||
|
], // ! means exclude from coverage.
|
||||||
|
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||||
|
coverageThreshold: {
|
||||||
|
// global: {
|
||||||
|
// statements: 80,
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
||||||
13391
package-lock.json
generated
13391
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
|
@ -5,17 +5,21 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"test:unit": "vue-cli-service test:unit"
|
"test:unit": "vue-cli-service test:unit --coverage --ci",
|
||||||
|
"test:unit:lite": "vue-cli-service test:unit --ci"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.10.2",
|
||||||
|
"axios": "^0.27.2",
|
||||||
|
"bootstrap": "^5.1.1",
|
||||||
|
"pinia": "^2.0.22",
|
||||||
|
"pinia-plugin-persistedstate": "^2.2.0",
|
||||||
"vue": "^3.2.13",
|
"vue": "^3.2.13",
|
||||||
"vue-router": "^4.0.3",
|
"vue-router": "^4.0.3"
|
||||||
"vuex": "^4.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-router": "~5.0.0",
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
"@vue/cli-plugin-unit-jest": "~5.0.0",
|
"@vue/cli-plugin-unit-jest": "~5.0.0",
|
||||||
"@vue/cli-plugin-vuex": "~5.0.0",
|
|
||||||
"@vue/cli-service": "~5.0.0",
|
"@vue/cli-service": "~5.0.0",
|
||||||
"@vue/test-utils": "^2.0.0-0",
|
"@vue/test-utils": "^2.0.0-0",
|
||||||
"@vue/vue3-jest": "^27.0.0-alpha.1",
|
"@vue/vue3-jest": "^27.0.0-alpha.1",
|
||||||
|
|
|
||||||
33
src/App.vue
33
src/App.vue
|
|
@ -1,30 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<nav>
|
<router-view v-slot="{ Component }">
|
||||||
<router-link to="/">Home</router-link> |
|
<transition :duration="{ enter: 200, leave: 200 }" name="route-fade" mode="out-in">
|
||||||
<router-link to="/about">About</router-link>
|
<!-- The above durations should be kept in sync with the global css class "fade-on-route-transition" -->
|
||||||
</nav>
|
<component :is="Component" />
|
||||||
<router-view/>
|
</transition>
|
||||||
|
</router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
#app {
|
@import "./node_modules/bootstrap/scss/bootstrap";
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
@import "@/styles/common-animations.scss";
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #2c3e50;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav {
|
|
||||||
padding: 30px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #2c3e50;
|
|
||||||
|
|
||||||
&.router-link-exact-active {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br>
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest" target="_blank" rel="noopener">unit-jest</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
||||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
||||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
||||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
||||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
||||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
||||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'HelloWorld',
|
|
||||||
props: {
|
|
||||||
msg: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped lang="scss">
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
7
src/constants/application-config.js
Normal file
7
src/constants/application-config.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
const applicationConfig = {
|
||||||
|
CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod"
|
||||||
|
APPLICATION_NAME: "SelfService",
|
||||||
|
SITE_ENTRY_TRIGGER_VALUE: "SelfService"
|
||||||
|
};
|
||||||
|
|
||||||
|
export { applicationConfig };
|
||||||
7
src/constants/dynamic-strings.js
Normal file
7
src/constants/dynamic-strings.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
const dynamicStrings = {
|
||||||
|
GLOBAL_STATE: "globalState",
|
||||||
|
CUSTOM: "custom",
|
||||||
|
ROUTER_LINK: "routerLink:"
|
||||||
|
};
|
||||||
|
|
||||||
|
export { dynamicStrings };
|
||||||
77
src/constants/endpoints.js
Normal file
77
src/constants/endpoints.js
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
const endpoints = {
|
||||||
|
GetRouteInfo: {
|
||||||
|
url: "/content/api/v1/content/RouteInfo",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
GetHomepageInfo: {
|
||||||
|
url: "/content/api/v1/content/HomepageInfo",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetVehicleYears: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/years",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetVehicleMakes: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/Makes",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetVehicleModels: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/Models",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetVehicleStyles: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/Styles",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetVehicle: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/lookup",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetDamageOptions: {
|
||||||
|
url: "/parts/api/v1/parts/damage-options",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
GetPageData: {
|
||||||
|
url: "/content/api/v1/content",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
LookupVehicleByYmms: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/Lookup",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
LookupVehicleByVin: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/Lookup",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
LookupVinByPlate: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/lookup-vin-by-plate",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
LookupVinByAddress: {
|
||||||
|
url: "/vehicle/api/v1/vehicle/lookup-vin-by-address",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
GetPartsOrQuestions: {
|
||||||
|
url: "/parts/api/v1/parts/parts-or-questions",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
GetParts: {
|
||||||
|
url: "/parts/api/v1/parts/parts",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
GetCapabilityQuestions: {
|
||||||
|
url: "/parts/api/v1/parts/capability-questions",
|
||||||
|
method: "GET"
|
||||||
|
},
|
||||||
|
GetPartFromCapabilityAnswer: {
|
||||||
|
url: "/parts/api/v1/parts/part-from-capability-answer",
|
||||||
|
method: "POST"
|
||||||
|
},
|
||||||
|
ValidateZip: {
|
||||||
|
url: "/location/api/v1/location/zip",
|
||||||
|
method: "GET",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { endpoints };
|
||||||
|
|
||||||
29
src/constants/error-message.js
Normal file
29
src/constants/error-message.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const errorMessages = {
|
||||||
|
DAMAGE_LOCATION_REQUIRED: "Please select damage location",
|
||||||
|
DAMAGE_SIDE_REQUIRED: "Please select vehicle side",
|
||||||
|
DRIVER_SIDE_OPTIONS_REQUIRED: "Please select window",
|
||||||
|
PASSENGER_SIDE_OPTIONS_REQUIRED: "Please select window",
|
||||||
|
WINDSHIELD_DAMAGE_TYPE_REQUIRED: "Please select windshield damage",
|
||||||
|
WINDSHIELD_CHIP_COUNT_REQUIRED: "Please select chip(s)",
|
||||||
|
WINSHIELD_REPLACE_OPTIONS_REQUIRED: "Please select windshield part",
|
||||||
|
REPLACE_OPTIONS_REQUIRED: "Please select rear window type",
|
||||||
|
STREET_ADDRESS_REQUIRED: "Please enter your street address",
|
||||||
|
CITY_REQUIRED: "Please enter your city",
|
||||||
|
STATE_REQUIRED: "Please enter your state",
|
||||||
|
ZIP_REQUIRED: "Please enter your ZIP",
|
||||||
|
ZIP_FORMAT: "Please enter a valid ZIP",
|
||||||
|
LICENSE_PLATE_REQUIRED: "Please enter your license plate number",
|
||||||
|
REGISTRATION_ZIP_REQUIRED: "Please enter your registration ZIP code",
|
||||||
|
FIRST_NAME_REQUIRED: "Please enter your first name",
|
||||||
|
LAST_NAME_REQUIRED: "Please enter your last name",
|
||||||
|
EMAIL_ADDRESS_REQUIRED: "Please enter your email address",
|
||||||
|
EMAIL_ADDRESS_FORMAT: "Please enter a valid email address",
|
||||||
|
SERVICE_ZIP_REQUIRED: "Please enter your service ZIP",
|
||||||
|
SERVICE_ZIP_FORMAT: "Please enter a valid service ZIP",
|
||||||
|
VIN_REQUIRED: "Please enter your VIN",
|
||||||
|
VIN_FORMAT: "Invalid VIN. Please make sure that you entered the correct 17-digit, alpha-numeric number. VINs do not contain the letters I, O, or Q",
|
||||||
|
OPTION_REQUIRED: "Please select an option",
|
||||||
|
VEHICLE_REQUIRED: "Please select a vehicle",
|
||||||
|
};
|
||||||
|
|
||||||
|
export { errorMessages };
|
||||||
5
src/constants/query-strings.js
Normal file
5
src/constants/query-strings.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
const queryStrings = {
|
||||||
|
ISS_PAGE: 'issPage'
|
||||||
|
};
|
||||||
|
|
||||||
|
export { queryStrings };
|
||||||
51
src/constants/store-actions.js
Normal file
51
src/constants/store-actions.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
const storeActions = {
|
||||||
|
// Content Actions
|
||||||
|
GET_ROUTE_INFO_ACTION: "getRouteInfo",
|
||||||
|
GET_HOMEPAGE_NAME: "getHomepageName",
|
||||||
|
GET_PAGE_DATA: "getPageData",
|
||||||
|
|
||||||
|
// Vehicle Actions
|
||||||
|
GET_VEHICLE_YEARS: "getVehicleYears",
|
||||||
|
GET_VEHICLE_MAKES: "getVehicleMakes",
|
||||||
|
GET_VEHICLE_MODELS: "getVehicleModels",
|
||||||
|
GET_VEHICLE_STYLES: "getVehicleStyles",
|
||||||
|
SET_VEHICLE: "setVehicle",
|
||||||
|
GET_DAMAGE_OPTIONS: "getDamageOptions",
|
||||||
|
GET_EVOX_IMAGE: "getEvoxImage",
|
||||||
|
|
||||||
|
// Lookup Actions
|
||||||
|
LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms",
|
||||||
|
LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin",
|
||||||
|
LOOKUP_VIN_BY_PLATE: "lookupVinByPlate",
|
||||||
|
LOOKUP_VIN_BY_ADDRESS: "lookupVinByAddress",
|
||||||
|
|
||||||
|
GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions",
|
||||||
|
GET_PARTS: "getParts",
|
||||||
|
GET_CAPABILITY_QUESTIONS: "getCapabilityQuestions",
|
||||||
|
GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: "getPartFromCapabilityQuestionAnswer",
|
||||||
|
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
|
||||||
|
VALIDATE_ZIP: "validateZip",
|
||||||
|
CLEAR_VIN: "clearVin",
|
||||||
|
|
||||||
|
// VEHICLE MUTATIONS
|
||||||
|
UPDATE_YEAR: "updateYear",
|
||||||
|
UPDATE_MAKE: "updateMake",
|
||||||
|
UPDATE_MODEL: "updateModel",
|
||||||
|
UPDATE_STYLE: "updateStyle",
|
||||||
|
UPDATE_CAR_ID: "updateCarId",
|
||||||
|
UPDATE_VEHICLE_CATEGORY: "updateVehicleCategory",
|
||||||
|
UPDATE_VEHICLE_IMAGE_URL: "updateVehicleImageUrl",
|
||||||
|
UPDATE_VEHICLE_IMAGE_VIF_NUMBER: "updateVehicleImageVifNumber",
|
||||||
|
UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor",
|
||||||
|
UPDATE_VEHICLE_VIN: "updateVehicleVin",
|
||||||
|
UPDATE_VEHICLE: "updateVehicle",
|
||||||
|
|
||||||
|
|
||||||
|
// DEPENDENCY MUTATIONS
|
||||||
|
|
||||||
|
// SAVE COMPONENT STATE
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export { storeActions };
|
||||||
|
|
||||||
11
src/constants/vehicle-categories.js
Normal file
11
src/constants/vehicle-categories.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
const vehicleCategories = {
|
||||||
|
CAR: "CAR",
|
||||||
|
TRUCK: "TRUCK",
|
||||||
|
VAN: "VAN",
|
||||||
|
COMMERCIALVAN: "COMMERCIAL VAN",
|
||||||
|
SUV: "SUV",
|
||||||
|
MOTORHOME: "MOTOR HOME",
|
||||||
|
SEMI: "SEMI",
|
||||||
|
};
|
||||||
|
|
||||||
|
export { vehicleCategories };
|
||||||
21
src/global-methods.js
Normal file
21
src/global-methods.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import { applicationConfig } from "@/constants/application-config.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
callHttpClient({ method, endpoint, payload}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const cfDistroUrl = applicationConfig.CONSUMER_CF_DISTRO;
|
||||||
|
const payloadAndAnalyticsData = Object.assign({}, payload, { AppName: "SelfService" });
|
||||||
|
|
||||||
|
axios({ method: method, url: cfDistroUrl + endpoint, data: payloadAndAnalyticsData, crossDomain: true, responseType: {}})
|
||||||
|
.then((response) => {
|
||||||
|
return resolve(response);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.error(error);
|
||||||
|
return reject(error.response);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
16
src/main.js
16
src/main.js
|
|
@ -1,6 +1,12 @@
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue';
|
||||||
import App from './App.vue'
|
import App from './App.vue';
|
||||||
import router from './router'
|
import router from './router';
|
||||||
import store from './store'
|
import "../node_modules/bootstrap/dist/js/bootstrap.js";
|
||||||
|
|
||||||
|
const vueApp = createApp(App);
|
||||||
|
|
||||||
|
vueApp.use(router);
|
||||||
|
vueApp.mount("#app");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
createApp(App).use(store).use(router).mount('#app')
|
|
||||||
|
|
|
||||||
50
src/mixins/base-mixin.js
Normal file
50
src/mixins/base-mixin.js
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { storeActions } from "@/constants/store-actions.js";
|
||||||
|
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||||
|
import { vehicleCategories } from "@/constants/vehicle-categories.js";
|
||||||
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
|
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cmsContentByWidget: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setCmsContent(cmsContent) {
|
||||||
|
this.$root.cmsContentByWidget = cmsContent;
|
||||||
|
},
|
||||||
|
getCmsContent(widgetName, fieldName) {
|
||||||
|
return this.$root.cmsContentByWidget?.[widgetName]?.[fieldName] ? this.$root.cmsContentByWidget[widgetName][fieldName] : '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
storeActions() {
|
||||||
|
return storeActions;
|
||||||
|
},
|
||||||
|
navigationScenarios() {
|
||||||
|
return navigationScenarios;
|
||||||
|
},
|
||||||
|
vehicleCategories() {
|
||||||
|
return vehicleCategories;
|
||||||
|
},
|
||||||
|
queryStrings(){
|
||||||
|
return queryStrings;
|
||||||
|
},
|
||||||
|
dynamicStrings(){
|
||||||
|
return dynamicStrings;
|
||||||
|
},
|
||||||
|
cssClassNameForCmsWidget(){
|
||||||
|
return "widget-name-" + this.cmsWidgetName;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function encodeUriData(payload) {
|
||||||
|
if (payload && Object.keys(payload).length > 0) {
|
||||||
|
// Loop through the payload and encode the values
|
||||||
|
Object.keys(payload).forEach((key) => {
|
||||||
|
payload[key] = encodeURIComponent(payload[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/router/dynamic-routing/component-loader.js
Normal file
3
src/router/dynamic-routing/component-loader.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function lazyLoadComponent(componentName) {
|
||||||
|
return () => import(`@/layouts/${componentName}/${componentName}.vue`); // /src/layouts/folder/component.vue
|
||||||
|
}
|
||||||
|
|
@ -1,27 +1,103 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import HomeView from '../views/HomeView.vue'
|
import { createWebHistory, createRouter } from "vue-router";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'home',
|
name: 'root',
|
||||||
component: HomeView
|
async beforeEnter(to, from, next) {
|
||||||
},
|
try {
|
||||||
{
|
if (router.hasRoute(to.query.issPage)) {
|
||||||
path: '/about',
|
return next({ name: to.query.issPage, query: to.query, params: to.params });
|
||||||
name: 'about',
|
}
|
||||||
// route level code-splitting
|
const routeData = await GetRouteInfoFromPageName(to.query.issPage);
|
||||||
// this generates a separate chunk (about.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
// Add our dynamic route.
|
||||||
component: function () {
|
router.addRoute({
|
||||||
return import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
|
path: routeData[0].path, // Always the same path, because we control it with query strings.
|
||||||
}
|
name: routeData[0].name,
|
||||||
}
|
component: routeData[0].component,
|
||||||
]
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Assign current query string parameters, as well as our fmgPage one.
|
||||||
|
next({
|
||||||
|
name: routeData[0].name,
|
||||||
|
query: Object.assign(to.query, { issPage: routeData[0].name }),
|
||||||
|
params: to.params
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
await GoToStartOn404(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory("/"),
|
history: createWebHistory("/"),
|
||||||
routes
|
routes,
|
||||||
})
|
});
|
||||||
|
|
||||||
export default router
|
// Get route information by page name.
|
||||||
|
// This will reach out to the Cms and there is a 1:1 relationship between page names and route names.
|
||||||
|
async function GetRouteInfoFromPageName(pageName) {
|
||||||
|
const response = await store.dispatch(storeActions.GET_ROUTE_INFO_ACTION, {
|
||||||
|
pageName: pageName,
|
||||||
|
});
|
||||||
|
const jsonFromResponse = JSON.parse(response.data.Result);
|
||||||
|
let routeData = [];
|
||||||
|
|
||||||
|
// Add our route data and return our array.
|
||||||
|
Object.keys(jsonFromResponse).forEach((key) => {
|
||||||
|
routeData.push({
|
||||||
|
path: "/",
|
||||||
|
name: `${key}`,
|
||||||
|
component: lazyLoadComponent(jsonFromResponse[key].LayoutName),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return routeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigate to the next route, depending on the scenario.
|
||||||
|
async function navigate(scenario, currentRoute, 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 = getNavigationMap(scenario, currentRoute);
|
||||||
|
const destinationIssPageValue = matchingScenarioMap.destinationIssPageValue;
|
||||||
|
|
||||||
|
if (destinationIssPageValue !== undefined) {
|
||||||
|
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our issPage one.
|
||||||
|
router.push({
|
||||||
|
name: "root",
|
||||||
|
query: Object.assign(optionalQuery, {
|
||||||
|
fmgPage: destinationIssPageValue,
|
||||||
|
}),
|
||||||
|
params: optionalParams
|
||||||
|
});
|
||||||
|
} else if (matchingScenarioMap.destinationUrl !== undefined) {
|
||||||
|
navigateToUrl(matchingScenarioMap.destinationUrl, optionalQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get navigation map depending on the scenario and the current 'page' you're on.
|
||||||
|
function getNavigationMap(scenario, currentRoute) {
|
||||||
|
const issPageValue = currentRoute.query.issPage;
|
||||||
|
const matchedQueryValue = routingTable(store)
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
item.issPageValue === issPageValue &&
|
||||||
|
item.maps.filter((map) => map.scenario === scenario).length > 0
|
||||||
|
)
|
||||||
|
.map((m) => m.maps.filter((map) => map.scenario === scenario))[0]
|
||||||
|
.filter(x => x.filter === true || x.filter === undefined);
|
||||||
|
|
||||||
|
return matchedQueryValue[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default router;
|
||||||
5
src/router/router-constants/issPage-values.js
Normal file
5
src/router/router-constants/issPage-values.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
const issPageValues = {
|
||||||
|
VEHICLE_YEAR: "vehicle-year",
|
||||||
|
};
|
||||||
|
|
||||||
|
export { issPageValues };
|
||||||
10
src/router/router-constants/navigation-scenarios.js
Normal file
10
src/router/router-constants/navigation-scenarios.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
const navigationScenarios = {
|
||||||
|
// General
|
||||||
|
CLICKED_BACK: "CLICKED_BACK",
|
||||||
|
CLICKED_FORWARD: "CLICKED_FORWARD",
|
||||||
|
|
||||||
|
// YMMS
|
||||||
|
SELECTED_YEAR: "SELECTED_YEAR",
|
||||||
|
};
|
||||||
|
|
||||||
|
export { navigationScenarios };
|
||||||
19
src/router/router-constants/routing-table.js
Normal file
19
src/router/router-constants/routing-table.js
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
|
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||||
|
|
||||||
|
// Get store from router/index.js instead of importing it here to get updated values
|
||||||
|
const routingTable = function(store) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
issPageValue: issPageValues.VEHICLE_YEAR,
|
||||||
|
maps: [
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.SELECTED_YEAR,
|
||||||
|
issPageValue: "PageOne"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export { routingTable };
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
import { createStore } from 'vuex'
|
|
||||||
|
|
||||||
export default createStore({
|
|
||||||
state: {
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
},
|
|
||||||
modules: {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
30
src/styles/common-animations.scss
Normal file
30
src/styles/common-animations.scss
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
.fade-enter-active {
|
||||||
|
transition: opacity 0.8s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-fade-enter-active .fade-on-route-transition {
|
||||||
|
transition: opacity 0.2s ease-out; //This duration should be kept in sync with the app.vue <transition> element attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-fade-leave-active .fade-on-route-transition {
|
||||||
|
transition: opacity 0.2s ease-in; //This duration should be kept in sync with the app.vue <transition> element attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-fade-enter-from .fade-on-route-transition,
|
||||||
|
.route-fade-leave-to .fade-on-route-transition {
|
||||||
|
/*
|
||||||
|
Hack around a Chrome 96 bug in handling nested opacity transitions.
|
||||||
|
This is not needed in other browsers or Chrome 99+ where the bug
|
||||||
|
has been fixed.
|
||||||
|
*/
|
||||||
|
opacity: 0.001;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="about">
|
|
||||||
<h1>This is an about page ... with new changes!</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="home">
|
|
||||||
<img alt="Vue logo" src="../assets/logo.png">
|
|
||||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// @ is an alias to /src
|
|
||||||
import HelloWorld from '@/components/HelloWorld.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'HomeView',
|
|
||||||
components: {
|
|
||||||
HelloWorld
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,5 +1,22 @@
|
||||||
|
process.env.VUE_APP_CONSUMER_CF_DISTRO =
|
||||||
|
"https://consumerapidev.safelite.com";
|
||||||
|
process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicPath: "/",
|
publicPath: "/",
|
||||||
|
css: {
|
||||||
|
loaderOptions: {
|
||||||
|
sass: {
|
||||||
|
// Load Order Matters!!!
|
||||||
|
// Note: only include functions, variables and mixins here
|
||||||
|
additionalData: `
|
||||||
|
@import "./node_modules/bootstrap/scss/functions";
|
||||||
|
@import "./node_modules/bootstrap/scss/variables";
|
||||||
|
@import "./node_modules/bootstrap/scss/mixins";
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
devtool: 'source-map'
|
devtool: 'source-map'
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,21 @@
|
||||||
|
process.env.VUE_APP_CONSUMER_CF_DISTRO = "__VUE_APP_CONSUMER_CF_DISTRO__";
|
||||||
|
process.env.VUE_APP_CURRENT_ENVIRONMENT = "__VUE_APP_CURRENT_ENVIRONMENT__";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicPath: "/",
|
publicPath: "/",
|
||||||
|
css: {
|
||||||
|
loaderOptions: {
|
||||||
|
sass: {
|
||||||
|
// Load Order Matters!!!
|
||||||
|
// Note: only include functions, variables and mixins here
|
||||||
|
additionalData: `
|
||||||
|
@import "./node_modules/bootstrap/scss/functions";
|
||||||
|
@import "./node_modules/bootstrap/scss/variables";
|
||||||
|
@import "./node_modules/bootstrap/scss/mixins";
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
devtool: 'source-map'
|
devtool: 'source-map'
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue