From 4fe0a59f7e1bbf4d797347b1370d2d14d8dc4fa7 Mon Sep 17 00:00:00 2001 From: RobA Date: Sat, 18 May 2024 07:28:41 -0300 Subject: [PATCH 01/17] logresponse modal made in vue --- src/components/Modal/AjaxModalWrapper.vue | 10 +- src/components/Modal/ModalManager.vue | 7 +- .../Modal/SideModalBodyLegacyAjax.vue | 24 ++- .../workflow/WorkflowLogResponseForModal.vue | 174 ++++++++++++++++++ 4 files changed, 197 insertions(+), 18 deletions(-) create mode 100644 src/pages/workflow/WorkflowLogResponseForModal.vue diff --git a/src/components/Modal/AjaxModalWrapper.vue b/src/components/Modal/AjaxModalWrapper.vue index 50a751d5c..baf59ec3a 100644 --- a/src/components/Modal/AjaxModalWrapper.vue +++ b/src/components/Modal/AjaxModalWrapper.vue @@ -9,12 +9,12 @@ import {ref, onMounted, inject, defineProps, onBeforeUnmount} from 'vue'; import {useFetch} from '@/composables/useFetch'; -const {options} = defineProps({ +const {legacyOptions} = defineProps({ /** * Following the object used within AjaxModalHandler * Particularly important is `url` and `modalHandler` */ - options: { + legacyOptions: { type: Object, default: () => {}, }, @@ -26,7 +26,7 @@ const pkp = window.pkp; // Fetches html content from legacy endpoints const {data: modalData, fetch: fetchAssignParticipantPage} = useFetch( - options.url, + legacyOptions.url, ); // Legacy modal has mechanism where it needs to check with form whether it can close @@ -65,8 +65,8 @@ function catchInsideClick(e) { * */ function passToHandlerElement(...args) { - if (options.modalHandler) { - options.modalHandler.getHtmlElement().trigger(...args); + if (legacyOptions.modalHandler) { + legacyOptions.modalHandler.getHtmlElement().trigger(...args); } return; diff --git a/src/components/Modal/ModalManager.vue b/src/components/Modal/ModalManager.vue index b28aee6eb..35f2c7d46 100644 --- a/src/components/Modal/ModalManager.vue +++ b/src/components/Modal/ModalManager.vue @@ -25,8 +25,9 @@ import {storeToRefs} from 'pinia'; import SideModal from '@/components/Modal/SideModal.vue'; import LegacyAjax from '@/components/Modal/SideModalBodyLegacyAjax.vue'; import PkpDialog from '@/components/Modal/Dialog.vue'; +import WorkflowLogResponseForModal from '@/pages/workflow/WorkflowLogResponseForModal.vue'; -const LegacyModals = {LegacyAjax}; +const GlobalModals = {LegacyAjax, WorkflowLogResponseForModal}; const modalStore = useModalStore(); const {sideModal1, sideModal2} = storeToRefs(useModalStore()); @@ -37,7 +38,7 @@ const component1 = computed(() => { return null; } return typeof sideModal1.value.component === 'string' - ? LegacyModals[sideModal1.value.component] + ? GlobalModals[sideModal1.value.component] : sideModal1.value.component; }); @@ -46,7 +47,7 @@ const component2 = computed(() => { return null; } return typeof sideModal2.value.component === 'string' - ? LegacyModals[sideModal2.value.component] + ? GlobalModals[sideModal2.value.component] : sideModal2.value.component; }); diff --git a/src/components/Modal/SideModalBodyLegacyAjax.vue b/src/components/Modal/SideModalBodyLegacyAjax.vue index 08560fbf0..c405d3aa7 100644 --- a/src/components/Modal/SideModalBodyLegacyAjax.vue +++ b/src/components/Modal/SideModalBodyLegacyAjax.vue @@ -1,12 +1,15 @@ diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue new file mode 100644 index 000000000..bdf442bef --- /dev/null +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -0,0 +1,174 @@ + + + + + From 9173b251ef6bbeef42f24db30f5ae083f0757b83 Mon Sep 17 00:00:00 2001 From: RobA Date: Sat, 18 May 2024 16:17:34 -0300 Subject: [PATCH 02/17] modal store prepared to take props --- .../workflow/WorkflowLogResponseForModal.vue | 73 ++++++------------- src/stores/modalStore.js | 31 +++++--- 2 files changed, 44 insertions(+), 60 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue index bdf442bef..a6e18f9c7 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.vue +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -11,11 +11,11 @@
-
+
@@ -83,8 +83,8 @@ export default { required: true } }, - setup(props, {emit}) { - const acceptReview = ref(false); + setup(props) { + const acceptReview = ref(0); const closeModal = inject('closeModal'); const logResponseForm = { @@ -104,8 +104,8 @@ export default { type: 'radio', showWhen: 'options-confirmation', options: { - 0: {value: true, label: t('editor.review.logResponse.form.option.accepted')}, - 1: {value: false, label: t('editor.review.logResponse.form.option.declined')}, + 0: {value: 1, label: t('editor.review.logResponse.form.option.accepted')}, + 1: {value: 0, label: t('editor.review.logResponse.form.option.declined')}, } } @@ -113,53 +113,28 @@ export default { acceptReview.value = value; } - function submit() { - // props.legacyOptions.modalHandler - // .getHtmlElement() - // .trigger('dataChanged', props.reviewAssignmentId); + function submit() { + // props.legacyOptions.modalHandler + // .getHtmlElement() + // .trigger('dataChanged', props.reviewAssignmentId); - $.ajax({ - url: props.url, - type: 'POST', - data: { - acceptReview: acceptReview.value, - csrfToken: pkp.currentUser.csrfToken, - }, - error: this.ajaxErrorCallback, - success(r) { - //SHOW SUCCESS MESSAGE - }, - }); + $.ajax({ + url: props.url, + type: 'POST', + data: { + acceptReview: acceptReview.value, + csrfToken: pkp.currentUser.csrfToken, + }, + // error: this.ajaxErrorCallback, + success(r) { + //SHOW SUCCESS MESSAGE + }, + }); - closeModal(); - } + closeModal(); + } return {submit, change, acceptReview, logResponseForm}; - }, - data() { - return { - form: { - // groupId: 'preferences', - formId: 'default', - isRequired: true, - primaryLocale: this.submissionLocale, - locales: this.journalLocales, - // allErrors: { - // acceptReview: [this.responseRequired], - // }, - name: 'acceptReview', - component: 'field-options', - label: t('editor.review.logResponse.form.detail'), - description: t('editor.review.logResponse.form.subDetail'), - value: {}, - type: 'radio', - showWhen: 'options-confirmation', - options: { - 0: {value: true, label: t('editor.review.logResponse.form.option.accepted')}, - 1: {value: false, label: t('editor.review.logResponse.form.option.declined')}, - } - } - } } }; diff --git a/src/stores/modalStore.js b/src/stores/modalStore.js index c71ef0243..4e4e76413 100644 --- a/src/stores/modalStore.js +++ b/src/stores/modalStore.js @@ -56,7 +56,7 @@ export const useModalStore = defineStore('modal', () => { * */ - // object structure: { modalId, props, opened, component} + // object structure: { modalId, props, opened, component} const sideModal1 = ref(null); // object structure: { modalId, props, opened, component} @@ -65,7 +65,13 @@ export const useModalStore = defineStore('modal', () => { // creating unique modalId to ensure correct modal is being closed let modalIdCounter = 1; - function openSideModal(_component, props = {}, _modalId = null) { + /** + * + * @param {*} _component + * @param {*} props + * @param {*} options - modalId: explicit ID coming from legacy stack, onClose: function to be called after modal is closed + */ + function openSideModal(_component, props = {}, options = {}) { modalIdCounter++; let component = null; if (typeof _component !== 'string') { @@ -76,13 +82,14 @@ export const useModalStore = defineStore('modal', () => { } // modalId is either calculated internally or its comming from the legacy handler if its legacy modal - const modalId = _modalId ? _modalId : modalIdCounter; + const modalId = options?.modalId ? options?.modalId : modalIdCounter; const opts = { modalId, opened: true, component, props, + onClose: options.onClose, }; // At this point we support two levels of side modals @@ -99,11 +106,11 @@ export const useModalStore = defineStore('modal', () => { function closeSideModal(triggerLegacyCloseHandler = true, _modalId) { let modalToClose = null; - if (sideModal1?.value?.modalId === _modalId) { + if (sideModal1?.value?.modalId === _modalId && sideModal1?.value?.opened) { modalToClose = sideModal1; } - if (sideModal2?.value?.modalId === _modalId) { + if (sideModal2?.value?.modalId === _modalId && sideModal2?.value?.opened) { modalToClose = sideModal2; } @@ -111,11 +118,14 @@ export const useModalStore = defineStore('modal', () => { if (!modalToClose) { return; } - modalToClose.value.opened = false; + modalToClose.value.opened = false; + if (modalToClose.value.onClose) { + modalToClose.value.onClose(); + } // To keep the side modal animation nice, it needs to keep the component&props around for bit longer setTimeout(() => { - if (!modalToClose.value.opened) { + if (!modalToClose.value?.opened) { modalToClose.value = null; } }, 300); @@ -135,12 +145,11 @@ export const useModalStore = defineStore('modal', () => { // Listener for open modal requests coming from legacy handler. pkp.eventBus.$on('open-modal-vue', (_args) => { + const props = _args.options?.props || {}; openSideModal( _args.component, - { - options: _args.options, - }, - _args.modalId, + {...props, legacyOptions: _args.options}, + {modalId: _args.modalId}, ); }); From 7505ae934cc0afaf5095e16bf1ec760cdd153176 Mon Sep 17 00:00:00 2001 From: RobA Date: Mon, 20 May 2024 08:56:27 -0300 Subject: [PATCH 03/17] cleared commented out code --- .../workflow/WorkflowLogResponseForModal.vue | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue index a6e18f9c7..127f443e8 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.vue +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -22,7 +22,7 @@
@@ -63,7 +63,7 @@ export default { required: true }, journalLocales: { - type: Array, + type: Object, required: true }, submissionId: { @@ -113,28 +113,25 @@ export default { acceptReview.value = value; } - function submit() { - // props.legacyOptions.modalHandler - // .getHtmlElement() - // .trigger('dataChanged', props.reviewAssignmentId); + function submit() { + $.ajax({ + url: props.url, + type: 'POST', + data: { + acceptReview: acceptReview.value, + csrfToken: pkp.currentUser.csrfToken, + } + }); - $.ajax({ - url: props.url, - type: 'POST', - data: { - acceptReview: acceptReview.value, - csrfToken: pkp.currentUser.csrfToken, - }, - // error: this.ajaxErrorCallback, - success(r) { - //SHOW SUCCESS MESSAGE - }, - }); + closeModal(); + } - closeModal(); - } + function cancel() { + acceptReview.value = null; + closeModal(); + } - return {submit, change, acceptReview, logResponseForm}; + return {submit, change, cancel, acceptReview, logResponseForm}; } }; From 21c6d90db97392dd6fd0a79be3387c15517fa186 Mon Sep 17 00:00:00 2001 From: RobA Date: Mon, 20 May 2024 10:40:10 -0300 Subject: [PATCH 04/17] close modal in success of ajax call --- src/pages/workflow/WorkflowLogResponseForModal.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue index 127f443e8..397f9cda0 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.vue +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -120,10 +120,11 @@ export default { data: { acceptReview: acceptReview.value, csrfToken: pkp.currentUser.csrfToken, - } + }, + success(r) { + closeModal(); + }, }); - - closeModal(); } function cancel() { From 10647054f334a9bce3b7514c93d193a8aa6a6f60 Mon Sep 17 00:00:00 2001 From: RobA Date: Wed, 29 May 2024 10:19:48 -0300 Subject: [PATCH 05/17] modal form validation working --- .../workflow/WorkflowLogResponseForModal.vue | 152 +++++------------- 1 file changed, 37 insertions(+), 115 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue index 397f9cda0..87cadcf9c 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.vue +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -1,46 +1,30 @@ - - From caa624349053e97ed66cef671d5e262e6cae3efe Mon Sep 17 00:00:00 2001 From: RobA Date: Wed, 29 May 2024 10:47:20 -0300 Subject: [PATCH 06/17] removed unused imports --- src/pages/workflow/WorkflowLogResponseForModal.vue | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue index 87cadcf9c..a5cc5c1c5 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.vue +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -23,20 +23,12 @@ import {inject} from 'vue'; import SideModalBody from '@/components/Modal/SideModalBody.vue'; import PkpForm from '@/components/Form/Form.vue'; -import PkpButton from '@/components/Button/Button.vue'; -import FieldOptions from '@/components/Form/fields/FieldOptions.vue'; -import ajaxError from '@/mixins/ajaxError'; -import ButtonRow from '@/components/ButtonRow/ButtonRow.vue'; export default { components: { SideModalBody, - PkpButton, - FieldOptions, - ButtonRow, PkpForm, }, - mixins: [ajaxError], props: { description: {type: String, required: true}, submissionId: {type: Number, required: true}, From 2c8c4442374d183024a7e7da6e8d912b3ee3f3e3 Mon Sep 17 00:00:00 2001 From: RobA Date: Wed, 29 May 2024 15:50:29 -0300 Subject: [PATCH 07/17] vue store added for component --- src/components/Form/Form.vue | 9 ++-- .../workflow/WorkflowLogResponseForModal.vue | 53 ++++++------------- .../workflowLogResponseForModalStore.js | 20 +++++++ 3 files changed, 41 insertions(+), 41 deletions(-) create mode 100644 src/pages/workflow/workflowLogResponseForModalStore.js diff --git a/src/components/Form/Form.vue b/src/components/Form/Form.vue index 52d5e0070..215104d2c 100644 --- a/src/components/Form/Form.vue +++ b/src/components/Form/Form.vue @@ -1,5 +1,5 @@ - diff --git a/src/pages/workflow/workflowLogResponseForModalStore.js b/src/pages/workflow/workflowLogResponseForModalStore.js new file mode 100644 index 000000000..d18819a3c --- /dev/null +++ b/src/pages/workflow/workflowLogResponseForModalStore.js @@ -0,0 +1,20 @@ +import {inject} from 'vue'; +import {defineComponentStore} from "@/utils/defineComponentStore"; + +export const useWorkflowLogResponseForModalStore = defineComponentStore( + 'workflowLogResponseForModal', + (props) => { + const closeModal = inject('closeModal'); + const form = props.logResponseForm; + + function formSuccess() { + closeModal(); + } + + function updateForm(formId, data) { + Object.keys(data).forEach((key) => (form[key] = data[key])); + } + + return {form, formSuccess, updateForm}; + } +) From eca2803646e21c1d0255495b519fcf15a50f4136 Mon Sep 17 00:00:00 2001 From: RobA Date: Mon, 24 Jun 2024 17:50:31 -0300 Subject: [PATCH 08/17] vue modal added to storybook --- .../workflow/WorkflowLogResponseForModal.mdx | 11 +++ .../WorkflowLogResponseForModal.stories.js | 77 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/pages/workflow/WorkflowLogResponseForModal.mdx create mode 100644 src/pages/workflow/WorkflowLogResponseForModal.stories.js diff --git a/src/pages/workflow/WorkflowLogResponseForModal.mdx b/src/pages/workflow/WorkflowLogResponseForModal.mdx new file mode 100644 index 000000000..5fe3b2b66 --- /dev/null +++ b/src/pages/workflow/WorkflowLogResponseForModal.mdx @@ -0,0 +1,11 @@ +import {Meta, ArgTypes} from '@storybook/blocks'; + +import * as WorkflowLogResponseForModalStories from './WorkflowLogResponseForModal.stories'; + + + +# Log Response For Modal + +Some basic description of functionality + + diff --git a/src/pages/workflow/WorkflowLogResponseForModal.stories.js b/src/pages/workflow/WorkflowLogResponseForModal.stories.js new file mode 100644 index 000000000..6f98993f4 --- /dev/null +++ b/src/pages/workflow/WorkflowLogResponseForModal.stories.js @@ -0,0 +1,77 @@ +import WorkflowLogResponseForModal from './WorkflowLogResponseForModal.vue'; +import PkpButton from '@/components/Button/Button.vue'; +import {useModal} from '@/composables/useModal'; +import {within, userEvent} from '@storybook/test'; + +export default { + title: 'Pages/Workflow/LogResponseFor', + component: WorkflowLogResponseForModal, +}; + +export const Base = { + render: (args) => ({ + components: {WorkflowLogResponseForModal, PkpButton}, + setup() { + const {openSideModal} = useModal(); + + function logResponseFor() { + openSideModal(WorkflowLogResponseForModal, args.modalProps); + } + return {logResponseFor, ...args}; + }, + template: 'Log Response For', + }), + args: { + modalProps: { + description: + 'Sodium butyrate improves growth performance of weaned piglets during the first period after weaning', + submissionId: 12, + logResponseForm: { + id: 'logResponseForm', + method: 'POST', + action: + 'http://localhost:7003/index.php/publicknowledge/$$$call$$$/grid/users/reviewer/reviewer-grid/add-log?submissionId=12&reviewAssignmentId=17&stageId=3&round=0', + fields: [ + { + name: 'acceptReview', + isRequired: true, + description: + 'If the reviewer contacts you through email or any other means, you can record their response for them', + component: 'field-options', + label: 'Record the response on behalf of the reviewer', + value: false, + type: 'radio', + options: [ + { + value: 1, + label: 'Reviewer has accepted the invitation to review', + }, + { + value: 0, + label: 'Reviewer has declined the invitation to review', + }, + ], + groupId: 'default', + }, + ], + groups: [{id: 'default', pageId: 'default'}], + pages: [{id: 'default', submitButton: {label: 'Log Response'}}], + primaryLocale: 'en', + visibleLocales: ['en'], + supportedFormLocales: ['en', 'fr_CA'], + }, + }, + }, + play: async ({canvasElement}) => { + // Assigns canvas to the component root element + const canvas = within(canvasElement); + const user = userEvent.setup(); + + await user.click(canvas.getByText('Log Response For')); + }, + decorators: [ + () => ({ + template: '
', + }), + ], +}; From 4ff2db6c050903cd35b6a39902bf8d5f2e60103e Mon Sep 17 00:00:00 2001 From: RobA Date: Thu, 27 Jun 2024 08:58:29 -0300 Subject: [PATCH 09/17] npm run format ran --- .../workflow/WorkflowLogResponseForModal.vue | 49 +++++++++---------- .../workflowLogResponseForModalStore.js | 6 +-- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.vue b/src/pages/workflow/WorkflowLogResponseForModal.vue index a2821d748..e33ec03a9 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.vue +++ b/src/pages/workflow/WorkflowLogResponseForModal.vue @@ -1,38 +1,37 @@ diff --git a/src/pages/workflow/workflowLogResponseForModalStore.js b/src/pages/workflow/workflowLogResponseForModalStore.js index d18819a3c..afd72fac3 100644 --- a/src/pages/workflow/workflowLogResponseForModalStore.js +++ b/src/pages/workflow/workflowLogResponseForModalStore.js @@ -1,5 +1,5 @@ import {inject} from 'vue'; -import {defineComponentStore} from "@/utils/defineComponentStore"; +import {defineComponentStore} from '@/utils/defineComponentStore'; export const useWorkflowLogResponseForModalStore = defineComponentStore( 'workflowLogResponseForModal', @@ -16,5 +16,5 @@ export const useWorkflowLogResponseForModalStore = defineComponentStore( } return {form, formSuccess, updateForm}; - } -) + }, +); From b2b32b892a80729043553a8d0a30f026af6aa3c8 Mon Sep 17 00:00:00 2001 From: RobA Date: Thu, 27 Jun 2024 09:11:17 -0300 Subject: [PATCH 10/17] updated storybook mdx --- src/pages/workflow/WorkflowLogResponseForModal.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workflow/WorkflowLogResponseForModal.mdx b/src/pages/workflow/WorkflowLogResponseForModal.mdx index 5fe3b2b66..f476953f5 100644 --- a/src/pages/workflow/WorkflowLogResponseForModal.mdx +++ b/src/pages/workflow/WorkflowLogResponseForModal.mdx @@ -4,8 +4,8 @@ import * as WorkflowLogResponseForModalStories from './WorkflowLogResponseForMod -# Log Response For Modal +# Log Response Modal -Some basic description of functionality +A vue modal containing a form for and admin to log a response to a review request on behalf of the reviewer. From 48913182393f9d9d75958b73c3f4b42e195a3238 Mon Sep 17 00:00:00 2001 From: RobA Date: Tue, 10 Sep 2024 13:29:27 -0300 Subject: [PATCH 11/17] reverted unintended changes --- .../ListPanel/doi/DoiItemVersionModal.vue | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/src/components/ListPanel/doi/DoiItemVersionModal.vue b/src/components/ListPanel/doi/DoiItemVersionModal.vue index cd8b347b8..58a29abdc 100644 --- a/src/components/ListPanel/doi/DoiItemVersionModal.vue +++ b/src/components/ListPanel/doi/DoiItemVersionModal.vue @@ -10,42 +10,50 @@ class="doiListItem__versionContainer" > {{ getVersionHeader(version) }} - - + + + + {{ column.label }} + + + + + + + + + + + + {{ item.hasDisabledMsg }} @@ -73,11 +81,16 @@