From c14eef113d75c79fad7013ea49f7bc53bb0e39f0 Mon Sep 17 00:00:00 2001 From: Tobias Messner Date: Thu, 14 Nov 2024 10:59:09 +0100 Subject: [PATCH] feat: Allow customizing feedback hint and update dialog - Allow customizing the hint text. - Always show the text input to prevent layout shift - Enable dynamic sizing for hint to prevent layout issues --- .../settings/configuration/models.py | 4 ++ backend/tests/test_feedback.py | 2 + docs/docs/admin/configure-for-your-org.md | 1 + .../model/feedback-configuration-input.ts | 4 ++ .../model/feedback-configuration-output.ts | 4 ++ .../feedback-dialog.component.html | 45 +++++++++---------- .../feedback-dialog.stories.ts | 43 +++++++++++++++++- frontend/src/storybook/feedback.ts | 1 + 8 files changed, 80 insertions(+), 24 deletions(-) diff --git a/backend/capellacollab/settings/configuration/models.py b/backend/capellacollab/settings/configuration/models.py index 6382332c06..5dbb91d2c9 100644 --- a/backend/capellacollab/settings/configuration/models.py +++ b/backend/capellacollab/settings/configuration/models.py @@ -157,6 +157,10 @@ class FeedbackConfiguration(core_pydantic.BaseModelStrict): description="Email addresses to send feedback to.", examples=[[], ["test@example.com"]], ) + hint_text: str = pydantic.Field( + default="Try to be specific. What happened? What were you doing?", + description="Text to display as a hint in the feedback form.", + ) class BetaConfiguration(core_pydantic.BaseModelStrict): diff --git a/backend/tests/test_feedback.py b/backend/tests/test_feedback.py index b8fac1bc5e..a89b55be83 100644 --- a/backend/tests/test_feedback.py +++ b/backend/tests/test_feedback.py @@ -203,6 +203,7 @@ def test_feedback_is_updated( "on_session_card": True, "interval": {"enabled": True, "hours_between_prompt": 24}, "recipients": ["test@example.com"], + "hint_text": "test", } }, ) @@ -218,6 +219,7 @@ def test_feedback_is_updated( "on_session_card": True, "interval": {"enabled": True, "hours_between_prompt": 24}, "recipients": ["test@example.com"], + "hint_text": "test", } diff --git a/docs/docs/admin/configure-for-your-org.md b/docs/docs/admin/configure-for-your-org.md index 774c6866c2..c1adc2ee66 100644 --- a/docs/docs/admin/configure-for-your-org.md +++ b/docs/docs/admin/configure-for-your-org.md @@ -95,6 +95,7 @@ feedback: recipients: # (1)! - test1@example.com - test2@example.com + hint_text: Try to be specific. What happened? What were you doing? ``` Prompts that are associated with a session automatically include anonymized diff --git a/frontend/src/app/openapi/model/feedback-configuration-input.ts b/frontend/src/app/openapi/model/feedback-configuration-input.ts index 921877fd53..6d07bb741c 100644 --- a/frontend/src/app/openapi/model/feedback-configuration-input.ts +++ b/frontend/src/app/openapi/model/feedback-configuration-input.ts @@ -37,5 +37,9 @@ export interface FeedbackConfigurationInput { * Email addresses to send feedback to. */ recipients?: Array; + /** + * Text to display as a hint in the feedback form. + */ + hint_text?: string; } diff --git a/frontend/src/app/openapi/model/feedback-configuration-output.ts b/frontend/src/app/openapi/model/feedback-configuration-output.ts index 2f69bf3d7c..5b32d748c2 100644 --- a/frontend/src/app/openapi/model/feedback-configuration-output.ts +++ b/frontend/src/app/openapi/model/feedback-configuration-output.ts @@ -37,5 +37,9 @@ export interface FeedbackConfigurationOutput { * Email addresses to send feedback to. */ recipients: Array; + /** + * Text to display as a hint in the feedback form. + */ + hint_text: string; } diff --git a/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.component.html b/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.component.html index b711e18722..0ea4f68738 100644 --- a/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.component.html +++ b/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.component.html @@ -17,7 +17,7 @@

How were your sessions? }

-
+
@for (rating of ratings; track rating) {
- @if (feedbackForm.get("rating")?.value) { - - @if (feedbackForm.get("rating")?.value === "good") { - What was good? - } @else { - What can we do better? - } - - @if (feedbackForm.controls.feedbackText.hasError("maxlength")) { - - Your feedback can't be longer than 500 characters. - - } - Try to be specific. What happened? What were you doing? - - } + + @if (feedbackForm.get("rating")?.value === "good") { + What was good? + } @else { + What can we do better? + } + + + @if (feedbackForm.controls.feedbackText.hasError("maxlength")) { + + Your feedback can't be longer than 500 characters. + + } + {{ (feedbackWrapperService.feedbackConfig$ | async)?.hint_text }} + + diff --git a/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.stories.ts b/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.stories.ts index 54eeea726e..3ff91d298c 100644 --- a/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.stories.ts +++ b/frontend/src/app/sessions/feedback/feedback-dialog/feedback-dialog.stories.ts @@ -6,6 +6,10 @@ import { MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Meta, moduleMetadata, StoryObj } from '@storybook/angular'; import { userEvent, within } from '@storybook/test'; import { dialogWrapper } from 'src/storybook/decorators'; +import { + mockFeedbackConfig, + mockFeedbackWrapperServiceProvider, +} from '../../../../storybook/feedback'; import { mockPersistentSession } from '../../../../storybook/session'; import { FeedbackDialogComponent } from './feedback-dialog.component'; @@ -32,6 +36,43 @@ export const NoSessions: Story = { ], }; +export const ShortHint: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: MAT_DIALOG_DATA, + useValue: { sessions: [], trigger: 'storybook' }, + }, + mockFeedbackWrapperServiceProvider({ + ...mockFeedbackConfig, + hint_text: 'Hint', + }), + ], + }), + ], +}; + +export const LongHint: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: MAT_DIALOG_DATA, + useValue: { sessions: [], trigger: 'storybook' }, + }, + mockFeedbackWrapperServiceProvider({ + ...mockFeedbackConfig, + hint_text: + 'This is a very long hint text that should be displayed in the feedback dialog.', + }), + ], + }), + ], +}; + export const RatingSelected: Story = { args: {}, decorators: [ @@ -68,7 +109,7 @@ export const OneSession: Story = { ], }; -export const OneSessionWithUserInformation: Story = { +export const OneSessionWithoutUserInformation: Story = { args: {}, decorators: [ moduleMetadata({ diff --git a/frontend/src/storybook/feedback.ts b/frontend/src/storybook/feedback.ts index 851d9737f5..6ac9cf05e7 100644 --- a/frontend/src/storybook/feedback.ts +++ b/frontend/src/storybook/feedback.ts @@ -16,6 +16,7 @@ export const mockFeedbackConfig: FeedbackConfigurationOutput = { hours_between_prompt: 1, }, recipients: [], + hint_text: 'Hint text', }; class MockFeedbackWrapperService implements Partial {