Conversation
|
@kelockhart Would you see if the video demo looks good before I include Tim for the code review? |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #814 +/- ##
========================================
- Coverage 62.0% 62.0% -0.0%
========================================
Files 317 317
Lines 36536 36536
Branches 1642 1642
========================================
- Hits 22621 22620 -1
- Misses 13878 13879 +1
Partials 37 37 🚀 New features to boost your workflow:
|
|
@shinyichen the functionality looks good! But I wonder if the little icon will be noticed. Can you try adding "feedback" or something next to the icon? |
0f546cd to
95df1c0
Compare
|
@kelockhart Please see updated screen capture. |
|
@shinyichen yes! Looks great, no more feedback on my end. |
There was a problem hiding this comment.
Pull request overview
Adds a “Feedback” entry point from the Abstract UAT Keywords section that routes users to the General Feedback form with a prefilled subject and record identifier.
Changes:
- Add a “Feedback” button to the UAT Keywords block on abstract details and navigate to the general feedback route with query params.
- Update the General Feedback page to prefill the comment body and email subject from
router.query. - Expand feedback
_subjecttyping to include the new UAT-specific subject.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/pages/feedback/general.tsx |
Reads subject/id from query to prefill comments and _subject during submission. |
src/components/AbstractDetails/AbstractDetails.tsx |
Adds UAT “Feedback” button that routes to general feedback with record id + subject. |
src/api/feedback/types.ts |
Updates _subject typing to allow the new UAT feedback subject (and currently any string). |
Comments suppressed due to low confidence (2)
src/pages/feedback/general.tsx:125
_subject: !!subject ? subject : 'Nectar Feedback'can pass astring[]through to the API if the query contains repeatedsubjectparams. Normalizesubjectto a single string before using it, and consider whitelisting allowed subjects so this endpoint isn't accepting arbitrary query-controlled subject lines.
{
name,
_replyto: email,
_subject: !!subject ? subject : 'Nectar Feedback',
'feedback-type': 'feedback',
'user-agent-string': globalThis?.navigator?.userAgent,
origin: 'bbb_feedback', // indicate general feedback
'g-recaptcha-response': recaptchaToken,
src/pages/feedback/general.tsx:88
useForm({ defaultValues })only appliesdefaultValueson the first mount. On client-side navigation,router.querymay be empty untilrouter.isReadyis true, so the comments prefill can be skipped. Consider callingreset(...)in an effect whenrouter.isReadyand the normalizedsubject/idare available (or passvaluestouseFormif you intend it to be reactive).
const initialFormValues: FormValues = {
name: '',
email: userEmail ?? '',
comments: !!subject && subject === 'UAT keywords feedback' ? `UAT Keywords feedback on record: ${id}\n\n` : '',
};
const formMethods = useForm<FormValues>({
defaultValues: initialFormValues,
resolver: zodResolver(validationSchema),
mode: 'onSubmit',
reValidateMode: 'onBlur',
shouldFocusError: true,
});
| const router = useRouter(); | ||
|
|
||
| const handleUATFeedback = () => { | ||
| void router.push({ | ||
| pathname: feedbackItems.general.path, | ||
| query: { id: doc.bibcode ? doc.bibcode : doc.identifier?.[0], subject: 'UAT keywords feedback' }, | ||
| }); | ||
| }; |
There was a problem hiding this comment.
handleUATFeedback is re-created on every render and passed into a memo(..., equals) component. Since equals compares function props by reference, this defeats memoization and can cause unnecessary rerenders of the (potentially large) UAT keyword list. Wrap handleUATFeedback in useCallback (with the needed deps) or pass a stable callback/URL into UATKeywords.
| | 'UAT keywords feedback' | ||
| | string; |
There was a problem hiding this comment.
Adding | string to FeedbackBaseParams._subject makes the literal union effectively untyped and removes most compile-time protection against invalid subjects across the codebase. If you only need to support the new UAT flow, keep _subject as a strict union (add 'UAT keywords feedback' only) and validate/coerce the query param on the general feedback page before assigning it.
| | 'UAT keywords feedback' | |
| | string; | |
| | 'UAT keywords feedback'; |
| const { subject, id } = router.query; | ||
|
|
||
| const initialFormValues: FormValues = { | ||
| name: '', | ||
| email: userEmail ?? '', | ||
| comments: '', | ||
| comments: !!subject && subject === 'UAT keywords feedback' ? `UAT Keywords feedback on record: ${id}\n\n` : '', | ||
| }; |
There was a problem hiding this comment.
router.query values are string | string[] | undefined. Here subject === 'UAT keywords feedback' and template-interpolating ${id} will behave unexpectedly for string[] (and can produce undefined in the prefill). Normalize subject/id to strings (e.g., take first element) before comparing/using them, and avoid prefilling when id is missing.
thostetler
left a comment
There was a problem hiding this comment.
I think the changes look generally pretty good. If we end up doing this sort of then again, we'll want to generalize it more so that we don't have the logic for this one case in the main email config.
I just have one small thing I mentioned
| name, | ||
| _replyto: email, | ||
| _subject: 'Nectar Feedback', | ||
| _subject: !!subject ? subject : 'Nectar Feedback', |
There was a problem hiding this comment.
I think we shouldn't allow the subject get passed in here directly.
Let's use an enum and force the subject to be uat-keywords that maps to "UAT Keywords..." or something like that, otherwise it defaults back to "Nectar Feedback"
Just to make sure that we can't have arbitrary strings getting into the subject directly.

Add a feedback button link in abstract UAT keywords. When clicked, link to general feedback prefilled with subject and record ID
Screen.Recording.2026-02-27.at.2.25.46.PM.mov