Browse Source

Merge branch 'V20211115' of git.openi.org.cn:OpenI/aiforge into fix-497

tags/v1.21.12.1
lewis 4 years ago
parent
commit
66cc55b221
22 changed files with 806 additions and 146 deletions
  1. +1
    -1
      README.md
  2. +2
    -2
      models/attachment.go
  3. +10
    -1
      models/cloudbrain.go
  4. +2
    -5
      models/file_chunk.go
  5. +9
    -0
      models/issue.go
  6. +86
    -5
      models/repo_activity_custom.go
  7. +11
    -0
      models/repo_collaboration.go
  8. +103
    -52
      models/repo_statistic.go
  9. +10
    -3
      modules/modelarts/modelarts.go
  10. +0
    -4
      modules/modelarts/resty.go
  11. +2
    -0
      modules/setting/setting.go
  12. +15
    -9
      options/locale/locale_en-US.ini
  13. +14
    -7
      options/locale/locale_zh-CN.ini
  14. +13
    -0
      routers/api/v1/api.go
  15. +362
    -0
      routers/api/v1/repo/repo_dashbord.go
  16. +1
    -1
      routers/home.go
  17. +14
    -8
      routers/repo/attachment.go
  18. +43
    -17
      routers/repo/modelarts.go
  19. +1
    -1
      routers/repo/repo_statistic.go
  20. +8
    -6
      templates/repo/modelarts/notebook/index.tmpl
  21. +4
    -4
      templates/repo/modelarts/trainjob/index.tmpl
  22. +95
    -20
      templates/repo/modelarts/trainjob/new.tmpl

+ 1
- 1
README.md View File

@@ -2,7 +2,7 @@

<h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1>

[![release](https://img.shields.io/badge/release-1.21.9.2-blue)](https://git.openi.org.cn/OpenI/aiforge/releases/latest)
[![release](https://img.shields.io/badge/release-1.21.11.1-blue)](https://git.openi.org.cn/OpenI/aiforge/releases/latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)




+ 2
- 2
models/attachment.go View File

@@ -379,7 +379,7 @@ func GetUnDecompressAttachments() ([]*Attachment, error) {

func getUnDecompressAttachments(e Engine) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)
return attachments, e.Where("decompress_state = ? and dataset_id != 0 and attachment.type = ? and (name like '%.zip' or name like '%.tar.gz' or name like '%.tgz')", DecompressStateInit, TypeCloudBrainOne).Find(&attachments)
return attachments, e.Where("decompress_state = ? and dataset_id != 0 and (name like '%.zip' or name like '%.tar.gz' or name like '%.tgz')", DecompressStateInit).Find(&attachments)
}

func GetAllPublicAttachments() ([]*AttachmentUsername, error) {
@@ -429,7 +429,7 @@ func GetAllUserAttachments(userID int64) ([]*AttachmentUsername, error) {
func getModelArtsUserAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) {
attachments := make([]*AttachmentUsername, 0, 10)
if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+
"= `user`.id").Where("attachment.type = ? and (uploader_id= ? or is_private = ?)", TypeCloudBrainNotebook, userID, false).Find(&attachments); err != nil {
"= `user`.id").Where("attachment.type = ? and (uploader_id= ? or is_private = ?)", TypeCloudBrainTwo, userID, false).Find(&attachments); err != nil {
return nil, err
}
return attachments, nil


+ 10
- 1
models/cloudbrain.go View File

@@ -29,6 +29,7 @@ const (
JobTypeBenchmark JobType = "BENCHMARK"
JobTypeSnn4imagenet JobType = "SNN4IMAGENET"
JobTypeBrainScore JobType = "BRAINSCORE"
JobTypeTrain JobType = "TRAIN"

ModelArtsCreateQueue ModelArtsJobStatus = "CREATE_QUEUING" //免费资源创建排队中
ModelArtsCreating ModelArtsJobStatus = "CREATING" //创建中
@@ -70,6 +71,7 @@ type Cloudbrain struct {
VersionID int64 `xorm:"INDEX DEFAULT 0"`
VersionName string
Uuid string
DatasetName string

User *User `xorm:"-"`
Repo *Repository `xorm:"-"`
@@ -152,7 +154,8 @@ type CloudbrainsOptions struct {
SortType string
CloudbrainIDs []int64
// JobStatus CloudbrainStatus
Type int
Type int
JobType string
}
type TaskPod struct {
TaskRoleStatus struct {
@@ -845,6 +848,12 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
)
}

if (opts.JobType) != "" {
cond = cond.And(
builder.Eq{"cloudbrain.job_type": opts.JobType},
)
}

// switch opts.JobStatus {
// case JobWaiting:
// cond.And(builder.Eq{"cloudbrain.status": int(JobWaiting)})


+ 2
- 5
models/file_chunk.go View File

@@ -14,11 +14,8 @@ const (
)

const (
TypeCloudBrainOne = 0
TypeCloudBrainNotebook = 1
TypeCloudBrainTrainJob = 2

TypeCloudBrainTwo = 1
TypeCloudBrainOne int = iota
TypeCloudBrainTwo
)

type FileChunk struct {


+ 9
- 0
models/issue.go View File

@@ -1356,6 +1356,15 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) {
return accum, nil
}

func GetPullCountByUserAndRepoId(repoId int64, userId int64) int64 {
issue := new(Issue)
total, err := x.Where("is_pull=true and repo_id=? and poster_id=?", repoId, userId).Count(issue)
if err != nil {
return 0
}
return total
}

func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, error) {
stats := &IssueStats{}



+ 86
- 5
models/repo_activity_custom.go View File

@@ -2,12 +2,18 @@ package models

import (
"fmt"
"sort"
"strings"
"time"

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

type ContributorWithUserId struct {
git.Contributor
UserId int64
}

func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) {
wikiPath := ""
if repo.HasWiki() {
@@ -63,22 +69,39 @@ func getRepoKPIStats(repoPath string, wikiPath string) (*git.RepoKPIStats, error
}

if recentlyContributors != nil {
resentlyContributorDistinctDict := make(map[string]int, 0)
for _, recentlyContributor := range recentlyContributors {

user, err := GetUserByActivateEmail(recentlyContributor.Email)
var ok bool
if err == nil {
_, ok = contributorDistinctDict[user.Email]
value, ok := resentlyContributorDistinctDict[user.Email]
if !ok {
resentlyContributorDistinctDict[user.Email] = recentlyContributor.CommitCnt
} else {
resentlyContributorDistinctDict[user.Email] = value + recentlyContributor.CommitCnt
}

} else {
_, ok = contributorDistinctDict[recentlyContributor.Email]
value, ok := resentlyContributorDistinctDict[recentlyContributor.Email]
if !ok {
resentlyContributorDistinctDict[recentlyContributor.Email] = recentlyContributor.CommitCnt
} else {
resentlyContributorDistinctDict[recentlyContributor.Email] = value + recentlyContributor.CommitCnt
}

}

if !ok {
}

for k, v := range resentlyContributorDistinctDict {
count, ok := contributorDistinctDict[k]
if ok && count == v {
stats.ContributorsAdded++
newContributersDict[recentlyContributor.Email] = struct{}{}
}

}

}

stats.Contributors = int64(len(contributorDistinctDict))
@@ -101,6 +124,64 @@ func getRepoKPIStats(repoPath string, wikiPath string) (*git.RepoKPIStats, error

}

func GetTop10Contributor(repoPath string) ([]ContributorWithUserId, error) {
contributors, err := git.GetContributors(repoPath)
if err != nil {
return make([]ContributorWithUserId, 0), err
}
contributorDistinctDict := make(map[string]ContributorWithUserId, 0)
if contributors != nil {
for _, contributor := range contributors {
if strings.Compare(contributor.Email, "") == 0 {
continue
}

user, err := GetUserByActivateEmail(contributor.Email)
if err == nil {

value, ok := contributorDistinctDict[user.Email]
if !ok {
contributorDistinctDict[user.Email] = ContributorWithUserId{
contributor,
user.ID,
}
} else {

value.CommitCnt += contributor.CommitCnt
}

} else {
value, ok := contributorDistinctDict[contributor.Email]
if !ok {
contributorDistinctDict[contributor.Email] = ContributorWithUserId{
contributor,
-1,
}
} else {
value.CommitCnt += contributor.CommitCnt
}

}

}
v := make([]ContributorWithUserId, 0, len(contributorDistinctDict))
for _, value := range contributorDistinctDict {
v = append(v, value)
}

sort.Slice(v, func(i, j int) bool {
return v[i].CommitCnt > v[j].CommitCnt
})

if len(v) <= 10 {
return v, nil
} else {
return v[0:10], nil
}
}
return make([]ContributorWithUserId, 0), nil
}

func setKeyContributerDict(contributorDistinctDict map[string]int, email string, keyContributorsDict map[string]struct{}) {
if contributorDistinctDict[email] >= 3 {
_, ok := keyContributorsDict[email]


+ 11
- 0
models/repo_collaboration.go View File

@@ -114,6 +114,17 @@ func (repo *Repository) isCollaborator(e Engine, userID int64) (bool, error) {
return e.Get(&Collaboration{RepoID: repo.ID, UserID: userID})
}

func (repo *Repository) GetCollaboratorMode(userID int64) int {
collaboration := &Collaboration{RepoID: repo.ID, UserID: userID}
has, err := x.Get(&collaboration)
if err != nil || !has {
return -1
} else {
return int(collaboration.Mode)
}

}

// IsCollaborator check if a user is a collaborator of a repository
func (repo *Repository) IsCollaborator(userID int64) (bool, error) {
return repo.isCollaborator(x, userID)


+ 103
- 52
models/repo_statistic.go View File

@@ -9,56 +9,56 @@ import (

// RepoStatistic statistic info of all repository
type RepoStatistic struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"unique(s) NOT NULL"`
Name string `xorm:"INDEX"`
IsPrivate bool
Date string `xorm:"unique(s) NOT NULL"`
NumWatches int64 `xorm:"NOT NULL DEFAULT 0"`
NumWatchesAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumStars int64 `xorm:"NOT NULL DEFAULT 0"`
NumStarsAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumForks int64 `xorm:"NOT NULL DEFAULT 0"`
NumForksAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumDownloads int64 `xorm:"NOT NULL DEFAULT 0"`
NumDownloadsAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumComments int64 `xorm:"NOT NULL DEFAULT 0"`
NumCommentsAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumVisits int64 `xorm:"NOT NULL DEFAULT 0"`
NumClosedIssues int64 `xorm:"NOT NULL DEFAULT 0"`
NumClosedIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumVersions int64 `xorm:"NOT NULL DEFAULT 0"`
NumDevMonths int64 `xorm:"NOT NULL DEFAULT 0"`
RepoSize int64 `xorm:"NOT NULL DEFAULT 0"`
DatasetSize int64 `xorm:"NOT NULL DEFAULT 0"`
NumModels int64 `xorm:"NOT NULL DEFAULT 0"`
NumWikiViews int64 `xorm:"NOT NULL DEFAULT 0"`
NumCommits int64 `xorm:"NOT NULL DEFAULT 0"`
NumCommitsAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumIssues int64 `xorm:"NOT NULL DEFAULT 0"`
NumIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumPulls int64 `xorm:"NOT NULL DEFAULT 0"`
NumPullsAdded int64 `xorm:"NOT NULL DEFAULT 0"`
IssueFixedRate float32 `xorm:"NOT NULL"`
NumContributor int64 `xorm:"NOT NULL DEFAULT 0"`
NumContributorAdded int64 `xorm:"NOT NULL DEFAULT 0"`
NumKeyContributor int64 `xorm:"NOT NULL DEFAULT 0"`
NumContributorsGrowth int64 `xorm:"NOT NULL DEFAULT 0"`
NumCommitsGrowth int64 `xorm:"NOT NULL DEFAULT 0"`
NumCommitLinesGrowth int64 `xorm:"NOT NULL DEFAULT 0"`
NumIssuesGrowth int64 `xorm:"NOT NULL DEFAULT 0"`
NumCommentsGrowth int64 `xorm:"NOT NULL DEFAULT 0"`
Impact float64 `xorm:"NOT NULL DEFAULT 0"`
Completeness float64 `xorm:"NOT NULL DEFAULT 0"`
Liveness float64 `xorm:"NOT NULL DEFAULT 0"`
ProjectHealth float64 `xorm:"NOT NULL DEFAULT 0"`
TeamHealth float64 `xorm:"NOT NULL DEFAULT 0"`
Growth float64 `xorm:"NOT NULL DEFAULT 0"`
RadarTotal float64 `xorm:"NOT NULL DEFAULT 0"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
ID int64 `xorm:"pk autoincr" json:"-"`
RepoID int64 `xorm:"unique(s) NOT NULL" json:"repo_id"`
Name string `xorm:"INDEX" json:"name"`
IsPrivate bool `json:"isPrivate"`
Date string `xorm:"unique(s) NOT NULL" json:"date"`
NumWatches int64 `xorm:"NOT NULL DEFAULT 0" json:"watch"`
NumWatchesAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumStars int64 `xorm:"NOT NULL DEFAULT 0" json:"star"`
NumStarsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumForks int64 `xorm:"NOT NULL DEFAULT 0" json:"fork"`
NumForksAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumDownloads int64 `xorm:"NOT NULL DEFAULT 0" json:"download"`
NumDownloadsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumComments int64 `xorm:"NOT NULL DEFAULT 0" json:"comment"`
NumCommentsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumVisits int64 `xorm:"NOT NULL DEFAULT 0" json:"view"`
NumClosedIssues int64 `xorm:"NOT NULL DEFAULT 0" json:"issueClosed"`
NumClosedIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumVersions int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumDevMonths int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
RepoSize int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
DatasetSize int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumModels int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumWikiViews int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumCommits int64 `xorm:"NOT NULL DEFAULT 0" json:"commit"`
NumCommitsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumIssues int64 `xorm:"NOT NULL DEFAULT 0" json:"issue"`
NumIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumPulls int64 `xorm:"NOT NULL DEFAULT 0" json:"pr"`
NumPullsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
IssueFixedRate float32 `xorm:"NOT NULL" json:"issueClosedRatio"`
NumContributor int64 `xorm:"NOT NULL DEFAULT 0" json:"contributor"`
NumContributorAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumKeyContributor int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumContributorsGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumCommitsGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumCommitLinesGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumIssuesGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
NumCommentsGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"`
Impact float64 `xorm:"NOT NULL DEFAULT 0" json:"impact"`
Completeness float64 `xorm:"NOT NULL DEFAULT 0" json:"completeness"`
Liveness float64 `xorm:"NOT NULL DEFAULT 0" json:"liveness"`
ProjectHealth float64 `xorm:"NOT NULL DEFAULT 0" json:"projectHealth"`
TeamHealth float64 `xorm:"NOT NULL DEFAULT 0" json:"teamHealth"`
Growth float64 `xorm:"NOT NULL DEFAULT 0" json:"growth"`
RadarTotal float64 `xorm:"NOT NULL DEFAULT 0" json:"openi"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created" json:"-"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated" json:"-"`
}

func DeleteRepoStatDaily(date string) error {
@@ -81,9 +81,60 @@ func DeleteRepoStatDaily(date string) error {
return nil
}

func GetRepoStatisticByDate(date string) ([]*RepoStatistic, error) {
func CountRepoStatByRawSql(sql string) (int64, error) {

return xStatistic.SQL(sql).Count()

}

func GetRepoStatisticByRawSql(sql string) []*RepoStatistic {
repoStatistics := make([]*RepoStatistic, 0)
xStatistic.SQL(sql).Find(&repoStatistics)
return repoStatistics
}

func GetRepoStatLastUpdatedTime(repoId ...string) (string, string, error) {

repoStatistic := new(RepoStatistic)
var has bool
var err error
if len(repoId) == 0 {
has, err = xStatistic.Desc("created_unix").Limit(1).Cols("created_unix", "date").Get(repoStatistic)

} else {
has, err = xStatistic.Where("repo_id=?", repoId[0]).Desc("created_unix").Limit(1).Cols("created_unix", "date").Get(repoStatistic)
}

if err != nil {
return "", "", err
} else {
if has {
return repoStatistic.CreatedUnix.Format("2006-01-02 15:04:05"), repoStatistic.Date, nil
} else {
return "", "", fmt.Errorf("Can not get the latest record.")
}
}

}

func GetRepoStatisticByDateAndRepoId(date string, repoId int64) (*RepoStatistic, error) {
repoStatistic := new(RepoStatistic)
has, err := xStatistic.Where("date=? and repo_id=?", date, repoId).Get(repoStatistic)
if err != nil {
return nil, err
} else {
if has {
return repoStatistic, nil
} else {
return nil, fmt.Errorf("The num of return records is 0.")
}
}

}

func GetRepoStatisticByDate(date string, repoId int64) ([]*RepoStatistic, error) {
repoStatistics := make([]*RepoStatistic, 0)
err := xStatistic.Where("date = ?", date).Find(&repoStatistics)
err := xStatistic.Where("date = ? and repo_id=?", date, repoId).Find(&repoStatistics)
return repoStatistics, err

}


+ 10
- 3
modules/modelarts/modelarts.go View File

@@ -159,7 +159,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description string) error
JobID: jobResult.ID,
JobName: jobName,
JobType: string(models.JobTypeDebug),
Type: models.TypeCloudBrainNotebook,
Type: models.TypeCloudBrainTwo,
Uuid: uuid,
})

@@ -195,17 +195,24 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) error {
return err
}

attach, err := models.GetAttachmentByUUID(req.Uuid)
if err != nil {
log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error())
return nil
}

err = models.CreateCloudbrain(&models.Cloudbrain{
Status: TransTrainJobStatus(jobResult.Status),
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
JobID: strconv.FormatInt(jobResult.JobID, 10),
JobName: req.JobName,
JobType: string(models.JobTypeDebug),
Type: models.TypeCloudBrainTrainJob,
JobType: string(models.JobTypeTrain),
Type: models.TypeCloudBrainTwo,
VersionID: jobResult.VersionID,
VersionName: jobResult.VersionName,
Uuid: req.Uuid,
DatasetName: attach.Name,
})

if err != nil {


+ 0
- 4
modules/modelarts/resty.go View File

@@ -366,10 +366,6 @@ sendjob:
return &result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error())
}
log.Error("createTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
if res.StatusCode() == 400 {
temp.ErrorCode = "0404"
temp.ErrorMsg = "启动文件未找到!"
}
return &result, fmt.Errorf("createTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg)
}



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

@@ -544,6 +544,7 @@ var (
GrowthContributors float64
GrowthCommit float64
GrowthComments float64
RecordBeginTime string
}{}
)

@@ -1324,6 +1325,7 @@ func SetRadarMapConfig() {
RadarMap.GrowthContributors = sec.Key("growth_contributors").MustFloat64(0.2)
RadarMap.GrowthCommit = sec.Key("growth_commit").MustFloat64(0.2)
RadarMap.GrowthComments = sec.Key("growth_comments").MustFloat64(0.2)
RadarMap.RecordBeginTime = sec.Key("record_beigin_time").MustString("2021-11-04")

}



+ 15
- 9
options/locale/locale_en-US.ini View File

@@ -764,15 +764,15 @@ submit_image=Submit Image
download=Download


cloudbrain=cloudbrain
cloudbrain=Cloudbrain
cloudbrain.new=New cloudbrain
cloudbrain.desc=cloudbrain
cloudbrain.desc=Cloudbrain
cloudbrain.cancel=Cancel
cloudbrain.commit_image = submit
clone_cnt=download
balance = balance
balance.total_view = total balance
balance.available = available balance:
cloudbrain.commit_image = Submit
clone_cnt=Download
balance = Balance
balance.total_view = Total Balance
balance.available = Available Balance:
cloudbrain1 = cloudbrain1
cloudbrain2 = cloudbrain2
cloudbrain_selection = select cloudbrain
@@ -785,13 +785,19 @@ cloudbrain_operate = Operate
cloudbrain_status_createtime = Status/Createtime
cloudbrain_status_runtime = Running Time


record_begintime_get_err=Can not get the record begin time.
parameter_is_wrong=The input parameter is wrong.
total_count_get_error=Can not get the total page.
last_update_time_error=Can not get the last updated time.
get_repo_stat_error=Can not get the statistics of the repository.
get_repo_info_error=Can not get the information of the repository.
modelarts.notebook=Debug Task
modelarts.train_job=Create Task
modelarts.train_job=Train Task
modelarts.train_job.new_debug= New Debug Task
modelarts.train_job.new_train=New Train Task
modelarts.train_job.config=Configuration information
modelarts.train_job.new=New train Task
modelarts.train_job.new_place=The description should not exceed 256 characters





+ 14
- 7
options/locale/locale_zh-CN.ini View File

@@ -787,22 +787,29 @@ cloudbrain_status_createtime=状态/创建时间
cloudbrain_status_runtime = 运行时长
cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。

record_begintime_get_err=无法获取统计开始时间。
parameter_is_wrong=输入参数错误,请检查输入参数。
total_count_get_error=查询总页数失败。
last_update_time_error=查询最新更新时间失败。
get_repo_stat_error=查询当前仓库的统计信息失败。
get_repo_info_error=查询当前仓库信息失败。
modelarts.notebook=调试任务
modelarts.train_job=训练任务
modelarts.train_job.new_debug=新建调试任务
modelarts.train_job.new_train=新建训练任务
modelarts.train_job.config=配置信息
modelarts.train_job.new=新建训练任务
modelarts.train_job.new_place=描述字数不超过256个字符



modelarts.train_job.basic_info=基本信息
modelarts.train_job.job_status=作业状态
modelarts.train_job.job_name=作业名称
modelarts.train_job.version=作业版本
modelarts.train_job.job_status=任务状态
modelarts.train_job.job_name=任务名称
modelarts.train_job.version=任务版本
modelarts.train_job.start_time=开始时间
modelarts.train_job.dura_time=运行时长
modelarts.train_job.description=作业描述
modelarts.train_job.description=任务描述
modelarts.train_job.parameter_setting=参数设置
modelarts.train_job.parameter_setting_info=参数信息
modelarts.train_job.fast_parameter_setting=一键式参数配置
@@ -830,12 +837,12 @@ modelarts.train_job.query_whether_save_parameter=保存作业参数
modelarts.train_job.save_helper=保存当前作业的配置参数,后续您可以使用已保存的配置参数快速创建训练作业。
modelarts.train_job.common_frame=常用框架
modelarts.train_job.amount_of_compute_node=计算节点个数
modelarts.train_job.job_parameter_name=作业参数名称
modelarts.train_job.parameter_description=作业参数描述
modelarts.train_job.job_parameter_name=任务参数名称
modelarts.train_job.parameter_description=任务参数描述
modelarts.log=日志
modelarts.version_manage=版本管理
modelarts.back=返回
modelarts.train_job_para_admin=作业参数管理
modelarts.train_job_para_admin=任务参数管理
modelarts.train_job_para.edit=编辑
modelarts.train_job_para.connfirm=确定



+ 13
- 0
routers/api/v1/api.go View File

@@ -523,6 +523,19 @@ func RegisterRoutes(m *macaron.Macaron) {
Get(notify.GetThread).
Patch(notify.ReadThread)
}, reqToken())
adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true})
//Project board
m.Group("/projectboard", func() {

m.Group("/project", func() {
m.Get("", adminReq, repo.GetAllProjectsPeriodStatistics)
m.Group("/:id", func() {
m.Get("", adminReq, repo.GetProjectLatestStatistics)
m.Get("/period", adminReq, repo.GetProjectPeriodStatistics)

})
})
})

// Users
m.Group("/users", func() {


+ 362
- 0
routers/api/v1/repo/repo_dashbord.go View File

@@ -0,0 +1,362 @@
package repo

import (
"fmt"
"net/http"
"strconv"
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"

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

const DEFAULT_PAGE_SIZE = 10
const DATE_FORMAT = "2006-01-02"

type ProjectsPeriodData struct {
RecordBeginTime string `json:"recordBeginTime"`
LastUpdatedTime string `json:"lastUpdatedTime"`
PageSize int `json:"pageSize"`
TotalPage int `json:"totalPage"`
PageRecords []*models.RepoStatistic `json:"pageRecords"`
}

type UserInfo struct {
User string `json:"user"`
Mode int `json:"mode"`
PR int64 `json:"pr"`
Commit int `json:"commit"`
}

type ProjectLatestData struct {
RecordBeginTime string `json:"recordBeginTime"`
LastUpdatedTime string `json:"lastUpdatedTime"`
CreatTime string `json:"creatTime"`
OpenI float64 `json:"openi"`
Comment int64 `json:"comment"`
View int64 `json:"view"`
Download int64 `json:"download"`
IssueClosedRatio float32 `json:"issueClosedRatio"`
Impact float64 `json:"impact"`
Completeness float64 `json:"completeness"`
Liveness float64 `json:"liveness"`
ProjectHealth float64 `json:"projectHealth"`
TeamHealth float64 `json:"teamHealth"`
Growth float64 `json:"growth"`
Description string `json:"description"`
Top10 []UserInfo `json:"top10"`
}

func GetAllProjectsPeriodStatistics(ctx *context.Context) {

recordBeginTime, err := getRecordBeginTime()
if err != nil {
log.Error("Can not get record begin time", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)
if err != nil {
log.Error("Parameter is wrong", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong"))
return
}
q := ctx.QueryTrim("q")
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
pageSize := ctx.QueryInt("pagesize")
if pageSize <= 0 {
pageSize = DEFAULT_PAGE_SIZE
}
orderBy := getOrderBy(ctx)

latestUpdatedTime, latestDate, err := models.GetRepoStatLastUpdatedTime()
if err != nil {
log.Error("Can not query the last updated time.", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error"))
return
}

countSql := generateCountSql(beginTime, endTime, latestDate, q)
total, err := models.CountRepoStatByRawSql(countSql)
if err != nil {
log.Error("Can not query total count.", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.total_count_get_error"))
return
}

projectsPeriodData := ProjectsPeriodData{
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT),
PageSize: pageSize,
TotalPage: getTotalPage(total, pageSize),
LastUpdatedTime: latestUpdatedTime,
PageRecords: models.GetRepoStatisticByRawSql(generatePageSql(beginTime, endTime, latestDate, q, orderBy, page, pageSize)),
}

ctx.JSON(http.StatusOK, projectsPeriodData)

}

func GetProjectLatestStatistics(ctx *context.Context) {
repoId := ctx.Params(":id")
recordBeginTime, err := getRecordBeginTime()
if err != nil {
log.Error("Can not get record begin time", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}
latestUpdatedTime, latestDate, err := models.GetRepoStatLastUpdatedTime(repoId)
repoIdInt, _ := strconv.ParseInt(repoId, 10, 64)
repoStat, err := models.GetRepoStatisticByDateAndRepoId(latestDate, repoIdInt)
if err != nil {
log.Error("Can not get the repo statistics "+repoId, err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.get_repo_stat_error"))
return
}

repository, err := models.GetRepositoryByID(repoIdInt)
if err != nil {
log.Error("Can not get the repo info "+repoId, err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.get_repo_info_error"))
return
}
projectLatestData := ProjectLatestData{
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT),
CreatTime: time.Unix(int64(repository.CreatedUnix), 0).Format(DATE_FORMAT),
LastUpdatedTime: latestUpdatedTime,
OpenI: repoStat.RadarTotal,
Comment: repoStat.NumComments,
View: repoStat.NumVisits,
Download: repoStat.NumDownloads,
IssueClosedRatio: repoStat.IssueFixedRate,
Impact: repoStat.Impact,
Completeness: repoStat.Completeness,
Liveness: repoStat.Liveness,
ProjectHealth: repoStat.ProjectHealth,
TeamHealth: repoStat.TeamHealth,
Growth: repoStat.Growth,
Description: repository.Description,
}

contributors, err := models.GetTop10Contributor(repository.RepoPath())
if err != nil {
log.Error("can not get contributors", err)
}
users := make([]UserInfo, 0)

for _, contributor := range contributors {
mode := repository.GetCollaboratorMode(contributor.UserId)
pr := models.GetPullCountByUserAndRepoId(repoIdInt, contributor.UserId)
userInfo := UserInfo{
User: contributor.Committer,
Commit: contributor.CommitCnt,
Mode: mode,
PR: pr,
}
users = append(users, userInfo)

}

projectLatestData.Top10 = users

ctx.JSON(http.StatusOK, projectLatestData)

}

func GetProjectPeriodStatistics(ctx *context.Context) {
repoId := ctx.Params(":id")
recordBeginTime, err := getRecordBeginTime()
if err != nil {
log.Error("Can not get record begin time", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}

repoIdInt, _ := strconv.ParseInt(repoId, 10, 64)

if err != nil {
log.Error("Can not get record begin time", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
return
}
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)
isOpenI := ctx.QueryBool("openi")
var repositorys []*models.RepoStatistic
if isOpenI {
repositorys = models.GetRepoStatisticByRawSql(generateRadarSql(beginTime, endTime, repoIdInt))
} else {
repositorys = models.GetRepoStatisticByRawSql(generateTargetSql(beginTime, endTime, repoIdInt))
}
ctx.JSON(http.StatusOK, repositorys)
}

func generateRadarSql(beginTime time.Time, endTime time.Time, repoId int64) string {
sql := "SELECT date, impact, completeness, liveness, project_health, team_health, growth, radar_total FROM repo_statistic" +
" where repo_id=" + strconv.FormatInt(repoId, 10) + " and created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)

return sql
}

func generateTargetSql(beginTime time.Time, endTime time.Time, repoId int64) string {
sql := "SELECT date, num_visits,num_downloads,num_commits FROM repo_statistic" +
" where repo_id=" + strconv.FormatInt(repoId, 10) + " and created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)

return sql
}

func generateCountSql(beginTime time.Time, endTime time.Time, yesterday string, q string) string {
countSql := "SELECT count(*) FROM " +
"(SELECT repo_id FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," +
"(SELECT repo_id,name,is_private,radar_total from public.repo_statistic where date='" + yesterday + "') B" +
" where A.repo_id=B.repo_id"
if q != "" {
countSql = countSql + " and B.name like '%" + q + "%'"
}
return countSql
}

func generatePageSql(beginTime time.Time, endTime time.Time, yesterday string, q string, orderBy string, page int, pageSize int) string {
countSql := "SELECT A.repo_id,name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " +
"(SELECT repo_id,sum(num_watches_added) as num_watches,sum(num_visits) as num_visits, sum(num_downloads_added) as num_downloads,sum(num_pulls_added) as num_pulls,sum(num_commits_added) as num_commits,sum(num_stars_added) as num_stars,sum(num_forks_added) num_forks,sum(num_issues_added) as num_issues,sum(num_closed_issues_added) as num_closed_issues,sum(num_contributor_added) as num_contributor " +
" FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," +
"(SELECT repo_id,name,is_private,radar_total from public.repo_statistic where date='" + yesterday + "') B" +
" where A.repo_id=B.repo_id"
if q != "" {
countSql = countSql + " and B.name like '%" + q + "%'"
}
countSql = countSql + " order by " + orderBy + " desc,A.repo_id" + " limit " + strconv.Itoa(pageSize) + " offset " + strconv.Itoa((page-1)*pageSize)
return countSql
}

func getOrderBy(ctx *context.Context) string {
orderBy := ""
switch ctx.Query("sort") {
case "openi":
orderBy = "B.radar_total"
case "view":
orderBy = "A.num_visits"
case "download":
orderBy = "A.num_downloads"
case "pr":
orderBy = "A.num_pulls"
case "commit":
orderBy = "A.num_commits"
case "watch":
orderBy = "A.num_watches"
case "star":
orderBy = "A.num_stars"
case "fork":
orderBy = "A.num_forks"
case "issue":
orderBy = "A.num_issues"
case "issue_closed":
orderBy = "A.num_closed_issues"
case "contributor":
orderBy = "A.num_contributor"
default:
orderBy = "B.radar_total"
}
return orderBy
}

func getTimePeroid(ctx *context.Context, recordBeginTime time.Time) (time.Time, time.Time, error) {
queryType := ctx.QueryTrim("type")
now := time.Now()
recordBeginTimeTemp := recordBeginTime.AddDate(0, 0, 1)

beginTimeStr := ctx.QueryTrim("beginTime")
endTimeStr := ctx.QueryTrim("endTime")
var beginTime time.Time
var endTime time.Time

if queryType != "" {

if queryType == "all" {
beginTime = recordBeginTimeTemp
endTime = now
} else if queryType == "yesterday" {
endTime = now
beginTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location())

} else if queryType == "current_week" {
beginTime = now.AddDate(0, 0, -int(time.Now().Weekday())+1)
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location())
endTime = now
} else if queryType == "current_month" {
endTime = now
beginTime = time.Date(endTime.Year(), endTime.Month(), 2, 0, 0, 0, 0, now.Location())
} else if queryType == "monthly" {
endTime = now
beginTime = now.AddDate(0, -1, 1)
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location())

} else if queryType == "current_year" {
endTime = now
beginTime = time.Date(endTime.Year(), 1, 2, 0, 0, 0, 0, now.Location())

} else if queryType == "last_month" {

lastMonthTime := now.AddDate(0, -1, 0)
beginTime = time.Date(lastMonthTime.Year(), lastMonthTime.Month(), 2, 0, 0, 0, 0, now.Location())
endTime = time.Date(now.Year(), now.Month(), 2, 0, 0, 0, 0, now.Location())

} else {
return now, now, fmt.Errorf("The value of type parameter is wrong.")

}

} else {
if beginTimeStr == "" || endTimeStr == "" {
//如果查询类型和开始时间结束时间都未设置,按queryType=all处理
beginTime = recordBeginTimeTemp
endTime = now

} else {

beginTime, err := time.Parse("2006-01-02", beginTimeStr)
if err != nil {
return now, now, err
}

endTime, err := time.Parse("2006-01-02", endTimeStr)
if err != nil {
return now, now, err
}

beginTime = beginTime.AddDate(0, 0, 1)
endTime = endTime.AddDate(0, 0, 1)
}

}

if beginTime.Before(recordBeginTimeTemp) {
beginTime = recordBeginTimeTemp
}

return beginTime, endTime, nil

}

func getRecordBeginTime() (time.Time, error) {

return time.Parse(DATE_FORMAT, setting.RadarMap.RecordBeginTime)
}

func getTotalPage(total int64, pageSize int) int {

another := 0
if int(total)%pageSize != 0 {
another = 1
}
return int(total)/pageSize + another

}

+ 1
- 1
routers/home.go View File

@@ -146,7 +146,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
ctx.Data["SortType"] = "hot"
orderBy = models.SearchOrderByHot
}
orderBy = orderBy + ",id"
//todo:support other topics
keyword := strings.Trim(ctx.Query("q"), " ")
topic := strings.Trim(ctx.Query("topic"), " ")


+ 14
- 8
routers/repo/attachment.go View File

@@ -917,16 +917,22 @@ func HandleUnDecompressAttachment() {
}

for _, attach := range attachs {
err = worker.SendDecompressTask(contexExt.Background(), attach.UUID, attach.Name)
if err != nil {
log.Error("SendDecompressTask(%s) failed:%s", attach.UUID, err.Error())
} else {
attach.DecompressState = models.DecompressStateIng
err = models.UpdateAttachment(attach)
if attach.Type == models.TypeCloudBrainOne {
err = worker.SendDecompressTask(contexExt.Background(), attach.UUID, attach.Name)
if err != nil {
log.Error("UpdateAttachment state(%s) failed:%s", attach.UUID, err.Error())
log.Error("SendDecompressTask(%s) failed:%s", attach.UUID, err.Error())
} else {
attach.DecompressState = models.DecompressStateIng
err = models.UpdateAttachment(attach)
if err != nil {
log.Error("UpdateAttachment state(%s) failed:%s", attach.UUID, err.Error())
}
}
} else if attach.Type == models.TypeCloudBrainTwo {
attachjson, _ := json.Marshal(attach)
labelmsg.SendDecompressAttachToLabelOBS(string(attachjson))
}

}

return
@@ -1014,7 +1020,7 @@ func queryDatasets(ctx *context.Context, attachs []*models.AttachmentUsername) {
}

func checkTypeCloudBrain(typeCloudBrain int) error {
if typeCloudBrain != models.TypeCloudBrainOne && typeCloudBrain != models.TypeCloudBrainNotebook {
if typeCloudBrain != models.TypeCloudBrainOne && typeCloudBrain != models.TypeCloudBrainTwo {
log.Error("type error:", typeCloudBrain)
return errors.New("type error")
}


+ 43
- 17
routers/repo/modelarts.go View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"os"
"path"
@@ -35,10 +36,10 @@ const (
tplModelArtsNew base.TplName = "repo/modelarts/new"
tplModelArtsShow base.TplName = "repo/modelarts/show"

tplModelArtsTrainJobIndex base.TplName = "repo/modelarts/trainjob/index"
tplModelArtsTrainJobNew base.TplName = "repo/modelarts/trainjob/new"
tplModelArtsTrainJobShow base.TplName = "repo/modelarts/trainjob/show"
tplModelArtsTrainJobShowModels base.TplName = "repo/modelarts/trainjob/models/index"
tplModelArtsTrainJobIndex base.TplName = "repo/modelarts/trainjob/index"
tplModelArtsTrainJobNew base.TplName = "repo/modelarts/trainjob/new"
tplModelArtsTrainJobShow base.TplName = "repo/modelarts/trainjob/show"
tplModelArtsTrainJobShowModels base.TplName = "repo/modelarts/trainjob/models/index"
)

// MustEnableDataset check if repository enable internal cb
@@ -286,7 +287,8 @@ func NotebookIndex(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
Type: models.TypeCloudBrainNotebook,
Type: models.TypeCloudBrainTwo,
JobType: string(models.JobTypeDebug),
})
if err != nil {
ctx.ServerError("Cloudbrain", err)
@@ -511,7 +513,8 @@ func TrainJobIndex(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
Type: models.TypeCloudBrainTrainJob,
Type: models.TypeCloudBrainTwo,
JobType: string(models.JobTypeTrain),
})
if err != nil {
ctx.ServerError("Cloudbrain", err)
@@ -621,7 +624,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath
dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + "/"
dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/"

//can, err := canUserCreateTrainJob(ctx.User.ID)
//if err != nil {
@@ -643,10 +646,29 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
return
}

attach, err := models.GetAttachmentByUUID(uuid)
if err != nil {
log.Error("GetAttachmentByUUID(%s) failed:%v", uuid, err.Error())
return
}

//todo: del the codeLocalPath
_, err = ioutil.ReadDir(codeLocalPath)
if err == nil {
os.RemoveAll(codeLocalPath)
}
if err := git.Clone(repo.RepoPath(), codeLocalPath, git.CloneRepoOptions{}); err != nil {
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
log.Error("创建任务失败,任务名称已存在!: %s (%v)", repo.FullName(), err)
trainJobNewDataPrepare(ctx)
ctx.RenderWithErr("Failed to clone repository", tplModelArtsTrainJobNew, &form)

ctx.Data["bootFile"] = form.BootFile
ctx.Data["uuid"] = form.Attachment
ctx.Data["datasetName"] = attach.Name
ctx.Data["params"] = form.Params
trainJobNewDataPrepare(ctx)
// ctx.RenderWithErr("Failed to clone repository", tplModelArtsTrainJobNew, &form)
ctx.RenderWithErr("创建任务失败,任务名称已存在!", tplModelArtsTrainJobNew, &form)
// ctx.RenderWithErr(err, tplModelArtsTrainJobNew, &form)
return
}

@@ -752,10 +774,14 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
Parameters: param,
}

err := modelarts.GenerateTrainJob(ctx, req)
err = modelarts.GenerateTrainJob(ctx, req)
if err != nil {
log.Error("GenerateTrainJob failed:%v", err.Error())
trainJobNewDataPrepare(ctx)
ctx.Data["bootFile"] = form.BootFile
ctx.Data["uuid"] = form.Attachment
ctx.Data["datasetName"] = attach.Name
ctx.Data["params"] = form.Params
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form)
return
}
@@ -860,12 +886,12 @@ func TrainJobShow(ctx *context.Context) {
return
}

attach, err := models.GetAttachmentByUUID(task.Uuid)
if err != nil {
log.Error("GetAttachmentByUUID(%s) failed:%v", jobID, err.Error())
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil)
return
}
// attach, err := models.GetAttachmentByUUID(task.Uuid)
// if err != nil {
// log.Error("GetAttachmentByUUID(%s) failed:%v", jobID, err.Error())
// ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil)
// return
// }

result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(task.VersionID, 10))
if err != nil {
@@ -889,7 +915,7 @@ func TrainJobShow(ctx *context.Context) {
return
}

result.DatasetName = attach.Name
result.DatasetName = task.DatasetName
}

resultLogFile, resultLog, err := trainJobGetLog(jobID)


+ 1
- 1
routers/repo/repo_statistic.go View File

@@ -115,7 +115,7 @@ func RepoStatisticDaily(date string) {
}

dayBeforeDate := t.AddDate(0, 0, -1).Format("2006-01-02")
repoStatisticsBefore, err := models.GetRepoStatisticByDate(dayBeforeDate)
repoStatisticsBefore, err := models.GetRepoStatisticByDate(dayBeforeDate, repo.ID)

if err != nil {
log.Error("get data of day before the date failed ", err)


+ 8
- 6
templates/repo/modelarts/notebook/index.tmpl View File

@@ -324,7 +324,7 @@
<form id="stopForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/stop" method="post" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}}
<a id="stop-model-debug-{{.JobID}}" style="margin-right: 2rem;" class="ui basic {{if or (eq .Status "STOPPED") (eq .Status "FAILED") (eq .Status "START_FAILED")}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();">
<a id="stop-model-debug-{{.JobID}}" style="margin-right: 2rem;" class="ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();">
{{$.i18n.Tr "repo.stop"}}
</a>
{{else}}
@@ -352,7 +352,7 @@
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post">
{{$.CsrfTokenHtml}}
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}}
<a id="model-delete-{{.JobID}}" class="ui compact {{if eq .Status "RUNNING"}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
<a id="model-delete-{{.JobID}}" class="ui compact {{if eq .Status "RUNNING" "CREATING" "WAITING" "STARTING" "STOPPING" }}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
{{else}}
@@ -477,10 +477,10 @@

}
if(status!=="STOPPED" || status!=="FAILED"){
$('#stop-model-debug-'+jobID).removeClass('disabled')
$('#stop-model-debug-'+jobID).addClass('blue')
$('#model-delete-'+jobID).removeClass('red')
$('#model-delete-'+jobID).addClass('disabled')
// $('#stop-model-debug-'+jobID).removeClass('disabled')
// $('#stop-model-debug-'+jobID).addClass('blue')
// $('#model-delete-'+jobID).removeClass('red')
// $('#model-delete-'+jobID).addClass('disabled')
}
if(status=="STOPPED" || status=="FAILED" ){
$('#stop-model-debug-'+jobID).removeClass('blue')
@@ -491,6 +491,8 @@
if(status=="START_FAILED"){
$('#stop-model-debug-'+jobID).removeClass('blue')
$('#stop-model-debug-'+jobID).addClass('disabled')
$('#model-delete-'+jobID).removeClass('disabled')
$('#model-delete-'+jobID).addClass('red')
}
}).fail(function(err) {
console.log(err);


+ 4
- 4
templates/repo/modelarts/trainjob/index.tmpl View File

@@ -291,7 +291,7 @@
<span>{{$.i18n.Tr "repo.cloudbrain_creator"}}</span>
</div>
<div class="five wide column text center">
<span>{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
<span style="margin-left: 6rem;">{{$.i18n.Tr "repo.cloudbrain_operate"}}</span>
</div>

</div>
@@ -355,7 +355,7 @@
<form id="stopForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/stop" method="post" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}}
<a id="stop-model-debug-{{.JobID}}" class="ui basic {{if or (eq .Status "KILLED") (eq .Status "FAILED") (eq .Status "START_FAILED")}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();">
<a id="stop-model-debug-{{.JobID}}" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();">
{{$.i18n.Tr "repo.stop"}}
</a>
{{else}}
@@ -380,7 +380,7 @@
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post">
{{$.CsrfTokenHtml}}
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}}
<a id="model-delete-{{.JobID}}" class="ui compact {{if eq .Status "RUNNING" }}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
<a id="model-delete-{{.JobID}}" class="ui compact {{if or (eq .Status "RUNNING") (eq .Status "INIT") (eq .Status "CREATING") (eq .Status "WAITING") }}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
</a>
{{else}}
@@ -535,7 +535,7 @@
$('#model-delete-'+jobID).removeClass('red')
$('#model-delete-'+jobID).addClass('disabled')
}
if(status=="KILLED" || status=="FAILED"){
if(status=="KILLED" || status=="FAILED" || status=="KILLING"){
$('#stop-model-debug-'+jobID).removeClass('blue')
$('#stop-model-debug-'+jobID).addClass('disabled')
$('#model-delete-'+jobID).removeClass('disabled')


+ 95
- 20
templates/repo/modelarts/trainjob/new.tmpl View File

@@ -156,16 +156,12 @@
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required unite min_title inline field">
<label>{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" tabindex="3" autofocus required maxlength="255">
<input style="width: 60%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" tabindex="3" autofocus required maxlength="255">
</div>
<!--<div class="inline field">
<label>{{.i18n.Tr "repo.modelarts.train_job.version"}}</label>
<span>第一版本</span>
</div>
-->
<div class="unite min_title inline field">
<label for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}&nbsp;&nbsp;</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="256" placeholder="描述字符不超过256个字符" onchange="this.value=this.value.substring(0, 256)" onkeydown="this.value=this.value.substring(0, 256)" onkeyup="this.value=this.value.substring(0, 256)"></textarea>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea>
</div>
<!-- <h4 class="ui dividing header">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}</h4>
<div class="inline field">
@@ -182,7 +178,7 @@
<div class="required unite min_title inline fields" style="width: 90%;">
<label>{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
<div class="field" style="flex: 1.5;">
<select class="ui search dropdown width" id="trainjob_engines" >
<select class="ui dropdown width" id="trainjob_engines" >
{{range .engines}}
<option value="{{.Value}}">{{.Value}}</option>
{{end}}
@@ -190,7 +186,7 @@

</div>
<div class="field" style="flex: 2;">
<select class="ui search dropdown width" id="trainjob_engine_versions" style='width: 100%;' name="engine_id">
<select class="ui dropdown width" id="trainjob_engine_versions" style='width: 100%;' name="engine_id">
{{range .engine_versions}}
<option name="engine_id" value="{{.ID}}">{{.Value}}</option>
{{end}}
@@ -235,20 +231,28 @@
</div> -->
<div class="inline unite min_title field required">
<label>{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label>
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" >
{{if .bootFile}}
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" >
{{else}}
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" >
{{end}}
<span>
<i class="question circle icon link" data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}} data-position="right center" data-variation="mini"></i>
</span>
</div>
<div class="required unite min_title inline field">
<label>{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label>
<select class="ui search dropdown width80" id="trainjob_datasets" name="attachment">
<select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集">
{{if $.uuid}}
<option name="attachment" value="{{$.uuid}}">{{$.datasetName}}</option>
{{end}}
{{range .attachments}}
<option value="">选择数据集</option>
<option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option>
{{end}}
</select>
</div>
<div class="inline unite min_title field">
<label>{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label>
<!-- <i class="plus square outline icon"></i> -->
@@ -263,7 +267,7 @@
<!-- <h4 class="ui dividing header">{{.i18n.Tr "repo.modelarts.train_job.resource_setting"}}</h4> -->
<div class="required field " style="display: none;">
<label>{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label>
<select class="ui search dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id">
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id">
{{range .resource_pools}}
<option value="{{.ID}}">{{.Value}}</option>
{{end}}
@@ -288,7 +292,7 @@

<div class="required unite min_title inline field">
<label>{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label>
<select class="ui search dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor">
<select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor">
{{range .flavor_infos}}
<option name="flavor" value="{{.Code}}">{{.Value}}</option>
{{end}}
@@ -297,11 +301,11 @@
<div class="inline required unite min_title field">
<label>{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label>
<div class="ui labeled input">
<span class="min"><i class="minus icon"></i></span>
<input style="border-radius: 0;" name="work_server_number" id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1">
<div class="ui labeled input" style="width: 5%;">
<!-- <span class="min"><i class="minus icon"></i></span> -->
<input style="border-radius: 0;text-align: center;" name="work_server_number" id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1" readonly>
<span class="add"><i class="plus icon"></i></span>
<!-- <span class="add"><i class="plus icon"></i></span> -->
</div>
<!-- <input name="work_server_number" id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255"> -->
</div>
@@ -356,6 +360,9 @@
let sever_num = $('#trainjob_work_server_num')
$('.add').click(function(){
sever_num.val(parseInt(sever_num.val())+1)
if(sever_num.val()>=26){
sever_num.val(parseInt(sever_num.val())-1)
}
})
$('.min').click(function(){
sever_num.val(parseInt(sever_num.val())-1)
@@ -368,10 +375,10 @@
function Add_parameter(i){
value = '<div class="two fields width85" id= "para'+ i +'">' +
'<div class="field">' +
'<input type="text" name="shipping_first-name" placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}> ' +
'<input type="text" name="shipping_first-name" required placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}> ' +
'</div> ' +
'<div class="field"> ' +
'<input type="text" name="shipping_last-name" placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}>' +
'<input type="text" name="shipping_last-name" required placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}>' +
'</div>'+
'<span>' +
'<i class="trash icon">' +
@@ -471,6 +478,55 @@
$('.ui.parameter.modal')
.modal('hide');
})
$('select.dropdown')
.dropdown();

$('.ui.form')
.form({
on: 'blur',
inline:true,
fields: {
boot_file: {
identifier : 'boot_file',
rules: [
{
type: 'regExp[/.+\.py$/g]',
prompt : '启动文件必须为.py结尾'
}
]
},
job_name:{
identifier : 'job_name',
rules: [
{
type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]',
prompt : '只包含大小写字母、数字、_和-,最长36个字符。'
}
]
},
attachment:{
identifier : 'attachment',
rules: [
{
type: 'empty',
prompt : '选择一个数据集'
}
]

},
work_server_number: {
identifier : 'work_server_number',
rules: [
{
type : 'integer[1..25]',
prompt : '计算节点需要在1-25之间,请您键入正确的值'
}
]
}
},
})



function validate(){
$('.ui.form')
@@ -487,6 +543,25 @@
}
]
},
job_name:{
identifier : 'job_name',
rules: [
{
type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]',
prompt : '只包含大小写字母、数字、_和-,最长36个字符。'
}
]
},
attachment:{
identifier : 'attachment',
rules: [
{
type: 'empty',
prompt : '选择一个数据集'
}
]

},
work_server_number: {
identifier : 'work_server_number',
rules: [


Loading…
Cancel
Save