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: the replies list includes placeholder notes again; only drafts are excluded. The replies template gets two v-if branches before the existing system and noteable ones: PlaceholderSystemNote when placeholderType === SYSTEM_NOTE (a quick action being applied), otherwise PlaceholderNote. Both receive note.notes[0] and use note.id as key.
  • New app/assets/javascripts/rapid_diffs/app/discussions/placeholder_note.vue: renders the placeholder with the Rapid Diffs TimelineEntryItem and NoteHeader, body via renderMarkdown and renderGFM, classes note 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 shared PlaceholderNote uses. The merge request page sets it in app/assets/javascripts/mr_notes/init_mr_notes.js via useNotes().setUserData.
  • New app/assets/javascripts/rapid_diffs/app/discussions/placeholder_system_note.vue: renders note.body in an <em> inside the Rapid Diffs TimelineEntryItem, data-testid="placeholder-system-note".
  • Specs: discussion_notes_spec.js tests that a placeholder reply renders through PlaceholderNote with the inner note, and a system placeholder through PlaceholderSystemNote. New placeholder_note_spec.js tests 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-if branches 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 with VUE_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 the vue3_migrate_mr_rapid_diffs migration 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

Merge request reports

Loading
Loading