mirror of
https://github.com/go-gitea/gitea.git
synced 2025-05-13 01:12:36 -04:00
Merge fe9be75a8977affbeec227b1c90170d468f77ce1 into 0f63a5ef48b23c6ab26a4b13cfd26edbe4efbfa3
This commit is contained in:
commit
b78f6cfd85
@ -10,7 +10,9 @@ import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@ -28,6 +30,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
@ -83,11 +86,12 @@ func Commits(ctx *context.Context) {
|
||||
ctx.ServerError("CommitsByRange", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
||||
processedCommits, err := processGitCommits(ctx, commits)
|
||||
if err != nil {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["GroupCommits"] = GroupCommitsByDate(processedCommits)
|
||||
commitIDs := make([]string, 0, len(commits))
|
||||
for _, c := range commits {
|
||||
commitIDs = append(commitIDs, c.ID.String())
|
||||
@ -199,11 +203,12 @@ func SearchCommits(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
ctx.Data["CommitCount"] = len(commits)
|
||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
||||
processedCommits, err := processGitCommits(ctx, commits)
|
||||
if err != nil {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["GroupCommits"] = GroupCommitsByDate(processedCommits)
|
||||
|
||||
ctx.Data["Keyword"] = query
|
||||
if all {
|
||||
@ -245,11 +250,12 @@ func FileHistory(ctx *context.Context) {
|
||||
ctx.ServerError("CommitsByFileAndRange", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
||||
processedCommits, err := processGitCommits(ctx, commits)
|
||||
if err != nil {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["GroupCommits"] = GroupCommitsByDate(processedCommits)
|
||||
|
||||
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
||||
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
||||
@ -463,3 +469,57 @@ func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) ([]*git_m
|
||||
}
|
||||
return commits, nil
|
||||
}
|
||||
|
||||
// GroupedCommits defines the structure for grouped commits.
|
||||
type GroupedCommits struct {
|
||||
Date timeutil.TimeStamp
|
||||
Commits []*git_model.SignCommitWithStatuses
|
||||
}
|
||||
|
||||
// GroupCommitsByDate groups the commits by date (in days) using UTC timezone.
|
||||
func GroupCommitsByDate(commits []*git_model.SignCommitWithStatuses) []GroupedCommits {
|
||||
// Use Unix timestamp of date as key (truncated to day)
|
||||
grouped := make(map[int64][]*git_model.SignCommitWithStatuses)
|
||||
|
||||
for _, commit := range commits {
|
||||
var sigTime time.Time
|
||||
if commit.Committer != nil {
|
||||
sigTime = commit.Committer.When
|
||||
} else if commit.Author != nil {
|
||||
sigTime = commit.Author.When
|
||||
}
|
||||
|
||||
// Convert time to UTC timezone first
|
||||
sigTimeUTC := sigTime.UTC()
|
||||
|
||||
// Truncate time to date part (remove hours, minutes, seconds)
|
||||
year, month, day := sigTimeUTC.Date()
|
||||
dateOnly := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
|
||||
dateUnix := dateOnly.Unix()
|
||||
|
||||
grouped[dateUnix] = append(grouped[dateUnix], commit)
|
||||
}
|
||||
|
||||
// Create result slice with pre-allocated capacity
|
||||
result := make([]GroupedCommits, 0, len(grouped))
|
||||
|
||||
// Collect all dates and sort them
|
||||
dates := make([]int64, 0, len(grouped))
|
||||
for dateUnix := range grouped {
|
||||
dates = append(dates, dateUnix)
|
||||
}
|
||||
// Sort dates in descending order (most recent first)
|
||||
sort.Slice(dates, func(i, j int) bool {
|
||||
return dates[i] > dates[j]
|
||||
})
|
||||
|
||||
// Build result in sorted order
|
||||
for _, dateUnix := range dates {
|
||||
result = append(result, GroupedCommits{
|
||||
Date: timeutil.TimeStamp(dateUnix),
|
||||
Commits: grouped[dateUnix],
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
114
routers/web/repo/commit_test.go
Normal file
114
routers/web/repo/commit_test.go
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/asymkey"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGroupCommitsByDate(t *testing.T) {
|
||||
// Create test data
|
||||
// These two commits represent the same moment but in different timezones
|
||||
// commit1: 2025-04-10T08:00:00+08:00
|
||||
// commit2: 2025-04-09T23:00:00-01:00
|
||||
// Their UTC time is both 2025-04-10T00:00:00Z
|
||||
|
||||
// Create the first commit (Asia timezone +8)
|
||||
asiaTimezone := time.FixedZone("Asia/Shanghai", 8*60*60)
|
||||
commit1Time := time.Date(2025, 4, 10, 8, 0, 0, 0, asiaTimezone)
|
||||
commit1 := &git_model.SignCommitWithStatuses{
|
||||
SignCommit: &asymkey.SignCommit{
|
||||
UserCommit: &user.UserCommit{
|
||||
Commit: &git.Commit{
|
||||
Committer: &git.Signature{
|
||||
When: commit1Time,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create the second commit (Western timezone -1)
|
||||
westTimezone := time.FixedZone("West", -1*60*60)
|
||||
commit2Time := time.Date(2025, 4, 9, 23, 0, 0, 0, westTimezone)
|
||||
commit2 := &git_model.SignCommitWithStatuses{
|
||||
SignCommit: &asymkey.SignCommit{
|
||||
UserCommit: &user.UserCommit{
|
||||
Commit: &git.Commit{
|
||||
Committer: &git.Signature{
|
||||
When: commit2Time,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Verify that the two timestamps actually represent the same moment
|
||||
assert.Equal(t, commit1Time.Unix(), commit2Time.Unix(), "The two commits should have the same Unix timestamp")
|
||||
|
||||
// Test the modified grouping behavior
|
||||
commits := []*git_model.SignCommitWithStatuses{commit1, commit2}
|
||||
grouped := GroupCommitsByDate(commits)
|
||||
|
||||
// Output the grouping results for observation
|
||||
t.Logf("Number of grouped results: %d", len(grouped))
|
||||
for i, group := range grouped {
|
||||
t.Logf("Group %d: Date %s, Number of commits %d", i, time.Unix(int64(group.Date), 0).Format("2006-01-02"), len(group.Commits))
|
||||
for j, c := range group.Commits {
|
||||
t.Logf(" Commit %d: Time %s", j, c.SignCommit.UserCommit.Commit.Committer.When.Format(time.RFC3339))
|
||||
}
|
||||
}
|
||||
|
||||
// After modification, these two commits should be grouped together as they are on the same day in UTC timezone
|
||||
assert.Len(t, grouped, 1, "After modification, the two commits should be grouped together")
|
||||
|
||||
// Verify the group date (should be 2025-04-10, the date in UTC timezone)
|
||||
utcDate := time.Date(2025, 4, 10, 0, 0, 0, 0, time.UTC)
|
||||
assert.Equal(t, timeutil.TimeStamp(utcDate.Unix()), grouped[0].Date)
|
||||
assert.Len(t, grouped[0].Commits, 2)
|
||||
|
||||
// Verify that both commits are in this group
|
||||
commitMap := make(map[*git_model.SignCommitWithStatuses]bool)
|
||||
for _, c := range grouped[0].Commits {
|
||||
commitMap[c] = true
|
||||
}
|
||||
assert.True(t, commitMap[commit1], "The first commit should be in the group")
|
||||
assert.True(t, commitMap[commit2], "The second commit should be in the group")
|
||||
|
||||
// Add a commit with a different date for testing
|
||||
nextDayTimezone := time.FixedZone("NextDay", 0)
|
||||
commit3Time := time.Date(2025, 4, 11, 0, 0, 0, 0, nextDayTimezone)
|
||||
commit3 := &git_model.SignCommitWithStatuses{
|
||||
SignCommit: &asymkey.SignCommit{
|
||||
UserCommit: &user.UserCommit{
|
||||
Commit: &git.Commit{
|
||||
Committer: &git.Signature{
|
||||
When: commit3Time,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Test with commits from different dates
|
||||
commits = append(commits, commit3)
|
||||
grouped = GroupCommitsByDate(commits)
|
||||
|
||||
// Now there should be two groups
|
||||
assert.Len(t, grouped, 2, "There should be two different date groups")
|
||||
|
||||
// Verify date sorting (descending, most recent date first)
|
||||
assert.True(t, time.Unix(int64(grouped[0].Date), 0).After(time.Unix(int64(grouped[1].Date), 0)),
|
||||
"Dates should be sorted in descending order")
|
||||
}
|
@ -665,7 +665,7 @@ func PrepareCompareDiff(
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return false
|
||||
}
|
||||
ctx.Data["Commits"] = commits
|
||||
ctx.Data["GroupCommits"] = GroupCommitsByDate(commits)
|
||||
ctx.Data["CommitCount"] = len(commits)
|
||||
|
||||
title := ci.HeadBranch
|
||||
|
@ -627,7 +627,7 @@ func ViewPullCommits(ctx *context.Context) {
|
||||
ctx.ServerError("processGitCommits", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Commits"] = commits
|
||||
ctx.Data["GroupCommits"] = GroupCommitsByDate(commits)
|
||||
ctx.Data["CommitCount"] = len(commits)
|
||||
|
||||
ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
|
||||
|
111
templates/repo/commits_list_group_by_date.tmpl
Normal file
111
templates/repo/commits_list_group_by_date.tmpl
Normal file
@ -0,0 +1,111 @@
|
||||
{{range $index, $groupCommit := .GroupCommits}}
|
||||
<div class="ui timeline commits-list-group-by-date" data-index="{{$index}}">
|
||||
|
||||
<div class="timeline-badge-wrapper">
|
||||
<div class="timeline-badge">
|
||||
{{svg "octicon-git-commit"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-body">
|
||||
<h3 class="flex-text-block tw-py-2 timeline-heading">
|
||||
Commits on {{DateUtils.AbsoluteShort $groupCommit.Date}}
|
||||
</h3>
|
||||
<div class="tw-flex tw-mt-2 timeline-list-container">
|
||||
<ul class="commits-list">
|
||||
{{range $groupCommit.Commits}}
|
||||
{{$commitRepoLink := $.RepoLink}}{{if $.CommitRepoLink}}{{$commitRepoLink = $.CommitRepoLink}}{{end}}
|
||||
<li class="commits-list-item">
|
||||
<div class="tw-pt-4 tw-pl-4 title">
|
||||
<h4>
|
||||
<span class="message-wrapper">
|
||||
{{if $.PageIsWiki}}
|
||||
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary | ctx.RenderUtils.RenderEmoji}}</span>
|
||||
{{else}}
|
||||
{{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
|
||||
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink ($.Repository.ComposeCommentMetas ctx)}}</span>
|
||||
{{end}}
|
||||
</span>
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<button class="ui button ellipsis-button" aria-expanded="false" data-global-click="onRepoEllipsisButtonClick">...</button>
|
||||
{{end}}
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody .Message ($.Repository.ComposeCommentMetas ctx)}}</pre>
|
||||
{{end}}
|
||||
{{if $.CommitsTagsMap}}
|
||||
{{range (index $.CommitsTagsMap .ID.String)}}
|
||||
{{- template "repo/tag/name" dict "RepoLink" $.Repository.Link "TagName" .TagName "IsRelease" (not .IsTag) -}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="tw-flex tw-items-center tw-gap-1 tw-pb-4 tw-pl-4 description">
|
||||
<div class="author">
|
||||
{{$userName := .Author.Name}}
|
||||
{{if .User}}
|
||||
{{if and .User.FullName DefaultShowFullName}}
|
||||
{{$userName = .User.FullName}}
|
||||
{{end}}
|
||||
{{ctx.AvatarUtils.Avatar .User 28 "tw-mr-2"}}<a class="muted author-wrapper" href="{{.User.HomeLink}}">{{$userName}}</a>
|
||||
{{else}}
|
||||
{{ctx.AvatarUtils.AvatarByEmail .Author.Email .Author.Name 28 "tw-mr-2"}}
|
||||
<span class="author-wrapper">{{$userName}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
<span>
|
||||
{{if .Committer}}
|
||||
committed
|
||||
{{else}}
|
||||
authored
|
||||
{{end}}
|
||||
</span>
|
||||
{{if .Committer}}
|
||||
{{DateUtils.TimeSince .Committer.When}}
|
||||
{{else}}
|
||||
{{DateUtils.TimeSince .Author.When}}
|
||||
{{end}}
|
||||
{{if .Statuses}}
|
||||
<span>·</span>
|
||||
{{end}}
|
||||
{{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses}}
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-wrap tw-items-center tw-gap-2 tw-pr-4 metadata">
|
||||
{{$commitBaseLink := ""}}
|
||||
{{if $.PageIsWiki}}
|
||||
{{$commitBaseLink = printf "%s/wiki/commit" $commitRepoLink}}
|
||||
{{else if $.PageIsPullCommits}}
|
||||
{{$commitBaseLink = printf "%s/pulls/%d/commits" $commitRepoLink $.Issue.Index}}
|
||||
{{else if $.Reponame}}
|
||||
{{$commitBaseLink = printf "%s/commit" $commitRepoLink}}
|
||||
{{end}}
|
||||
<div class="commit-sign-badge">
|
||||
{{template "repo/commit_sign_badge" dict "Commit" . "CommitBaseLink" $commitBaseLink "CommitSignVerification" .Verification}}
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-wrap tw-items-center tw-gap-2">
|
||||
<div>
|
||||
<button class="btn interact-bg tw-p-2 copy-commit-id" data-tooltip-content="{{ctx.Locale.Tr "copy_hash"}}" data-clipboard-text="{{.ID}}">{{svg "octicon-copy"}}</button>
|
||||
</div>
|
||||
{{/* at the moment, wiki doesn't support these "view" links like "view at history point" */}}
|
||||
{{if not $.PageIsWiki}}
|
||||
{{/* view single file diff */}}
|
||||
{{if $.FileTreePath}}
|
||||
<a class="btn interact-bg tw-p-2 view-single-diff" data-tooltip-content="{{ctx.Locale.Tr "repo.commits.view_file_diff"}}"
|
||||
href="{{$commitRepoLink}}/commit/{{.ID.String}}?files={{$.FileTreePath}}"
|
||||
>{{svg "octicon-file-diff"}}</a>
|
||||
{{end}}
|
||||
|
||||
{{/* view at history point */}}
|
||||
{{$viewCommitLink := printf "%s/src/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
|
||||
{{if $.FileTreePath}}{{$viewCommitLink = printf "%s/%s" $viewCommitLink (PathEscapeSegments $.FileTreePath)}}{{end}}
|
||||
<a class="btn interact-bg tw-p-2 view-commit-path" data-tooltip-content="{{ctx.Locale.Tr "repo.commits.view_path"}}" href="{{$viewCommitLink}}">{{svg "octicon-file-code"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{end}}
|
@ -29,8 +29,8 @@
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if and .Commits (gt .CommitCount 0)}}
|
||||
{{template "repo/commits_list" .}}
|
||||
{{if and .GroupCommits (gt .CommitCount 0)}}
|
||||
{{template "repo/commits_list_group_by_date" .}}
|
||||
{{end}}
|
||||
|
||||
{{template "base/paginate" .}}
|
||||
|
@ -707,7 +707,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Get first commit URL
|
||||
commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
|
||||
commitURL, exists := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge a").Last().Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
|
@ -49,7 +49,7 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
// Get first commit URL
|
||||
commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
|
||||
commitURL, exists := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge a").Last().Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
@ -87,12 +87,12 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
doc = NewHTMLParser(t, resp.Body)
|
||||
|
||||
commitURL, exists = doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href")
|
||||
commitURL, exists = doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge a").Last().Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
assert.Equal(t, commitID, path.Base(commitURL))
|
||||
|
||||
cls, ok := doc.doc.Find("#commits-table tbody tr td.message .commit-status").Last().Attr("class")
|
||||
cls, ok := doc.doc.Find(".timeline.commits-list-group-by-date .description .commit-status").Last().Attr("class")
|
||||
assert.True(t, ok)
|
||||
assert.Contains(t, cls, statesIcons[status])
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func testRepoCommitsSearch(t *testing.T, query, commit string) {
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
sel := doc.doc.Find("#commits-table tbody tr td.sha a")
|
||||
sel := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge a")
|
||||
assert.Equal(t, commit, strings.TrimSpace(sel.Text()))
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ func TestRepoCommits(t *testing.T) {
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
commitURL, exists := doc.doc.Find("#commits-table .commit-id-short").Attr("href")
|
||||
commitURL, exists := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge .commit-id-short").Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
}
|
||||
@ -50,7 +50,7 @@ func Test_ReposGitCommitListNotMaster(t *testing.T) {
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
commits := []string{}
|
||||
doc.doc.Find("#commits-table .commit-id-short").Each(func(i int, s *goquery.Selection) {
|
||||
doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge .commit-id-short").Each(func(i int, s *goquery.Selection) {
|
||||
commitURL, exists := s.Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
@ -63,7 +63,7 @@ func Test_ReposGitCommitListNotMaster(t *testing.T) {
|
||||
assert.Equal(t, "5099b81332712fe655e34e8dd63574f503f61811", commits[2])
|
||||
|
||||
userNames := []string{}
|
||||
doc.doc.Find("#commits-table .author-wrapper").Each(func(i int, s *goquery.Selection) {
|
||||
doc.doc.Find(".timeline.commits-list-group-by-date .description .author-wrapper").Each(func(i int, s *goquery.Selection) {
|
||||
userPath, exists := s.Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, userPath)
|
||||
@ -87,7 +87,7 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
// Get first commit URL
|
||||
commitURL, exists := doc.doc.Find("#commits-table .commit-id-short").Attr("href")
|
||||
commitURL, exists := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge .commit-id-short").Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
@ -105,7 +105,7 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
||||
|
||||
doc = NewHTMLParser(t, resp.Body)
|
||||
// Check if commit status is displayed in message column (.tippy-target to ignore the tippy trigger)
|
||||
sel := doc.doc.Find("#commits-table .message .tippy-target .commit-status")
|
||||
sel := doc.doc.Find(".timeline.commits-list-group-by-date .description .tippy-target .commit-status")
|
||||
assert.Equal(t, 1, sel.Length())
|
||||
for _, class := range classes {
|
||||
assert.True(t, sel.HasClass(class))
|
||||
@ -181,7 +181,7 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
// Get first commit URL
|
||||
commitURL, exists := doc.doc.Find("#commits-table .commit-id-short").Attr("href")
|
||||
commitURL, exists := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge .commit-id-short").Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
@ -216,7 +216,7 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
|
||||
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
// Get first commit URL
|
||||
commitURL, exists := doc.doc.Find("#commits-table .commit-id-short").Attr("href")
|
||||
commitURL, exists := doc.doc.Find(".timeline.commits-list-group-by-date .commit-sign-badge .commit-id-short").Attr("href")
|
||||
assert.True(t, exists)
|
||||
assert.NotEmpty(t, commitURL)
|
||||
|
||||
@ -241,6 +241,6 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
|
||||
|
||||
doc = NewHTMLParser(t, resp.Body)
|
||||
// Check that the data-global-init="initCommitStatuses" (for trigger) and commit-status (svg) are present
|
||||
sel := doc.doc.Find(`#commits-table .message [data-global-init="initCommitStatuses"] .commit-status`)
|
||||
sel := doc.doc.Find(`.timeline.commits-list-group-by-date .description [data-global-init="initCommitStatuses"] .commit-status`)
|
||||
assert.Equal(t, 1, sel.Length())
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ func TestCommitListActions(t *testing.T) {
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
AssertHTMLElement(t, htmlDoc, `.commit-list .copy-commit-id`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, false)
|
||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .copy-commit-id`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-single-diff`, false)
|
||||
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-commit-path`, true)
|
||||
})
|
||||
|
||||
t.Run("RepoFileHistory", func(t *testing.T) {
|
||||
@ -60,8 +60,8 @@ func TestCommitListActions(t *testing.T) {
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
AssertHTMLElement(t, htmlDoc, `.commit-list .copy-commit-id`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .copy-commit-id`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-single-diff`, true)
|
||||
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-commit-path`, true)
|
||||
})
|
||||
}
|
||||
|
@ -2281,3 +2281,110 @@ tbody.commit-list {
|
||||
.branch-selector-dropdown .scrolling.menu .loading-indicator {
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline {
|
||||
display: flex;
|
||||
margin-left: 16px;
|
||||
position: relative;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline[data-index="0"] {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline::before {
|
||||
background-color: var(--color-timeline);
|
||||
bottom: 0;
|
||||
content: "";
|
||||
display: block;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .timeline-badge-wrapper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .timeline-badge {
|
||||
border-style: solid;
|
||||
border-radius: var(--border-radius-full);
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-box-body);
|
||||
float: left;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
margin-left: -16px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .timeline-heading {
|
||||
font-size: 15px;
|
||||
font-weight: var(--font-weight-normal);
|
||||
color: var(--color-text-light-2);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .timeline-body {
|
||||
max-width: 100%;
|
||||
flex: auto;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .timeline-list-container {
|
||||
border: 1px solid var(--color-secondary);
|
||||
background: var(--color-box-body);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list-item {
|
||||
list-style: none;
|
||||
display: grid;
|
||||
gap: .5rem;
|
||||
min-height: 2rem;
|
||||
position: relative;
|
||||
--core-grid-template-columns: minmax(30%, 1fr);
|
||||
--last-grid-template-column: minmax(0, max-content);
|
||||
grid-template-columns: var(--core-grid-template-columns) var(--last-grid-template-column);
|
||||
grid-template-areas: "primary metadata" "main-content metadata";
|
||||
grid-template-rows: repeat(2, auto);
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list-item:not(:last-child) {
|
||||
border-bottom: 1px solid var(--color-secondary);
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list-item:hover {
|
||||
background-color: var(--color-hover)
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list-item .title {
|
||||
grid-area: primary;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list-item .description {
|
||||
grid-area: main-content;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .commits-list-item .metadata {
|
||||
grid-area: metadata;
|
||||
}
|
||||
|
||||
.commits-list-group-by-date.timeline .author img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user