Skip to content

Commit

Permalink
Merge pull request #60 from ymaheshwari1/feat/timeZone
Browse files Browse the repository at this point in the history
Implemented: support to update the app's timeZone and display the next runTime for the schedule
  • Loading branch information
ymaheshwari1 authored Feb 1, 2024
2 parents f891e68 + c95de16 commit b486fe8
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 178 deletions.
10 changes: 9 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref } from "vue";
import { IonApp, IonRouterOutlet, loadingController } from "@ionic/vue";
import emitter from "@/event-bus"
import { Settings } from 'luxon'
import store from "./store";
const loader = ref(null) as any
const userProfile = computed(() => store.getters["user/getUserProfile"])
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
Expand Down Expand Up @@ -42,6 +45,11 @@ onMounted(async () => {
});
emitter.on("presentLoader", presentLoader);
emitter.on("dismissLoader", dismissLoader);
if (userProfile.value) {
// Luxon timezone should be set with the user's selected timezone
userProfile.value.timeZone && (Settings.defaultZone = userProfile.value.timeZone);
}
})
onUnmounted(() => {
Expand Down
118 changes: 118 additions & 0 deletions src/components/TimezoneModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon :icon="close" />
</ion-button>
</ion-buttons>
<ion-title>{{ $t("Select time zone") }}</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar @ionFocus="selectSearchBarText($event)" :placeholder="$t('Search time zones')" v-model="queryString" v-on:keyup.enter="queryString = $event.target.value; findTimeZone()" />
</ion-toolbar>
</ion-header>

<ion-content class="ion-padding">
<!-- Empty state -->
<div class="empty-state" v-if="filteredTimeZones.length === 0">
<p>{{ $t("No time zone found")}}</p>
</div>

<!-- Timezones -->
<div v-else>
<ion-list>
<ion-radio-group value="rd" v-model="timeZoneId">
<ion-item :key="timeZone.id" v-for="timeZone in filteredTimeZones">
<ion-radio label-placement="end" justify="start" :value="timeZone.id">{{ timeZone.label }} ({{ timeZone.id }})</ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
</div>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button :disabled="!timeZoneId" @click="setUserTimeZone">
<ion-icon :icon="save" />
</ion-fab-button>
</ion-fab>
</ion-content>
</template>

<script setup lang="ts">
import {
IonButtons,
IonButton,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonItem,
IonIcon,
IonRadioGroup,
IonRadio,
IonList,
IonSearchbar,
IonTitle,
IonToolbar,
modalController,
} from "@ionic/vue";
import { onBeforeMount, ref } from "vue";
import { close, save } from "ionicons/icons";
import { useStore } from "@/store";
import { UserService } from "@/services/UserService";
import { hasError } from "@/utils"
import { DateTime } from "luxon";
const store = useStore();
let queryString = ref("")
let filteredTimeZones = ref([])
let timeZones = ref([])
let timeZoneId = ref("")
onBeforeMount(() => {
getAvailableTimeZones();
})
function closeModal() {
modalController.dismiss({ dismissed: true });
}
function escapeRegExp(text: string) {
//TODO Handle it in a better way
// Currently when the user types special character as it part of Regex expressions it breaks the code
// so removed the characters for now
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}
function findTimeZone() {
const regularExp = new RegExp(`${escapeRegExp(queryString.value)}`, "i");
filteredTimeZones.value = timeZones.value.filter((timeZone: any) => {
return regularExp.test(timeZone.id) || regularExp.test(timeZone.label);
});
}
function getAvailableTimeZones() {
UserService.getAvailableTimeZones().then((resp: any) => {
if (resp.status === 200 && !hasError(resp)) {
timeZones.value = resp.data.timeZones.filter((timeZone: any) => {
return DateTime.local().setZone(timeZone.id).isValid;
});
findTimeZone();
}
})
}
function selectSearchBarText(event: any) {
event.target.getInputElement().then((element: any) => {
element.select();
})
}
async function setUserTimeZone() {
return store.dispatch("user/setUserTimeZone", {
"tzId": timeZoneId.value
}).then(() => {
closeModal()
})
}
</script>
2 changes: 1 addition & 1 deletion src/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const getEComStores = async (token: any): Promise<any> => {

const getAvailableTimeZones = async (): Promise <any> => {
return api({
url: "getAvailableTimeZones",
url: "user/getAvailableTimeZones",
method: "get",
cache: true
});
Expand Down
16 changes: 11 additions & 5 deletions src/store/modules/user/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { hasError, showToast } from "@/utils"
import { translate } from "@/i18n"
import logger from "@/logger"
import emitter from "@/event-bus"
import { Settings } from "luxon"

const actions: ActionTree<UserState, RootState> = {

Expand All @@ -28,6 +29,10 @@ const actions: ActionTree<UserState, RootState> = {
// TODO: fetch only associated product stores for user, currently api does not support this
userProfile.stores = await UserService.getEComStores(token);

if (userProfile.timeZone) {
Settings.defaultZone = userProfile.timeZone;
}

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] : {});
Expand Down Expand Up @@ -55,12 +60,13 @@ const actions: ActionTree<UserState, RootState> = {
* Update user timeZone
*/
async setUserTimeZone({ state, commit }, payload) {
const resp = await UserService.setUserTimeZone(payload)
if (resp.status === 200 && !hasError(resp)) {
const current: any = state.current;
current.userTimeZone = payload.tzId;
const current: any = state.current;
// TODO: add support to change the user time on server, currently api to update user is not available
if(current.timeZone !== payload.tzId) {
current.timeZone = payload.tzId;
commit(types.USER_INFO_UPDATED, current);
showToast(translate("Time zone updated successfully"));
Settings.defaultZone = current.timeZone;
showToast("Time zone updated successfully");
}
},

Expand Down
6 changes: 5 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,8 @@ const getTime = (time: any) => {
return time ? DateTime.fromMillis(time).toLocaleString(DateTime.DATETIME_MED) : '-';
}

export { getTime, showToast, hasError , parseCsv , jsonToCsv, JsonToCsvOption, sortSequence }
const getTimeFromSeconds = (time: any) => {
return time ? DateTime.fromSeconds(time).toLocaleString(DateTime.DATETIME_MED) : '-';
}

export { getTime, getTimeFromSeconds, showToast, hasError , parseCsv , jsonToCsv, JsonToCsvOption, sortSequence }
9 changes: 7 additions & 2 deletions src/views/BrokeringRoute.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
</ion-button>
</ion-item>
<ion-item>
<ion-icon slot="start" :icon="timeOutline"/>
<ion-label>{{ "Run time" }}</ion-label>
<ion-label slot="end">{{ getTimeFromSeconds(job.nextExecutionDateTime) }}</ion-label>
</ion-item>
<ion-item lines="none">
<ion-icon slot="start" :icon="timerOutline"/>
<ion-select label="Schedule" interface="popover" :placeholder="$t('Select')" :value="job.cronExpression" @ionChange="updateCronExpression($event)">
<ion-select-option v-for="(expression, description) in cronExpressions" :key="expression" :value="expression">{{ description }}</ion-select-option>
Expand Down Expand Up @@ -118,7 +123,7 @@

<script setup lang="ts">
import { IonBadge, IonButtons, IonButton, IonCard, IonCardHeader, IonCardTitle, IonChip, IonContent, IonFab, IonFabButton, IonHeader, IonIcon, IonItem, IonLabel, IonList, IonListHeader, IonPage, IonReorder, IonReorderGroup, IonSelect, IonSelectOption, IonTextarea, IonTitle, IonToolbar, alertController, modalController, onIonViewWillEnter } from "@ionic/vue";
import { addCircleOutline, archiveOutline, arrowBackOutline, refreshOutline, reorderTwoOutline, saveOutline, timerOutline } from "ionicons/icons"
import { addCircleOutline, archiveOutline, arrowBackOutline, refreshOutline, reorderTwoOutline, saveOutline, timeOutline, timerOutline } from "ionicons/icons"
import { onBeforeRouteLeave, useRouter } from "vue-router";
import { useStore } from "vuex";
import { computed, defineProps, ref } from "vue";
Expand All @@ -127,7 +132,7 @@ import ArchivedRoutingModal from "@/components/ArchivedRoutingModal.vue"
import { OrderRoutingService } from "@/services/RoutingService";
import logger from "@/logger";
import { DateTime } from "luxon";
import { hasError, getTime, showToast, sortSequence } from "@/utils";
import { hasError, getTime, getTimeFromSeconds, showToast, sortSequence } from "@/utils";
import emitter from "@/event-bus";
const router = useRouter();
Expand Down
6 changes: 3 additions & 3 deletions src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@
{{ "The timezone you select is used to ensure automations you schedule are always accurate to the time you select." }}
</ion-card-content>
<ion-item lines="none">
<ion-label> {{ userProfile && userProfile.timeZone ? userProfile.timeZone : "-" }} </ion-label>
<ion-button disabled @click="changeTimeZone()" slot="end" fill="outline" color="dark">{{ "Change" }}</ion-button>
<ion-label>{{ userProfile && userProfile.timeZone ? userProfile.timeZone : "-" }}</ion-label>
<ion-button @click="changeTimeZone()" slot="end" fill="outline" color="dark">{{ "Change" }}</ion-button>
</ion-item>
</ion-card>
</section>
Expand All @@ -83,7 +83,7 @@ import { IonAvatar, IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSu
import { computed, onMounted, ref } from "vue";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import TimeZoneModal from "@/views/TimezoneModal.vue";
import TimeZoneModal from "@/components/TimezoneModal.vue";
import Image from "@/components/Image.vue"
import { DateTime } from "luxon";
Expand Down
Loading

0 comments on commit b486fe8

Please sign in to comment.