mirror of
https://github.com/go-gitea/gitea.git
synced 2025-05-14 00:02:55 -04:00
Merge fe9be75a8977affbeec227b1c90170d468f77ce1 into 0f63a5ef48b23c6ab26a4b13cfd26edbe4efbfa3
This commit is contained in:
commit
b78f6cfd85
@ -10,7 +10,9 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
@ -28,6 +30,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/templates"
|
"code.gitea.io/gitea/modules/templates"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
@ -83,11 +86,12 @@ func Commits(ctx *context.Context) {
|
|||||||
ctx.ServerError("CommitsByRange", err)
|
ctx.ServerError("CommitsByRange", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
processedCommits, err := processGitCommits(ctx, commits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("processGitCommits", err)
|
ctx.ServerError("processGitCommits", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ctx.Data["GroupCommits"] = GroupCommitsByDate(processedCommits)
|
||||||
commitIDs := make([]string, 0, len(commits))
|
commitIDs := make([]string, 0, len(commits))
|
||||||
for _, c := range commits {
|
for _, c := range commits {
|
||||||
commitIDs = append(commitIDs, c.ID.String())
|
commitIDs = append(commitIDs, c.ID.String())
|
||||||
@ -199,11 +203,12 @@ func SearchCommits(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["CommitCount"] = len(commits)
|
ctx.Data["CommitCount"] = len(commits)
|
||||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
processedCommits, err := processGitCommits(ctx, commits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("processGitCommits", err)
|
ctx.ServerError("processGitCommits", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ctx.Data["GroupCommits"] = GroupCommitsByDate(processedCommits)
|
||||||
|
|
||||||
ctx.Data["Keyword"] = query
|
ctx.Data["Keyword"] = query
|
||||||
if all {
|
if all {
|
||||||
@ -245,11 +250,12 @@ func FileHistory(ctx *context.Context) {
|
|||||||
ctx.ServerError("CommitsByFileAndRange", err)
|
ctx.ServerError("CommitsByFileAndRange", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
|
processedCommits, err := processGitCommits(ctx, commits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("processGitCommits", err)
|
ctx.ServerError("processGitCommits", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ctx.Data["GroupCommits"] = GroupCommitsByDate(processedCommits)
|
||||||
|
|
||||||
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
||||||
ctx.Data["Reponame"] = ctx.Repo.Repository.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
|
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)
|
ctx.ServerError("processGitCommits", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["GroupCommits"] = GroupCommitsByDate(commits)
|
||||||
ctx.Data["CommitCount"] = len(commits)
|
ctx.Data["CommitCount"] = len(commits)
|
||||||
|
|
||||||
title := ci.HeadBranch
|
title := ci.HeadBranch
|
||||||
|
@ -627,7 +627,7 @@ func ViewPullCommits(ctx *context.Context) {
|
|||||||
ctx.ServerError("processGitCommits", err)
|
ctx.ServerError("processGitCommits", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Commits"] = commits
|
ctx.Data["GroupCommits"] = GroupCommitsByDate(commits)
|
||||||
ctx.Data["CommitCount"] = len(commits)
|
ctx.Data["CommitCount"] = len(commits)
|
||||||
|
|
||||||
ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
|
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>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if and .Commits (gt .CommitCount 0)}}
|
{{if and .GroupCommits (gt .CommitCount 0)}}
|
||||||
{{template "repo/commits_list" .}}
|
{{template "repo/commits_list_group_by_date" .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{template "base/paginate" .}}
|
{{template "base/paginate" .}}
|
||||||
|
@ -707,7 +707,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) {
|
|||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
// Get first commit URL
|
// 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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
|||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
// Get first commit URL
|
// 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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
@ -87,12 +87,12 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
|||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
doc = NewHTMLParser(t, resp.Body)
|
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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
assert.Equal(t, commitID, path.Base(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.True(t, ok)
|
||||||
assert.Contains(t, cls, statesIcons[status])
|
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)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
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()))
|
assert.Equal(t, commit, strings.TrimSpace(sel.Text()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func TestRepoCommits(t *testing.T) {
|
|||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ func Test_ReposGitCommitListNotMaster(t *testing.T) {
|
|||||||
|
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
commits := []string{}
|
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")
|
commitURL, exists := s.Attr("href")
|
||||||
assert.True(t, exists)
|
assert.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
@ -63,7 +63,7 @@ func Test_ReposGitCommitListNotMaster(t *testing.T) {
|
|||||||
assert.Equal(t, "5099b81332712fe655e34e8dd63574f503f61811", commits[2])
|
assert.Equal(t, "5099b81332712fe655e34e8dd63574f503f61811", commits[2])
|
||||||
|
|
||||||
userNames := []string{}
|
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")
|
userPath, exists := s.Attr("href")
|
||||||
assert.True(t, exists)
|
assert.True(t, exists)
|
||||||
assert.NotEmpty(t, userPath)
|
assert.NotEmpty(t, userPath)
|
||||||
@ -87,7 +87,7 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
|||||||
|
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
// Get first commit URL
|
// 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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
|||||||
|
|
||||||
doc = NewHTMLParser(t, resp.Body)
|
doc = NewHTMLParser(t, resp.Body)
|
||||||
// Check if commit status is displayed in message column (.tippy-target to ignore the tippy trigger)
|
// 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())
|
assert.Equal(t, 1, sel.Length())
|
||||||
for _, class := range classes {
|
for _, class := range classes {
|
||||||
assert.True(t, sel.HasClass(class))
|
assert.True(t, sel.HasClass(class))
|
||||||
@ -181,7 +181,7 @@ func TestRepoCommitsStatusParallel(t *testing.T) {
|
|||||||
|
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
// Get first commit URL
|
// 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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
|
|||||||
|
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
// Get first commit URL
|
// 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.True(t, exists)
|
||||||
assert.NotEmpty(t, commitURL)
|
assert.NotEmpty(t, commitURL)
|
||||||
|
|
||||||
@ -241,6 +241,6 @@ func TestRepoCommitsStatusMultiple(t *testing.T) {
|
|||||||
|
|
||||||
doc = NewHTMLParser(t, resp.Body)
|
doc = NewHTMLParser(t, resp.Body)
|
||||||
// Check that the data-global-init="initCommitStatuses" (for trigger) and commit-status (svg) are present
|
// 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())
|
assert.Equal(t, 1, sel.Length())
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,9 @@ func TestCommitListActions(t *testing.T) {
|
|||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
AssertHTMLElement(t, htmlDoc, `.commit-list .copy-commit-id`, true)
|
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .copy-commit-id`, true)
|
||||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, false)
|
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-single-diff`, false)
|
||||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, true)
|
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-commit-path`, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("RepoFileHistory", func(t *testing.T) {
|
t.Run("RepoFileHistory", func(t *testing.T) {
|
||||||
@ -60,8 +60,8 @@ func TestCommitListActions(t *testing.T) {
|
|||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
|
|
||||||
AssertHTMLElement(t, htmlDoc, `.commit-list .copy-commit-id`, true)
|
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .copy-commit-id`, true)
|
||||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-single-diff`, true)
|
AssertHTMLElement(t, htmlDoc, `.timeline.commits-list-group-by-date .view-single-diff`, true)
|
||||||
AssertHTMLElement(t, htmlDoc, `.commit-list .view-commit-path`, 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 {
|
.branch-selector-dropdown .scrolling.menu .loading-indicator {
|
||||||
height: 4em;
|
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