| @@ -65,6 +65,11 @@ type Cloudbrain struct { | |||
| Repo *Repository `xorm:"-"` | |||
| } | |||
| type CloudbrainInfo struct { | |||
| Cloudbrain `xorm:"extends"` | |||
| User `xorm:"extends"` | |||
| } | |||
| type CloudBrainLoginResult struct { | |||
| Code string | |||
| Msg string | |||
| @@ -523,7 +528,7 @@ type NotebookDelResult struct { | |||
| InstanceID string `json:"instance_id"` | |||
| } | |||
| func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) { | |||
| func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| @@ -583,8 +588,10 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) { | |||
| } | |||
| sess.OrderBy("cloudbrain.created_unix DESC") | |||
| cloudbrains := make([]*Cloudbrain, 0, setting.UI.IssuePagingNum) | |||
| if err := sess.Where(cond).Find(&cloudbrains); err != nil { | |||
| cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) | |||
| if err := sess.Table(&Cloudbrain{}).Where(cond). | |||
| Join("left", "`user`", "cloudbrain.user_id = `user`.id"). | |||
| Find(&cloudbrains); err != nil { | |||
| return nil, 0, fmt.Errorf("Find: %v", err) | |||
| } | |||
| sess.Close() | |||
| @@ -13,6 +13,7 @@ import ( | |||
| type RepoKPIStats struct { | |||
| Contributors int64 | |||
| KeyContributors int64 | |||
| DevelopAge int64 | |||
| ContributorsAdded int64 | |||
| CommitsAdded 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) | |||
| 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) { | |||
| timeUntil := time.Now() | |||
| @@ -573,7 +573,7 @@ authorized_oauth2_applications_description = You've granted access to your perso | |||
| revoke_key = Revoke | |||
| revoke_oauth2_grant = Revoke Access | |||
| revoke_oauth2_grant_description = Revoking access for this third party application will prevent this application from accessing your data. Are you sure? | |||
| revoke_oauth2_grant_success = You've revoked access successfully. | |||
| revoke_oauth2_grant_success = You have revoked access successfully. | |||
| twofa_desc = Two-factor authentication enhances the security of your account. | |||
| twofa_is_enrolled = Your account is currently <strong>enrolled</strong> in two-factor authentication. | |||
| @@ -770,6 +770,7 @@ cloudbrain_selection = select cloudbrain | |||
| cloudbrain_platform_selection = Select the cloudbrain platform you want to use: | |||
| confirm_choice = confirm | |||
| cloudbran1_tips = Only data in zip format can create cloudbrain tasks | |||
| cloudbrain_creator=Creator | |||
| template.items = Template Items | |||
| template.git_content = Git Content (Default Branch) | |||
| @@ -772,6 +772,7 @@ cloudbrain_selection=云脑选择 | |||
| cloudbrain_platform_selection=选择您准备使用的云脑平台: | |||
| confirm_choice=确定 | |||
| cloudbran1_tips=只有zip格式的数据集才能发起云脑任务 | |||
| cloudbrain_creator=创建者 | |||
| template.items=模板选项 | |||
| template.git_content=Git数据(默认分支) | |||
| @@ -69,7 +69,8 @@ func CloudBrainIndex(ctx *context.Context) { | |||
| timestamp := time.Now().Unix() | |||
| for i, task := range ciTasks { | |||
| if task.Status == string(models.JobRunning) && (timestamp-int64(task.CreatedUnix) > 10) { | |||
| log.Info("", task.User.Name) | |||
| if task.Status == string(models.JobRunning) && (timestamp-int64(task.Cloudbrain.CreatedUnix) > 10) { | |||
| ciTasks[i].CanDebug = true | |||
| } else { | |||
| ciTasks[i].CanDebug = false | |||
| @@ -1,12 +1,12 @@ | |||
| <div class="repos--seach"> | |||
| <div class="ui container"> | |||
| <div class="ui two column centered grid"> | |||
| <form class="mobile ten wide tablet computer column ui form ignore-dirty"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty"> | |||
| <div class="ui fluid action input"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <input type="hidden" name="sort" value="{{$.SortType}}"> | |||
| <button class="ui blue button">{{.i18n.Tr "explore.search"}}</button> | |||
| <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| @@ -1,11 +1,11 @@ | |||
| <div class="repos--seach"> | |||
| <div class="ui container"> | |||
| <div class="ui two column centered grid"> | |||
| <form class="sixteen wide mobile eight fourteen tablet fourteen wide computer column ui form ignore-dirty"> | |||
| <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty"> | |||
| <div class="ui fluid action input"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | |||
| <input type="hidden" name="tab" value="{{$.TabName}}"> | |||
| <button class="ui blue button">{{.i18n.Tr "explore.search"}}</button> | |||
| <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> | |||
| </div> | |||
| </form> | |||
| </div> | |||
| @@ -262,10 +262,10 @@ | |||
| <div class="row"> | |||
| <!-- 任务名 --> | |||
| <div class="six wide column"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}"> | |||
| <div class="five wide column"> | |||
| <a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}"> | |||
| <span class="fitted">{{svg "octicon-tasklist" 16}}</span> | |||
| <span class="fitted">{{.JobName}}</span> | |||
| <span class="fitted text_over" style="width: 90%;">{{.JobName}}</span> | |||
| </a> | |||
| </div> | |||
| @@ -285,10 +285,14 @@ | |||
| {{end}} | |||
| <!-- 任务创建时间 --> | |||
| <span class="time-show">{{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||
| <span class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span> | |||
| </div> | |||
| <div class="seven wide column text right"> | |||
| <div class="two wide column"> | |||
| <span style="display: block;">{{$.i18n.Tr "repo.cloudbrain_creator"}}</span><span class="text_over" title="{{.User.Name}}">{{.User.Name}}</span> | |||
| </div> | |||
| <div class="six wide column text right"> | |||
| <div class="ui compact buttons" style="margin-right:10px;"> | |||
| {{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}} | |||
| <a class="ui basic button" href="{{$.Link}}/{{.JobID}}/rate" target="_blank"> | |||
| @@ -37,7 +37,7 @@ | |||
| </div> | |||
| {{if .Permission.CanWrite $.UnitTypeDatasets}} | |||
| <div class="column four wide right aligned"> | |||
| <a class="ui button primary" href="javascript:void(0)" id="dataset-edit"> | |||
| <a class="ui green button" href="javascript:void(0)" id="dataset-edit"> | |||
| {{.i18n.Tr "dataset.edit"}} | |||
| </a> | |||
| </div> | |||
| @@ -66,7 +66,7 @@ | |||
| <input name="type" value="{{.Type}}" type="hidden" /> | |||
| <div class="sixteen wide column"> | |||
| <a class="ui button" id="cancel">{{.i18n.Tr "cancel"}}</a> | |||
| <button class="ui primary button" id="submit">{{.i18n.Tr "dataset.update_dataset"}}</button> | |||
| <button class="ui green button" id="submit">{{.i18n.Tr "dataset.update_dataset"}}</button> | |||
| </div> | |||
| </div> | |||
| @@ -2,14 +2,24 @@ | |||
| <div class="repository labels"> | |||
| {{template "repo/header" .}} | |||
| <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> | |||
| {{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}} | |||
| {{template "repo/issue/labels/label_new" .}} | |||
| @@ -3,14 +3,19 @@ | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <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 class="column center aligned"> | |||
| {{template "repo/issue/search" .}} | |||
| </div> | |||
| {{if not .Repository.IsArchived}} | |||
| <div class="column right aligned"> | |||
| {{template "repo/issue/navbar" .}} | |||
| {{if .PageIsIssueList}} | |||
| <a class="ui green button" href="{{.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a> | |||
| {{else}} | |||
| @@ -3,8 +3,14 @@ | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <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 class="column center aligned"> | |||
| @@ -2,13 +2,29 @@ | |||
| <div class="repository new milestone"> | |||
| {{template "repo/header" .}} | |||
| <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> | |||
| {{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 class="ui divider"></div> | |||
| <h2 class="ui dividing header"> | |||
| @@ -2,14 +2,25 @@ | |||
| <div class="repository milestones"> | |||
| {{template "repo/header" .}} | |||
| <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> | |||
| {{template "base/alert" .}} | |||
| <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 .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | |||
| </div> | |||
| @@ -2,9 +2,21 @@ | |||
| <div class="repository new issue"> | |||
| {{template "repo/header" .}} | |||
| <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> | |||
| {{template "repo/issue/new_form" .}} | |||
| </div> | |||
| @@ -7,7 +7,7 @@ | |||
| <input type="hidden" name="assignee" value="{{$.AssigneeID}}"/> | |||
| <div class="ui search action input"> | |||
| <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | |||
| <button class="ui blue button" type="submit">{{.i18n.Tr "explore.search"}}</button> | |||
| <button class="ui green button" type="submit">{{.i18n.Tr "explore.search"}}</button> | |||
| </div> | |||
| </div> | |||
| </form> | |||
| @@ -3,11 +3,16 @@ | |||
| {{template "repo/header" .}} | |||
| <div class="ui container"> | |||
| <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> | |||
| {{if not .Repository.IsArchived}} | |||
| <div class="column right aligned"> | |||
| {{template "repo/issue/navbar" .}} | |||
| {{if .PageIsIssueList}} | |||
| <a class="ui green button" href="{{.RepoLink}}/issues/new">{{.i18n.Tr "repo.issues.new"}}</a> | |||
| {{else}} | |||
| @@ -262,7 +262,7 @@ | |||
| {{.Status}} | |||
| </span> | |||
| <!-- 任务创建时间 --> | |||
| <span class="">{{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||
| <span class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span> | |||
| </div> | |||
| <div class="seven wide column text right"> | |||
| @@ -74,7 +74,7 @@ | |||
| <input type="hidden" name="state" value="{{$.State}}"/> | |||
| <div class="ui search action input"> | |||
| <input name="q" value="{{$.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | |||
| <button class="ui blue button" type="submit">{{.i18n.Tr "explore.search"}}</button> | |||
| <button class="ui green button" type="submit">{{.i18n.Tr "explore.search"}}</button> | |||
| </div> | |||
| </div> | |||
| </form> | |||
| @@ -232,4 +232,13 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;} | |||
| .i-bg-used{background-position: -514px -52px;} | |||
| .icon-bind{background-position: -550px -52px;} | |||
| .icon-unbind{background-position: -568px -52px;} | |||
| .showCircle{display:inline-block;background-image:url('/img/loading.gif');background-repeat:no-repeat;width:16px;height:16px;background-size:16px 16px;margin-right:5px;} | |||
| .showCircle{display:inline-block;background-image:url('/img/loading.gif');background-repeat:no-repeat;width:16px;height:16px;background-size:16px 16px;margin-right:5px;} | |||
| .text_over{ | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| -o-text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| display: inline-block; | |||
| width: 100%; | |||
| } | |||