mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-18 08:35:22 +00:00
998716ae49
* feat: unified item timeline with comment-on-update, threading, and reactions (IDEA-115) Replace the separate Comments section and Version History modal on the item detail page with a single chronological timeline that interleaves comments, activities, and content versions. Key changes: - Add --comment flag to `pad item update` so agents/users can explain status changes inline (creates a comment linked to the activity) - Add threaded replies (parent_id on comments) with inline reply UI - Add emoji reactions on comments (new comment_reactions table) - New /timeline API endpoint merges comments, activities, and versions server-side with dedup and collapsing of rapid edits - New Svelte timeline components: ItemTimeline, TimelineCommentCard, TimelineActivityCard, TimelineVersionCard, ReactionPicker - Remove Implementation Notes and Decision Log inputs from web UI - Update skill docs to encourage --comment on status changes * fix: address review findings for PR #54 (iteration 1) - Use ListItemVersions instead of ListVersions in timeline endpoint so item content history renders correctly - Add workspace validation to reply and reaction handlers to prevent cross-workspace comment mutation - Raise activity cap from 500 to 10000 to avoid silently truncating long timelines - Fix toggleReaction to always POST (idempotent) instead of incorrectly matching other users' reactions for DELETE - Await onReply promise before clearing draft to prevent duplicate submissions and lost drafts on failure - Register reaction_added/reaction_removed in SSE ITEM_EVENTS so reactions from other sessions appear in real-time Co-Authored-By: Claude <noreply@anthropic.com> * fix: address review findings for PR #54 (iteration 2) - Fix nil pointer dereference in timeline handler when item not found - Store empty string instead of NULL for reaction user_id so UNIQUE constraint works correctly in SQLite - Add workspace validation to handleDeleteComment (cross-workspace deletion was possible) - Fix SKILL.md duplicate numbering (4. appeared twice) - Remove || true debug artifacts from reaction conditionals - Replace SvelteMap with plain Map in non-reactive groupReactions - Use != null checks for timeline API params to handle offset=0 - Log warning on comment creation failure during item update Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
48 lines
1.5 KiB
Go
48 lines
1.5 KiB
Go
package models
|
|
|
|
import "time"
|
|
|
|
// Comment represents a comment on an item.
|
|
type Comment struct {
|
|
ID string `json:"id"`
|
|
ItemID string `json:"item_id"`
|
|
WorkspaceID string `json:"workspace_id"`
|
|
Author string `json:"author"`
|
|
Body string `json:"body"`
|
|
CreatedBy string `json:"created_by"`
|
|
Source string `json:"source"`
|
|
ActivityID string `json:"activity_id,omitempty"`
|
|
ParentID string `json:"parent_id,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
// Populated by joins (not stored)
|
|
ItemTitle string `json:"item_title,omitempty"`
|
|
ItemSlug string `json:"item_slug,omitempty"`
|
|
|
|
// Populated by handlers for threaded views
|
|
Replies []Comment `json:"replies,omitempty"`
|
|
Reactions []Reaction `json:"reactions,omitempty"`
|
|
}
|
|
|
|
// CommentCreate is the input for creating a new comment.
|
|
type CommentCreate struct {
|
|
Author string `json:"author,omitempty"`
|
|
Body string `json:"body"`
|
|
CreatedBy string `json:"created_by,omitempty"`
|
|
Source string `json:"source,omitempty"`
|
|
ParentID string `json:"parent_id,omitempty"`
|
|
ActivityID string `json:"activity_id,omitempty"`
|
|
}
|
|
|
|
// Reaction represents an emoji reaction on a comment.
|
|
type Reaction struct {
|
|
ID string `json:"id"`
|
|
CommentID string `json:"comment_id"`
|
|
UserID string `json:"user_id,omitempty"`
|
|
Actor string `json:"actor"`
|
|
Emoji string `json:"emoji"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
ActorName string `json:"actor_name,omitempty"`
|
|
}
|