commits = Commits | commits = Commits | ||||
releases = Releases | releases = Releases | ||||
commits.commits = Commits | |||||
commits.search = Search commits | |||||
commits.find = Find | |||||
commits.author = Author | |||||
commits.message = Message | |||||
commits.date = Date | |||||
commits.older = Older | |||||
commits.newer = Newer | |||||
settings = Settings | settings = Settings | ||||
settings.options = Options | settings.options = Options | ||||
settings.collaboration = Collaboration | settings.collaboration = Collaboration |
commits = 提交历史 | commits = 提交历史 | ||||
releases = 版本发布 | releases = 版本发布 | ||||
commits.commits = 次代码提交 | |||||
commits.search = 搜索提交历史 | |||||
commits.find = 查找 | |||||
commits.author = 作者 | |||||
commits.message = 备注 | |||||
commits.date = 提交日期 | |||||
commits.older = 更旧的提交 | |||||
commits.newer = 更新的提交 | |||||
settings = 仓库设置 | settings = 仓库设置 | ||||
settings.options = 基本设置 | settings.options = 基本设置 | ||||
settings.collaboration = 管理协作者 | settings.collaboration = 管理协作者 |
return repos, err | return repos, err | ||||
} | } | ||||
// __ __ __ .__ | |||||
// / \ / \_____ _/ |_ ____ | |__ | |||||
// \ \/\/ /\__ \\ __\/ ___\| | \ | |||||
// \ / / __ \| | \ \___| Y \ | |||||
// \__/\ / (____ /__| \___ >___| / | |||||
// \/ \/ \/ \/ | |||||
// Watch is connection request for receiving repository notifycation. | // Watch is connection request for receiving repository notifycation. | ||||
type Watch struct { | type Watch struct { | ||||
Id int64 | Id int64 | ||||
return nil | return nil | ||||
} | } | ||||
// _________ __ | |||||
// / _____// |______ _______ | |||||
// \_____ \\ __\__ \\_ __ \ | |||||
// / \| | / __ \| | \/ | |||||
// /_______ /|__| (____ /__| | |||||
// \/ \/ | |||||
type Star struct { | type Star struct { | ||||
Id int64 | Id int64 | ||||
Uid int64 `xorm:"UNIQUE(s)"` | Uid int64 `xorm:"UNIQUE(s)"` |
package models | package models | ||||
import ( | import ( | ||||
"container/list" | |||||
"crypto/sha256" | "crypto/sha256" | ||||
"encoding/hex" | "encoding/hex" | ||||
"errors" | "errors" | ||||
return ids | return ids | ||||
} | } | ||||
// UserCommit represtns a commit with validation of user. | |||||
type UserCommit struct { | |||||
UserName string | |||||
*git.Commit | |||||
} | |||||
// ValidCommitsWithEmails checks if authors' e-mails of commits are correcponding to users. | |||||
func ValidCommitsWithEmails(oldCommits *list.List) *list.List { | |||||
newCommits := list.New() | |||||
e := oldCommits.Front() | |||||
for e != nil { | |||||
c := e.Value.(*git.Commit) | |||||
uname := "" | |||||
u, err := GetUserByEmail(c.Author.Email) | |||||
if err == nil { | |||||
uname = u.Name | |||||
} | |||||
newCommits.PushBack(UserCommit{ | |||||
UserName: uname, | |||||
Commit: c, | |||||
}) | |||||
e = e.Next() | |||||
} | |||||
return newCommits | |||||
} | |||||
// GetUserByEmail returns the user object by given e-mail if exists. | // GetUserByEmail returns the user object by given e-mail if exists. | ||||
func GetUserByEmail(email string) (*User, error) { | func GetUserByEmail(email string) (*User, error) { | ||||
if len(email) == 0 { | if len(email) == 0 { |
height: 16px; | height: 16px; | ||||
vertical-align: middle; | vertical-align: middle; | ||||
} | } | ||||
img.avatar-20 { | |||||
width: 20px; | |||||
height: 20px; | |||||
vertical-align: middle; | |||||
} | |||||
img.avatar-24 { | img.avatar-24 { | ||||
width: 24px; | width: 24px; | ||||
height: 24px; | height: 24px; | ||||
width: 100%; | width: 100%; | ||||
list-style: none; | list-style: none; | ||||
} | } | ||||
#commits-list { | |||||
padding-top: 20px; | |||||
} | |||||
.commit-list th { | |||||
background-color: #FFF; | |||||
line-height: 28px !important; | |||||
} | |||||
.commit-list .date { | |||||
width: 120px; | |||||
} | |||||
.commit-list .author { | |||||
padding-left: 20px; | |||||
min-width: 180px; | |||||
} | |||||
.commit-list .author img { | |||||
margin-top: -4px; | |||||
} | |||||
.commit-list .sha a { | |||||
font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace; | |||||
font-size: 14px; | |||||
} | |||||
#admin-wrapper, | #admin-wrapper, | ||||
#setting-wrapper { | #setting-wrapper { | ||||
padding-bottom: 100px; | padding-bottom: 100px; |
.label-green { | .label-green { | ||||
background-color: #65ad4e; | background-color: #65ad4e; | ||||
} | } | ||||
.label-green:hover { | |||||
background-color: #71bf57; | |||||
color: #FFF; | |||||
} | |||||
.label-orange { | .label-orange { | ||||
background-color: #df7514; | background-color: #df7514; | ||||
} | } |
height: 16px; | height: 16px; | ||||
vertical-align: middle; | vertical-align: middle; | ||||
} | } | ||||
img.avatar-20 { | |||||
width: 20px; | |||||
height: 20px; | |||||
vertical-align: middle; | |||||
} | |||||
img.avatar-24 { | img.avatar-24 { | ||||
width: 24px; | width: 24px; | ||||
height: 24px; | height: 24px; |
/* repository main */ | /* repository main */ | ||||
#repo-wrapper { | #repo-wrapper { | ||||
padding-bottom: 100px; | |||||
padding-bottom: 100px; | |||||
} | } | ||||
#repo-header { | #repo-header { | ||||
height: 69px; | |||||
border-bottom: 1px solid@repoHeaderBorderColor; | |||||
background-color: @repoHeaderBgColor; | |||||
height: 69px; | |||||
border-bottom: 1px solid@repoHeaderBorderColor; | |||||
background-color: @repoHeaderBgColor; | |||||
} | } | ||||
#repo-header-name { | #repo-header-name { | ||||
line-height: 66px; | line-height: 66px; | ||||
.setting-list { | .setting-list { | ||||
width: 100%; | width: 100%; | ||||
list-style: none; | list-style: none; | ||||
} | |||||
#commits-list { | |||||
padding-top: 20px; | |||||
} | |||||
.commit-list { | |||||
th { | |||||
background-color: #FFF; | |||||
line-height: 28px !important; | |||||
} | |||||
.date { | |||||
width: 120px; | |||||
} | |||||
.author { | |||||
padding-left: 20px; | |||||
min-width: 180px; | |||||
img { | |||||
margin-top: -4px; | |||||
} | |||||
} | |||||
.sha a { | |||||
font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace; | |||||
font-size: 14px; | |||||
} | |||||
} | } |
.label-gray { | .label-gray { | ||||
background-color: @labelGrayColor; | background-color: @labelGrayColor; | ||||
} | } | ||||
.label-green { | .label-green { | ||||
background-color: @labelGreenColor; | |||||
background-color: @labelGreenColor; | |||||
&:hover { | |||||
background-color: @btnHoverGreenColor; | |||||
color: #FFF; | |||||
} | |||||
} | } | ||||
.label-orange { | .label-orange { | ||||
background-color: @labelOrangeColor; | background-color: @labelOrangeColor; | ||||
} | } |
} | } | ||||
// Both `git log branchName` and `git log commitId` work. | // Both `git log branchName` and `git log commitId` work. | ||||
ctx.Data["Commits"], err = ctx.Repo.Commit.CommitsByRange(page) | |||||
commits, err := ctx.Repo.Commit.CommitsByRange(page) | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "CommitsByRange", err) | ctx.Handle(500, "CommitsByRange", err) | ||||
return | return | ||||
} | } | ||||
commits = models.ValidCommitsWithEmails(commits) | |||||
ctx.Data["Commits"] = commits | |||||
ctx.Data["Username"] = userName | ctx.Data["Username"] = userName | ||||
ctx.Data["Reponame"] = repoName | ctx.Data["Reponame"] = repoName | ||||
ctx.Data["CommitCount"] = commitsCount | ctx.Data["CommitCount"] = commitsCount |
</table> | </table> | ||||
{{if or .LastPageNum .NextPageNum}} | {{if or .LastPageNum .NextPageNum}} | ||||
<ul class="pagination"> | <ul class="pagination"> | ||||
{{if .LastPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{AppSubUrl}}/admin/users?p={{.LastPageNum}}">« Prev.</a></li>{{end}} | |||||
{{if .NextPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{AppSubUrl}}/admin/users?p={{.NextPageNum}}">» Next</a></li>{{end}} | |||||
{{if .LastPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{AppSubUrl}}/admin/users?p={{.LastPageNum}}">« {{.i18n.Tr "admin.prev"}}</a></li>{{end}} | |||||
{{if .NextPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{AppSubUrl}}/admin/users?p={{.NextPageNum}}">» {{.i18n.Tr "admin.next"}}</a></li>{{end}} | |||||
</ul> | </ul> | ||||
{{end}} | {{end}} | ||||
</div> | </div> |
{{template "base/head" .}} | |||||
{{template "base/navbar" .}} | |||||
{{template "repo/nav" .}} | |||||
{{template "repo/toolbar" .}} | |||||
<div id="body" class="container"> | |||||
{{template "repo/commits_table" .}} | |||||
{{template "ng/base/head" .}} | |||||
{{template "ng/base/header" .}} | |||||
<div id="repo-wrapper"> | |||||
{{template "repo/header" .}} | |||||
<div class="container clear"> | |||||
{{template "repo/commits_table" .}} | |||||
</div> | |||||
</div> | </div> | ||||
{{template "base/footer" .}} | |||||
{{template "ng/base/footer" .}} |
<div id="commits"> | |||||
<div class="panel panel-default commit-box info-box"> | |||||
<div class="panel-heading info-head"> | |||||
<form class="search pull-right col-md-3" action="{{.RepoLink}}/commits/{{.BranchName}}/search" method="get" id="commits-search-form"> | |||||
<div class="input-group"> | |||||
<input class="form-control search" type="search" placeholder="search commit" name="q" value="{{.Keyword}}" /> | |||||
<div class="input-group-btn"> | |||||
<button type="submit" class="btn btn-default">Find</button> | |||||
</div> | |||||
</div> | |||||
<div id="commits-list"> | |||||
<div class="panel panel-radius"> | |||||
<div class="panel-header"> | |||||
<form class="search pull-right" action="{{.RepoLink}}/commits/{{.BranchName}}/search" method="get" id="commits-search-form"> | |||||
<input class="ipt ipt-radius" type="search" name="q" placeholder="{{.i18n.Tr "repo.commits.search"}}" value="{{.Keyword}}" /> | |||||
<button class="btn btn-black btn-small btn-radius">{{.i18n.Tr "repo.commits.find"}}</button> | |||||
</form> | </form> | ||||
<h4>{{.CommitCount}} Commits</h4> | |||||
<h4>{{.CommitCount}} {{.i18n.Tr "repo.commits.commits"}}</h4> | |||||
</div> | </div> | ||||
<table class="panel-footer table commit-list table table-striped"> | |||||
<table class="panel-body table commit-list table-striped"> | |||||
<thead> | <thead> | ||||
<tr> | <tr> | ||||
<th class="author">Author</th> | |||||
<th class="author">{{.i18n.Tr "repo.commits.author"}}</th> | |||||
<th class="sha">SHA1</th> | <th class="sha">SHA1</th> | ||||
<th class="message">Message</th> | |||||
<th class="date">Date</th> | |||||
<th class="message">{{.i18n.Tr "repo.commits.message"}}</th> | |||||
<th class="date">{{.i18n.Tr "repo.commits.date"}}</th> | |||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> | ||||
{{$r := List .Commits}} | {{$r := List .Commits}} | ||||
{{range $r}} | {{range $r}} | ||||
<tr> | <tr> | ||||
<td class="author"><img class="avatar" src="{{AvatarLink .Author.Email}}" alt=""/><a href="{{AppSubUrl}}/user/email2user?email={{.Author.Email}}">{{.Author.Name}}</a></td> | |||||
<td class="sha"><a rel="nofollow" class="label label-success" href="{{AppSubUrl}}/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td> | |||||
<td class="author"><img class="avatar-20" src="{{AvatarLink .Author.Email}}" alt=""/> {{if .UserName}}<a href="{{AppSubUrl}}/{{.UserName}}">{{.Author.Name}}</a>{{else}}{{.Author.Name}}{{end}}</td> | |||||
<td class="sha"><a rel="nofollow" class="label label-green" href="{{AppSubUrl}}/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td> | |||||
<td class="message">{{.Summary}} </td> | <td class="message">{{.Summary}} </td> | ||||
<td class="date">{{TimeSince .Author.When $.Lang}}</td> | <td class="date">{{TimeSince .Author.When $.Lang}}</td> | ||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
{{if not .IsSearchPage}}<ul class="pagination" id="commits-pager"> | |||||
{{if .LastPageNum}}<li><a href="{{.RepoLink}}/commits/{{.BranchName}}{{if .FileName}}/{{.FileName}}{{end}}?p={{.LastPageNum}}" rel="nofollow">« Newer</a></li>{{end}} | |||||
{{if .NextPageNum}}<li><a href="{{.RepoLink}}/commits/{{.BranchName}}{{if .FileName}}/{{.FileName}}{{end}}?p={{.NextPageNum}}" rel="nofollow">» Older</a></li>{{end}} | |||||
</ul>{{end}} | |||||
{{if not .IsSearchPage}} | |||||
<ul class="pagination"> | |||||
{{if .LastPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{.RepoLink}}/commits/{{.BranchName}}{{if .FileName}}/{{.FileName}}{{end}}?p={{.LastPageNum}}" rel="nofollow">« {{.i18n.Tr "repo.commits.newer"}}</a></li>{{end}} | |||||
{{if .NextPageNum}}<li><a class="btn btn-medium btn-gray btn-radius" href="{{.RepoLink}}/commits/{{.BranchName}}{{if .FileName}}/{{.FileName}}{{end}}?p={{.NextPageNum}}" rel="nofollow">» {{.i18n.Tr "repo.commits.older"}}</a></li>{{end}} | |||||
</ul> | |||||
{{end}} | |||||
</div> | </div> |