From 0b6d071fdc2e47e8a6e85d93f44805f5dcd86207 Mon Sep 17 00:00:00 2001 From: gopikrishnan13 Date: Wed, 25 Sep 2024 17:42:51 +0530 Subject: [PATCH 1/3] feat: Rework preserve last visited tab --- .../src/composables/useActiveTabManager.js | 68 +++++++++++++++++++ frontend/src/pages/Deal.vue | 4 +- frontend/src/pages/Lead.vue | 5 +- 3 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 frontend/src/composables/useActiveTabManager.js diff --git a/frontend/src/composables/useActiveTabManager.js b/frontend/src/composables/useActiveTabManager.js new file mode 100644 index 00000000..9f99306b --- /dev/null +++ b/frontend/src/composables/useActiveTabManager.js @@ -0,0 +1,68 @@ +import { ref, watch } from 'vue'; + +// Debounce function to delay updates +function debounce(fn, delay) { + let timeout; + return (...args) => { + clearTimeout(timeout); + timeout = setTimeout(() => fn(...args), delay); + }; +} + +export function useActiveTabManager(tabs, storageKey) { + + const preserveLastVisitedTab = debounce((tabName) => { + localStorage.setItem(storageKey, tabName.toLowerCase()); + }, 300); + + function setActiveTabInUrl(tabName) { + window.location.hash = '#' + tabName.toLowerCase(); + } + + function getActiveTabFromUrl() { + return window.location.hash.replace('#', ''); + } + + function findTabIndex(tabName){ + return tabs.value.findIndex(tabOptions => tabOptions.name.toLowerCase() === tabName); + } + + function getTabIndex(tabName) { + let index = findTabIndex(tabName) + return index !== -1 ? index : 0; // Default to the first tab if not found + } + + function getActiveTabFromLocalStorage() { + return localStorage.getItem(storageKey); + } + + function getActiveTab() { + let activeTab = getActiveTabFromUrl(); + if(activeTab){ + let index = findTabIndex(activeTab) + if(index !== -1){ + preserveLastVisitedTab(activeTab) + return index + } + return 0 + } + + let lastVisitedTab = getActiveTabFromLocalStorage(); + if(lastVisitedTab){ + setActiveTabInUrl(lastVisitedTab) + return getTabIndex(lastVisitedTab) + } + + return 0 // Default to the first tab if nothing is found + } + + const tabIndex = ref(getActiveTab()); + + watch(tabIndex, (tabIndexValue) => { + let currentTab = tabs.value[tabIndexValue].name; + setActiveTabInUrl(currentTab); + preserveLastVisitedTab(currentTab); + }); + + return { tabIndex }; +} diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index c9ef4fbb..363cc179 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -354,6 +354,8 @@ import { } from 'frappe-ui' import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue' import { useRoute, useRouter } from 'vue-router' +import {useActiveTabManager} from '@/composables/useActiveTabManager' + const { $dialog, $socket, makeCall } = globalStore() const { statusOptions, getDealStatus } = statusesStore() @@ -513,7 +515,6 @@ usePageMeta(() => { } }) -const tabIndex = ref(0) const tabs = computed(() => { let tabOptions = [ { @@ -556,6 +557,7 @@ const tabs = computed(() => { ] return tabOptions.filter((tab) => (tab.condition ? tab.condition() : true)) }) +const { tabIndex } = useActiveTabManager(tabs, 'lastDealTab') const fieldsLayout = createResource({ url: 'crm.api.doc.get_sidebar_fields', diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index 25fedfd5..43c50441 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -330,6 +330,7 @@ import { } from 'frappe-ui' import { ref, computed, onMounted, watch } from 'vue' import { useRouter, useRoute } from 'vue-router' +import {useActiveTabManager} from '@/composables/useActiveTabManager' const { $dialog, $socket, makeCall } = globalStore() const { getContactByName, contacts } = contactsStore() @@ -463,8 +464,6 @@ usePageMeta(() => { } }) -const tabIndex = ref(0) - const tabs = computed(() => { let tabOptions = [ { @@ -508,6 +507,8 @@ const tabs = computed(() => { return tabOptions.filter((tab) => (tab.condition ? tab.condition() : true)) }) +const { tabIndex } = useActiveTabManager(tabs, 'lastLeadTab') + watch(tabs, (value) => { if (value && route.params.tabName) { let index = value.findIndex( From 97af42fad10684e313ebb61f50507feb6dfa3810 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Fri, 27 Sep 2024 22:08:48 +0530 Subject: [PATCH 2/3] chore: used debounce function from vueuse and useStorage instead of localStorage --- .../src/composables/useActiveTabManager.js | 57 +++++++++---------- frontend/src/pages/Deal.vue | 2 +- frontend/src/pages/Lead.vue | 2 +- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/frontend/src/composables/useActiveTabManager.js b/frontend/src/composables/useActiveTabManager.js index 9f99306b..3a134869 100644 --- a/frontend/src/composables/useActiveTabManager.js +++ b/frontend/src/composables/useActiveTabManager.js @@ -1,54 +1,49 @@ -import { ref, watch } from 'vue'; - -// Debounce function to delay updates -function debounce(fn, delay) { - let timeout; - return (...args) => { - clearTimeout(timeout); - timeout = setTimeout(() => fn(...args), delay); - }; -} +import { ref, watch } from 'vue' +import { useDebounceFn, useStorage } from '@vueuse/core' export function useActiveTabManager(tabs, storageKey) { - - const preserveLastVisitedTab = debounce((tabName) => { - localStorage.setItem(storageKey, tabName.toLowerCase()); - }, 300); + const activieTab = useStorage(storageKey, 'activity') + + const preserveLastVisitedTab = useDebounceFn((tabName) => { + activieTab.value = tabName.toLowerCase() + }, 300) function setActiveTabInUrl(tabName) { - window.location.hash = '#' + tabName.toLowerCase(); + window.location.hash = '#' + tabName.toLowerCase() } function getActiveTabFromUrl() { - return window.location.hash.replace('#', ''); + return window.location.hash.replace('#', '') } - function findTabIndex(tabName){ - return tabs.value.findIndex(tabOptions => tabOptions.name.toLowerCase() === tabName); + function findTabIndex(tabName) { + return tabs.value.findIndex( + (tabOptions) => tabOptions.name.toLowerCase() === tabName, + ) } function getTabIndex(tabName) { let index = findTabIndex(tabName) - return index !== -1 ? index : 0; // Default to the first tab if not found + return index !== -1 ? index : 0 // Default to the first tab if not found } function getActiveTabFromLocalStorage() { - return localStorage.getItem(storageKey); + return activieTab.value } function getActiveTab() { - let activeTab = getActiveTabFromUrl(); - if(activeTab){ + let activeTab = getActiveTabFromUrl() + if (activeTab) { let index = findTabIndex(activeTab) - if(index !== -1){ + if (index !== -1) { preserveLastVisitedTab(activeTab) return index } return 0 } - let lastVisitedTab = getActiveTabFromLocalStorage(); - if(lastVisitedTab){ + let lastVisitedTab = getActiveTabFromLocalStorage() + if (lastVisitedTab) { setActiveTabInUrl(lastVisitedTab) return getTabIndex(lastVisitedTab) } @@ -56,13 +51,13 @@ export function useActiveTabManager(tabs, storageKey) { return 0 // Default to the first tab if nothing is found } - const tabIndex = ref(getActiveTab()); + const tabIndex = ref(getActiveTab()) watch(tabIndex, (tabIndexValue) => { - let currentTab = tabs.value[tabIndexValue].name; - setActiveTabInUrl(currentTab); - preserveLastVisitedTab(currentTab); - }); + let currentTab = tabs.value[tabIndexValue].name + setActiveTabInUrl(currentTab) + preserveLastVisitedTab(currentTab) + }) - return { tabIndex }; + return { tabIndex } } diff --git a/frontend/src/pages/Deal.vue b/frontend/src/pages/Deal.vue index 363cc179..9c73e7be 100644 --- a/frontend/src/pages/Deal.vue +++ b/frontend/src/pages/Deal.vue @@ -354,7 +354,7 @@ import { } from 'frappe-ui' import { ref, computed, h, onMounted, onBeforeUnmount } from 'vue' import { useRoute, useRouter } from 'vue-router' -import {useActiveTabManager} from '@/composables/useActiveTabManager' +import { useActiveTabManager } from '@/composables/useActiveTabManager' const { $dialog, $socket, makeCall } = globalStore() diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index 43c50441..03e10670 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -330,7 +330,7 @@ import { } from 'frappe-ui' import { ref, computed, onMounted, watch } from 'vue' import { useRouter, useRoute } from 'vue-router' -import {useActiveTabManager} from '@/composables/useActiveTabManager' +import { useActiveTabManager } from '@/composables/useActiveTabManager' const { $dialog, $socket, makeCall } = globalStore() const { getContactByName, contacts } = contactsStore() From 028ad81d7f875c8efeb530d02000d6ef556a0b3c Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Fri, 27 Sep 2024 22:36:30 +0530 Subject: [PATCH 3/3] fix: also watch hash change and change tab accordingly --- .../src/composables/useActiveTabManager.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/frontend/src/composables/useActiveTabManager.js b/frontend/src/composables/useActiveTabManager.js index 3a134869..5b9cd484 100644 --- a/frontend/src/composables/useActiveTabManager.js +++ b/frontend/src/composables/useActiveTabManager.js @@ -1,8 +1,10 @@ import { ref, watch } from 'vue' +import { useRoute } from 'vue-router' import { useDebounceFn, useStorage } from '@vueuse/core' export function useActiveTabManager(tabs, storageKey) { const activieTab = useStorage(storageKey, 'activity') + const route = useRoute() const preserveLastVisitedTab = useDebounceFn((tabName) => { activieTab.value = tabName.toLowerCase() @@ -13,7 +15,7 @@ export function useActiveTabManager(tabs, storageKey) { } function getActiveTabFromUrl() { - return window.location.hash.replace('#', '') + return route.hash.replace('#', '') } function findTabIndex(tabName) { @@ -59,5 +61,20 @@ export function useActiveTabManager(tabs, storageKey) { preserveLastVisitedTab(currentTab) }) + watch( + () => route.hash, + (tabValue) => { + if (!tabValue) return + + let tabName = tabValue.replace('#', '') + let index = findTabIndex(tabName) + if (index === -1) index = 0 + + let currentTab = tabs.value[index].name + preserveLastVisitedTab(currentTab) + tabIndex.value = index + }, + ) + return { tabIndex } }