From f465ca4d79b5fc841a10df6e441fb4fac95dec68 Mon Sep 17 00:00:00 2001 From: Yash Maheshwari Date: Thu, 18 Jan 2024 22:50:20 +0530 Subject: [PATCH 1/5] Implemented: logic to define actions for fetching user-profile and product-stores(#10) --- src/services/UserService.ts | 71 +++++++- src/store/modules/user/UserState.ts | 1 + src/store/modules/user/actions.ts | 39 +++-- src/store/modules/user/getters.ts | 3 + src/store/modules/user/index.ts | 1 + src/store/modules/user/mutation-types.ts | 3 +- src/store/modules/user/mutations.ts | 3 + src/views/Settings.vue | 198 +++++++++++++++++------ 8 files changed, 242 insertions(+), 77 deletions(-) diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 6f61ac5..629079f 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -1,15 +1,70 @@ import api, {client} from "@/api" import store from "@/store"; +import { hasError } from "@/utils"; const login = async (username: string, password: string): Promise => { - return api({ - url: "login", - method: "post", - data: { - username, - password + let token = '' + try { + const resp = await api({ + url: "login", + method: "post", + data: { + username, + password + } + }) as any; + + if(!hasError(resp) && resp.data.token) { + token = resp.data.token + } else { + throw "Sorry, login failed. Please try again"; } - }); + } catch(err) { + return Promise.reject(err); + } + return Promise.resolve(token) +} + +const getUserProfile = async (token: any): Promise => { + const baseURL = store.getters["user/getBaseUrl"]; + try { + const resp = await client({ + url: "user/profile", + method: "GET", + baseURL, + headers: { + "api_key": token, + "Content-Type": "application/json" + } + }); + if(hasError(resp)) throw "Error getting user profile"; + return Promise.resolve(resp.data) + } catch(error: any) { + return Promise.reject(error) + } +} + +const getEComStores = async (token: any): Promise => { + try { + const baseURL = store.getters["user/getBaseUrl"]; + const resp = await client({ + url: "performFind", + method: "get", + baseURL, + headers: { + "api_key": token, + "Content-Type": "application/json" + } + }); + // Disallow login if the user is not associated with any product store + if (hasError(resp) || resp.data.docs.length === 0) { + throw resp.data; + } else { + return Promise.resolve(resp.data.docs); + } + } catch(error: any) { + return Promise.reject(error) + } } const getAvailableTimeZones = async (): Promise => { @@ -41,6 +96,8 @@ const checkPermission = async (payload: any): Promise => { export const UserService = { login, getAvailableTimeZones, + getEComStores, + getUserProfile, setUserTimeZone, checkPermission } \ No newline at end of file diff --git a/src/store/modules/user/UserState.ts b/src/store/modules/user/UserState.ts index 73ef910..010c977 100644 --- a/src/store/modules/user/UserState.ts +++ b/src/store/modules/user/UserState.ts @@ -3,4 +3,5 @@ export default interface UserState { current: object | null; currentFacility: object; instanceUrl: string; + currentEComStore: object | null, } \ No newline at end of file diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts index a83cc20..498b904 100644 --- a/src/store/modules/user/actions.ts +++ b/src/store/modules/user/actions.ts @@ -14,26 +14,18 @@ const actions: ActionTree = { */ async login({ commit }, { username, password }) { try { - // TODO: implement support for fetching user-profile // TODO: implement support for permission check - // TODO: implement support for fetching product stores for user - const resp = await UserService.login(username, password) - if (resp.status === 200 && resp.data) { - if (resp.data.token) { - commit(types.USER_TOKEN_CHANGED, { newToken: resp.data.token }) - return resp.data; - } else if (hasError(resp)) { - showToast(translate("Sorry, your username or password is incorrect. Please try again.")); - logger.error("error", resp.data._ERROR_MESSAGE_); - return Promise.reject(new Error(resp.data._ERROR_MESSAGE_)); - } - } else { - showToast(translate("Something went wrong")); - logger.error("error", resp.data._ERROR_MESSAGE_); - return Promise.reject(new Error(resp.data._ERROR_MESSAGE_)); - } + const token = await UserService.login(username, password) + + const userProfile = await UserService.getUserProfile(token); + + // Check if we need to fetch only associated product stores of user + userProfile.stores = await UserService.getEComStores(token); + + commit(types.USER_TOKEN_CHANGED, { newToken: token }) + commit(types.USER_INFO_UPDATED, userProfile); } catch (err: any) { - showToast(translate("Something went wrong")); + showToast(translate(err)); logger.error("error", err); return Promise.reject(new Error(err)) } @@ -45,7 +37,6 @@ const actions: ActionTree = { async logout ({ commit }) { // TODO add any other tasks if need commit(types.USER_END_SESSION) - }, /** @@ -73,7 +64,15 @@ const actions: ActionTree = { */ setUserInstanceUrl ({ commit }, payload){ commit(types.USER_INSTANCE_URL_UPDATED, payload) - } + }, + + setEcomStore({ commit, state }, payload) { + let productStore = payload.productStore; + if(!productStore) { + productStore = (state.current as any).stores.find((store: any) => store.productStoreId === payload.productStoreId); + } + commit(types.USER_CURRENT_ECOM_STORE_UPDATED, productStore); + }, } export default actions; \ No newline at end of file diff --git a/src/store/modules/user/getters.ts b/src/store/modules/user/getters.ts index d83899d..b60f2ff 100644 --- a/src/store/modules/user/getters.ts +++ b/src/store/modules/user/getters.ts @@ -21,6 +21,9 @@ const getters: GetterTree = { getInstanceUrl (state) { const baseUrl = process.env.VUE_APP_BASE_URL; return baseUrl ? baseUrl : state.instanceUrl; + }, + getCurrentEComStore(state) { + return state.currentEComStore } } export default getters; \ No newline at end of file diff --git a/src/store/modules/user/index.ts b/src/store/modules/user/index.ts index 0ce5100..599b35f 100644 --- a/src/store/modules/user/index.ts +++ b/src/store/modules/user/index.ts @@ -12,6 +12,7 @@ const userModule: Module = { current: null, currentFacility: {}, instanceUrl: "", + currentEComStore: {} }, getters, actions, diff --git a/src/store/modules/user/mutation-types.ts b/src/store/modules/user/mutation-types.ts index 532596c..c9ed7df 100644 --- a/src/store/modules/user/mutation-types.ts +++ b/src/store/modules/user/mutation-types.ts @@ -3,4 +3,5 @@ export const USER_TOKEN_CHANGED = SN_USER + "/TOKEN_CHANGED" export const USER_END_SESSION = SN_USER + "/END_SESSION" export const USER_INFO_UPDATED = SN_USER + "/INFO_UPDATED" export const USER_CURRENT_FACILITY_UPDATED = SN_USER + "/CURRENT_FACILITY_UPDATED" -export const USER_INSTANCE_URL_UPDATED = SN_USER + "/INSTANCE_URL_UPDATED" \ No newline at end of file +export const USER_INSTANCE_URL_UPDATED = SN_USER + "/INSTANCE_URL_UPDATED" +export const USER_CURRENT_ECOM_STORE_UPDATED = SN_USER + '/CURRENT_ECOM_STORE_UPDATED' \ No newline at end of file diff --git a/src/store/modules/user/mutations.ts b/src/store/modules/user/mutations.ts index 5811c81..c1246c0 100644 --- a/src/store/modules/user/mutations.ts +++ b/src/store/modules/user/mutations.ts @@ -19,6 +19,9 @@ const mutations: MutationTree = { }, [types.USER_INSTANCE_URL_UPDATED] (state, payload) { state.instanceUrl = payload; + }, + [types.USER_CURRENT_ECOM_STORE_UPDATED] (state, payload) { + state.currentEComStore = payload; } } export default mutations; \ No newline at end of file diff --git a/src/views/Settings.vue b/src/views/Settings.vue index 0fe6193..cdcc379 100644 --- a/src/views/Settings.vue +++ b/src/views/Settings.vue @@ -2,80 +2,144 @@ - - {{ $t("Settings") }} + + {{ "Settings" }} - - - - {{ $t("Store") }} - - {{ facility.name }} - - - - - - {{ $t("OMS") }} -

{{ instanceUrl }}

-
- - - - {{ userProfile && userProfile.userTimeZone ? userProfile.userTimeZone : "-" }} - {{ $t("Change") }} - - - - - {{ userProfile !== null ? userProfile.partyName : "" }} - {{ $t("Logout") }} - + +
+

{{ "OMS" }}

+
+
+ + + + + + {{ "Product Store" }} + + + {{ "Store" }} + + + + {{ "A store repesents a company or a unique catalog of products. If your OMS is connected to multiple eCommerce stores sellling different collections of products, you may have multiple Product Stores set up in HotWax Commerce." }} + + + + {{ store.storeName }} + + + +
+
+
+

+ {{ "App" }} +

{{ "Version: " + appVersion }}

+

+

{{ "Built: " + getDateTime(appInfo.builtTime) }}

+
+
+ + + + {{ "Timezone" }} + + + + {{ "The timezone you select is used to ensure automations you schedule are always accurate to the time you select." }} + + + {{ userProfile && userProfile.userTimeZone ? userProfile.userTimeZone : "-" }} + {{ "Change" }} + + +
+ + From 1cce0a871ae39ce82caf15058cf1d08f42716d9b Mon Sep 17 00:00:00 2001 From: Yash Maheshwari Date: Thu, 18 Jan 2024 22:50:55 +0530 Subject: [PATCH 2/5] Improved: state to set current ecom store on login(#10) --- src/store/modules/user/actions.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts index 498b904..773d308 100644 --- a/src/store/modules/user/actions.ts +++ b/src/store/modules/user/actions.ts @@ -24,6 +24,7 @@ const actions: ActionTree = { commit(types.USER_TOKEN_CHANGED, { newToken: token }) commit(types.USER_INFO_UPDATED, userProfile); + commit(types.USER_CURRENT_ECOM_STORE_UPDATED, userProfile.stores.length ? userProfile.stores[0] : {}); } catch (err: any) { showToast(translate(err)); logger.error("error", err); From 2bf1f953d2e33da325f2c3c100b790806e6d24fb Mon Sep 17 00:00:00 2001 From: Yash Maheshwari Date: Thu, 18 Jan 2024 23:19:38 +0530 Subject: [PATCH 3/5] Improved: settings page to use composition api, updated getter for baseUrl, and updated userService(#10) --- src/services/UserService.ts | 8 +- src/store/modules/user/actions.ts | 1 + src/store/modules/user/getters.ts | 15 ++- src/views/Settings.vue | 147 +++++++++--------------------- 4 files changed, 60 insertions(+), 111 deletions(-) diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 629079f..6367b24 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -48,8 +48,8 @@ const getEComStores = async (token: any): Promise => { try { const baseURL = store.getters["user/getBaseUrl"]; const resp = await client({ - url: "performFind", - method: "get", + url: "user/productStore", + method: "GET", baseURL, headers: { "api_key": token, @@ -57,10 +57,10 @@ const getEComStores = async (token: any): Promise => { } }); // Disallow login if the user is not associated with any product store - if (hasError(resp) || resp.data.docs.length === 0) { + if (hasError(resp) || resp.data.length === 0) { throw resp.data; } else { - return Promise.resolve(resp.data.docs); + return Promise.resolve(resp.data); } } catch(error: any) { return Promise.reject(error) diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts index 773d308..0c2d560 100644 --- a/src/store/modules/user/actions.ts +++ b/src/store/modules/user/actions.ts @@ -25,6 +25,7 @@ const actions: ActionTree = { commit(types.USER_TOKEN_CHANGED, { newToken: token }) commit(types.USER_INFO_UPDATED, userProfile); commit(types.USER_CURRENT_ECOM_STORE_UPDATED, userProfile.stores.length ? userProfile.stores[0] : {}); + return Promise.resolve({ token }) } catch (err: any) { showToast(translate(err)); logger.error("error", err); diff --git a/src/store/modules/user/getters.ts b/src/store/modules/user/getters.ts index b60f2ff..dd9aa3e 100644 --- a/src/store/modules/user/getters.ts +++ b/src/store/modules/user/getters.ts @@ -3,27 +3,32 @@ import UserState from "./UserState" import RootState from "@/store/RootState" const getters: GetterTree = { - isAuthenticated (state) { + isAuthenticated(state) { return !!state.token; }, isUserAuthenticated(state) { return state.token && state.current }, - getUserToken (state) { + getUserToken(state) { return state.token }, - getUserProfile (state) { + getUserProfile(state) { return state.current }, - getCurrentFacility (state){ + getCurrentFacility(state){ return state.currentFacility; }, - getInstanceUrl (state) { + getInstanceUrl(state) { const baseUrl = process.env.VUE_APP_BASE_URL; return baseUrl ? baseUrl : state.instanceUrl; }, getCurrentEComStore(state) { return state.currentEComStore + }, + getBaseUrl(state) { + let baseURL = process.env.VUE_APP_BASE_URL; + if (!baseURL) baseURL = state.instanceUrl; + return baseURL.startsWith('http') ? baseURL : `https://${baseURL}.hotwax.io/rest/s1/order-routing/`; } } export default getters; \ No newline at end of file diff --git a/src/views/Settings.vue b/src/views/Settings.vue index cdcc379..586acda 100644 --- a/src/views/Settings.vue +++ b/src/views/Settings.vue @@ -18,15 +18,11 @@ is added on sides from ion-item and ion-padding-vertical to compensate the removed vertical padding --> - {{ userProfile.userLoginId }} - {{ userProfile?.partyName }} + {{ userProfile.userId }} + {{ userProfile?.userFullName }} {{ "Logout" }} - - {{ "Go to Launchpad" }} - - @@ -35,8 +31,6 @@

{{ "OMS" }}

- - @@ -75,7 +69,7 @@ {{ "The timezone you select is used to ensure automations you schedule are always accurate to the time you select." }} - {{ userProfile && userProfile.userTimeZone ? userProfile.userTimeZone : "-" }} + {{ userProfile && userProfile.timeZone ? userProfile.timeZone : "-" }} {{ "Change" }} @@ -84,102 +78,51 @@ -