Skip to content

Commit

Permalink
Merge branch 'main' into #193-product-store-selector
Browse files Browse the repository at this point in the history
  • Loading branch information
R-Sourabh committed Oct 23, 2024
2 parents afe0d04 + 76fce68 commit 202e891
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 13 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hotwax/dxp-components",
"version": "1.15.2",
"version": "1.15.4",
"description": "",
"type": "module",
"main": "lib/index.cjs",
Expand Down
162 changes: 162 additions & 0 deletions src/components/DxpFacilitySwitcher.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<template>
<ion-card>
<ion-card-header>
<ion-card-title>
{{ $t('Facility') }}
</ion-card-title>
</ion-card-header>
<ion-card-content>
{{ $t('Specify which facility you want to operate from. Order, inventory and other configuration data will be specific to the facility you select.') }}
</ion-card-content>
<ion-item lines="none">
<ion-label>
{{ currentFacility.facilityName }}
<p>{{ currentFacility.facilityId }}</p>
</ion-label>
<ion-button id="open-facility-modal" slot="end" fill="outline" color="dark">{{ $t('Change')}}</ion-button>
</ion-item>
</ion-card>
<!-- Using inline modal(as recommended by ionic), also using it inline as the component inside modal is not getting mounted when using modalController -->
<ion-modal ref="facilityModal" trigger="open-facility-modal" @didPresent="loadFacilities()" @didDismiss="clearSearch()">
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon :icon="closeOutline"/>
</ion-button>
</ion-buttons>
<ion-title>{{ $t("Select Facility") }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-toolbar>
<ion-searchbar @ionFocus="selectSearchBarText($event)" :placeholder="$t('Search facilities')" v-model="queryString" @keyup.enter="queryString = $event.target.value; findFacility()" @keydown="preventSpecialCharacters($event)"/>
</ion-toolbar>
<ion-content>
<ion-radio-group v-model="selectedFacilityId">
<ion-list>
<!-- Loading state -->
<div class="empty-state" v-if="isLoading">
<ion-item lines="none">
<ion-spinner color="secondary" name="crescent" slot="start" />
{{ $t("Fetching facilities") }}
</ion-item>
</div>
<!-- Empty state -->
<div class="empty-state" v-else-if="!filteredFacilities.length">
<p>{{ $t("No facilities found") }}</p>
</div>
<div v-else>
<ion-item v-for="facility in filteredFacilities" :key="facility.facilityId">
<ion-radio label-placement="end" justify="start" :value="facility.facilityId">
<ion-label>
{{ facility.facilityName }}
<p>{{ facility.facilityId }}</p>
</ion-label>
</ion-radio>
</ion-item>
</div>
</ion-list>
</ion-radio-group>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button :disabled="selectedFacilityId === currentFacility.facilityId" @click="updateFacility">
<ion-icon :icon="saveOutline" />
</ion-fab-button>
</ion-fab>
</ion-content>
</ion-modal>
</template>

<script setup lang="ts">
import {
IonButton,
IonButtons,
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonModal,
IonRadio,
IonRadioGroup,
IonSearchbar,
IonSpinner,
IonTitle,
IonToolbar
} from '@ionic/vue';
import { closeOutline, saveOutline } from "ionicons/icons";
import { useUserStore } from 'src/store/user';
import { computed, ref } from 'vue';
const userStore = useUserStore();
const facilities = computed(() => userStore.getFacilites)
const currentFacility = computed(() => userStore.getCurrentFacility)
const facilityModal = ref()
const queryString = ref('')
const isLoading = ref(true);
const filteredFacilities = ref([])
const selectedFacilityId = ref(currentFacility.value.facilityId)
const emit = defineEmits(["updateFacility"])
const closeModal = () => {
facilityModal.value.$el.dismiss(null, 'cancel');
}
function loadFacilities() {
filteredFacilities.value = facilities.value;
isLoading.value = false;
}
const findFacility = () => {
isLoading.value = true
const searchedString = queryString.value.trim().toLowerCase();
if(searchedString) {
filteredFacilities.value = facilities.value.filter((facility: any) =>
facility.facilityName.toLowerCase().includes(searchedString) ||
facility.facilityId.toLowerCase().includes(searchedString)
);
} else {
filteredFacilities.value = facilities.value;
}
isLoading.value = false
}
async function selectSearchBarText(event: any) {
const element = await event.target.getInputElement()
element.select();
}
function preventSpecialCharacters($event: any) {
// Searching special characters fails the API, hence, they must be omitted
if(/[`!@#$%^&*()_+\-=\\|,.<>?~]/.test($event.key)) $event.preventDefault();
}
async function updateFacility() {
const selectedFacility = facilities.value.find((facility: any) => facility.facilityId === selectedFacilityId.value)
await userStore.setFacilityPreference(selectedFacility)
emit('updateFacility', selectedFacility);
closeModal();
}
function clearSearch() {
queryString.value = ''
filteredFacilities.value = []
isLoading.value = true
}
</script>

<style scoped>
ion-content {
--padding-bottom: 80px;
}
</style>
3 changes: 2 additions & 1 deletion src/components/DxpOmsInstanceNavigator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ion-card-content>
{{ $t('This is the name of the OMS you are connected to right now. Make sure that you are connected to the right instance before proceeding.') }}
</ion-card-content>
<ion-button @click="goToOms(token.value, oms)" fill="clear">
<ion-button @click="goToOms(token.value, oms)" fill="clear" :disabled="!appContext.hasPermission(appContext.Actions.APP_COMMERCE_VIEW)">
{{ $t('Go to OMS') }}
<ion-icon slot="end" :icon="openOutline" />
</ion-button>
Expand All @@ -32,6 +32,7 @@ import { goToOms } from '../utils';
import { openOutline } from 'ionicons/icons'
import { computed } from 'vue';
import { useAuthStore } from "../store/auth";
import { appContext } from "src";
const authStore = useAuthStore();
Expand Down
4 changes: 2 additions & 2 deletions src/components/DxpProductIdentifier.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
{{ 'Choosing a product identifier allows you to view products with your preferred identifiers.' }}
</ion-card-content>

<ion-item>
<ion-item :disabled="!appContext.hasPermission(appContext.Actions.APP_PRODUCT_IDENTIFIER_UPDATE)">
<ion-select :label="$t('Primary')" interface="popover" :placeholder="'primary identifier'" :value="productIdentificationPref.primaryId" @ionChange="setProductIdentificationPref($event.detail.value, 'primaryId')">
<ion-select-option v-for="identification in productIdentificationOptions" :key="identification" :value="identification" >{{ identification }}</ion-select-option>
</ion-select>
</ion-item>
<ion-item lines="none">
<ion-item lines="none" :disabled="!appContext.hasPermission(appContext.Actions.APP_PRODUCT_IDENTIFIER_UPDATE)">
<ion-select :label="$t('Secondary')" interface="popover" :placeholder="'secondary identifier'" :value="productIdentificationPref.secondaryId" @ionChange="setProductIdentificationPref($event.detail.value, 'secondaryId')">
<ion-select-option v-for="identification in productIdentificationOptions" :key="identification" :value="identification" >{{ identification }}</ion-select-option>
<ion-select-option value="">{{ "None" }}</ion-select-option>
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import '@ionic/vue/css/flex-utils.css';
import '@ionic/vue/css/display.css';

export { default as DxpAppVersionInfo } from './DxpAppVersionInfo.vue';
export { default as DxpFacilitySwitcher } from './DxpFacilitySwitcher.vue'
export { default as DxpGitBookSearch } from './DxpGitBookSearch.vue';
export { default as DxpImage } from './DxpImage.vue';
export { default as DxpLanguageSwitcher } from './DxpLanguageSwitcher.vue';
Expand Down
12 changes: 11 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ declare var process: any;
import { createPinia } from "pinia";
import { useProductIdentificationStore } from "./store/productIdentification";
import { useAuthStore } from "./store/auth";
import { DxpAppVersionInfo, DxpGitBookSearch, DxpImage, DxpLanguageSwitcher, DxpLogin, DxpMenuFooterNavigation, DxpOmsInstanceNavigator, DxpProductIdentifier, DxpProductStoreSelector, DxpShopifyImg, DxpTimeZoneSwitcher, DxpUserProfile } from "./components";
import { DxpAppVersionInfo, DxpFacilitySwitcher, DxpGitBookSearch, DxpImage, DxpLanguageSwitcher, DxpLogin, DxpMenuFooterNavigation, DxpOmsInstanceNavigator, DxpProductIdentifier, DxpProductStoreSelector, DxpShopifyImg, DxpTimeZoneSwitcher, DxpUserProfile } from "./components";
import { goToOms, getProductIdentificationValue } from "./utils";
import { initialiseFirebaseApp } from "./utils/firebase"
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
Expand All @@ -25,6 +25,7 @@ let loginContext = {} as any
let shopifyImgContext = {} as any
let appContext = {} as any
let productIdentificationContext = {} as any
let facilityContext = {} as any
let productStoreContext = {} as any
let notificationContext = {} as any
let gitBookContext = {} as any
Expand Down Expand Up @@ -68,6 +69,7 @@ export let dxpComponents = {
})

app.component('DxpAppVersionInfo', DxpAppVersionInfo)
app.component('DxpFacilitySwitcher', DxpFacilitySwitcher)
app.component('DxpGitBookSearch', DxpGitBookSearch)
app.component('DxpImage', DxpImage)
app.component('DxpLanguageSwitcher', DxpLanguageSwitcher)
Expand Down Expand Up @@ -98,6 +100,10 @@ export let dxpComponents = {

productIdentificationContext.getProductIdentificationPref = options.getProductIdentificationPref
productIdentificationContext.setProductIdentificationPref = options.setProductIdentificationPref

facilityContext.getUserFacilities = options.getUserFacilities
facilityContext.setUserPreference = options.setUserPreference
facilityContext.getUserPreference = options.getUserPreference

productStoreContext.getEComStoresByFacility = options.getEComStoresByFacility
productStoreContext.setUserPreference = options.setUserPreference
Expand All @@ -115,6 +121,9 @@ export let dxpComponents = {
loginContext.getConfig = options.getConfig
loginContext.initialise = options.initialise

appContext.Actions = options.Actions
appContext.hasPermission = options.hasPermission

// set a default locale in the state
i18n.global.locale.value = useUserStore().getLocale

Expand All @@ -141,6 +150,7 @@ export {
loginContext,
notificationContext,
productIdentificationContext,
facilityContext,
productStoreContext,
shopifyImgContext,
translate,
Expand Down
2 changes: 1 addition & 1 deletion src/store/productIdentification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const useProductIdentificationStore = defineStore('productIdentification'
primaryId: '',
secondaryId: ''
},
productIdentificationOptions: ["productId", "groupId", "groupName", "internalName", "parentProductName", "primaryProductCategoryName", "sku", "title", "SHOPIFY_PROD_SKU"]
productIdentificationOptions: ["productId", "groupId", "groupName", "internalName", "parentProductName", "primaryProductCategoryName", "sku", "title", "SHOPIFY_PROD_SKU", "upc"]
}
},
getters: {
Expand Down
57 changes: 52 additions & 5 deletions src/store/user.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { defineStore } from "pinia";
import { appContext, i18n, translate, userContext, useAuthStore } from "../../src";
import { i18n, translate, userContext, useAuthStore } from "../../src";
import { DateTime } from "luxon";
import { showToast } from "src/utils";
import { facilityContext } from "../index";
import { productStoreContext } from "../index";

declare let process: any;
Expand All @@ -14,16 +15,20 @@ export const useUserStore = defineStore('user', {
localeOptions: process.env.VUE_APP_LOCALES ? JSON.parse(process.env.VUE_APP_LOCALES) : { "en-US": "English" },
locale: 'en-US',
currentTimeZoneId: '',
timeZones: []
timeZones: [],
facilities: [],
currentFacility: {} as any
}
},
getters: {
getLocale: (state) => state.locale,
getLocaleOptions: (state) => state.localeOptions,
getTimeZones: (state) => state.timeZones,
getCurrentEComStore: (state) => state.currentEComStore,
getCurrentTimeZone: (state) => state.currentTimeZoneId,
getFacilites: (state) => state.facilities,
getCurrentFacility: (state) => state.currentFacility,
getProductStores: (state) => state.eComStores,
getCurrentTimeZone: (state) => state.currentTimeZoneId
getCurrentEComStore: (state) => state.currentEComStore,
},
actions: {
async setLocale(locale: string) {
Expand Down Expand Up @@ -79,6 +84,48 @@ export const useUserStore = defineStore('user', {
updateTimeZone(tzId: string) {
this.currentTimeZoneId = tzId
},
async getUserFacilities(partyId: any, facilityGroupId: any, isAdminUser: boolean) {
const authStore = useAuthStore();

try {
const response = await facilityContext.getUserFacilities(authStore.getToken.value, authStore.getBaseUrl, partyId, facilityGroupId, isAdminUser);
this.facilities = response;
} catch (error) {
console.error(error);
}
return this.facilities
},
async getFacilityPreference(userPrefTypeId: any) {
const authStore = useAuthStore();

if (!this.facilities.length) {
return;
}
let preferredFacility = this.facilities[0];

try {
let preferredFacilityId = await facilityContext.getUserPreference(authStore.getToken.value, authStore.getBaseUrl, userPrefTypeId);
if(preferredFacilityId) {
const facility = this.facilities.find((facility: any) => facility.facilityId === preferredFacilityId);
facility && (preferredFacility = facility)
}
} catch (error) {
console.error(error);
}
this.currentFacility = preferredFacility;
},
async setFacilityPreference(payload: any) {

try {
await facilityContext.setUserPreference({
userPrefTypeId: 'SELECTED_FACILITY',
userPrefValue: payload.facilityId
})
} catch (error) {
console.error('error', error)
}
this.currentFacility = payload;
},
async getEComStoresByFacility(facilityId?: any) {
const authStore = useAuthStore();

Expand Down Expand Up @@ -120,7 +167,7 @@ export const useUserStore = defineStore('user', {
console.error('error', error)
}
this.currentEComStore = payload;
},
}
},
persist: true
})

0 comments on commit 202e891

Please sign in to comment.