| @@ -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}} | ||||