Skip to content

Commit

Permalink
Merge pull request #431 from hotwax/inventory-count-2.0
Browse files Browse the repository at this point in the history
Improved: inventory-count to directed inventory-count
  • Loading branch information
ymaheshwari1 authored Aug 14, 2024
2 parents 348fcb8 + 2634fbd commit 45f4303
Showing 66 changed files with 8,192 additions and 5,400 deletions.
3 changes: 1 addition & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -2,8 +2,7 @@ VUE_APP_I18N_LOCALE=en
VUE_APP_I18N_FALLBACK_LOCALE=en
VUE_APP_CACHE_MAX_AGE=3600
VUE_APP_VIEW_SIZE=10
VUE_APP_BASE_URL=
VUE_APP_PERMISSION_ID="INVCOUNT_APP_VIEW"
VUE_APP_ALIAS=
VUE_APP_DEFAULT_LOG_LEVEL="error"
VUE_APP_PRDT_IDENT=["productId", "groupId", "groupName", "internalName", "parentProductName", "sku", "title", "SHOPIFY_PROD_SKU", "ERP_ID", "UPCA"]
VUE_APP_LOGIN_URL="http://launchpad.hotwax.io/login"
5,291 changes: 1,857 additions & 3,434 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -18,11 +18,12 @@
"@casl/ability": "^6.0.0",
"@hotwax/app-version-info": "^1.0.0",
"@hotwax/apps-theme": "^1.2.6",
"@hotwax/dxp-components": "^1.13.0",
"@hotwax/dxp-components": "^1.14.0",
"@hotwax/oms-api": "^1.14.0",
"@ionic/core": "^7.6.0",
"@ionic/vue": "^7.6.0",
"@ionic/vue-router": "^7.6.0",
"@ionic/core": "^7.8.6",
"@ionic/vue": "^7.8.6",
"@ionic/vue-router": "^7.8.6",
"@types/papaparse": "^5.3.1",
"axios": "^0.21.1",
"axios-cache-adapter": "^2.7.3",
"boon-js": "^2.0.3",
@@ -32,16 +33,18 @@
"mitt": "^2.1.0",
"register-service-worker": "^1.7.1",
"vue": "^3.2.26",
"vue-barcode-reader": "^1.0.0",
"vue-i18n": "~9.1.6",
"vue-logger-plugin": "^2.2.3",
"vue-router": "^4.0.12",
"vuex": "^4.0.1",
"vuex-persistedstate": "^4.0.0-beta.3"
},
"devDependencies": {
"@capacitor/cli": "^2.4.7",
"@intlify/vue-i18n-loader": "^2.1.0",
"@types/file-saver": "^2.0.5",
"@types/luxon": "^3.2.0",
"@types/papaparse": "5.3.1",
"@typescript-eslint/eslint-plugin": "~5.26.0",
"@typescript-eslint/parser": "~5.26.0",
"@vue/cli-plugin-babel": "~5.0.8",
@@ -57,6 +60,8 @@
"cypress": "^8.3.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"file-saver": "^2.0.5",
"papaparse": "^5.3.1",
"typescript": "~4.7.4",
"vue-cli-plugin-i18n": "^1.0.1"
}
169 changes: 72 additions & 97 deletions src/App.vue
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>
119 changes: 119 additions & 0 deletions src/api/index.ts
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

'StatusCodes' is defined but never used

Check warning on line 6 in src/api/index.ts

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

'StatusCodes' is defined but never used

Check warning on line 6 in src/api/index.ts

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

'StatusCodes' is defined but never used

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

'status' is assigned a value but never used

Check warning on line 46 in src/api/index.ts

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

'status' is assigned a value but never used

Check warning on line 46 in src/api/index.ts

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

'status' is assigned a value but never used
// 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.
17 changes: 9 additions & 8 deletions src/authorization/Actions.ts
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"
}
Loading

0 comments on commit 45f4303

Please sign in to comment.