diff --git a/models/action.go b/models/action.go index 4821910db..2a9d88399 100755 --- a/models/action.go +++ b/models/action.go @@ -49,6 +49,14 @@ const ( ActionApprovePullRequest // 21 ActionRejectPullRequest // 22 ActionCommentPull // 23 + + ActionUploadAttachment //24 + ActionCreateDebugGPUTask //25 + ActionCreateDebugNPUTask //26 + ActionCreateTrainTask //27 + ActionCreateInferenceTask // 28 + ActionCreateBenchMarkTask //29 + ActionCreateNewModelTask //30 ) // Action represents user operation type and other information to diff --git a/models/cloudbrain.go b/models/cloudbrain.go index 6115792ba..d7a7b73e1 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -103,7 +103,7 @@ type Cloudbrain struct { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` Duration int64 TrainJobDuration string - Image string //GPU镜像名称 + Image string //镜像名称 GpuQueue string //GPU类型即GPU队列 ResourceSpecId int //GPU规格id DeletedAt time.Time `xorm:"deleted"` @@ -220,17 +220,20 @@ type GetImagesPayload struct { type CloudbrainsOptions struct { ListOptions - RepoID int64 // include all repos if empty - UserID int64 - JobID string - SortType string - CloudbrainIDs []int64 - // JobStatus CloudbrainStatus + RepoID int64 // include all repos if empty + UserID int64 + JobID string + SortType string + CloudbrainIDs []int64 + JobStatus []string + JobStatusNot bool + Keyword string Type int JobTypes []string VersionName string IsLatestVersion string JobTypeNot bool + NeedRepoInfo bool } type TaskPod struct { @@ -450,6 +453,16 @@ type FlavorInfo struct { Desc string `json:"desc"` } +type ImageInfosModelArts struct { + ImageInfo []*ImageInfoModelArts `json:"image_info"` +} + +type ImageInfoModelArts struct { + Id string `json:"id"` + Value string `json:"value"` + Desc string `json:"desc"` +} + type PoolInfos struct { PoolInfo []*PoolInfo `json:"pool_info"` } @@ -1073,16 +1086,39 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { } if (opts.IsLatestVersion) != "" { - cond = cond.And( - builder.Eq{"cloudbrain.is_latest_version": opts.IsLatestVersion}, - ) + cond = cond.And(builder.Or(builder.And(builder.Eq{"cloudbrain.is_latest_version": opts.IsLatestVersion}, builder.Eq{"cloudbrain.job_type": "TRAIN"}), builder.Neq{"cloudbrain.job_type": "TRAIN"})) } if len(opts.CloudbrainIDs) > 0 { cond = cond.And(builder.In("cloudbrain.id", opts.CloudbrainIDs)) } - count, err := sess.Where(cond).Count(new(Cloudbrain)) + if len(opts.JobStatus) > 0 { + if opts.JobStatusNot { + cond = cond.And( + builder.NotIn("cloudbrain.status", opts.JobStatus), + ) + } else { + cond = cond.And( + builder.In("cloudbrain.status", opts.JobStatus), + ) + } + } + + var count int64 + var err error + condition := "cloudbrain.user_id = `user`.id" + if len(opts.Keyword) == 0 { + count, err = sess.Where(cond).Count(new(Cloudbrain)) + } else { + lowerKeyWord := strings.ToLower(opts.Keyword) + + cond = cond.And(builder.Or(builder.Like{"LOWER(cloudbrain.job_name)", lowerKeyWord}, builder.Like{"`user`.lower_name", lowerKeyWord})) + count, err = sess.Table(&Cloudbrain{}).Where(cond). + Join("left", "`user`", condition).Count(new(CloudbrainInfo)) + + } + if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) } @@ -1100,11 +1136,25 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { sess.OrderBy("cloudbrain.created_unix DESC") cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) if err := sess.Table(&Cloudbrain{}).Where(cond). - Join("left", "`user`", "cloudbrain.user_id = `user`.id"). + Join("left", "`user`", condition). Find(&cloudbrains); err != nil { return nil, 0, fmt.Errorf("Find: %v", err) } + if opts.NeedRepoInfo { + var ids []int64 + for _, task := range cloudbrains { + ids = append(ids, task.RepoID) + } + repositoryMap, err := GetRepositoriesMapByIDs(ids) + if err == nil { + for _, task := range cloudbrains { + task.Repo = repositoryMap[task.RepoID] + } + } + + } + return cloudbrains, count, nil } diff --git a/modules/auth/modelarts.go b/modules/auth/modelarts.go index 74d9ea831..00ee1d551 100755 --- a/modules/auth/modelarts.go +++ b/modules/auth/modelarts.go @@ -19,7 +19,8 @@ type CreateModelArtsNotebookForm struct { JobName string `form:"job_name" binding:"Required"` Attachment string `form:"attachment"` Description string `form:"description"` - Flavor string `form:"flavor"` + Flavor string `form:"flavor" binding:"Required"` + ImageId string `form:"image_id" binding:"Required"` } func (f *CreateModelArtsNotebookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go index f15443b30..b86a2d3f4 100755 --- a/modules/cloudbrain/cloudbrain.go +++ b/modules/cloudbrain/cloudbrain.go @@ -1,16 +1,17 @@ package cloudbrain import ( - "code.gitea.io/gitea/modules/storage" "encoding/json" "errors" "strconv" - "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" + "code.gitea.io/gitea/modules/setting" ) const ( @@ -221,13 +222,19 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, ComputeResource: models.GPUResource, BenchmarkTypeID: benchmarkTypeID, BenchmarkChildTypeID: benchmarkChildTypeID, - Description: description, + Description: description, }) if err != nil { return err } + if string(models.JobTypeBenchmark) == jobType { + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, jobName, models.ActionCreateBenchMarkTask) + } else { + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, jobName, models.ActionCreateDebugGPUTask) + } + return nil } diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go index 03280d36f..06a145e13 100755 --- a/modules/modelarts/modelarts.go +++ b/modules/modelarts/modelarts.go @@ -2,6 +2,7 @@ package modelarts import ( "encoding/json" + "errors" "fmt" "path" "strconv" @@ -9,6 +10,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" ) @@ -63,6 +65,7 @@ const ( var ( poolInfos *models.PoolInfos FlavorInfos *models.FlavorInfos + ImageInfos *models.ImageInfosModelArts ) type GenerateTrainJobReq struct { @@ -260,24 +263,31 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin if err != nil { return err } - + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobResult.ID, jobName, models.ActionCreateDebugNPUTask) return nil } -func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor string) error { +func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor, imageId string) error { if poolInfos == nil { json.Unmarshal([]byte(setting.PoolInfos), &poolInfos) } + + imageName, err := GetNotebookImageName(imageId) + if err != nil { + log.Error("GetNotebookImageName failed: %v", err.Error()) + return err + } + jobResult, err := createNotebook2(models.CreateNotebook2Params{ JobName: jobName, Description: description, Flavor: flavor, Duration: autoStopDurationMs, - ImageID: "59a6e9f5-93c0-44dd-85b0-82f390c5d53a", + ImageID: imageId, PoolID: poolInfos.PoolInfo[0].PoolId, Feature: models.NotebookFeature, Volume: models.VolumeReq{ - Capacity: 100, + Capacity: setting.Capacity, Category: models.EVSCategory, Ownership: models.ManagedOwnership, }, @@ -288,7 +298,7 @@ func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor return err } err = models.CreateCloudbrain(&models.Cloudbrain{ - Status: string(models.JobWaiting), + Status: jobResult.Status, UserID: ctx.User.ID, RepoID: ctx.Repo.Repository.ID, JobID: jobResult.ID, @@ -297,12 +307,14 @@ func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor Type: models.TypeCloudBrainTwo, Uuid: uuid, ComputeResource: models.NPUResource, + Image: imageName, + Description: description, }) if err != nil { return err } - + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobResult.ID, jobName, models.ActionCreateDebugNPUTask) return nil } @@ -336,12 +348,12 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error()) return err } - + jobId := strconv.FormatInt(jobResult.JobID, 10) err = models.CreateCloudbrain(&models.Cloudbrain{ Status: TransTrainJobStatus(jobResult.Status), UserID: ctx.User.ID, RepoID: ctx.Repo.Repository.ID, - JobID: strconv.FormatInt(jobResult.JobID, 10), + JobID: jobId, JobName: req.JobName, DisplayJobName: req.DisplayJobName, JobType: string(models.JobTypeTrain), @@ -373,7 +385,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error()) return err } - + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobId, req.JobName, models.ActionCreateTrainTask) return nil } @@ -558,12 +570,12 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error()) return err } - + jobID := strconv.FormatInt(jobResult.JobID, 10) err = models.CreateCloudbrain(&models.Cloudbrain{ Status: TransTrainJobStatus(jobResult.Status), UserID: ctx.User.ID, RepoID: ctx.Repo.Repository.ID, - JobID: strconv.FormatInt(jobResult.JobID, 10), + JobID: jobID, JobName: req.JobName, JobType: string(models.JobTypeInference), Type: models.TypeCloudBrainTwo, @@ -586,6 +598,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e EngineName: req.EngineName, LabelName: req.LabelName, IsLatestVersion: req.IsLatestVersion, + ComputeResource: models.NPUResource, VersionCount: req.VersionCount, TotalVersionCount: req.TotalVersionCount, ModelName: req.ModelName, @@ -598,6 +611,29 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error()) return err } - + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, req.JobName, models.ActionCreateInferenceTask) return nil } + +func GetNotebookImageName(imageId string) (string, error) { + var validImage = false + var imageName = "" + + if ImageInfos == nil { + json.Unmarshal([]byte(setting.ImageInfos), &ImageInfos) + } + + for _, imageInfo := range ImageInfos.ImageInfo { + if imageInfo.Id == imageId { + validImage = true + imageName = imageInfo.Value + } + } + + if !validImage { + log.Error("the image id(%s) is invalid", imageId) + return imageName, errors.New("the image id is invalid") + } + + return imageName, nil +} diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index 4bc296657..2ac73c2c3 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -330,3 +330,18 @@ func (a *actionNotifier) NotifySyncDeleteRef(doer *models.User, repo *models.Rep log.Error("notifyWatchers: %v", err) } } + +func (a *actionNotifier) NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) { + if err := models.NotifyWatchers(&models.Action{ + ActUserID: doer.ID, + ActUser: doer, + OpType: optype, + RepoID: repo.ID, + Repo: repo, + IsPrivate: repo.IsPrivate, + RefName: name, + Content: id, + }); err != nil { + log.Error("notifyWatchers: %v", err) + } +} diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index 8325f710c..8d6fdeb52 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -54,4 +54,6 @@ type Notifier interface { NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits) NotifySyncCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string) NotifySyncDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) + + NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) } diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index a74c47980..0d3489882 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -154,3 +154,7 @@ func (*NullNotifier) NotifySyncCreateRef(doer *models.User, repo *models.Reposit // NotifySyncDeleteRef places a place holder function func (*NullNotifier) NotifySyncDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) { } + +func (*NullNotifier) NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) { + +} diff --git a/modules/notification/notification.go b/modules/notification/notification.go index d12024663..0fd6fa471 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -37,6 +37,13 @@ func NewContext() { RegisterNotifier(action.NewNotifier()) } +// NotifyUploadAttachment notifies attachment upload message to notifiers +func NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) { + for _, notifier := range notifiers { + notifier.NotifyOtherTask(doer, repo, id, name, optype) + } +} + // NotifyCreateIssueComment notifies issue comment related message to notifiers func NotifyCreateIssueComment(doer *models.User, repo *models.Repository, issue *models.Issue, comment *models.Comment) { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index c6828f9f7..4e063fe05 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -513,6 +513,8 @@ var ( PoolInfos string Flavor string DebugHost string + ImageInfos string + Capacity int //train-job ResourcePools string Engines string @@ -1326,7 +1328,8 @@ func NewContext() { ProfileID = sec.Key("PROFILE_ID").MustString("") PoolInfos = sec.Key("POOL_INFOS").MustString("") Flavor = sec.Key("FLAVOR").MustString("") - DebugHost = sec.Key("DEBUG_SERVER_HOST").MustString("http://192.168.202.73") + ImageInfos = sec.Key("IMAGE_INFOS").MustString("") + Capacity = sec.Key("IMAGE_INFOS").MustInt(100) ResourcePools = sec.Key("Resource_Pools").MustString("") Engines = sec.Key("Engines").MustString("") EngineVersions = sec.Key("Engine_Versions").MustString("") diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index f277ff8fc..5c0c600be 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -864,9 +864,13 @@ confirm_choice = confirm cloudbran1_tips = Only data in zip format can create cloudbrain tasks cloudbrain_creator=Creator cloudbrain_task = Task Name +cloudbrain_task_type = Task Type +cloudbrain_task_name=Cloud Brain Task Name cloudbrain_operate = Operate cloudbrain_status_createtime = Status/Createtime cloudbrain_status_runtime = Running Time +cloudbrain_jobname_err=Name must start with a lowercase letter or number,can include lowercase letter,number,_ and -,can not end with _, and can be up to 36 characters long. +cloudbrain_query_fail=Failed to query cloudbrain information. record_begintime_get_err=Can not get the record begin time. parameter_is_wrong=The input parameter is wrong. @@ -2344,6 +2348,12 @@ datasets.owner=Owner datasets.name=name datasets.private=Private +cloudbrain.all_task_types=All Task Types +cloudbrain.all_computing_resources=All Computing Resources +cloudbrain.all_status=All Status +cloudbrain.download_report=Download Report +cloudbrain.cloudbrain_name=Cloudbrain Name + hooks.desc = Webhooks automatically make HTTP POST requests to a server when certain openi events trigger. Webhooks defined here are defaults and will be copied into all new repositories. Read more in the webhooks guide. hooks.add_webhook = Add Default Webhook hooks.update_webhook = Update Default Webhook @@ -2683,6 +2693,13 @@ mirror_sync_create = synced new reference %[2]s to %[2]s at %[3]s from mirror approve_pull_request = `approved %s#%[2]s` reject_pull_request = `suggested changes for %s#%[2]s` +upload_dataset=`upload dataset %s` +task_gpudebugjob=`created CPU/GPU type debugging task%s` +task_npudebugjob=`created NPU type debugging task %s` +task_trainjob=`created training task%s` +task_inferencejob=`created reasoning task %s` +task_benchmark=`created profiling task %s` +task_createmodel=`created new model %s` [tool] ago = %s ago @@ -2757,6 +2774,7 @@ head.dataset = Datasets foot.council = Council foot.technical_committee = Technical Committee foot.join = Join OpenI +foot.agreement=Use agreement foot.news = News foot.community_news = Community News foot.member_news = Member news diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 197481358..42deebcb7 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -868,10 +868,13 @@ confirm_choice=确定 cloudbran1_tips=只有zip格式的数据集才能发起云脑任务 cloudbrain_creator=创建者 cloudbrain_task=任务名称 +cloudbrain_task_type=任务类型 +cloudbrain_task_name=云脑侧任务名称 cloudbrain_operate=操作 cloudbrain_status_createtime=状态/创建时间 cloudbrain_status_runtime = 运行时长 cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。 +cloudbrain_query_fail=查询云脑任务失败。 record_begintime_get_err=无法获取统计开始时间。 parameter_is_wrong=输入参数错误,请检查输入参数。 @@ -2354,6 +2357,12 @@ datasets.owner=所有者 datasets.name=名称 datasets.private=私有 +cloudbrain.all_task_types=全部任务类型 +cloudbrain.all_computing_resources=全部计算资源 +cloudbrain.all_status=全部状态 +cloudbrain.download_report=下载此报告 +cloudbrain.cloudbrain_name=云脑侧名称 + hooks.desc=当某些 openi 事件触发时, Web 钩子会自动向服务器发出 HTTP POST 请求。此处定义的 Web 钩子是默认值, 将复制到所有新建项目中。参阅 Web钩子指南 获取更多内容。 hooks.add_webhook=新增默认Web钩子 hooks.update_webhook=更新默认Web钩子 @@ -2420,7 +2429,7 @@ auths.sspi_auto_activate_users_helper=允许 SSPI 认证自动激活新用户 auths.sspi_strip_domain_names=从用户名中删除域名部分 auths.sspi_strip_domain_names_helper=如果选中此项,域名将从登录名中删除(例如,"DOMAIN\user"和"user@example.org",两者都将变成只是“用户”)。 auths.sspi_separator_replacement=要使用的分隔符代替\, / 和 @ -auths.sspi_separator_replacement_helper=用于替换下级登录名称分隔符的字符 (例如) "DOMAIN\user") 中的 \ 和用户主名字(如"user@example.org中的 @ )。 +auths.sspi_separator_replacement_helper=用于替换下级登录名称分隔符的字符 (例如) "DOMAIN\user") 中的 \ 和用户主名字(如"user@example.org"中的 @ )。 auths.sspi_default_language=默认语言 auths.sspi_default_language_helper=SSPI 认证方法为用户自动创建的默认语言。如果您想要自动检测到语言,请留空。 auths.tips=帮助提示 @@ -2693,6 +2702,13 @@ mirror_sync_create=从镜像同步了新的引用 %[2]s mirror_sync_delete=从镜像同步并从 %[3]s 删除了引用 %[2]s approve_pull_request=`同意了 %s#%[2]s` reject_pull_request=`建议变更 %s#%[2]s` +upload_dataset=`上传了数据集文件 %s` +task_gpudebugjob=`创建了CPU/GPU类型调试任务 %s` +task_npudebugjob=`创建了NPU类型调试任务 %s` +task_trainjob=`创建了训练任务 %s` +task_inferencejob=`创建了推理任务 %s` +task_benchmark=`创建了评测任务 %s` +task_createmodel=`导入了新模型 %s` [tool] ago=%s前 @@ -2767,6 +2783,7 @@ head.dataset=数据集 foot.council=理事会 foot.technical_committee=技术委员会 foot.join=加入启智 +foot.agreement=使用协议 foot.news=动态 foot.community_news=社区动态 foot.member_news=成员动态 diff --git a/package-lock.json b/package-lock.json index a8e5e3e25..7b706207b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13869,6 +13869,130 @@ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", "dev": true }, + "ts-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.0.0.tgz", + "integrity": "sha512-iissbnuJkqbB3YAmnWyEbmdNcGcoiiXopKHKyqdoCrFQVi9pnplXeveQDXJnQOCYNNcb2pjT2zzSYTX6c9QtAA==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^3.1.4", + "semver": "^5.0.1" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", @@ -13928,6 +14052,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true + }, "ua-parser-js": { "version": "0.7.21", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", diff --git a/package.json b/package.json index ba5459a07..e5f829bf1 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,8 @@ "script-loader": "0.7.2", "stylelint": "13.3.3", "stylelint-config-standard": "20.0.0", + "ts-loader": "4.0.0", + "typescript": "4.5.5", "updates": "10.2.11" }, "browserslist": [ diff --git a/public/home/home.js b/public/home/home.js index 7d5cbe4b1..8f7d6a626 100644 --- a/public/home/home.js +++ b/public/home/home.js @@ -126,11 +126,14 @@ socket.onmessage = function (e) { actionName = actionName.replace("{oldRepoName}",record.Content); html += recordPrefix + actionName; html += " " + getRepotext(record) + "" + } + else if(record.OpType == "24" || record.OpType == "25" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "29" || record.OpType == "30"){ + html += recordPrefix + actionName; + html += " " + record.RefName + "" } else{ continue; } - if(record.Repo != null){ var time = getTime(record.CreatedUnix,currentTime); html += " " + time; @@ -138,13 +141,32 @@ socket.onmessage = function (e) { html += ""; html += ""; } - } output.innerHTML = html; swiperNewMessage.updateSlides(); swiperNewMessage.updateProgress(); }; +function getTaskLink(record){ + var re = getRepoLink(record); + if(record.OpType == 24){ + return re + "/datasets?type=" + record.Content; + }else if(record.OpType == 25){ + return re + "/cloudbrain/" + record.RefName; + }else if(record.OpType == 26){ + return re + "/modelarts/notebook/" + record.Content; + }else if(record.OpType == 27){ + return re + "/modelarts/train-job/" + record.Content; + }else if(record.OpType == 28){ + return re + "/modelarts/inference-job/" + record.Content; + }else if(record.OpType == 29){ + return re + "/cloudbrain/benchmark/" + record.RefName; + }else if(record.OpType == 30){ + return re + "/modelmanage/show_model_info?name=" + record.RefName; + } + return re; +} + function getMsg(record){ var html =""; html += "
"; @@ -276,7 +298,14 @@ var actionNameZH={ "15":"重新开启了合并请求", "17":"从 {repoName} 删除分支 {deleteBranchName}", "22":"建议变更", - "23":"评论了合并请求" + "23":"评论了合并请求", + "24":"上传了数据集文件", + "25":"创建了CPU/GPU类型调试任务", + "26":"创建了NPU类型调试任务", + "27":"创建了训练任务", + "28":"创建了推理任务", + "29":"创建了评测任务", + "30":"导入了新模型" }; var actionNameEN={ @@ -294,7 +323,14 @@ var actionNameEN={ "15":" reopened pull request", "17":" deleted branch {deleteBranchName} from {repoName}", "22":" proposed changes", - "23":" commented on pull request" + "23":" commented on pull request", + "24":" upload dataset ", + "25":" created CPU/GPU type debugging task ", + "26":" created NPU type debugging task ", + "27":" created training task", + "28":" created reasoning task", + "29":" created profiling task", + "30":" created new model" }; var repoAndOrgZH={ diff --git a/routers/admin/cloudbrains.go b/routers/admin/cloudbrains.go new file mode 100644 index 000000000..1cf5ca256 --- /dev/null +++ b/routers/admin/cloudbrains.go @@ -0,0 +1,217 @@ +package admin + +import ( + "net/http" + "net/url" + "strconv" + "strings" + "time" + + "github.com/360EntSecGroup-Skylar/excelize/v2" + + "code.gitea.io/gitea/modules/modelarts" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +const ( + tplCloudBrains base.TplName = "admin/cloudbrain/list" + EXCEL_DATE_FORMAT = "20060102150405" + CREATE_TIME_FORMAT = "2006/01/02 15:04:05.00" +) + +func CloudBrains(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("admin.cloudBrains") + ctx.Data["PageIsAdmin"] = true + ctx.Data["PageIsAdminCloudBrains"] = true + + listType := ctx.Query("listType") + jobType := ctx.Query("jobType") + jobStatus := ctx.Query("jobStatus") + + ctx.Data["ListType"] = listType + ctx.Data["JobType"] = jobType + ctx.Data["JobStatus"] = jobStatus + + page := ctx.QueryInt("page") + if page <= 0 { + page = 1 + } + debugType := modelarts.DebugType + if listType == models.GPUResource { + debugType = models.TypeCloudBrainOne + } else if listType == models.NPUResource { + debugType = models.TypeCloudBrainTwo + } + + var jobTypes []string + jobTypeNot := false + if jobType == string(models.JobTypeDebug) { + jobTypes = append(jobTypes, string(models.JobTypeSnn4imagenet), string(models.JobTypeBrainScore), string(models.JobTypeDebug)) + } else if jobType != "all" && jobType != "" { + jobTypes = append(jobTypes, jobType) + } + + var jobStatuses []string + jobStatusNot := false + if jobStatus == "other" { + jobStatusNot = true + jobStatuses = append(jobStatuses, string(models.ModelArtsTrainJobWaiting), string(models.ModelArtsTrainJobFailed), string(models.ModelArtsRunning), string(models.ModelArtsTrainJobCompleted), + string(models.ModelArtsStarting), string(models.ModelArtsRestarting), string(models.ModelArtsStartFailed), + string(models.ModelArtsStopping), string(models.ModelArtsStopped)) + } else if jobStatus != "all" && jobStatus != "" { + jobStatuses = append(jobStatuses, jobStatus) + } + + keyword := strings.Trim(ctx.Query("q"), " ") + + ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ + ListOptions: models.ListOptions{ + Page: page, + PageSize: setting.UI.IssuePagingNum, + }, + Keyword: keyword, + Type: debugType, + JobTypeNot: jobTypeNot, + JobStatusNot: jobStatusNot, + JobStatus: jobStatuses, + JobTypes: jobTypes, + NeedRepoInfo: true, + IsLatestVersion: modelarts.IsLatestVersion, + }) + if err != nil { + ctx.ServerError("Get job failed:", err) + return + } + + for i, task := range ciTasks { + ciTasks[i].CanDebug = true + ciTasks[i].CanDel = true + ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource + } + + pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, getTotalPage(count, setting.UI.IssuePagingNum)) + pager.SetDefaultParams(ctx) + pager.AddParam(ctx, "listType", "ListType") + ctx.Data["Page"] = pager + ctx.Data["PageIsCloudBrain"] = true + ctx.Data["Tasks"] = ciTasks + ctx.Data["CanCreate"] = true + ctx.Data["Keyword"] = keyword + + ctx.HTML(200, tplCloudBrains) + +} + +func DownloadCloudBrains(ctx *context.Context) { + + page := 1 + + pageSize := 300 + + var cloudBrain = ctx.Tr("repo.cloudbrain") + fileName := getFileName(cloudBrain) + + _, total, err := models.Cloudbrains(&models.CloudbrainsOptions{ + ListOptions: models.ListOptions{ + Page: page, + PageSize: 1, + }, + Type: modelarts.DebugType, + NeedRepoInfo: false, + IsLatestVersion: modelarts.IsLatestVersion, + }) + + if err != nil { + log.Warn("Can not get cloud brain info", err) + ctx.Error(http.StatusBadRequest, ctx.Tr("repo.cloudbrain_query_fail")) + return + } + + totalPage := getTotalPage(total, pageSize) + + f := excelize.NewFile() + + index := f.NewSheet(cloudBrain) + f.DeleteSheet("Sheet1") + + for k, v := range allHeader(ctx) { + f.SetCellValue(cloudBrain, k, v) + } + + var row = 2 + for i := 0; i < totalPage; i++ { + + pageRecords, _, err := models.Cloudbrains(&models.CloudbrainsOptions{ + ListOptions: models.ListOptions{ + Page: page, + PageSize: pageSize, + }, + Type: modelarts.DebugType, + NeedRepoInfo: true, + }) + if err != nil { + log.Warn("Can not get cloud brain info", err) + continue + } + for _, record := range pageRecords { + + for k, v := range allValues(row, record, ctx) { + f.SetCellValue(cloudBrain, k, v) + } + row++ + + } + + page++ + } + f.SetActiveSheet(index) + + ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName)) + ctx.Resp.Header().Set("Content-Type", "application/octet-stream") + + f.WriteTo(ctx.Resp) +} + +func allValues(row int, rs *models.CloudbrainInfo, ctx *context.Context) map[string]string { + return map[string]string{getCellName("A", row): rs.JobName, getCellName("B", row): rs.Status, getCellName("C", row): rs.JobType, getCellName("D", row): time.Unix(int64(rs.Cloudbrain.CreatedUnix), 0).Format(CREATE_TIME_FORMAT), getCellName("E", row): getDurationTime(rs), + getCellName("F", row): rs.ComputeResource, getCellName("G", row): rs.Name, getCellName("H", row): rs.Repo.OwnerName + "/" + rs.Repo.Alias, getCellName("I", row): rs.JobName, + } +} + +func getDurationTime(rs *models.CloudbrainInfo) string { + if rs.JobType == "TRAIN" || rs.JobType == "INFERENCE" { + return rs.TrainJobDuration + } else { + return "-" + } +} + +func getFileName(baseName string) string { + return baseName + "_" + time.Now().Format(EXCEL_DATE_FORMAT) + ".xlsx" + +} + +func getTotalPage(total int64, pageSize int) int { + + another := 0 + if int(total)%pageSize != 0 { + another = 1 + } + return int(total)/pageSize + another + +} + +func allHeader(ctx *context.Context) map[string]string { + + return map[string]string{"A1": ctx.Tr("repo.cloudbrain_task"), "B1": ctx.Tr("repo.modelarts.status"), "C1": ctx.Tr("repo.cloudbrain_task_type"), "D1": ctx.Tr("repo.modelarts.createtime"), "E1": ctx.Tr("repo.modelarts.train_job.dura_time"), "F1": ctx.Tr("repo.modelarts.computing_resources"), "G1": ctx.Tr("repo.cloudbrain_creator"), "H1": ctx.Tr("repo.repo_name"), "I1": ctx.Tr("repo.cloudbrain_task_name")} + +} + +func getCellName(col string, row int) string { + return col + strconv.Itoa(row) +} diff --git a/routers/home.go b/routers/home.go index 397e1990d..2db8d2112 100755 --- a/routers/home.go +++ b/routers/home.go @@ -38,6 +38,7 @@ const ( tplExploreCode base.TplName = "explore/code" tplExploreImages base.TplName = "explore/images" tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis" + tplHomeTerm base.TplName = "terms" ) // Home render home page @@ -596,3 +597,7 @@ func RecommendRepoFromPromote(ctx *context.Context) { ctx.JSON(200, result) } } + +func HomeTerm(ctx *context.Context) { + ctx.HTML(200, tplHomeTerm) +} diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index fe4d9794c..e2040e0d2 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" uuid "github.com/satori/go.uuid" @@ -113,7 +114,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes) log.Info("save model end.") - + notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask) return nil } diff --git a/routers/repo/attachment.go b/routers/repo/attachment.go index c2d096416..bc843c555 100755 --- a/routers/repo/attachment.go +++ b/routers/repo/attachment.go @@ -20,11 +20,11 @@ import ( "code.gitea.io/gitea/modules/labelmsg" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/minio_ext" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/worker" - gouuid "github.com/satori/go.uuid" ) @@ -845,6 +845,9 @@ func CompleteMultipart(ctx *context.Context) { ctx.Error(500, fmt.Sprintf("InsertAttachment: %v", err)) return } + dataset, _ := models.GetDatasetByID(attachment.DatasetID) + repository, _ := models.GetRepositoryByID(dataset.RepoID) + notification.NotifyOtherTask(ctx.User, repository, fmt.Sprint(attachment.Type), attachment.Name, models.ActionUploadAttachment) if attachment.DatasetID != 0 { if isCanDecompress(attachment.Name) { @@ -865,7 +868,6 @@ func CompleteMultipart(ctx *context.Context) { labelmsg.SendDecompressAttachToLabelOBS(string(attachjson)) } } else { - dataset, _ := models.GetDatasetByID(attachment.DatasetID) var labelMap map[string]string labelMap = make(map[string]string) labelMap["UUID"] = uuid diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go index d26b8f08c..880d28dcf 100755 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -350,18 +350,15 @@ func CloudBrainShow(ctx *context.Context) { func cloudBrainShow(ctx *context.Context, tpName base.TplName) { ctx.Data["PageIsCloudBrain"] = true - var jobName = ctx.Params(":jobname") task, err := models.GetCloudbrainByName(jobName) if err != nil { ctx.Data["error"] = err.Error() } - result, err := cloudbrain.GetJob(task.JobID) if err != nil { ctx.Data["error"] = err.Error() } - if result != nil { jobRes, _ := models.ConvertToJobResultPayload(result.Payload) jobRes.Resource.Memory = strings.ReplaceAll(jobRes.Resource.Memory, "Mi", "MB") @@ -369,6 +366,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { ctx.Data["resource_spec"] = spec taskRoles := jobRes.TaskRoles if jobRes.JobStatus.State != string(models.JobFailed) { + taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) ctx.Data["taskRes"] = taskRes task.Status = taskRes.TaskStatuses[0].State @@ -588,7 +586,13 @@ func CloudBrainDel(ctx *context.Context) { ctx.ServerError(err.Error(), err) return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=" + listType) + + var isAdminPage = ctx.Query("isadminpage") + if ctx.IsUserSiteAdmin() && isAdminPage == "true" { + ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") + } else { + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=" + listType) + } } func deleteCloudbrainJob(ctx *context.Context) error { @@ -1099,6 +1103,9 @@ func GetChildTypes(ctx *context.Context) { } func CloudBrainBenchmarkNew(ctx *context.Context) { + ctx.Data["description"] = "" + ctx.Data["benchmarkTypeID"] = -1 + ctx.Data["benchmark_child_types_id_hidden"] = -1 err := cloudBrainNewDataPrepare(ctx) if err != nil { ctx.ServerError("get new cloudbrain info failed", err) @@ -1201,6 +1208,9 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF benchmarkTypeID := form.BenchmarkTypeID benchmarkChildTypeID := form.BenchmarkChildTypeID + ctx.Data["description"] = form.Description + ctx.Data["benchmarkTypeID"] = benchmarkTypeID + ctx.Data["benchmark_child_types_id_hidden"] = benchmarkChildTypeID if !jobNamePattern.MatchString(jobName) { cloudBrainNewDataPrepare(ctx) ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainBenchmarkNew, &form) @@ -1344,5 +1354,11 @@ func BenchmarkDel(ctx *context.Context) { ctx.ServerError(err.Error(), err) return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark") + + var isAdminPage = ctx.Query("isadminpage") + if ctx.IsUserSiteAdmin() && isAdminPage == "true" { + ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") + } else { + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark") + } } diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index b983a4e17..64c8fab46 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -120,8 +120,13 @@ func MustEnableModelArts(ctx *context.Context) { } func NotebookNew(ctx *context.Context) { - ctx.Data["PageIsCloudBrain"] = true + notebookNewDataPrepare(ctx) + + ctx.HTML(200, tplModelArtsNotebookNew) +} +func notebookNewDataPrepare(ctx *context.Context) error { + ctx.Data["PageIsCloudBrain"] = true t := time.Now() var jobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] ctx.Data["job_name"] = jobName @@ -129,26 +134,14 @@ func NotebookNew(ctx *context.Context) { attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) if err != nil { ctx.ServerError("GetAllUserAttachments failed:", err) - return + return err } - ctx.Data["attachments"] = attachs - ctx.Data["dataset_path"] = modelarts.DataSetMountPath - ctx.Data["env"] = modelarts.NotebookEnv - ctx.Data["notebook_type"] = modelarts.NotebookType - if modelarts.FlavorInfos == nil { - json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) - } - ctx.Data["flavors"] = modelarts.FlavorInfos.FlavorInfo - - ctx.HTML(200, tplModelArtsNotebookNew) -} -func notebookNewDataPrepare(ctx *context.Context) error { - ctx.Data["PageIsCloudBrain"] = true - t := time.Now() - var jobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] - ctx.Data["job_name"] = jobName + if modelarts.ImageInfos == nil { + json.Unmarshal([]byte(setting.ImageInfos), &modelarts.ImageInfos) + } + ctx.Data["images"] = modelarts.ImageInfos.ImageInfo if modelarts.FlavorInfos == nil { json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) @@ -208,8 +201,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm uuid := form.Attachment description := form.Description flavor := form.Flavor - - flavor = "modelarts.bm.910.arm.public.1" + imageId := form.ImageId count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) if err != nil { @@ -240,7 +232,7 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm } } - err = modelarts.GenerateNotebook2(ctx, jobName, uuid, description, flavor) + err = modelarts.GenerateNotebook2(ctx, jobName, uuid, description, flavor, imageId) if err != nil { log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) notebookNewDataPrepare(ctx) @@ -279,10 +271,19 @@ func NotebookShow(ctx *context.Context) { result.CreateTime = time.Unix(int64(result.CreateAt/1000), 0).Format("2006-01-02 15:04:05") result.LatestUpdateTime = time.Unix(int64(result.UpdateAt/1000), 0).Format("2006-01-02 15:04:05") - //result.QueuingInfo.BeginTime = time.Unix(int64(result.QueuingInfo.BeginTimestamp/1000), 0).Format("2006-01-02 15:04:05") - //result.QueuingInfo.EndTime = time.Unix(int64(result.QueuingInfo.EndTimestamp/1000), 0).Format("2006-01-02 15:04:05") } + datasetDownloadLink := "-" + if ctx.IsSigned { + if task.Uuid != "" && task.UserID == ctx.User.ID { + attachment, err := models.GetAttachmentByUUID(task.Uuid) + if err == nil { + datasetDownloadLink = attachment.S3DownloadURL() + } + } + } + + ctx.Data["datasetDownloadLink"] = datasetDownloadLink ctx.Data["task"] = task ctx.Data["jobID"] = jobID ctx.Data["jobName"] = task.JobName @@ -461,7 +462,12 @@ func NotebookDel(ctx *context.Context) { return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=" + listType) + var isAdminPage = ctx.Query("isadminpage") + if ctx.IsUserSiteAdmin() && isAdminPage == "true" { + ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") + } else { + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=" + listType) + } } func TrainJobIndex(ctx *context.Context) { @@ -1473,6 +1479,7 @@ func TrainJobShow(ctx *context.Context) { ctx.Data["displayJobName"] = VersionListTasks[0].DisplayJobName ctx.Data["version_list_task"] = VersionListTasks ctx.Data["version_list_count"] = VersionListCount + ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, &VersionListTasks[0].Cloudbrain) ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow) } @@ -1569,7 +1576,12 @@ func TrainJobDel(ctx *context.Context) { DeleteJobStorage(VersionListTasks[0].JobName) } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") + var isAdminPage = ctx.Query("isadminpage") + if ctx.IsUserSiteAdmin() && isAdminPage == "true" { + ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") + } else { + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") + } } func TrainJobStop(ctx *context.Context) { @@ -2072,6 +2084,7 @@ func InferenceJobShow(ctx *context.Context) { ctx.Data["jobID"] = jobID ctx.Data["jobName"] = task.JobName ctx.Data["task"] = task + ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, task) tempUids := []int64{} tempUids = append(tempUids, task.UserID) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 55b24e97a..e9c7d3fd1 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -319,6 +319,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/action/notification", routers.ActionNotification) m.Get("/recommend/org", routers.RecommendOrgFromPromote) m.Get("/recommend/repo", routers.RecommendRepoFromPromote) + m.Get("/home/term", routers.HomeTerm) m.Group("/explore", func() { m.Get("", func(ctx *context.Context) { ctx.Redirect(setting.AppSubURL + "/explore/repos") @@ -507,6 +508,10 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", admin.Datasets) // m.Post("/delete", admin.DeleteDataset) }) + m.Group("/cloudbrains", func() { + m.Get("", admin.CloudBrains) + m.Get("/download", admin.DownloadCloudBrains) + }) m.Group("/^:configType(hooks|system-hooks)$", func() { m.Get("", admin.DefaultOrSystemWebhooks) @@ -996,7 +1001,6 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", reqRepoCloudBrainReader, repo.CloudBrainBenchMarkShow) }) m.Group("/:jobid", func() { - // m.Get("", reqRepoCloudBrainReader, repo.CloudBrainBenchMarkShow) m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.BenchmarkDel) m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) diff --git a/services/socketwrap/clientManager.go b/services/socketwrap/clientManager.go index 53de73673..3ba35f8ff 100644 --- a/services/socketwrap/clientManager.go +++ b/services/socketwrap/clientManager.go @@ -10,7 +10,7 @@ import ( "github.com/elliotchance/orderedmap" ) -var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23} +var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30} type ClientsManager struct { Clients *orderedmap.OrderedMap diff --git a/templates/admin/cloudbrain/list.tmpl b/templates/admin/cloudbrain/list.tmpl new file mode 100644 index 000000000..0a09230eb --- /dev/null +++ b/templates/admin/cloudbrain/list.tmpl @@ -0,0 +1,219 @@ +{{template "base/head" .}} + +
+
+
+
+
+
+
+
+
+ +
+
+ {{template "admin/navbar" .}} +
+ {{template "base/alert" .}} +
+
+ {{template "admin/cloudbrain/search" .}} + +
+ +
+ +
+
+
+ {{$.i18n.Tr "repo.cloudbrain_task"}} +
+
+ {{$.i18n.Tr "repo.cloudbrain_task_type"}} +
+
+ {{$.i18n.Tr "repo.modelarts.status"}} +
+
+ {{$.i18n.Tr "repo.modelarts.createtime"}} +
+
+ {{$.i18n.Tr "repo.cloudbrain_status_runtime"}} +
+
+ {{$.i18n.Tr "repo.modelarts.computing_resources"}} +
+
+ {{$.i18n.Tr "repo.cloudbrain_creator"}} +
+
+ {{$.i18n.Tr "repository"}} +
+
+ {{.i18n.Tr "admin.cloudbrain.cloudbrain_name"}} +
+
+ {{$.i18n.Tr "repo.cloudbrain_operate"}} +
+
+
+ {{range .Tasks}} +
+
+ +
+ {{if eq .JobType "DEBUG"}} + + {{.JobName}} + + {{else if eq .JobType "INFERENCE"}} + + {{.JobName}} + + {{else if eq .JobType "TRAIN"}} + + {{.JobName}} + + {{else if eq .JobType "BENCHMARK"}} + + {{.JobName}} + + {{end}} +
+ +
+ {{.JobType}} +
+ +
+ + {{.Status}} + +
+ +
+ {{TimeSinceUnix1 .Cloudbrain.CreatedUnix}} +
+ +
+ {{if .TrainJobDuration}}{{.TrainJobDuration}}{{else}}--{{end}} +
+ +
+ {{if .ComputeResource}}{{.ComputeResource}}{{else}}--{{end}} +
+ +
+ {{if .User.Name}} + + {{else}} + + {{end}} +
+ + + +
+ {{.JobName}} +
+
+ {{if eq .JobType "DEBUG"}} +
+
+ {{$.CsrfTokenHtml}} + {{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} + + {{$.i18n.Tr "repo.debug"}} + + {{else}} + + {{$.i18n.Tr "repo.debug_again"}} + + {{end}} +
+
+ {{end}} + +
+ {{if eq .JobType "DEBUG" "BENCHMARK"}} +
+ {{$.CsrfTokenHtml}} + + {{$.i18n.Tr "repo.stop"}} + +
+ {{else}} + + {{$.i18n.Tr "repo.stop"}} + + {{end}} +
+ +
+ {{$.CsrfTokenHtml}} + + {{$.i18n.Tr "repo.delete"}} + +
+
+
+
+ {{end}} +
+
+ + +
+
+
+ +
+
+
+
+ +
+ +
+
+{{template "base/footer" .}} + diff --git a/templates/admin/cloudbrain/search.tmpl b/templates/admin/cloudbrain/search.tmpl new file mode 100644 index 000000000..bbd45e550 --- /dev/null +++ b/templates/admin/cloudbrain/search.tmpl @@ -0,0 +1,46 @@ +
+
+
+ + +
+
+
+
+ + + +
\ No newline at end of file diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index 2b9f8b7c4..47a9ee811 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -14,6 +14,9 @@ {{.i18n.Tr "admin.datasets"}} + + 云脑任务 + {{.i18n.Tr "admin.hooks"}} diff --git a/templates/base/footer_content.tmpl b/templates/base/footer_content.tmpl index 42084b871..bcf46f9f0 100755 --- a/templates/base/footer_content.tmpl +++ b/templates/base/footer_content.tmpl @@ -8,6 +8,8 @@ {{.i18n.Tr "custom.foot.council"}} {{.i18n.Tr "custom.foot.technical_committee"}} {{.i18n.Tr "custom.foot.join"}} + {{.i18n.Tr "custom.foot.agreement"}} +
- +
@@ -102,11 +102,16 @@  
+ @@ -182,12 +187,16 @@ function setChildType(){ let type_id = $('#benchmark_types_id').val(); + let child_selected_id = $('#benchmark_child_types_id_hidden').val(); $.get(`${repolink}/cloudbrain/benchmark/get_child_types?benchmark_type_id=${type_id}`, (data) => { - console.log(JSON.stringify(data)) const n_length = data['child_types'].length let html='' for (let i=0;i${data['child_types'][i].value}`; + if(child_selected_id == data['child_types'][i].id){ + html += ``; + }else{ + html += ``; + } } document.getElementById("benchmark_child_types_id").innerHTML=html; }) diff --git a/templates/repo/cloudbrain/benchmark/show.tmpl b/templates/repo/cloudbrain/benchmark/show.tmpl index 10453b446..cf18c4b8c 100755 --- a/templates/repo/cloudbrain/benchmark/show.tmpl +++ b/templates/repo/cloudbrain/benchmark/show.tmpl @@ -188,6 +188,7 @@ td, th { {{range $k ,$v := .version_list_task}}
+
@@ -441,7 +442,6 @@ td, th { jobName = urlArr.slice(-1)[0] }) - function loadLog(version_name){ document.getElementById("mask").style.display = "block" $.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${jobName}/log?version_name=${version_name}&lines=50&order=asc`, (data) => { diff --git a/templates/repo/createCourse.tmpl b/templates/repo/createCourse.tmpl index f606d3aa1..a354dade2 100644 --- a/templates/repo/createCourse.tmpl +++ b/templates/repo/createCourse.tmpl @@ -94,7 +94,6 @@ $(document).ready(function(){ $('#course_label_item').empty() }else{ $.get(`/api/v1/topics/search?q=${query}`,(data)=>{ - console.log(data) if(data.topics.length!==0){ let html='' $('#course_label_item').empty() @@ -107,5 +106,4 @@ $(document).ready(function(){ } }); }) -console.log() \ No newline at end of file diff --git a/templates/repo/datasets/index.tmpl b/templates/repo/datasets/index.tmpl index 167b1ef44..65ba2bb6e 100755 --- a/templates/repo/datasets/index.tmpl +++ b/templates/repo/datasets/index.tmpl @@ -11,9 +11,8 @@ {{template "repo/header" .}} diff --git a/templates/repo/modelarts/inferencejob/show.tmpl b/templates/repo/modelarts/inferencejob/show.tmpl index 691087f66..30f7d7a88 100644 --- a/templates/repo/modelarts/inferencejob/show.tmpl +++ b/templates/repo/modelarts/inferencejob/show.tmpl @@ -469,13 +469,13 @@ td, th {
{{template "base/footer" .}} \ No newline at end of file +{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/repo/modelarts/trainjob/show.tmpl b/templates/repo/modelarts/trainjob/show.tmpl index ba07266c1..6401f4dcd 100755 --- a/templates/repo/modelarts/trainjob/show.tmpl +++ b/templates/repo/modelarts/trainjob/show.tmpl @@ -518,6 +518,7 @@ td, th {
+
{{template "base/footer" .}} \ No newline at end of file + \ No newline at end of file diff --git a/templates/terms.tmpl b/templates/terms.tmpl new file mode 100644 index 000000000..3c02a119c --- /dev/null +++ b/templates/terms.tmpl @@ -0,0 +1,70 @@ +{{template "base/head_home" .}} +
+

OpenI启智社区AI协作平台使用协议

+
+

+ OpenI启智社区AI协作平台作为新一代人工智能领域开源开放开发协作平台,不仅为用户提供代码托管与数据集管理等服务,同时提供开发者所需的计算算力资源,一个良好的开发环境对用户、组织和项目都尤为重要。 +

+

+ 为了保障用户权益,维护平台正常秩序,实现平台规范化运营,给开发者提供一个良好的开发环境,您不得在本平台进行恶意攻击、挖矿等任何违法或扰乱平台秩序的行为。一经发现,平台有权变更、暂停或终止您对平台服务的使用而无须事先声明,包括但不限于限制您使用平台服务的次数与资源、账号永久封闭等。 +

+

+ AI协作平台使用协议及违规处罚 +

+

+ 1. 您需保证对平台服务的使用不违反国家各项法律法规的规定,且不侵害任何第三方权益,如因此造成任何后果及损失,由您自行承担全部责任。 +

+

+ 2. 禁止行为 +

+

+ 您充分理解并同意,您在使用平台服务时,应当遵守所有中华人民共和国的法律、法规、规章制度、规范、政策、行政命令、强制标准及行业标准等(统称为“法律法规”)。除非法律法规允许且启智社区事先书面许可,您不得从事以下活动,也不得同意、授权或指示任何第三人从事包括但不限于以下内容的活动: +
+ (1) 对平台服务进行挖矿、逆向工程、反编辑等恶意行为损坏平台服务相关内容与数据,或不正当手段获取原始数据和其他数据等;
+ (2) 对平台服务或者平台服务运行过程中释放出的任何数据或其他数据及平台服务运行过程中的交互数据进行复制、更改、修改等操作,包括但不限于使用插件、外挂或非经授权的第三方工具或服务接入平台服务和相关系统; +
+ (3) 宣扬或提供关于非法行为的说明信息、宣扬针对任何团体或个人的人身伤害或传播任何病毒、蠕虫、缺陷、特洛伊木马或其他具有破坏性的内容等;
+ (4) 删除本平台服务中包含的任何版权声明、商标声明或其他所有权声明;包括但不限于任何有损本平台一切相关知识产权的行为;
+ (5) 创造任何网站或应用程序以重现或复制平台服务或本平台。 +

+

+ 3. 遵守法律规范 +

+

+ 您不得利用平台服务上传、上载、发布、发表、传播任何违法内容,包括但不限于您制作、复制、发布、传播下列信息: +

+

+ (1)煽动抗拒、破坏宪法和法律、行政法规实施
+ (2)煽动颠覆国家政权,推翻社会主义制度
+ (3)煽动分裂国家、破坏国家统一
+ (4)煽动民族仇恨、民族歧视、破坏民族团结
+ (5)捏造或者歪曲事实、散布谣言,扰乱社会秩序
+ (6)宣扬封建迷信、淫秽、色情、赌博、暴力、教唆犯罪
+ (7)公然侮辱他人或者捏造事实诽谤他人
+ (8)损害国家机关信誉或有损国家领导人荣誉
+ (9)其他违反宪法和法律、行政法规
+ (10)含有虚假、有害、胁迫、侵害他人隐私、骚扰、侵害、中伤、粗俗、猥亵或其他道德上令人反感的内容
+ (11)含有中国法律、法规、规章、条例以及任何具有法律效力之规范所限制或禁止的其他内容 +

+

+ 一经发现,平台将按照国家有关规定,及时删除网站中含有上述内容的地址、目录,并保留原始记录,在二十四小时之内向公安机关报告。 +

+

+ 4. 保障网络信息安全 +

+

+ 您不得利用平台服务从事以下危害计算机网络信息安全的活动:
+ (1) 未经允许,进入计算机信息网络或者使用计算机信息网络资源的;
+ (2) 未经允许,对计算机信息网络功能进行删除、修改或者增加的;
+ (3) 未经允许,对进入计算机信息网络中存储、处理或者传输的数据和应用程序进行删除、修改或者增加的;
+ (4) 故意制作、传播计算机病毒等破坏性程序的;
+ (5) 其他危害计算机信息网络安全的行为。 +

+

+ 5. 您充分理解并同意,您对自己使用平台服务的一切行为及由此产生的一切结果负责,包括但不限于您所发表的任何内容、提供的任何服务以及由此产生的任何后果。您应对平台服务的内容应自行判断并决定是否使用,并承担因使用平台服务及其相关内容而引起的所有风险,包括因对平台服务及其内容的真实性、完整性、准确性、及时性及实用性的依赖而产生的风险。平台不对此提供任何担保和保证,不对因前述风险而导致的任何后果或损失对您承担责任。 +

+

+ 如果您违反了法律法规或本协议,OpenI启智社区有权依据合理判断对违反法律法规或本协议的行为作出处理,并保留对该违反行为采取法律所能提供的所有补救手段的权利。OpenI启智社区有权对违反法律法规及本协议的任何用户调查并采取适当的法律行动,包括但不限于民事诉讼等。OpenI启智社区有权根据违法违规行为的严重程度,将上述违法违规行为的线索和您的个人信息报告司法机关或其他执法机关,并配合司法机关或其他执法机关进行的调查、听证、起诉等。您应当自行承担由此产生的任何法律责任。 +

+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl index f3794989c..519dcda8f 100644 --- a/templates/user/dashboard/feeds.tmpl +++ b/templates/user/dashboard/feeds.tmpl @@ -69,7 +69,21 @@ {{$.i18n.Tr "action.reject_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} {{else if eq .GetOpType 23}} {{ $index := index .GetIssueInfos 0}} - {{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} + {{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoPath | Str2html}} + {{else if eq .GetOpType 24}} + {{$.i18n.Tr "action.upload_dataset" .GetRepoLink .Content .RefName | Str2html}} + {{else if eq .GetOpType 25}} + {{$.i18n.Tr "action.task_gpudebugjob" .GetRepoLink .RefName .RefName | Str2html}} + {{else if eq .GetOpType 26}} + {{$.i18n.Tr "action.task_npudebugjob" .GetRepoLink .Content .RefName | Str2html}} + {{else if eq .GetOpType 27}} + {{$.i18n.Tr "action.task_trainjob" .GetRepoLink .Content .RefName | Str2html}} + {{else if eq .GetOpType 28}} + {{$.i18n.Tr "action.task_inferencejob" .GetRepoLink .Content .RefName | Str2html}} + {{else if eq .GetOpType 29}} + {{$.i18n.Tr "action.task_benchmark" .GetRepoLink .RefName .RefName | Str2html}} + {{else if eq .GetOpType 30}} + {{$.i18n.Tr "action.task_createmodel" .GetRepoLink .RefName .RefName | Str2html}} {{end}}

{{if or (eq .GetOpType 5) (eq .GetOpType 18)}} @@ -101,7 +115,23 @@
- {{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32}} + {{if eq .GetOpType 24}} + + {{else if eq .GetOpType 25}} + + {{else if eq .GetOpType 26}} + + {{else if eq .GetOpType 27}} + + {{else if eq .GetOpType 28}} + + {{else if eq .GetOpType 29}} + + {{else if eq .GetOpType 30}} + + {{else}} + {{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32}} + {{end}}
diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl index 85d1fb65c..eb0d76e5b 100644 --- a/templates/user/dashboard/issues.tmpl +++ b/templates/user/dashboard/issues.tmpl @@ -208,6 +208,3 @@ {{template "base/footer" .}} - \ No newline at end of file diff --git a/templates/user/dashboard/milestones.tmpl b/templates/user/dashboard/milestones.tmpl index 1c0ee84fc..4038ce5b0 100644 --- a/templates/user/dashboard/milestones.tmpl +++ b/templates/user/dashboard/milestones.tmpl @@ -117,6 +117,3 @@ {{template "base/footer" .}} - \ No newline at end of file diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index d42ed4058..fa5e0c9b7 100755 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -141,6 +141,7 @@ {{if eq .TabName "activity"}} {{if .EnableHeatmap}} +
diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..e69de29bb diff --git a/web_src/js/components/Images.vue b/web_src/js/components/Images.vue index 6fe26d532..a56d81e4c 100644 --- a/web_src/js/components/Images.vue +++ b/web_src/js/components/Images.vue @@ -310,7 +310,6 @@ export default { }, handleCurrentChange(val){ - console.log(val) this.params.page = val this.getImageList() @@ -350,7 +349,6 @@ export default { }) }, copyUrl(url){ - console.log(url) const cInput = document.createElement('input') cInput.value = url document.body.appendChild(cInput) @@ -380,16 +378,13 @@ export default { clearP(value){ - console.log("sorce value",value) if(!value) return '' const reg = /\<\/?p\>/g; value = value.replace(reg,'') - console.log("repalace:",value) return value }, transformTimestamp(timestamp){ - console.log("timestamp",timestamp) let a = new Date(timestamp).getTime(); const date = new Date(a); const Y = date.getFullYear() + '-'; diff --git a/web_src/js/components/UserAnalysis.vue b/web_src/js/components/UserAnalysis.vue index 5650e164f..682dbc78c 100755 --- a/web_src/js/components/UserAnalysis.vue +++ b/web_src/js/components/UserAnalysis.vue @@ -200,7 +200,6 @@ var saveFileName='' var Date=(this.params.startDate).split('-') var startDate=Date[0]+''+Date[1]+''+Date[2] - console.log(startDate) Date=(this.params.endDate).split('-') var endDate=Date[0]+Date[1]+Date[2] saveFileName = '用户分析_'+this.search+''+startDate+'_'+endDate @@ -258,7 +257,6 @@ getUserList(type_val,index){ this.type_val = type_val this.dynamic = index; - console.log("dj:"+type_val) var now = new Date(); // 当前日期 var nowDayOfWeek = now.getDay(); // 今天本周的第几天 var nowDay = now.getDate(); // 当前日 @@ -324,7 +322,6 @@ // console.log("res.data:"+res.data.data) this.totalNum = res.data.count - console.log("res.count:"+res.data.count) }) @@ -354,9 +351,7 @@ }, filters:{ - transformTimestamp(timestamp){ - console.log("timestamp",timestamp) let a = new Date(timestamp*1000); const date = new Date(a); const Y = date.getFullYear() + '/'; @@ -366,7 +361,6 @@ const m = (date.getMinutes() <10 ? '0'+date.getMinutes() : date.getMinutes());// + ':' ; // const s = (date.getSeconds() <10 ? '0'+date.getSeconds() : date.getSeconds()) ; // 秒 const dateString = Y + M + D + h + m ;//+ s; - console.log('dateString', dateString); // > dateString 2021-07-06 14:23 return dateString; }, }, diff --git a/web_src/js/excel/Export2Excel.js b/web_src/js/excel/Export2Excel.js index 3c6d022af..85921f7ad 100755 --- a/web_src/js/excel/Export2Excel.js +++ b/web_src/js/excel/Export2Excel.js @@ -100,7 +100,6 @@ export function export_table_to_excel(id) { /* original data */ var data = oo[0]; var ws_name = "SheetJS"; - console.log(data); var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); @@ -118,7 +117,7 @@ export function export_table_to_excel(id) { } function formatJson(jsonData) { - console.log(jsonData) + } export function export_json_to_excel(th, jsonData, defaultTitle) { diff --git a/web_src/js/excel/util.js b/web_src/js/excel/util.js index b600e5e37..809b5b51b 100755 --- a/web_src/js/excel/util.js +++ b/web_src/js/excel/util.js @@ -3,7 +3,6 @@ export function export2Excel(columns,list,filename){ const { export_json_to_excel } = require('./Export2Excel'); let tHeader = [] let filterVal = [] - console.log(columns) if(!columns){ return; } diff --git a/web_src/js/features/cloudrbanin.js b/web_src/js/features/cloudrbanin.js new file mode 100644 index 000000000..5fcaf56c8 --- /dev/null +++ b/web_src/js/features/cloudrbanin.js @@ -0,0 +1,236 @@ +export default async function initCloudrain() { + let timeid = window.setInterval(loadJobStatus, 15000); + $(document).ready(loadJobStatus); + function loadJobStatus() { + $(".job-status").each((index, job) => { + const jobID = job.dataset.jobid; + const repoPath = job.dataset.repopath; + // const computeResource = job.dataset.resource + const versionname = job.dataset.version + const status_text = $(`#${jobID}-text`).text() + console.log(versionname) + const finalState = ['STOPPED','CREATE_FAILED','UNAVAILABLE','DELETED','RESIZE_FAILED','SUCCEEDED','IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED','SUBMIT_MODEL_FAILED','DEPLOY_SERVICE_FAILED','CHECK_FAILED'] + if (finalState.includes(status_text)) { + return + } + // const diffResource = computeResource == "NPU" ? 'modelarts/notebook' : 'cloudbrain' + $.get(`/api/v1/repos/${repoPath}/${jobID}?version_name=${versionname}`, (data) => { + const jobID = data.JobID + const status = data.JobStatus + const duration = data.JobDuration + $('#duration-'+jobID).text(duration) + if (status != status_text) { + $('#' + jobID+'-icon').removeClass().addClass(status) + $('#' + jobID+ '-text').text(status) + finalState.includes(status) && $('#' + jobID + '-stop').removeClass('blue').addClass('disabled') + } + if(status==="RUNNING"){ + $('#ai-debug-'+jobID).removeClass('disabled').addClass('blue').text('调试').css("margin","0 1rem") + $('#model-image-'+jobID).removeClass('disabled').addClass('blue') + } + if(status!=="RUNNING"){ + // $('#model-debug-'+jobID).removeClass('blue') + // $('#model-debug-'+jobID).addClass('disabled') + $('#model-image-'+jobID).removeClass('blue').addClass('disabled') + } + if(["CREATING","STOPPING","WAITING","STARTING"].includes(status)){ + $('#ai-debug-'+jobID).removeClass('blue').addClass('disabled') + } + if(['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'].includes(status)){ + $('#ai-debug-'+jobID).removeClass('disabled').addClass('blue').text('再次调试').css("margin","0") + } + if(["RUNNING","WAITING"].includes(status)){ + $('#ai-stop-'+jobID).removeClass('disabled').addClass('blue') + } + if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED","SUCCEEDED"].includes(status)){ + $('#ai-stop-'+jobID).removeClass('blue').addClass('disabled') + } + + if(["STOPPED","FAILED","START_FAILED","KILLED","COMPLETED","SUCCEEDED"].includes(status)){ + $('#ai-delete-'+jobID).removeClass('disabled').addClass('blue') + }else{ + $('#ai-delete-'+jobID).removeClass('blue').addClass('disabled') + } + }).fail(function(err) { + console.log(err); + }); + }); + }; + function assertDelete(obj,versionName,repoPath) { + if (obj.style.color == "rgb(204, 204, 204)") { + return + } else { + const delId = obj.parentNode.id + let flag = 1; + $('.ui.basic.modal') + .modal({ + onDeny: function() { + flag = false + }, + onApprove: function() { + if(!versionName){ + document.getElementById(delId).submit() + } + else{ + deleteVersion(versionName,repoPath) + } + flag = true + }, + onHidden: function() { + if (flag == false) { + $('.alert').html('您已取消操作').removeClass('alert-success').addClass('alert-danger').show().delay(1500).fadeOut(); + } + } + }) + .modal('show') + } + } + function deleteVersion(versionName,repoPath){ + const url = `/api/v1/repos/${repoPath}` + $.post(url,{version_name:versionName},(data)=>{ + if(data.StatusOK===0){ + location.reload() + } + }).fail(function(err) { + console.log(err); + }); + } + $('.ui.basic.ai_delete').click(function() { + const repoPath = this.dataset.repopath + const versionName = this.dataset.version + if(repoPath && versionName){ + assertDelete(this,versionName,repoPath) + } + else{ + assertDelete(this) + } + }) + function stopDebug(JobID,stopUrl){ + $.ajax({ + type:"POST", + url:stopUrl, + data:$('#stopForm-'+JobID).serialize(), + success:function(res){ + if(res.result_code==="0"){ + $('#' + JobID+'-icon').removeClass().addClass(res.status) + $('#' + JobID+ '-text').text(res.status) + if(res.status==="STOPPED"){ + $('#ai-debug-'+JobID).removeClass('disabled').addClass('blue').text("再次调试").css("margin","0") + $('#ai-image-'+JobID).removeClass('blue').addClass('disabled') + $('#ai-model-debug-'+JobID).removeClass('blue').addClass('disabled') + $('#ai-delete-'+JobID).removeClass('disabled').addClass('blue') + $('#ai-stop-'+JobID).removeClass('blue').addClass('disabled') + } + else{ + $('#ai-debug-'+JobID).removeClass('blue').addClass('disabled') + $('#ai-stop-'+JobID).removeClass('blue').addClass('disabled') + } + + }else{ + $('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut(); + } + }, + error :function(res){ + console.log(res) + + } + }) + } + $('.ui.basic.ai_stop').click(function() { + const jobID = this.dataset.jobid + const repoPath = this.dataset.repopath + stopDebug(jobID,repoPath) + }) + + function stopVersion(version_name,jobID,repoPath){ + const url = `/api/v1/repos/${repoPath}/${jobID}/stop_version` + $.post(url,{version_name:version_name},(data)=>{ + if(data.StatusOK===0){ + $('#ai-stop-'+jobID).removeClass('blue') + $('#ai-stop-'+jobID).addClass('disabled') + refreshStatus(version_name,jobID,repoPath) + } + }).fail(function(err) { + console.log(err); + }); + } + function refreshStatus(version_name,jobID,repoPath){ + + const url = `/api/v1/repos/${repoPath}/${jobID}/?version_name${version_name}` + $.get(url,(data)=>{ + $(`#${jobID}-icon`).attr("class",data.JobStatus) + // detail status and duration + $(`#${jobID}-text`).text(data.JobStatus) + }).fail(function(err) { + console.log(err); + }); + } + $('.ui.basic.ai_stop_version').click(function() { + const jobID = this.dataset.jobid + const repoPath = this.dataset.repopath + const versionName = this.dataset.version + stopVersion(versionName,jobID,repoPath) + }) + function getModelInfo(repoPath,modelName,versionName,jobName){ + console.log("getModelInfo") + $.get(`${repoPath}/modelmanage/show_model_info_api?name=${modelName}`,(data)=>{ + if(data.length===0){ + $(`#${jobName}`).popup('toggle') + }else{ + let versionData = data.filter((item)=>{ + return item.Version === versionName + }) + if(versionData.length==0){ + $(`#${jobName}`).popup('toggle') + } + else{ + location.href = `${repoPath}/modelmanage/show_model_info?name=${modelName}` + } + } + }) + } + $('.goto_modelmanage').click(function() { + const repoPath = this.dataset.repopath + const modelName = this.dataset.modelname + const versionName = this.dataset.version + const jobName = this.dataset.jobname + getModelInfo(repoPath,modelName,versionName,jobName) + }) + function debugAgain(JobID,debugUrl){ + if($('#' + JobID+ '-text').text()==="RUNNING"){ + window.open(debugUrl+'debug') + }else{ + $.ajax({ + type:"POST", + url:debugUrl+'restart', + data:$('#debugAgainForm-'+JobID).serialize(), + success:function(res){ + if(res.result_code==="0"){ + if(res.job_id!==JobID){ + location.reload() + }else{ + $('#' + JobID+'-icon').removeClass().addClass(res.status) + $('#' + JobID+ '-text').text(res.status) + $('#ai-debug-'+JobID).removeClass('blue').addClass('disabled') + $('#ai-delete-'+JobID).removeClass('blue').addClass('disabled') + $('#ai-debug-'+JobID).text("调试").css("margin","0 1rem") + } + }else{ + $('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut(); + } + }, + error :function(res){ + console.log(res) + + } + }) + } + } + $('.ui.basic.ai_debug').click(function() { + const jobID = this.dataset.jobid + const repoPath = this.dataset.repopath + debugAgain(jobID,repoPath) + }) +} + + \ No newline at end of file diff --git a/web_src/js/index.js b/web_src/js/index.js index 6bc0d2b88..cec6823a6 100755 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -40,6 +40,8 @@ import EditTopics from './components/EditTopics.vue'; import DataAnalysis from './components/DataAnalysis.vue' import Contributors from './components/Contributors.vue' import Model from './components/Model.vue'; +import initCloudrain from './features/cloudrbanin.js' + Vue.use(ElementUI); Vue.prototype.$axios = axios; @@ -2936,6 +2938,7 @@ $(document).ready(async () => { initNotificationCount(); initTribute(); initDropDown(); + initCloudrain(); // Repo clone url. if ($('#repo-clone-url').length > 0) { @@ -3584,14 +3587,16 @@ function initVueApp() { } initVueComponents(); - + new Vue({ delimiters: ['${', '}'], el, data: { + page:parseInt(new URLSearchParams(window.location.search).get('page')), searchLimit: Number( (document.querySelector('meta[name=_search_limit]') || {}).content ), + page:1, suburl: AppSubUrl, uid: Number( (document.querySelector('meta[name=_context_uid]') || {}).content @@ -3600,6 +3605,15 @@ function initVueApp() { }, components: { ActivityTopAuthors + }, + mounted(){ + this.page = parseInt(new URLSearchParams(window.location.search).get('page')) + }, + methods:{ + handleCurrentChange:function (val) { + window.location.href='/admin/cloudbrains?page='+val + this.page = val + } } }); } @@ -3688,8 +3702,6 @@ function initVueModel() { } function initVueDataAnalysis() { const el = document.getElementById('data_analysis'); - console.log("el",el) - if (!el) { return; } @@ -3756,7 +3768,6 @@ function initFilterBranchTagDropdown(selector) { }); }); $data.remove(); - console.log("-this",this) new Vue({ delimiters: ['${', '}'], el: this, diff --git a/web_src/less/openi.less b/web_src/less/openi.less index 1d165dda8..c9e6a546f 100644 --- a/web_src/less/openi.less +++ b/web_src/less/openi.less @@ -720,4 +720,13 @@ display: block; .markdown:not(code).file-view{ padding: 2em 0!important; } -} \ No newline at end of file +} +//elemet-ui + +.el-pagination.is-background .el-pager li:not(.disabled).active { + background-color: #5bb973 !important; + color: #FFF !important; + } + .el-pagination.is-background .el-pager li:hover { + color: #5bb973 !important; + } \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index a08810ebc..cd3635427 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -115,6 +115,15 @@ module.exports = { }, ], }, + { + test: /\.ts$/, + use: [ + { + loader: "ts-loader", + } + ], + exclude: /node_modules/ + }, { test: /\.js$/, exclude: /node_modules/, @@ -252,6 +261,7 @@ module.exports = { alias: { vue$: 'vue/dist/vue.esm.js', // needed because vue's default export is the runtime only }, + extensions: ['.tsx', '.ts', '.js'] }, watchOptions: { ignored: [