Render reply placeholders in Rapid Diffs discussions
Why
When a user replies to a diff discussion, the notes store inserts an optimistic placeholder note (isPlaceholderNote: true, placeholderType, body in notes[0].body, no author) until the server saves the reply. The legacy notes UI (app/assets/javascripts/notes/components/discussion_notes.vue) shows it as a "being posted" note through the shared PlaceholderNote and PlaceholderSystemNote components.
Rapid Diffs, the new merge request diff view, never showed it. Under Vue 2 the placeholder was routed through noteable_note.vue, which threw on the missing author; Vue 2 swallowed the error and rendered blank. The base MR !255283 (closed) fixes the crash by skipping placeholders. This MR adds the missing feedback: the reply appears at once, marked as being posted, and is replaced by the saved note.
What
app/assets/javascripts/rapid_diffs/app/discussions/discussion_notes.vue: thereplieslist includes placeholder notes again; only drafts are excluded. The replies template gets twov-ifbranches before the existing system and noteable ones:PlaceholderSystemNotewhenplaceholderType === SYSTEM_NOTE(a quick action being applied), otherwisePlaceholderNote. Both receivenote.notes[0]and usenote.idas key.- New
app/assets/javascripts/rapid_diffs/app/discussions/placeholder_note.vue: renders the placeholder with the Rapid DiffsTimelineEntryItemandNoteHeader, body viarenderMarkdownandrenderGFM, classesnote note-wrapper being-posted fade-in-half,data-testid="placeholder-note". The author is the current user from the notes store,mapState(useNotes, ['getUserData'])(~/notes/store/legacy_notes), the same source the sharedPlaceholderNoteuses. The merge request page sets it inapp/assets/javascripts/mr_notes/init_mr_notes.jsviauseNotes().setUserData. - New
app/assets/javascripts/rapid_diffs/app/discussions/placeholder_system_note.vue: rendersnote.bodyin an<em>inside the Rapid DiffsTimelineEntryItem,data-testid="placeholder-system-note". - Specs:
discussion_notes_spec.jstests that a placeholder reply renders throughPlaceholderNotewith the inner note, and a system placeholder throughPlaceholderSystemNote. Newplaceholder_note_spec.jstests that the author comes from the store user data and that the body renders as markdown.
How
The two components follow the Rapid Diffs note layout (TimelineEntryItem with a #content slot, Tailwind spacing) rather than the shared vue_shared/components/notes/placeholder_note.vue, which is built on the legacy .timeline-entry layout and would render with the wrong structure inside the Rapid Diffs timeline. The layout and classes come from !255075 (merged) by @thomasrandolph, which took the same approach.
Differences from !255075 (merged):
- The author comes from the notes store instead of
window.gon, so it matches the shared component and the rest of the notes UI. - The template uses
v-ifbranches like the legacy component, instead of three helper methods and a dynamic<component :is>. note.id(a UUID set by the store) is the key for placeholders, so no key helper is needed.
Stacked on !255283 (closed) (the crash fix). Merge that first, then retarget this MR to master.
How to verify
yarn jest spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.js spec/frontend/rapid_diffs/app/discussions/placeholder_note_spec.js, and the same withVUE_VERSION=3, pass with 34 examples.- Manually in GDK: open a merge request's Changes tab, comment on a diff line, reply to the thread. The reply appears immediately, faded, with the current user's avatar and name, then is replaced by the saved note. Reply with a quick action only (for example
/assign me) to see a faded italic system placeholder. This works with Vue 2 and, with thevue3_migrate_mr_rapid_diffsmigration files from !255209 (closed), with Vue 3.
Screenshots or screen recordings
TODO: before and after screenshots of the placeholder.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.
References
- Base MR, merge first: !255283 (closed)
- Issue for the crash: #628791 (closed)
- Original implementation this is derived from: !255075 (merged)
- Vue 3 migration of the Rapid Diffs page: !255209 (closed)
- Vue 3 migration (Code Review) epic: gitlab-org#23167