feat(web/bugs): show previous title in changes

Amolith and Crush created

Title change events now display both the old title
(strikethrough) and new title (underline) using semantic
HTML tags (<del> and <ins>), providing better context for
how bug titles have evolved over time.

Implements: bug-ef59d5b
Co-authored-by: Crush <crush@charm.land>

Change summary

pkg/web/templates/bug.html |  2 +-
pkg/web/webui_bugs.go      | 14 ++++++++------
2 files changed, 9 insertions(+), 7 deletions(-)

Detailed changes

pkg/web/templates/bug.html 🔗

@@ -58,7 +58,7 @@
   
   {{else if eq .Type "title"}}
   <article id="{{.ID}}">
-    <p>{{if .AuthorAvatar}}<img src="{{.AuthorAvatar}}" alt="" class="avatar avatar-timeline" loading="lazy" referrerpolicy="no-referrer">{{end}}<strong>{{.Author}}</strong> changed the title to <strong>{{.Title}}</strong> <time datetime="{{.Timestamp | rfc3339}}" data-tooltip="{{.Timestamp | formatDate}}">{{.Timestamp | relativeTime}}</time></p>
+    <p>{{if .AuthorAvatar}}<img src="{{.AuthorAvatar}}" alt="" class="avatar avatar-timeline" loading="lazy" referrerpolicy="no-referrer">{{end}}<strong>{{.Author}}</strong> changed the title from <del>{{.PreviousTitle}}</del> to <ins>{{.Title}}</ins> <time datetime="{{.Timestamp | rfc3339}}" data-tooltip="{{.Timestamp | formatDate}}">{{.Timestamp | relativeTime}}</time></p>
   </article>
   
   {{else if eq .Type "status"}}

pkg/web/webui_bugs.go 🔗

@@ -68,6 +68,7 @@ type TimelineItem struct {
 
 	Message       template.HTML
 	Title         string
+	PreviousTitle string
 	Status        string
 	AddedLabels   []Label
 	RemovedLabels []Label
@@ -237,12 +238,13 @@ func buildTimelineItems(snap *bug.Snapshot) []TimelineItem {
 
 		case *bug.SetTitleTimelineItem:
 			items = append(items, TimelineItem{
-				Type:         "title",
-				ID:           op.CombinedId().String(),
-				Author:       op.Author.DisplayName(),
-				AuthorAvatar: op.Author.AvatarUrl(),
-				Timestamp:    op.UnixTime.Time(),
-				Title:        op.Title,
+				Type:          "title",
+				ID:            op.CombinedId().String(),
+				Author:        op.Author.DisplayName(),
+				AuthorAvatar:  op.Author.AvatarUrl(),
+				Timestamp:     op.UnixTime.Time(),
+				Title:         op.Title,
+				PreviousTitle: op.Was,
 			})
 
 		case *bug.SetStatusTimelineItem: