From f1801089978dff3c9c54d8cd8eb90df72e00b209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarda=20Kot=C4=9B=C5=A1ovec?= Date: Thu, 27 Feb 2025 17:56:27 +0100 Subject: [PATCH] pkp/pkp-lib#10969 Address breaking change in vue3, where inject in pinia stores does not provide current component provides --- src/composables/useDataChanged.js | 14 ++++++--- src/composables/useFetch.js | 6 ++-- .../modals/workflowLogResponseModalStore.js | 8 +++-- ...kflowChangeSubmissionLanguageModalStore.js | 9 ++++-- src/pages/workflow/workflowStore.js | 5 ++-- src/utils/defineComponentStore.js | 30 ++++++++++++++++++- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/composables/useDataChanged.js b/src/composables/useDataChanged.js index a32223f99..d45a250eb 100644 --- a/src/composables/useDataChanged.js +++ b/src/composables/useDataChanged.js @@ -1,17 +1,23 @@ -import {inject, onUnmounted} from 'vue'; +import {onUnmounted} from 'vue'; +import {injectFromCurrentInstance} from '@/utils/defineComponentStore'; + export function useDataChanged(callback) { if (callback) { - const registerDataChangeCallback = inject('registerDataChangeCallback'); + const registerDataChangeCallback = injectFromCurrentInstance( + 'registerDataChangeCallback', + ); registerDataChangeCallback(callback); - const unRegisterDataChangeCallback = inject('unRegisterDataChangeCallback'); + const unRegisterDataChangeCallback = injectFromCurrentInstance( + 'unRegisterDataChangeCallback', + ); onUnmounted(() => { unRegisterDataChangeCallback(callback); }); } - const triggerDataChange = inject('triggerDataChange'); + const triggerDataChange = injectFromCurrentInstance('triggerDataChange'); return {triggerDataChange}; } diff --git a/src/composables/useFetch.js b/src/composables/useFetch.js index a71d17135..01a3690df 100644 --- a/src/composables/useFetch.js +++ b/src/composables/useFetch.js @@ -1,8 +1,8 @@ -import {ref, unref, inject} from 'vue'; +import {ref, unref} from 'vue'; import {ofetch, createFetch} from 'ofetch'; import {useModalStore} from '@/stores/modalStore'; import {useProgressStore} from '@/stores/progressStore'; - +import {injectFromCurrentInstance} from '@/utils/defineComponentStore'; import {useDebounceFn} from '@vueuse/core'; let ofetchInstance = ofetch; @@ -98,7 +98,7 @@ export function useFetch(url, options = {}) { let lastRequestController = null; - const modalLevel = inject('modalLevel'); + const modalLevel = injectFromCurrentInstance('modalLevel'); const screenName = modalLevel?.value ? `modal_${modalLevel.value}` : 'base'; const progressStore = useProgressStore(); diff --git a/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js b/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js index 5ba8fcce9..e60fb3fdb 100644 --- a/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js +++ b/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js @@ -1,11 +1,13 @@ -import {inject} from 'vue'; -import {defineComponentStore} from '@/utils/defineComponentStore'; +import { + defineComponentStore, + injectFromCurrentInstance, +} from '@/utils/defineComponentStore'; import {useForm} from '@/composables/useForm'; export const useWorkflowLogResponseModalStore = defineComponentStore( 'workflowLogResponseModal', (props) => { - const closeModal = inject('closeModal'); + const closeModal = injectFromCurrentInstance('closeModal'); const {set: updateForm, form} = useForm(props.logResponseForm); function formSuccess() { diff --git a/src/pages/workflow/modals/workflowChangeSubmissionLanguageModalStore.js b/src/pages/workflow/modals/workflowChangeSubmissionLanguageModalStore.js index 447095c6f..b9fdd565d 100644 --- a/src/pages/workflow/modals/workflowChangeSubmissionLanguageModalStore.js +++ b/src/pages/workflow/modals/workflowChangeSubmissionLanguageModalStore.js @@ -1,5 +1,8 @@ -import {inject, ref, computed, watch} from 'vue'; -import {defineComponentStore} from '@/utils/defineComponentStore'; +import {ref, computed, watch} from 'vue'; +import { + defineComponentStore, + injectFromCurrentInstance, +} from '@/utils/defineComponentStore'; import {useUrl} from '@/composables/useUrl'; import {useFetch} from '@/composables/useFetch'; import {useForm} from '@/composables/useForm'; @@ -62,7 +65,7 @@ export const useWorkflowChangeSubmissionLanguageModalStore = // Get publication props getData(); - const closeModal = inject('closeModal'); + const closeModal = injectFromCurrentInstance('closeModal'); /** * Functions diff --git a/src/pages/workflow/workflowStore.js b/src/pages/workflow/workflowStore.js index 597875e13..1ecfbe08a 100644 --- a/src/pages/workflow/workflowStore.js +++ b/src/pages/workflow/workflowStore.js @@ -1,4 +1,5 @@ -import {computed, inject} from 'vue'; +import {computed} from 'vue'; +import {injectFromCurrentInstance} from '@/utils/defineComponentStore'; import {defineComponentStore} from '@/utils/defineComponentStore'; import { @@ -33,7 +34,7 @@ export const useWorkflowStore = defineComponentStore( /** * Action to close the workflow from inside * */ - const closeWorkflowModal = inject('closeModal'); + const closeWorkflowModal = injectFromCurrentInstance('closeModal'); /** * Submission & Publication diff --git a/src/utils/defineComponentStore.js b/src/utils/defineComponentStore.js index 35ccd9b4d..3a8501419 100644 --- a/src/utils/defineComponentStore.js +++ b/src/utils/defineComponentStore.js @@ -1,5 +1,11 @@ import {defineStore, getActivePinia} from 'pinia'; -import {onMounted, onBeforeUnmount, provide, inject} from 'vue'; +import { + onMounted, + onBeforeUnmount, + provide, + inject, + getCurrentInstance, +} from 'vue'; let storesMap = {}; @@ -7,6 +13,28 @@ export function getComponentStoreByName(storeName) { return storesMap[storeName].useStore(); } +/** + * This is replacement for `inject` method offered from vue, to be used inside pinia "component stores" + * Component stores follow component life cycle for great convinience, but this is not common + * use case. Pinia stores are mostly used as global stores independent from components. + * + * With recent change in vue (https://github.com/vuejs/core/issues/11488), + * inject used within pinia defaults to injecting from root app component provides, instead + * of current instance. Therefore using custom implementation to get current instance provides. + * + * + */ +export function injectFromCurrentInstance(name) { + const instance = getCurrentInstance(); + const provides = instance + ? instance.parent == null + ? instance.vnode.appContext && instance.vnode.appContext.provides + : instance.parent.provides + : void 0; + + return provides?.[name]; +} + export function defineComponentStore( _storeName, setupFn,