Browse Source

Merge branch 'V20211018' of git.openi.org.cn:OpenI/aiforge into repo-statistic

pull/541/head
lewis 3 years ago
parent
commit
2f896cdc93
22 changed files with 649 additions and 109 deletions
  1. +1
    -0
      go.mod
  2. +25
    -2
      models/cloudbrain.go
  3. +14
    -0
      models/repo_list.go
  4. +312
    -0
      modules/repository/elk_pagedata.go
  5. +16
    -0
      modules/setting/setting.go
  6. +10
    -1
      options/locale/locale_en-US.ini
  7. +9
    -0
      options/locale/locale_zh-CN.ini
  8. +4
    -3
      routers/home.go
  9. +2
    -1
      routers/repo/cloudbrain.go
  10. +38
    -0
      routers/repo/view.go
  11. +11
    -11
      templates/explore/repo_left.tmpl
  12. +14
    -14
      templates/explore/repo_list.tmpl
  13. +1
    -1
      templates/explore/repo_search.tmpl
  14. +57
    -26
      templates/repo/cloudbrain/index.tmpl
  15. +15
    -0
      templates/repo/home.tmpl
  16. +1
    -6
      templates/repo/issue/list.tmpl
  17. +9
    -1
      templates/repo/issue/view.tmpl
  18. +40
    -10
      templates/repo/modelarts/index.tmpl
  19. +15
    -1
      templates/repo/pulls/commits.tmpl
  20. +15
    -1
      templates/repo/pulls/files.tmpl
  21. +36
    -27
      web_src/js/components/EditTopics.vue
  22. +4
    -4
      web_src/less/openi.less

+ 1
- 0
go.mod View File

@@ -52,6 +52,7 @@ require (
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28 github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/golang/protobuf v1.4.1 // indirect github.com/golang/protobuf v1.4.1 // indirect
github.com/gomodule/redigo v2.0.0+incompatible
github.com/google/go-github/v24 v24.0.1 github.com/google/go-github/v24 v24.0.1
github.com/gorilla/context v1.1.1 github.com/gorilla/context v1.1.1
github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/hashicorp/go-retryablehttp v0.6.6 // indirect


+ 25
- 2
models/cloudbrain.go View File

@@ -5,11 +5,12 @@ import (
"fmt" "fmt"
"strings" "strings"
"time" "time"
"xorm.io/builder"
"xorm.io/xorm" "xorm.io/xorm"


"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"xorm.io/builder"
) )


type CloudbrainStatus string type CloudbrainStatus string
@@ -59,6 +60,7 @@ type Cloudbrain struct {
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
DeletedAt time.Time `xorm:"deleted"` DeletedAt time.Time `xorm:"deleted"`
CanDebug bool `xorm:"-"` CanDebug bool `xorm:"-"`
CanDel bool `xorm:"-"`
Type int `xorm:"INDEX DEFAULT 0"` Type int `xorm:"INDEX DEFAULT 0"`


User *User `xorm:"-"` User *User `xorm:"-"`
@@ -67,7 +69,7 @@ type Cloudbrain struct {


type CloudbrainInfo struct { type CloudbrainInfo struct {
Cloudbrain `xorm:"extends"` Cloudbrain `xorm:"extends"`
User `xorm:"extends"`
User `xorm:"extends"`
} }


type CloudBrainLoginResult struct { type CloudBrainLoginResult struct {
@@ -669,3 +671,24 @@ func GetCloudbrainByName(jobName string) (*Cloudbrain, error) {
cb := &Cloudbrain{JobName: jobName} cb := &Cloudbrain{JobName: jobName}
return getRepoCloudBrain(cb) return getRepoCloudBrain(cb)
} }

func CanDelJob(isSigned bool, user *User, job *CloudbrainInfo) bool {
if !isSigned || job.Status != string(JobStopped) {
return false
}
repo, err := GetRepositoryByID(job.RepoID)
if err != nil {
log.Error("GetRepositoryByID failed:%v", err.Error())
return false
}
permission, _ := GetUserRepoPermission(repo, user)
if err != nil {
log.Error("GetUserRepoPermission failed:%v", err.Error())
return false
}

if user.ID == job.UserID || user.IsAdmin || permission.AccessMode >= AccessModeAdmin {
return true
}
return false
}

+ 14
- 0
models/repo_list.go View File

@@ -166,6 +166,8 @@ type SearchRepoOptions struct {
Archived util.OptionalBool Archived util.OptionalBool
// only search topic name // only search topic name
TopicOnly bool TopicOnly bool
//search by Specific TopicName
TopicName string
// include description in keyword search // include description in keyword search
IncludeDescription bool IncludeDescription bool
// None -> include has milestones AND has no milestone // None -> include has milestones AND has no milestone
@@ -327,6 +329,18 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
} }
cond = cond.And(keywordCond) cond = cond.And(keywordCond)
} }
if opts.TopicName != "" {
var subQueryCond = builder.NewCond()
subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": opts.TopicName})
subQuery := builder.Select("repo_topic.repo_id").From("repo_topic").
Join("INNER", "topic", "topic.id = repo_topic.topic_id").
Where(subQueryCond).
GroupBy("repo_topic.repo_id")

var topicNameCond = builder.In("id", subQuery)
cond = cond.And(topicNameCond)

}


if opts.Fork != util.OptionalBoolNone { if opts.Fork != util.OptionalBoolNone {
cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue}) cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue})


+ 312
- 0
modules/repository/elk_pagedata.go View File

@@ -0,0 +1,312 @@
package repository

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

"code.gitea.io/gitea/modules/setting"
)

//输入elk的json结构begin
type InputInfo struct {
Batch []Batch `json:"batch"`
}
type Fields struct {
Field string `json:"field"`
Format string `json:"format"`
}
type MatchPhrase struct {
Message string `json:"message"`
}
type Should struct {
MatchPhrase MatchPhrase `json:"match_phrase"`
}
type Bool struct {
Should []Should `json:"should"`
MinimumShouldMatch int `json:"minimum_should_match"`
}
type Timestamptest struct {
// Gte time.Time `json:"gte"`
Gte string `json:"gte"`
Lte string `json:"lte"`
Format string `json:"format"`
}
type Range struct {
Timestamptest Timestamptest `json:"@timestamptest"`
}

type FilterMatchPhrase struct {
UserName string `json:"userName.keyword,omitempty"`
ProjectName string `json:"projectName.keyword,omitempty"`
TagName string `json:"tagName.keyword,omitempty"`
}

type Filter struct {
Bool *Bool `json:"bool,omitempty"`
Range *Range `json:"range,omitempty"`
FilterMatchPhrase *FilterMatchPhrase `json:"match_phrase,omitempty"`
}
type MustNotMatchPhrase struct {
ProjectName string `json:"projectName"`
}
type MustNot struct {
MustNotMatchPhrase MustNotMatchPhrase `json:"match_phrase"`
}
type BoolIn struct {
Filter []Filter `json:"filter"`
MustNot []MustNot `json:"must_not"`
}
type Query struct {
BoolIn BoolIn `json:"bool"`
}
type Body struct {
Size int `json:"size"`
Fields []Fields `json:"fields"`
Query Query `json:"query"`
}
type Params struct {
Index string `json:"index"`
Body Body `json:"body"`
}
type Request struct {
Params Params `json:"params"`
}
type Batch struct {
Request Request `json:"request"`
}

//输入elk的json结构end

//elk输出的json结构begin
type Hits struct {
Total int `json:"total"`
}
type RawResponse struct {
Hits Hits `json:"hits"`
}
type Result struct {
RawResponse RawResponse `json:"rawResponse"`
Loaded int `json:"loaded"`
}
type ResultInfo struct {
Id int `json:"id"`
Result Result `json:"result"`
}

//elk输出的json结构end

//发送post请求到elk
func SendReqToElk(jsonStr []byte) (content string) {
ElkBase64Init := setting.ElkUser + ":" + setting.ElkPassword
ElkBase64 := base64.StdEncoding.EncodeToString([]byte(ElkBase64Init))
BasicElkBase64 := "Basic" + " " + ElkBase64
url := setting.ElkUrl
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("kbn-version", "7.13.2")
req.Header.Set("Authorization", BasicElkBase64)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
return string(body)
}

//处理返回的elk数据,只保留totalView,即访问量;loaded是分片载入次数,用来判断返回的数据是否准确
func GetResultFromElk(resultinfo ResultInfo, jobResult string) (loaded int, totalView int) {
var resultTest ResultInfo
errs := json.Unmarshal([]byte(jobResult), &resultTest)
fmt.Println(errs)
return resultTest.Result.Loaded, resultTest.Result.RawResponse.Hits.Total
}

//初始化传给elk的数据结构,给定用户名和项目名,查询的起止时间,返回初始化后的结构
func ProjectViewInit(User string, Project string, Gte string, Lte string) (projectViewInit InputInfo) {
var inputStruct InputInfo
inputStruct.Batch = make([]Batch, 1)
inputStruct.Batch[0].Request.Params.Index = setting.Index
inputStruct.Batch[0].Request.Params.Body.Size = 0
inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1)
inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField
inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 3)
//限定查询时间
var timeRange Range
timeRange.Timestamptest.Gte = Gte
timeRange.Timestamptest.Lte = Lte
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[0].Range = &timeRange
//限定用户
var userName FilterMatchPhrase
userName.UserName = User
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[1].FilterMatchPhrase = &userName
//限定项目
var projectName FilterMatchPhrase
projectName.ProjectName = Project
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[2].FilterMatchPhrase = &projectName
return inputStruct
}

//初始化传给elk的数据结构,给定查询信息和非项目名,查询的起止时间,返回初始化后的结构
func AllProjectViewInit(MessageInfo string, NotProject string, Gte string, Lte string) (allProjectViewInit InputInfo) {
var inputStruct InputInfo
inputStruct.Batch = make([]Batch, 1)
inputStruct.Batch[0].Request.Params.Index = setting.Index
inputStruct.Batch[0].Request.Params.Body.Size = 0
inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1)
inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField
inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 2)
//限定message
var bool Bool
bool.Should = make([]Should, 1)
bool.Should[0].MatchPhrase.Message = MessageInfo
bool.MinimumShouldMatch = 1
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[0].Bool = &bool
//限定查询时间
var timeRange Range
timeRange.Timestamptest.Gte = Gte
timeRange.Timestamptest.Lte = Lte
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[1].Range = &timeRange
//限定非项目
// var boolIn BoolIn
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.MustNot = make([]MustNot, 1)
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.MustNot[0].MustNotMatchPhrase.ProjectName = NotProject
return inputStruct
}

//初始化传给elk的数据结构,给定查询信息和tagName,查询的起止时间,返回初始化后的结构
func TagNameInit(MessageInfo string, Tagname string, Gte string, Lte string) (projectViewInit InputInfo) {
var inputStruct InputInfo
inputStruct.Batch = make([]Batch, 1)
inputStruct.Batch[0].Request.Params.Index = setting.Index
inputStruct.Batch[0].Request.Params.Body.Size = 0
inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1)
inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField
inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 3)
//限定message
var bool Bool
bool.Should = make([]Should, 1)
bool.Should[0].MatchPhrase.Message = MessageInfo
bool.MinimumShouldMatch = 1
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[0].Bool = &bool
//限定tagName
var tagName FilterMatchPhrase
tagName.TagName = Tagname
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[1].FilterMatchPhrase = &tagName
//限定查询时间
var timeRange Range
timeRange.Timestamptest.Gte = Gte
timeRange.Timestamptest.Lte = Lte
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[2].Range = &timeRange
return inputStruct
}

//向elk发送请求,将获取的结果只保留访问量,输入是初始化后的数据结构,返回访问量
func ViewInfo(viewInfo InputInfo) (totalView int) {
jsons, errs := json.Marshal(viewInfo)
if errs != nil {
fmt.Println("errs:", errs.Error())
}
// fmt.Println("viewInfoInit:",string(jsons))
var jsonStr = []byte(jsons)
var resultInfo ResultInfo
loaded, totalView := GetResultFromElk(resultInfo, SendReqToElk(jsonStr))
time := 0
for {
if loaded == 0 {
loaded_next, totalView := GetResultFromElk(resultInfo, SendReqToElk(jsonStr))
time++
if loaded_next != 0 && time < 100 {
fmt.Println("totalView:", totalView)
return totalView
}
if time > 100 {
break
}
} else {
break
}
}
fmt.Println("loaded:", loaded)
return totalView
}

// @title ProjectView
// @description 获取指定用户和项目的访问量
// @param User string "用户名"
// @param Project string "项目名"
// @param Gte string "起始时间" 如time.Now().AddDate(0, 0, -1).Format(time.RFC3339)
// @param Lte string "结束时间" 如time.Now().Format(time.RFC3339)
// @return totalView int "访问量"
func AppointProjectView(User string, Project string, Gte string, Lte string) (totalView int) {
InitInfo := ProjectViewInit(User, Project, Gte, Lte)
return ViewInfo(InitInfo)
}

//统计项目相关页面的访问量
type ProjectInfo struct {
/* 统计所有项目中该页面的浏览情况,不需要区分项目。以aiforge项目为例 */
//地址:https://git.openi.org.cn/OpenI/aiforge/datasets?type=0
Project_dataset_type_0 int
//地址:https://git.openi.org.cn/OpenI/aiforge/datasets?type=1
Project_dataset_type_1 int
//地址:https://git.openi.org.cn/OpenI/aiforge/issues
Project_issues int
//地址:https://git.openi.org.cn/OpenI/aiforge/labels
Project_labels int
//地址:https://git.openi.org.cn/OpenI/aiforge/milestones
Project_milestones int
//地址:https://git.openi.org.cn/OpenI/aiforge/pulls
Project_pulls int
//地址:https://git.openi.org.cn/OpenI/aiforge/release
Project_release int
//地址:https://git.openi.org.cn/OpenI/aiforge/wiki
Project_wiki int
//地址:https://git.openi.org.cn/OpenI/aiforge/activity
Project_activity int
//地址:https://git.openi.org.cn/OpenI/aiforge/cloudbrain
Project_cloudbrain int
//地址:https://git.openi.org.cn/OpenI/aiforge/modelarts
Project_modelarts int
//地址:https://git.openi.org.cn/OpenI/aiforge/blockchain
Project_blockchain int
//地址:https://git.openi.org.cn/OpenI/aiforge/watchers
Project_watchers int
//地址:https://git.openi.org.cn/OpenI/aiforge/stars
Project_stars int
//地址:https://git.openi.org.cn/OpenI/aiforge/forks
Project_forks int
}

// @title AllProjectView
// @description 获取指定用户和项目的访问量
// @param Gte string "起始时间" 如time.Now().AddDate(0, 0, -1).Format(time.RFC3339)
// @param Lte string "结束时间"
// @return projectInfo ProjectInfo "统计所有项目中页面的浏览情况,不需要区分项目"
func AllProjectView(Gte string, Lte string) (projectInfo ProjectInfo) {
projectInfo.Project_dataset_type_0 = ViewInfo(AllProjectViewInit("/datasets?type=0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_dataset_type_1 = ViewInfo(AllProjectViewInit("/datasets?type=1", "%{[request][2]}", Gte, Lte))
projectInfo.Project_issues = ViewInfo(AllProjectViewInit("/issues HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_labels = ViewInfo(TagNameInit("/labels HTTP/2.0", "labels", Gte, Lte))
projectInfo.Project_milestones = ViewInfo(AllProjectViewInit("/milestones HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_pulls = ViewInfo(AllProjectViewInit("/pulls HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_release = ViewInfo(AllProjectViewInit("/release HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_wiki = ViewInfo(AllProjectViewInit("/wiki HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_activity = ViewInfo(AllProjectViewInit("/activity HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_cloudbrain = ViewInfo(AllProjectViewInit("/cloudbrain HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_modelarts = ViewInfo(AllProjectViewInit("/modelarts HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_blockchain = ViewInfo(AllProjectViewInit("/blockchain HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_watchers = ViewInfo(AllProjectViewInit("/watchers HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_stars = ViewInfo(AllProjectViewInit("/stars HTTP/2.0", "%{[request][2]}", Gte, Lte))
projectInfo.Project_forks = ViewInfo(AllProjectViewInit("/forks HTTP/2.0", "%{[request][2]}", Gte, Lte))
return projectInfo
}

+ 16
- 0
modules/setting/setting.go View File

@@ -482,6 +482,14 @@ var (
PoolInfos string PoolInfos string
Flavor string Flavor string
FlavorInfos string FlavorInfos string

//elk config
ElkUrl string
ElkUser string
ElkPassword string
Index string
TimeField string
ElkTimeFormat string
) )


// DateLang transforms standard language locale name to corresponding value in datetime plugin. // DateLang transforms standard language locale name to corresponding value in datetime plugin.
@@ -1201,6 +1209,14 @@ func NewContext() {
PoolInfos = sec.Key("POOL_INFOS").MustString("") PoolInfos = sec.Key("POOL_INFOS").MustString("")
Flavor = sec.Key("FLAVOR").MustString("") Flavor = sec.Key("FLAVOR").MustString("")
FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("") FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("")

sec = Cfg.Section("elk")
ElkUrl = sec.Key("ELKURL").MustString("http://192.168.207.35:5601/internal/bsearch")
ElkUser = sec.Key("ELKUSER").MustString("Qizhi")
ElkPassword = sec.Key("ELKPASSWORD").MustString("Pcl2020")
Index = sec.Key("INDEX").MustString("filebeat-7.3.2*")
TimeField = sec.Key("TIMEFIELD").MustString(" @timestamptest")
ElkTimeFormat = sec.Key("ELKTIMEFORMAT").MustString("date_time")
} }


func loadInternalToken(sec *ini.Section) string { func loadInternalToken(sec *ini.Section) string {


+ 10
- 1
options/locale/locale_en-US.ini View File

@@ -87,7 +87,7 @@ write = Write
preview = Preview preview = Preview
loading = Loading… loading = Loading…


error404_index = Request forbidden by administrative rules
error404_index = Request forbidden by administrative rules
error500_index = Internal Server Error error500_index = Internal Server Error
error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it. error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.
error500= Sorry, the site has encountered some problems, we are trying to <strong>fix the page</strong>, please try again later. error500= Sorry, the site has encountered some problems, we are trying to <strong>fix the page</strong>, please try again later.
@@ -771,6 +771,9 @@ cloudbrain_platform_selection = Select the cloudbrain platform you want to use:
confirm_choice = confirm confirm_choice = confirm
cloudbran1_tips = Only data in zip format can create cloudbrain tasks cloudbran1_tips = Only data in zip format can create cloudbrain tasks
cloudbrain_creator=Creator cloudbrain_creator=Creator
cloudbrain_task = Task Name
cloudbrain_operate = Operate
cloudbrain_status_createtime = Status/Createtime


template.items = Template Items template.items = Template Items
template.git_content = Git Content (Default Branch) template.git_content = Git Content (Default Branch)
@@ -847,6 +850,7 @@ filter_branch_and_tag = Filter branch or tag
branches = Branches branches = Branches
tags = Tags tags = Tags
issues = Issues issues = Issues
issues_detail = Detail
pulls = Pull Requests pulls = Pull Requests
labels = Labels labels = Labels
org_labels_desc = Organization level labels that can be used with <strong>all repositories</strong> under this organization org_labels_desc = Organization level labels that can be used with <strong>all repositories</strong> under this organization
@@ -1243,6 +1247,11 @@ pulls.reject_count_1 = "%d change request"
pulls.reject_count_n = "%d change requests" pulls.reject_count_n = "%d change requests"
pulls.waiting_count_1 = "%d waiting review" pulls.waiting_count_1 = "%d waiting review"
pulls.waiting_count_n = "%d waiting reviews" pulls.waiting_count_n = "%d waiting reviews"
pulls.commits_count_1=This branch is %d commit behind the upstream.
pulls.commits_count_n=This branch is %d commit behind the upstream.
pulls.fetch_upstream=Fetch upstream
pulls.upstream_up_to_date=No new commits to fetch
pulls.upstream_error=Cannot get upstream info


pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled. pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled.
pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually. pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually.


+ 9
- 0
options/locale/locale_zh-CN.ini View File

@@ -773,6 +773,9 @@ cloudbrain_platform_selection=选择您准备使用的云脑平台:
confirm_choice=确定 confirm_choice=确定
cloudbran1_tips=只有zip格式的数据集才能发起云脑任务 cloudbran1_tips=只有zip格式的数据集才能发起云脑任务
cloudbrain_creator=创建者 cloudbrain_creator=创建者
cloudbrain_task=任务名称
cloudbrain_operate=操作
cloudbrain_status_createtime=状态/创建时间


template.items=模板选项 template.items=模板选项
template.git_content=Git数据(默认分支) template.git_content=Git数据(默认分支)
@@ -849,6 +852,7 @@ filter_branch_and_tag=过滤分支或标签
branches=分支列表 branches=分支列表
tags=标签列表 tags=标签列表
issues=任务 issues=任务
issues_detail=详情
pulls=合并请求 pulls=合并请求
labels=标签 labels=标签
org_labels_desc=组织级别的标签,可以被本组织下的 <strong>所有项目</strong> 使用 org_labels_desc=组织级别的标签,可以被本组织下的 <strong>所有项目</strong> 使用
@@ -1245,6 +1249,11 @@ pulls.reject_count_1=%d 变更请求
pulls.reject_count_n=%d 变更请求 pulls.reject_count_n=%d 变更请求
pulls.waiting_count_1=%d 个正在等待审核 pulls.waiting_count_1=%d 个正在等待审核
pulls.waiting_count_n=%d 个正在等待审核 pulls.waiting_count_n=%d 个正在等待审核
pulls.commits_count_1=当前分支落后上游分支 %d 个提交
pulls.commits_count_n=当前分支落后上游分支 %d 个提交
pulls.fetch_upstream=拉取上游更新
pulls.upstream_up_to_date=上游分支没有新的更新
pulls.upstream_error=获取上游分支信息错误


pulls.no_merge_desc=由于未启用合并选项,此合并请求无法被合并。 pulls.no_merge_desc=由于未启用合并选项,此合并请求无法被合并。
pulls.no_merge_helper=在项目设置中启用合并选项或者手工合并请求。 pulls.no_merge_helper=在项目设置中启用合并选项或者手工合并请求。


+ 4
- 3
routers/home.go View File

@@ -149,8 +149,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {


//todo:support other topics //todo:support other topics
keyword := strings.Trim(ctx.Query("q"), " ") keyword := strings.Trim(ctx.Query("q"), " ")
topicOnly := ctx.QueryBool("topic")
ctx.Data["TopicOnly"] = topicOnly
topic := strings.Trim(ctx.Query("topic"), " ")


repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
ListOptions: models.ListOptions{ ListOptions: models.ListOptions{
@@ -164,7 +163,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
OwnerID: opts.OwnerID, OwnerID: opts.OwnerID,
AllPublic: true, AllPublic: true,
AllLimited: true, AllLimited: true,
TopicOnly: topicOnly,
TopicName: topic,
IncludeDescription: setting.UI.SearchRepoDescription, IncludeDescription: setting.UI.SearchRepoDescription,
}) })
if err != nil { if err != nil {
@@ -177,6 +176,8 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit) repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit)
} }
ctx.Data["Keyword"] = keyword ctx.Data["Keyword"] = keyword
ctx.Data["Topic"] = topic

ctx.Data["Total"] = count ctx.Data["Total"] = count
ctx.Data["Repos"] = repos ctx.Data["Repos"] = repos
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled


+ 2
- 1
routers/repo/cloudbrain.go View File

@@ -69,12 +69,13 @@ func CloudBrainIndex(ctx *context.Context) {


timestamp := time.Now().Unix() timestamp := time.Now().Unix()
for i, task := range ciTasks { for i, task := range ciTasks {
log.Info("", task.User.Name)
if task.Status == string(models.JobRunning) && (timestamp-int64(task.Cloudbrain.CreatedUnix) > 10) { if task.Status == string(models.JobRunning) && (timestamp-int64(task.Cloudbrain.CreatedUnix) > 10) {
ciTasks[i].CanDebug = true ciTasks[i].CanDebug = true
} else { } else {
ciTasks[i].CanDebug = false ciTasks[i].CanDebug = false
} }

ciTasks[i].CanDel = models.CanDelJob(ctx.IsSigned, ctx.User, task)
} }


pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)


+ 38
- 0
routers/repo/view.go View File

@@ -790,6 +790,44 @@ func renderCode(ctx *context.Context) {
} }
} }


//如果是fork的仓库
if ctx.Repo.Repository.IsFork {
//获得fetchUpstream对应的分支参数
/*
// 1. /{:baseOwner}/{:baseRepoName}/compare/{:baseBranch}...{:headBranch}
// 2. /{:baseOwner}/{:baseRepoName}/compare/{:baseBranch}...{:headOwner}:{:headBranch}
// 3. /{:baseOwner}/{:baseRepoName}/compare/{:baseBranch}...{:headOwner}/{:headRepoName}:{:headBranch}
*/
baseGitRepo, err := git.OpenRepository(ctx.Repo.Repository.BaseRepo.RepoPath())
defer baseGitRepo.Close()
if err != nil {
log.Error("error open baseRepo:%s",ctx.Repo.Repository.BaseRepo.RepoPath())
ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error
}else{
if _,error:= baseGitRepo.GetBranch(ctx.Repo.BranchName);error==nil{
//base repo has the same branch, then compare between current repo branch and base repo's branch
compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName
ctx.SetParams("*",compareUrl)
}else{
//else, compare between current repo branch and base repo's default branch
compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch
ctx.SetParams("*",compareUrl)
}
_, _, headGitRepo, compareInfo, _, _ := ParseCompareInfo(ctx)
defer headGitRepo.Close()
if compareInfo!= nil {
if compareInfo.Commits!=nil {
log.Info("compareInfoCommits数量:%d",compareInfo.Commits.Len())
ctx.Data["FetchUpstreamCnt"] = compareInfo.Commits.Len()
}else{
log.Info("compareInfo nothing different")
ctx.Data["FetchUpstreamCnt"] = 0
}
}else{
ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error
}
}
}
ctx.Data["Paths"] = paths ctx.Data["Paths"] = paths
ctx.Data["TreeLink"] = treeLink ctx.Data["TreeLink"] = treeLink
ctx.Data["TreeNames"] = treeNames ctx.Data["TreeNames"] = treeNames


+ 11
- 11
templates/explore/repo_left.tmpl View File

@@ -6,67 +6,67 @@
</svg> </svg>
全部领域 全部领域
</a> </a>
<a class="{{if eq $.Keyword "大模型"}}active {{end}}item" href="/explore/repos?q=大模型&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "大模型"}}active {{end}}item" href="/explore/repos?q=&topic=大模型&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M19 3H5C3.89 3 3 3.89 3 5V19C3 20.11 3.9 21 5 21H19C20.11 21 21 20.11 21 19V5C21 3.89 20.1 3 19 3M16.1 15.9C15.07 15.9 14.09 15.5 13.35 14.76L12.71 14.12L14.13 12.71L14.76 13.34C15.12 13.7 15.6 13.9 16.11 13.9C17.15 13.9 18 13.05 18 12S17.15 10.1 16.1 10.1C15.6 10.1 15.12 10.3 14.76 10.66L10.65 14.76C9.91 15.5 8.94 15.9 7.9 15.9C5.75 15.9 4 14.15 4 12S5.75 8.1 7.9 8.1C8.94 8.1 9.91 8.5 10.65 9.24L11.29 9.88L9.87 11.3L9.24 10.66C8.88 10.3 8.4 10.1 7.9 10.1C6.85 10.1 6 10.95 6 12S6.85 13.9 7.9 13.9C8.4 13.9 8.88 13.7 9.24 13.34L13.35 9.24C14.09 8.5 15.06 8.1 16.1 8.1C18.25 8.1 20 9.85 20 12S18.25 15.9 16.1 15.9Z" /> <path fill="currentColor" d="M19 3H5C3.89 3 3 3.89 3 5V19C3 20.11 3.9 21 5 21H19C20.11 21 21 20.11 21 19V5C21 3.89 20.1 3 19 3M16.1 15.9C15.07 15.9 14.09 15.5 13.35 14.76L12.71 14.12L14.13 12.71L14.76 13.34C15.12 13.7 15.6 13.9 16.11 13.9C17.15 13.9 18 13.05 18 12S17.15 10.1 16.1 10.1C15.6 10.1 15.12 10.3 14.76 10.66L10.65 14.76C9.91 15.5 8.94 15.9 7.9 15.9C5.75 15.9 4 14.15 4 12S5.75 8.1 7.9 8.1C8.94 8.1 9.91 8.5 10.65 9.24L11.29 9.88L9.87 11.3L9.24 10.66C8.88 10.3 8.4 10.1 7.9 10.1C6.85 10.1 6 10.95 6 12S6.85 13.9 7.9 13.9C8.4 13.9 8.88 13.7 9.24 13.34L13.35 9.24C14.09 8.5 15.06 8.1 16.1 8.1C18.25 8.1 20 9.85 20 12S18.25 15.9 16.1 15.9Z" />
</svg> </svg>
大模型 大模型
</a> </a>
<a class="{{if eq $.Keyword "AI开发工具"}}active {{end}}item" href="/explore/repos?q=AI开发工具&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "AI开发工具"}}active {{end}}item" href="/explore/repos?q=&topic=AI开发工具&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M11 8H9V10C9 11.1 8.1 12 7 12C8.1 12 9 12.9 9 14V16H11V18H9C7.9 18 7 17.1 7 16V15C7 13.9 6.1 13 5 13V11C6.1 11 7 10.1 7 9V8C7 6.9 7.9 6 9 6H11V8M19 13C17.9 13 17 13.9 17 15V16C17 17.1 16.1 18 15 18H13V16H15V14C15 12.9 15.9 12 17 12C15.9 12 15 11.1 15 10V8H13V6H15C16.1 6 17 6.9 17 8V9C17 10.1 17.9 11 19 11V13Z" /> <path fill="currentColor" d="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M11 8H9V10C9 11.1 8.1 12 7 12C8.1 12 9 12.9 9 14V16H11V18H9C7.9 18 7 17.1 7 16V15C7 13.9 6.1 13 5 13V11C6.1 11 7 10.1 7 9V8C7 6.9 7.9 6 9 6H11V8M19 13C17.9 13 17 13.9 17 15V16C17 17.1 16.1 18 15 18H13V16H15V14C15 12.9 15.9 12 17 12C15.9 12 15 11.1 15 10V8H13V6H15C16.1 6 17 6.9 17 8V9C17 10.1 17.9 11 19 11V13Z" />
</svg> </svg>
AI开发工具 AI开发工具
</a> </a>
<a class="{{if eq $.Keyword "计算机视觉"}}active {{end}}item" href="/explore/repos?q=计算机视觉&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "计算机视觉"}}active {{end}}item" href="/explore/repos?q=&topic=计算机视觉&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17M12,4.5C7,4.5 2.73,7.61 1,12C2.73,16.39 7,19.5 12,19.5C17,19.5 21.27,16.39 23,12C21.27,7.61 17,4.5 12,4.5Z" /> <path fill="currentColor" d="M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17M12,4.5C7,4.5 2.73,7.61 1,12C2.73,16.39 7,19.5 12,19.5C17,19.5 21.27,16.39 23,12C21.27,7.61 17,4.5 12,4.5Z" />
</svg> </svg>
计算机视觉 计算机视觉
</a> </a>
<a class="{{if eq $.Keyword "自然语言处理"}}active {{end}}item" href="/explore/repos?q=自然语言处理&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "自然语言处理"}}active {{end}}item" href="/explore/repos?q=&topic=自然语言处理&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M9,5A4,4 0 0,1 13,9A4,4 0 0,1 9,13A4,4 0 0,1 5,9A4,4 0 0,1 9,5M9,15C11.67,15 17,16.34 17,19V21H1V19C1,16.34 6.33,15 9,15M16.76,5.36C18.78,7.56 18.78,10.61 16.76,12.63L15.08,10.94C15.92,9.76 15.92,8.23 15.08,7.05L16.76,5.36M20.07,2C24,6.05 23.97,12.11 20.07,16L18.44,14.37C21.21,11.19 21.21,6.65 18.44,3.63L20.07,2Z" /> <path fill="currentColor" d="M9,5A4,4 0 0,1 13,9A4,4 0 0,1 9,13A4,4 0 0,1 5,9A4,4 0 0,1 9,5M9,15C11.67,15 17,16.34 17,19V21H1V19C1,16.34 6.33,15 9,15M16.76,5.36C18.78,7.56 18.78,10.61 16.76,12.63L15.08,10.94C15.92,9.76 15.92,8.23 15.08,7.05L16.76,5.36M20.07,2C24,6.05 23.97,12.11 20.07,16L18.44,14.37C21.21,11.19 21.21,6.65 18.44,3.63L20.07,2Z" />
</svg> </svg>
自然语言处理 自然语言处理
</a> </a>
<a class="{{if eq $.Keyword "机器学习"}}active {{end}}item" href="/explore/repos?q=机器学习&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "机器学习"}}active {{end}}item" href="/explore/repos?q=&topic=机器学习&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,12V13.5A4,4 0 0,1 23,17.5C23,18.32 22.75,19.08 22.33,19.71L21.24,18.62C21.41,18.28 21.5,17.9 21.5,17.5A2.5,2.5 0 0,0 19,15V16.5L16.75,14.25L19,12M19,23V21.5A4,4 0 0,1 15,17.5C15,16.68 15.25,15.92 15.67,15.29L16.76,16.38C16.59,16.72 16.5,17.1 16.5,17.5A2.5,2.5 0 0,0 19,20V18.5L21.25,20.75L19,23M12,3C16.42,3 20,4.79 20,7C20,9.21 16.42,11 12,11C7.58,11 4,9.21 4,7C4,4.79 7.58,3 12,3M4,9C4,11.21 7.58,13 12,13C13.11,13 14.17,12.89 15.14,12.68C14.19,13.54 13.5,14.67 13.18,15.96L12,16C7.58,16 4,14.21 4,12V9M20,9V11H19.5L18.9,11.03C19.6,10.43 20,9.74 20,9M4,14C4,16.21 7.58,18 12,18L13,17.97C13.09,19.03 13.42,20 13.95,20.88L12,21C7.58,21 4,19.21 4,17V14Z" /> <path fill="currentColor" d="M19,12V13.5A4,4 0 0,1 23,17.5C23,18.32 22.75,19.08 22.33,19.71L21.24,18.62C21.41,18.28 21.5,17.9 21.5,17.5A2.5,2.5 0 0,0 19,15V16.5L16.75,14.25L19,12M19,23V21.5A4,4 0 0,1 15,17.5C15,16.68 15.25,15.92 15.67,15.29L16.76,16.38C16.59,16.72 16.5,17.1 16.5,17.5A2.5,2.5 0 0,0 19,20V18.5L21.25,20.75L19,23M12,3C16.42,3 20,4.79 20,7C20,9.21 16.42,11 12,11C7.58,11 4,9.21 4,7C4,4.79 7.58,3 12,3M4,9C4,11.21 7.58,13 12,13C13.11,13 14.17,12.89 15.14,12.68C14.19,13.54 13.5,14.67 13.18,15.96L12,16C7.58,16 4,14.21 4,12V9M20,9V11H19.5L18.9,11.03C19.6,10.43 20,9.74 20,9M4,14C4,16.21 7.58,18 12,18L13,17.97C13.09,19.03 13.42,20 13.95,20.88L12,21C7.58,21 4,19.21 4,17V14Z" />
</svg> </svg>
机器学习 机器学习
</a> </a>
<a class="{{if eq $.Keyword "神经网络"}}active {{end}}item" href="/explore/repos?q=神经网络&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "神经网络"}}active {{end}}item" href="/explore/repos?q=&topic=神经网络&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M13 3C9.23 3 6.19 5.95 6 9.66L4.08 12.19C3.84 12.5 4.08 13 4.5 13H6V16C6 17.11 6.89 18 8 18H9V21H16V16.31C18.37 15.19 20 12.8 20 10C20 6.14 16.88 3 13 3M17.06 9.57L15.1 10.09L16.54 11.54C16.89 11.88 16.89 12.46 16.54 12.81C16.19 13.16 15.61 13.16 15.27 12.81L13.81 11.37L13.3 13.33C13.18 13.82 12.68 14.1 12.21 13.97C11.72 13.84 11.44 13.35 11.57 12.87L12.1 10.9L10.13 11.43C9.65 11.56 9.15 11.28 9.03 10.79C8.9 10.32 9.18 9.82 9.67 9.7L11.63 9.19L10.19 7.73C9.84 7.39 9.84 6.82 10.19 6.46C10.54 6.11 11.12 6.11 11.46 6.46L12.91 7.9L13.43 5.94C13.55 5.46 14.04 5.18 14.5 5.3C15 5.43 15.28 5.92 15.16 6.41L14.63 8.37L16.59 7.84C17.08 7.72 17.57 8 17.7 8.5C17.82 8.96 17.54 9.45 17.06 9.57Z" /> <path fill="currentColor" d="M13 3C9.23 3 6.19 5.95 6 9.66L4.08 12.19C3.84 12.5 4.08 13 4.5 13H6V16C6 17.11 6.89 18 8 18H9V21H16V16.31C18.37 15.19 20 12.8 20 10C20 6.14 16.88 3 13 3M17.06 9.57L15.1 10.09L16.54 11.54C16.89 11.88 16.89 12.46 16.54 12.81C16.19 13.16 15.61 13.16 15.27 12.81L13.81 11.37L13.3 13.33C13.18 13.82 12.68 14.1 12.21 13.97C11.72 13.84 11.44 13.35 11.57 12.87L12.1 10.9L10.13 11.43C9.65 11.56 9.15 11.28 9.03 10.79C8.9 10.32 9.18 9.82 9.67 9.7L11.63 9.19L10.19 7.73C9.84 7.39 9.84 6.82 10.19 6.46C10.54 6.11 11.12 6.11 11.46 6.46L12.91 7.9L13.43 5.94C13.55 5.46 14.04 5.18 14.5 5.3C15 5.43 15.28 5.92 15.16 6.41L14.63 8.37L16.59 7.84C17.08 7.72 17.57 8 17.7 8.5C17.82 8.96 17.54 9.45 17.06 9.57Z" />
</svg> </svg>
神经网络 神经网络
</a> </a>
<a class="{{if eq $.Keyword "自动驾驶"}}active {{end}}item" href="/explore/repos?q=自动驾驶&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "自动驾驶"}}active {{end}}item" href="/explore/repos?q=&topic=自动驾驶&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M5,14H19L17.5,9.5H6.5L5,14M17.5,19A1.5,1.5 0 0,0 19,17.5A1.5,1.5 0 0,0 17.5,16A1.5,1.5 0 0,0 16,17.5A1.5,1.5 0 0,0 17.5,19M6.5,19A1.5,1.5 0 0,0 8,17.5A1.5,1.5 0 0,0 6.5,16A1.5,1.5 0 0,0 5,17.5A1.5,1.5 0 0,0 6.5,19M18.92,9L21,15V23A1,1 0 0,1 20,24H19A1,1 0 0,1 18,23V22H6V23A1,1 0 0,1 5,24H4A1,1 0 0,1 3,23V15L5.08,9C5.28,8.42 5.85,8 6.5,8H17.5C18.15,8 18.72,8.42 18.92,9M12,0C14.12,0 16.15,0.86 17.65,2.35L16.23,3.77C15.11,2.65 13.58,2 12,2C10.42,2 8.89,2.65 7.77,3.77L6.36,2.35C7.85,0.86 9.88,0 12,0M12,4C13.06,4 14.07,4.44 14.82,5.18L13.4,6.6C13.03,6.23 12.53,6 12,6C11.5,6 10.97,6.23 10.6,6.6L9.18,5.18C9.93,4.44 10.94,4 12,4Z" /> <path fill="currentColor" d="M5,14H19L17.5,9.5H6.5L5,14M17.5,19A1.5,1.5 0 0,0 19,17.5A1.5,1.5 0 0,0 17.5,16A1.5,1.5 0 0,0 16,17.5A1.5,1.5 0 0,0 17.5,19M6.5,19A1.5,1.5 0 0,0 8,17.5A1.5,1.5 0 0,0 6.5,16A1.5,1.5 0 0,0 5,17.5A1.5,1.5 0 0,0 6.5,19M18.92,9L21,15V23A1,1 0 0,1 20,24H19A1,1 0 0,1 18,23V22H6V23A1,1 0 0,1 5,24H4A1,1 0 0,1 3,23V15L5.08,9C5.28,8.42 5.85,8 6.5,8H17.5C18.15,8 18.72,8.42 18.92,9M12,0C14.12,0 16.15,0.86 17.65,2.35L16.23,3.77C15.11,2.65 13.58,2 12,2C10.42,2 8.89,2.65 7.77,3.77L6.36,2.35C7.85,0.86 9.88,0 12,0M12,4C13.06,4 14.07,4.44 14.82,5.18L13.4,6.6C13.03,6.23 12.53,6 12,6C11.5,6 10.97,6.23 10.6,6.6L9.18,5.18C9.93,4.44 10.94,4 12,4Z" />
</svg> </svg>
自动驾驶 自动驾驶
</a> </a>
<a class="{{if eq $.Keyword "机器人"}}active {{end}}item" href="/explore/repos?q=机器人&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "机器人"}}active {{end}}item" href="/explore/repos?q=&topic=机器人&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" /> <path fill="currentColor" d="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z" />
</svg> </svg>
机器人 机器人
</a> </a>
<a class="{{if eq $.Keyword "联邦学习"}}active {{end}}item" href="/explore/repos?q=联邦学习&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "联邦学习"}}active {{end}}item" href="/explore/repos?q=&topic=联邦学习&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M3 11H11V3H3M5 5H9V9H5M13 21H21V13H13M15 15H19V19H15M3 21H11V13H3M5 15H9V19H5M13 3V11H21V3M19 9H15V5H19Z" /> <path fill="currentColor" d="M3 11H11V3H3M5 5H9V9H5M13 21H21V13H13M15 15H19V19H15M3 21H11V13H3M5 15H9V19H5M13 3V11H21V3M19 9H15V5H19Z" />
</svg> </svg>
联邦学习 联邦学习
</a> </a>
<a class="{{if eq $.Keyword "数据挖掘"}}active {{end}}item" href="/explore/repos?q=数据挖掘&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "数据挖掘"}}active {{end}}item" href="/explore/repos?q=&topic=数据挖掘&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M18.36,2.64C20,2.64 21.36,4 21.36,5.64C21.36,7.29 20,8.64 18.36,8.64C16.71,8.64 15.36,7.29 15.36,5.64C15.36,5.34 15.41,5.06 15.5,4.8C14.43,4.29 13.25,4 12,4A8,8 0 0,0 4,12L4.04,12.84L2.05,13.05L2,12A10,10 0 0,1 12,2C13.69,2 15.28,2.42 16.67,3.16C17.16,2.83 17.74,2.64 18.36,2.64M18.36,4.64A1,1 0 0,0 17.36,5.64A1,1 0 0,0 18.36,6.64C18.92,6.64 19.36,6.19 19.36,5.64C19.36,5.08 18.92,4.64 18.36,4.64M5.64,15.36C7.29,15.36 8.64,16.71 8.64,18.36C8.64,18.66 8.59,18.94 8.5,19.2C9.57,19.71 10.75,20 12,20A8,8 0 0,0 20,12L19.96,11.16L21.95,10.95L22,12A10,10 0 0,1 12,22C10.31,22 8.72,21.58 7.33,20.84C6.84,21.17 6.26,21.36 5.64,21.36C4,21.36 2.64,20 2.64,18.36C2.64,16.71 4,15.36 5.64,15.36M5.64,17.36C5.08,17.36 4.64,17.81 4.64,18.36C4.64,18.92 5.08,19.36 5.64,19.36A1,1 0 0,0 6.64,18.36A1,1 0 0,0 5.64,17.36M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8Z" /> <path fill="currentColor" d="M18.36,2.64C20,2.64 21.36,4 21.36,5.64C21.36,7.29 20,8.64 18.36,8.64C16.71,8.64 15.36,7.29 15.36,5.64C15.36,5.34 15.41,5.06 15.5,4.8C14.43,4.29 13.25,4 12,4A8,8 0 0,0 4,12L4.04,12.84L2.05,13.05L2,12A10,10 0 0,1 12,2C13.69,2 15.28,2.42 16.67,3.16C17.16,2.83 17.74,2.64 18.36,2.64M18.36,4.64A1,1 0 0,0 17.36,5.64A1,1 0 0,0 18.36,6.64C18.92,6.64 19.36,6.19 19.36,5.64C19.36,5.08 18.92,4.64 18.36,4.64M5.64,15.36C7.29,15.36 8.64,16.71 8.64,18.36C8.64,18.66 8.59,18.94 8.5,19.2C9.57,19.71 10.75,20 12,20A8,8 0 0,0 20,12L19.96,11.16L21.95,10.95L22,12A10,10 0 0,1 12,22C10.31,22 8.72,21.58 7.33,20.84C6.84,21.17 6.26,21.36 5.64,21.36C4,21.36 2.64,20 2.64,18.36C2.64,16.71 4,15.36 5.64,15.36M5.64,17.36C5.08,17.36 4.64,17.81 4.64,18.36C4.64,18.92 5.08,19.36 5.64,19.36A1,1 0 0,0 6.64,18.36A1,1 0 0,0 5.64,17.36M12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8Z" />
</svg> </svg>
数据挖掘 数据挖掘
</a> </a>
<a class="{{if eq $.Keyword "RISC-V"}}active {{end}}item" href="/explore/repos?q=RISC-V&topic=1&sort={{.SortType}}">
<a class="{{if eq $.Topic "RISC-V"}}active {{end}}item" href="/explore/repos?q=&topic=RISC-V&sort={{.SortType}}">
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> <svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24">
<path fill="currentColor" d="M17,17H7V7H17M21,11V9H19V7C19,5.89 18.1,5 17,5H15V3H13V5H11V3H9V5H7C5.89,5 5,5.89 5,7V9H3V11H5V13H3V15H5V17A2,2 0 0,0 7,19H9V21H11V19H13V21H15V19H17A2,2 0 0,0 19,17V15H21V13H19V11M13,13H11V11H13M15,9H9V15H15V9Z" /> <path fill="currentColor" d="M17,17H7V7H17M21,11V9H19V7C19,5.89 18.1,5 17,5H15V3H13V5H11V3H9V5H7C5.89,5 5,5.89 5,7V9H3V11H5V13H3V15H5V17A2,2 0 0,0 7,19H9V21H11V19H13V21H15V19H17A2,2 0 0,0 19,17V15H21V13H19V11M13,13H11V11H13M15,9H9V15H15V9Z" />
</svg> </svg>


+ 14
- 14
templates/explore/repo_list.tmpl View File

@@ -40,20 +40,20 @@


<div class="ui secondary pointing tabular top attached borderless menu navbar"> <div class="ui secondary pointing tabular top attached borderless menu navbar">
{{if .PageIsExplore}} {{if .PageIsExplore}}
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?sort=hot&q={{$.Keyword}}&tab={{$.TabName}}">
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot">
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> <svg class="svg octicon-repo" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-repo" /> <use xlink:href="#octicon-repo" />
</svg> </svg>
热门{{.i18n.Tr "explore.repos"}} 热门{{.i18n.Tr "explore.repos"}}
</a> </a>
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?sort=active&q={{$.Keyword}}&tab={{$.TabName}}">
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active">
<svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> <svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-inbox" /> <use xlink:href="#octicon-inbox" />
</svg> </svg>
活跃{{.i18n.Tr "explore.repos"}} 活跃{{.i18n.Tr "explore.repos"}}
</a> </a>
{{end}} {{end}}
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=recentupdate">
<svg class="svg octicon-organization" width="16" height="16" aria-hidden="true"> <svg class="svg octicon-organization" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-organization" /> <use xlink:href="#octicon-organization" />
</svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}} </svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}
@@ -67,16 +67,16 @@
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a>
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a>
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a>
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a>
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a>
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a>
</div> </div>
</div> </div>
</div> </div>
@@ -143,7 +143,7 @@
{{if .Topics }} {{if .Topics }}
<div class="ui tags"> <div class="ui tags">
{{range .Topics}} {{range .Topics}}
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1"><div class="ui small label topic">{{.}}</div></a>{{end}}
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q=&topic={{.}}"><div class="ui small label topic">{{.}}</div></a>{{end}}
{{end}} {{end}}
</div> </div>
{{end}} {{end}}


+ 1
- 1
templates/explore/repo_search.tmpl View File

@@ -9,7 +9,7 @@
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin-top:1.2rem"> <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin-top:1.2rem">
<div class="ui fluid action input"> <div class="ui fluid action input">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus>
<input type="hidden" name="tab" value="{{$.TabName}}">
<input type="hidden" name="topic" value="{{$.Topic}}">
<input type="hidden" name="sort" value="{{$.SortType}}"> <input type="hidden" name="sort" value="{{$.SortType}}">
<button class="ui green button">{{.i18n.Tr "explore.search"}}</button> <button class="ui green button">{{.i18n.Tr "explore.search"}}</button>
</div> </div>


+ 57
- 26
templates/repo/cloudbrain/index.tmpl View File

@@ -241,59 +241,87 @@
<div class="ui sixteen wide column"> <div class="ui sixteen wide column">


<!-- 排序区 --> <!-- 排序区 -->
<div class="ui sixteen wide column">
<!-- <div class="ui sixteen wide column">
<div class="ui two column stackable grid"> <div class="ui two column stackable grid">
<div class="column"> <div class="column">
</div> </div>
<!-- <div class="column right aligned">
<div class="column right aligned">
<div class="ui right dropdown type jump item"> <div class="ui right dropdown type jump item">
<span class="text"> <span class="text">
{{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> {{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i>
</span> </span>
</div> </div>
</div> -->
</div>
</div> </div>
</div>
</div> -->


<!-- 任务展示 --> <!-- 任务展示 -->

<!-- 表头 -->
<div class="dataset list"> <div class="dataset list">
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="five wide column">
<span style="margin:0 6px">{{$.i18n.Tr "repo.cloudbrain_task"}}</span>
</div>
<div class="three wide column">
<span>{{$.i18n.Tr "repo.cloudbrain_status_createtime"}}</span>
</div>
<div class="one wide column">
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span>
</div>
<div class="seven wide column text center">
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
</div>

</div>
</div>
{{range .Tasks}} {{range .Tasks}}
<div class="ui grid stackable item"> <div class="ui grid stackable item">
<div class="row"> <div class="row">


<!-- 任务名 --> <!-- 任务名 -->
<div class="five wide column"> <div class="five wide column">
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}">
<span class="fitted">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted text_over" style="width: 90%;">{{.JobName}}</span>
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 15px;">
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted text_over" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span>
</a> </a>
</div> </div>


<div class="three wide column"> <div class="three wide column">
<!--任务状态 --> <!--任务状态 -->
<!-- <span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}}
<span class="job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
<!-- {{.Status}} -->
<!-- {{if eq .Status "RUNNING"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-stop"></i><span style="margin-left: 0.4em;font-size: 12px;">运行中</span></span>
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-stop"></i><span style="margin-left: 0.4em;font-size: 12px;">运行中</span></span>
{{else}}
{{.Status}}
{{end}} -->
<span><i style="vertical-align: middle;" class="{{.Status}}"></i><span style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span>
<!-- <span class="job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}" >
{{if eq .Status "STOPPED"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-stop"></i><span style="margin-left: 0.4em;font-size: 12px;">已停止</span></span>
{{else if eq .Status "RUNNING"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-running"></i><span style="margin-left: 0.4em;font-size: 12px;">运行中</span></span>
{{else if eq .Status "FAILED"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-running"></i><span style="margin-left: 0.4em;font-size: 12px;">运行失败</span></span>
{{else if eq .Status "WAITING"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="showCircle"></i><span style="margin-left: 0.4em;font-size: 12px;">初始化等待</span></span>
{{end}}
</span> --> </span> -->
{{if eq .Status "STOPPED"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-stop"></i><span style="margin-left: 0.4em;font-size: 12px;">已停止</span></span>
{{else if eq .Status "RUNNING"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-running"></i><span style="margin-left: 0.4em;font-size: 12px;">运行中</span></span>
{{else if eq .Status "FAILED"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-running"></i><span style="margin-left: 0.4em;font-size: 12px;">运行失败</span></span>
{{else if eq .Status "WAITING"}}
<span style="display:flex;position: relative; justify-content: flex-start;"><i class="showCircle"></i><span style="margin-left: 0.4em;font-size: 12px;">初始化等待</span></span>
{{end}}
<!-- 任务创建时间 --> <!-- 任务创建时间 -->
<span class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
<span style="font-size: 12px;margin-left: 0.4rem;" class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
</div> </div>


<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 class="one wide column">
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
</div> </div>
<div class="six wide column text right">
<div class="ui compact buttons" style="margin-right:10px;">
<div class="seven wide column text right">
<div class="ui compact buttons">
{{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}} {{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}}
<a class="ui basic button" href="{{$.Link}}/{{.JobID}}/rate" target="_blank"> <a class="ui basic button" href="{{$.Link}}/{{.JobID}}/rate" target="_blank">
评分 评分
@@ -325,9 +353,9 @@
</div> </div>
<!-- 删除镜像 --> <!-- 删除镜像 -->
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{if ne .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post">
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{if not .CanDel}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post">
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
<a class="ui compact {{if ne .Status "STOPPED"}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
<a class="ui compact {{if not .CanDel}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
删除 删除
</a> </a>
</form> </form>
@@ -456,15 +484,18 @@
$(document).ready(loadJobStatus); $(document).ready(loadJobStatus);
function loadJobStatus() { function loadJobStatus() {
$(".job-status").each((index, job) => { $(".job-status").each((index, job) => {
console.log("---------",index,job)
const jobID = job.dataset.jobid; const jobID = job.dataset.jobid;
const repoPath = job.dataset.repopath; const repoPath = job.dataset.repopath;
if (job.textContent.trim() == 'STOPPED') { if (job.textContent.trim() == 'STOPPED') {
return return
} }


$.get(`/api/v1/repos/${repoPath}/cloudbrain/${jobID}`, (data) => { $.get(`/api/v1/repos/${repoPath}/cloudbrain/${jobID}`, (data) => {
const jobID = data.JobID const jobID = data.JobID
const status = data.JobStatus const status = data.JobStatus
console.log("status",status)
if (status != job.textContent.trim()) { if (status != job.textContent.trim()) {
//$('#' + jobID).text(status) //$('#' + jobID).text(status)
//if (status == 'STOPPED') { //if (status == 'STOPPED') {


+ 15
- 0
templates/repo/home.tmpl View File

@@ -154,6 +154,21 @@
<a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}"> <a href="{{.BaseRepo.Link}}/compare/{{.BaseRepo.DefaultBranch | EscapePound}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{.Repository.Owner.Name}}:{{end}}{{.BranchName | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button> <button id="new-pull-request" class="ui compact basic button">{{if .PullRequestCtx.Allowed}}{{.i18n.Tr "repo.pulls.compare_changes"}}{{else}}{{.i18n.Tr "action.compare_branch"}}{{end}}</button>
</a> </a>
{{if and .Repository.IsFork .PullRequestCtx.Allowed}}
{{if gt .FetchUpstreamCnt 0 }}
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button" title="{{$.i18n.Tr (TrN $.i18n.Lang .FetchUpstreamCnt "repo.pulls.commits_count_1" "repo.pulls.commits_count_n") .FetchUpstreamCnt}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{else if lt .FetchUpstreamCnt 0}}
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_error"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{else}}
<a href="{{.Repository.Link}}/compare/{{.BranchName | EscapePound}}...{{.BaseRepo.Owner.Name}}:{{.BaseRepo.DefaultBranch | EscapePound}}">
<button id="new-pull-request" class="ui compact basic button" title="{{.i18n.Tr "repo.pulls.upstream_up_to_date"}}">{{.i18n.Tr "repo.pulls.fetch_upstream"}}</button>
</a>
{{end}}
{{end}}
</div> </div>
{{end}} {{end}}
{{else}} {{else}}


+ 1
- 6
templates/repo/issue/list.tmpl View File

@@ -3,12 +3,7 @@
{{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" 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 class="column" style="display: flex;align-items: center;">
</div> </div>
<div class="column center aligned"> <div class="column center aligned">
{{template "repo/issue/search" .}} {{template "repo/issue/search" .}}


+ 9
- 1
templates/repo/issue/view.tmpl View File

@@ -4,11 +4,19 @@
<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" style="display: flex;align-items: center;"> <div class="column" style="display: flex;align-items: center;">
{{if .PageIsIssueList}}
<div class="ui large breadcrumb"> <div class="ui large breadcrumb">
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> <a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a>
<div class="divider"> / </div> <div class="divider"> / </div>
<div class="action section">{{.Title | RenderEmoji}}</div>
<div class="action section">{{.i18n.Tr "repo.issues_detail"}}</div>
</div> </div>
{{else}}
<div class="ui large breadcrumb">
<a class="section" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.pulls"}}</a>
<div class="divider"> / </div>
<div class="action section">{{.i18n.Tr "repo.issues_detail"}}</div>
</div>
{{end}}
</div> </div>
{{if not .Repository.IsArchived}} {{if not .Repository.IsArchived}}
<div class="column right aligned"> <div class="column right aligned">


+ 40
- 10
templates/repo/modelarts/index.tmpl View File

@@ -228,41 +228,71 @@
<div class="ui sixteen wide column"> <div class="ui sixteen wide column">


<!-- 排序区 --> <!-- 排序区 -->
<div class="ui sixteen wide column">
<!-- <div class="ui sixteen wide column">
<div class="ui two column stackable grid"> <div class="ui two column stackable grid">
<div class="column"> <div class="column">
</div> </div>
<!-- <div class="column right aligned">
<div class="column right aligned">
<div class="ui right dropdown type jump item"> <div class="ui right dropdown type jump item">
<span class="text"> <span class="text">
{{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> {{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i>
</span> </span>
</div> </div>
</div> -->
</div>
</div> </div>
</div>
</div> -->


<!-- 任务展示 --> <!-- 任务展示 -->
<div class="dataset list"> <div class="dataset list">

<!-- 表头 -->
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
<div class="five wide column">
<span style="margin:0 6px">{{$.i18n.Tr "repo.cloudbrain_task"}}</span>
</div>
<div class="three wide column">
<span>{{$.i18n.Tr "repo.cloudbrain_status_createtime"}}</span>
</div>
<div class="one wide column">
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span>
</div>
<div class="seven wide column text center">
<span style="margin-left: 10rem;">{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
</div>

</div>
</div>



{{range .Tasks}} {{range .Tasks}}
<div class="ui grid stackable item"> <div class="ui grid stackable item">
<div class="row"> <div class="row">
<!-- 任务名 --> <!-- 任务名 -->
<div class="six wide column">
<a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted">{{.JobName}}</span>
<div class="five wide column">
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 15px;">
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span>
</a> </a>
</div> </div>


<div class="three wide column"> <div class="three wide column">
<!--任务状态 --> <!--任务状态 -->
<span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
<!-- <span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}} {{.Status}}
</span> -->
<span class="job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
<span><i style="vertical-align: middle;" class="{{.Status}}"></i><span style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span>
</span> </span>
<!-- 任务创建时间 --> <!-- 任务创建时间 -->
<span class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
<span style="font-size: 12px;margin-left: 0.4rem;" class="">{{TimeSinceUnix .Cloudbrain.CreatedUnix $.Lang}}</span>
</div>

<div class="one wide column">
<a href="{{AppSubUrl}}/{{.User.Name}}" title="{{.User.Name}}"><img class="ui avatar image" src="{{.User.RelAvatarLink}}"></a>
</div> </div>


<div class="seven wide column text right"> <div class="seven wide column text right">


+ 15
- 1
templates/repo/pulls/commits.tmpl View File

@@ -2,11 +2,25 @@
<div class="repository view issue pull commits"> <div class="repository view issue pull commits">
{{template "repo/header" .}} {{template "repo/header" .}}
<div class="ui container"> <div class="ui container">
<div class="navbar">
<!-- <div class="navbar">
{{template "repo/issue/navbar" .}} {{template "repo/issue/navbar" .}}
<div class="ui right"> <div class="ui right">
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a> <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
</div> </div>
</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}}/pulls">{{.i18n.Tr "repo.pulls"}}</a>
<div class="divider"> / </div>
<div class="action section">{{.i18n.Tr "repo.issues_detail"}}</div>
</div>
</div>
<div class="column right aligned">
{{template "repo/issue/navbar" .}}
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
</div>
</div> </div>
<div class="ui divider"></div> <div class="ui divider"></div>
{{template "repo/issue/view_title" .}} {{template "repo/issue/view_title" .}}


+ 15
- 1
templates/repo/pulls/files.tmpl View File

@@ -2,11 +2,25 @@
<div class="repository view issue pull files diff"> <div class="repository view issue pull files diff">
{{template "repo/header" .}} {{template "repo/header" .}}
<div class="ui container {{if .IsSplitStyle}}fluid padded{{end}}"> <div class="ui container {{if .IsSplitStyle}}fluid padded{{end}}">
<div class="navbar">
<!-- <div class="navbar">
{{template "repo/issue/navbar" .}} {{template "repo/issue/navbar" .}}
<div class="ui right"> <div class="ui right">
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a> <a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
</div> </div>
</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}}/pulls">{{.i18n.Tr "repo.pulls"}}</a>
<div class="divider"> / </div>
<div class="action section">{{.i18n.Tr "repo.issues_detail"}}</div>
</div>
</div>
<div class="column right aligned">
{{template "repo/issue/navbar" .}}
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | EscapePound}}...{{.PullRequestCtx.HeadInfo | EscapePound}}">{{.i18n.Tr "repo.pulls.new"}}</a>
</div>
</div> </div>
<div class="ui divider"></div> <div class="ui divider"></div>
{{template "repo/issue/view_title" .}} {{template "repo/issue/view_title" .}}


+ 36
- 27
web_src/js/components/EditTopics.vue View File

@@ -61,18 +61,23 @@ export default {
if(!this.showInitTopic[item]){ if(!this.showInitTopic[item]){

this.arrayTopics.push(array.topic_name)
if(this.arrayTopics.includes(array.topic_name)){
return
}
else{
this.arrayTopics.push(array.topic_name)
let topics = this.arrayTopics
let strTopics = topics.join(',')
let data = this.qs.stringify({
_csrf:csrf,
topics:strTopics
})
this.Post(data,topics)
this.$set(this.showInitTopic,item,true)
$('#repo-topics1').children('span').remove()
}
let topics = this.arrayTopics
let strTopics = topics.join(',')
let data = this.qs.stringify({
_csrf:csrf,
topics:strTopics
})
this.Post(data,topics)
this.$set(this.showInitTopic,item,true)
$('#repo-topics1').children('span').remove()


@@ -93,7 +98,6 @@ export default {
this.Post(data,topics) this.Post(data,topics)
this.$set(this.showInitTopic,item,false) this.$set(this.showInitTopic,item,false)
if(this.arrayTopics.length===0){ if(this.arrayTopics.length===0){
console.log("set empty")
$('#repo-topics1').append('<span class="no-description text-italic">暂无标签</span>') $('#repo-topics1').append('<span class="no-description text-italic">暂无标签</span>')
}else{ }else{
$('#repo-topics1').children('span').remove() $('#repo-topics1').children('span').remove()
@@ -197,32 +201,37 @@ export default {
}) })
}, },
postTopic(){ postTopic(){
const patter = /^[\u4e00-\u9fa5a-z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,35}$/
const patter = /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,34}$/
let regexp = patter.test(this.input) let regexp = patter.test(this.input)
console.log("regexp",regexp)
if(!regexp){ if(!regexp){
this.$notify({ this.$notify({
message: '主题必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符',
message: '标签名必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符',
duration: 3000, duration: 3000,
type:'error' type:'error'
}); });
return return
}else{ }else{
let topic = this.input let topic = this.input
this.arrayTopics.push(topic)
if(this.arrayTopics.includes(topic)){
return
}
else{
this.arrayTopics.push(topic)
let topics = this.arrayTopics
let strTopics = topics.join(',')
let data = this.qs.stringify({
_csrf:csrf,
topics:strTopics
})
this.Post(data,topics)
$('#repo-topics1').children('span').remove()
this.showInputValue = false
this.showAddTopic = true
this.showAddFlage = true
}
let topics = this.arrayTopics
let strTopics = topics.join(',')
let data = this.qs.stringify({
_csrf:csrf,
topics:strTopics
})
this.Post(data,topics)
$('#repo-topics1').children('span').remove()
this.showInputValue = false
this.showAddTopic = true
this.showAddFlage = true
} }




+ 4
- 4
web_src/less/openi.less View File

@@ -224,15 +224,15 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;}
// icon cloudbrain // icon cloudbrain
.i-round{display:inline-block;width:18px;height:18px;background:url("/img/icons.svg");background-position: -496px -52px;} .i-round{display:inline-block;width:18px;height:18px;background:url("/img/icons.svg");background-position: -496px -52px;}
.i-bg-organ{background-position: -496px -52px;} .i-bg-organ{background-position: -496px -52px;}
.i-bg-stop{background-position: -459px -52px;}
.i-bg-running{background-position: -478px -52px;}
.STOPPED{display:inline-block;width:18px;height:18px;background:url("/img/icons.svg");background-position: -496px -52px;background-position: -459px -52px;}
.RUNNING{display:inline-block;width:18px;height:18px;background:url("/img/icons.svg");background-position: -496px -52px;background-position: -478px -52px;}
.i-bg-orange{background-position: -495px -51px;} .i-bg-orange{background-position: -495px -51px;}
.i-bg-red{background-position: -532px -52px;}
.FAILED{display:inline-block;width:18px;height:18px;background:url("/img/icons.svg");background-position: -496px -52px;background-position: -532px -52px;}
.i-bg-green{background-position: -441px -52px;} .i-bg-green{background-position: -441px -52px;}
.i-bg-used{background-position: -514px -52px;} .i-bg-used{background-position: -514px -52px;}
.icon-bind{background-position: -550px -52px;} .icon-bind{background-position: -550px -52px;}
.icon-unbind{background-position: -568px -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;}
.CREATING, .STOPPING, .DELETING, .STARTING, .WAITING{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{ .text_over{
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;


Loading…
Cancel
Save