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 bf01fd646..05fcf72e1 100644 --- a/src/components/Modal/SideModal.stories.js +++ b/src/components/Modal/SideModal.stories.js @@ -3,6 +3,7 @@ import {ref} 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