From c05aef574c0803d773981887ca187837caa49d8f Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Tue, 25 Feb 2025 17:06:14 +0100 Subject: [PATCH 01/12] add basic from and modal --- src/components/FeedbackForm.vue | 76 +++++++++++++++++++ src/components/FeedbackModal.vue | 53 +++++++++++++ .../stories/FeedbackModal.stories.ts | 33 ++++++++ 3 files changed, 162 insertions(+) create mode 100644 src/components/FeedbackForm.vue create mode 100644 src/components/FeedbackModal.vue create mode 100644 src/components/stories/FeedbackModal.stories.ts diff --git a/src/components/FeedbackForm.vue b/src/components/FeedbackForm.vue new file mode 100644 index 00000000..7eefe921 --- /dev/null +++ b/src/components/FeedbackForm.vue @@ -0,0 +1,76 @@ + + diff --git a/src/components/FeedbackModal.vue b/src/components/FeedbackModal.vue new file mode 100644 index 00000000..35a22b2a --- /dev/null +++ b/src/components/FeedbackModal.vue @@ -0,0 +1,53 @@ + + diff --git a/src/components/stories/FeedbackModal.stories.ts b/src/components/stories/FeedbackModal.stories.ts new file mode 100644 index 00000000..5b2cac81 --- /dev/null +++ b/src/components/stories/FeedbackModal.stories.ts @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import FeedbackModal from '@/components/FeedbackModal.vue' + +const meta: Meta = { + title: 'Components/FeedbackModal', + component: FeedbackModal, + tags: ['autodocs'], + render: args => { + return { + setup() { + return { args } + }, + components: { FeedbackModal }, + template: ` +
+ +
+ ` + } + } +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + isVisible: true, + isLoading: true, + title: 'Feedback' + } +} From dfceae8713e4b48ebebf855b1b41744d4b84022a Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Wed, 26 Feb 2025 16:33:51 +0100 Subject: [PATCH 02/12] add labels and translations --- src/components/FeedbackForm.vue | 32 +++++++++++++------ src/components/FeedbackModal.vue | 8 +---- .../stories/FeedbackModal.stories.ts | 2 +- src/constants.ts | 11 +++++++ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/components/FeedbackForm.vue b/src/components/FeedbackForm.vue index 7eefe921..800ee1a1 100644 --- a/src/components/FeedbackForm.vue +++ b/src/components/FeedbackForm.vue @@ -1,7 +1,10 @@ @@ -92,7 +117,8 @@ const handleOnSubmit = (event: Event) => { "label_OtherIssue": "Other issue", "label_type_of_issue": "What type of issue are you experiencing?", "label_additional_details": "Additional details (optional)", - "label_additional_details_hint": "(Provide any extra information that might help us understand the issue better.)" + "label_additional_details_hint": "(Provide any extra information that might help us understand the issue better.)", + "label_max_length_exceeded": "The content exceeds the maximum length of 500 characters." } } diff --git a/src/components/FeedbackModal.vue b/src/components/FeedbackModal.vue index 5dbb3c38..d0138c64 100644 --- a/src/components/FeedbackModal.vue +++ b/src/components/FeedbackModal.vue @@ -9,12 +9,13 @@ hideBackdrop > -
+

Errors that will be reported

  • + {{ d }} {{ d.message }}
    id: {{ d.id }}
    code: {{ d.code }} {{ d.route }} diff --git a/src/components/Modals.vue b/src/components/Modals.vue index cf931653..68460b64 100644 --- a/src/components/Modals.vue +++ b/src/components/Modals.vue @@ -147,6 +147,7 @@ @dismiss="() => resetView()" @submit="createFeedback" :errorMessages="errorMessages" + :is-loading="feedbackCollectorResponse.status === 'loading'" >
@@ -180,7 +181,7 @@ import { subscriptionDatasets as subscriptionDatasetsService, feedback as feedbackService } from '@/services' -import type { FeathersError } from '@feathersjs/errors' +import { BadRequest, type FeathersError } from '@feathersjs/errors' import { useUserStore } from '@/stores/user' import { AvailablePlans, PlanLabels } from '@/constants' import TermsOfUseStatus from './TermsOfUseStatus.vue' @@ -214,7 +215,12 @@ const bitmap = computed(() => { const view = ref<(typeof Views)[number] | null>(store.view) const isLoading = ref(false) const isLoggedIn = computed(() => !!userStore.userData) -const errorMessages = computed(() => notificationsStore.errorMessages) +const errorMessages = computed(() => { + if (feedbackCollectorResponse.value.status === 'error') { + return [new BadRequest('Error', feedbackCollectorResponse.value.data)] + } + return notificationsStore.errorMessages +}) // date of accepting the ToU on localStorage const acceptTermsDateOnLocalStorage = computed(() => userStore.acceptTermsDateOnLocalStorage) // date of accepting the ToU on current store (sort of cached value) @@ -228,6 +234,14 @@ const userChangePlanRequestResponse = ref<{ data: null }) +const feedbackCollectorResponse = ref<{ + data: any + status: 'idle' | 'loading' | 'success' | 'error' +}>({ + status: 'idle', + data: null +}) + const termsOfUseResponse = ref<{ data: TermsOfUse status: 'idle' | 'loading' | 'success' | 'error' @@ -477,15 +491,19 @@ const patchCurrentPlanChangeRequest = async ({ plan }) => { const createFeedback = async (payload: FeedbackFormPayload) => { console.debug('[FeedbackModal] @createFeedback', payload) + feedbackCollectorResponse.value = { data: null, status: 'loading' } await feedbackService - .create(payload) + .create(payload, { + ignoreErrors: true + }) .then(data => { console.info('[FeedbackModal] Feedback sent successfully. data:', data) store.view = null + feedbackCollectorResponse.value = { data, status: 'success' } }) .catch((err: FeathersError) => { console.error('[FeedbackModal] create', err.message, err.data) - throw err + feedbackCollectorResponse.value = { data: err.data, status: 'error' } }) } diff --git a/src/services/index.ts b/src/services/index.ts index 6becba38..6fcea99c 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -190,7 +190,7 @@ export const termsOfUse = app.service('terms-of-use') export const userChangePlanRequest = app.service('user-change-plan-request') export const userRequests = app.service('user-requests') export const subscriptionDatasets = app.service('subscriptions') -export const feedback = app.service('feedback') +export const feedback = app.service('feedback-collector') export const MIDDLELAYER_API = import.meta.env.VITE_MIDDLELAYER_API export const MIDDLELAYER_MEDIA_PATH = import.meta.env.VITE_MIDDLELAYER_MEDIA_PATH From 4d3d563275ccb67b0d802078b3afd873582311aa Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Fri, 28 Feb 2025 17:09:54 +0100 Subject: [PATCH 10/12] add ContentItemFacsimileIssue and ContentItemTranscriptionIssue --- src/constants.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/constants.ts b/src/constants.ts index 5c6c693c..502947f6 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -44,11 +44,15 @@ export const Views: string[] = [ ] const FeedbackOptionContentItemMetadataIssue = 'ContentItemMetadataIssue' +const FeedbackOptionContentItemFacsimileIssue = 'ContentItemFacsimileIssue' +const FeedbackOptionContentItemTranscriptionIssue = 'ContentItemTranscriptionIssue' const FeedbackOptionLayoutSegmentationIssue = 'LayoutSegmentationIssue' const FeedbackOptionDocumentLoadingIssue = 'DocumentLoadingIssue' const FeedbackOptionOtherIssue = 'OtherIssue' export const AvailableFeedbackOptions = [ FeedbackOptionContentItemMetadataIssue, + FeedbackOptionContentItemFacsimileIssue, + FeedbackOptionContentItemTranscriptionIssue, FeedbackOptionLayoutSegmentationIssue, FeedbackOptionDocumentLoadingIssue, FeedbackOptionOtherIssue From fa1c5b68150ce9216257f44dfce3fb2f3dc49b45 Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Fri, 28 Feb 2025 17:09:59 +0100 Subject: [PATCH 11/12] Update FeedbackForm.vue --- src/components/FeedbackForm.vue | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/FeedbackForm.vue b/src/components/FeedbackForm.vue index 5c2a1232..80970c7d 100644 --- a/src/components/FeedbackForm.vue +++ b/src/components/FeedbackForm.vue @@ -111,9 +111,11 @@ const handleOnSubmit = (event: Event) => { { "en": { - "label_ContentItemMetadataIssue": "Content item metadata issue", - "label_LayoutSegmentationIssue": "Layout segmentation issue", - "label_DocumentLoadingIssue": "Document loading issue", + "label_ContentItemMetadataIssue": "Faulty or missing metadata", + "label_ContentItemFacsimileIssue": "Facsimile issue", + "label_ContentItemTranscriptionIssue": "Transcription issue", + "label_LayoutSegmentationIssue": "Wrong Facsimile Layout segmentation", + "label_DocumentLoadingIssue": "User interface issue", "label_OtherIssue": "Other issue", "label_type_of_issue": "What type of issue are you experiencing?", "label_additional_details": "Additional details (optional)", From 47e0bc252ad009a9dfe99eb6bfbb2a675ef58a5c Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Fri, 28 Feb 2025 17:10:27 +0100 Subject: [PATCH 12/12] refine route properties to be sent to feedback --- src/components/FeedbackModal.vue | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/FeedbackModal.vue b/src/components/FeedbackModal.vue index d0138c64..497e8080 100644 --- a/src/components/FeedbackModal.vue +++ b/src/components/FeedbackModal.vue @@ -42,6 +42,22 @@ import { computed } from 'vue' import { BadRequestWithData } from './FeathersErrorManager.vue' import { useRoute } from 'vue-router' +export interface FeedbackFormPayloadWithRoute extends FeedbackFormPayload { + route: { + fullPath: string + params: Record + query: Record + name: string | null + } + errorMessages: { + id: string + code: number + name: string + message: string + route: string[] + }[] +} + const props = withDefaults( defineProps<{ dialogClass?: string @@ -83,9 +99,14 @@ const confirm = () => { } const handleSubmit = (payload: FeedbackFormPayload) => { - const payloadWithRoute = { + const payloadWithRoute: FeedbackFormPayloadWithRoute = { ...payload, - route: route.path, + route: { + fullPath: route.fullPath, + params: route.params, + query: route.query, + name: route.name as string | null + }, errorMessages: props.errorMessages } console.debug('[FeedbackModal] handleSubmit', payloadWithRoute)