Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jardakotesovec committed Apr 8, 2024
1 parent 703a3f9 commit e96e9db
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 22 deletions.
20 changes: 15 additions & 5 deletions src/components/Modal/AjaxModalWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
<div ref="contentDiv" @click="catchInsideClick"></div>
</template>
<script setup>
/**
* Component to mimick part of AjaxModalHandler which fetches the html content from given url
* and presents it to the user
*/
import {ref, onMounted, inject, defineProps, onBeforeUnmount} from 'vue';
import {useFetch} from '@/composables/useFetch';
const {options} = defineProps({
/**
* Following the object used within AjaxModalHandler
* Particularly important is `url` and `modalHandler`
*/
options: {
type: Object,
default: () => {},
Expand All @@ -16,10 +24,13 @@ const contentDiv = ref(null);
// eslint-disable-next-line no-unused-vars
const pkp = window.pkp;
// Fetches html content from legacy endpoints
const {data: modalData, fetch: fetchAssignParticipantPage} = useFetch(
options.url,
);
// Legacy modal has mechanism where it needs to check with form whether it can close
// Mimicking this behaviour
const registerCloseCallback = inject('registerCloseCallback');
registerCloseCallback(() => {
// eslint-disable-next-line no-unused-vars
Expand Down Expand Up @@ -49,6 +60,10 @@ function catchInsideClick(e) {
}
}
/** The wrapping div element for modal is still created by legacy modal handler, but its not mounted
* only used to keep the legacy event communication going from inside modal to the outside (often its grid component)
*
*/
function passToHandlerElement(...args) {
if (options.modalHandler) {
options.modalHandler.getHtmlElement().trigger(...args);
Expand All @@ -60,7 +75,6 @@ function passToHandlerElement(...args) {
onMounted(async () => {
await fetchAssignParticipantPage();
if (modalData.value) {
// TODO CONSIDER REMOVE BINDS ON UNMOUNT
$(contentDiv.value).html(modalData.value.content);
$(contentDiv.value).bind('formSubmitted', passToHandlerElement);
$(contentDiv.value).bind('wizardClose', passToHandlerElement);
Expand Down Expand Up @@ -90,10 +104,6 @@ onBeforeUnmount(() => {
$(contentDiv.value).unbind('ajaxHtmlError', passToHandlerElement);
$(contentDiv.value).unbind('modalFinished', passToHandlerElement);
// Publish some otherwise private events triggered
// by nested widgets so that they can be handled by
// the element that opened the modal.
$(contentDiv.value).unbind('redirectRequested', passToHandlerElement);
$(contentDiv.value).unbind('dataChanged', passToHandlerElement);
$(contentDiv.value).unbind('updateHeader', passToHandlerElement);
Expand Down
2 changes: 2 additions & 0 deletions src/components/Modal/ModalManager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const LegacyModals = {LegacyAjax};
const modalStore = useModalStore();
const {sideModal1, sideModal2} = storeToRefs(useModalStore());
// Component can be either string or actual vue component
const component1 = computed(() => {
if (!sideModal1.value?.component) {
return null;
Expand Down
41 changes: 24 additions & 17 deletions src/stores/modalStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,32 +54,28 @@ export const useModalStore = defineStore('modal', () => {
/**
* Side Modal Level
*
* To recognise how many side modals is opened to adjust styling
*/
const modalLevel = ref(0);
function increaseModalLevel() {
modalLevel.value++;
}

function decreaseModalLevel() {
modalLevel.value--;
}

// { modalId, props, opened, component}
// object structure: { modalId, props, opened, component}
const sideModal1 = ref(null);
// { modalId, props, opened, component}

// object structure: { modalId, props, opened, component}
const sideModal2 = ref(null);

// creating unique modalId to ensure correct modal is being closed
let modalIdCounter = 1;

function openSideModal(_component, props = {}, _modalId = null) {
modalIdCounter++;
let component = null;
if (typeof _component !== 'string') {
// avoid making vue component object reactive which would be unnecessary performance hit
component = markRaw(_component);
} else {
component = _component;
}

// modalId is either calculated internally or its comming from the legacy handler if its legacy modal
const modalId = _modalId ? _modalId : modalIdCounter;

const opts = {
Expand All @@ -89,9 +85,14 @@ export const useModalStore = defineStore('modal', () => {
props,
};

// At this point we support two levels of side modals (we might need to extend it to 3 at somep oint)
//
// toBeClosed is used for edge case when modal close is delayed in 'onFormSuccess_' in ModalHandler to indicate
// form successfully submitted, which does not work well in scenario when follow-up modal is immediatelly opened and
// is supposed to replace it (selecting issue & publishing article flow)
if (!sideModal1.value?.opened || sideModal1.value?.toBeClosed) {
sideModal1.value = opts;
} else if (!sideModal2.value?.opened) {
} else if (!sideModal2.value?.opened || sideModal2.value?.toBeClosed) {
sideModal2.value = opts;
}
}
Expand All @@ -106,12 +107,17 @@ export const useModalStore = defineStore('modal', () => {
modalToClose = sideModal2;
}
modalToClose.value.opened = false;

// To keep the side modal animation nice, it needs to keep the component&props around for bit longer
setTimeout(() => {
if (!modalToClose.value.opened) {
modalToClose.value = null;
}
}, 300);

// When closing legacy modal its always important to do legacy handler clean up.
// Therefore it depends if the close request is coming from the legacy handler (therefore the clean up will be done as part of that)
// or whether close is triggered by clicking on close button or outside of the modal, which needs to trigger handler modalClose for all the clean up
if (
triggerLegacyCloseHandler &&
modalToClose.value?.props?.options?.modalHandler
Expand All @@ -120,7 +126,7 @@ export const useModalStore = defineStore('modal', () => {
}
}

/** POC, its disabled for now, it will handle legacy modals in future to improve their accessibility */
// Listener for open modal requests coming from legacy handler.
pkp.eventBus.$on('open-modal-vue', (_args) => {
openSideModal(
_args.component,
Expand All @@ -131,6 +137,8 @@ export const useModalStore = defineStore('modal', () => {
);
});

// For special case when the closing modal is delayed, but we know it will be closed.
// Therefore any quick subsequent modal open should replace this one rather than creating second level
pkp.eventBus.$on('close-modal-vue-soon', (_args) => {
const modalId = _args.modalId;
if (sideModal1.value?.modalId === modalId) {
Expand All @@ -141,14 +149,17 @@ export const useModalStore = defineStore('modal', () => {
}
});

// Listener for close modal requests coming from legacy handler.
pkp.eventBus.$on('close-modal-vue', (_args) => {
closeSideModal(false, _args.modalId);
});

// Listener for open dialog modals coming from legacy handler.
pkp.eventBus.$on('open-dialog-vue', (_args) => {
openDialog(_args.dialogProps);
});

// Listener for close dialog modals coming from legacy handler.
pkp.eventBus.$on('close-dialog-vue', (_args) => {
closeDialog(false);
});
Expand All @@ -164,10 +175,6 @@ export const useModalStore = defineStore('modal', () => {
openDialogNetworkError,
openDialog,
closeDialog,
/** side modal level */
modalLevel,
increaseModalLevel,
decreaseModalLevel,
openSideModal,
closeSideModal,
sideModal1,
Expand Down

0 comments on commit e96e9db

Please sign in to comment.