From 2fbebd35c80952be91c20fad78294cfad9cf6708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarda=20Kot=C4=9B=C5=A1ovec?= Date: Tue, 9 Jan 2024 10:32:11 +0100 Subject: [PATCH 1/9] pkp/pkp-lib#i9527 Add Dialog to storybook, document useDialog and refine styling --- .storybook/preview.js | 12 +- src/App.vue | 13 +- .../ActionPanel/ActionPanel.stories.js | 6 +- src/components/Container/Page.vue | 8 +- src/components/Icon/Icon.vue | 3 + src/components/Icon/XMark.vue | 15 ++ .../AnnouncementsListPanel.stories.js | 5 +- src/components/Modal/AjaxModalWrapper.vue | 4 +- src/components/Modal/Dialog.vue | 88 +++---- ...egacyModalManager.vue => ModalManager.vue} | 4 +- src/components/Modal/SideModal.vue | 237 ------------------ src/components/Modal/SideModalBody.vue | 31 ++- src/composables/useDialog.js | 11 + src/composables/useDialog.mdx | 54 ++++ src/composables/useDialog.stories.js | 73 ++++++ src/composables/useFetch.js | 6 +- src/composables/useFetch.test.js | 12 +- src/mixins/dialog.js | 6 +- src/pages/submissions/AssignEditorsModal.vue | 6 +- src/pages/submissions/SubmissionsPage.vue | 2 - src/stores/dialogStore.js | 43 ---- src/stores/modalStore.js | 81 ++++++ 22 files changed, 333 insertions(+), 387 deletions(-) create mode 100644 src/components/Icon/XMark.vue rename src/components/Modal/{LegacyModalManager.vue => ModalManager.vue} (83%) create mode 100644 src/composables/useDialog.js create mode 100644 src/composables/useDialog.mdx create mode 100644 src/composables/useDialog.stories.js delete mode 100644 src/stores/dialogStore.js create mode 100644 src/stores/modalStore.js diff --git a/.storybook/preview.js b/.storybook/preview.js index a6bf329ea..ffc5f8ea3 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -21,7 +21,6 @@ import Tabs from '@/components/Tabs/Tabs.vue'; import FloatingVue from 'floating-vue'; import PkpDialog from '@/components/Modal/Dialog.vue'; -import {useDialogStore} from '@/stores/dialogStore'; import VueScrollTo from 'vue-scrollto'; @@ -115,17 +114,10 @@ const preview = { }), /** Globally Available Dialog */ (story) => ({ - setup() { - const dialogStore = useDialogStore(); - return {dialogStore}; - }, + setup() {}, components: {story, PkpDialog}, template: `
- +
`, }), diff --git a/src/App.vue b/src/App.vue index 89fa187fd..606f1f07d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,10 +1,6 @@ - - diff --git a/src/components/Modal/SideModalBody.vue b/src/components/Modal/SideModalBody.vue index aed3cfd48..f9350fece 100644 --- a/src/components/Modal/SideModalBody.vue +++ b/src/components/Modal/SideModalBody.vue @@ -1,7 +1,7 @@ +``` + + diff --git a/src/composables/useDialog.stories.js b/src/composables/useDialog.stories.js new file mode 100644 index 000000000..ad4a133a3 --- /dev/null +++ b/src/composables/useDialog.stories.js @@ -0,0 +1,73 @@ +import {useDialog} from './useDialog'; +import PkpButton from '@/components/Button/Button.vue'; + +export default { + title: 'composables/useDialog', + render: (args) => ({ + components: {PkpButton}, + setup() { + const {openDialog} = useDialog(); + + return {openDialog, args}; + }, + template: ` + {{args.buttonName}} + `, + }), +}; + +export const BasicExample = { + args: { + buttonName: 'Basic Example', + name: 'basic', + title: 'Submit Article', + message: 'Are you sure you want to submit this article?', + actions: [ + { + label: 'Confirm', + isPrimary: true, + callback: (close) => { + // Simulate a server request + setTimeout(() => close(), 2000); + }, + }, + { + label: 'Cancel', + isWarnable: true, + callback: (close) => close(), + }, + ], + }, +}; + +export const FullExample = { + args: { + buttonName: 'Full Example', + + name: 'full', + title: 'Several Actions', + message: + 'This dialog includes an action that is a link (Visit Page). It also logs something to the console when the modal is closed. Dialogs should have 2 or 3 actions at the most.', + actions: [ + { + label: 'Confirm', + isPrimary: true, + callback: (close) => { + // Simulate a server request + setTimeout(() => close(), 2000); + }, + }, + { + label: 'Visit Page', + element: 'a', + href: 'https://example.org', + }, + { + label: 'Cancel', + isWarnable: true, + callback: (close) => close(), + }, + ], + close: () => console.log('closed full example dialog'), // eslint-disable-line + }, +}; diff --git a/src/composables/useFetch.js b/src/composables/useFetch.js index 4ec8906b5..c2816daba 100644 --- a/src/composables/useFetch.js +++ b/src/composables/useFetch.js @@ -1,6 +1,6 @@ import {ref, unref} from 'vue'; import {ofetch, createFetch} from 'ofetch'; -import {useDialogStore} from '@/stores/dialogStore'; +import {useModalStore} from '@/stores/modalStore'; let ofetchInstance = ofetch; @@ -53,7 +53,7 @@ export function useFetch(url, options = {}) { const query = ref(_query || {}); const body = ref(_body || undefined); - const dialogStore = useDialogStore(); + const modalStore = useModalStore(); const isLoading = ref(false); const data = ref(null); const validationError = ref(null); @@ -111,7 +111,7 @@ export function useFetch(url, options = {}) { return; } - dialogStore.openDialogNetworkError(e); + modalStore.openDialogNetworkError(e); } finally { lastRequestController = null; isLoading.value = false; diff --git a/src/composables/useFetch.test.js b/src/composables/useFetch.test.js index 5f9333697..27bd3a3e6 100644 --- a/src/composables/useFetch.test.js +++ b/src/composables/useFetch.test.js @@ -14,7 +14,7 @@ import {HttpResponse, http, delay} from 'msw'; import {setActivePinia, createPinia} from 'pinia'; import {useFetch} from './useFetch'; -import {useDialogStore} from '@/stores/dialogStore'; +import {useModalStore} from '@/stores/modalStore'; export const restHandlers = [ http.get('http://mock/get/status200', async ({request}) => { @@ -198,14 +198,14 @@ describe('features', () => { }); test('network dialog error is displayed if there is http code other than 2XX', async () => { const url = ref('http://mock/get/status500'); - const dialogStore = useDialogStore(); - expect(dialogStore.dialogOpened).toBe(false); + const modalStore = useModalStore(); + expect(modalStore.dialogOpened).toBe(false); const {fetch} = useFetch(url); await fetch(); - expect(dialogStore.dialogOpened).toBe(true); - dialogStore.closeDialog(); - expect(dialogStore.dialogOpened).toBe(false); + expect(modalStore.dialogOpened).toBe(true); + modalStore.closeDialog(); + expect(modalStore.dialogOpened).toBe(false); }); }); diff --git a/src/mixins/dialog.js b/src/mixins/dialog.js index 1b66f8cae..81eb2afb4 100644 --- a/src/mixins/dialog.js +++ b/src/mixins/dialog.js @@ -7,7 +7,7 @@ * @see https://vuejs.org/v2/guide/mixins.html */ -import {useDialogStore} from '@/stores/dialogStore'; +import {useModalStore} from '@/stores/modalStore'; export default { methods: { @@ -17,8 +17,8 @@ export default { * @param {Object} props Props to pass to the component */ openDialog(props, modalProps, modalEvents) { - const dialogStore = useDialogStore(); - dialogStore.openDialog(props); + const modalStore = useModalStore(); + modalStore.openDialog(props); }, }, }; diff --git a/src/pages/submissions/AssignEditorsModal.vue b/src/pages/submissions/AssignEditorsModal.vue index aff5a94b8..0ef7cbb3e 100644 --- a/src/pages/submissions/AssignEditorsModal.vue +++ b/src/pages/submissions/AssignEditorsModal.vue @@ -1,9 +1,9 @@