feat(web): order the home page by last activity and move repositories up live
- commit
- 427726483415e5fdfc0b1c4aae86aea88a80a1fa
- author
- brice · · 2026-10-19 15:48 UTC
- parent
- 4fc291e
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
28 files · +816 -525
M gen/ermite/storage/repo.pb.go +22 -11 generated file: collapsed
M internal/adapters/kvstore/repos.go +2 -0
| @@ -208,6 +208,7 @@ func encodeRepo(r domain.Repo) ([]byte, error) { | |||
| 208 | 208 | Visibility: vis, | |
| 209 | 209 | CreatedAt: encodeTime(r.CreatedAt), | |
| 210 | 210 | PushedAt: encodeTime(r.PushedAt), | |
| 211 | + | ActiveAt: encodeTime(r.ActiveAt), | |
| 211 | 212 | Settings: pbSettings, | |
| 212 | 213 | } | |
| 213 | 214 | return mustMarshal(pb), nil | |
| @@ -229,6 +230,7 @@ func decodeRepo(val []byte) (domain.Repo, error) { | |||
| 229 | 230 | Visibility: decodeVisibility(pb.GetVisibility()), | |
| 230 | 231 | CreatedAt: decodeTime(pb.GetCreatedAt()), | |
| 231 | 232 | PushedAt: decodeTime(pb.GetPushedAt()), | |
| 233 | + | ActiveAt: decodeTime(pb.GetActiveAt()), | |
| 232 | 234 | Settings: decodeSettings(pb.GetSettings()), | |
| 233 | 235 | }, nil | |
| 234 | 236 | } | |
| @@ -208,6 +208,7 @@ func encodeRepo(r domain.Repo) ([]byte, error) { | |||||
| 208 | Visibility: vis, | 208 | Visibility: vis, | ||
| 209 | CreatedAt: encodeTime(r.CreatedAt), | 209 | CreatedAt: encodeTime(r.CreatedAt), | ||
| 210 | PushedAt: encodeTime(r.PushedAt), | 210 | PushedAt: encodeTime(r.PushedAt), | ||
| 211 | + | ActiveAt: encodeTime(r.ActiveAt), | |||
| 211 | Settings: pbSettings, | 212 | Settings: pbSettings, | ||
| 212 | } | 213 | } | ||
| 213 | return mustMarshal(pb), nil | 214 | return mustMarshal(pb), nil | ||
| @@ -229,6 +230,7 @@ func decodeRepo(val []byte) (domain.Repo, error) { | |||||
| 229 | Visibility: decodeVisibility(pb.GetVisibility()), | 230 | Visibility: decodeVisibility(pb.GetVisibility()), | ||
| 230 | CreatedAt: decodeTime(pb.GetCreatedAt()), | 231 | CreatedAt: decodeTime(pb.GetCreatedAt()), | ||
| 231 | PushedAt: decodeTime(pb.GetPushedAt()), | 232 | PushedAt: decodeTime(pb.GetPushedAt()), | ||
| 233 | + | ActiveAt: decodeTime(pb.GetActiveAt()), | |||
| 232 | Settings: decodeSettings(pb.GetSettings()), | 234 | Settings: decodeSettings(pb.GetSettings()), | ||
| 233 | }, nil | 235 | }, nil | ||
| 234 | } | 236 | } | ||
M internal/adapters/kvstore/store_test.go +2 -1
| @@ -43,7 +43,7 @@ func TestCreateGetListUpdateDelete(t *testing.T) { | |||
| 43 | 43 | s := openStore(t, t.TempDir()) | |
| 44 | 44 | ||
| 45 | 45 | b := domain.Repo{Name: name(t, "b"), Description: "second", Topics: []string{"cli", "go"}, Visibility: domain.VisibilityPublic, CreatedAt: created, Settings: domain.DefaultRepoSettings()} | |
| 46 | - | a := domain.Repo{Name: name(t, "a"), Visibility: domain.VisibilityPrivate, CreatedAt: created, PushedAt: created.Add(time.Hour), Settings: domain.DefaultRepoSettings()} | |
| 46 | + | a := domain.Repo{Name: name(t, "a"), Visibility: domain.VisibilityPrivate, CreatedAt: created, PushedAt: created.Add(time.Hour), ActiveAt: created.Add(2 * time.Hour), Settings: domain.DefaultRepoSettings()} | |
| 47 | 47 | require.NoError(t, s.Create(ctx, b)) | |
| 48 | 48 | require.NoError(t, s.Create(ctx, a)) | |
| 49 | 49 | ||
| @@ -54,6 +54,7 @@ func TestCreateGetListUpdateDelete(t *testing.T) { | |||
| 54 | 54 | require.NoError(t, err) | |
| 55 | 55 | assert.Equal(t, a, got) | |
| 56 | 56 | assert.True(t, got.PushedAt.Equal(a.PushedAt)) | |
| 57 | + | assert.True(t, got.ActiveAt.Equal(a.ActiveAt)) | |
| 57 | 58 | ||
| 58 | 59 | list, err := s.List(ctx) | |
| 59 | 60 | require.NoError(t, err) | |
| @@ -43,7 +43,7 @@ func TestCreateGetListUpdateDelete(t *testing.T) { | |||||
| 43 | s := openStore(t, t.TempDir()) | 43 | s := openStore(t, t.TempDir()) | ||
| 44 | 44 | ||||
| 45 | b := domain.Repo{Name: name(t, "b"), Description: "second", Topics: []string{"cli", "go"}, Visibility: domain.VisibilityPublic, CreatedAt: created, Settings: domain.DefaultRepoSettings()} | 45 | b := domain.Repo{Name: name(t, "b"), Description: "second", Topics: []string{"cli", "go"}, Visibility: domain.VisibilityPublic, CreatedAt: created, Settings: domain.DefaultRepoSettings()} | ||
| 46 | - | a := domain.Repo{Name: name(t, "a"), Visibility: domain.VisibilityPrivate, CreatedAt: created, PushedAt: created.Add(time.Hour), Settings: domain.DefaultRepoSettings()} | 46 | + | a := domain.Repo{Name: name(t, "a"), Visibility: domain.VisibilityPrivate, CreatedAt: created, PushedAt: created.Add(time.Hour), ActiveAt: created.Add(2 * time.Hour), Settings: domain.DefaultRepoSettings()} |
| 47 | require.NoError(t, s.Create(ctx, b)) | 47 | require.NoError(t, s.Create(ctx, b)) | ||
| 48 | require.NoError(t, s.Create(ctx, a)) | 48 | require.NoError(t, s.Create(ctx, a)) | ||
| 49 | 49 | ||||
| @@ -54,6 +54,7 @@ func TestCreateGetListUpdateDelete(t *testing.T) { | |||||
| 54 | require.NoError(t, err) | 54 | require.NoError(t, err) | ||
| 55 | assert.Equal(t, a, got) | 55 | assert.Equal(t, a, got) | ||
| 56 | assert.True(t, got.PushedAt.Equal(a.PushedAt)) | 56 | assert.True(t, got.PushedAt.Equal(a.PushedAt)) | ||
| 57 | + | assert.True(t, got.ActiveAt.Equal(a.ActiveAt)) | |||
| 57 | 58 | ||||
| 58 | list, err := s.List(ctx) | 59 | list, err := s.List(ctx) | ||
| 59 | require.NoError(t, err) | 60 | require.NoError(t, err) | ||
M internal/adapters/web/components.templ +2 -2
| @@ -37,7 +37,7 @@ templ CloneBlock(c Clone) { | |||
| 37 | 37 | // right its figures and CI state over its newest commits. Its id is the | |
| 38 | 38 | // target of SSE swaps; the name link comes first, `enter` follows it. | |
| 39 | 39 | templ HomeRowView(r HomeRow) { | |
| 40 | - | <li id={ r.ID } class="repo" data-cursor?={ r.Cursor }> | |
| 40 | + | <li id={ r.ID } class="repo" data-cursor?={ r.Cursor } data-activity?={ r.Fresh }> | |
| 41 | 41 | <div class="repo-main"> | |
| 42 | 42 | <h2 class="repo-name"> | |
| 43 | 43 | <a href={ templ.SafeURL(r.Href) }>{ r.Name }</a> | |
| @@ -45,7 +45,7 @@ templ HomeRowView(r HomeRow) { | |||
| 45 | 45 | <span class="pill">private</span> | |
| 46 | 46 | } | |
| 47 | 47 | if r.Fresh { | |
| 48 | - | <span class="pill new">new push</span> | |
| 48 | + | <span class="pill new">new activity</span> | |
| 49 | 49 | } | |
| 50 | 50 | </h2> | |
| 51 | 51 | if r.Desc != "" { | |
| @@ -37,7 +37,7 @@ templ CloneBlock(c Clone) { | |||||
| 37 | // right its figures and CI state over its newest commits. Its id is the | 37 | // right its figures and CI state over its newest commits. Its id is the | ||
| 38 | // target of SSE swaps; the name link comes first, `enter` follows it. | 38 | // target of SSE swaps; the name link comes first, `enter` follows it. | ||
| 39 | templ HomeRowView(r HomeRow) { | 39 | templ HomeRowView(r HomeRow) { | ||
| 40 | - | <li id={ r.ID } class="repo" data-cursor?={ r.Cursor }> | 40 | + | <li id={ r.ID } class="repo" data-cursor?={ r.Cursor } data-activity?={ r.Fresh }> |
| 41 | <div class="repo-main"> | 41 | <div class="repo-main"> | ||
| 42 | <h2 class="repo-name"> | 42 | <h2 class="repo-name"> | ||
| 43 | <a href={ templ.SafeURL(r.Href) }>{ r.Name }</a> | 43 | <a href={ templ.SafeURL(r.Href) }>{ r.Name }</a> | ||
| @@ -45,7 +45,7 @@ templ HomeRowView(r HomeRow) { | |||||
| 45 | <span class="pill">private</span> | 45 | <span class="pill">private</span> | ||
| 46 | } | 46 | } | ||
| 47 | if r.Fresh { | 47 | if r.Fresh { | ||
| 48 | - | <span class="pill new">new push</span> | 48 | + | <span class="pill new">new activity</span> |
| 49 | } | 49 | } | ||
| 50 | </h2> | 50 | </h2> | ||
| 51 | if r.Desc != "" { | 51 | if r.Desc != "" { | ||
M internal/adapters/web/components_templ.go +119 -113
| @@ -195,7 +195,13 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 195 | 195 | return templ_7745c5c3_Err | |
| 196 | 196 | } | |
| 197 | 197 | } | |
| 198 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "><div class=\"repo-main\"><h2 class=\"repo-name\"><a href=\"") | |
| 198 | + | if r.Fresh { | |
| 199 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " data-activity") | |
| 200 | + | if templ_7745c5c3_Err != nil { | |
| 201 | + | return templ_7745c5c3_Err | |
| 202 | + | } | |
| 203 | + | } | |
| 204 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "><div class=\"repo-main\"><h2 class=\"repo-name\"><a href=\"") | |
| 199 | 205 | if templ_7745c5c3_Err != nil { | |
| 200 | 206 | return templ_7745c5c3_Err | |
| 201 | 207 | } | |
| @@ -208,7 +214,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 208 | 214 | if templ_7745c5c3_Err != nil { | |
| 209 | 215 | return templ_7745c5c3_Err | |
| 210 | 216 | } | |
| 211 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">") | |
| 217 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">") | |
| 212 | 218 | if templ_7745c5c3_Err != nil { | |
| 213 | 219 | return templ_7745c5c3_Err | |
| 214 | 220 | } | |
| @@ -221,28 +227,28 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 221 | 227 | if templ_7745c5c3_Err != nil { | |
| 222 | 228 | return templ_7745c5c3_Err | |
| 223 | 229 | } | |
| 224 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</a> ") | |
| 230 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</a> ") | |
| 225 | 231 | if templ_7745c5c3_Err != nil { | |
| 226 | 232 | return templ_7745c5c3_Err | |
| 227 | 233 | } | |
| 228 | 234 | if r.Private { | |
| 229 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<span class=\"pill\">private</span> ") | |
| 235 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<span class=\"pill\">private</span> ") | |
| 230 | 236 | if templ_7745c5c3_Err != nil { | |
| 231 | 237 | return templ_7745c5c3_Err | |
| 232 | 238 | } | |
| 233 | 239 | } | |
| 234 | 240 | if r.Fresh { | |
| 235 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<span class=\"pill new\">new push</span>") | |
| 241 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<span class=\"pill new\">new activity</span>") | |
| 236 | 242 | if templ_7745c5c3_Err != nil { | |
| 237 | 243 | return templ_7745c5c3_Err | |
| 238 | 244 | } | |
| 239 | 245 | } | |
| 240 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</h2>") | |
| 246 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</h2>") | |
| 241 | 247 | if templ_7745c5c3_Err != nil { | |
| 242 | 248 | return templ_7745c5c3_Err | |
| 243 | 249 | } | |
| 244 | 250 | if r.Desc != "" { | |
| 245 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<p class=\"repo-desc\">") | |
| 251 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<p class=\"repo-desc\">") | |
| 246 | 252 | if templ_7745c5c3_Err != nil { | |
| 247 | 253 | return templ_7745c5c3_Err | |
| 248 | 254 | } | |
| @@ -255,18 +261,18 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 255 | 261 | if templ_7745c5c3_Err != nil { | |
| 256 | 262 | return templ_7745c5c3_Err | |
| 257 | 263 | } | |
| 258 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</p>") | |
| 264 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</p>") | |
| 259 | 265 | if templ_7745c5c3_Err != nil { | |
| 260 | 266 | return templ_7745c5c3_Err | |
| 261 | 267 | } | |
| 262 | 268 | } else { | |
| 263 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<p class=\"repo-desc mute\">no description</p>") | |
| 269 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<p class=\"repo-desc mute\">no description</p>") | |
| 264 | 270 | if templ_7745c5c3_Err != nil { | |
| 265 | 271 | return templ_7745c5c3_Err | |
| 266 | 272 | } | |
| 267 | 273 | } | |
| 268 | 274 | if len(r.Topics) > 0 { | |
| 269 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<ul class=\"repo-topics\" aria-label=\"") | |
| 275 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<ul class=\"repo-topics\" aria-label=\"") | |
| 270 | 276 | if templ_7745c5c3_Err != nil { | |
| 271 | 277 | return templ_7745c5c3_Err | |
| 272 | 278 | } | |
| @@ -279,12 +285,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 279 | 285 | if templ_7745c5c3_Err != nil { | |
| 280 | 286 | return templ_7745c5c3_Err | |
| 281 | 287 | } | |
| 282 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" data-fit>") | |
| 288 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" data-fit>") | |
| 283 | 289 | if templ_7745c5c3_Err != nil { | |
| 284 | 290 | return templ_7745c5c3_Err | |
| 285 | 291 | } | |
| 286 | 292 | for _, t := range r.Topics { | |
| 287 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<li>") | |
| 293 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<li>") | |
| 288 | 294 | if templ_7745c5c3_Err != nil { | |
| 289 | 295 | return templ_7745c5c3_Err | |
| 290 | 296 | } | |
| @@ -297,17 +303,17 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 297 | 303 | if templ_7745c5c3_Err != nil { | |
| 298 | 304 | return templ_7745c5c3_Err | |
| 299 | 305 | } | |
| 300 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</li>") | |
| 306 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</li>") | |
| 301 | 307 | if templ_7745c5c3_Err != nil { | |
| 302 | 308 | return templ_7745c5c3_Err | |
| 303 | 309 | } | |
| 304 | 310 | } | |
| 305 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</ul>") | |
| 311 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</ul>") | |
| 306 | 312 | if templ_7745c5c3_Err != nil { | |
| 307 | 313 | return templ_7745c5c3_Err | |
| 308 | 314 | } | |
| 309 | 315 | } else { | |
| 310 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"repo-topics\" aria-hidden=\"true\"></div>") | |
| 316 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"repo-topics\" aria-hidden=\"true\"></div>") | |
| 311 | 317 | if templ_7745c5c3_Err != nil { | |
| 312 | 318 | return templ_7745c5c3_Err | |
| 313 | 319 | } | |
| @@ -318,12 +324,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 318 | 324 | return templ_7745c5c3_Err | |
| 319 | 325 | } | |
| 320 | 326 | } else { | |
| 321 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"repo-pulse\" aria-hidden=\"true\"></div>") | |
| 327 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<div class=\"repo-pulse\" aria-hidden=\"true\"></div>") | |
| 322 | 328 | if templ_7745c5c3_Err != nil { | |
| 323 | 329 | return templ_7745c5c3_Err | |
| 324 | 330 | } | |
| 325 | 331 | } | |
| 326 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</div><div class=\"repo-head\"><dl class=\"repo-stats\" aria-label=\"") | |
| 332 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div><div class=\"repo-head\"><dl class=\"repo-stats\" aria-label=\"") | |
| 327 | 333 | if templ_7745c5c3_Err != nil { | |
| 328 | 334 | return templ_7745c5c3_Err | |
| 329 | 335 | } | |
| @@ -336,12 +342,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 336 | 342 | if templ_7745c5c3_Err != nil { | |
| 337 | 343 | return templ_7745c5c3_Err | |
| 338 | 344 | } | |
| 339 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">") | |
| 345 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\">") | |
| 340 | 346 | if templ_7745c5c3_Err != nil { | |
| 341 | 347 | return templ_7745c5c3_Err | |
| 342 | 348 | } | |
| 343 | 349 | if s := r.Stats; s != nil { | |
| 344 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<div><dt>commits</dt><dd>") | |
| 350 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<div><dt>commits</dt><dd>") | |
| 345 | 351 | if templ_7745c5c3_Err != nil { | |
| 346 | 352 | return templ_7745c5c3_Err | |
| 347 | 353 | } | |
| @@ -354,7 +360,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 354 | 360 | if templ_7745c5c3_Err != nil { | |
| 355 | 361 | return templ_7745c5c3_Err | |
| 356 | 362 | } | |
| 357 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</dd></div><div><dt>last 30 days</dt><dd>") | |
| 363 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</dd></div><div><dt>last 30 days</dt><dd>") | |
| 358 | 364 | if templ_7745c5c3_Err != nil { | |
| 359 | 365 | return templ_7745c5c3_Err | |
| 360 | 366 | } | |
| @@ -367,17 +373,17 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 367 | 373 | if templ_7745c5c3_Err != nil { | |
| 368 | 374 | return templ_7745c5c3_Err | |
| 369 | 375 | } | |
| 370 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</dd></div>") | |
| 376 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</dd></div>") | |
| 371 | 377 | if templ_7745c5c3_Err != nil { | |
| 372 | 378 | return templ_7745c5c3_Err | |
| 373 | 379 | } | |
| 374 | 380 | } | |
| 375 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<div class=\"rs-active\"><dt>last activity</dt>") | |
| 381 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<div class=\"rs-active\"><dt>last activity</dt>") | |
| 376 | 382 | if templ_7745c5c3_Err != nil { | |
| 377 | 383 | return templ_7745c5c3_Err | |
| 378 | 384 | } | |
| 379 | 385 | if r.ActiveAt != "" { | |
| 380 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<dd><time datetime=\"") | |
| 386 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<dd><time datetime=\"") | |
| 381 | 387 | if templ_7745c5c3_Err != nil { | |
| 382 | 388 | return templ_7745c5c3_Err | |
| 383 | 389 | } | |
| @@ -390,7 +396,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 390 | 396 | if templ_7745c5c3_Err != nil { | |
| 391 | 397 | return templ_7745c5c3_Err | |
| 392 | 398 | } | |
| 393 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" title=\"") | |
| 399 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" title=\"") | |
| 394 | 400 | if templ_7745c5c3_Err != nil { | |
| 395 | 401 | return templ_7745c5c3_Err | |
| 396 | 402 | } | |
| @@ -403,7 +409,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 403 | 409 | if templ_7745c5c3_Err != nil { | |
| 404 | 410 | return templ_7745c5c3_Err | |
| 405 | 411 | } | |
| 406 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\">") | |
| 412 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\">") | |
| 407 | 413 | if templ_7745c5c3_Err != nil { | |
| 408 | 414 | return templ_7745c5c3_Err | |
| 409 | 415 | } | |
| @@ -416,27 +422,27 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 416 | 422 | if templ_7745c5c3_Err != nil { | |
| 417 | 423 | return templ_7745c5c3_Err | |
| 418 | 424 | } | |
| 419 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</time></dd>") | |
| 425 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</time></dd>") | |
| 420 | 426 | if templ_7745c5c3_Err != nil { | |
| 421 | 427 | return templ_7745c5c3_Err | |
| 422 | 428 | } | |
| 423 | 429 | } else { | |
| 424 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<dd class=\"mute\">never</dd>") | |
| 430 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<dd class=\"mute\">never</dd>") | |
| 425 | 431 | if templ_7745c5c3_Err != nil { | |
| 426 | 432 | return templ_7745c5c3_Err | |
| 427 | 433 | } | |
| 428 | 434 | } | |
| 429 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</div>") | |
| 435 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</div>") | |
| 430 | 436 | if templ_7745c5c3_Err != nil { | |
| 431 | 437 | return templ_7745c5c3_Err | |
| 432 | 438 | } | |
| 433 | 439 | if s := r.Stats; s != nil && s.Tag != "" { | |
| 434 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<div class=\"rs-tag\"><dt>last tag</dt>") | |
| 440 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<div class=\"rs-tag\"><dt>last tag</dt>") | |
| 435 | 441 | if templ_7745c5c3_Err != nil { | |
| 436 | 442 | return templ_7745c5c3_Err | |
| 437 | 443 | } | |
| 438 | 444 | if s.TagHref != "" { | |
| 439 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<dd><a href=\"") | |
| 445 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<dd><a href=\"") | |
| 440 | 446 | if templ_7745c5c3_Err != nil { | |
| 441 | 447 | return templ_7745c5c3_Err | |
| 442 | 448 | } | |
| @@ -449,7 +455,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 449 | 455 | if templ_7745c5c3_Err != nil { | |
| 450 | 456 | return templ_7745c5c3_Err | |
| 451 | 457 | } | |
| 452 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\" title=\"") | |
| 458 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "\" title=\"") | |
| 453 | 459 | if templ_7745c5c3_Err != nil { | |
| 454 | 460 | return templ_7745c5c3_Err | |
| 455 | 461 | } | |
| @@ -462,7 +468,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 462 | 468 | if templ_7745c5c3_Err != nil { | |
| 463 | 469 | return templ_7745c5c3_Err | |
| 464 | 470 | } | |
| 465 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "\">") | |
| 471 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\">") | |
| 466 | 472 | if templ_7745c5c3_Err != nil { | |
| 467 | 473 | return templ_7745c5c3_Err | |
| 468 | 474 | } | |
| @@ -475,12 +481,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 475 | 481 | if templ_7745c5c3_Err != nil { | |
| 476 | 482 | return templ_7745c5c3_Err | |
| 477 | 483 | } | |
| 478 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</a></dd>") | |
| 484 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</a></dd>") | |
| 479 | 485 | if templ_7745c5c3_Err != nil { | |
| 480 | 486 | return templ_7745c5c3_Err | |
| 481 | 487 | } | |
| 482 | 488 | } else { | |
| 483 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<dd title=\"") | |
| 489 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<dd title=\"") | |
| 484 | 490 | if templ_7745c5c3_Err != nil { | |
| 485 | 491 | return templ_7745c5c3_Err | |
| 486 | 492 | } | |
| @@ -493,7 +499,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 493 | 499 | if templ_7745c5c3_Err != nil { | |
| 494 | 500 | return templ_7745c5c3_Err | |
| 495 | 501 | } | |
| 496 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\">") | |
| 502 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "\">") | |
| 497 | 503 | if templ_7745c5c3_Err != nil { | |
| 498 | 504 | return templ_7745c5c3_Err | |
| 499 | 505 | } | |
| @@ -506,22 +512,22 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 506 | 512 | if templ_7745c5c3_Err != nil { | |
| 507 | 513 | return templ_7745c5c3_Err | |
| 508 | 514 | } | |
| 509 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</dd>") | |
| 515 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</dd>") | |
| 510 | 516 | if templ_7745c5c3_Err != nil { | |
| 511 | 517 | return templ_7745c5c3_Err | |
| 512 | 518 | } | |
| 513 | 519 | } | |
| 514 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</div>") | |
| 520 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</div>") | |
| 515 | 521 | if templ_7745c5c3_Err != nil { | |
| 516 | 522 | return templ_7745c5c3_Err | |
| 517 | 523 | } | |
| 518 | 524 | } | |
| 519 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</dl>") | |
| 525 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</dl>") | |
| 520 | 526 | if templ_7745c5c3_Err != nil { | |
| 521 | 527 | return templ_7745c5c3_Err | |
| 522 | 528 | } | |
| 523 | 529 | if r.CI != nil { | |
| 524 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "<a class=\"repo-ci\" href=\"") | |
| 530 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<a class=\"repo-ci\" href=\"") | |
| 525 | 531 | if templ_7745c5c3_Err != nil { | |
| 526 | 532 | return templ_7745c5c3_Err | |
| 527 | 533 | } | |
| @@ -534,7 +540,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 534 | 540 | if templ_7745c5c3_Err != nil { | |
| 535 | 541 | return templ_7745c5c3_Err | |
| 536 | 542 | } | |
| 537 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" title=\"") | |
| 543 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\" title=\"") | |
| 538 | 544 | if templ_7745c5c3_Err != nil { | |
| 539 | 545 | return templ_7745c5c3_Err | |
| 540 | 546 | } | |
| @@ -547,7 +553,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 547 | 553 | if templ_7745c5c3_Err != nil { | |
| 548 | 554 | return templ_7745c5c3_Err | |
| 549 | 555 | } | |
| 550 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\">") | |
| 556 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\">") | |
| 551 | 557 | if templ_7745c5c3_Err != nil { | |
| 552 | 558 | return templ_7745c5c3_Err | |
| 553 | 559 | } | |
| @@ -556,7 +562,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 556 | 562 | if templ_7745c5c3_Err != nil { | |
| 557 | 563 | return templ_7745c5c3_Err | |
| 558 | 564 | } | |
| 559 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "<span class=\"") | |
| 565 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "<span class=\"") | |
| 560 | 566 | if templ_7745c5c3_Err != nil { | |
| 561 | 567 | return templ_7745c5c3_Err | |
| 562 | 568 | } | |
| @@ -569,7 +575,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 569 | 575 | if templ_7745c5c3_Err != nil { | |
| 570 | 576 | return templ_7745c5c3_Err | |
| 571 | 577 | } | |
| 572 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" aria-hidden=\"true\"></span> <span class=\"sr\">CI: </span><span class=\"ci-label\">") | |
| 578 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" aria-hidden=\"true\"></span> <span class=\"sr\">CI: </span><span class=\"ci-label\">") | |
| 573 | 579 | if templ_7745c5c3_Err != nil { | |
| 574 | 580 | return templ_7745c5c3_Err | |
| 575 | 581 | } | |
| @@ -582,27 +588,27 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 582 | 588 | if templ_7745c5c3_Err != nil { | |
| 583 | 589 | return templ_7745c5c3_Err | |
| 584 | 590 | } | |
| 585 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "</span></a>") | |
| 591 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</span></a>") | |
| 586 | 592 | if templ_7745c5c3_Err != nil { | |
| 587 | 593 | return templ_7745c5c3_Err | |
| 588 | 594 | } | |
| 589 | 595 | } | |
| 590 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</div>") | |
| 596 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</div>") | |
| 591 | 597 | if templ_7745c5c3_Err != nil { | |
| 592 | 598 | return templ_7745c5c3_Err | |
| 593 | 599 | } | |
| 594 | 600 | if len(r.Commits) > 0 { | |
| 595 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "<ul class=\"repo-commits\"") | |
| 601 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "<ul class=\"repo-commits\"") | |
| 596 | 602 | if templ_7745c5c3_Err != nil { | |
| 597 | 603 | return templ_7745c5c3_Err | |
| 598 | 604 | } | |
| 599 | 605 | if len(r.Commits) == homeRecent { | |
| 600 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, " data-full") | |
| 606 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, " data-full") | |
| 601 | 607 | if templ_7745c5c3_Err != nil { | |
| 602 | 608 | return templ_7745c5c3_Err | |
| 603 | 609 | } | |
| 604 | 610 | } | |
| 605 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, " aria-label=\"") | |
| 611 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, " aria-label=\"") | |
| 606 | 612 | if templ_7745c5c3_Err != nil { | |
| 607 | 613 | return templ_7745c5c3_Err | |
| 608 | 614 | } | |
| @@ -615,12 +621,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 615 | 621 | if templ_7745c5c3_Err != nil { | |
| 616 | 622 | return templ_7745c5c3_Err | |
| 617 | 623 | } | |
| 618 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "\">") | |
| 624 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "\">") | |
| 619 | 625 | if templ_7745c5c3_Err != nil { | |
| 620 | 626 | return templ_7745c5c3_Err | |
| 621 | 627 | } | |
| 622 | 628 | for _, c := range r.Commits { | |
| 623 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "<li><a class=\"rc-sha\" href=\"") | |
| 629 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "<li><a class=\"rc-sha\" href=\"") | |
| 624 | 630 | if templ_7745c5c3_Err != nil { | |
| 625 | 631 | return templ_7745c5c3_Err | |
| 626 | 632 | } | |
| @@ -633,7 +639,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 633 | 639 | if templ_7745c5c3_Err != nil { | |
| 634 | 640 | return templ_7745c5c3_Err | |
| 635 | 641 | } | |
| 636 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "\">") | |
| 642 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "\">") | |
| 637 | 643 | if templ_7745c5c3_Err != nil { | |
| 638 | 644 | return templ_7745c5c3_Err | |
| 639 | 645 | } | |
| @@ -646,7 +652,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 646 | 652 | if templ_7745c5c3_Err != nil { | |
| 647 | 653 | return templ_7745c5c3_Err | |
| 648 | 654 | } | |
| 649 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "</a> <span class=\"rc-subject\" title=\"") | |
| 655 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "</a> <span class=\"rc-subject\" title=\"") | |
| 650 | 656 | if templ_7745c5c3_Err != nil { | |
| 651 | 657 | return templ_7745c5c3_Err | |
| 652 | 658 | } | |
| @@ -659,7 +665,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 659 | 665 | if templ_7745c5c3_Err != nil { | |
| 660 | 666 | return templ_7745c5c3_Err | |
| 661 | 667 | } | |
| 662 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "\">") | |
| 668 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "\">") | |
| 663 | 669 | if templ_7745c5c3_Err != nil { | |
| 664 | 670 | return templ_7745c5c3_Err | |
| 665 | 671 | } | |
| @@ -672,12 +678,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 672 | 678 | if templ_7745c5c3_Err != nil { | |
| 673 | 679 | return templ_7745c5c3_Err | |
| 674 | 680 | } | |
| 675 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</span> ") | |
| 681 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "</span> ") | |
| 676 | 682 | if templ_7745c5c3_Err != nil { | |
| 677 | 683 | return templ_7745c5c3_Err | |
| 678 | 684 | } | |
| 679 | 685 | if c.WhenAt != "" { | |
| 680 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<time class=\"dim\" datetime=\"") | |
| 686 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "<time class=\"dim\" datetime=\"") | |
| 681 | 687 | if templ_7745c5c3_Err != nil { | |
| 682 | 688 | return templ_7745c5c3_Err | |
| 683 | 689 | } | |
| @@ -690,7 +696,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 690 | 696 | if templ_7745c5c3_Err != nil { | |
| 691 | 697 | return templ_7745c5c3_Err | |
| 692 | 698 | } | |
| 693 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "\" title=\"") | |
| 699 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\" title=\"") | |
| 694 | 700 | if templ_7745c5c3_Err != nil { | |
| 695 | 701 | return templ_7745c5c3_Err | |
| 696 | 702 | } | |
| @@ -703,7 +709,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 703 | 709 | if templ_7745c5c3_Err != nil { | |
| 704 | 710 | return templ_7745c5c3_Err | |
| 705 | 711 | } | |
| 706 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\">") | |
| 712 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "\">") | |
| 707 | 713 | if templ_7745c5c3_Err != nil { | |
| 708 | 714 | return templ_7745c5c3_Err | |
| 709 | 715 | } | |
| @@ -716,27 +722,27 @@ func HomeRowView(r HomeRow) templ.Component { | |||
| 716 | 722 | if templ_7745c5c3_Err != nil { | |
| 717 | 723 | return templ_7745c5c3_Err | |
| 718 | 724 | } | |
| 719 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "</time>") | |
| 725 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</time>") | |
| 720 | 726 | if templ_7745c5c3_Err != nil { | |
| 721 | 727 | return templ_7745c5c3_Err | |
| 722 | 728 | } | |
| 723 | 729 | } | |
| 724 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</li>") | |
| 730 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "</li>") | |
| 725 | 731 | if templ_7745c5c3_Err != nil { | |
| 726 | 732 | return templ_7745c5c3_Err | |
| 727 | 733 | } | |
| 728 | 734 | } | |
| 729 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "</ul>") | |
| 735 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "</ul>") | |
| 730 | 736 | if templ_7745c5c3_Err != nil { | |
| 731 | 737 | return templ_7745c5c3_Err | |
| 732 | 738 | } | |
| 733 | 739 | } else if r.NoCommits { | |
| 734 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "<p class=\"repo-commits mute\">no commits yet</p>") | |
| 740 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "<p class=\"repo-commits mute\">no commits yet</p>") | |
| 735 | 741 | if templ_7745c5c3_Err != nil { | |
| 736 | 742 | return templ_7745c5c3_Err | |
| 737 | 743 | } | |
| 738 | 744 | } | |
| 739 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "</li>") | |
| 745 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "</li>") | |
| 740 | 746 | if templ_7745c5c3_Err != nil { | |
| 741 | 747 | return templ_7745c5c3_Err | |
| 742 | 748 | } | |
| @@ -769,17 +775,17 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 769 | 775 | templ_7745c5c3_Var38 = templ.NopComponent | |
| 770 | 776 | } | |
| 771 | 777 | ctx = templ.ClearChildren(ctx) | |
| 772 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "<figure class=\"repo-pulse\"") | |
| 778 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "<figure class=\"repo-pulse\"") | |
| 773 | 779 | if templ_7745c5c3_Err != nil { | |
| 774 | 780 | return templ_7745c5c3_Err | |
| 775 | 781 | } | |
| 776 | 782 | if h.Live { | |
| 777 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, " data-live") | |
| 783 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, " data-live") | |
| 778 | 784 | if templ_7745c5c3_Err != nil { | |
| 779 | 785 | return templ_7745c5c3_Err | |
| 780 | 786 | } | |
| 781 | 787 | } | |
| 782 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "><svg viewBox=\"0 0 600 64\" role=\"img\" aria-label=\"") | |
| 788 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "><svg viewBox=\"0 0 600 64\" role=\"img\" aria-label=\"") | |
| 783 | 789 | if templ_7745c5c3_Err != nil { | |
| 784 | 790 | return templ_7745c5c3_Err | |
| 785 | 791 | } | |
| @@ -792,7 +798,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 792 | 798 | if templ_7745c5c3_Err != nil { | |
| 793 | 799 | return templ_7745c5c3_Err | |
| 794 | 800 | } | |
| 795 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\" focusable=\"false\"><defs><linearGradient id=\"") | |
| 801 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\" focusable=\"false\"><defs><linearGradient id=\"") | |
| 796 | 802 | if templ_7745c5c3_Err != nil { | |
| 797 | 803 | return templ_7745c5c3_Err | |
| 798 | 804 | } | |
| @@ -805,7 +811,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 805 | 811 | if templ_7745c5c3_Err != nil { | |
| 806 | 812 | return templ_7745c5c3_Err | |
| 807 | 813 | } | |
| 808 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop class=\"pulse-stop-top\" offset=\"0\"></stop> <stop class=\"pulse-stop-bottom\" offset=\"1\"></stop></linearGradient></defs> <path class=\"pulse-grid\" d=\"M0 21.5 H600 M0 42.5 H600 M0 63.5 H600\" vector-effect=\"non-scaling-stroke\"></path> <path class=\"pulse-area\" d=\"") | |
| 814 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop class=\"pulse-stop-top\" offset=\"0\"></stop> <stop class=\"pulse-stop-bottom\" offset=\"1\"></stop></linearGradient></defs> <path class=\"pulse-grid\" d=\"M0 21.5 H600 M0 42.5 H600 M0 63.5 H600\" vector-effect=\"non-scaling-stroke\"></path> <path class=\"pulse-area\" d=\"") | |
| 809 | 815 | if templ_7745c5c3_Err != nil { | |
| 810 | 816 | return templ_7745c5c3_Err | |
| 811 | 817 | } | |
| @@ -818,7 +824,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 818 | 824 | if templ_7745c5c3_Err != nil { | |
| 819 | 825 | return templ_7745c5c3_Err | |
| 820 | 826 | } | |
| 821 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "\" fill=\"") | |
| 827 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "\" fill=\"") | |
| 822 | 828 | if templ_7745c5c3_Err != nil { | |
| 823 | 829 | return templ_7745c5c3_Err | |
| 824 | 830 | } | |
| @@ -831,7 +837,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 831 | 837 | if templ_7745c5c3_Err != nil { | |
| 832 | 838 | return templ_7745c5c3_Err | |
| 833 | 839 | } | |
| 834 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "\"></path> <path class=\"pulse-line\" d=\"") | |
| 840 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "\"></path> <path class=\"pulse-line\" d=\"") | |
| 835 | 841 | if templ_7745c5c3_Err != nil { | |
| 836 | 842 | return templ_7745c5c3_Err | |
| 837 | 843 | } | |
| @@ -844,7 +850,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 844 | 850 | if templ_7745c5c3_Err != nil { | |
| 845 | 851 | return templ_7745c5c3_Err | |
| 846 | 852 | } | |
| 847 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "\" vector-effect=\"non-scaling-stroke\"></path> <circle class=\"pulse-dot\" cx=\"") | |
| 853 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "\" vector-effect=\"non-scaling-stroke\"></path> <circle class=\"pulse-dot\" cx=\"") | |
| 848 | 854 | if templ_7745c5c3_Err != nil { | |
| 849 | 855 | return templ_7745c5c3_Err | |
| 850 | 856 | } | |
| @@ -857,7 +863,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 857 | 863 | if templ_7745c5c3_Err != nil { | |
| 858 | 864 | return templ_7745c5c3_Err | |
| 859 | 865 | } | |
| 860 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "\" cy=\"") | |
| 866 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "\" cy=\"") | |
| 861 | 867 | if templ_7745c5c3_Err != nil { | |
| 862 | 868 | return templ_7745c5c3_Err | |
| 863 | 869 | } | |
| @@ -870,7 +876,7 @@ func pulse(h *Heartbeat) templ.Component { | |||
| 870 | 876 | if templ_7745c5c3_Err != nil { | |
| 871 | 877 | return templ_7745c5c3_Err | |
| 872 | 878 | } | |
| 873 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "\" r=\"3.5\"></circle></svg></figure>") | |
| 879 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "\" r=\"3.5\"></circle></svg></figure>") | |
| 874 | 880 | if templ_7745c5c3_Err != nil { | |
| 875 | 881 | return templ_7745c5c3_Err | |
| 876 | 882 | } | |
| @@ -900,7 +906,7 @@ func Outline(headings []Heading) templ.Component { | |||
| 900 | 906 | templ_7745c5c3_Var46 = templ.NopComponent | |
| 901 | 907 | } | |
| 902 | 908 | ctx = templ.ClearChildren(ctx) | |
| 903 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "<nav class=\"outline\" aria-label=\"Outline\">") | |
| 909 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "<nav class=\"outline\" aria-label=\"Outline\">") | |
| 904 | 910 | if templ_7745c5c3_Err != nil { | |
| 905 | 911 | return templ_7745c5c3_Err | |
| 906 | 912 | } | |
| @@ -910,7 +916,7 @@ func Outline(headings []Heading) templ.Component { | |||
| 910 | 916 | if templ_7745c5c3_Err != nil { | |
| 911 | 917 | return templ_7745c5c3_Err | |
| 912 | 918 | } | |
| 913 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "<a class=\"") | |
| 919 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "<a class=\"") | |
| 914 | 920 | if templ_7745c5c3_Err != nil { | |
| 915 | 921 | return templ_7745c5c3_Err | |
| 916 | 922 | } | |
| @@ -923,7 +929,7 @@ func Outline(headings []Heading) templ.Component { | |||
| 923 | 929 | if templ_7745c5c3_Err != nil { | |
| 924 | 930 | return templ_7745c5c3_Err | |
| 925 | 931 | } | |
| 926 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "\" href=\"") | |
| 932 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "\" href=\"") | |
| 927 | 933 | if templ_7745c5c3_Err != nil { | |
| 928 | 934 | return templ_7745c5c3_Err | |
| 929 | 935 | } | |
| @@ -936,7 +942,7 @@ func Outline(headings []Heading) templ.Component { | |||
| 936 | 942 | if templ_7745c5c3_Err != nil { | |
| 937 | 943 | return templ_7745c5c3_Err | |
| 938 | 944 | } | |
| 939 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "\">") | |
| 945 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "\">") | |
| 940 | 946 | if templ_7745c5c3_Err != nil { | |
| 941 | 947 | return templ_7745c5c3_Err | |
| 942 | 948 | } | |
| @@ -949,12 +955,12 @@ func Outline(headings []Heading) templ.Component { | |||
| 949 | 955 | if templ_7745c5c3_Err != nil { | |
| 950 | 956 | return templ_7745c5c3_Err | |
| 951 | 957 | } | |
| 952 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "</a>") | |
| 958 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "</a>") | |
| 953 | 959 | if templ_7745c5c3_Err != nil { | |
| 954 | 960 | return templ_7745c5c3_Err | |
| 955 | 961 | } | |
| 956 | 962 | } | |
| 957 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "</nav>") | |
| 963 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "</nav>") | |
| 958 | 964 | if templ_7745c5c3_Err != nil { | |
| 959 | 965 | return templ_7745c5c3_Err | |
| 960 | 966 | } | |
| @@ -984,7 +990,7 @@ func ReadmeCard(r Readme) templ.Component { | |||
| 984 | 990 | templ_7745c5c3_Var51 = templ.NopComponent | |
| 985 | 991 | } | |
| 986 | 992 | ctx = templ.ClearChildren(ctx) | |
| 987 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "<section class=\"card readme\" aria-labelledby=\"readme-h\"><h2 class=\"card-h\" id=\"readme-h\"><span class=\"ico i-file\" aria-hidden=\"true\"></span> ") | |
| 993 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "<section class=\"card readme\" aria-labelledby=\"readme-h\"><h2 class=\"card-h\" id=\"readme-h\"><span class=\"ico i-file\" aria-hidden=\"true\"></span> ") | |
| 988 | 994 | if templ_7745c5c3_Err != nil { | |
| 989 | 995 | return templ_7745c5c3_Err | |
| 990 | 996 | } | |
| @@ -997,7 +1003,7 @@ func ReadmeCard(r Readme) templ.Component { | |||
| 997 | 1003 | if templ_7745c5c3_Err != nil { | |
| 998 | 1004 | return templ_7745c5c3_Err | |
| 999 | 1005 | } | |
| 1000 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "</h2>") | |
| 1006 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "</h2>") | |
| 1001 | 1007 | if templ_7745c5c3_Err != nil { | |
| 1002 | 1008 | return templ_7745c5c3_Err | |
| 1003 | 1009 | } | |
| @@ -1005,7 +1011,7 @@ func ReadmeCard(r Readme) templ.Component { | |||
| 1005 | 1011 | if templ_7745c5c3_Err != nil { | |
| 1006 | 1012 | return templ_7745c5c3_Err | |
| 1007 | 1013 | } | |
| 1008 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "</section>") | |
| 1014 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "</section>") | |
| 1009 | 1015 | if templ_7745c5c3_Err != nil { | |
| 1010 | 1016 | return templ_7745c5c3_Err | |
| 1011 | 1017 | } | |
| @@ -1036,7 +1042,7 @@ func ReadmeView(r Readme) templ.Component { | |||
| 1036 | 1042 | templ_7745c5c3_Var53 = templ.NopComponent | |
| 1037 | 1043 | } | |
| 1038 | 1044 | ctx = templ.ClearChildren(ctx) | |
| 1039 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "<article class=\"prose\" aria-label=\"") | |
| 1045 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "<article class=\"prose\" aria-label=\"") | |
| 1040 | 1046 | if templ_7745c5c3_Err != nil { | |
| 1041 | 1047 | return templ_7745c5c3_Err | |
| 1042 | 1048 | } | |
| @@ -1049,12 +1055,12 @@ func ReadmeView(r Readme) templ.Component { | |||
| 1049 | 1055 | if templ_7745c5c3_Err != nil { | |
| 1050 | 1056 | return templ_7745c5c3_Err | |
| 1051 | 1057 | } | |
| 1052 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "\" hx-ignore>") | |
| 1058 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "\" hx-ignore>") | |
| 1053 | 1059 | if templ_7745c5c3_Err != nil { | |
| 1054 | 1060 | return templ_7745c5c3_Err | |
| 1055 | 1061 | } | |
| 1056 | 1062 | if r.Note != "" { | |
| 1057 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "<p class=\"dim\">") | |
| 1063 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "<p class=\"dim\">") | |
| 1058 | 1064 | if templ_7745c5c3_Err != nil { | |
| 1059 | 1065 | return templ_7745c5c3_Err | |
| 1060 | 1066 | } | |
| @@ -1067,7 +1073,7 @@ func ReadmeView(r Readme) templ.Component { | |||
| 1067 | 1073 | if templ_7745c5c3_Err != nil { | |
| 1068 | 1074 | return templ_7745c5c3_Err | |
| 1069 | 1075 | } | |
| 1070 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "</p>") | |
| 1076 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "</p>") | |
| 1071 | 1077 | if templ_7745c5c3_Err != nil { | |
| 1072 | 1078 | return templ_7745c5c3_Err | |
| 1073 | 1079 | } | |
| @@ -1077,7 +1083,7 @@ func ReadmeView(r Readme) templ.Component { | |||
| 1077 | 1083 | return templ_7745c5c3_Err | |
| 1078 | 1084 | } | |
| 1079 | 1085 | } | |
| 1080 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "</article>") | |
| 1086 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "</article>") | |
| 1081 | 1087 | if templ_7745c5c3_Err != nil { | |
| 1082 | 1088 | return templ_7745c5c3_Err | |
| 1083 | 1089 | } | |
| @@ -1108,17 +1114,17 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1108 | 1114 | templ_7745c5c3_Var56 = templ.NopComponent | |
| 1109 | 1115 | } | |
| 1110 | 1116 | ctx = templ.ClearChildren(ctx) | |
| 1111 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "<table class=\"list commits\" aria-label=\"Commits\"><tbody data-rows>") | |
| 1117 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "<table class=\"list commits\" aria-label=\"Commits\"><tbody data-rows>") | |
| 1112 | 1118 | if templ_7745c5c3_Err != nil { | |
| 1113 | 1119 | return templ_7745c5c3_Err | |
| 1114 | 1120 | } | |
| 1115 | 1121 | for _, c := range rows { | |
| 1116 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "<tr") | |
| 1122 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "<tr") | |
| 1117 | 1123 | if templ_7745c5c3_Err != nil { | |
| 1118 | 1124 | return templ_7745c5c3_Err | |
| 1119 | 1125 | } | |
| 1120 | 1126 | if c.ID != "" { | |
| 1121 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, " id=\"") | |
| 1127 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, " id=\"") | |
| 1122 | 1128 | if templ_7745c5c3_Err != nil { | |
| 1123 | 1129 | return templ_7745c5c3_Err | |
| 1124 | 1130 | } | |
| @@ -1131,18 +1137,18 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1131 | 1137 | if templ_7745c5c3_Err != nil { | |
| 1132 | 1138 | return templ_7745c5c3_Err | |
| 1133 | 1139 | } | |
| 1134 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "\"") | |
| 1140 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "\"") | |
| 1135 | 1141 | if templ_7745c5c3_Err != nil { | |
| 1136 | 1142 | return templ_7745c5c3_Err | |
| 1137 | 1143 | } | |
| 1138 | 1144 | } | |
| 1139 | 1145 | if c.Cursor { | |
| 1140 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, " data-cursor") | |
| 1146 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, " data-cursor") | |
| 1141 | 1147 | if templ_7745c5c3_Err != nil { | |
| 1142 | 1148 | return templ_7745c5c3_Err | |
| 1143 | 1149 | } | |
| 1144 | 1150 | } | |
| 1145 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "><td class=\"c-sha mute\">") | |
| 1151 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "><td class=\"c-sha mute\">") | |
| 1146 | 1152 | if templ_7745c5c3_Err != nil { | |
| 1147 | 1153 | return templ_7745c5c3_Err | |
| 1148 | 1154 | } | |
| @@ -1155,7 +1161,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1155 | 1161 | if templ_7745c5c3_Err != nil { | |
| 1156 | 1162 | return templ_7745c5c3_Err | |
| 1157 | 1163 | } | |
| 1158 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "</td><td class=\"c-subject\"><a href=\"") | |
| 1164 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "</td><td class=\"c-subject\"><a href=\"") | |
| 1159 | 1165 | if templ_7745c5c3_Err != nil { | |
| 1160 | 1166 | return templ_7745c5c3_Err | |
| 1161 | 1167 | } | |
| @@ -1168,7 +1174,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1168 | 1174 | if templ_7745c5c3_Err != nil { | |
| 1169 | 1175 | return templ_7745c5c3_Err | |
| 1170 | 1176 | } | |
| 1171 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "\">") | |
| 1177 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "\">") | |
| 1172 | 1178 | if templ_7745c5c3_Err != nil { | |
| 1173 | 1179 | return templ_7745c5c3_Err | |
| 1174 | 1180 | } | |
| @@ -1181,12 +1187,12 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1181 | 1187 | if templ_7745c5c3_Err != nil { | |
| 1182 | 1188 | return templ_7745c5c3_Err | |
| 1183 | 1189 | } | |
| 1184 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "</a> ") | |
| 1190 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "</a> ") | |
| 1185 | 1191 | if templ_7745c5c3_Err != nil { | |
| 1186 | 1192 | return templ_7745c5c3_Err | |
| 1187 | 1193 | } | |
| 1188 | 1194 | if c.Merge { | |
| 1189 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "<span class=\"pill\">merge</span> ") | |
| 1195 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "<span class=\"pill\">merge</span> ") | |
| 1190 | 1196 | if templ_7745c5c3_Err != nil { | |
| 1191 | 1197 | return templ_7745c5c3_Err | |
| 1192 | 1198 | } | |
| @@ -1198,7 +1204,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1198 | 1204 | } | |
| 1199 | 1205 | } | |
| 1200 | 1206 | for _, b := range c.Branches { | |
| 1201 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "<span class=\"pill\">") | |
| 1207 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "<span class=\"pill\">") | |
| 1202 | 1208 | if templ_7745c5c3_Err != nil { | |
| 1203 | 1209 | return templ_7745c5c3_Err | |
| 1204 | 1210 | } | |
| @@ -1211,13 +1217,13 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1211 | 1217 | if templ_7745c5c3_Err != nil { | |
| 1212 | 1218 | return templ_7745c5c3_Err | |
| 1213 | 1219 | } | |
| 1214 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "</span> ") | |
| 1220 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "</span> ") | |
| 1215 | 1221 | if templ_7745c5c3_Err != nil { | |
| 1216 | 1222 | return templ_7745c5c3_Err | |
| 1217 | 1223 | } | |
| 1218 | 1224 | } | |
| 1219 | 1225 | for _, t := range c.Tags { | |
| 1220 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "<span class=\"pill tag\"><span class=\"sr\">tag </span>") | |
| 1226 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "<span class=\"pill tag\"><span class=\"sr\">tag </span>") | |
| 1221 | 1227 | if templ_7745c5c3_Err != nil { | |
| 1222 | 1228 | return templ_7745c5c3_Err | |
| 1223 | 1229 | } | |
| @@ -1230,12 +1236,12 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1230 | 1236 | if templ_7745c5c3_Err != nil { | |
| 1231 | 1237 | return templ_7745c5c3_Err | |
| 1232 | 1238 | } | |
| 1233 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "</span>") | |
| 1239 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "</span>") | |
| 1234 | 1240 | if templ_7745c5c3_Err != nil { | |
| 1235 | 1241 | return templ_7745c5c3_Err | |
| 1236 | 1242 | } | |
| 1237 | 1243 | } | |
| 1238 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "</td><td class=\"c-ck\">") | |
| 1244 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "</td><td class=\"c-ck\">") | |
| 1239 | 1245 | if templ_7745c5c3_Err != nil { | |
| 1240 | 1246 | return templ_7745c5c3_Err | |
| 1241 | 1247 | } | |
| @@ -1243,7 +1249,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1243 | 1249 | if templ_7745c5c3_Err != nil { | |
| 1244 | 1250 | return templ_7745c5c3_Err | |
| 1245 | 1251 | } | |
| 1246 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "</td><td class=\"c-who dim\">") | |
| 1252 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "</td><td class=\"c-who dim\">") | |
| 1247 | 1253 | if templ_7745c5c3_Err != nil { | |
| 1248 | 1254 | return templ_7745c5c3_Err | |
| 1249 | 1255 | } | |
| @@ -1256,7 +1262,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1256 | 1262 | if templ_7745c5c3_Err != nil { | |
| 1257 | 1263 | return templ_7745c5c3_Err | |
| 1258 | 1264 | } | |
| 1259 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "</td><td class=\"c-when nowrap dim\"><time datetime=\"") | |
| 1265 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "</td><td class=\"c-when nowrap dim\"><time datetime=\"") | |
| 1260 | 1266 | if templ_7745c5c3_Err != nil { | |
| 1261 | 1267 | return templ_7745c5c3_Err | |
| 1262 | 1268 | } | |
| @@ -1269,7 +1275,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1269 | 1275 | if templ_7745c5c3_Err != nil { | |
| 1270 | 1276 | return templ_7745c5c3_Err | |
| 1271 | 1277 | } | |
| 1272 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "\" title=\"") | |
| 1278 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "\" title=\"") | |
| 1273 | 1279 | if templ_7745c5c3_Err != nil { | |
| 1274 | 1280 | return templ_7745c5c3_Err | |
| 1275 | 1281 | } | |
| @@ -1282,7 +1288,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1282 | 1288 | if templ_7745c5c3_Err != nil { | |
| 1283 | 1289 | return templ_7745c5c3_Err | |
| 1284 | 1290 | } | |
| 1285 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "\">") | |
| 1291 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "\">") | |
| 1286 | 1292 | if templ_7745c5c3_Err != nil { | |
| 1287 | 1293 | return templ_7745c5c3_Err | |
| 1288 | 1294 | } | |
| @@ -1295,12 +1301,12 @@ func CommitRows(rows []CommitRow) templ.Component { | |||
| 1295 | 1301 | if templ_7745c5c3_Err != nil { | |
| 1296 | 1302 | return templ_7745c5c3_Err | |
| 1297 | 1303 | } | |
| 1298 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "</time></td></tr>") | |
| 1304 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "</time></td></tr>") | |
| 1299 | 1305 | if templ_7745c5c3_Err != nil { | |
| 1300 | 1306 | return templ_7745c5c3_Err | |
| 1301 | 1307 | } | |
| 1302 | 1308 | } | |
| 1303 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "</tbody></table>") | |
| 1309 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "</tbody></table>") | |
| 1304 | 1310 | if templ_7745c5c3_Err != nil { | |
| 1305 | 1311 | return templ_7745c5c3_Err | |
| 1306 | 1312 | } | |
| @@ -1336,7 +1342,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||
| 1336 | 1342 | if templ_7745c5c3_Err != nil { | |
| 1337 | 1343 | return templ_7745c5c3_Err | |
| 1338 | 1344 | } | |
| 1339 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "<span class=\"") | |
| 1345 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "<span class=\"") | |
| 1340 | 1346 | if templ_7745c5c3_Err != nil { | |
| 1341 | 1347 | return templ_7745c5c3_Err | |
| 1342 | 1348 | } | |
| @@ -1349,7 +1355,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||
| 1349 | 1355 | if templ_7745c5c3_Err != nil { | |
| 1350 | 1356 | return templ_7745c5c3_Err | |
| 1351 | 1357 | } | |
| 1352 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "\" title=\"") | |
| 1358 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "\" title=\"") | |
| 1353 | 1359 | if templ_7745c5c3_Err != nil { | |
| 1354 | 1360 | return templ_7745c5c3_Err | |
| 1355 | 1361 | } | |
| @@ -1362,12 +1368,12 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||
| 1362 | 1368 | if templ_7745c5c3_Err != nil { | |
| 1363 | 1369 | return templ_7745c5c3_Err | |
| 1364 | 1370 | } | |
| 1365 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "\">") | |
| 1371 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "\">") | |
| 1366 | 1372 | if templ_7745c5c3_Err != nil { | |
| 1367 | 1373 | return templ_7745c5c3_Err | |
| 1368 | 1374 | } | |
| 1369 | 1375 | if b.Proto != "" { | |
| 1370 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "<span class=\"sig-proto\">") | |
| 1376 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "<span class=\"sig-proto\">") | |
| 1371 | 1377 | if templ_7745c5c3_Err != nil { | |
| 1372 | 1378 | return templ_7745c5c3_Err | |
| 1373 | 1379 | } | |
| @@ -1380,7 +1386,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||
| 1380 | 1386 | if templ_7745c5c3_Err != nil { | |
| 1381 | 1387 | return templ_7745c5c3_Err | |
| 1382 | 1388 | } | |
| 1383 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "</span> ") | |
| 1389 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "</span> ") | |
| 1384 | 1390 | if templ_7745c5c3_Err != nil { | |
| 1385 | 1391 | return templ_7745c5c3_Err | |
| 1386 | 1392 | } | |
| @@ -1394,7 +1400,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||
| 1394 | 1400 | if templ_7745c5c3_Err != nil { | |
| 1395 | 1401 | return templ_7745c5c3_Err | |
| 1396 | 1402 | } | |
| 1397 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "</span>") | |
| 1403 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "</span>") | |
| 1398 | 1404 | if templ_7745c5c3_Err != nil { | |
| 1399 | 1405 | return templ_7745c5c3_Err | |
| 1400 | 1406 | } | |
| @@ -195,7 +195,13 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 195 | return templ_7745c5c3_Err | 195 | return templ_7745c5c3_Err | ||
| 196 | } | 196 | } | ||
| 197 | } | 197 | } | ||
| 198 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "><div class=\"repo-main\"><h2 class=\"repo-name\"><a href=\"") | 198 | + | if r.Fresh { |
| 199 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " data-activity") | |||
| 200 | + | if templ_7745c5c3_Err != nil { | |||
| 201 | + | return templ_7745c5c3_Err | |||
| 202 | + | } | |||
| 203 | + | } | |||
| 204 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "><div class=\"repo-main\"><h2 class=\"repo-name\"><a href=\"") | |||
| 199 | if templ_7745c5c3_Err != nil { | 205 | if templ_7745c5c3_Err != nil { | ||
| 200 | return templ_7745c5c3_Err | 206 | return templ_7745c5c3_Err | ||
| 201 | } | 207 | } | ||
| @@ -208,7 +214,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 208 | if templ_7745c5c3_Err != nil { | 214 | if templ_7745c5c3_Err != nil { | ||
| 209 | return templ_7745c5c3_Err | 215 | return templ_7745c5c3_Err | ||
| 210 | } | 216 | } | ||
| 211 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\">") | 217 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">") |
| 212 | if templ_7745c5c3_Err != nil { | 218 | if templ_7745c5c3_Err != nil { | ||
| 213 | return templ_7745c5c3_Err | 219 | return templ_7745c5c3_Err | ||
| 214 | } | 220 | } | ||
| @@ -221,28 +227,28 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 221 | if templ_7745c5c3_Err != nil { | 227 | if templ_7745c5c3_Err != nil { | ||
| 222 | return templ_7745c5c3_Err | 228 | return templ_7745c5c3_Err | ||
| 223 | } | 229 | } | ||
| 224 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</a> ") | 230 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</a> ") |
| 225 | if templ_7745c5c3_Err != nil { | 231 | if templ_7745c5c3_Err != nil { | ||
| 226 | return templ_7745c5c3_Err | 232 | return templ_7745c5c3_Err | ||
| 227 | } | 233 | } | ||
| 228 | if r.Private { | 234 | if r.Private { | ||
| 229 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<span class=\"pill\">private</span> ") | 235 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<span class=\"pill\">private</span> ") |
| 230 | if templ_7745c5c3_Err != nil { | 236 | if templ_7745c5c3_Err != nil { | ||
| 231 | return templ_7745c5c3_Err | 237 | return templ_7745c5c3_Err | ||
| 232 | } | 238 | } | ||
| 233 | } | 239 | } | ||
| 234 | if r.Fresh { | 240 | if r.Fresh { | ||
| 235 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<span class=\"pill new\">new push</span>") | 241 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<span class=\"pill new\">new activity</span>") |
| 236 | if templ_7745c5c3_Err != nil { | 242 | if templ_7745c5c3_Err != nil { | ||
| 237 | return templ_7745c5c3_Err | 243 | return templ_7745c5c3_Err | ||
| 238 | } | 244 | } | ||
| 239 | } | 245 | } | ||
| 240 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</h2>") | 246 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</h2>") |
| 241 | if templ_7745c5c3_Err != nil { | 247 | if templ_7745c5c3_Err != nil { | ||
| 242 | return templ_7745c5c3_Err | 248 | return templ_7745c5c3_Err | ||
| 243 | } | 249 | } | ||
| 244 | if r.Desc != "" { | 250 | if r.Desc != "" { | ||
| 245 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<p class=\"repo-desc\">") | 251 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<p class=\"repo-desc\">") |
| 246 | if templ_7745c5c3_Err != nil { | 252 | if templ_7745c5c3_Err != nil { | ||
| 247 | return templ_7745c5c3_Err | 253 | return templ_7745c5c3_Err | ||
| 248 | } | 254 | } | ||
| @@ -255,18 +261,18 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 255 | if templ_7745c5c3_Err != nil { | 261 | if templ_7745c5c3_Err != nil { | ||
| 256 | return templ_7745c5c3_Err | 262 | return templ_7745c5c3_Err | ||
| 257 | } | 263 | } | ||
| 258 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</p>") | 264 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</p>") |
| 259 | if templ_7745c5c3_Err != nil { | 265 | if templ_7745c5c3_Err != nil { | ||
| 260 | return templ_7745c5c3_Err | 266 | return templ_7745c5c3_Err | ||
| 261 | } | 267 | } | ||
| 262 | } else { | 268 | } else { | ||
| 263 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<p class=\"repo-desc mute\">no description</p>") | 269 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<p class=\"repo-desc mute\">no description</p>") |
| 264 | if templ_7745c5c3_Err != nil { | 270 | if templ_7745c5c3_Err != nil { | ||
| 265 | return templ_7745c5c3_Err | 271 | return templ_7745c5c3_Err | ||
| 266 | } | 272 | } | ||
| 267 | } | 273 | } | ||
| 268 | if len(r.Topics) > 0 { | 274 | if len(r.Topics) > 0 { | ||
| 269 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<ul class=\"repo-topics\" aria-label=\"") | 275 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<ul class=\"repo-topics\" aria-label=\"") |
| 270 | if templ_7745c5c3_Err != nil { | 276 | if templ_7745c5c3_Err != nil { | ||
| 271 | return templ_7745c5c3_Err | 277 | return templ_7745c5c3_Err | ||
| 272 | } | 278 | } | ||
| @@ -279,12 +285,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 279 | if templ_7745c5c3_Err != nil { | 285 | if templ_7745c5c3_Err != nil { | ||
| 280 | return templ_7745c5c3_Err | 286 | return templ_7745c5c3_Err | ||
| 281 | } | 287 | } | ||
| 282 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" data-fit>") | 288 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" data-fit>") |
| 283 | if templ_7745c5c3_Err != nil { | 289 | if templ_7745c5c3_Err != nil { | ||
| 284 | return templ_7745c5c3_Err | 290 | return templ_7745c5c3_Err | ||
| 285 | } | 291 | } | ||
| 286 | for _, t := range r.Topics { | 292 | for _, t := range r.Topics { | ||
| 287 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<li>") | 293 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<li>") |
| 288 | if templ_7745c5c3_Err != nil { | 294 | if templ_7745c5c3_Err != nil { | ||
| 289 | return templ_7745c5c3_Err | 295 | return templ_7745c5c3_Err | ||
| 290 | } | 296 | } | ||
| @@ -297,17 +303,17 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 297 | if templ_7745c5c3_Err != nil { | 303 | if templ_7745c5c3_Err != nil { | ||
| 298 | return templ_7745c5c3_Err | 304 | return templ_7745c5c3_Err | ||
| 299 | } | 305 | } | ||
| 300 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</li>") | 306 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</li>") |
| 301 | if templ_7745c5c3_Err != nil { | 307 | if templ_7745c5c3_Err != nil { | ||
| 302 | return templ_7745c5c3_Err | 308 | return templ_7745c5c3_Err | ||
| 303 | } | 309 | } | ||
| 304 | } | 310 | } | ||
| 305 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</ul>") | 311 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</ul>") |
| 306 | if templ_7745c5c3_Err != nil { | 312 | if templ_7745c5c3_Err != nil { | ||
| 307 | return templ_7745c5c3_Err | 313 | return templ_7745c5c3_Err | ||
| 308 | } | 314 | } | ||
| 309 | } else { | 315 | } else { | ||
| 310 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div class=\"repo-topics\" aria-hidden=\"true\"></div>") | 316 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"repo-topics\" aria-hidden=\"true\"></div>") |
| 311 | if templ_7745c5c3_Err != nil { | 317 | if templ_7745c5c3_Err != nil { | ||
| 312 | return templ_7745c5c3_Err | 318 | return templ_7745c5c3_Err | ||
| 313 | } | 319 | } | ||
| @@ -318,12 +324,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 318 | return templ_7745c5c3_Err | 324 | return templ_7745c5c3_Err | ||
| 319 | } | 325 | } | ||
| 320 | } else { | 326 | } else { | ||
| 321 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"repo-pulse\" aria-hidden=\"true\"></div>") | 327 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<div class=\"repo-pulse\" aria-hidden=\"true\"></div>") |
| 322 | if templ_7745c5c3_Err != nil { | 328 | if templ_7745c5c3_Err != nil { | ||
| 323 | return templ_7745c5c3_Err | 329 | return templ_7745c5c3_Err | ||
| 324 | } | 330 | } | ||
| 325 | } | 331 | } | ||
| 326 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</div><div class=\"repo-head\"><dl class=\"repo-stats\" aria-label=\"") | 332 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</div><div class=\"repo-head\"><dl class=\"repo-stats\" aria-label=\"") |
| 327 | if templ_7745c5c3_Err != nil { | 333 | if templ_7745c5c3_Err != nil { | ||
| 328 | return templ_7745c5c3_Err | 334 | return templ_7745c5c3_Err | ||
| 329 | } | 335 | } | ||
| @@ -336,12 +342,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 336 | if templ_7745c5c3_Err != nil { | 342 | if templ_7745c5c3_Err != nil { | ||
| 337 | return templ_7745c5c3_Err | 343 | return templ_7745c5c3_Err | ||
| 338 | } | 344 | } | ||
| 339 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\">") | 345 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\">") |
| 340 | if templ_7745c5c3_Err != nil { | 346 | if templ_7745c5c3_Err != nil { | ||
| 341 | return templ_7745c5c3_Err | 347 | return templ_7745c5c3_Err | ||
| 342 | } | 348 | } | ||
| 343 | if s := r.Stats; s != nil { | 349 | if s := r.Stats; s != nil { | ||
| 344 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<div><dt>commits</dt><dd>") | 350 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<div><dt>commits</dt><dd>") |
| 345 | if templ_7745c5c3_Err != nil { | 351 | if templ_7745c5c3_Err != nil { | ||
| 346 | return templ_7745c5c3_Err | 352 | return templ_7745c5c3_Err | ||
| 347 | } | 353 | } | ||
| @@ -354,7 +360,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 354 | if templ_7745c5c3_Err != nil { | 360 | if templ_7745c5c3_Err != nil { | ||
| 355 | return templ_7745c5c3_Err | 361 | return templ_7745c5c3_Err | ||
| 356 | } | 362 | } | ||
| 357 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</dd></div><div><dt>last 30 days</dt><dd>") | 363 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</dd></div><div><dt>last 30 days</dt><dd>") |
| 358 | if templ_7745c5c3_Err != nil { | 364 | if templ_7745c5c3_Err != nil { | ||
| 359 | return templ_7745c5c3_Err | 365 | return templ_7745c5c3_Err | ||
| 360 | } | 366 | } | ||
| @@ -367,17 +373,17 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 367 | if templ_7745c5c3_Err != nil { | 373 | if templ_7745c5c3_Err != nil { | ||
| 368 | return templ_7745c5c3_Err | 374 | return templ_7745c5c3_Err | ||
| 369 | } | 375 | } | ||
| 370 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</dd></div>") | 376 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</dd></div>") |
| 371 | if templ_7745c5c3_Err != nil { | 377 | if templ_7745c5c3_Err != nil { | ||
| 372 | return templ_7745c5c3_Err | 378 | return templ_7745c5c3_Err | ||
| 373 | } | 379 | } | ||
| 374 | } | 380 | } | ||
| 375 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<div class=\"rs-active\"><dt>last activity</dt>") | 381 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<div class=\"rs-active\"><dt>last activity</dt>") |
| 376 | if templ_7745c5c3_Err != nil { | 382 | if templ_7745c5c3_Err != nil { | ||
| 377 | return templ_7745c5c3_Err | 383 | return templ_7745c5c3_Err | ||
| 378 | } | 384 | } | ||
| 379 | if r.ActiveAt != "" { | 385 | if r.ActiveAt != "" { | ||
| 380 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<dd><time datetime=\"") | 386 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<dd><time datetime=\"") |
| 381 | if templ_7745c5c3_Err != nil { | 387 | if templ_7745c5c3_Err != nil { | ||
| 382 | return templ_7745c5c3_Err | 388 | return templ_7745c5c3_Err | ||
| 383 | } | 389 | } | ||
| @@ -390,7 +396,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 390 | if templ_7745c5c3_Err != nil { | 396 | if templ_7745c5c3_Err != nil { | ||
| 391 | return templ_7745c5c3_Err | 397 | return templ_7745c5c3_Err | ||
| 392 | } | 398 | } | ||
| 393 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" title=\"") | 399 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" title=\"") |
| 394 | if templ_7745c5c3_Err != nil { | 400 | if templ_7745c5c3_Err != nil { | ||
| 395 | return templ_7745c5c3_Err | 401 | return templ_7745c5c3_Err | ||
| 396 | } | 402 | } | ||
| @@ -403,7 +409,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 403 | if templ_7745c5c3_Err != nil { | 409 | if templ_7745c5c3_Err != nil { | ||
| 404 | return templ_7745c5c3_Err | 410 | return templ_7745c5c3_Err | ||
| 405 | } | 411 | } | ||
| 406 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\">") | 412 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\">") |
| 407 | if templ_7745c5c3_Err != nil { | 413 | if templ_7745c5c3_Err != nil { | ||
| 408 | return templ_7745c5c3_Err | 414 | return templ_7745c5c3_Err | ||
| 409 | } | 415 | } | ||
| @@ -416,27 +422,27 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 416 | if templ_7745c5c3_Err != nil { | 422 | if templ_7745c5c3_Err != nil { | ||
| 417 | return templ_7745c5c3_Err | 423 | return templ_7745c5c3_Err | ||
| 418 | } | 424 | } | ||
| 419 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</time></dd>") | 425 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</time></dd>") |
| 420 | if templ_7745c5c3_Err != nil { | 426 | if templ_7745c5c3_Err != nil { | ||
| 421 | return templ_7745c5c3_Err | 427 | return templ_7745c5c3_Err | ||
| 422 | } | 428 | } | ||
| 423 | } else { | 429 | } else { | ||
| 424 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<dd class=\"mute\">never</dd>") | 430 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<dd class=\"mute\">never</dd>") |
| 425 | if templ_7745c5c3_Err != nil { | 431 | if templ_7745c5c3_Err != nil { | ||
| 426 | return templ_7745c5c3_Err | 432 | return templ_7745c5c3_Err | ||
| 427 | } | 433 | } | ||
| 428 | } | 434 | } | ||
| 429 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</div>") | 435 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</div>") |
| 430 | if templ_7745c5c3_Err != nil { | 436 | if templ_7745c5c3_Err != nil { | ||
| 431 | return templ_7745c5c3_Err | 437 | return templ_7745c5c3_Err | ||
| 432 | } | 438 | } | ||
| 433 | if s := r.Stats; s != nil && s.Tag != "" { | 439 | if s := r.Stats; s != nil && s.Tag != "" { | ||
| 434 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<div class=\"rs-tag\"><dt>last tag</dt>") | 440 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<div class=\"rs-tag\"><dt>last tag</dt>") |
| 435 | if templ_7745c5c3_Err != nil { | 441 | if templ_7745c5c3_Err != nil { | ||
| 436 | return templ_7745c5c3_Err | 442 | return templ_7745c5c3_Err | ||
| 437 | } | 443 | } | ||
| 438 | if s.TagHref != "" { | 444 | if s.TagHref != "" { | ||
| 439 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<dd><a href=\"") | 445 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<dd><a href=\"") |
| 440 | if templ_7745c5c3_Err != nil { | 446 | if templ_7745c5c3_Err != nil { | ||
| 441 | return templ_7745c5c3_Err | 447 | return templ_7745c5c3_Err | ||
| 442 | } | 448 | } | ||
| @@ -449,7 +455,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 449 | if templ_7745c5c3_Err != nil { | 455 | if templ_7745c5c3_Err != nil { | ||
| 450 | return templ_7745c5c3_Err | 456 | return templ_7745c5c3_Err | ||
| 451 | } | 457 | } | ||
| 452 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\" title=\"") | 458 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "\" title=\"") |
| 453 | if templ_7745c5c3_Err != nil { | 459 | if templ_7745c5c3_Err != nil { | ||
| 454 | return templ_7745c5c3_Err | 460 | return templ_7745c5c3_Err | ||
| 455 | } | 461 | } | ||
| @@ -462,7 +468,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 462 | if templ_7745c5c3_Err != nil { | 468 | if templ_7745c5c3_Err != nil { | ||
| 463 | return templ_7745c5c3_Err | 469 | return templ_7745c5c3_Err | ||
| 464 | } | 470 | } | ||
| 465 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "\">") | 471 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\">") |
| 466 | if templ_7745c5c3_Err != nil { | 472 | if templ_7745c5c3_Err != nil { | ||
| 467 | return templ_7745c5c3_Err | 473 | return templ_7745c5c3_Err | ||
| 468 | } | 474 | } | ||
| @@ -475,12 +481,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 475 | if templ_7745c5c3_Err != nil { | 481 | if templ_7745c5c3_Err != nil { | ||
| 476 | return templ_7745c5c3_Err | 482 | return templ_7745c5c3_Err | ||
| 477 | } | 483 | } | ||
| 478 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</a></dd>") | 484 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</a></dd>") |
| 479 | if templ_7745c5c3_Err != nil { | 485 | if templ_7745c5c3_Err != nil { | ||
| 480 | return templ_7745c5c3_Err | 486 | return templ_7745c5c3_Err | ||
| 481 | } | 487 | } | ||
| 482 | } else { | 488 | } else { | ||
| 483 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<dd title=\"") | 489 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<dd title=\"") |
| 484 | if templ_7745c5c3_Err != nil { | 490 | if templ_7745c5c3_Err != nil { | ||
| 485 | return templ_7745c5c3_Err | 491 | return templ_7745c5c3_Err | ||
| 486 | } | 492 | } | ||
| @@ -493,7 +499,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 493 | if templ_7745c5c3_Err != nil { | 499 | if templ_7745c5c3_Err != nil { | ||
| 494 | return templ_7745c5c3_Err | 500 | return templ_7745c5c3_Err | ||
| 495 | } | 501 | } | ||
| 496 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\">") | 502 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "\">") |
| 497 | if templ_7745c5c3_Err != nil { | 503 | if templ_7745c5c3_Err != nil { | ||
| 498 | return templ_7745c5c3_Err | 504 | return templ_7745c5c3_Err | ||
| 499 | } | 505 | } | ||
| @@ -506,22 +512,22 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 506 | if templ_7745c5c3_Err != nil { | 512 | if templ_7745c5c3_Err != nil { | ||
| 507 | return templ_7745c5c3_Err | 513 | return templ_7745c5c3_Err | ||
| 508 | } | 514 | } | ||
| 509 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</dd>") | 515 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</dd>") |
| 510 | if templ_7745c5c3_Err != nil { | 516 | if templ_7745c5c3_Err != nil { | ||
| 511 | return templ_7745c5c3_Err | 517 | return templ_7745c5c3_Err | ||
| 512 | } | 518 | } | ||
| 513 | } | 519 | } | ||
| 514 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</div>") | 520 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</div>") |
| 515 | if templ_7745c5c3_Err != nil { | 521 | if templ_7745c5c3_Err != nil { | ||
| 516 | return templ_7745c5c3_Err | 522 | return templ_7745c5c3_Err | ||
| 517 | } | 523 | } | ||
| 518 | } | 524 | } | ||
| 519 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</dl>") | 525 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</dl>") |
| 520 | if templ_7745c5c3_Err != nil { | 526 | if templ_7745c5c3_Err != nil { | ||
| 521 | return templ_7745c5c3_Err | 527 | return templ_7745c5c3_Err | ||
| 522 | } | 528 | } | ||
| 523 | if r.CI != nil { | 529 | if r.CI != nil { | ||
| 524 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "<a class=\"repo-ci\" href=\"") | 530 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "<a class=\"repo-ci\" href=\"") |
| 525 | if templ_7745c5c3_Err != nil { | 531 | if templ_7745c5c3_Err != nil { | ||
| 526 | return templ_7745c5c3_Err | 532 | return templ_7745c5c3_Err | ||
| 527 | } | 533 | } | ||
| @@ -534,7 +540,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 534 | if templ_7745c5c3_Err != nil { | 540 | if templ_7745c5c3_Err != nil { | ||
| 535 | return templ_7745c5c3_Err | 541 | return templ_7745c5c3_Err | ||
| 536 | } | 542 | } | ||
| 537 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" title=\"") | 543 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\" title=\"") |
| 538 | if templ_7745c5c3_Err != nil { | 544 | if templ_7745c5c3_Err != nil { | ||
| 539 | return templ_7745c5c3_Err | 545 | return templ_7745c5c3_Err | ||
| 540 | } | 546 | } | ||
| @@ -547,7 +553,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 547 | if templ_7745c5c3_Err != nil { | 553 | if templ_7745c5c3_Err != nil { | ||
| 548 | return templ_7745c5c3_Err | 554 | return templ_7745c5c3_Err | ||
| 549 | } | 555 | } | ||
| 550 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\">") | 556 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "\">") |
| 551 | if templ_7745c5c3_Err != nil { | 557 | if templ_7745c5c3_Err != nil { | ||
| 552 | return templ_7745c5c3_Err | 558 | return templ_7745c5c3_Err | ||
| 553 | } | 559 | } | ||
| @@ -556,7 +562,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 556 | if templ_7745c5c3_Err != nil { | 562 | if templ_7745c5c3_Err != nil { | ||
| 557 | return templ_7745c5c3_Err | 563 | return templ_7745c5c3_Err | ||
| 558 | } | 564 | } | ||
| 559 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "<span class=\"") | 565 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "<span class=\"") |
| 560 | if templ_7745c5c3_Err != nil { | 566 | if templ_7745c5c3_Err != nil { | ||
| 561 | return templ_7745c5c3_Err | 567 | return templ_7745c5c3_Err | ||
| 562 | } | 568 | } | ||
| @@ -569,7 +575,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 569 | if templ_7745c5c3_Err != nil { | 575 | if templ_7745c5c3_Err != nil { | ||
| 570 | return templ_7745c5c3_Err | 576 | return templ_7745c5c3_Err | ||
| 571 | } | 577 | } | ||
| 572 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" aria-hidden=\"true\"></span> <span class=\"sr\">CI: </span><span class=\"ci-label\">") | 578 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" aria-hidden=\"true\"></span> <span class=\"sr\">CI: </span><span class=\"ci-label\">") |
| 573 | if templ_7745c5c3_Err != nil { | 579 | if templ_7745c5c3_Err != nil { | ||
| 574 | return templ_7745c5c3_Err | 580 | return templ_7745c5c3_Err | ||
| 575 | } | 581 | } | ||
| @@ -582,27 +588,27 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 582 | if templ_7745c5c3_Err != nil { | 588 | if templ_7745c5c3_Err != nil { | ||
| 583 | return templ_7745c5c3_Err | 589 | return templ_7745c5c3_Err | ||
| 584 | } | 590 | } | ||
| 585 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "</span></a>") | 591 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</span></a>") |
| 586 | if templ_7745c5c3_Err != nil { | 592 | if templ_7745c5c3_Err != nil { | ||
| 587 | return templ_7745c5c3_Err | 593 | return templ_7745c5c3_Err | ||
| 588 | } | 594 | } | ||
| 589 | } | 595 | } | ||
| 590 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</div>") | 596 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</div>") |
| 591 | if templ_7745c5c3_Err != nil { | 597 | if templ_7745c5c3_Err != nil { | ||
| 592 | return templ_7745c5c3_Err | 598 | return templ_7745c5c3_Err | ||
| 593 | } | 599 | } | ||
| 594 | if len(r.Commits) > 0 { | 600 | if len(r.Commits) > 0 { | ||
| 595 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "<ul class=\"repo-commits\"") | 601 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "<ul class=\"repo-commits\"") |
| 596 | if templ_7745c5c3_Err != nil { | 602 | if templ_7745c5c3_Err != nil { | ||
| 597 | return templ_7745c5c3_Err | 603 | return templ_7745c5c3_Err | ||
| 598 | } | 604 | } | ||
| 599 | if len(r.Commits) == homeRecent { | 605 | if len(r.Commits) == homeRecent { | ||
| 600 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, " data-full") | 606 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, " data-full") |
| 601 | if templ_7745c5c3_Err != nil { | 607 | if templ_7745c5c3_Err != nil { | ||
| 602 | return templ_7745c5c3_Err | 608 | return templ_7745c5c3_Err | ||
| 603 | } | 609 | } | ||
| 604 | } | 610 | } | ||
| 605 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, " aria-label=\"") | 611 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, " aria-label=\"") |
| 606 | if templ_7745c5c3_Err != nil { | 612 | if templ_7745c5c3_Err != nil { | ||
| 607 | return templ_7745c5c3_Err | 613 | return templ_7745c5c3_Err | ||
| 608 | } | 614 | } | ||
| @@ -615,12 +621,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 615 | if templ_7745c5c3_Err != nil { | 621 | if templ_7745c5c3_Err != nil { | ||
| 616 | return templ_7745c5c3_Err | 622 | return templ_7745c5c3_Err | ||
| 617 | } | 623 | } | ||
| 618 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "\">") | 624 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "\">") |
| 619 | if templ_7745c5c3_Err != nil { | 625 | if templ_7745c5c3_Err != nil { | ||
| 620 | return templ_7745c5c3_Err | 626 | return templ_7745c5c3_Err | ||
| 621 | } | 627 | } | ||
| 622 | for _, c := range r.Commits { | 628 | for _, c := range r.Commits { | ||
| 623 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "<li><a class=\"rc-sha\" href=\"") | 629 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "<li><a class=\"rc-sha\" href=\"") |
| 624 | if templ_7745c5c3_Err != nil { | 630 | if templ_7745c5c3_Err != nil { | ||
| 625 | return templ_7745c5c3_Err | 631 | return templ_7745c5c3_Err | ||
| 626 | } | 632 | } | ||
| @@ -633,7 +639,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 633 | if templ_7745c5c3_Err != nil { | 639 | if templ_7745c5c3_Err != nil { | ||
| 634 | return templ_7745c5c3_Err | 640 | return templ_7745c5c3_Err | ||
| 635 | } | 641 | } | ||
| 636 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "\">") | 642 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "\">") |
| 637 | if templ_7745c5c3_Err != nil { | 643 | if templ_7745c5c3_Err != nil { | ||
| 638 | return templ_7745c5c3_Err | 644 | return templ_7745c5c3_Err | ||
| 639 | } | 645 | } | ||
| @@ -646,7 +652,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 646 | if templ_7745c5c3_Err != nil { | 652 | if templ_7745c5c3_Err != nil { | ||
| 647 | return templ_7745c5c3_Err | 653 | return templ_7745c5c3_Err | ||
| 648 | } | 654 | } | ||
| 649 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "</a> <span class=\"rc-subject\" title=\"") | 655 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "</a> <span class=\"rc-subject\" title=\"") |
| 650 | if templ_7745c5c3_Err != nil { | 656 | if templ_7745c5c3_Err != nil { | ||
| 651 | return templ_7745c5c3_Err | 657 | return templ_7745c5c3_Err | ||
| 652 | } | 658 | } | ||
| @@ -659,7 +665,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 659 | if templ_7745c5c3_Err != nil { | 665 | if templ_7745c5c3_Err != nil { | ||
| 660 | return templ_7745c5c3_Err | 666 | return templ_7745c5c3_Err | ||
| 661 | } | 667 | } | ||
| 662 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "\">") | 668 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "\">") |
| 663 | if templ_7745c5c3_Err != nil { | 669 | if templ_7745c5c3_Err != nil { | ||
| 664 | return templ_7745c5c3_Err | 670 | return templ_7745c5c3_Err | ||
| 665 | } | 671 | } | ||
| @@ -672,12 +678,12 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 672 | if templ_7745c5c3_Err != nil { | 678 | if templ_7745c5c3_Err != nil { | ||
| 673 | return templ_7745c5c3_Err | 679 | return templ_7745c5c3_Err | ||
| 674 | } | 680 | } | ||
| 675 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</span> ") | 681 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "</span> ") |
| 676 | if templ_7745c5c3_Err != nil { | 682 | if templ_7745c5c3_Err != nil { | ||
| 677 | return templ_7745c5c3_Err | 683 | return templ_7745c5c3_Err | ||
| 678 | } | 684 | } | ||
| 679 | if c.WhenAt != "" { | 685 | if c.WhenAt != "" { | ||
| 680 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<time class=\"dim\" datetime=\"") | 686 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "<time class=\"dim\" datetime=\"") |
| 681 | if templ_7745c5c3_Err != nil { | 687 | if templ_7745c5c3_Err != nil { | ||
| 682 | return templ_7745c5c3_Err | 688 | return templ_7745c5c3_Err | ||
| 683 | } | 689 | } | ||
| @@ -690,7 +696,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 690 | if templ_7745c5c3_Err != nil { | 696 | if templ_7745c5c3_Err != nil { | ||
| 691 | return templ_7745c5c3_Err | 697 | return templ_7745c5c3_Err | ||
| 692 | } | 698 | } | ||
| 693 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "\" title=\"") | 699 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\" title=\"") |
| 694 | if templ_7745c5c3_Err != nil { | 700 | if templ_7745c5c3_Err != nil { | ||
| 695 | return templ_7745c5c3_Err | 701 | return templ_7745c5c3_Err | ||
| 696 | } | 702 | } | ||
| @@ -703,7 +709,7 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 703 | if templ_7745c5c3_Err != nil { | 709 | if templ_7745c5c3_Err != nil { | ||
| 704 | return templ_7745c5c3_Err | 710 | return templ_7745c5c3_Err | ||
| 705 | } | 711 | } | ||
| 706 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\">") | 712 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "\">") |
| 707 | if templ_7745c5c3_Err != nil { | 713 | if templ_7745c5c3_Err != nil { | ||
| 708 | return templ_7745c5c3_Err | 714 | return templ_7745c5c3_Err | ||
| 709 | } | 715 | } | ||
| @@ -716,27 +722,27 @@ func HomeRowView(r HomeRow) templ.Component { | |||||
| 716 | if templ_7745c5c3_Err != nil { | 722 | if templ_7745c5c3_Err != nil { | ||
| 717 | return templ_7745c5c3_Err | 723 | return templ_7745c5c3_Err | ||
| 718 | } | 724 | } | ||
| 719 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "</time>") | 725 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</time>") |
| 720 | if templ_7745c5c3_Err != nil { | 726 | if templ_7745c5c3_Err != nil { | ||
| 721 | return templ_7745c5c3_Err | 727 | return templ_7745c5c3_Err | ||
| 722 | } | 728 | } | ||
| 723 | } | 729 | } | ||
| 724 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</li>") | 730 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "</li>") |
| 725 | if templ_7745c5c3_Err != nil { | 731 | if templ_7745c5c3_Err != nil { | ||
| 726 | return templ_7745c5c3_Err | 732 | return templ_7745c5c3_Err | ||
| 727 | } | 733 | } | ||
| 728 | } | 734 | } | ||
| 729 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "</ul>") | 735 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "</ul>") |
| 730 | if templ_7745c5c3_Err != nil { | 736 | if templ_7745c5c3_Err != nil { | ||
| 731 | return templ_7745c5c3_Err | 737 | return templ_7745c5c3_Err | ||
| 732 | } | 738 | } | ||
| 733 | } else if r.NoCommits { | 739 | } else if r.NoCommits { | ||
| 734 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "<p class=\"repo-commits mute\">no commits yet</p>") | 740 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "<p class=\"repo-commits mute\">no commits yet</p>") |
| 735 | if templ_7745c5c3_Err != nil { | 741 | if templ_7745c5c3_Err != nil { | ||
| 736 | return templ_7745c5c3_Err | 742 | return templ_7745c5c3_Err | ||
| 737 | } | 743 | } | ||
| 738 | } | 744 | } | ||
| 739 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "</li>") | 745 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "</li>") |
| 740 | if templ_7745c5c3_Err != nil { | 746 | if templ_7745c5c3_Err != nil { | ||
| 741 | return templ_7745c5c3_Err | 747 | return templ_7745c5c3_Err | ||
| 742 | } | 748 | } | ||
| @@ -769,17 +775,17 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 769 | templ_7745c5c3_Var38 = templ.NopComponent | 775 | templ_7745c5c3_Var38 = templ.NopComponent | ||
| 770 | } | 776 | } | ||
| 771 | ctx = templ.ClearChildren(ctx) | 777 | ctx = templ.ClearChildren(ctx) | ||
| 772 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "<figure class=\"repo-pulse\"") | 778 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "<figure class=\"repo-pulse\"") |
| 773 | if templ_7745c5c3_Err != nil { | 779 | if templ_7745c5c3_Err != nil { | ||
| 774 | return templ_7745c5c3_Err | 780 | return templ_7745c5c3_Err | ||
| 775 | } | 781 | } | ||
| 776 | if h.Live { | 782 | if h.Live { | ||
| 777 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, " data-live") | 783 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, " data-live") |
| 778 | if templ_7745c5c3_Err != nil { | 784 | if templ_7745c5c3_Err != nil { | ||
| 779 | return templ_7745c5c3_Err | 785 | return templ_7745c5c3_Err | ||
| 780 | } | 786 | } | ||
| 781 | } | 787 | } | ||
| 782 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "><svg viewBox=\"0 0 600 64\" role=\"img\" aria-label=\"") | 788 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "><svg viewBox=\"0 0 600 64\" role=\"img\" aria-label=\"") |
| 783 | if templ_7745c5c3_Err != nil { | 789 | if templ_7745c5c3_Err != nil { | ||
| 784 | return templ_7745c5c3_Err | 790 | return templ_7745c5c3_Err | ||
| 785 | } | 791 | } | ||
| @@ -792,7 +798,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 792 | if templ_7745c5c3_Err != nil { | 798 | if templ_7745c5c3_Err != nil { | ||
| 793 | return templ_7745c5c3_Err | 799 | return templ_7745c5c3_Err | ||
| 794 | } | 800 | } | ||
| 795 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\" focusable=\"false\"><defs><linearGradient id=\"") | 801 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\" focusable=\"false\"><defs><linearGradient id=\"") |
| 796 | if templ_7745c5c3_Err != nil { | 802 | if templ_7745c5c3_Err != nil { | ||
| 797 | return templ_7745c5c3_Err | 803 | return templ_7745c5c3_Err | ||
| 798 | } | 804 | } | ||
| @@ -805,7 +811,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 805 | if templ_7745c5c3_Err != nil { | 811 | if templ_7745c5c3_Err != nil { | ||
| 806 | return templ_7745c5c3_Err | 812 | return templ_7745c5c3_Err | ||
| 807 | } | 813 | } | ||
| 808 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop class=\"pulse-stop-top\" offset=\"0\"></stop> <stop class=\"pulse-stop-bottom\" offset=\"1\"></stop></linearGradient></defs> <path class=\"pulse-grid\" d=\"M0 21.5 H600 M0 42.5 H600 M0 63.5 H600\" vector-effect=\"non-scaling-stroke\"></path> <path class=\"pulse-area\" d=\"") | 814 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop class=\"pulse-stop-top\" offset=\"0\"></stop> <stop class=\"pulse-stop-bottom\" offset=\"1\"></stop></linearGradient></defs> <path class=\"pulse-grid\" d=\"M0 21.5 H600 M0 42.5 H600 M0 63.5 H600\" vector-effect=\"non-scaling-stroke\"></path> <path class=\"pulse-area\" d=\"") |
| 809 | if templ_7745c5c3_Err != nil { | 815 | if templ_7745c5c3_Err != nil { | ||
| 810 | return templ_7745c5c3_Err | 816 | return templ_7745c5c3_Err | ||
| 811 | } | 817 | } | ||
| @@ -818,7 +824,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 818 | if templ_7745c5c3_Err != nil { | 824 | if templ_7745c5c3_Err != nil { | ||
| 819 | return templ_7745c5c3_Err | 825 | return templ_7745c5c3_Err | ||
| 820 | } | 826 | } | ||
| 821 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "\" fill=\"") | 827 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "\" fill=\"") |
| 822 | if templ_7745c5c3_Err != nil { | 828 | if templ_7745c5c3_Err != nil { | ||
| 823 | return templ_7745c5c3_Err | 829 | return templ_7745c5c3_Err | ||
| 824 | } | 830 | } | ||
| @@ -831,7 +837,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 831 | if templ_7745c5c3_Err != nil { | 837 | if templ_7745c5c3_Err != nil { | ||
| 832 | return templ_7745c5c3_Err | 838 | return templ_7745c5c3_Err | ||
| 833 | } | 839 | } | ||
| 834 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "\"></path> <path class=\"pulse-line\" d=\"") | 840 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "\"></path> <path class=\"pulse-line\" d=\"") |
| 835 | if templ_7745c5c3_Err != nil { | 841 | if templ_7745c5c3_Err != nil { | ||
| 836 | return templ_7745c5c3_Err | 842 | return templ_7745c5c3_Err | ||
| 837 | } | 843 | } | ||
| @@ -844,7 +850,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 844 | if templ_7745c5c3_Err != nil { | 850 | if templ_7745c5c3_Err != nil { | ||
| 845 | return templ_7745c5c3_Err | 851 | return templ_7745c5c3_Err | ||
| 846 | } | 852 | } | ||
| 847 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "\" vector-effect=\"non-scaling-stroke\"></path> <circle class=\"pulse-dot\" cx=\"") | 853 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "\" vector-effect=\"non-scaling-stroke\"></path> <circle class=\"pulse-dot\" cx=\"") |
| 848 | if templ_7745c5c3_Err != nil { | 854 | if templ_7745c5c3_Err != nil { | ||
| 849 | return templ_7745c5c3_Err | 855 | return templ_7745c5c3_Err | ||
| 850 | } | 856 | } | ||
| @@ -857,7 +863,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 857 | if templ_7745c5c3_Err != nil { | 863 | if templ_7745c5c3_Err != nil { | ||
| 858 | return templ_7745c5c3_Err | 864 | return templ_7745c5c3_Err | ||
| 859 | } | 865 | } | ||
| 860 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "\" cy=\"") | 866 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "\" cy=\"") |
| 861 | if templ_7745c5c3_Err != nil { | 867 | if templ_7745c5c3_Err != nil { | ||
| 862 | return templ_7745c5c3_Err | 868 | return templ_7745c5c3_Err | ||
| 863 | } | 869 | } | ||
| @@ -870,7 +876,7 @@ func pulse(h *Heartbeat) templ.Component { | |||||
| 870 | if templ_7745c5c3_Err != nil { | 876 | if templ_7745c5c3_Err != nil { | ||
| 871 | return templ_7745c5c3_Err | 877 | return templ_7745c5c3_Err | ||
| 872 | } | 878 | } | ||
| 873 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, "\" r=\"3.5\"></circle></svg></figure>") | 879 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "\" r=\"3.5\"></circle></svg></figure>") |
| 874 | if templ_7745c5c3_Err != nil { | 880 | if templ_7745c5c3_Err != nil { | ||
| 875 | return templ_7745c5c3_Err | 881 | return templ_7745c5c3_Err | ||
| 876 | } | 882 | } | ||
| @@ -900,7 +906,7 @@ func Outline(headings []Heading) templ.Component { | |||||
| 900 | templ_7745c5c3_Var46 = templ.NopComponent | 906 | templ_7745c5c3_Var46 = templ.NopComponent | ||
| 901 | } | 907 | } | ||
| 902 | ctx = templ.ClearChildren(ctx) | 908 | ctx = templ.ClearChildren(ctx) | ||
| 903 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, "<nav class=\"outline\" aria-label=\"Outline\">") | 909 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "<nav class=\"outline\" aria-label=\"Outline\">") |
| 904 | if templ_7745c5c3_Err != nil { | 910 | if templ_7745c5c3_Err != nil { | ||
| 905 | return templ_7745c5c3_Err | 911 | return templ_7745c5c3_Err | ||
| 906 | } | 912 | } | ||
| @@ -910,7 +916,7 @@ func Outline(headings []Heading) templ.Component { | |||||
| 910 | if templ_7745c5c3_Err != nil { | 916 | if templ_7745c5c3_Err != nil { | ||
| 911 | return templ_7745c5c3_Err | 917 | return templ_7745c5c3_Err | ||
| 912 | } | 918 | } | ||
| 913 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "<a class=\"") | 919 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "<a class=\"") |
| 914 | if templ_7745c5c3_Err != nil { | 920 | if templ_7745c5c3_Err != nil { | ||
| 915 | return templ_7745c5c3_Err | 921 | return templ_7745c5c3_Err | ||
| 916 | } | 922 | } | ||
| @@ -923,7 +929,7 @@ func Outline(headings []Heading) templ.Component { | |||||
| 923 | if templ_7745c5c3_Err != nil { | 929 | if templ_7745c5c3_Err != nil { | ||
| 924 | return templ_7745c5c3_Err | 930 | return templ_7745c5c3_Err | ||
| 925 | } | 931 | } | ||
| 926 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 88, "\" href=\"") | 932 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "\" href=\"") |
| 927 | if templ_7745c5c3_Err != nil { | 933 | if templ_7745c5c3_Err != nil { | ||
| 928 | return templ_7745c5c3_Err | 934 | return templ_7745c5c3_Err | ||
| 929 | } | 935 | } | ||
| @@ -936,7 +942,7 @@ func Outline(headings []Heading) templ.Component { | |||||
| 936 | if templ_7745c5c3_Err != nil { | 942 | if templ_7745c5c3_Err != nil { | ||
| 937 | return templ_7745c5c3_Err | 943 | return templ_7745c5c3_Err | ||
| 938 | } | 944 | } | ||
| 939 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, "\">") | 945 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "\">") |
| 940 | if templ_7745c5c3_Err != nil { | 946 | if templ_7745c5c3_Err != nil { | ||
| 941 | return templ_7745c5c3_Err | 947 | return templ_7745c5c3_Err | ||
| 942 | } | 948 | } | ||
| @@ -949,12 +955,12 @@ func Outline(headings []Heading) templ.Component { | |||||
| 949 | if templ_7745c5c3_Err != nil { | 955 | if templ_7745c5c3_Err != nil { | ||
| 950 | return templ_7745c5c3_Err | 956 | return templ_7745c5c3_Err | ||
| 951 | } | 957 | } | ||
| 952 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "</a>") | 958 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "</a>") |
| 953 | if templ_7745c5c3_Err != nil { | 959 | if templ_7745c5c3_Err != nil { | ||
| 954 | return templ_7745c5c3_Err | 960 | return templ_7745c5c3_Err | ||
| 955 | } | 961 | } | ||
| 956 | } | 962 | } | ||
| 957 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "</nav>") | 963 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "</nav>") |
| 958 | if templ_7745c5c3_Err != nil { | 964 | if templ_7745c5c3_Err != nil { | ||
| 959 | return templ_7745c5c3_Err | 965 | return templ_7745c5c3_Err | ||
| 960 | } | 966 | } | ||
| @@ -984,7 +990,7 @@ func ReadmeCard(r Readme) templ.Component { | |||||
| 984 | templ_7745c5c3_Var51 = templ.NopComponent | 990 | templ_7745c5c3_Var51 = templ.NopComponent | ||
| 985 | } | 991 | } | ||
| 986 | ctx = templ.ClearChildren(ctx) | 992 | ctx = templ.ClearChildren(ctx) | ||
| 987 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "<section class=\"card readme\" aria-labelledby=\"readme-h\"><h2 class=\"card-h\" id=\"readme-h\"><span class=\"ico i-file\" aria-hidden=\"true\"></span> ") | 993 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "<section class=\"card readme\" aria-labelledby=\"readme-h\"><h2 class=\"card-h\" id=\"readme-h\"><span class=\"ico i-file\" aria-hidden=\"true\"></span> ") |
| 988 | if templ_7745c5c3_Err != nil { | 994 | if templ_7745c5c3_Err != nil { | ||
| 989 | return templ_7745c5c3_Err | 995 | return templ_7745c5c3_Err | ||
| 990 | } | 996 | } | ||
| @@ -997,7 +1003,7 @@ func ReadmeCard(r Readme) templ.Component { | |||||
| 997 | if templ_7745c5c3_Err != nil { | 1003 | if templ_7745c5c3_Err != nil { | ||
| 998 | return templ_7745c5c3_Err | 1004 | return templ_7745c5c3_Err | ||
| 999 | } | 1005 | } | ||
| 1000 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "</h2>") | 1006 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "</h2>") |
| 1001 | if templ_7745c5c3_Err != nil { | 1007 | if templ_7745c5c3_Err != nil { | ||
| 1002 | return templ_7745c5c3_Err | 1008 | return templ_7745c5c3_Err | ||
| 1003 | } | 1009 | } | ||
| @@ -1005,7 +1011,7 @@ func ReadmeCard(r Readme) templ.Component { | |||||
| 1005 | if templ_7745c5c3_Err != nil { | 1011 | if templ_7745c5c3_Err != nil { | ||
| 1006 | return templ_7745c5c3_Err | 1012 | return templ_7745c5c3_Err | ||
| 1007 | } | 1013 | } | ||
| 1008 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "</section>") | 1014 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "</section>") |
| 1009 | if templ_7745c5c3_Err != nil { | 1015 | if templ_7745c5c3_Err != nil { | ||
| 1010 | return templ_7745c5c3_Err | 1016 | return templ_7745c5c3_Err | ||
| 1011 | } | 1017 | } | ||
| @@ -1036,7 +1042,7 @@ func ReadmeView(r Readme) templ.Component { | |||||
| 1036 | templ_7745c5c3_Var53 = templ.NopComponent | 1042 | templ_7745c5c3_Var53 = templ.NopComponent | ||
| 1037 | } | 1043 | } | ||
| 1038 | ctx = templ.ClearChildren(ctx) | 1044 | ctx = templ.ClearChildren(ctx) | ||
| 1039 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "<article class=\"prose\" aria-label=\"") | 1045 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "<article class=\"prose\" aria-label=\"") |
| 1040 | if templ_7745c5c3_Err != nil { | 1046 | if templ_7745c5c3_Err != nil { | ||
| 1041 | return templ_7745c5c3_Err | 1047 | return templ_7745c5c3_Err | ||
| 1042 | } | 1048 | } | ||
| @@ -1049,12 +1055,12 @@ func ReadmeView(r Readme) templ.Component { | |||||
| 1049 | if templ_7745c5c3_Err != nil { | 1055 | if templ_7745c5c3_Err != nil { | ||
| 1050 | return templ_7745c5c3_Err | 1056 | return templ_7745c5c3_Err | ||
| 1051 | } | 1057 | } | ||
| 1052 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "\" hx-ignore>") | 1058 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "\" hx-ignore>") |
| 1053 | if templ_7745c5c3_Err != nil { | 1059 | if templ_7745c5c3_Err != nil { | ||
| 1054 | return templ_7745c5c3_Err | 1060 | return templ_7745c5c3_Err | ||
| 1055 | } | 1061 | } | ||
| 1056 | if r.Note != "" { | 1062 | if r.Note != "" { | ||
| 1057 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "<p class=\"dim\">") | 1063 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "<p class=\"dim\">") |
| 1058 | if templ_7745c5c3_Err != nil { | 1064 | if templ_7745c5c3_Err != nil { | ||
| 1059 | return templ_7745c5c3_Err | 1065 | return templ_7745c5c3_Err | ||
| 1060 | } | 1066 | } | ||
| @@ -1067,7 +1073,7 @@ func ReadmeView(r Readme) templ.Component { | |||||
| 1067 | if templ_7745c5c3_Err != nil { | 1073 | if templ_7745c5c3_Err != nil { | ||
| 1068 | return templ_7745c5c3_Err | 1074 | return templ_7745c5c3_Err | ||
| 1069 | } | 1075 | } | ||
| 1070 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "</p>") | 1076 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "</p>") |
| 1071 | if templ_7745c5c3_Err != nil { | 1077 | if templ_7745c5c3_Err != nil { | ||
| 1072 | return templ_7745c5c3_Err | 1078 | return templ_7745c5c3_Err | ||
| 1073 | } | 1079 | } | ||
| @@ -1077,7 +1083,7 @@ func ReadmeView(r Readme) templ.Component { | |||||
| 1077 | return templ_7745c5c3_Err | 1083 | return templ_7745c5c3_Err | ||
| 1078 | } | 1084 | } | ||
| 1079 | } | 1085 | } | ||
| 1080 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "</article>") | 1086 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "</article>") |
| 1081 | if templ_7745c5c3_Err != nil { | 1087 | if templ_7745c5c3_Err != nil { | ||
| 1082 | return templ_7745c5c3_Err | 1088 | return templ_7745c5c3_Err | ||
| 1083 | } | 1089 | } | ||
| @@ -1108,17 +1114,17 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1108 | templ_7745c5c3_Var56 = templ.NopComponent | 1114 | templ_7745c5c3_Var56 = templ.NopComponent | ||
| 1109 | } | 1115 | } | ||
| 1110 | ctx = templ.ClearChildren(ctx) | 1116 | ctx = templ.ClearChildren(ctx) | ||
| 1111 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "<table class=\"list commits\" aria-label=\"Commits\"><tbody data-rows>") | 1117 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "<table class=\"list commits\" aria-label=\"Commits\"><tbody data-rows>") |
| 1112 | if templ_7745c5c3_Err != nil { | 1118 | if templ_7745c5c3_Err != nil { | ||
| 1113 | return templ_7745c5c3_Err | 1119 | return templ_7745c5c3_Err | ||
| 1114 | } | 1120 | } | ||
| 1115 | for _, c := range rows { | 1121 | for _, c := range rows { | ||
| 1116 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 101, "<tr") | 1122 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "<tr") |
| 1117 | if templ_7745c5c3_Err != nil { | 1123 | if templ_7745c5c3_Err != nil { | ||
| 1118 | return templ_7745c5c3_Err | 1124 | return templ_7745c5c3_Err | ||
| 1119 | } | 1125 | } | ||
| 1120 | if c.ID != "" { | 1126 | if c.ID != "" { | ||
| 1121 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, " id=\"") | 1127 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, " id=\"") |
| 1122 | if templ_7745c5c3_Err != nil { | 1128 | if templ_7745c5c3_Err != nil { | ||
| 1123 | return templ_7745c5c3_Err | 1129 | return templ_7745c5c3_Err | ||
| 1124 | } | 1130 | } | ||
| @@ -1131,18 +1137,18 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1131 | if templ_7745c5c3_Err != nil { | 1137 | if templ_7745c5c3_Err != nil { | ||
| 1132 | return templ_7745c5c3_Err | 1138 | return templ_7745c5c3_Err | ||
| 1133 | } | 1139 | } | ||
| 1134 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "\"") | 1140 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "\"") |
| 1135 | if templ_7745c5c3_Err != nil { | 1141 | if templ_7745c5c3_Err != nil { | ||
| 1136 | return templ_7745c5c3_Err | 1142 | return templ_7745c5c3_Err | ||
| 1137 | } | 1143 | } | ||
| 1138 | } | 1144 | } | ||
| 1139 | if c.Cursor { | 1145 | if c.Cursor { | ||
| 1140 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, " data-cursor") | 1146 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, " data-cursor") |
| 1141 | if templ_7745c5c3_Err != nil { | 1147 | if templ_7745c5c3_Err != nil { | ||
| 1142 | return templ_7745c5c3_Err | 1148 | return templ_7745c5c3_Err | ||
| 1143 | } | 1149 | } | ||
| 1144 | } | 1150 | } | ||
| 1145 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "><td class=\"c-sha mute\">") | 1151 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "><td class=\"c-sha mute\">") |
| 1146 | if templ_7745c5c3_Err != nil { | 1152 | if templ_7745c5c3_Err != nil { | ||
| 1147 | return templ_7745c5c3_Err | 1153 | return templ_7745c5c3_Err | ||
| 1148 | } | 1154 | } | ||
| @@ -1155,7 +1161,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1155 | if templ_7745c5c3_Err != nil { | 1161 | if templ_7745c5c3_Err != nil { | ||
| 1156 | return templ_7745c5c3_Err | 1162 | return templ_7745c5c3_Err | ||
| 1157 | } | 1163 | } | ||
| 1158 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "</td><td class=\"c-subject\"><a href=\"") | 1164 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "</td><td class=\"c-subject\"><a href=\"") |
| 1159 | if templ_7745c5c3_Err != nil { | 1165 | if templ_7745c5c3_Err != nil { | ||
| 1160 | return templ_7745c5c3_Err | 1166 | return templ_7745c5c3_Err | ||
| 1161 | } | 1167 | } | ||
| @@ -1168,7 +1174,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1168 | if templ_7745c5c3_Err != nil { | 1174 | if templ_7745c5c3_Err != nil { | ||
| 1169 | return templ_7745c5c3_Err | 1175 | return templ_7745c5c3_Err | ||
| 1170 | } | 1176 | } | ||
| 1171 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "\">") | 1177 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "\">") |
| 1172 | if templ_7745c5c3_Err != nil { | 1178 | if templ_7745c5c3_Err != nil { | ||
| 1173 | return templ_7745c5c3_Err | 1179 | return templ_7745c5c3_Err | ||
| 1174 | } | 1180 | } | ||
| @@ -1181,12 +1187,12 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1181 | if templ_7745c5c3_Err != nil { | 1187 | if templ_7745c5c3_Err != nil { | ||
| 1182 | return templ_7745c5c3_Err | 1188 | return templ_7745c5c3_Err | ||
| 1183 | } | 1189 | } | ||
| 1184 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "</a> ") | 1190 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "</a> ") |
| 1185 | if templ_7745c5c3_Err != nil { | 1191 | if templ_7745c5c3_Err != nil { | ||
| 1186 | return templ_7745c5c3_Err | 1192 | return templ_7745c5c3_Err | ||
| 1187 | } | 1193 | } | ||
| 1188 | if c.Merge { | 1194 | if c.Merge { | ||
| 1189 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "<span class=\"pill\">merge</span> ") | 1195 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "<span class=\"pill\">merge</span> ") |
| 1190 | if templ_7745c5c3_Err != nil { | 1196 | if templ_7745c5c3_Err != nil { | ||
| 1191 | return templ_7745c5c3_Err | 1197 | return templ_7745c5c3_Err | ||
| 1192 | } | 1198 | } | ||
| @@ -1198,7 +1204,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1198 | } | 1204 | } | ||
| 1199 | } | 1205 | } | ||
| 1200 | for _, b := range c.Branches { | 1206 | for _, b := range c.Branches { | ||
| 1201 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "<span class=\"pill\">") | 1207 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "<span class=\"pill\">") |
| 1202 | if templ_7745c5c3_Err != nil { | 1208 | if templ_7745c5c3_Err != nil { | ||
| 1203 | return templ_7745c5c3_Err | 1209 | return templ_7745c5c3_Err | ||
| 1204 | } | 1210 | } | ||
| @@ -1211,13 +1217,13 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1211 | if templ_7745c5c3_Err != nil { | 1217 | if templ_7745c5c3_Err != nil { | ||
| 1212 | return templ_7745c5c3_Err | 1218 | return templ_7745c5c3_Err | ||
| 1213 | } | 1219 | } | ||
| 1214 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "</span> ") | 1220 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "</span> ") |
| 1215 | if templ_7745c5c3_Err != nil { | 1221 | if templ_7745c5c3_Err != nil { | ||
| 1216 | return templ_7745c5c3_Err | 1222 | return templ_7745c5c3_Err | ||
| 1217 | } | 1223 | } | ||
| 1218 | } | 1224 | } | ||
| 1219 | for _, t := range c.Tags { | 1225 | for _, t := range c.Tags { | ||
| 1220 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "<span class=\"pill tag\"><span class=\"sr\">tag </span>") | 1226 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "<span class=\"pill tag\"><span class=\"sr\">tag </span>") |
| 1221 | if templ_7745c5c3_Err != nil { | 1227 | if templ_7745c5c3_Err != nil { | ||
| 1222 | return templ_7745c5c3_Err | 1228 | return templ_7745c5c3_Err | ||
| 1223 | } | 1229 | } | ||
| @@ -1230,12 +1236,12 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1230 | if templ_7745c5c3_Err != nil { | 1236 | if templ_7745c5c3_Err != nil { | ||
| 1231 | return templ_7745c5c3_Err | 1237 | return templ_7745c5c3_Err | ||
| 1232 | } | 1238 | } | ||
| 1233 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "</span>") | 1239 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "</span>") |
| 1234 | if templ_7745c5c3_Err != nil { | 1240 | if templ_7745c5c3_Err != nil { | ||
| 1235 | return templ_7745c5c3_Err | 1241 | return templ_7745c5c3_Err | ||
| 1236 | } | 1242 | } | ||
| 1237 | } | 1243 | } | ||
| 1238 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "</td><td class=\"c-ck\">") | 1244 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "</td><td class=\"c-ck\">") |
| 1239 | if templ_7745c5c3_Err != nil { | 1245 | if templ_7745c5c3_Err != nil { | ||
| 1240 | return templ_7745c5c3_Err | 1246 | return templ_7745c5c3_Err | ||
| 1241 | } | 1247 | } | ||
| @@ -1243,7 +1249,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1243 | if templ_7745c5c3_Err != nil { | 1249 | if templ_7745c5c3_Err != nil { | ||
| 1244 | return templ_7745c5c3_Err | 1250 | return templ_7745c5c3_Err | ||
| 1245 | } | 1251 | } | ||
| 1246 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "</td><td class=\"c-who dim\">") | 1252 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "</td><td class=\"c-who dim\">") |
| 1247 | if templ_7745c5c3_Err != nil { | 1253 | if templ_7745c5c3_Err != nil { | ||
| 1248 | return templ_7745c5c3_Err | 1254 | return templ_7745c5c3_Err | ||
| 1249 | } | 1255 | } | ||
| @@ -1256,7 +1262,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1256 | if templ_7745c5c3_Err != nil { | 1262 | if templ_7745c5c3_Err != nil { | ||
| 1257 | return templ_7745c5c3_Err | 1263 | return templ_7745c5c3_Err | ||
| 1258 | } | 1264 | } | ||
| 1259 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "</td><td class=\"c-when nowrap dim\"><time datetime=\"") | 1265 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "</td><td class=\"c-when nowrap dim\"><time datetime=\"") |
| 1260 | if templ_7745c5c3_Err != nil { | 1266 | if templ_7745c5c3_Err != nil { | ||
| 1261 | return templ_7745c5c3_Err | 1267 | return templ_7745c5c3_Err | ||
| 1262 | } | 1268 | } | ||
| @@ -1269,7 +1275,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1269 | if templ_7745c5c3_Err != nil { | 1275 | if templ_7745c5c3_Err != nil { | ||
| 1270 | return templ_7745c5c3_Err | 1276 | return templ_7745c5c3_Err | ||
| 1271 | } | 1277 | } | ||
| 1272 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "\" title=\"") | 1278 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "\" title=\"") |
| 1273 | if templ_7745c5c3_Err != nil { | 1279 | if templ_7745c5c3_Err != nil { | ||
| 1274 | return templ_7745c5c3_Err | 1280 | return templ_7745c5c3_Err | ||
| 1275 | } | 1281 | } | ||
| @@ -1282,7 +1288,7 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1282 | if templ_7745c5c3_Err != nil { | 1288 | if templ_7745c5c3_Err != nil { | ||
| 1283 | return templ_7745c5c3_Err | 1289 | return templ_7745c5c3_Err | ||
| 1284 | } | 1290 | } | ||
| 1285 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "\">") | 1291 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "\">") |
| 1286 | if templ_7745c5c3_Err != nil { | 1292 | if templ_7745c5c3_Err != nil { | ||
| 1287 | return templ_7745c5c3_Err | 1293 | return templ_7745c5c3_Err | ||
| 1288 | } | 1294 | } | ||
| @@ -1295,12 +1301,12 @@ func CommitRows(rows []CommitRow) templ.Component { | |||||
| 1295 | if templ_7745c5c3_Err != nil { | 1301 | if templ_7745c5c3_Err != nil { | ||
| 1296 | return templ_7745c5c3_Err | 1302 | return templ_7745c5c3_Err | ||
| 1297 | } | 1303 | } | ||
| 1298 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "</time></td></tr>") | 1304 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "</time></td></tr>") |
| 1299 | if templ_7745c5c3_Err != nil { | 1305 | if templ_7745c5c3_Err != nil { | ||
| 1300 | return templ_7745c5c3_Err | 1306 | return templ_7745c5c3_Err | ||
| 1301 | } | 1307 | } | ||
| 1302 | } | 1308 | } | ||
| 1303 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "</tbody></table>") | 1309 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "</tbody></table>") |
| 1304 | if templ_7745c5c3_Err != nil { | 1310 | if templ_7745c5c3_Err != nil { | ||
| 1305 | return templ_7745c5c3_Err | 1311 | return templ_7745c5c3_Err | ||
| 1306 | } | 1312 | } | ||
| @@ -1336,7 +1342,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||||
| 1336 | if templ_7745c5c3_Err != nil { | 1342 | if templ_7745c5c3_Err != nil { | ||
| 1337 | return templ_7745c5c3_Err | 1343 | return templ_7745c5c3_Err | ||
| 1338 | } | 1344 | } | ||
| 1339 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "<span class=\"") | 1345 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "<span class=\"") |
| 1340 | if templ_7745c5c3_Err != nil { | 1346 | if templ_7745c5c3_Err != nil { | ||
| 1341 | return templ_7745c5c3_Err | 1347 | return templ_7745c5c3_Err | ||
| 1342 | } | 1348 | } | ||
| @@ -1349,7 +1355,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||||
| 1349 | if templ_7745c5c3_Err != nil { | 1355 | if templ_7745c5c3_Err != nil { | ||
| 1350 | return templ_7745c5c3_Err | 1356 | return templ_7745c5c3_Err | ||
| 1351 | } | 1357 | } | ||
| 1352 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "\" title=\"") | 1358 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "\" title=\"") |
| 1353 | if templ_7745c5c3_Err != nil { | 1359 | if templ_7745c5c3_Err != nil { | ||
| 1354 | return templ_7745c5c3_Err | 1360 | return templ_7745c5c3_Err | ||
| 1355 | } | 1361 | } | ||
| @@ -1362,12 +1368,12 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||||
| 1362 | if templ_7745c5c3_Err != nil { | 1368 | if templ_7745c5c3_Err != nil { | ||
| 1363 | return templ_7745c5c3_Err | 1369 | return templ_7745c5c3_Err | ||
| 1364 | } | 1370 | } | ||
| 1365 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "\">") | 1371 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "\">") |
| 1366 | if templ_7745c5c3_Err != nil { | 1372 | if templ_7745c5c3_Err != nil { | ||
| 1367 | return templ_7745c5c3_Err | 1373 | return templ_7745c5c3_Err | ||
| 1368 | } | 1374 | } | ||
| 1369 | if b.Proto != "" { | 1375 | if b.Proto != "" { | ||
| 1370 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "<span class=\"sig-proto\">") | 1376 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "<span class=\"sig-proto\">") |
| 1371 | if templ_7745c5c3_Err != nil { | 1377 | if templ_7745c5c3_Err != nil { | ||
| 1372 | return templ_7745c5c3_Err | 1378 | return templ_7745c5c3_Err | ||
| 1373 | } | 1379 | } | ||
| @@ -1380,7 +1386,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||||
| 1380 | if templ_7745c5c3_Err != nil { | 1386 | if templ_7745c5c3_Err != nil { | ||
| 1381 | return templ_7745c5c3_Err | 1387 | return templ_7745c5c3_Err | ||
| 1382 | } | 1388 | } | ||
| 1383 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "</span> ") | 1389 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "</span> ") |
| 1384 | if templ_7745c5c3_Err != nil { | 1390 | if templ_7745c5c3_Err != nil { | ||
| 1385 | return templ_7745c5c3_Err | 1391 | return templ_7745c5c3_Err | ||
| 1386 | } | 1392 | } | ||
| @@ -1394,7 +1400,7 @@ func signaturePill(b *SignatureBadge) templ.Component { | |||||
| 1394 | if templ_7745c5c3_Err != nil { | 1400 | if templ_7745c5c3_Err != nil { | ||
| 1395 | return templ_7745c5c3_Err | 1401 | return templ_7745c5c3_Err | ||
| 1396 | } | 1402 | } | ||
| 1397 | - | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "</span>") | 1403 | + | templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "</span>") |
| 1398 | if templ_7745c5c3_Err != nil { | 1404 | if templ_7745c5c3_Err != nil { | ||
| 1399 | return templ_7745c5c3_Err | 1405 | return templ_7745c5c3_Err | ||
| 1400 | } | 1406 | } | ||
M internal/adapters/web/events.go +2 -0
| @@ -50,6 +50,8 @@ import ( | |||
| 50 | 50 | // | |
| 51 | 51 | // home-list data: <li id="repo-<name>">…</li>, or <li id="repo-<name>" data-gone></li> | |
| 52 | 52 | // for a repository that is deleted or no longer visible | |
| 53 | + | // Activity rows carry data-activity: push, MR lifecycle/comment, | |
| 54 | + | // or issue lifecycle/comment (never pending moderation or CI). | |
| 53 | 55 | // repo-last-push data: <dd id="last-push-<name>">…</dd> | |
| 54 | 56 | // refs-list data: <tbody id="ref-rows">…</tbody>, and again with | |
| 55 | 57 | // <dl id="refs-kv">…</dl>, the facts of the rail | |
| @@ -50,6 +50,8 @@ import ( | |||||
| 50 | // | 50 | // | ||
| 51 | // home-list data: <li id="repo-<name>">…</li>, or <li id="repo-<name>" data-gone></li> | 51 | // home-list data: <li id="repo-<name>">…</li>, or <li id="repo-<name>" data-gone></li> | ||
| 52 | // for a repository that is deleted or no longer visible | 52 | // for a repository that is deleted or no longer visible | ||
| 53 | + | // Activity rows carry data-activity: push, MR lifecycle/comment, | |||
| 54 | + | // or issue lifecycle/comment (never pending moderation or CI). | |||
| 53 | // repo-last-push data: <dd id="last-push-<name>">…</dd> | 55 | // repo-last-push data: <dd id="last-push-<name>">…</dd> | ||
| 54 | // refs-list data: <tbody id="ref-rows">…</tbody>, and again with | 56 | // refs-list data: <tbody id="ref-rows">…</tbody>, and again with | ||
| 55 | // <dl id="refs-kv">…</dl>, the facts of the rail | 57 | // <dl id="refs-kv">…</dl>, the facts of the rail | ||
M internal/adapters/web/fragments.go +18 -0
| @@ -112,6 +112,24 @@ func (l *liveStream) home(ctx context.Context, we ports.WatchEvent) ([]fragment, | |||
| 112 | 112 | name = ev.Repo.String() | |
| 113 | 113 | case domain.PushEvent: | |
| 114 | 114 | name, fresh = ev.Repo.String(), true | |
| 115 | + | case domain.MergeRequestOpened: | |
| 116 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |
| 117 | + | case domain.MergeRequestMerged: | |
| 118 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |
| 119 | + | case domain.MergeRequestClosed: | |
| 120 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |
| 121 | + | case domain.MergeRequestReady: | |
| 122 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |
| 123 | + | case domain.CommentAdded: | |
| 124 | + | name, fresh = ev.Repo.String(), true | |
| 125 | + | case domain.IssueOpened: | |
| 126 | + | name, fresh = ev.Issue.Repo.String(), true | |
| 127 | + | case domain.IssueClosed: | |
| 128 | + | name, fresh = ev.Issue.Repo.String(), true | |
| 129 | + | case domain.IssueReopened: | |
| 130 | + | name, fresh = ev.Issue.Repo.String(), true | |
| 131 | + | case domain.IssueCommented: | |
| 132 | + | name, fresh = ev.Repo.String(), true | |
| 115 | 133 | case domain.RunUpdated: | |
| 116 | 134 | name = ev.Run.Repo.String() // the CI state of the row | |
| 117 | 135 | case domain.JobUpdated: | |
| @@ -112,6 +112,24 @@ func (l *liveStream) home(ctx context.Context, we ports.WatchEvent) ([]fragment, | |||||
| 112 | name = ev.Repo.String() | 112 | name = ev.Repo.String() | ||
| 113 | case domain.PushEvent: | 113 | case domain.PushEvent: | ||
| 114 | name, fresh = ev.Repo.String(), true | 114 | name, fresh = ev.Repo.String(), true | ||
| 115 | + | case domain.MergeRequestOpened: | |||
| 116 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |||
| 117 | + | case domain.MergeRequestMerged: | |||
| 118 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |||
| 119 | + | case domain.MergeRequestClosed: | |||
| 120 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |||
| 121 | + | case domain.MergeRequestReady: | |||
| 122 | + | name, fresh = ev.MergeRequest.Repo.String(), true | |||
| 123 | + | case domain.CommentAdded: | |||
| 124 | + | name, fresh = ev.Repo.String(), true | |||
| 125 | + | case domain.IssueOpened: | |||
| 126 | + | name, fresh = ev.Issue.Repo.String(), true | |||
| 127 | + | case domain.IssueClosed: | |||
| 128 | + | name, fresh = ev.Issue.Repo.String(), true | |||
| 129 | + | case domain.IssueReopened: | |||
| 130 | + | name, fresh = ev.Issue.Repo.String(), true | |||
| 131 | + | case domain.IssueCommented: | |||
| 132 | + | name, fresh = ev.Repo.String(), true | |||
| 115 | case domain.RunUpdated: | 133 | case domain.RunUpdated: | ||
| 116 | name = ev.Run.Repo.String() // the CI state of the row | 134 | name = ev.Run.Repo.String() // the CI state of the row | ||
| 117 | case domain.JobUpdated: | 135 | case domain.JobUpdated: | ||
M internal/adapters/web/home.go +22 -11
| @@ -56,12 +56,12 @@ func (s *Server) listRepos(ctx context.Context) ([]ports.RepoView, error) { | |||
| 56 | 56 | // homeSorts are the orders the home list offers, in order. The query also | |
| 57 | 57 | // accepts "desc" and "branch", which the page does not link to. | |
| 58 | 58 | var homeSorts = []struct{ key, label string }{ | |
| 59 | - | {"push", "last push"}, | |
| 59 | + | {"activity", "last activity"}, | |
| 60 | 60 | {"name", "name"}, | |
| 61 | 61 | } | |
| 62 | 62 | ||
| 63 | 63 | // homeKeys are the keys of ?sort= that sortRepos knows. | |
| 64 | - | var homeKeys = []string{"push", "name", "desc", "branch"} | |
| 64 | + | var homeKeys = []string{"activity", "name", "desc", "branch"} | |
| 65 | 65 | ||
| 66 | 66 | // sortRepos orders repos by the column key; ties keep the order by name. | |
| 67 | 67 | func sortRepos(repos []ports.RepoView, key string, desc bool) { | |
| @@ -71,8 +71,8 @@ func sortRepos(repos []ports.RepoView, key string, desc bool) { | |||
| 71 | 71 | return strings.ToLower(a.Description) < strings.ToLower(b.Description) | |
| 72 | 72 | case "branch": | |
| 73 | 73 | return a.DefaultBranch < b.DefaultBranch | |
| 74 | - | case "push": | |
| 75 | - | return a.PushedAt.Before(b.PushedAt) | |
| 74 | + | case "activity": | |
| 75 | + | return repoActiveAt(a).Before(repoActiveAt(b)) | |
| 76 | 76 | } | |
| 77 | 77 | return a.Name.String() < b.Name.String() | |
| 78 | 78 | } | |
| @@ -84,17 +84,17 @@ func sortRepos(repos []ports.RepoView, key string, desc bool) { | |||
| 84 | 84 | }) | |
| 85 | 85 | } | |
| 86 | 86 | ||
| 87 | - | // home lists the repositories: /?sort=<col>&dir=asc|desc, newest push first | |
| 87 | + | // home lists the repositories: /?sort=<col>&dir=asc|desc, newest activity first | |
| 88 | 88 | // by default. | |
| 89 | 89 | func (s *Server) home(ctx context.Context, r *http.Request) (templ.Component, int, error) { | |
| 90 | 90 | repos, err := s.listRepos(ctx) | |
| 91 | 91 | if err != nil { | |
| 92 | 92 | return nil, 0, err | |
| 93 | 93 | } | |
| 94 | - | key, desc := "push", true | |
| 94 | + | key, desc := "activity", true | |
| 95 | 95 | for _, k := range homeKeys { | |
| 96 | 96 | if r.URL.Query().Get("sort") == k { | |
| 97 | - | key, desc = k, k == "push" | |
| 97 | + | key, desc = k, k == "activity" | |
| 98 | 98 | } | |
| 99 | 99 | } | |
| 100 | 100 | if d := r.URL.Query().Get("dir"); d == "asc" || d == "desc" { | |
| @@ -103,11 +103,11 @@ func (s *Server) home(ctx context.Context, r *http.Request) (templ.Component, in | |||
| 103 | 103 | sortRepos(repos, key, desc) | |
| 104 | 104 | ||
| 105 | 105 | now := s.cfg.Now() | |
| 106 | - | p := HomePage{} | |
| 106 | + | p := HomePage{Sort: key, Desc: desc} | |
| 107 | 107 | for _, c := range homeSorts { | |
| 108 | 108 | sl := SortLink{Label: c.label} | |
| 109 | 109 | next := "asc" | |
| 110 | - | if c.key == "push" { | |
| 110 | + | if c.key == "activity" { | |
| 111 | 111 | next = "desc" | |
| 112 | 112 | } | |
| 113 | 113 | if c.key == key { | |
| @@ -267,8 +267,8 @@ func homeRow(r ports.RepoView, now time.Time, cursor, signed bool) HomeRow { | |||
| 267 | 267 | Desc: r.Description, Topics: r.Topics, Cursor: cursor, | |
| 268 | 268 | Private: signed && r.Visibility == domain.VisibilityPrivate, | |
| 269 | 269 | } | |
| 270 | - | if !r.PushedAt.IsZero() { | |
| 271 | - | row.Active, row.ActiveAt = ago(now, r.PushedAt), rfc3339(r.PushedAt) | |
| 270 | + | if at := repoActiveAt(r); !at.IsZero() { | |
| 271 | + | row.Active, row.ActiveAt = ago(now, at), rfc3339(at) | |
| 272 | 272 | } | |
| 273 | 273 | return row | |
| 274 | 274 | } | |
| @@ -284,3 +284,14 @@ func repoCmds(repos []ports.RepoView, except string) []CmdItem { | |||
| 284 | 284 | } | |
| 285 | 285 | return out | |
| 286 | 286 | } | |
| 287 | + | ||
| 288 | + | // repoActiveAt falls back for repositories without recorded activity. | |
| 289 | + | func repoActiveAt(r ports.RepoView) time.Time { | |
| 290 | + | if !r.ActiveAt.IsZero() { | |
| 291 | + | return r.ActiveAt | |
| 292 | + | } | |
| 293 | + | if r.PushedAt.After(r.CreatedAt) { | |
| 294 | + | return r.PushedAt | |
| 295 | + | } | |
| 296 | + | return r.CreatedAt | |
| 297 | + | } | |
| @@ -56,12 +56,12 @@ func (s *Server) listRepos(ctx context.Context) ([]ports.RepoView, error) { | |||||
| 56 | // homeSorts are the orders the home list offers, in order. The query also | 56 | // homeSorts are the orders the home list offers, in order. The query also | ||
| 57 | // accepts "desc" and "branch", which the page does not link to. | 57 | // accepts "desc" and "branch", which the page does not link to. | ||
| 58 | var homeSorts = []struct{ key, label string }{ | 58 | var homeSorts = []struct{ key, label string }{ | ||
| 59 | - | {"push", "last push"}, | 59 | + | {"activity", "last activity"}, |
| 60 | {"name", "name"}, | 60 | {"name", "name"}, | ||
| 61 | } | 61 | } | ||
| 62 | 62 | ||||
| 63 | // homeKeys are the keys of ?sort= that sortRepos knows. | 63 | // homeKeys are the keys of ?sort= that sortRepos knows. | ||
| 64 | - | var homeKeys = []string{"push", "name", "desc", "branch"} | 64 | + | var homeKeys = []string{"activity", "name", "desc", "branch"} |
| 65 | 65 | ||||
| 66 | // sortRepos orders repos by the column key; ties keep the order by name. | 66 | // sortRepos orders repos by the column key; ties keep the order by name. | ||
| 67 | func sortRepos(repos []ports.RepoView, key string, desc bool) { | 67 | func sortRepos(repos []ports.RepoView, key string, desc bool) { | ||
| @@ -71,8 +71,8 @@ func sortRepos(repos []ports.RepoView, key string, desc bool) { | |||||
| 71 | return strings.ToLower(a.Description) < strings.ToLower(b.Description) | 71 | return strings.ToLower(a.Description) < strings.ToLower(b.Description) | ||
| 72 | case "branch": | 72 | case "branch": | ||
| 73 | return a.DefaultBranch < b.DefaultBranch | 73 | return a.DefaultBranch < b.DefaultBranch | ||
| 74 | - | case "push": | 74 | + | case "activity": |
| 75 | - | return a.PushedAt.Before(b.PushedAt) | 75 | + | return repoActiveAt(a).Before(repoActiveAt(b)) |
| 76 | } | 76 | } | ||
| 77 | return a.Name.String() < b.Name.String() | 77 | return a.Name.String() < b.Name.String() | ||
| 78 | } | 78 | } | ||
| @@ -84,17 +84,17 @@ func sortRepos(repos []ports.RepoView, key string, desc bool) { | |||||
| 84 | }) | 84 | }) | ||
| 85 | } | 85 | } | ||
| 86 | 86 | ||||
| 87 | - | // home lists the repositories: /?sort=<col>&dir=asc|desc, newest push first | 87 | + | // home lists the repositories: /?sort=<col>&dir=asc|desc, newest activity first |
| 88 | // by default. | 88 | // by default. | ||
| 89 | func (s *Server) home(ctx context.Context, r *http.Request) (templ.Component, int, error) { | 89 | func (s *Server) home(ctx context.Context, r *http.Request) (templ.Component, int, error) { | ||
| 90 | repos, err := s.listRepos(ctx) | 90 | repos, err := s.listRepos(ctx) | ||
| 91 | if err != nil { | 91 | if err != nil { | ||
| 92 | return nil, 0, err | 92 | return nil, 0, err | ||
| 93 | } | 93 | } | ||
| 94 | - | key, desc := "push", true | 94 | + | key, desc := "activity", true |
| 95 | for _, k := range homeKeys { | 95 | for _, k := range homeKeys { | ||
| 96 | if r.URL.Query().Get("sort") == k { | 96 | if r.URL.Query().Get("sort") == k { | ||
| 97 | - | key, desc = k, k == "push" | 97 | + | key, desc = k, k == "activity" |
| 98 | } | 98 | } | ||
| 99 | } | 99 | } | ||
| 100 | if d := r.URL.Query().Get("dir"); d == "asc" || d == "desc" { | 100 | if d := r.URL.Query().Get("dir"); d == "asc" || d == "desc" { | ||
| @@ -103,11 +103,11 @@ func (s *Server) home(ctx context.Context, r *http.Request) (templ.Component, in | |||||
| 103 | sortRepos(repos, key, desc) | 103 | sortRepos(repos, key, desc) | ||
| 104 | 104 | ||||
| 105 | now := s.cfg.Now() | 105 | now := s.cfg.Now() | ||
| 106 | - | p := HomePage{} | 106 | + | p := HomePage{Sort: key, Desc: desc} |
| 107 | for _, c := range homeSorts { | 107 | for _, c := range homeSorts { | ||
| 108 | sl := SortLink{Label: c.label} | 108 | sl := SortLink{Label: c.label} | ||
| 109 | next := "asc" | 109 | next := "asc" | ||
| 110 | - | if c.key == "push" { | 110 | + | if c.key == "activity" { |
| 111 | next = "desc" | 111 | next = "desc" | ||
| 112 | } | 112 | } | ||
| 113 | if c.key == key { | 113 | if c.key == key { | ||
| @@ -267,8 +267,8 @@ func homeRow(r ports.RepoView, now time.Time, cursor, signed bool) HomeRow { | |||||
| 267 | Desc: r.Description, Topics: r.Topics, Cursor: cursor, | 267 | Desc: r.Description, Topics: r.Topics, Cursor: cursor, | ||
| 268 | Private: signed && r.Visibility == domain.VisibilityPrivate, | 268 | Private: signed && r.Visibility == domain.VisibilityPrivate, | ||
| 269 | } | 269 | } | ||
| 270 | - | if !r.PushedAt.IsZero() { | 270 | + | if at := repoActiveAt(r); !at.IsZero() { |
| 271 | - | row.Active, row.ActiveAt = ago(now, r.PushedAt), rfc3339(r.PushedAt) | 271 | + | row.Active, row.ActiveAt = ago(now, at), rfc3339(at) |
| 272 | } | 272 | } | ||
| 273 | return row | 273 | return row | ||
| 274 | } | 274 | } | ||
| @@ -284,3 +284,14 @@ func repoCmds(repos []ports.RepoView, except string) []CmdItem { | |||||
| 284 | } | 284 | } | ||
| 285 | return out | 285 | return out | ||
| 286 | } | 286 | } | ||
| 287 | + | ||||
| 288 | + | // repoActiveAt falls back for repositories without recorded activity. | |||
| 289 | + | func repoActiveAt(r ports.RepoView) time.Time { | |||
| 290 | + | if !r.ActiveAt.IsZero() { | |||
| 291 | + | return r.ActiveAt | |||
| 292 | + | } | |||
| 293 | + | if r.PushedAt.After(r.CreatedAt) { | |||
| 294 | + | return r.PushedAt | |||
| 295 | + | } | |||
| 296 | + | return r.CreatedAt | |||
| 297 | + | } | |||
M internal/adapters/web/home_test.go +49 -1
| @@ -252,7 +252,7 @@ func TestRunUpdatedRefreshesTheHomeRow(t *testing.T) { | |||
| 252 | 252 | assert.Equal(t, "home-list", got[0].event) | |
| 253 | 253 | assert.Contains(t, got[0].html, `id="repo-proj"`) | |
| 254 | 254 | assert.Contains(t, got[0].html, "passing") | |
| 255 | - | assert.NotContains(t, got[0].html, "new push", "a run is not a push") | |
| 255 | + | assert.NotContains(t, got[0].html, "new activity", "a run is not a push") | |
| 256 | 256 | ||
| 257 | 257 | // A job that ended refreshes the row too; one in progress does not. | |
| 258 | 258 | got, err = (&liveStream{s: srv}).render(t.Context(), ports.WatchEvent{Event: domain.JobUpdated{Job: domain.CIJob{Repo: repo, Phase: domain.CIPhaseRunning}}}) | |
| @@ -344,3 +344,51 @@ func TestHomeOffersTheLayouts(t *testing.T) { | |||
| 344 | 344 | require.NotEqual(t, -1, store) | |
| 345 | 345 | assert.Less(t, store, app, "the store loads before the app script") | |
| 346 | 346 | } | |
| 347 | + | ||
| 348 | + | func TestHomeActivityOrderAndFallback(t *testing.T) { | |
| 349 | + | t.Parallel() | |
| 350 | + | now := time.Now().UTC() | |
| 351 | + | a, b, c := publicRepo(t, "a"), publicRepo(t, "b"), publicRepo(t, "c") | |
| 352 | + | a.PushedAt = now.Add(-time.Hour) | |
| 353 | + | a.ActiveAt = now | |
| 354 | + | b.PushedAt = now.Add(-time.Minute) | |
| 355 | + | c.CreatedAt = now.Add(-30 * time.Minute) | |
| 356 | + | repos := []ports.RepoView{b, c, a} | |
| 357 | + | sortRepos(repos, "activity", true) | |
| 358 | + | assert.Equal(t, []ports.RepoView{a, b, c}, repos) | |
| 359 | + | sortRepos(repos, "activity", false) | |
| 360 | + | assert.Equal(t, []ports.RepoView{c, b, a}, repos) | |
| 361 | + | assert.Equal(t, rfc3339(now), homeRow(a, now, false, false).ActiveAt) | |
| 362 | + | c.PushedAt = c.CreatedAt.Add(-time.Hour) | |
| 363 | + | assert.Equal(t, c.CreatedAt, repoActiveAt(c), "fallback is the later of creation and push") | |
| 364 | + | } | |
| 365 | + | ||
| 366 | + | func TestActivityEventsRefreshTheHomeRow(t *testing.T) { | |
| 367 | + | t.Parallel() | |
| 368 | + | repo := publicRepo(t, "proj") | |
| 369 | + | srv := newTestServer(t, Config{Repos: reposServing(t, repo), Browse: homeBrowse(t)}) | |
| 370 | + | mr := domain.MergeRequest{Repo: repo.Name} | |
| 371 | + | issue := domain.Issue{Repo: repo.Name} | |
| 372 | + | for _, ev := range []domain.Event{ | |
| 373 | + | domain.PushEvent{Repo: repo.Name}, | |
| 374 | + | domain.MergeRequestOpened{MergeRequest: mr}, domain.MergeRequestMerged{MergeRequest: mr}, | |
| 375 | + | domain.MergeRequestClosed{MergeRequest: mr}, domain.MergeRequestReady{MergeRequest: mr}, | |
| 376 | + | domain.CommentAdded{Repo: repo.Name}, domain.IssueOpened{Issue: issue}, | |
| 377 | + | domain.IssueClosed{Issue: issue}, domain.IssueReopened{Issue: issue}, domain.IssueCommented{Repo: repo.Name}, | |
| 378 | + | } { | |
| 379 | + | t.Run(ev.EventKind(), func(t *testing.T) { | |
| 380 | + | got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: ev}) | |
| 381 | + | require.NoError(t, err) | |
| 382 | + | require.Len(t, got, 1) | |
| 383 | + | assert.Equal(t, "home-list", got[0].event) | |
| 384 | + | assert.Contains(t, got[0].html, `id="repo-proj"`) | |
| 385 | + | assert.Contains(t, got[0].html, `data-activity`) | |
| 386 | + | assert.Contains(t, got[0].html, "new activity") | |
| 387 | + | }) | |
| 388 | + | } | |
| 389 | + | for _, ev := range []domain.Event{domain.IssueSubmitted{Repo: repo.Name}, domain.IssuePendingRemoved{Repo: repo.Name}} { | |
| 390 | + | got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: ev}) | |
| 391 | + | require.NoError(t, err) | |
| 392 | + | assert.Empty(t, got) | |
| 393 | + | } | |
| 394 | + | } | |
| @@ -252,7 +252,7 @@ func TestRunUpdatedRefreshesTheHomeRow(t *testing.T) { | |||||
| 252 | assert.Equal(t, "home-list", got[0].event) | 252 | assert.Equal(t, "home-list", got[0].event) | ||
| 253 | assert.Contains(t, got[0].html, `id="repo-proj"`) | 253 | assert.Contains(t, got[0].html, `id="repo-proj"`) | ||
| 254 | assert.Contains(t, got[0].html, "passing") | 254 | assert.Contains(t, got[0].html, "passing") | ||
| 255 | - | assert.NotContains(t, got[0].html, "new push", "a run is not a push") | 255 | + | assert.NotContains(t, got[0].html, "new activity", "a run is not a push") |
| 256 | 256 | ||||
| 257 | // A job that ended refreshes the row too; one in progress does not. | 257 | // A job that ended refreshes the row too; one in progress does not. | ||
| 258 | got, err = (&liveStream{s: srv}).render(t.Context(), ports.WatchEvent{Event: domain.JobUpdated{Job: domain.CIJob{Repo: repo, Phase: domain.CIPhaseRunning}}}) | 258 | got, err = (&liveStream{s: srv}).render(t.Context(), ports.WatchEvent{Event: domain.JobUpdated{Job: domain.CIJob{Repo: repo, Phase: domain.CIPhaseRunning}}}) | ||
| @@ -344,3 +344,51 @@ func TestHomeOffersTheLayouts(t *testing.T) { | |||||
| 344 | require.NotEqual(t, -1, store) | 344 | require.NotEqual(t, -1, store) | ||
| 345 | assert.Less(t, store, app, "the store loads before the app script") | 345 | assert.Less(t, store, app, "the store loads before the app script") | ||
| 346 | } | 346 | } | ||
| 347 | + | ||||
| 348 | + | func TestHomeActivityOrderAndFallback(t *testing.T) { | |||
| 349 | + | t.Parallel() | |||
| 350 | + | now := time.Now().UTC() | |||
| 351 | + | a, b, c := publicRepo(t, "a"), publicRepo(t, "b"), publicRepo(t, "c") | |||
| 352 | + | a.PushedAt = now.Add(-time.Hour) | |||
| 353 | + | a.ActiveAt = now | |||
| 354 | + | b.PushedAt = now.Add(-time.Minute) | |||
| 355 | + | c.CreatedAt = now.Add(-30 * time.Minute) | |||
| 356 | + | repos := []ports.RepoView{b, c, a} | |||
| 357 | + | sortRepos(repos, "activity", true) | |||
| 358 | + | assert.Equal(t, []ports.RepoView{a, b, c}, repos) | |||
| 359 | + | sortRepos(repos, "activity", false) | |||
| 360 | + | assert.Equal(t, []ports.RepoView{c, b, a}, repos) | |||
| 361 | + | assert.Equal(t, rfc3339(now), homeRow(a, now, false, false).ActiveAt) | |||
| 362 | + | c.PushedAt = c.CreatedAt.Add(-time.Hour) | |||
| 363 | + | assert.Equal(t, c.CreatedAt, repoActiveAt(c), "fallback is the later of creation and push") | |||
| 364 | + | } | |||
| 365 | + | ||||
| 366 | + | func TestActivityEventsRefreshTheHomeRow(t *testing.T) { | |||
| 367 | + | t.Parallel() | |||
| 368 | + | repo := publicRepo(t, "proj") | |||
| 369 | + | srv := newTestServer(t, Config{Repos: reposServing(t, repo), Browse: homeBrowse(t)}) | |||
| 370 | + | mr := domain.MergeRequest{Repo: repo.Name} | |||
| 371 | + | issue := domain.Issue{Repo: repo.Name} | |||
| 372 | + | for _, ev := range []domain.Event{ | |||
| 373 | + | domain.PushEvent{Repo: repo.Name}, | |||
| 374 | + | domain.MergeRequestOpened{MergeRequest: mr}, domain.MergeRequestMerged{MergeRequest: mr}, | |||
| 375 | + | domain.MergeRequestClosed{MergeRequest: mr}, domain.MergeRequestReady{MergeRequest: mr}, | |||
| 376 | + | domain.CommentAdded{Repo: repo.Name}, domain.IssueOpened{Issue: issue}, | |||
| 377 | + | domain.IssueClosed{Issue: issue}, domain.IssueReopened{Issue: issue}, domain.IssueCommented{Repo: repo.Name}, | |||
| 378 | + | } { | |||
| 379 | + | t.Run(ev.EventKind(), func(t *testing.T) { | |||
| 380 | + | got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: ev}) | |||
| 381 | + | require.NoError(t, err) | |||
| 382 | + | require.Len(t, got, 1) | |||
| 383 | + | assert.Equal(t, "home-list", got[0].event) | |||
| 384 | + | assert.Contains(t, got[0].html, `id="repo-proj"`) | |||
| 385 | + | assert.Contains(t, got[0].html, `data-activity`) | |||
| 386 | + | assert.Contains(t, got[0].html, "new activity") | |||
| 387 | + | }) | |||
| 388 | + | } | |||
| 389 | + | for _, ev := range []domain.Event{domain.IssueSubmitted{Repo: repo.Name}, domain.IssuePendingRemoved{Repo: repo.Name}} { | |||
| 390 | + | got, err := (&liveStream{s: srv}).home(t.Context(), ports.WatchEvent{Event: ev}) | |||
| 391 | + | require.NoError(t, err) | |||
| 392 | + | assert.Empty(t, got) | |||
| 393 | + | } | |||
| 394 | + | } | |||
M internal/adapters/web/jstest/a11y.test.mjs +25 -0
| @@ -8,6 +8,7 @@ import { test } from 'node:test'; | |||
| 8 | 8 | import { dom, El, el, flushFrames, installDom, settle } from './dom.mjs'; | |
| 9 | 9 | ||
| 10 | 10 | // The few things ermite.js uses that dom.mjs does not have. | |
| 11 | + | El.prototype.prepend = function (...nodes) { this.nodes.unshift(...this.adopt(nodes)); }; | |
| 11 | 12 | El.prototype.replaceWith = function (n) { | |
| 12 | 13 | const p = this.parent; | |
| 13 | 14 | const i = p.nodes.indexOf(this); | |
| @@ -333,3 +334,27 @@ test('the preference is read from storage when the page loads', async () => { | |||
| 333 | 334 | assert.deepEqual(dom.body.events, []); | |
| 334 | 335 | store.set('keys-off', ''); | |
| 335 | 336 | }); | |
| 337 | + | ||
| 338 | + | ||
| 339 | + | test('activity moves a home row up only in newest activity order, preserving focus and cursor', () => { | |
| 340 | + | for (const [sort, desc, activity, moves] of [ | |
| 341 | + | ['activity', 'true', true, true], | |
| 342 | + | ['activity', 'false', true, false], | |
| 343 | + | ['name', 'true', true, false], | |
| 344 | + | ['name', 'false', true, false], | |
| 345 | + | ['activity', 'true', false, false], // CI or metadata, not activity | |
| 346 | + | ]) { | |
| 347 | + | const r = rows(); | |
| 348 | + | r.list.dataset.sort = sort; | |
| 349 | + | r.list.dataset.desc = desc; | |
| 350 | + | const old = r.list.children[1]; | |
| 351 | + | old.setAttribute('data-cursor', ''); | |
| 352 | + | active = old.children[0]; | |
| 353 | + | const fresh = r.mk('repo-b', '/b'); | |
| 354 | + | if (activity) fresh.setAttribute('data-activity', ''); | |
| 355 | + | swapWith(`activity-${sort}-${desc}-${activity}`, fresh); | |
| 356 | + | assert.equal(r.list.children.indexOf(fresh), moves ? 0 : 1); | |
| 357 | + | assert.equal(active, fresh.children[0]); | |
| 358 | + | assert.ok(fresh.hasAttribute('data-cursor')); | |
| 359 | + | } | |
| 360 | + | }); | |
| @@ -8,6 +8,7 @@ import { test } from 'node:test'; | |||||
| 8 | import { dom, El, el, flushFrames, installDom, settle } from './dom.mjs'; | 8 | import { dom, El, el, flushFrames, installDom, settle } from './dom.mjs'; | ||
| 9 | 9 | ||||
| 10 | // The few things ermite.js uses that dom.mjs does not have. | 10 | // The few things ermite.js uses that dom.mjs does not have. | ||
| 11 | + | El.prototype.prepend = function (...nodes) { this.nodes.unshift(...this.adopt(nodes)); }; | |||
| 11 | El.prototype.replaceWith = function (n) { | 12 | El.prototype.replaceWith = function (n) { | ||
| 12 | const p = this.parent; | 13 | const p = this.parent; | ||
| 13 | const i = p.nodes.indexOf(this); | 14 | const i = p.nodes.indexOf(this); | ||
| @@ -333,3 +334,27 @@ test('the preference is read from storage when the page loads', async () => { | |||||
| 333 | assert.deepEqual(dom.body.events, []); | 334 | assert.deepEqual(dom.body.events, []); | ||
| 334 | store.set('keys-off', ''); | 335 | store.set('keys-off', ''); | ||
| 335 | }); | 336 | }); | ||
| 337 | + | ||||
| 338 | + | ||||
| 339 | + | test('activity moves a home row up only in newest activity order, preserving focus and cursor', () => { | |||
| 340 | + | for (const [sort, desc, activity, moves] of [ | |||
| 341 | + | ['activity', 'true', true, true], | |||
| 342 | + | ['activity', 'false', true, false], | |||
| 343 | + | ['name', 'true', true, false], | |||
| 344 | + | ['name', 'false', true, false], | |||
| 345 | + | ['activity', 'true', false, false], // CI or metadata, not activity | |||
| 346 | + | ]) { | |||
| 347 | + | const r = rows(); | |||
| 348 | + | r.list.dataset.sort = sort; | |||
| 349 | + | r.list.dataset.desc = desc; | |||
| 350 | + | const old = r.list.children[1]; | |||
| 351 | + | old.setAttribute('data-cursor', ''); | |||
| 352 | + | active = old.children[0]; | |||
| 353 | + | const fresh = r.mk('repo-b', '/b'); | |||
| 354 | + | if (activity) fresh.setAttribute('data-activity', ''); | |||
| 355 | + | swapWith(`activity-${sort}-${desc}-${activity}`, fresh); | |||
| 356 | + | assert.equal(r.list.children.indexOf(fresh), moves ? 0 : 1); | |||
| 357 | + | assert.equal(active, fresh.children[0]); | |||
| 358 | + | assert.ok(fresh.hasAttribute('data-cursor')); | |||
| 359 | + | } | |||
| 360 | + | }); | |||
M internal/adapters/web/pages.templ +3 -1
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | 3 | package web | |
| 4 | 4 | ||
| 5 | + | import "fmt" | |
| 6 | + | ||
| 5 | 7 | // Home is the repository list. | |
| 6 | 8 | templ Home(l Layout, p HomePage) { | |
| 7 | 9 | @Shell(l, nil) { | |
| @@ -49,7 +51,7 @@ templ Home(l Layout, p HomePage) { | |||
| 49 | 51 | </button> | |
| 50 | 52 | </div> | |
| 51 | 53 | </div> | |
| 52 | - | <ul class="repos" id="repo-rows" data-rows> | |
| 54 | + | <ul class="repos" id="repo-rows" data-rows data-sort={ p.Sort } data-desc={ fmt.Sprint(p.Desc) }> | |
| 53 | 55 | for _, r := range p.Rows { | |
| 54 | 56 | @HomeRowView(r) | |
| 55 | 57 | } | |
| @@ -2,6 +2,8 @@ | |||||
| 2 | 2 | ||||
| 3 | package web | 3 | package web | ||
| 4 | 4 | ||||
| 5 | + | import "fmt" | |||
| 6 | + | ||||
| 5 | // Home is the repository list. | 7 | // Home is the repository list. | ||
| 6 | templ Home(l Layout, p HomePage) { | 8 | templ Home(l Layout, p HomePage) { | ||
| 7 | @Shell(l, nil) { | 9 | @Shell(l, nil) { | ||
| @@ -49,7 +51,7 @@ templ Home(l Layout, p HomePage) { | |||||
| 49 | </button> | 51 | </button> | ||
| 50 | </div> | 52 | </div> | ||
| 51 | </div> | 53 | </div> | ||
| 52 | - | <ul class="repos" id="repo-rows" data-rows> | 54 | + | <ul class="repos" id="repo-rows" data-rows data-sort={ p.Sort } data-desc={ fmt.Sprint(p.Desc) }> |
| 53 | for _, r := range p.Rows { | 55 | for _, r := range p.Rows { | ||
| 54 | @HomeRowView(r) | 56 | @HomeRowView(r) | ||
| 55 | } | 57 | } | ||
M internal/adapters/web/pages_templ.go +370 -342 generated file: collapsed
M internal/adapters/web/static/js/ermite.js +5 -1
| @@ -820,7 +820,8 @@ | |||
| 820 | 820 | // internal/adapters/web/events.go). A fragment is a top-level element with an | |
| 821 | 821 | // id: it replaces the element of the page that has the same id. A fragment | |
| 822 | 822 | // marked data-gone removes it; a row of a repository the home page does not | |
| 823 | - | // list yet is added at the top of the list. A slot (data-slot: the place of a | |
| 823 | + | // list yet is added at the top of the list. Activity updates also move existing | |
| 824 | + | // home rows to the top when sorted by newest activity; CI updates stay put. A slot (data-slot: the place of a | |
| 824 | 825 | // banner, a persistent status region) keeps its element and only gets the | |
| 825 | 826 | // children of the fragment, so that screen readers announce the change. A gap, | |
| 826 | 827 | // which says the page may have missed events or that what it shows changed, | |
| @@ -919,6 +920,9 @@ window.ermiteLive = (() => { | |||
| 919 | 920 | } | |
| 920 | 921 | if (old.hasAttribute('data-cursor')) el.setAttribute('data-cursor', ''); | |
| 921 | 922 | old.replaceWith(el); | |
| 923 | + | const rows = document.getElementById('repo-rows'); | |
| 924 | + | if (rows && el.parentElement === rows && rows.dataset.sort === 'activity' && | |
| 925 | + | rows.dataset.desc === 'true' && el.hasAttribute('data-activity')) rows.prepend(el); | |
| 922 | 926 | window.htmx?.process(el); | |
| 923 | 927 | fitIn(el); | |
| 924 | 928 | if (had) refocus(el, had); | |
| @@ -820,7 +820,8 @@ | |||||
| 820 | // internal/adapters/web/events.go). A fragment is a top-level element with an | 820 | // internal/adapters/web/events.go). A fragment is a top-level element with an | ||
| 821 | // id: it replaces the element of the page that has the same id. A fragment | 821 | // id: it replaces the element of the page that has the same id. A fragment | ||
| 822 | // marked data-gone removes it; a row of a repository the home page does not | 822 | // marked data-gone removes it; a row of a repository the home page does not | ||
| 823 | - | // list yet is added at the top of the list. A slot (data-slot: the place of a | 823 | + | // list yet is added at the top of the list. Activity updates also move existing |
| 824 | + | // home rows to the top when sorted by newest activity; CI updates stay put. A slot (data-slot: the place of a | |||
| 824 | // banner, a persistent status region) keeps its element and only gets the | 825 | // banner, a persistent status region) keeps its element and only gets the | ||
| 825 | // children of the fragment, so that screen readers announce the change. A gap, | 826 | // children of the fragment, so that screen readers announce the change. A gap, | ||
| 826 | // which says the page may have missed events or that what it shows changed, | 827 | // which says the page may have missed events or that what it shows changed, | ||
| @@ -919,6 +920,9 @@ window.ermiteLive = (() => { | |||||
| 919 | } | 920 | } | ||
| 920 | if (old.hasAttribute('data-cursor')) el.setAttribute('data-cursor', ''); | 921 | if (old.hasAttribute('data-cursor')) el.setAttribute('data-cursor', ''); | ||
| 921 | old.replaceWith(el); | 922 | old.replaceWith(el); | ||
| 923 | + | const rows = document.getElementById('repo-rows'); | |||
| 924 | + | if (rows && el.parentElement === rows && rows.dataset.sort === 'activity' && | |||
| 925 | + | rows.dataset.desc === 'true' && el.hasAttribute('data-activity')) rows.prepend(el); | |||
| 922 | window.htmx?.process(el); | 926 | window.htmx?.process(el); | ||
| 923 | fitIn(el); | 927 | fitIn(el); | ||
| 924 | if (had) refocus(el, had); | 928 | if (had) refocus(el, had); | ||
M internal/adapters/web/view.go +3 -1
| @@ -96,7 +96,7 @@ type HomeRow struct { | |||
| 96 | 96 | Stats *HomeStats | |
| 97 | 97 | // Private marks a private repository; only set for a signed-in visitor. | |
| 98 | 98 | Private bool | |
| 99 | - | // Fresh marks a row that a push just updated (live updates only). | |
| 99 | + | // Fresh marks a row that activity just updated (live updates only). | |
| 100 | 100 | Fresh bool | |
| 101 | 101 | // Commits are the newest of the default branch. NoCommits says there is | |
| 102 | 102 | // none (never pushed, or an empty branch); a failed read says nothing. | |
| @@ -138,6 +138,8 @@ type SortLink struct { | |||
| 138 | 138 | ||
| 139 | 139 | // HomePage is the repository list. | |
| 140 | 140 | type HomePage struct { | |
| 141 | + | Sort string | |
| 142 | + | Desc bool | |
| 141 | 143 | Sorts []SortLink | |
| 142 | 144 | Rows []HomeRow | |
| 143 | 145 | } | |
| @@ -96,7 +96,7 @@ type HomeRow struct { | |||||
| 96 | Stats *HomeStats | 96 | Stats *HomeStats | ||
| 97 | // Private marks a private repository; only set for a signed-in visitor. | 97 | // Private marks a private repository; only set for a signed-in visitor. | ||
| 98 | Private bool | 98 | Private bool | ||
| 99 | - | // Fresh marks a row that a push just updated (live updates only). | 99 | + | // Fresh marks a row that activity just updated (live updates only). |
| 100 | Fresh bool | 100 | Fresh bool | ||
| 101 | // Commits are the newest of the default branch. NoCommits says there is | 101 | // Commits are the newest of the default branch. NoCommits says there is | ||
| 102 | // none (never pushed, or an empty branch); a failed read says nothing. | 102 | // none (never pushed, or an empty branch); a failed read says nothing. | ||
| @@ -138,6 +138,8 @@ type SortLink struct { | |||||
| 138 | 138 | ||||
| 139 | // HomePage is the repository list. | 139 | // HomePage is the repository list. | ||
| 140 | type HomePage struct { | 140 | type HomePage struct { | ||
| 141 | + | Sort string | |||
| 142 | + | Desc bool | |||
| 141 | Sorts []SortLink | 143 | Sorts []SortLink | ||
| 142 | Rows []HomeRow | 144 | Rows []HomeRow | ||
| 143 | } | 145 | } | ||
M internal/app/testdata/web/home.html +32 -30
| @@ -61,7 +61,7 @@ | |||
| 61 | 61 | </div> | |
| 62 | 62 | <nav class="sort" aria-label="Sort repositories"> | |
| 63 | 63 | <span class="mute">sort</span> | |
| 64 | - | <a href="/?sort=push&dir=asc" aria-current="true">last push <span aria-hidden="true">▼</span> | |
| 64 | + | <a href="/?sort=activity&dir=asc" aria-current="true">last activity <span aria-hidden="true">▼</span> | |
| 65 | 65 | <span class="sr">, descending, select for ascending</span> | |
| 66 | 66 | </a> | |
| 67 | 67 | <a href="/?sort=name&dir=asc">name </a> | |
| @@ -81,8 +81,31 @@ | |||
| 81 | 81 | </button> | |
| 82 | 82 | </div> | |
| 83 | 83 | </div> | |
| 84 | - | <ul class="repos" id="repo-rows" data-rows> | |
| 85 | - | <li id="repo-demo" class="repo" data-cursor> | |
| 84 | + | <ul class="repos" id="repo-rows" data-rows data-sort="activity" data-desc="true"> | |
| 85 | + | <li id="repo-quiet" class="repo" data-cursor> | |
| 86 | + | <div class="repo-main"> | |
| 87 | + | <h2 class="repo-name"> | |
| 88 | + | <a href="/quiet">quiet</a> | |
| 89 | + | </h2> | |
| 90 | + | <p class="repo-desc mute">no description</p> | |
| 91 | + | <div class="repo-topics" aria-hidden="true"> | |
| 92 | + | </div> | |
| 93 | + | <div class="repo-pulse" aria-hidden="true"> | |
| 94 | + | </div> | |
| 95 | + | </div> | |
| 96 | + | <div class="repo-head"> | |
| 97 | + | <dl class="repo-stats" aria-label="Figures of quiet"> | |
| 98 | + | <div class="rs-active"> | |
| 99 | + | <dt>last activity</dt> | |
| 100 | + | <dd> | |
| 101 | + | <time datetime="STAMP" title="STAMP">AGO</time> | |
| 102 | + | </dd> | |
| 103 | + | </div> | |
| 104 | + | </dl> | |
| 105 | + | </div> | |
| 106 | + | <p class="repo-commits mute">no commits yet</p> | |
| 107 | + | </li> | |
| 108 | + | <li id="repo-demo" class="repo"> | |
| 86 | 109 | <div class="repo-main"> | |
| 87 | 110 | <h2 class="repo-name"> | |
| 88 | 111 | <a href="/demo">demo</a> | |
| @@ -148,27 +171,6 @@ | |||
| 148 | 171 | </li> | |
| 149 | 172 | </ul> | |
| 150 | 173 | </li> | |
| 151 | - | <li id="repo-quiet" class="repo"> | |
| 152 | - | <div class="repo-main"> | |
| 153 | - | <h2 class="repo-name"> | |
| 154 | - | <a href="/quiet">quiet</a> | |
| 155 | - | </h2> | |
| 156 | - | <p class="repo-desc mute">no description</p> | |
| 157 | - | <div class="repo-topics" aria-hidden="true"> | |
| 158 | - | </div> | |
| 159 | - | <div class="repo-pulse" aria-hidden="true"> | |
| 160 | - | </div> | |
| 161 | - | </div> | |
| 162 | - | <div class="repo-head"> | |
| 163 | - | <dl class="repo-stats" aria-label="Figures of quiet"> | |
| 164 | - | <div class="rs-active"> | |
| 165 | - | <dt>last activity</dt> | |
| 166 | - | <dd class="mute">never</dd> | |
| 167 | - | </div> | |
| 168 | - | </dl> | |
| 169 | - | </div> | |
| 170 | - | <p class="repo-commits mute">no commits yet</p> | |
| 171 | - | </li> | |
| 172 | 174 | </ul> | |
| 173 | 175 | </section> | |
| 174 | 176 | </div> | |
| @@ -343,15 +345,15 @@ | |||
| 343 | 345 | <span class="k">go</span> | |
| 344 | 346 | </a> | |
| 345 | 347 | </li> | |
| 346 | - | <li id="cmd-o1" role="option" aria-selected="false" data-k="repo demo"> | |
| 347 | - | <a href="/demo" tabindex="-1"> | |
| 348 | - | <span class="lbl">demo</span> | |
| 348 | + | <li id="cmd-o1" role="option" aria-selected="false" data-k="repo quiet"> | |
| 349 | + | <a href="/quiet" tabindex="-1"> | |
| 350 | + | <span class="lbl">quiet</span> | |
| 349 | 351 | <span class="k">repo</span> | |
| 350 | 352 | </a> | |
| 351 | 353 | </li> | |
| 352 | - | <li id="cmd-o2" role="option" aria-selected="false" data-k="repo quiet"> | |
| 353 | - | <a href="/quiet" tabindex="-1"> | |
| 354 | - | <span class="lbl">quiet</span> | |
| 354 | + | <li id="cmd-o2" role="option" aria-selected="false" data-k="repo demo"> | |
| 355 | + | <a href="/demo" tabindex="-1"> | |
| 356 | + | <span class="lbl">demo</span> | |
| 355 | 357 | <span class="k">repo</span> | |
| 356 | 358 | </a> | |
| 357 | 359 | </li> | |
| @@ -61,7 +61,7 @@ | |||||
| 61 | </div> | 61 | </div> | ||
| 62 | <nav class="sort" aria-label="Sort repositories"> | 62 | <nav class="sort" aria-label="Sort repositories"> | ||
| 63 | <span class="mute">sort</span> | 63 | <span class="mute">sort</span> | ||
| 64 | - | <a href="/?sort=push&dir=asc" aria-current="true">last push <span aria-hidden="true">▼</span> | 64 | + | <a href="/?sort=activity&dir=asc" aria-current="true">last activity <span aria-hidden="true">▼</span> |
| 65 | <span class="sr">, descending, select for ascending</span> | 65 | <span class="sr">, descending, select for ascending</span> | ||
| 66 | </a> | 66 | </a> | ||
| 67 | <a href="/?sort=name&dir=asc">name </a> | 67 | <a href="/?sort=name&dir=asc">name </a> | ||
| @@ -81,8 +81,31 @@ | |||||
| 81 | </button> | 81 | </button> | ||
| 82 | </div> | 82 | </div> | ||
| 83 | </div> | 83 | </div> | ||
| 84 | - | <ul class="repos" id="repo-rows" data-rows> | 84 | + | <ul class="repos" id="repo-rows" data-rows data-sort="activity" data-desc="true"> |
| 85 | - | <li id="repo-demo" class="repo" data-cursor> | 85 | + | <li id="repo-quiet" class="repo" data-cursor> |
| 86 | + | <div class="repo-main"> | |||
| 87 | + | <h2 class="repo-name"> | |||
| 88 | + | <a href="/quiet">quiet</a> | |||
| 89 | + | </h2> | |||
| 90 | + | <p class="repo-desc mute">no description</p> | |||
| 91 | + | <div class="repo-topics" aria-hidden="true"> | |||
| 92 | + | </div> | |||
| 93 | + | <div class="repo-pulse" aria-hidden="true"> | |||
| 94 | + | </div> | |||
| 95 | + | </div> | |||
| 96 | + | <div class="repo-head"> | |||
| 97 | + | <dl class="repo-stats" aria-label="Figures of quiet"> | |||
| 98 | + | <div class="rs-active"> | |||
| 99 | + | <dt>last activity</dt> | |||
| 100 | + | <dd> | |||
| 101 | + | <time datetime="STAMP" title="STAMP">AGO</time> | |||
| 102 | + | </dd> | |||
| 103 | + | </div> | |||
| 104 | + | </dl> | |||
| 105 | + | </div> | |||
| 106 | + | <p class="repo-commits mute">no commits yet</p> | |||
| 107 | + | </li> | |||
| 108 | + | <li id="repo-demo" class="repo"> | |||
| 86 | <div class="repo-main"> | 109 | <div class="repo-main"> | ||
| 87 | <h2 class="repo-name"> | 110 | <h2 class="repo-name"> | ||
| 88 | <a href="/demo">demo</a> | 111 | <a href="/demo">demo</a> | ||
| @@ -148,27 +171,6 @@ | |||||
| 148 | </li> | 171 | </li> | ||
| 149 | </ul> | 172 | </ul> | ||
| 150 | </li> | 173 | </li> | ||
| 151 | - | <li id="repo-quiet" class="repo"> | |||
| 152 | - | <div class="repo-main"> | |||
| 153 | - | <h2 class="repo-name"> | |||
| 154 | - | <a href="/quiet">quiet</a> | |||
| 155 | - | </h2> | |||
| 156 | - | <p class="repo-desc mute">no description</p> | |||
| 157 | - | <div class="repo-topics" aria-hidden="true"> | |||
| 158 | - | </div> | |||
| 159 | - | <div class="repo-pulse" aria-hidden="true"> | |||
| 160 | - | </div> | |||
| 161 | - | </div> | |||
| 162 | - | <div class="repo-head"> | |||
| 163 | - | <dl class="repo-stats" aria-label="Figures of quiet"> | |||
| 164 | - | <div class="rs-active"> | |||
| 165 | - | <dt>last activity</dt> | |||
| 166 | - | <dd class="mute">never</dd> | |||
| 167 | - | </div> | |||
| 168 | - | </dl> | |||
| 169 | - | </div> | |||
| 170 | - | <p class="repo-commits mute">no commits yet</p> | |||
| 171 | - | </li> | |||
| 172 | </ul> | 174 | </ul> | ||
| 173 | </section> | 175 | </section> | ||
| 174 | </div> | 176 | </div> | ||
| @@ -343,15 +345,15 @@ | |||||
| 343 | <span class="k">go</span> | 345 | <span class="k">go</span> | ||
| 344 | </a> | 346 | </a> | ||
| 345 | </li> | 347 | </li> | ||
| 346 | - | <li id="cmd-o1" role="option" aria-selected="false" data-k="repo demo"> | 348 | + | <li id="cmd-o1" role="option" aria-selected="false" data-k="repo quiet"> |
| 347 | - | <a href="/demo" tabindex="-1"> | 349 | + | <a href="/quiet" tabindex="-1"> |
| 348 | - | <span class="lbl">demo</span> | 350 | + | <span class="lbl">quiet</span> |
| 349 | <span class="k">repo</span> | 351 | <span class="k">repo</span> | ||
| 350 | </a> | 352 | </a> | ||
| 351 | </li> | 353 | </li> | ||
| 352 | - | <li id="cmd-o2" role="option" aria-selected="false" data-k="repo quiet"> | 354 | + | <li id="cmd-o2" role="option" aria-selected="false" data-k="repo demo"> |
| 353 | - | <a href="/quiet" tabindex="-1"> | 355 | + | <a href="/demo" tabindex="-1"> |
| 354 | - | <span class="lbl">quiet</span> | 356 | + | <span class="lbl">demo</span> |
| 355 | <span class="k">repo</span> | 357 | <span class="k">repo</span> | ||
| 356 | </a> | 358 | </a> | ||
| 357 | </li> | 359 | </li> | ||
M internal/app/web_events_test.go +2 -2
| @@ -123,7 +123,7 @@ func TestWebEventsHome(t *testing.T) { | |||
| 123 | 123 | assert.Equal(t, "home-list", ev.name) | |
| 124 | 124 | assert.NotEmpty(t, ev.id) | |
| 125 | 125 | assert.Contains(t, ev.data, `<li id="repo-pub"`) | |
| 126 | - | assert.Contains(t, ev.data, `new push`) | |
| 126 | + | assert.Contains(t, ev.data, `new activity`) | |
| 127 | 127 | assert.Contains(t, ev.data, `href="/pub"`) | |
| 128 | 128 | assert.Contains(t, ev.data, `<ul class="repo-commits" aria-label="Recent commits of pub">`, "the live row lists the commits too") | |
| 129 | 129 | ||
| @@ -134,7 +134,7 @@ func TestWebEventsHome(t *testing.T) { | |||
| 134 | 134 | assert.Equal(t, "home-list", ev.name) | |
| 135 | 135 | assert.Contains(t, ev.data, `<li id="repo-fresh"`) | |
| 136 | 136 | assert.Contains(t, ev.data, "a <b>fresh</b> one", "text is escaped") | |
| 137 | - | assert.NotContains(t, ev.data, "new push") | |
| 137 | + | assert.NotContains(t, ev.data, "new activity") | |
| 138 | 138 | ||
| 139 | 139 | // A repository that turns private is removed from the anonymous list. | |
| 140 | 140 | priv := domain.VisibilityPrivate | |
| @@ -123,7 +123,7 @@ func TestWebEventsHome(t *testing.T) { | |||||
| 123 | assert.Equal(t, "home-list", ev.name) | 123 | assert.Equal(t, "home-list", ev.name) | ||
| 124 | assert.NotEmpty(t, ev.id) | 124 | assert.NotEmpty(t, ev.id) | ||
| 125 | assert.Contains(t, ev.data, `<li id="repo-pub"`) | 125 | assert.Contains(t, ev.data, `<li id="repo-pub"`) | ||
| 126 | - | assert.Contains(t, ev.data, `new push`) | 126 | + | assert.Contains(t, ev.data, `new activity`) |
| 127 | assert.Contains(t, ev.data, `href="/pub"`) | 127 | assert.Contains(t, ev.data, `href="/pub"`) | ||
| 128 | assert.Contains(t, ev.data, `<ul class="repo-commits" aria-label="Recent commits of pub">`, "the live row lists the commits too") | 128 | assert.Contains(t, ev.data, `<ul class="repo-commits" aria-label="Recent commits of pub">`, "the live row lists the commits too") | ||
| 129 | 129 | ||||
| @@ -134,7 +134,7 @@ func TestWebEventsHome(t *testing.T) { | |||||
| 134 | assert.Equal(t, "home-list", ev.name) | 134 | assert.Equal(t, "home-list", ev.name) | ||
| 135 | assert.Contains(t, ev.data, `<li id="repo-fresh"`) | 135 | assert.Contains(t, ev.data, `<li id="repo-fresh"`) | ||
| 136 | assert.Contains(t, ev.data, "a <b>fresh</b> one", "text is escaped") | 136 | assert.Contains(t, ev.data, "a <b>fresh</b> one", "text is escaped") | ||
| 137 | - | assert.NotContains(t, ev.data, "new push") | 137 | + | assert.NotContains(t, ev.data, "new activity") |
| 138 | 138 | ||||
| 139 | // A repository that turns private is removed from the anonymous list. | 139 | // A repository that turns private is removed from the anonymous list. | ||
| 140 | priv := domain.VisibilityPrivate | 140 | priv := domain.VisibilityPrivate | ||
M internal/domain/repo.go +1 -0
| @@ -42,6 +42,7 @@ type Repo struct { | |||
| 42 | 42 | Visibility Visibility | |
| 43 | 43 | CreatedAt time.Time | |
| 44 | 44 | PushedAt time.Time // zero until the first push | |
| 45 | + | ActiveAt time.Time // latest push, merge request or issue activity | |
| 45 | 46 | // Settings are the merge settings; the stores always fill them in, with | |
| 46 | 47 | // the defaults for a repository that never stored any. | |
| 47 | 48 | Settings RepoSettings | |
| @@ -42,6 +42,7 @@ type Repo struct { | |||||
| 42 | Visibility Visibility | 42 | Visibility Visibility | ||
| 43 | CreatedAt time.Time | 43 | CreatedAt time.Time | ||
| 44 | PushedAt time.Time // zero until the first push | 44 | PushedAt time.Time // zero until the first push | ||
| 45 | + | ActiveAt time.Time // latest push, merge request or issue activity | |||
| 45 | // Settings are the merge settings; the stores always fill them in, with | 46 | // Settings are the merge settings; the stores always fill them in, with | ||
| 46 | // the defaults for a repository that never stored any. | 47 | // the defaults for a repository that never stored any. | ||
| 47 | Settings RepoSettings | 48 | Settings RepoSettings | ||
M internal/ports/dto.go +1 -1
| @@ -21,7 +21,7 @@ type RepoPage struct { | |||
| 21 | 21 | ||
| 22 | 22 | // RepoView is a repository with the Git state that belongs in its summary. | |
| 23 | 23 | type RepoView struct { | |
| 24 | - | domain.Repo | |
| 24 | + | domain.Repo // includes ActiveAt, the latest repository activity | |
| 25 | 25 | // DefaultBranch is the branch HEAD points to, even when it does not exist | |
| 26 | 26 | // yet; empty when HEAD is detached or the directory is missing. | |
| 27 | 27 | DefaultBranch string | |
| @@ -21,7 +21,7 @@ type RepoPage struct { | |||||
| 21 | 21 | ||||
| 22 | // RepoView is a repository with the Git state that belongs in its summary. | 22 | // RepoView is a repository with the Git state that belongs in its summary. | ||
| 23 | type RepoView struct { | 23 | type RepoView struct { | ||
| 24 | - | domain.Repo | 24 | + | domain.Repo // includes ActiveAt, the latest repository activity |
| 25 | // DefaultBranch is the branch HEAD points to, even when it does not exist | 25 | // DefaultBranch is the branch HEAD points to, even when it does not exist | ||
| 26 | // yet; empty when HEAD is detached or the directory is missing. | 26 | // yet; empty when HEAD is detached or the directory is missing. | ||
| 27 | DefaultBranch string | 27 | DefaultBranch string | ||
A internal/usecase/activity.go +53 -0
| @@ -0,0 +1,53 @@ | |||
| 1 | + | // SPDX-License-Identifier: AGPL-3.0-or-later | |
| 2 | + | ||
| 3 | + | package usecase | |
| 4 | + | ||
| 5 | + | import ( | |
| 6 | + | "context" | |
| 7 | + | "errors" | |
| 8 | + | "fmt" | |
| 9 | + | "time" | |
| 10 | + | ||
| 11 | + | "github.com/bnema/zerowrap" | |
| 12 | + | ||
| 13 | + | "bnema.dev/ermite/internal/domain" | |
| 14 | + | "bnema.dev/ermite/internal/ports" | |
| 15 | + | ) | |
| 16 | + | ||
| 17 | + | // recordActivity is best-effort: a metadata failure never fails the action. | |
| 18 | + | func recordActivity(ctx context.Context, meta ports.RepoMetaStore, name domain.RepoName, at time.Time) { | |
| 19 | + | if _, err := touchActiveAt(ctx, meta, name, at); err != nil { | |
| 20 | + | log := zerowrap.FromCtx(ctx) | |
| 21 | + | log.Error().Err(err).Str("repo", name.String()).Msg("record repository activity") | |
| 22 | + | } | |
| 23 | + | } | |
| 24 | + | ||
| 25 | + | // touchActiveAt preserves later activity and retries concurrent metadata writes. | |
| 26 | + | // A repository deleted meanwhile is not an error. | |
| 27 | + | func touchActiveAt(ctx context.Context, meta ports.RepoMetaStore, name domain.RepoName, now time.Time) (domain.Repo, error) { | |
| 28 | + | for range pushRetries { | |
| 29 | + | repo, err := meta.Get(ctx, name) | |
| 30 | + | if errors.Is(err, domain.ErrNotFound) { | |
| 31 | + | return domain.Repo{}, nil | |
| 32 | + | } | |
| 33 | + | if err != nil { | |
| 34 | + | return domain.Repo{}, fmt.Errorf("get repository %q: %w", name, err) | |
| 35 | + | } | |
| 36 | + | if !now.After(repo.ActiveAt) { | |
| 37 | + | return repo, nil // a later activity already recorded | |
| 38 | + | } | |
| 39 | + | repo.ActiveAt = now | |
| 40 | + | err = meta.Update(ctx, repo) | |
| 41 | + | if errors.Is(err, domain.ErrConflict) { | |
| 42 | + | continue | |
| 43 | + | } | |
| 44 | + | if errors.Is(err, domain.ErrNotFound) { | |
| 45 | + | return domain.Repo{}, nil | |
| 46 | + | } | |
| 47 | + | if err != nil { | |
| 48 | + | return repo, fmt.Errorf("update repository %q: %w", name, err) | |
| 49 | + | } | |
| 50 | + | return repo, nil | |
| 51 | + | } | |
| 52 | + | return domain.Repo{}, fmt.Errorf("update active_at of %q: %w", name, domain.ErrConflict) | |
| 53 | + | } | |
| @@ -0,0 +1,53 @@ | |||||
| 1 | + | // SPDX-License-Identifier: AGPL-3.0-or-later | |||
| 2 | + | ||||
| 3 | + | package usecase | |||
| 4 | + | ||||
| 5 | + | import ( | |||
| 6 | + | "context" | |||
| 7 | + | "errors" | |||
| 8 | + | "fmt" | |||
| 9 | + | "time" | |||
| 10 | + | ||||
| 11 | + | "github.com/bnema/zerowrap" | |||
| 12 | + | ||||
| 13 | + | "bnema.dev/ermite/internal/domain" | |||
| 14 | + | "bnema.dev/ermite/internal/ports" | |||
| 15 | + | ) | |||
| 16 | + | ||||
| 17 | + | // recordActivity is best-effort: a metadata failure never fails the action. | |||
| 18 | + | func recordActivity(ctx context.Context, meta ports.RepoMetaStore, name domain.RepoName, at time.Time) { | |||
| 19 | + | if _, err := touchActiveAt(ctx, meta, name, at); err != nil { | |||
| 20 | + | log := zerowrap.FromCtx(ctx) | |||
| 21 | + | log.Error().Err(err).Str("repo", name.String()).Msg("record repository activity") | |||
| 22 | + | } | |||
| 23 | + | } | |||
| 24 | + | ||||
| 25 | + | // touchActiveAt preserves later activity and retries concurrent metadata writes. | |||
| 26 | + | // A repository deleted meanwhile is not an error. | |||
| 27 | + | func touchActiveAt(ctx context.Context, meta ports.RepoMetaStore, name domain.RepoName, now time.Time) (domain.Repo, error) { | |||
| 28 | + | for range pushRetries { | |||
| 29 | + | repo, err := meta.Get(ctx, name) | |||
| 30 | + | if errors.Is(err, domain.ErrNotFound) { | |||
| 31 | + | return domain.Repo{}, nil | |||
| 32 | + | } | |||
| 33 | + | if err != nil { | |||
| 34 | + | return domain.Repo{}, fmt.Errorf("get repository %q: %w", name, err) | |||
| 35 | + | } | |||
| 36 | + | if !now.After(repo.ActiveAt) { | |||
| 37 | + | return repo, nil // a later activity already recorded | |||
| 38 | + | } | |||
| 39 | + | repo.ActiveAt = now | |||
| 40 | + | err = meta.Update(ctx, repo) | |||
| 41 | + | if errors.Is(err, domain.ErrConflict) { | |||
| 42 | + | continue | |||
| 43 | + | } | |||
| 44 | + | if errors.Is(err, domain.ErrNotFound) { | |||
| 45 | + | return domain.Repo{}, nil | |||
| 46 | + | } | |||
| 47 | + | if err != nil { | |||
| 48 | + | return repo, fmt.Errorf("update repository %q: %w", name, err) | |||
| 49 | + | } | |||
| 50 | + | return repo, nil | |||
| 51 | + | } | |||
| 52 | + | return domain.Repo{}, fmt.Errorf("update active_at of %q: %w", name, domain.ErrConflict) | |||
| 53 | + | } | |||
A internal/usecase/activity_test.go +42 -0
| @@ -0,0 +1,42 @@ | |||
| 1 | + | // SPDX-License-Identifier: AGPL-3.0-or-later | |
| 2 | + | ||
| 3 | + | package usecase | |
| 4 | + | ||
| 5 | + | import ( | |
| 6 | + | "errors" | |
| 7 | + | "testing" | |
| 8 | + | "time" | |
| 9 | + | ||
| 10 | + | "github.com/stretchr/testify/mock" | |
| 11 | + | "github.com/stretchr/testify/require" | |
| 12 | + | ||
| 13 | + | "bnema.dev/ermite/internal/domain" | |
| 14 | + | "bnema.dev/ermite/internal/ports/mocks" | |
| 15 | + | ) | |
| 16 | + | ||
| 17 | + | func TestTouchActiveAt(t *testing.T) { | |
| 18 | + | name, err := domain.ParseRepoName("proj") | |
| 19 | + | require.NoError(t, err) | |
| 20 | + | now := time.Now().UTC() | |
| 21 | + | t.Run("retries and preserves later activity", func(t *testing.T) { | |
| 22 | + | meta := mocks.NewRepoMetaStore(t) | |
| 23 | + | meta.EXPECT().Get(mock.Anything, name).Return(domain.Repo{Name: name}, nil).Once() | |
| 24 | + | meta.EXPECT().Update(mock.Anything, mock.MatchedBy(func(r domain.Repo) bool { return r.ActiveAt.Equal(now) && r.PushedAt.IsZero() })).Return(domain.ErrConflict).Once() | |
| 25 | + | later := domain.Repo{Name: name, ActiveAt: now.Add(time.Hour)} | |
| 26 | + | meta.EXPECT().Get(mock.Anything, name).Return(later, nil).Once() | |
| 27 | + | got, err := touchActiveAt(t.Context(), meta, name, now) | |
| 28 | + | require.NoError(t, err) | |
| 29 | + | require.Equal(t, later, got) | |
| 30 | + | }) | |
| 31 | + | t.Run("deleted repository", func(t *testing.T) { | |
| 32 | + | meta := mocks.NewRepoMetaStore(t) | |
| 33 | + | meta.EXPECT().Get(mock.Anything, name).Return(domain.Repo{}, domain.ErrNotFound) | |
| 34 | + | _, err := touchActiveAt(t.Context(), meta, name, now) | |
| 35 | + | require.NoError(t, err) | |
| 36 | + | }) | |
| 37 | + | t.Run("best effort failure", func(t *testing.T) { | |
| 38 | + | meta := mocks.NewRepoMetaStore(t) | |
| 39 | + | meta.EXPECT().Get(mock.Anything, name).Return(domain.Repo{}, errors.New("offline")) | |
| 40 | + | require.NotPanics(t, func() { recordActivity(t.Context(), meta, name, now) }) | |
| 41 | + | }) | |
| 42 | + | } | |
| @@ -0,0 +1,42 @@ | |||||
| 1 | + | // SPDX-License-Identifier: AGPL-3.0-or-later | |||
| 2 | + | ||||
| 3 | + | package usecase | |||
| 4 | + | ||||
| 5 | + | import ( | |||
| 6 | + | "errors" | |||
| 7 | + | "testing" | |||
| 8 | + | "time" | |||
| 9 | + | ||||
| 10 | + | "github.com/stretchr/testify/mock" | |||
| 11 | + | "github.com/stretchr/testify/require" | |||
| 12 | + | ||||
| 13 | + | "bnema.dev/ermite/internal/domain" | |||
| 14 | + | "bnema.dev/ermite/internal/ports/mocks" | |||
| 15 | + | ) | |||
| 16 | + | ||||
| 17 | + | func TestTouchActiveAt(t *testing.T) { | |||
| 18 | + | name, err := domain.ParseRepoName("proj") | |||
| 19 | + | require.NoError(t, err) | |||
| 20 | + | now := time.Now().UTC() | |||
| 21 | + | t.Run("retries and preserves later activity", func(t *testing.T) { | |||
| 22 | + | meta := mocks.NewRepoMetaStore(t) | |||
| 23 | + | meta.EXPECT().Get(mock.Anything, name).Return(domain.Repo{Name: name}, nil).Once() | |||
| 24 | + | meta.EXPECT().Update(mock.Anything, mock.MatchedBy(func(r domain.Repo) bool { return r.ActiveAt.Equal(now) && r.PushedAt.IsZero() })).Return(domain.ErrConflict).Once() | |||
| 25 | + | later := domain.Repo{Name: name, ActiveAt: now.Add(time.Hour)} | |||
| 26 | + | meta.EXPECT().Get(mock.Anything, name).Return(later, nil).Once() | |||
| 27 | + | got, err := touchActiveAt(t.Context(), meta, name, now) | |||
| 28 | + | require.NoError(t, err) | |||
| 29 | + | require.Equal(t, later, got) | |||
| 30 | + | }) | |||
| 31 | + | t.Run("deleted repository", func(t *testing.T) { | |||
| 32 | + | meta := mocks.NewRepoMetaStore(t) | |||
| 33 | + | meta.EXPECT().Get(mock.Anything, name).Return(domain.Repo{}, domain.ErrNotFound) | |||
| 34 | + | _, err := touchActiveAt(t.Context(), meta, name, now) | |||
| 35 | + | require.NoError(t, err) | |||
| 36 | + | }) | |||
| 37 | + | t.Run("best effort failure", func(t *testing.T) { | |||
| 38 | + | meta := mocks.NewRepoMetaStore(t) | |||
| 39 | + | meta.EXPECT().Get(mock.Anything, name).Return(domain.Repo{}, errors.New("offline")) | |||
| 40 | + | require.NotPanics(t, func() { recordActivity(t.Context(), meta, name, now) }) | |||
| 41 | + | }) | |||
| 42 | + | } | |||
M internal/usecase/issues.go +3 -0
| @@ -124,6 +124,7 @@ func (i *Issues) Create(ctx context.Context, p domain.Principal, name domain.Rep | |||
| 124 | 124 | log := zerowrap.FromCtx(ctx) | |
| 125 | 125 | log.Info().Str("repo", name.String()).Int64("number", issue.Number). | |
| 126 | 126 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue opened") | |
| 127 | + | recordActivity(ctx, i.meta, repo.Name, now) | |
| 127 | 128 | i.bus.Publish(ctx, domain.IssueOpened{Issue: issue, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | |
| 128 | 129 | return issue, nil | |
| 129 | 130 | } | |
| @@ -211,6 +212,7 @@ func (i *Issues) AddComment(ctx context.Context, p domain.Principal, name domain | |||
| 211 | 212 | log := zerowrap.FromCtx(ctx) | |
| 212 | 213 | log.Info().Str("repo", name.String()).Int64("number", number).Int64("comment", c.ID). | |
| 213 | 214 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue comment added") | |
| 215 | + | recordActivity(ctx, i.meta, name, c.CreatedAt) | |
| 214 | 216 | i.bus.Publish(ctx, domain.IssueCommented{ | |
| 215 | 217 | Repo: name, Number: number, Comment: c, At: c.CreatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, | |
| 216 | 218 | }) | |
| @@ -260,6 +262,7 @@ func (i *Issues) transition(ctx context.Context, p domain.Principal, name domain | |||
| 260 | 262 | log := zerowrap.FromCtx(ctx) | |
| 261 | 263 | log.Info().Str("repo", name.String()).Int64("number", number). | |
| 262 | 264 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue " + verb + "d") | |
| 265 | + | recordActivity(ctx, i.meta, repo.Name, issue.UpdatedAt) | |
| 263 | 266 | if to == domain.IssueStateOpen { | |
| 264 | 267 | i.bus.Publish(ctx, domain.IssueReopened{Issue: issue, At: issue.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | |
| 265 | 268 | } else { | |
| @@ -124,6 +124,7 @@ func (i *Issues) Create(ctx context.Context, p domain.Principal, name domain.Rep | |||||
| 124 | log := zerowrap.FromCtx(ctx) | 124 | log := zerowrap.FromCtx(ctx) | ||
| 125 | log.Info().Str("repo", name.String()).Int64("number", issue.Number). | 125 | log.Info().Str("repo", name.String()).Int64("number", issue.Number). | ||
| 126 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue opened") | 126 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue opened") | ||
| 127 | + | recordActivity(ctx, i.meta, repo.Name, now) | |||
| 127 | i.bus.Publish(ctx, domain.IssueOpened{Issue: issue, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | 128 | i.bus.Publish(ctx, domain.IssueOpened{Issue: issue, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | ||
| 128 | return issue, nil | 129 | return issue, nil | ||
| 129 | } | 130 | } | ||
| @@ -211,6 +212,7 @@ func (i *Issues) AddComment(ctx context.Context, p domain.Principal, name domain | |||||
| 211 | log := zerowrap.FromCtx(ctx) | 212 | log := zerowrap.FromCtx(ctx) | ||
| 212 | log.Info().Str("repo", name.String()).Int64("number", number).Int64("comment", c.ID). | 213 | log.Info().Str("repo", name.String()).Int64("number", number).Int64("comment", c.ID). | ||
| 213 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue comment added") | 214 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue comment added") | ||
| 215 | + | recordActivity(ctx, i.meta, name, c.CreatedAt) | |||
| 214 | i.bus.Publish(ctx, domain.IssueCommented{ | 216 | i.bus.Publish(ctx, domain.IssueCommented{ | ||
| 215 | Repo: name, Number: number, Comment: c, At: c.CreatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, | 217 | Repo: name, Number: number, Comment: c, At: c.CreatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, | ||
| 216 | }) | 218 | }) | ||
| @@ -260,6 +262,7 @@ func (i *Issues) transition(ctx context.Context, p domain.Principal, name domain | |||||
| 260 | log := zerowrap.FromCtx(ctx) | 262 | log := zerowrap.FromCtx(ctx) | ||
| 261 | log.Info().Str("repo", name.String()).Int64("number", number). | 263 | log.Info().Str("repo", name.String()).Int64("number", number). | ||
| 262 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue " + verb + "d") | 264 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("issue " + verb + "d") | ||
| 265 | + | recordActivity(ctx, i.meta, repo.Name, issue.UpdatedAt) | |||
| 263 | if to == domain.IssueStateOpen { | 266 | if to == domain.IssueStateOpen { | ||
| 264 | i.bus.Publish(ctx, domain.IssueReopened{Issue: issue, At: issue.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | 267 | i.bus.Publish(ctx, domain.IssueReopened{Issue: issue, At: issue.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | ||
| 265 | } else { | 268 | } else { | ||
M internal/usecase/issues_integration_test.go +4 -0
| @@ -46,6 +46,10 @@ func TestIssuesOverTheStore(t *testing.T) { | |||
| 46 | 46 | require.NoError(t, err) | |
| 47 | 47 | assert.EqualValues(t, 2, issue.Number, "the number follows the merge request") | |
| 48 | 48 | assert.Equal(t, "bot", issue.Author) | |
| 49 | + | repo, err := store.Get(ctx, n) | |
| 50 | + | require.NoError(t, err) | |
| 51 | + | assert.True(t, repo.ActiveAt.Equal(now)) | |
| 52 | + | assert.True(t, repo.PushedAt.IsZero()) | |
| 49 | 53 | ||
| 50 | 54 | kind, err := issues.Kind(ctx, domain.Anonymous(), n, 1) | |
| 51 | 55 | require.NoError(t, err) | |
| @@ -46,6 +46,10 @@ func TestIssuesOverTheStore(t *testing.T) { | |||||
| 46 | require.NoError(t, err) | 46 | require.NoError(t, err) | ||
| 47 | assert.EqualValues(t, 2, issue.Number, "the number follows the merge request") | 47 | assert.EqualValues(t, 2, issue.Number, "the number follows the merge request") | ||
| 48 | assert.Equal(t, "bot", issue.Author) | 48 | assert.Equal(t, "bot", issue.Author) | ||
| 49 | + | repo, err := store.Get(ctx, n) | |||
| 50 | + | require.NoError(t, err) | |||
| 51 | + | assert.True(t, repo.ActiveAt.Equal(now)) | |||
| 52 | + | assert.True(t, repo.PushedAt.IsZero()) | |||
| 49 | 53 | ||||
| 50 | kind, err := issues.Kind(ctx, domain.Anonymous(), n, 1) | 54 | kind, err := issues.Kind(ctx, domain.Anonymous(), n, 1) | ||
| 51 | require.NoError(t, err) | 55 | require.NoError(t, err) | ||
M internal/usecase/issues_test.go +2 -0
| @@ -39,6 +39,7 @@ func newIssueUnit(t *testing.T, vis domain.Visibility, mode domain.IssuesMode) * | |||
| 39 | 39 | clock := mocks.NewClock(t) | |
| 40 | 40 | clock.EXPECT().Now().Return(now).Maybe() | |
| 41 | 41 | u.meta.EXPECT().Get(mock.Anything, u.repo.Name).Return(u.repo, nil).Maybe() | |
| 42 | + | u.meta.EXPECT().Update(mock.Anything, mock.MatchedBy(func(r domain.Repo) bool { return r.Name == u.repo.Name && r.ActiveAt.Equal(now) && r.PushedAt.IsZero() })).Return(nil).Maybe() | |
| 42 | 43 | u.issues = usecase.NewIssues(usecase.IssuesConfig{Meta: u.meta, Store: u.store, MergeRequests: u.mrs, Bus: u.bus, Clock: clock}) | |
| 43 | 44 | return u | |
| 44 | 45 | } | |
| @@ -116,6 +117,7 @@ func TestIssueCreateAndTransitions(t *testing.T) { | |||
| 116 | 117 | got, err := u.issues.Create(ctx, p, u.repo.Name, ports.CreateIssueParams{Title: " Crash ", Body: "why"}) | |
| 117 | 118 | require.NoError(t, err) | |
| 118 | 119 | assert.EqualValues(t, 7, got.Number) | |
| 120 | + | u.meta.AssertCalled(t, "Update", mock.Anything, mock.MatchedBy(func(r domain.Repo) bool { return r.ActiveAt.Equal(now) && r.PushedAt.IsZero() })) | |
| 119 | 121 | }) | |
| 120 | 122 | ||
| 121 | 123 | t.Run("invalid text stores nothing", func(t *testing.T) { | |
| @@ -39,6 +39,7 @@ func newIssueUnit(t *testing.T, vis domain.Visibility, mode domain.IssuesMode) * | |||||
| 39 | clock := mocks.NewClock(t) | 39 | clock := mocks.NewClock(t) | ||
| 40 | clock.EXPECT().Now().Return(now).Maybe() | 40 | clock.EXPECT().Now().Return(now).Maybe() | ||
| 41 | u.meta.EXPECT().Get(mock.Anything, u.repo.Name).Return(u.repo, nil).Maybe() | 41 | u.meta.EXPECT().Get(mock.Anything, u.repo.Name).Return(u.repo, nil).Maybe() | ||
| 42 | + | u.meta.EXPECT().Update(mock.Anything, mock.MatchedBy(func(r domain.Repo) bool { return r.Name == u.repo.Name && r.ActiveAt.Equal(now) && r.PushedAt.IsZero() })).Return(nil).Maybe() | |||
| 42 | u.issues = usecase.NewIssues(usecase.IssuesConfig{Meta: u.meta, Store: u.store, MergeRequests: u.mrs, Bus: u.bus, Clock: clock}) | 43 | u.issues = usecase.NewIssues(usecase.IssuesConfig{Meta: u.meta, Store: u.store, MergeRequests: u.mrs, Bus: u.bus, Clock: clock}) | ||
| 43 | return u | 44 | return u | ||
| 44 | } | 45 | } | ||
| @@ -116,6 +117,7 @@ func TestIssueCreateAndTransitions(t *testing.T) { | |||||
| 116 | got, err := u.issues.Create(ctx, p, u.repo.Name, ports.CreateIssueParams{Title: " Crash ", Body: "why"}) | 117 | got, err := u.issues.Create(ctx, p, u.repo.Name, ports.CreateIssueParams{Title: " Crash ", Body: "why"}) | ||
| 117 | require.NoError(t, err) | 118 | require.NoError(t, err) | ||
| 118 | assert.EqualValues(t, 7, got.Number) | 119 | assert.EqualValues(t, 7, got.Number) | ||
| 120 | + | u.meta.AssertCalled(t, "Update", mock.Anything, mock.MatchedBy(func(r domain.Repo) bool { return r.ActiveAt.Equal(now) && r.PushedAt.IsZero() })) | |||
| 119 | }) | 121 | }) | ||
| 120 | 122 | ||||
| 121 | t.Run("invalid text stores nothing", func(t *testing.T) { | 123 | t.Run("invalid text stores nothing", func(t *testing.T) { | ||
M internal/usecase/mergerequests.go +5 -0
| @@ -254,6 +254,7 @@ func (m *MergeRequests) Create(ctx context.Context, p domain.Principal, name dom | |||
| 254 | 254 | if err != nil { | |
| 255 | 255 | return domain.MergeRequest{}, err | |
| 256 | 256 | } | |
| 257 | + | recordActivity(ctx, m.meta, repo.Name, now) | |
| 257 | 258 | m.bus.Publish(ctx, domain.MergeRequestOpened{MergeRequest: mr, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | |
| 258 | 259 | if m.pulls != nil { | |
| 259 | 260 | // The commits the opening is for are the ones of now. | |
| @@ -377,6 +378,7 @@ func (m *MergeRequests) MarkReady(ctx context.Context, p domain.Principal, name | |||
| 377 | 378 | if err != nil { | |
| 378 | 379 | return domain.MergeRequest{}, fmt.Errorf("mark !%d of %q ready: %w", number, name, err) | |
| 379 | 380 | } | |
| 381 | + | recordActivity(ctx, m.meta, repo.Name, mr.UpdatedAt) | |
| 380 | 382 | m.bus.Publish(ctx, domain.MergeRequestReady{MergeRequest: mr, At: mr.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | |
| 381 | 383 | return m.withHead(ctx, mr) | |
| 382 | 384 | } | |
| @@ -656,6 +658,7 @@ func (m *MergeRequests) AddComment(ctx context.Context, p domain.Principal, name | |||
| 656 | 658 | log := zerowrap.FromCtx(ctx) | |
| 657 | 659 | log.Info().Str("repo", name.String()).Int64("number", number).Int64("comment", c.ID). | |
| 658 | 660 | Int64("reply_to", c.ReplyTo).Str("verdict", c.Verdict.String()).Bool("on_line", !general).Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("comment added") | |
| 661 | + | recordActivity(ctx, m.meta, name, c.CreatedAt) | |
| 659 | 662 | m.bus.Publish(ctx, domain.CommentAdded{ | |
| 660 | 663 | Repo: name, Number: number, Comment: c, At: c.CreatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, | |
| 661 | 664 | }) | |
| @@ -796,6 +799,7 @@ func (m *MergeRequests) Close(ctx context.Context, p domain.Principal, name doma | |||
| 796 | 799 | log := zerowrap.FromCtx(ctx) | |
| 797 | 800 | log.Info().Str("repo", name.String()).Int64("number", number). | |
| 798 | 801 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("merge request closed") | |
| 802 | + | recordActivity(ctx, m.meta, repo.Name, mr.UpdatedAt) | |
| 799 | 803 | m.bus.Publish(ctx, domain.MergeRequestClosed{MergeRequest: mr, At: mr.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | |
| 800 | 804 | if m.pulls != nil { | |
| 801 | 805 | m.pulls.OnPullRequest(ctx, name, ports.PullRequestEvent{Number: number, Action: domain.PullClosed, Head: mr.HeadID, Base: mr.BaseID}, p) | |
| @@ -998,6 +1002,7 @@ func (m *MergeRequests) merge(ctx context.Context, p domain.Principal, name doma | |||
| 998 | 1002 | } | |
| 999 | 1003 | } | |
| 1000 | 1004 | at := mr.UpdatedAt | |
| 1005 | + | recordActivity(ctx, m.meta, repo.Name, at) | |
| 1001 | 1006 | m.bus.Publish(ctx, domain.MergeRequestMerged{MergeRequest: mr, At: at, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | |
| 1002 | 1007 | m.bus.Publish(ctx, domain.PushEvent{ | |
| 1003 | 1008 | Repo: name, At: at, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, Updates: updates, | |
| @@ -254,6 +254,7 @@ func (m *MergeRequests) Create(ctx context.Context, p domain.Principal, name dom | |||||
| 254 | if err != nil { | 254 | if err != nil { | ||
| 255 | return domain.MergeRequest{}, err | 255 | return domain.MergeRequest{}, err | ||
| 256 | } | 256 | } | ||
| 257 | + | recordActivity(ctx, m.meta, repo.Name, now) | |||
| 257 | m.bus.Publish(ctx, domain.MergeRequestOpened{MergeRequest: mr, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | 258 | m.bus.Publish(ctx, domain.MergeRequestOpened{MergeRequest: mr, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | ||
| 258 | if m.pulls != nil { | 259 | if m.pulls != nil { | ||
| 259 | // The commits the opening is for are the ones of now. | 260 | // The commits the opening is for are the ones of now. | ||
| @@ -377,6 +378,7 @@ func (m *MergeRequests) MarkReady(ctx context.Context, p domain.Principal, name | |||||
| 377 | if err != nil { | 378 | if err != nil { | ||
| 378 | return domain.MergeRequest{}, fmt.Errorf("mark !%d of %q ready: %w", number, name, err) | 379 | return domain.MergeRequest{}, fmt.Errorf("mark !%d of %q ready: %w", number, name, err) | ||
| 379 | } | 380 | } | ||
| 381 | + | recordActivity(ctx, m.meta, repo.Name, mr.UpdatedAt) | |||
| 380 | m.bus.Publish(ctx, domain.MergeRequestReady{MergeRequest: mr, At: mr.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | 382 | m.bus.Publish(ctx, domain.MergeRequestReady{MergeRequest: mr, At: mr.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | ||
| 381 | return m.withHead(ctx, mr) | 383 | return m.withHead(ctx, mr) | ||
| 382 | } | 384 | } | ||
| @@ -656,6 +658,7 @@ func (m *MergeRequests) AddComment(ctx context.Context, p domain.Principal, name | |||||
| 656 | log := zerowrap.FromCtx(ctx) | 658 | log := zerowrap.FromCtx(ctx) | ||
| 657 | log.Info().Str("repo", name.String()).Int64("number", number).Int64("comment", c.ID). | 659 | log.Info().Str("repo", name.String()).Int64("number", number).Int64("comment", c.ID). | ||
| 658 | Int64("reply_to", c.ReplyTo).Str("verdict", c.Verdict.String()).Bool("on_line", !general).Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("comment added") | 660 | Int64("reply_to", c.ReplyTo).Str("verdict", c.Verdict.String()).Bool("on_line", !general).Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("comment added") | ||
| 661 | + | recordActivity(ctx, m.meta, name, c.CreatedAt) | |||
| 659 | m.bus.Publish(ctx, domain.CommentAdded{ | 662 | m.bus.Publish(ctx, domain.CommentAdded{ | ||
| 660 | Repo: name, Number: number, Comment: c, At: c.CreatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, | 663 | Repo: name, Number: number, Comment: c, At: c.CreatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, | ||
| 661 | }) | 664 | }) | ||
| @@ -796,6 +799,7 @@ func (m *MergeRequests) Close(ctx context.Context, p domain.Principal, name doma | |||||
| 796 | log := zerowrap.FromCtx(ctx) | 799 | log := zerowrap.FromCtx(ctx) | ||
| 797 | log.Info().Str("repo", name.String()).Int64("number", number). | 800 | log.Info().Str("repo", name.String()).Int64("number", number). | ||
| 798 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("merge request closed") | 801 | Str("principal", p.Label()).Str("token_id", p.TokenID()).Msg("merge request closed") | ||
| 802 | + | recordActivity(ctx, m.meta, repo.Name, mr.UpdatedAt) | |||
| 799 | m.bus.Publish(ctx, domain.MergeRequestClosed{MergeRequest: mr, At: mr.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | 803 | m.bus.Publish(ctx, domain.MergeRequestClosed{MergeRequest: mr, At: mr.UpdatedAt, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | ||
| 800 | if m.pulls != nil { | 804 | if m.pulls != nil { | ||
| 801 | m.pulls.OnPullRequest(ctx, name, ports.PullRequestEvent{Number: number, Action: domain.PullClosed, Head: mr.HeadID, Base: mr.BaseID}, p) | 805 | m.pulls.OnPullRequest(ctx, name, ports.PullRequestEvent{Number: number, Action: domain.PullClosed, Head: mr.HeadID, Base: mr.BaseID}, p) | ||
| @@ -998,6 +1002,7 @@ func (m *MergeRequests) merge(ctx context.Context, p domain.Principal, name doma | |||||
| 998 | } | 1002 | } | ||
| 999 | } | 1003 | } | ||
| 1000 | at := mr.UpdatedAt | 1004 | at := mr.UpdatedAt | ||
| 1005 | + | recordActivity(ctx, m.meta, repo.Name, at) | |||
| 1001 | m.bus.Publish(ctx, domain.MergeRequestMerged{MergeRequest: mr, At: at, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | 1006 | m.bus.Publish(ctx, domain.MergeRequestMerged{MergeRequest: mr, At: at, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}) | ||
| 1002 | m.bus.Publish(ctx, domain.PushEvent{ | 1007 | m.bus.Publish(ctx, domain.PushEvent{ | ||
| 1003 | Repo: name, At: at, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, Updates: updates, | 1008 | Repo: name, At: at, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt, Updates: updates, | ||
M internal/usecase/mergerequests_integration_test.go +11 -0
| @@ -1448,3 +1448,14 @@ func TestNoteThreadsRangesAndVerdicts(t *testing.T) { | |||
| 1448 | 1448 | _, err = r.mrs.DeleteComment(r.ctx, root, r.repo, mr.Number, changes.ID) | |
| 1449 | 1449 | assert.ErrorIs(t, err, domain.ErrPreconditionFailed) | |
| 1450 | 1450 | } | |
| 1451 | + | ||
| 1452 | + | func TestMergeRequestRecordsRepositoryActivity(t *testing.T) { | |
| 1453 | + | r := newMRRig(t) | |
| 1454 | + | r.seed() | |
| 1455 | + | r.feature("activity") | |
| 1456 | + | _, err := r.mrs.Create(r.ctx, root, r.repo, ports.CreateMergeRequestParams{Title: "Activity", Source: "activity", Target: "main"}) | |
| 1457 | + | require.NoError(t, err) | |
| 1458 | + | repo, err := r.store.Get(r.ctx, r.repo) | |
| 1459 | + | require.NoError(t, err) | |
| 1460 | + | assert.True(t, repo.ActiveAt.Equal(now)) | |
| 1461 | + | } | |
| @@ -1448,3 +1448,14 @@ func TestNoteThreadsRangesAndVerdicts(t *testing.T) { | |||||
| 1448 | _, err = r.mrs.DeleteComment(r.ctx, root, r.repo, mr.Number, changes.ID) | 1448 | _, err = r.mrs.DeleteComment(r.ctx, root, r.repo, mr.Number, changes.ID) | ||
| 1449 | assert.ErrorIs(t, err, domain.ErrPreconditionFailed) | 1449 | assert.ErrorIs(t, err, domain.ErrPreconditionFailed) | ||
| 1450 | } | 1450 | } | ||
| 1451 | + | ||||
| 1452 | + | func TestMergeRequestRecordsRepositoryActivity(t *testing.T) { | |||
| 1453 | + | r := newMRRig(t) | |||
| 1454 | + | r.seed() | |||
| 1455 | + | r.feature("activity") | |||
| 1456 | + | _, err := r.mrs.Create(r.ctx, root, r.repo, ports.CreateMergeRequestParams{Title: "Activity", Source: "activity", Target: "main"}) | |||
| 1457 | + | require.NoError(t, err) | |||
| 1458 | + | repo, err := r.store.Get(r.ctx, r.repo) | |||
| 1459 | + | require.NoError(t, err) | |||
| 1460 | + | assert.True(t, repo.ActiveAt.Equal(now)) | |||
| 1461 | + | } | |||
M internal/usecase/pushes.go +10 -4
| @@ -209,7 +209,7 @@ func (u *Pushes) checkWorkflows(ctx context.Context, name domain.RepoName, updat | |||
| 209 | 209 | return nil | |
| 210 | 210 | } | |
| 211 | 211 | ||
| 212 | - | // Record is the post-receive step of an accepted push: it sets pushed_at, | |
| 212 | + | // Record is the post-receive step of an accepted push: it sets pushed_at and active_at, | |
| 213 | 213 | // repairs HEAD when it points to a missing branch, tells the reader that the | |
| 214 | 214 | // repository changed, queues the workflows the push triggers, publishes a | |
| 215 | 215 | // PushEvent and schedules maintenance. Every | |
| @@ -245,7 +245,8 @@ func (u *Pushes) Record(ctx context.Context, p domain.Principal, name domain.Rep | |||
| 245 | 245 | return errors.Join(errs...) | |
| 246 | 246 | } | |
| 247 | 247 | ||
| 248 | - | // touchPushedAt stores pushed_at, retrying when another write got in between. | |
| 248 | + | // touchPushedAt stores pushed_at and active_at, preserving later timestamps | |
| 249 | + | // and retrying when another write got in between. | |
| 249 | 250 | // A repository deleted meanwhile is not an error. It returns the repository | |
| 250 | 251 | // as read, or the zero value when it is unknown. A push (Pushes.Record) and a | |
| 251 | 252 | // merge, which moves a branch too, both record through it. | |
| @@ -258,10 +259,15 @@ func touchPushedAt(ctx context.Context, meta ports.RepoMetaStore, name domain.Re | |||
| 258 | 259 | if err != nil { | |
| 259 | 260 | return domain.Repo{}, fmt.Errorf("get repository %q: %w", name, err) | |
| 260 | 261 | } | |
| 261 | - | if !now.After(repo.PushedAt) { | |
| 262 | + | if !now.After(repo.PushedAt) && !now.After(repo.ActiveAt) { | |
| 262 | 263 | return repo, nil // a later push already recorded | |
| 263 | 264 | } | |
| 264 | - | repo.PushedAt = now | |
| 265 | + | if now.After(repo.PushedAt) { | |
| 266 | + | repo.PushedAt = now | |
| 267 | + | } | |
| 268 | + | if now.After(repo.ActiveAt) { | |
| 269 | + | repo.ActiveAt = now | |
| 270 | + | } | |
| 265 | 271 | err = meta.Update(ctx, repo) | |
| 266 | 272 | if errors.Is(err, domain.ErrConflict) { | |
| 267 | 273 | continue | |
| @@ -209,7 +209,7 @@ func (u *Pushes) checkWorkflows(ctx context.Context, name domain.RepoName, updat | |||||
| 209 | return nil | 209 | return nil | ||
| 210 | } | 210 | } | ||
| 211 | 211 | ||||
| 212 | - | // Record is the post-receive step of an accepted push: it sets pushed_at, | 212 | + | // Record is the post-receive step of an accepted push: it sets pushed_at and active_at, |
| 213 | // repairs HEAD when it points to a missing branch, tells the reader that the | 213 | // repairs HEAD when it points to a missing branch, tells the reader that the | ||
| 214 | // repository changed, queues the workflows the push triggers, publishes a | 214 | // repository changed, queues the workflows the push triggers, publishes a | ||
| 215 | // PushEvent and schedules maintenance. Every | 215 | // PushEvent and schedules maintenance. Every | ||
| @@ -245,7 +245,8 @@ func (u *Pushes) Record(ctx context.Context, p domain.Principal, name domain.Rep | |||||
| 245 | return errors.Join(errs...) | 245 | return errors.Join(errs...) | ||
| 246 | } | 246 | } | ||
| 247 | 247 | ||||
| 248 | - | // touchPushedAt stores pushed_at, retrying when another write got in between. | 248 | + | // touchPushedAt stores pushed_at and active_at, preserving later timestamps |
| 249 | + | // and retrying when another write got in between. | |||
| 249 | // A repository deleted meanwhile is not an error. It returns the repository | 250 | // A repository deleted meanwhile is not an error. It returns the repository | ||
| 250 | // as read, or the zero value when it is unknown. A push (Pushes.Record) and a | 251 | // as read, or the zero value when it is unknown. A push (Pushes.Record) and a | ||
| 251 | // merge, which moves a branch too, both record through it. | 252 | // merge, which moves a branch too, both record through it. | ||
| @@ -258,10 +259,15 @@ func touchPushedAt(ctx context.Context, meta ports.RepoMetaStore, name domain.Re | |||||
| 258 | if err != nil { | 259 | if err != nil { | ||
| 259 | return domain.Repo{}, fmt.Errorf("get repository %q: %w", name, err) | 260 | return domain.Repo{}, fmt.Errorf("get repository %q: %w", name, err) | ||
| 260 | } | 261 | } | ||
| 261 | - | if !now.After(repo.PushedAt) { | 262 | + | if !now.After(repo.PushedAt) && !now.After(repo.ActiveAt) { |
| 262 | return repo, nil // a later push already recorded | 263 | return repo, nil // a later push already recorded | ||
| 263 | } | 264 | } | ||
| 264 | - | repo.PushedAt = now | 265 | + | if now.After(repo.PushedAt) { |
| 266 | + | repo.PushedAt = now | |||
| 267 | + | } | |||
| 268 | + | if now.After(repo.ActiveAt) { | |||
| 269 | + | repo.ActiveAt = now | |||
| 270 | + | } | |||
| 265 | err = meta.Update(ctx, repo) | 271 | err = meta.Update(ctx, repo) | ||
| 266 | if errors.Is(err, domain.ErrConflict) { | 272 | if errors.Is(err, domain.ErrConflict) { | ||
| 267 | continue | 273 | continue | ||
M internal/usecase/pushes_test.go +4 -4
| @@ -306,7 +306,7 @@ func TestPushesRecord(t *testing.T) { | |||
| 306 | 306 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | |
| 307 | 307 | repo := domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: now.Add(-time.Hour)} | |
| 308 | 308 | f.meta.EXPECT().Get(ctx, n).Return(repo, nil) | |
| 309 | - | f.meta.EXPECT().Update(ctx, domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: repo.CreatedAt, PushedAt: now}).Return(nil) | |
| 309 | + | f.meta.EXPECT().Update(ctx, domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: repo.CreatedAt, PushedAt: now, ActiveAt: now}).Return(nil) | |
| 310 | 310 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", true, nil) | |
| 311 | 311 | f.bus.EXPECT().Publish(ctx, domain.PushEvent{Repo: n, Updates: ups, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}).Return() | |
| 312 | 312 | ||
| @@ -334,7 +334,7 @@ func TestPushesRecord(t *testing.T) { | |||
| 334 | 334 | repo := domain.Repo{Name: n} | |
| 335 | 335 | f.meta.EXPECT().Get(ctx, n).Return(repo, nil).Once() | |
| 336 | 336 | f.meta.EXPECT().Update(ctx, mock.Anything).Return(domain.ErrConflict).Once() | |
| 337 | - | later := domain.Repo{Name: n, PushedAt: now.Add(time.Second)} | |
| 337 | + | later := domain.Repo{Name: n, PushedAt: now.Add(time.Second), ActiveAt: now.Add(time.Second)} | |
| 338 | 338 | f.meta.EXPECT().Get(ctx, n).Return(later, nil).Once() // a later push recorded meanwhile | |
| 339 | 339 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", true, nil) | |
| 340 | 340 | f.bus.EXPECT().Publish(ctx, mock.Anything).Return() | |
| @@ -414,7 +414,7 @@ func TestPushesDefaultBranchRule(t *testing.T) { | |||
| 414 | 414 | t.Parallel() | |
| 415 | 415 | f := newPushFixture(t) | |
| 416 | 416 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | |
| 417 | - | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now}, nil) | |
| 417 | + | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now, ActiveAt: now}, nil) | |
| 418 | 418 | f.git.EXPECT().DefaultBranch(ctx, n).Return(tt.head, tt.exists, nil) | |
| 419 | 419 | if tt.want != "" { | |
| 420 | 420 | f.git.EXPECT().SetDefaultBranch(ctx, n, tt.want).Return(nil) | |
| @@ -429,7 +429,7 @@ func TestPushesDefaultBranchRule(t *testing.T) { | |||
| 429 | 429 | f := newPushFixture(t) | |
| 430 | 430 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | |
| 431 | 431 | boom := errors.New("boom") | |
| 432 | - | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now}, nil) | |
| 432 | + | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now, ActiveAt: now}, nil) | |
| 433 | 433 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", false, nil) | |
| 434 | 434 | f.git.EXPECT().SetDefaultBranch(ctx, n, "dev").Return(boom) | |
| 435 | 435 | f.bus.EXPECT().Publish(ctx, mock.Anything).Return() | |
| @@ -306,7 +306,7 @@ func TestPushesRecord(t *testing.T) { | |||||
| 306 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | 306 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | ||
| 307 | repo := domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: now.Add(-time.Hour)} | 307 | repo := domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: now.Add(-time.Hour)} | ||
| 308 | f.meta.EXPECT().Get(ctx, n).Return(repo, nil) | 308 | f.meta.EXPECT().Get(ctx, n).Return(repo, nil) | ||
| 309 | - | f.meta.EXPECT().Update(ctx, domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: repo.CreatedAt, PushedAt: now}).Return(nil) | 309 | + | f.meta.EXPECT().Update(ctx, domain.Repo{Name: n, Visibility: domain.VisibilityPrivate, CreatedAt: repo.CreatedAt, PushedAt: now, ActiveAt: now}).Return(nil) |
| 310 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", true, nil) | 310 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", true, nil) | ||
| 311 | f.bus.EXPECT().Publish(ctx, domain.PushEvent{Repo: n, Updates: ups, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}).Return() | 311 | f.bus.EXPECT().Publish(ctx, domain.PushEvent{Repo: n, Updates: ups, At: now, Visibility: repo.Visibility, CreatedAt: repo.CreatedAt}).Return() | ||
| 312 | 312 | ||||
| @@ -334,7 +334,7 @@ func TestPushesRecord(t *testing.T) { | |||||
| 334 | repo := domain.Repo{Name: n} | 334 | repo := domain.Repo{Name: n} | ||
| 335 | f.meta.EXPECT().Get(ctx, n).Return(repo, nil).Once() | 335 | f.meta.EXPECT().Get(ctx, n).Return(repo, nil).Once() | ||
| 336 | f.meta.EXPECT().Update(ctx, mock.Anything).Return(domain.ErrConflict).Once() | 336 | f.meta.EXPECT().Update(ctx, mock.Anything).Return(domain.ErrConflict).Once() | ||
| 337 | - | later := domain.Repo{Name: n, PushedAt: now.Add(time.Second)} | 337 | + | later := domain.Repo{Name: n, PushedAt: now.Add(time.Second), ActiveAt: now.Add(time.Second)} |
| 338 | f.meta.EXPECT().Get(ctx, n).Return(later, nil).Once() // a later push recorded meanwhile | 338 | f.meta.EXPECT().Get(ctx, n).Return(later, nil).Once() // a later push recorded meanwhile | ||
| 339 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", true, nil) | 339 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", true, nil) | ||
| 340 | f.bus.EXPECT().Publish(ctx, mock.Anything).Return() | 340 | f.bus.EXPECT().Publish(ctx, mock.Anything).Return() | ||
| @@ -414,7 +414,7 @@ func TestPushesDefaultBranchRule(t *testing.T) { | |||||
| 414 | t.Parallel() | 414 | t.Parallel() | ||
| 415 | f := newPushFixture(t) | 415 | f := newPushFixture(t) | ||
| 416 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | 416 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | ||
| 417 | - | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now}, nil) | 417 | + | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now, ActiveAt: now}, nil) |
| 418 | f.git.EXPECT().DefaultBranch(ctx, n).Return(tt.head, tt.exists, nil) | 418 | f.git.EXPECT().DefaultBranch(ctx, n).Return(tt.head, tt.exists, nil) | ||
| 419 | if tt.want != "" { | 419 | if tt.want != "" { | ||
| 420 | f.git.EXPECT().SetDefaultBranch(ctx, n, tt.want).Return(nil) | 420 | f.git.EXPECT().SetDefaultBranch(ctx, n, tt.want).Return(nil) | ||
| @@ -429,7 +429,7 @@ func TestPushesDefaultBranchRule(t *testing.T) { | |||||
| 429 | f := newPushFixture(t) | 429 | f := newPushFixture(t) | ||
| 430 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | 430 | f.sched.EXPECT().Schedule(ctx, n).Return().Once() | ||
| 431 | boom := errors.New("boom") | 431 | boom := errors.New("boom") | ||
| 432 | - | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now}, nil) | 432 | + | f.meta.EXPECT().Get(ctx, n).Return(domain.Repo{Name: n, PushedAt: now, ActiveAt: now}, nil) |
| 433 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", false, nil) | 433 | f.git.EXPECT().DefaultBranch(ctx, n).Return("main", false, nil) | ||
| 434 | f.git.EXPECT().SetDefaultBranch(ctx, n, "dev").Return(boom) | 434 | f.git.EXPECT().SetDefaultBranch(ctx, n, "dev").Return(boom) | ||
| 435 | f.bus.EXPECT().Publish(ctx, mock.Anything).Return() | 435 | f.bus.EXPECT().Publish(ctx, mock.Anything).Return() | ||
M proto/ermite/storage/repo.proto +2 -0
| @@ -32,6 +32,8 @@ message Repo { | |||
| 32 | 32 | RepoSettings settings = 6; | |
| 33 | 33 | // Normalized and sorted; empty on repositories stored before topics. | |
| 34 | 34 | repeated string topics = 7; | |
| 35 | + | // Latest push, merge request or issue activity; unset until recorded. | |
| 36 | + | google.protobuf.Timestamp active_at = 8; | |
| 35 | 37 | } | |
| 36 | 38 | ||
| 37 | 39 | // SchemaVersion is stored under the key "meta/schema". | |
| @@ -32,6 +32,8 @@ message Repo { | |||||
| 32 | RepoSettings settings = 6; | 32 | RepoSettings settings = 6; | ||
| 33 | // Normalized and sorted; empty on repositories stored before topics. | 33 | // Normalized and sorted; empty on repositories stored before topics. | ||
| 34 | repeated string topics = 7; | 34 | repeated string topics = 7; | ||
| 35 | + | // Latest push, merge request or issue activity; unset until recorded. | |||
| 36 | + | google.protobuf.Timestamp active_at = 8; | |||
| 35 | } | 37 | } | ||
| 36 | 38 | ||||
| 37 | // SchemaVersion is stored under the key "meta/schema". | 39 | // SchemaVersion is stored under the key "meta/schema". | ||