From 76ca2af23931b0072c2bb3884951059056e6bbd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarda=20Kot=C4=9B=C5=A1ovec?= Date: Tue, 2 Jul 2024 14:44:18 +0200 Subject: [PATCH] I9992 (#366) * pkp/pkp-lib#9992 Migrate Announcements to SideModal * pkp/pkp-lib#9992 clean up announcements moved to SideModal * pkp/pkp-lib#9992 Composer modals migrated to SideModal * pkp/pkp-lib#9992 FileAttacher modal clean up * pkp/pkp-lib#9992 Migrate issue stats modal to SideModal * pkp/pkp-lib#9992 publication stats migrated to side modal * pkp/pkp-lib#9992 users stats export modal migrated to side modal * pkp/pkp-lib#9992 wizard modal migrated to side modal * pkp/pkp-lib#9992 FieldPreparedContent migrated to side modal * pkp/pkp-lib#9992 InstitutionsListPanel migrated to side modal, make sure that the form errors are propagated to the modal for other ListPanels * pkp/pkp-lib#9992 Migrate SubmissionFilesEditModal to openSideModal * pkp/pkp-lib#9992 HighlightsListPanel migrated to side modal * pkp/pkp-lib#9992 Migrate ContributorsListPanel to side panel, rename some other modals for more consistent naming * pkp/pkp-lib#9992 Migrate CatalogListPanel to side modal * pkp/pkp-lib#9992 Migrate doi list panel to side modal * pkp/pkp-lib#9992 migrate workflow page to side modal * pkp/pkp-lib#9992 migrate manageEmails to side modal * pkp/pkp-lib#9992 Migrate error doi message modals to useDialog * pkp/pkp-lib#9992 clean up modals in stories, copied over the tpl files * pkp/pkp-lib#9992 move title directly to modal component when its not dynamic * pkp/pkp-lib#9992 Update documentation for SideModal and Dialog, refactor Dialog to expose the props for docs * pkp/pkp-lib#9992 Clean up * pkp/pkp-lib#9992 Fix SideModal stories template * pkp/pkp-lib#9992 Address code review feedback --- src/components/Composer/Composer.vue | 45 ++--- src/components/Composer/FileAttacherModal.vue | 26 +++ .../Container/ManageEmailsPage.stories.js | 65 ------ src/components/Container/ManageEmailsPage.vue | 50 +++-- src/components/Container/StatsContextPage.vue | 22 +++ src/components/Container/StatsIssuesPage.vue | 24 ++- .../Container/StatsPublicationsPage.vue | 29 ++- src/components/Container/StatsUsersPage.vue | 19 +- .../Container/SubmissionWizardPage.stories.js | 13 -- .../Container/SubmissionWizardPage.vue | 16 +- src/components/Container/WorkflowPage.vue | 20 +- src/components/FileAttacher/AttacherModal.vue | 40 ++++ src/components/FileAttacher/FileAttacher.vue | 43 ++-- .../Form/fields/FieldPreparedContent.vue | 39 ++-- .../FieldPreparedContentInsertModal.vue | 33 ++++ .../announcements/AnnouncementsEditModal.vue | 26 +++ .../announcements/AnnouncementsListPanel.vue | 50 ++--- .../contributors/ContributorsEditModal.vue | 26 +++ .../contributors/ContributorsListPanel.vue | 170 ++++------------ .../contributors/ContributorsPreviewModal.vue | 48 +++++ .../doi/DoiFailedActionDialogBody.vue | 16 ++ .../ListPanel/doi/DoiItemVersionModal.vue | 109 ++++++++++ .../doi/DoiItemViewErrorDialogBody.vue | 23 +++ ...DoiItemViewRegisteredMessageDialogBody.vue | 11 ++ src/components/ListPanel/doi/DoiListItem.vue | 187 ++++++------------ src/components/ListPanel/doi/DoiListPanel.vue | 106 ++++------ .../ListPanel/doi/DoiStatusInfoModal.vue | 53 +++++ .../highlights/HighlightsEditModal.vue | 26 +++ .../highlights/HighlightsListPanel.vue | 48 ++--- .../institutions/InstitutionsEditModal.vue | 26 +++ .../institutions/InstitutionsListPanel.vue | 45 ++--- .../SubmissionFilesEditModal.vue | 26 +++ .../SubmissionFilesListPanel.vue | 36 ++-- .../submissions/CatalogEditModal.vue | 26 +++ .../submissions/CatalogListPanel.vue | 38 ++-- src/components/Modal/Dialog.mdx | 30 +++ .../Modal/Dialog.stories.js} | 67 +++++-- src/components/Modal/Dialog.vue | 83 ++++---- src/components/Modal/Modal.mdx | 2 +- src/components/Modal/ModalManager.vue | 26 ++- src/components/Modal/SideModal.mdx | 14 +- src/components/Modal/SideModal.stories.js | 7 +- src/components/Modal/SideModalBody.vue | 3 - src/components/Modal/SideModalLayoutBasic.vue | 7 + src/composables/useModal.js | 10 +- src/composables/useModal.mdx | 31 ++- src/pages/manageEmails/EditMailableModal.vue | 69 +++++++ src/pages/manageEmails/EditTemplateModal.vue | 29 +++ .../ContextDownloadReportModal.vue | 53 +++++ .../statsIssues/IssueDownloadReportModal.vue | 58 ++++++ .../PublicationsDownloadReportModal.vue | 106 ++++++++++ src/pages/statsUsers/UserExportModal.vue | 27 +++ .../ReconfigureSubmissionModal.vue | 28 +++ .../workflow/SelectRevisionDecisionModal.vue | 26 +++ src/stores/modalStore.js | 48 +++-- 55 files changed, 1581 insertions(+), 723 deletions(-) create mode 100644 src/components/Composer/FileAttacherModal.vue create mode 100644 src/components/FileAttacher/AttacherModal.vue create mode 100644 src/components/Form/fields/FieldPreparedContentInsertModal.vue create mode 100644 src/components/ListPanel/announcements/AnnouncementsEditModal.vue create mode 100644 src/components/ListPanel/contributors/ContributorsEditModal.vue create mode 100644 src/components/ListPanel/contributors/ContributorsPreviewModal.vue create mode 100644 src/components/ListPanel/doi/DoiFailedActionDialogBody.vue create mode 100644 src/components/ListPanel/doi/DoiItemVersionModal.vue create mode 100644 src/components/ListPanel/doi/DoiItemViewErrorDialogBody.vue create mode 100644 src/components/ListPanel/doi/DoiItemViewRegisteredMessageDialogBody.vue create mode 100644 src/components/ListPanel/doi/DoiStatusInfoModal.vue create mode 100644 src/components/ListPanel/highlights/HighlightsEditModal.vue create mode 100644 src/components/ListPanel/institutions/InstitutionsEditModal.vue create mode 100644 src/components/ListPanel/submissionFiles/SubmissionFilesEditModal.vue create mode 100644 src/components/ListPanel/submissions/CatalogEditModal.vue create mode 100644 src/components/Modal/Dialog.mdx rename src/{composables/useModal.stories.js => components/Modal/Dialog.stories.js} (64%) create mode 100644 src/components/Modal/SideModalLayoutBasic.vue create mode 100644 src/pages/manageEmails/EditMailableModal.vue create mode 100644 src/pages/manageEmails/EditTemplateModal.vue create mode 100644 src/pages/statsContext/ContextDownloadReportModal.vue create mode 100644 src/pages/statsIssues/IssueDownloadReportModal.vue create mode 100644 src/pages/statsPublications/PublicationsDownloadReportModal.vue create mode 100644 src/pages/statsUsers/UserExportModal.vue create mode 100644 src/pages/submissionWizard/ReconfigureSubmissionModal.vue create mode 100644 src/pages/workflow/SelectRevisionDecisionModal.vue diff --git a/src/components/Composer/Composer.vue b/src/components/Composer/Composer.vue index e0f33adcd..01e59f498 100644 --- a/src/components/Composer/Composer.vue +++ b/src/components/Composer/Composer.vue @@ -253,18 +253,6 @@ - - - { - if (this.$refs.attachedFiles) { - this.$refs.attachedFiles.focus(); - } else { - this.setFocusIn(this.$el.querySelector('.composer__body')); - } - }); - }, - /** * Search for email templates */ diff --git a/src/components/Composer/FileAttacherModal.vue b/src/components/Composer/FileAttacherModal.vue new file mode 100644 index 000000000..7db6be662 --- /dev/null +++ b/src/components/Composer/FileAttacherModal.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/Container/ManageEmailsPage.stories.js b/src/components/Container/ManageEmailsPage.stories.js index 05277005c..7916a7175 100644 --- a/src/components/Container/ManageEmailsPage.stories.js +++ b/src/components/Container/ManageEmailsPage.stories.js @@ -97,71 +97,6 @@ const ManageEmailsPageWithDataAndTemplate = { - - - - - - `, data() { diff --git a/src/components/Container/ManageEmailsPage.vue b/src/components/Container/ManageEmailsPage.vue index 6416edaf8..0ca9c0f45 100644 --- a/src/components/Container/ManageEmailsPage.vue +++ b/src/components/Container/ManageEmailsPage.vue @@ -4,6 +4,12 @@ import Modal from '../Modal/Modal.vue'; import PkpFilter from '../Filter/Filter.vue'; import Search from '../Search/Search.vue'; import dialog from '../../mixins/dialog'; +import EditMailableModal from '@/pages/manageEmails/EditMailableModal.vue'; +import EditTemplateModal from '@/pages/manageEmails/EditTemplateModal.vue'; +import {useLocalize} from '@/composables/useLocalize'; +import {useModal} from '@/composables/useModal'; + +const {t} = useLocalize(); export default { name: 'ManageEmailsPage', @@ -36,8 +42,6 @@ export default { mailables: [], /** The URL to the `/mailables` endpoint in the REST API. */ mailablesApiUrl: '', - /** Used to reset focus when a modal is closed. */ - resetFocusTo: {}, /** The value of the search input. */ searchPhrase: '', /** A "clean" copy of the form to add or edit an `EmailTemplate`. The `currentTemplateForm` is a copy of this form that has been modified to add or edit a specific template. */ @@ -296,8 +300,8 @@ export default { * Fired when the mailable modal is closed */ closeMailableModal() { - this.isModalOpenedMailable = false; - this.resetFocus(); + const {closeSideModal} = useModal(); + closeSideModal(EditMailableModal); setTimeout(() => { this.currentMailable = {}; this.currentTemplate = {}; @@ -315,9 +319,15 @@ export default { openMailable(mailable) { if (mailable.supportsTemplates) { this.getMailable(mailable, (mailable) => { - this.resetFocusTo = document.activeElement; this.currentMailable = mailable; - this.isModalOpenedMailable = true; + const {openSideModal} = useModal(); + openSideModal(EditMailableModal, { + title: mailable ? mailable.name : '', + mailable: this.currentMailable, + onOpenTemplate: this.openTemplate, + onConfirmResetTemplate: this.confirmRemoveTemplate, + onConfirmRemoveTemplate: this.confirmRemoveTemplate, + }); }); } else { this.getTemplate(mailable.emailTemplateKey, (template) => { @@ -334,9 +344,18 @@ export default { */ openTemplate(template) { template = template || {}; - this.resetFocusTo = document.activeElement; this.currentTemplate = template; - this.$nextTick(() => (this.isModalOpenedTemplate = true)); + const {openSideModal} = useModal(); + this.$nextTick(() => + openSideModal(EditTemplateModal, { + title: this.currentTemplate + ? t('manager.mailables.editTemplate') + : t('manager.emails.addEmail'), + currentTemplateForm: this.currentTemplateForm, + onUpdateCurrentTemplateForm: this.updateCurrentTemplateForm, + onTemplateSaved: this.templateSaved, + }), + ); }, /** @@ -355,17 +374,6 @@ export default { this.activeFilters = newFilters; }, - /** - * A helper function to move the focus back to the element - * it was last at. This is usually used with modals to restore - * the focus after a modal is closed. - */ - resetFocus() { - if (this.resetFocusTo) { - this.resetFocusTo.focus(); - } - }, - /** * Setup the form to edit an email template * @@ -455,9 +463,9 @@ export default { * Fired when the email template modal has been closed */ closeTemplateModal() { - this.isModalOpenedTemplate = false; + const {closeSideModal} = useModal(); + closeSideModal(EditTemplateModal); if (this.currentMailable.supportsTemplates) { - this.resetFocus(); setTimeout(() => { this.currentTemplate = {}; }, 300); diff --git a/src/components/Container/StatsContextPage.vue b/src/components/Container/StatsContextPage.vue index acac6cbdf..4e0948019 100644 --- a/src/components/Container/StatsContextPage.vue +++ b/src/components/Container/StatsContextPage.vue @@ -1,5 +1,7 @@ diff --git a/src/components/FileAttacher/FileAttacher.vue b/src/components/FileAttacher/FileAttacher.vue index d085b0ab0..dcff81656 100644 --- a/src/components/FileAttacher/FileAttacher.vue +++ b/src/components/FileAttacher/FileAttacher.vue @@ -16,41 +16,18 @@ - - - diff --git a/src/components/ListPanel/announcements/AnnouncementsEditModal.vue b/src/components/ListPanel/announcements/AnnouncementsEditModal.vue new file mode 100644 index 000000000..1addee7ed --- /dev/null +++ b/src/components/ListPanel/announcements/AnnouncementsEditModal.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/ListPanel/announcements/AnnouncementsListPanel.vue b/src/components/ListPanel/announcements/AnnouncementsListPanel.vue index 6c49ef018..1f03c23b5 100644 --- a/src/components/ListPanel/announcements/AnnouncementsListPanel.vue +++ b/src/components/ListPanel/announcements/AnnouncementsListPanel.vue @@ -41,19 +41,6 @@ /> - - - @@ -61,22 +48,20 @@ diff --git a/src/components/ListPanel/contributors/ContributorsListPanel.vue b/src/components/ListPanel/contributors/ContributorsListPanel.vue index 782c8159b..713a821bd 100644 --- a/src/components/ListPanel/contributors/ContributorsListPanel.vue +++ b/src/components/ListPanel/contributors/ContributorsListPanel.vue @@ -36,7 +36,7 @@ :disabled="isLoading" @click="openPreviewModal" > - {{ i18nPreview }} + {{ t('contributor.listPanel.preview') }} - {{ i18nAddContributor }} + {{ t('grid.action.addContributor') }} @@ -81,14 +81,14 @@ v-if="publication.primaryContactId == item.id" :is-primary="true" > - {{ i18nPrimaryContact }} + {{ t('author.users.contributor.principalContact') }} - {{ i18nSetPrimaryContact }} + {{ t('author.users.contributor.setPrincipalContact') }} {{ t('common.edit') }} @@ -103,74 +103,26 @@ - - - - -

- {{ i18nPreviewDescription }} -

- - - - - - - - - - - - - - - - - - - - - -
{{ i18nFormat }}{{ i18nDisplay }}
{{ i18nAbbreviated }}{{ publication.authorsStringShort }}
- {{ i18nPublicationLists }} - {{ publication.authorsStringIncludeInBrowse }}
{{ i18nFull }}{{ publication.authorsString }}
-
diff --git a/src/components/ListPanel/doi/DoiFailedActionDialogBody.vue b/src/components/ListPanel/doi/DoiFailedActionDialogBody.vue new file mode 100644 index 000000000..6f55400b9 --- /dev/null +++ b/src/components/ListPanel/doi/DoiFailedActionDialogBody.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/ListPanel/doi/DoiItemVersionModal.vue b/src/components/ListPanel/doi/DoiItemVersionModal.vue new file mode 100644 index 000000000..87e112241 --- /dev/null +++ b/src/components/ListPanel/doi/DoiItemVersionModal.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/src/components/ListPanel/doi/DoiItemViewErrorDialogBody.vue b/src/components/ListPanel/doi/DoiItemViewErrorDialogBody.vue new file mode 100644 index 000000000..c1152e19f --- /dev/null +++ b/src/components/ListPanel/doi/DoiItemViewErrorDialogBody.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/src/components/ListPanel/doi/DoiItemViewRegisteredMessageDialogBody.vue b/src/components/ListPanel/doi/DoiItemViewRegisteredMessageDialogBody.vue new file mode 100644 index 000000000..596807fe3 --- /dev/null +++ b/src/components/ListPanel/doi/DoiItemViewRegisteredMessageDialogBody.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/components/ListPanel/doi/DoiListItem.vue b/src/components/ListPanel/doi/DoiListItem.vue index 10808fcaf..27f619fe1 100644 --- a/src/components/ListPanel/doi/DoiListItem.vue +++ b/src/components/ListPanel/doi/DoiListItem.vue @@ -105,7 +105,7 @@ @@ -149,7 +149,7 @@ v-if="isDeposited && hasRegisteredMessage" ref="recordedMessageModalButton" :is-disabled="isEditingDois" - @click="isModalOpenedRegisteredMessage = true" + @click="viewRecord" > {{ t('manager.dois.registration.viewRecord') }}
@@ -164,109 +164,29 @@ v-if="hasErrors && hasErrorMessage" ref="errorMessageModalButton" :is-disabled="isEditingDois" - @click="isModalOpenedErrorMessage = true" + @click="openViewErrorModal" > {{ t('manager.dois.registration.viewError') }} - - - -

{{ registrationAgencyInfo['errorMessagePreamble'] }}

-
-
{{ currentVersionDoiObjects[0]['errorMessage'] }}
-
-
- - -

{{ registrationAgencyInfo['registeredMessagePreamble'] }}

-

{{ currentVersionDoiObjects[0]['registeredMessage'] }}

-
- - - - -
- - - {{ isEditingDois ? t('common.save') : t('common.edit') }} - -
-
@@ -839,13 +800,6 @@ export default { diff --git a/src/components/Modal/Modal.mdx b/src/components/Modal/Modal.mdx index 325afe48b..2eb2c49d3 100644 --- a/src/components/Modal/Modal.mdx +++ b/src/components/Modal/Modal.mdx @@ -6,7 +6,7 @@ import * as ModalStories from './Modal.stories.js'; # Modal -**Deprecated** in favour of SideModal. +**Deprecated** in favour of SideModal. Please migrate to use SideModal and `openSideModal` function from [useModal](../?path=/docs/composables-usemodal--docs#opensidemodal) composable. ## Usage diff --git a/src/components/Modal/ModalManager.vue b/src/components/Modal/ModalManager.vue index 571b07961..ffdb861f8 100644 --- a/src/components/Modal/ModalManager.vue +++ b/src/components/Modal/ModalManager.vue @@ -6,6 +6,12 @@ @close="() => close(sideModal1?.modalId)" > + + + - + diff --git a/src/components/Modal/SideModal.mdx b/src/components/Modal/SideModal.mdx index 19a37ed05..c6180e810 100644 --- a/src/components/Modal/SideModal.mdx +++ b/src/components/Modal/SideModal.mdx @@ -13,13 +13,15 @@ import * as SideModalStories from './SideModal.stories.js'; # Side Modal -Side modal has been introduced with new submission listing and will gradually replace both legacy jQuery modal and Vue.js central modal. - -To correctly handle accessibility (title, description) and focus management - [headless-ui](https://headlessui.com) library is used. +Side modal has been introduced in 3.5 all existing modals, including jquery legacy ones are now rendered as SideModal. ## Usage -We recommend to define modals as individual component files, rather than inline them, that ensures that the `setup` function and any other component life cycle event are triggered as modal is opened/closed. Therefore its easier to control when for example to fetch data from API. We might introduce option to define inline modals for basic use cases in future +It's important to create modals as separate files, which works best with our [useModal](../?path=/docs/composables-usemodal--docs#opensidemodal) composable. Also having them defined as individual components ensures that the `setup` function and any other component life cycle event are triggered as modal is opened/closed. Therefore, it's easier to control when for example to fetch data from API. + +## Accessibility + +To correctly handle accessibility (title, description) and focus management - [headless-ui](https://headlessui.com) library is used. ### Defining Modal Component @@ -42,9 +44,7 @@ We recommend to define modals as individual component files, rather than inline -
-
CONTENT
-
+ CONTENT diff --git a/src/components/Modal/SideModal.stories.js b/src/components/Modal/SideModal.stories.js index 455d0d1e6..b5ac1bcda 100644 --- a/src/components/Modal/SideModal.stories.js +++ b/src/components/Modal/SideModal.stories.js @@ -3,6 +3,7 @@ import {ref, inject} from 'vue'; import SideModal from './SideModal.vue'; import {useModal} from '@/composables/useModal.js'; import SideModalBody from './SideModalBody.vue'; +import SideModalLayoutBasic from './SideModalLayoutBasic.vue'; import SideModalLayout2Columns from './SideModalLayout2Columns.vue'; import PkpForm from '@/components/Form/Form.vue'; import cloneDeep from 'clone-deep'; @@ -18,7 +19,7 @@ export default { }; const SideModalBase = { - components: {SideModalBody}, + components: {SideModalBody, SideModalLayoutBasic}, template: ` @@ -35,9 +36,7 @@ const SideModalBase = { -
-
CONTENT
-
+ CONTENT
`, }; diff --git a/src/components/Modal/SideModalBody.vue b/src/components/Modal/SideModalBody.vue index 58785767e..71ad822cf 100644 --- a/src/components/Modal/SideModalBody.vue +++ b/src/components/Modal/SideModalBody.vue @@ -51,8 +51,6 @@ - - @@ -60,7 +58,6 @@ import {inject, computed} from 'vue'; import {DialogPanel, DialogTitle, DialogDescription} from '@headlessui/vue'; import Icon from '@/components/Icon/Icon.vue'; -import PkpDialog from '@/components/Modal/Dialog.vue'; import {useLocalize} from '@/composables/useLocalize'; diff --git a/src/components/Modal/SideModalLayoutBasic.vue b/src/components/Modal/SideModalLayoutBasic.vue new file mode 100644 index 000000000..f90b1ff55 --- /dev/null +++ b/src/components/Modal/SideModalLayoutBasic.vue @@ -0,0 +1,7 @@ + diff --git a/src/composables/useModal.js b/src/composables/useModal.js index 548a1b54b..f269e93cd 100644 --- a/src/composables/useModal.js +++ b/src/composables/useModal.js @@ -11,5 +11,13 @@ export function useModal() { modalStore.openSideModal(component, props, opts); } - return {openDialog, openSideModal}; + function closeSideModal(component) { + modalStore.closeSideModal(component); + } + + function isSideModalOpened(component) { + modalStore.isSideModalOpened(component); + } + + return {openDialog, openSideModal, closeSideModal, isSideModalOpened}; } diff --git a/src/composables/useModal.mdx b/src/composables/useModal.mdx index a5e494b25..0d07423cb 100644 --- a/src/composables/useModal.mdx +++ b/src/composables/useModal.mdx @@ -1,14 +1,10 @@ import {Primary, Controls, Stories, Meta, ArgTypes} from '@storybook/blocks'; -import * as useModalStories from './useModal.stories.js'; - - - # useModal ## openDialog -Dialogs provide a quick way to show a simple confirmation prompt. Import `useModal` composable and use the openDialog() method to create a dialog. +Dialog component's purpose is to display simple feedback like success and error messages. Or request confirmation for example before deleting some content. Import `useModal` composable and use the openDialog() method to create a dialog. Check [Dialog](../?path=/docs/components-dialog--docs) component for more details on available props. ```html