Skip to content

Commit

Permalink
Merge pull request #206 from ymaheshwari1/fulfillment/#159
Browse files Browse the repository at this point in the history
Implemented: support to fetch data dynamically and added support to add custom field in the download exim(#159)
  • Loading branch information
adityasharma7 authored Jul 18, 2023
2 parents 62827f0 + 524413f commit fa9fd36
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 24 deletions.
102 changes: 102 additions & 0 deletions src/components/CustomFieldModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon slot="icon-only" :icon="closeOutline" />
</ion-button>
</ion-buttons>
<ion-title>{{ $t("Add custom field") }}</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<ion-list>
<ion-item lines="full">
<ion-label position="fixed">{{ $t("Key") }}</ion-label>
<ion-input :placeholder="$t('Enter key')" name="key" v-model="key" id="key" type="text" required />
</ion-item>
<ion-item>
<ion-label position="fixed">{{ $t("Value") }}</ion-label>
<ion-input :placeholder="$t('Enter value')" name="value" v-model="value" id="value" type="text" required />
</ion-item>
</ion-list>

<ion-fab @click="saveCustomField()" vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button>
<ion-icon :icon="checkmarkDoneOutline" />
</ion-fab-button>
</ion-fab>
</ion-content>
</template>

<script lang="ts">
import {
IonButtons,
IonButton,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
modalController
} from "@ionic/vue";
import { defineComponent } from "vue";
import { checkmarkDoneOutline, closeOutline } from "ionicons/icons";
import { useStore } from "vuex";
import { showToast } from "@/utils"
import { translate } from "@/i18n";
export default defineComponent({
name: "CustomFieldModal",
components: {
IonButtons,
IonButton,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
},
data() {
return {
key: '',
value: ''
}
},
methods: {
closeModal() {
modalController.dismiss({ dismissed: true});
},
saveCustomField() {
const fieldKey = this.key.trim();
if(!fieldKey) {
showToast(translate('Please enter a valid key'))
return;
}
modalController.dismiss({ dismissed: true, value: { key: fieldKey, value: this.value } });
}
},
setup() {
const store = useStore();
return {
checkmarkDoneOutline,
closeOutline,
store
};
},
});
</script>
7 changes: 7 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
" doesn't have any orders in progress right now.": " doesn't have any orders in progress right now.",
" doesn't have any outstanding orders right now.": " doesn't have any outstanding orders right now.",
"Add Box": "Add Box",
"Add custom field": "Add custom field",
"Are you sure you want to change the time zone to?": "Are you sure you want to change the time zone to?",
"Are you sure you want perform this action?": "Are you sure you want perform this action?",
"Are you sure you want to recycle outstanding order(s)?": "Are you sure you want to recycle { ordersCount } outstanding order(s)?",
Expand All @@ -28,14 +29,18 @@
"Download packed orders": "Download packed orders",
"eCom Store": "eCom Store",
"Edit packaging": "Edit packaging",
"Enter key": "Enter key",
"Enter value": "Enter value",
"EXIM": "EXIM",
"Facility ID": "Facility ID",
"Facility updated successfully": "Facility updated successfully",
"Failed to add box": "Failed to add box",
"Failed to create picklist for orders": "Failed to create picklist for orders",
"Failed to generate shipping label": "Failed to generate shipping label",
"Failed to get packed orders information": "Failed to get packed orders information",
"Failed to pack order": "Failed to pack order",
"Failed to pack orders": "Failed to pack orders",
"Failed to parse the data": "Failed to parse the data",
"Failed to print shipping label and packing slip": "Failed to print shipping label and packing slip",
"Failed to ship order": "Failed to ship order",
"Failed to recycle in progress orders": "Failed to recycle in progress orders",
Expand All @@ -52,6 +57,7 @@
"Import shipped order details from an external system based on tracking codes. Orders that have tracking codes will automatically be shipped at the end of the day.": "Import shipped order details from an external system based on tracking codes. Orders that have tracking codes will automatically be shipped at the end of the day.",
"Import shipped orders": "Import shipped orders",
"In Progress": "In Progress",
"Key": "Key",
"Last brokered": "Last brokered",
"Loading": "Loading",
"Login": "Login",
Expand Down Expand Up @@ -162,6 +168,7 @@
"Unpacking this order will send it back to 'In progress' and it will have to be repacked.": "Unpacking this order will send it back to 'In progress' and it will have to be repacked.",
"Upload": "Upload",
"Username": "Username",
"Value": "Value",
"Worn Display": "Worn Display",
"Yes": "Yes",
"You are packing an order. Select additional documents that you would like to print.": "You are packing an order. Select additional documents that you would like to print.",
Expand Down
7 changes: 7 additions & 0 deletions src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
" doesn't have any orders in progress right now.": " no tiene ningún pedido en curso en este momento.",
" doesn't have any outstanding orders right now.": " no tiene ningún pedido pendiente en este momento.",
"Add Box": "Agregar caja",
"Add custom field": "Add custom field",
"Are you sure you want to change the time zone to?": "¿Estás seguro de que quieres cambiar la zona horaria a?",
"Are you sure you want perform this action?": "¿Estás segura de que quieres realizar esta acción?",
"Are you sure you want to recycle outstanding order(s)?": "¿Está seguro de que desea reciclar # pedido(s) pendiente(s)?",
Expand All @@ -28,14 +29,18 @@
"Download packed orders": "Download packed orders",
"eCom Store": "Tienda electrónica",
"Edit packaging": "Edit packaging",
"Enter key": "Enter key",
"Enter value": "Enter value",
"EXIM": "EXIM",
"Facility ID": "Facility ID",
"Facility updated successfully": "Facility updated successfully",
"Failed to add box": "Failed to add box",
"Failed to create picklist for orders": "Failed to create picklist for orders",
"Failed to generate shipping label": "Failed to generate shipping label",
"Failed to get packed orders information": "Failed to get packed orders information",
"Failed to pack order": "Failed to pack order",
"Failed to pack orders": "Failed to pack orders",
"Failed to parse the data": "Failed to parse the data",
"Failed to print shipping label and packing slip": "Failed to print shipping label and packing slip",
"Failed to ship order": "Failed to ship order",
"Failed to recycle in progress orders": "Failed to recycle in progress orders",
Expand All @@ -52,6 +57,7 @@
"Import shipped order details from an external system based on tracking codes. Orders that have tracking codes will automatically be shipped at the end of the day.": "Import shipped order details from an external system based on tracking codes. Orders that have tracking codes will automatically be shipped at the end of the day.",
"Import shipped orders": "Import shipped orders",
"In Progress": "En curso",
"Key": "Key",
"Last brokered": "Última intermediación",
"Loading": "Loading",
"Login": "Acceso",
Expand Down Expand Up @@ -162,6 +168,7 @@
"Unpacking this order will send it back to 'In progress' and it will have to be repacked.": "Al desbloquear este pedido, se enviará de nuevo a 'En curso' y tendrá que volver a empacarse.",
"Upload": "Upload",
"Username": "Username",
"Value": "Value",
"Worn Display": "Worn Display",
"Yes": "",
"You are packing an order. Select additional documents that you would like to print.": "You are packing an order. Select additional documents that you would like to print.",
Expand Down
10 changes: 10 additions & 0 deletions src/services/UploadService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const uploadJsonFile = async (payload: any): Promise <any> => {
...payload
});
}

const prepareUploadJsonPayload = (request: UploadRequest) => {
const blob = new Blob([JSON.stringify(request.uploadData)], { type: 'application/json'});
const formData = new FormData();
Expand All @@ -26,7 +27,16 @@ const prepareUploadJsonPayload = (request: UploadRequest) => {
}
}

const fetchPackedOrders = async (payload: any): Promise <any> => {
return api({
url: "generateCsvFile",
method: "get",
...payload
});
}

export const UploadService = {
fetchPackedOrders,
prepareUploadJsonPayload,
uploadJsonFile
}
104 changes: 80 additions & 24 deletions src/views/DownloadPackedOrders.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
</ion-header>

<ion-content>
<!-- TODO: remove this option to upload file and make api call in ionViewWillEnter to get the csv file -->
<input :placeholder="$t('Select CSV')" @change="parse" ref="file" class="ion-hide" type="file" id="downloadPackedOrders"/>
<label for="downloadPackedOrders">{{ $t("Upload") }}</label>
<main>
<ion-list>
<ion-list-header>{{ $t("Select the fields you want to include in your export") }}</ion-list-header>
Expand All @@ -28,6 +25,18 @@
</ion-item>
</ion-list>

<ion-list>
<ion-button fill="clear" @click="addCustomField()" :disabled="!Object.keys(fieldMapping).length">{{ $t('Add custom field') }}</ion-button>

<ion-item :key="key" v-for="(value, key) in customFields">
<ion-label>{{ key }}</ion-label>
<ion-label slot="end">{{ value }}</ion-label>
<ion-button slot="end" fill="clear" @click="removeCustomField(key)">
<ion-icon :icon="trashOutline" />
</ion-button>
</ion-item>
</ion-list>

<ion-button size="large" :disabled="!content.length" color="medium" @click="download" expand="block">
{{ $t("Download") }}
</ion-button>
Expand All @@ -40,13 +49,15 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { mapGetters } from "vuex";
import { alertController, IonBackButton, IonButton, IonCheckbox, IonContent, IonHeader, IonIcon, IonItem, IonLabel, IonList, IonListHeader, IonPage, IonTitle, IonToolbar } from '@ionic/vue'
import { pencilOutline } from 'ionicons/icons'
import { alertController, IonBackButton, IonButton, IonCheckbox, IonContent, IonHeader, IonIcon, IonItem, IonLabel, IonList, IonListHeader, IonPage, IonTitle, IonToolbar, modalController } from '@ionic/vue'
import { pencilOutline, trashOutline } from 'ionicons/icons'
import { parseCsv, jsonToCsv, showToast } from '@/utils';
import { translate } from "@/i18n";
import logger from '@/logger';
import { DateTime } from 'luxon';
import { useRouter } from 'vue-router';
import { UploadService } from '@/services/UploadService';
import CustomFieldModal from '@/components/CustomFieldModal.vue'
export default defineComponent({
name: 'UploadImportOrders',
Expand All @@ -67,43 +78,66 @@ export default defineComponent({
},
data() {
return {
file: {} as any,
content: [] as any,
fieldMapping: {} as any,
fileColumns: [] as Array<string>,
dataColumns: [] as Array<string>,
selectedData: {} as any,
isFieldClicked: false
isFieldClicked: false,
customFields: {} as any
}
},
computed: {
...mapGetters({
currentFacility: 'user/getCurrentFacility'
})
},
ionViewDidEnter() {
// TODO: make api call to get the CSV file, instead of upload file option
this.file = {}
async ionViewDidEnter() {
this.content = []
await this.fetchPackedOrders();
},
methods: {
async parse(event: any) {
const file = event.target.files[0];
async fetchPackedOrders() {
// TODO: need to set a timeout, as when the orders size gets big then the api might take long time to return the information
const payload = {
params: {
configId: 'MDM_PACKED_SHIPMENT',
mimeTypeId: 'application/octet',
facilityId: this.currentFacility.facilityId
}
}
try {
if (file) {
this.content = await parseCsv(file).then(res => res);
// get the column names from the file
this.fileColumns = Object.keys(this.content[0]);
// generate default mappings for the columns
this.fieldMapping = this.fileColumns.reduce((fieldMapping: any, field: string) => {
fieldMapping[field] = field
return fieldMapping;
}, {})
const resp = await UploadService.fetchPackedOrders(payload);
if(resp.status == 200 && resp.data) {
await this.parse(resp.data)
} else {
logger.error("No file upload. Please try again");
throw resp.data
}
} catch (err) {
showToast(translate('Failed to get packed orders information'))
logger.error('Failed to get packed orders', err)
}
},
async parse(data: any) {
try {
this.content = await parseCsv(data).then(res => res);
// get the column names from the data
this.dataColumns = Object.keys(this.content[0]);
// generate default mappings for the columns
this.fieldMapping = this.dataColumns.reduce((fieldMapping: any, field: string) => {
// check to not add the field for which the key is not available, as when fetching the data we are getting an empty key
if(!field) {
return fieldMapping;
}
fieldMapping[field] = field
return fieldMapping;
}, {})
} catch {
this.content = []
logger.error("Please upload a valid csv to continue");
logger.error("Failed to parse the data");
}
},
async addCustomLabel(field: any) {
Expand Down Expand Up @@ -166,6 +200,11 @@ export default defineComponent({
}, {}))
})
// adding custom fields in the data
Object.keys(this.customFields).map((field: any) => {
downloadData.map((data: any) => data[field] = this.customFields[field])
})
const alert = await alertController.create({
header: this.$t("Download packed orders"),
message: this.$t("Make sure all the labels provided are correct."),
Expand All @@ -185,13 +224,30 @@ export default defineComponent({
},
selectAll() {
this.selectedData = JSON.parse(JSON.stringify(this.fieldMapping))
},
async addCustomField() {
const customFieldModal = await modalController.create({
component: CustomFieldModal
});
customFieldModal.onDidDismiss().then((result) => {
if(result.data && result.data.value) {
this.customFields[result.data.value.key] = result.data.value.value
}
})
return customFieldModal.present();
},
removeCustomField(key: any) {
delete this.customFields[key];
}
},
setup() {
const router = useRouter();
return {
pencilOutline,
trashOutline,
router
}
}
Expand Down

0 comments on commit fa9fd36

Please sign in to comment.