feat(procurement): enable saving and editing notes on procurement tracker steps#5885
feat(procurement): enable saving and editing notes on procurement tracker steps#5885Santi-3rd wants to merge 8 commits into
Conversation
rajohnson90
left a comment
There was a problem hiding this comment.
AI PR review identified at least one problem that needs to be fixed:
frontend/.../ProcurementTrackerStepOne.hooks.js:24 — useEffect overwrites in-progress draft on RTK Query
refetch (CONFIRMED, same in all 6 hooks)
handleSaveNotes invalidates the "ProcurementTrackers" cache tag, triggering an immediate refetch. When
the new stepOneData.notes prop arrives, the useEffect fires setStep1Notes(stepOneData?.notes ?? "") —
overwriting keystrokes typed since the last save. Race: user clicks Save → types more text → refetch
resolves → effect resets the field to the older saved value. Fix: skip the effect when the field is dirty
(track with a isDirty ref, reset after a successful save).
| * @param {string} value - The new notes value. | ||
| */ | ||
| const setNotes = React.useCallback((value) => { | ||
| isDirtyRef.current = true; |
There was a problem hiding this comment.
setNotes marks the field dirty unconditionally, so Cancel (and completion) leave it permanently dirty.
setNotes always sets isDirtyRef.current = true, even when the caller is restoring the server value rather than typing a fresh edit. StepNotesEditor’s Cancel handler calls setNotes(savedNotes ?? ""), which brings the field value back in line with the server but leaves the dirty flag true.
Per this hook’s own docstring, the sync-from-server effect is supposed to resume once the field is clean again. After a Cancel it never will (the flag is only cleared on a successful save), so a later external server update — another user editing the note, or a refetch delivering a newer value — won’t flow into the field. The completion handlers (handleStep1Complete, etc.) have the same issue: they send notes but never clear the flag.
Suggestion: expose a resetNotes(value) (or clearDirty) from useSaveNotes that sets the value and clears isDirtyRef, and use it in the Cancel path (and after completion). Edge-case severity, but it contradicts the documented intent and none of the current tests cover it.
|
Duplicated inline "Save Notes" block across all 6 step files — Medium The active-step editing markup ( + TextArea with textAreaStyle={{ height: "8.5rem", minWidth: "30rem" }} + maxLength={750} + the faCheck "Save Notes" button) is copy-pasted verbatim into all six
ProcurementTrackerStep*.jsx files, and is nearly identical to the editing branch already inside StepNotesEditor.jsx. This is the exact repetition the branch set out to remove (refactor: removed repeated code). Extract a shared SaveNotesButton (or let StepNotesEditor cover the active-step form too) so the style constants and button live in one place. |
What changed
Enables users to save notes on procurement tracker steps independently of completing the step, and to edit notes on steps that are already completed.
Frontend —
frontend/src/components/Agreements/ProcurementTracker/ProcurementTrackerStep{One..Six}/TextAreais now enabled independently of the step's completion / pre-solicitation state, with a dedicated Save Notes button (data-cy="save-notes-button") that PATCHes only thenotesfield and surfaces a success/error alert.stepXData?.notesand stays in sync via auseEffect, so previously saved notes are shown.handleSaveNotesto each step's hook and wired it through the component.Backend —
backend/ops_api/ops/validation/rules/procurement_tracker_step.pyNoUpdatingCompletedProcurementStepRulenow allows a notes-only update on a completed step (viaEDITABLE_AFTER_COMPLETION = {"notes"}) while still blocking any other field change.AcquisitionPlanningRequiredFieldsRuleonly enforcestask_completed_by/date_completedwhen the step is actually being moved to complete, and treats fields already persisted on the step as satisfied — so notes-only edits and partial updates aren't wrongly rejected.Tests
Issue
#5435
How to test
Backend:
cd backend/ops_api pipenv run pytest tests/ops/features/test_validate_procurement_tracker_steps.py pipenv run pytest tests/ops/procurement_tracker/test_procurement_tracker_steps_api.pyFrontend:
Manual:
A11y impact
A11Y-SUPPRESSIONmetadata (owner, expires, rationale)Storybook
src/components/UI/Screenshots
Definition of Done Checklist
Links
N/A