@@ -13,6 +13,7 @@ import ( | |||||
type RepoKPIStats struct { | type RepoKPIStats struct { | ||||
Contributors int64 | Contributors int64 | ||||
KeyContributors int64 | KeyContributors int64 | ||||
DevelopAge int64 | |||||
ContributorsAdded int64 | ContributorsAdded int64 | ||||
CommitsAdded int64 | CommitsAdded int64 | ||||
CommitLinesModified int64 | CommitLinesModified int64 | ||||
@@ -66,6 +67,10 @@ func GetRepoKPIStats(repoPath string) (*RepoKPIStats, error) { | |||||
} | } | ||||
err = setDevelopAge(repoPath, stats) | |||||
if err != nil { | |||||
return nil, fmt.Errorf("FillFromGit: %v", err) | |||||
} | |||||
err = setRepoKPIStats(repoPath, fourMonthAgo, stats, newContributersDict) | err = setRepoKPIStats(repoPath, fourMonthAgo, stats, newContributersDict) | ||||
if err != nil { | if err != nil { | ||||
@@ -75,6 +80,27 @@ func GetRepoKPIStats(repoPath string) (*RepoKPIStats, error) { | |||||
} | } | ||||
func setDevelopAge(repoPath string, stats *RepoKPIStats) error { | |||||
args := []string{"log", "--no-merges", "--branches=*", "--format=%cd", "--date=short"} | |||||
stdout, err := NewCommand(args...).RunInDirBytes(repoPath) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
scanner := bufio.NewScanner(bytes.NewReader(stdout)) | |||||
scanner.Split(bufio.ScanLines) | |||||
developMonth := make(map[string]struct{}) | |||||
for scanner.Scan() { | |||||
l := strings.TrimSpace(scanner.Text()) | |||||
month := l[0:strings.LastIndex(l, "-")] | |||||
if _, ok := developMonth[month]; !ok { | |||||
developMonth[month] = struct{}{} | |||||
} | |||||
} | |||||
stats.DevelopAge = int64(len(developMonth)) | |||||
return nil | |||||
} | |||||
//获取一天内的用户贡献指标 | //获取一天内的用户贡献指标 | ||||
func GetUserKPIStats(repoPath string) (map[string]*UserKPIStats, error) { | func GetUserKPIStats(repoPath string) (map[string]*UserKPIStats, error) { | ||||
timeUntil := time.Now() | timeUntil := time.Now() | ||||
@@ -2,14 +2,24 @@ | |||||
<div class="repository labels"> | <div class="repository labels"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="navbar"> | |||||
{{template "repo/issue/navbar" .}} | |||||
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | |||||
<div class="ui right"> | |||||
<div class="ui green new-label button">{{.i18n.Tr "repo.issues.new_label"}}</div> | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
<div class="ui two column stackable grid"> | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
<div class="action section">{{.Title | RenderEmoji}}</div> | |||||
</div> | |||||
</div> | |||||
<div class="column right aligned"> | |||||
{{template "repo/issue/navbar" .}} | |||||
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | |||||
<div class="ui right"> | |||||
<div class="ui green new-label button">{{.i18n.Tr "repo.issues.new_label"}}</div> | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | {{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | ||||
{{template "repo/issue/labels/label_new" .}} | {{template "repo/issue/labels/label_new" .}} | ||||
@@ -3,14 +3,19 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="ui three column stackable grid"> | <div class="ui three column stackable grid"> | ||||
<div class="column"> | |||||
{{template "repo/issue/navbar" .}} | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
</div> | |||||
</div> | </div> | ||||
<div class="column center aligned"> | <div class="column center aligned"> | ||||
{{template "repo/issue/search" .}} | {{template "repo/issue/search" .}} | ||||
</div> | </div> | ||||
{{if not .Repository.IsArchived}} | {{if not .Repository.IsArchived}} | ||||
<div class="column right aligned"> | <div class="column right aligned"> | ||||
{{template "repo/issue/navbar" .}} | |||||
{{if .PageIsIssueList}} | {{if .PageIsIssueList}} | ||||
<a class="ui green button" href="{{.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a> | <a class="ui green button" href="{{.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a> | ||||
{{else}} | {{else}} | ||||
@@ -3,8 +3,14 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="ui three column stackable grid"> | <div class="ui three column stackable grid"> | ||||
<div class="column"> | |||||
<h3>{{.Milestone.Name}}</h3> | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
<a class="section" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | |||||
<div class="divider"> / </div> | |||||
<div class="action section">{{.Milestone.Name}}</div> | |||||
</div> | |||||
</div> | </div> | ||||
<div class="column center aligned"> | <div class="column center aligned"> | ||||
@@ -2,13 +2,29 @@ | |||||
<div class="repository new milestone"> | <div class="repository new milestone"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="navbar"> | |||||
{{template "repo/issue/navbar" .}} | |||||
{{if and (or .CanWriteIssues .CanWritePulls) .PageIsEditMilestone}} | |||||
<div class="ui right floated secondary menu"> | |||||
<a class="ui green button" href="{{$.RepoLink}}/milestones/new">{{.i18n.Tr "repo.milestones.new"}}</a> | |||||
<div class="ui two column stackable grid"> | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
<a class="section" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | |||||
<div class="divider"> / </div> | |||||
{{if .PageIsEditMilestone}} | |||||
<div class="action section">{{.i18n.Tr "repo.milestones.edit"}}</div> | |||||
{{else}} | |||||
<div class="action section">{{.i18n.Tr "repo.milestones.new"}}</div> | |||||
{{end}} | |||||
</div> | |||||
</div> | </div> | ||||
{{end}} | |||||
<div class="column right aligned"> | |||||
{{template "repo/issue/navbar" .}} | |||||
{{if and (or .CanWriteIssues .CanWritePulls) .PageIsEditMilestone}} | |||||
<div class="ui right floated secondary menu"> | |||||
<a class="ui green button" href="{{$.RepoLink}}/milestones/new">{{.i18n.Tr "repo.milestones.new"}}</a> | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
</div> | </div> | ||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
<h2 class="ui dividing header"> | <h2 class="ui dividing header"> | ||||
@@ -2,14 +2,25 @@ | |||||
<div class="repository milestones"> | <div class="repository milestones"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="navbar"> | |||||
{{template "repo/issue/navbar" .}} | |||||
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | |||||
<div class="ui right"> | |||||
<a class="ui green button" href="{{$.Link}}/new">{{.i18n.Tr "repo.milestones.new"}}</a> | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
<div class="ui two column stackable grid"> | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
<div class="action section">{{.Title | RenderEmoji}}</div> | |||||
</div> | |||||
</div> | |||||
{{if not .Repository.IsArchived}} | |||||
<div class="column right aligned"> | |||||
{{template "repo/issue/navbar" .}} | |||||
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | |||||
<div class="ui right"> | |||||
<a class="ui green button" href="{{$.Link}}/new">{{.i18n.Tr "repo.milestones.new"}}</a> | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<div class="ui tiny basic buttons"> | <div class="ui tiny basic buttons"> | ||||
@@ -1,4 +1,4 @@ | |||||
<div class="ui compact left small menu"> | |||||
<div class="ui compact small menu" style="margin-right: 1rem;"> | |||||
<a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.i18n.Tr "repo.labels"}}</a> | <a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.i18n.Tr "repo.labels"}}</a> | ||||
<a class="{{if .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | <a class="{{if .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | ||||
</div> | </div> |
@@ -2,9 +2,21 @@ | |||||
<div class="repository new issue"> | <div class="repository new issue"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="navbar"> | |||||
{{template "repo/issue/navbar" .}} | |||||
</div> | |||||
<div class="ui two column stackable grid"> | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
<div class="action section">{{.i18n.Tr "repo.issues.new"}}</div> | |||||
</div> | |||||
</div> | |||||
<div class="column right aligned"> | |||||
{{template "repo/issue/navbar" .}} | |||||
</div> | |||||
</div> | |||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
{{template "repo/issue/new_form" .}} | {{template "repo/issue/new_form" .}} | ||||
</div> | </div> | ||||
@@ -3,11 +3,16 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="ui two column stackable grid"> | <div class="ui two column stackable grid"> | ||||
<div class="column"> | |||||
{{template "repo/issue/navbar" .}} | |||||
<div class="column" style="display: flex;align-items: center;"> | |||||
<div class="ui large breadcrumb"> | |||||
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | |||||
<div class="divider"> / </div> | |||||
<div class="action section">{{.Title | RenderEmoji}}</div> | |||||
</div> | |||||
</div> | </div> | ||||
{{if not .Repository.IsArchived}} | {{if not .Repository.IsArchived}} | ||||
<div class="column right aligned"> | <div class="column right aligned"> | ||||
{{template "repo/issue/navbar" .}} | |||||
{{if .PageIsIssueList}} | {{if .PageIsIssueList}} | ||||
<a class="ui green button" href="{{.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a> | <a class="ui green button" href="{{.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a> | ||||
{{else}} | {{else}} | ||||