-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #431 from hotwax/inventory-count-2.0
Improved: inventory-count to directed inventory-count
- Loading branch information
Showing
66 changed files
with
8,192 additions
and
5,400 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,91 @@ | ||
<template> | ||
<ion-app> | ||
<ion-page> | ||
<ion-content> | ||
<ion-router-outlet /> | ||
</ion-content> | ||
</ion-page> | ||
<ion-app v-if="!$router.currentRoute.value.fullPath.includes('/tabs/') && hasPermission(Actions.APP_DRAFT_VIEW)"> | ||
<IonSplitPane content-id="main-content" when="lg"> | ||
<Menu /> | ||
<ion-router-outlet id="main-content"></ion-router-outlet> | ||
</IonSplitPane> | ||
</ion-app> | ||
<ion-app v-else> | ||
<ion-router-outlet id="main-content"></ion-router-outlet> | ||
</ion-app> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { IonApp, IonRouterOutlet, IonPage, IonContent } from '@ionic/vue'; | ||
import { defineComponent } from 'vue'; | ||
<script setup lang="ts"> | ||
import { IonApp, IonRouterOutlet, IonSplitPane } from '@ionic/vue'; | ||
import { computed, onMounted, onUnmounted, ref } from 'vue'; | ||
import { loadingController } from '@ionic/vue'; | ||
import emitter from "@/event-bus" | ||
import { mapGetters, useStore } from 'vuex'; | ||
import { initialise, resetConfig } from '@/adapter' | ||
import { useRouter } from 'vue-router'; | ||
import { useProductIdentificationStore } from '@hotwax/dxp-components'; | ||
import store from "./store"; | ||
import { translate } from "@/i18n" | ||
import { Settings } from 'luxon' | ||
import Menu from '@/components/Menu.vue'; | ||
import { Actions, hasPermission } from '@/authorization' | ||
export default defineComponent({ | ||
name: 'App', | ||
components: { | ||
IonApp, | ||
IonRouterOutlet, | ||
IonPage, | ||
IonContent | ||
}, | ||
data() { | ||
return { | ||
loader: null as any, | ||
maxAge: process.env.VUE_APP_CACHE_MAX_AGE ? parseInt(process.env.VUE_APP_CACHE_MAX_AGE) : 0 | ||
} | ||
}, | ||
methods: { | ||
async presentLoader(options = { message: '', backdropDismiss: true }) { | ||
// When having a custom message remove already existing loader | ||
if(options.message && this.loader) this.dismissLoader(); | ||
const userProfile = computed(() => store.getters["user/getUserProfile"]) | ||
const userToken = computed(() => store.getters["user/getUserToken"]) | ||
const instanceUrl = computed(() => store.getters["user/getInstanceUrl"]) | ||
if (!this.loader) { | ||
this.loader = await loadingController | ||
.create({ | ||
message: options.message ? this.$t(options.message) : this.$t("Click the backdrop to dismiss."), | ||
translucent: true, | ||
backdropDismiss: options.backdropDismiss | ||
}); | ||
} | ||
this.loader.present(); | ||
}, | ||
dismissLoader() { | ||
if (this.loader) { | ||
this.loader.dismiss(); | ||
this.loader = null as any; | ||
} | ||
const loader = ref(null) as any | ||
const maxAge = process.env.VUE_APP_CACHE_MAX_AGE ? parseInt(process.env.VUE_APP_CACHE_MAX_AGE) : 0 | ||
initialise({ | ||
token: userToken.value, | ||
instanceUrl: instanceUrl.value, | ||
cacheMaxAge: maxAge, | ||
events: { | ||
responseError: () => { | ||
setTimeout(() => dismissLoader(), 100); | ||
}, | ||
async unauthorised() { | ||
// Mark the user as unauthorised, this will help in not making the logout api call in actions | ||
this.store.dispatch("user/logout", { isUserUnauthorised: true }); | ||
const redirectUrl = window.location.origin + '/login'; | ||
window.location.href = `${process.env.VUE_APP_LOGIN_URL}?redirectUrl=${redirectUrl}`; | ||
queueTask: (payload: any) => { | ||
emitter.emit("queueTask", payload); | ||
} | ||
}, | ||
async mounted() { | ||
this.loader = await loadingController | ||
} | ||
}) | ||
async function presentLoader(options = { message: "Click the backdrop to dismiss.", backdropDismiss: true }) { | ||
// When having a custom message remove already existing loader, if not removed it takes into account the already existing loader | ||
if(options.message && loader.value) dismissLoader(); | ||
if (!loader.value) { | ||
loader.value = await loadingController | ||
.create({ | ||
message: this.$t("Click the backdrop to dismiss."), | ||
message: translate(options.message), | ||
translucent: true, | ||
backdropDismiss: true | ||
backdropDismiss: options.backdropDismiss | ||
}); | ||
emitter.on('presentLoader', this.presentLoader); | ||
emitter.on('dismissLoader', this.dismissLoader); | ||
} | ||
loader.value.present(); | ||
} | ||
// Get product identification from api using dxp-component | ||
await useProductIdentificationStore().getIdentificationPref(this.currentEComStore?.productStoreId) | ||
.catch((error) => console.error(error)); | ||
}, | ||
created() { | ||
initialise({ | ||
token: this.userToken, | ||
instanceUrl: this.instanceUrl, | ||
cacheMaxAge: this.maxAge, | ||
events: { | ||
unauthorised: this.unauthorised, | ||
responseError: () => { | ||
setTimeout(() => this.dismissLoader(), 100); | ||
}, | ||
queueTask: (payload: any) => { | ||
emitter.emit("queueTask", payload); | ||
} | ||
} | ||
}) | ||
}, | ||
unmounted() { | ||
emitter.off('presentLoader', this.presentLoader); | ||
emitter.off('dismissLoader', this.dismissLoader); | ||
function dismissLoader() { | ||
if (loader.value) { | ||
loader.value.dismiss(); | ||
loader.value = null as any; | ||
} | ||
} | ||
resetConfig() | ||
}, | ||
computed: { | ||
...mapGetters({ | ||
userToken: 'user/getUserToken', | ||
instanceUrl: 'user/getInstanceUrl', | ||
currentEComStore: 'user/getCurrentEComStore' | ||
}) | ||
}, | ||
setup() { | ||
const store = useStore(); | ||
const router = useRouter(); | ||
onMounted(async () => { | ||
loader.value = await loadingController | ||
.create({ | ||
message: translate("Click the backdrop to dismiss."), | ||
translucent: true, | ||
backdropDismiss: true | ||
}); | ||
emitter.on("presentLoader", presentLoader); | ||
emitter.on("dismissLoader", dismissLoader); | ||
return { | ||
router, | ||
store | ||
} | ||
if (userProfile.value) { | ||
// Luxon timezone should be set with the user's selected timezone | ||
userProfile.value.timeZone && (Settings.defaultZone = userProfile.value.timeZone); | ||
} | ||
}); | ||
}) | ||
onUnmounted(() => { | ||
emitter.off("presentLoader", presentLoader); | ||
emitter.off("dismissLoader", dismissLoader); | ||
resetConfig() | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import axios from "axios"; | ||
import { setupCache } from "axios-cache-adapter" | ||
import OfflineHelper from "@/offline-helper" | ||
import emitter from "@/event-bus" | ||
import store from "@/store"; | ||
import { StatusCodes } from "http-status-codes"; | ||
Check warning on line 6 in src/api/index.ts GitHub Actions / call-workflow-in-another-repo / build_and_deploy
Check warning on line 6 in src/api/index.ts GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)
|
||
|
||
axios.interceptors.request.use((config: any) => { | ||
// TODO: pass csrf token | ||
const token = store.getters["user/getUserToken"]; | ||
|
||
if (token) { | ||
config.headers["api_key"] = token; | ||
config.headers["Content-Type"] = "application/json"; | ||
} | ||
|
||
return config; | ||
}); | ||
|
||
// TODO: need to update this as per the changes in the Moqui response format, if required. | ||
axios.interceptors.response.use(function (response) { | ||
// Any status code that lie within the range of 2xx cause this function to trigger | ||
// Do something with response data | ||
|
||
// TODO: explore more on a secure way to store the csrf token | ||
// Cannot store it in cookies or localStorage as its not safe | ||
// https://stackoverflow.com/questions/67062876/is-it-secure-to-store-a-csrf-token-value-in-the-dom | ||
// https://stackoverflow.com/questions/62289684/what-is-the-correct-way-for-a-client-to-store-a-csrf-token | ||
const csrfToken = response.headers["x-csrf-token"] | ||
const meta = document.createElement("meta") | ||
meta.name = "csrf" | ||
meta.content = csrfToken | ||
document.getElementsByTagName("head")[0].appendChild(meta) | ||
|
||
document.cookie = `x-csrf-token=${csrfToken}` | ||
|
||
return response; | ||
}, function (error) { | ||
// TODO Handle it in a better way | ||
// Currently when the app gets offline, the time between adding a loader and removing it is fractional due to which loader dismiss is called before loader present | ||
// which cause loader to run indefinitely | ||
// Following gives dismiss loader a delay of 100 microseconds to get both the actions in sync | ||
setTimeout(() => emitter.emit("dismissLoader"), 100); | ||
if (error.response) { | ||
// TODO Handle case for failed queue request | ||
const { status } = error.response; | ||
Check warning on line 46 in src/api/index.ts GitHub Actions / call-workflow-in-another-repo / build_and_deploy
Check warning on line 46 in src/api/index.ts GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)
|
||
// if (status === StatusCodes.UNAUTHORIZED) { | ||
// store.dispatch("user/logout"); | ||
// const redirectUrl = window.location.origin + '/login'; | ||
// // Explicitly passing isLoggedOut as in case of maarg apps we need to call the logout api in launchpad | ||
// window.location.href = `${process.env.VUE_APP_LOGIN_URL}?redirectUrl=${redirectUrl}&isLoggedOut=true`; | ||
// } | ||
} | ||
// Any status codes that falls outside the range of 2xx cause this function to trigger | ||
// Do something with response error | ||
return Promise.reject(error); | ||
}); | ||
|
||
const maxAge = process.env.VUE_APP_CACHE_MAX_AGE ? parseInt(process.env.VUE_APP_CACHE_MAX_AGE) : 0; | ||
const axiosCache = setupCache({ | ||
maxAge: maxAge * 1000 | ||
}) | ||
|
||
|
||
/** | ||
* Generic method to call APIs | ||
* | ||
* @param {string} url - API Url | ||
* @param {string=} method - "GET", "PUT", "POST", "DELETE , and "PATCH" | ||
* @param {any} [data] - Optional: `data` is the data to be sent as the request body. Only applicable for request methods "PUT", "POST", "DELETE , and "PATCH" | ||
* When no `transformRequest` is set, must be of one of the following types: | ||
* - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams | ||
* - Browser only: FormData, File, Blob | ||
* - Node only: Stream, Buffer | ||
* @param {any} [params] - Optional: `params` are the URL parameters to be sent with the request. Must be a plain object or a URLSearchParams object | ||
* @param {boolean} [cache] - Optional: Apply caching to it | ||
* @param {boolean} [queue] - Optional: Apply offline queueing to it | ||
* @return {Promise} Response from API as returned by Axios | ||
*/ | ||
const api = async (customConfig: any) => { | ||
// Prepare configuration | ||
const config: any = { | ||
url: customConfig.url, | ||
method: customConfig.method, | ||
data: customConfig.data, | ||
params: customConfig.params, | ||
// withCredentials: true | ||
} | ||
|
||
const baseURL = store.getters["user/getInstanceUrl"]; | ||
|
||
if (baseURL) { | ||
config.baseURL = baseURL.startsWith('http') ? baseURL.includes('/rest/s1/inventory-cycle-count') ? baseURL : `${baseURL}/rest/s1/inventory-cycle-count/` : `https://${baseURL}.hotwax.io/rest/s1/inventory-cycle-count/`; | ||
} | ||
|
||
if(customConfig.cache) config.adapter = axiosCache.adapter; | ||
const networkStatus = await OfflineHelper.getNetworkStatus(); | ||
if (customConfig.queue && !networkStatus.connected) { | ||
if (!config.headers) config.headers = { ...axios.defaults.headers.common, ...config.headers }; | ||
emitter.emit("queueTask", { | ||
callbackEvent: customConfig.callbackEvent, | ||
payload: config | ||
}); | ||
} else { | ||
return axios(config); | ||
} | ||
} | ||
|
||
/** | ||
* Client method to directly pass configuration to axios | ||
* | ||
* @param {any} config - API configuration | ||
* @return {Promise} Response from API as returned by Axios | ||
*/ | ||
const client = (config: any) => { | ||
return axios.create().request(config) | ||
} | ||
|
||
export { api as default, client, axios }; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
export default { | ||
"APP_UPLOAD_VIEW": "APP_UPLOAD_VIEW", | ||
"APP_COUNT_VIEW": "APP_COUNT_VIEW", | ||
"APP_SEARCH_VIEW": "APP_SEARCH_VIEW", | ||
"APP_VARIANCE_LOG": "APP_VARIANCE_LOG", | ||
"APP_INVNTRY_CNT_IMPORT": "APP_INVNTRY_CNT_IMPORT", | ||
"APP_QOH_STNG_UPDATE": "APP_QOH_STNG_UPDATE", | ||
"INVCOUNT_APP_VIEW": "INVCOUNT_APP_VIEW" | ||
} | ||
"APP_DRAFT_VIEW": "APP_DRAFT_VIEW", | ||
"APP_ASSIGNED_VIEW": "APP_ASSIGNED_VIEW", | ||
"APP_PENDING_REVIEW_VIEW": "APP_PENDING_REVIEW_VIEW", | ||
"APP_CLOSED_VIEW": "APP_CLOSED_VIEW", | ||
"APP_STORE_PERMISSIONS_VIEW": "APP_STORE_PERMISSIONS_VIEW", | ||
"APP_SETTINGS_VIEW": "APP_SETTINGS_VIEW", | ||
"APP_COUNT_VIEW": "APP_COUNT_VIEW", | ||
"APP_PRODUCT_IDENTIFIER_UPDATE": "APP_PRODUCT_IDENTIFIER_UPDATE" | ||
} |
Oops, something went wrong.