Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/950 Reviewed-by: lewis <747342561@qq.com>pull/961/head
@@ -176,10 +176,10 @@ func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) { | |||
} | |||
} | |||
func GetObsListObject(jobName, parentDir string, versionOutputPath string) ([]FileInfo, error) { | |||
func GetObsListObject(jobName, parentDir, versionName string) ([]FileInfo, error) { | |||
input := &obs.ListObjectsInput{} | |||
input.Bucket = setting.Bucket | |||
input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, versionOutputPath, parentDir), "/") | |||
input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, versionName, parentDir), "/") | |||
strPrefix := strings.Split(input.Prefix, "/") | |||
output, err := ObsCli.ListObjects(input) | |||
fileInfos := make([]FileInfo, 0) | |||
@@ -275,8 +275,34 @@ func GetObsCreateSignedUrl(jobName, parentDir, fileName string) (string, error) | |||
log.Error("CreateSignedUrl failed:", err.Error()) | |||
return "", err | |||
} | |||
log.Info("SignedUrl:%s", output.SignedUrl) | |||
return output.SignedUrl, nil | |||
} | |||
func GetObsCreateSignedUrlByBucketAndKey(bucket, key string) (string, error) { | |||
input := &obs.CreateSignedUrlInput{} | |||
input.Bucket = bucket | |||
input.Key = key | |||
input.Expires = 60 * 60 | |||
input.Method = obs.HttpMethodGet | |||
comma := strings.LastIndex(key, "/") | |||
filename := key | |||
if comma != -1 { | |||
filename = key[comma+1:] | |||
} | |||
reqParams := make(map[string]string) | |||
filename = url.QueryEscape(filename) | |||
reqParams["response-content-disposition"] = "attachment; filename=\"" + filename + "\"" | |||
input.QueryParams = reqParams | |||
output, err := ObsCli.CreateSignedUrl(input) | |||
if err != nil { | |||
log.Error("CreateSignedUrl failed:", err.Error()) | |||
return "", err | |||
} | |||
return output.SignedUrl, nil | |||
} | |||
func ObsGetPreSignedUrl(uuid, fileName string) (string, error) { | |||
@@ -311,3 +337,20 @@ func ObsCreateObject(path string) error { | |||
return nil | |||
} | |||
func ObsDownloadAFile(bucket string, key string) (io.ReadCloser, error) { | |||
input := &obs.GetObjectInput{} | |||
input.Bucket = bucket | |||
input.Key = key | |||
output, err := ObsCli.GetObject(input) | |||
if err == nil { | |||
log.Info("StorageClass:%s, ETag:%s, ContentType:%s, ContentLength:%d, LastModified:%s\n", | |||
output.StorageClass, output.ETag, output.ContentType, output.ContentLength, output.LastModified) | |||
return output.Body, nil | |||
} else if obsError, ok := err.(obs.ObsError); ok { | |||
log.Error("Code:%s, Message:%s", obsError.Code, obsError.Message) | |||
return nil, obsError | |||
} else { | |||
return nil, err | |||
} | |||
} |
@@ -7,6 +7,7 @@ package repo | |||
import ( | |||
"net/http" | |||
"path" | |||
"strconv" | |||
"strings" | |||
@@ -14,6 +15,7 @@ import ( | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/modelarts" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/storage" | |||
) | |||
@@ -302,8 +304,7 @@ func ModelList(ctx *context.APIContext) { | |||
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | |||
return | |||
} | |||
VersionOutputPath := modelarts.GetVersionOutputPathByTotalVersionCount(task.TotalVersionCount) | |||
models, err := storage.GetObsListObject(task.JobName, parentDir, VersionOutputPath) | |||
models, err := storage.GetObsListObject(task.JobName, parentDir, versionName) | |||
if err != nil { | |||
log.Info("get TrainJobListModel failed:", err) | |||
ctx.ServerError("GetObsListObject:", err) | |||
@@ -321,27 +322,61 @@ func ModelList(ctx *context.APIContext) { | |||
}) | |||
} | |||
func ModelDownload(ctx *context.APIContext) { | |||
func ModelDownload(ctx *context.Context) { | |||
var ( | |||
err error | |||
) | |||
var jobID = ctx.Params(":jobid") | |||
versionName := ctx.Query("version_name") | |||
// versionName := "V0001" | |||
parentDir := ctx.Query("parent_dir") | |||
fileName := ctx.Query("file_name") | |||
log.Info("DownloadSingleModelFile start.") | |||
// id := ctx.Params(":ID") | |||
// path := Model_prefix + models.AttachmentRelativePath(id) + "/" + parentDir + fileName | |||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
if err != nil { | |||
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | |||
return | |||
} | |||
VersionOutputPath := modelarts.GetVersionOutputPathByTotalVersionCount(task.TotalVersionCount) | |||
parentDir = VersionOutputPath + "/" + parentDir | |||
url, err := storage.GetObsCreateSignedUrl(task.JobName, parentDir, fileName) | |||
if err != nil { | |||
log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("GetObsCreateSignedUrl", err) | |||
return | |||
path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, setting.OutPutPath, versionName, parentDir, fileName), "/") | |||
log.Info("Download path is:%s", path) | |||
if setting.PROXYURL != "" { | |||
body, err := storage.ObsDownloadAFile(setting.Bucket, path) | |||
if err != nil { | |||
log.Info("download error.") | |||
} else { | |||
//count++ | |||
// models.ModifyModelDownloadCount(id) | |||
defer body.Close() | |||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName) | |||
ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||
p := make([]byte, 1024) | |||
var readErr error | |||
var readCount int | |||
// 读取对象内容 | |||
for { | |||
readCount, readErr = body.Read(p) | |||
if readCount > 0 { | |||
ctx.Resp.Write(p[:readCount]) | |||
//fmt.Printf("%s", p[:readCount]) | |||
} | |||
if readErr != nil { | |||
break | |||
} | |||
} | |||
} | |||
} else { | |||
url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) | |||
if err != nil { | |||
log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("GetObsCreateSignedUrl", err) | |||
return | |||
} | |||
//count++ | |||
// models.ModifyModelDownloadCount(id) | |||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||
} | |||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||
} |
@@ -369,6 +369,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
} | |||
ctx.Data["Branches"] = Branches | |||
ctx.Data["BranchesCount"] = len(Branches) | |||
ctx.Data["params"] = "" | |||
configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
if err != nil { | |||
@@ -380,7 +381,92 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
return nil | |||
} | |||
func ErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
//can, err := canUserCreateTrainJob(ctx.User.ID) | |||
//if err != nil { | |||
// ctx.ServerError("canUserCreateTrainJob", err) | |||
// return | |||
//} | |||
// | |||
//if !can { | |||
// log.Error("the user can not create train-job") | |||
// ctx.ServerError("the user can not create train-job", fmt.Errorf("the user can not create train-job")) | |||
// return | |||
//} | |||
t := time.Now() | |||
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
ctx.Data["job_name"] = jobName | |||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
if err != nil { | |||
ctx.ServerError("GetAllUserAttachments failed:", err) | |||
return err | |||
} | |||
ctx.Data["attachments"] = attachs | |||
var resourcePools modelarts.ResourcePool | |||
if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return err | |||
} | |||
ctx.Data["resource_pools"] = resourcePools.Info | |||
var engines modelarts.Engine | |||
if err = json.Unmarshal([]byte(setting.Engines), &engines); err != nil { | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return err | |||
} | |||
ctx.Data["engines"] = engines.Info | |||
var versionInfos modelarts.VersionInfo | |||
if err = json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return err | |||
} | |||
ctx.Data["engine_versions"] = versionInfos.Version | |||
var flavorInfos modelarts.Flavor | |||
if err = json.Unmarshal([]byte(setting.TrainJobFLAVORINFOS), &flavorInfos); err != nil { | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return err | |||
} | |||
ctx.Data["flavor_infos"] = flavorInfos.Info | |||
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||
ctx.Data["train_url"] = outputObsPath | |||
Branches, err := ctx.Repo.GitRepo.GetBranches() | |||
if err != nil { | |||
ctx.ServerError("GetBranches error:", err) | |||
return err | |||
} | |||
ctx.Data["Branches"] = Branches | |||
ctx.Data["BranchesCount"] = len(Branches) | |||
configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
if err != nil { | |||
ctx.ServerError("getConfigList failed:", err) | |||
return err | |||
} | |||
var Parameters modelarts.Parameters | |||
if err = json.Unmarshal([]byte(form.Params), &Parameters); err != nil { | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return err | |||
} | |||
ctx.Data["params"] = Parameters.Parameter | |||
ctx.Data["config_list"] = configList.ParaConfigs | |||
ctx.Data["bootFile"] = form.BootFile | |||
ctx.Data["uuid"] = form.Attachment | |||
ctx.Data["branch_name"] = form.BranchName | |||
return nil | |||
} | |||
func TrainJobNewVersion(ctx *context.Context) { | |||
err := trainJobNewVersionDataPrepare(ctx) | |||
if err != nil { | |||
ctx.ServerError("get new train-job info failed", err) | |||
@@ -394,6 +480,12 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
var jobID = ctx.Params(":jobid") | |||
// var versionName = ctx.Params(":version-name") | |||
var versionName = ctx.Query("version_name") | |||
// canNewJob, err := canUserCreateTrainJobVersion(ctx, jobID) | |||
// if err != nil { | |||
// ctx.ServerError("get can info failed", err) | |||
// return err | |||
// } | |||
// ctx.Data["canNewJob"] = canNewJob | |||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
if err != nil { | |||
@@ -455,7 +547,8 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
ctx.ServerError("GetBranches error:", err) | |||
return err | |||
} | |||
ctx.Data["branches"] = Branches | |||
ctx.Data["branch"] = Branches | |||
ctx.Data["branch_name"] = task.BranchName | |||
ctx.Data["description"] = task.Description | |||
ctx.Data["boot_file"] = task.BootFile | |||
@@ -477,7 +570,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
return nil | |||
} | |||
func ErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||
func VersionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
var jobID = ctx.Params(":jobid") | |||
// var versionName = ctx.Params(":version-name") | |||
@@ -580,7 +673,6 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
isSaveParam := form.IsSaveParam | |||
repo := ctx.Repo.Repository | |||
codeLocalPath := setting.JobPath + jobName + modelarts.CodePath | |||
// codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/" | |||
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | |||
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/" | |||
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | |||
@@ -593,7 +685,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
if err := paramCheckCreateTrainJob(form); err != nil { | |||
log.Error("paramCheckCreateTrainJob failed:(%v)", err) | |||
trainJobNewDataPrepare(ctx) | |||
ErrorNewDataPrepare(ctx, form) | |||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | |||
return | |||
} | |||
@@ -792,7 +884,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
if err := paramCheckCreateTrainJob(form); err != nil { | |||
log.Error("paramCheckCreateTrainJob failed:(%v)", err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -815,7 +907,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
Branch: branch_name, | |||
}); err != nil { | |||
log.Error("创建任务失败,任务名称已存在!: %s (%v)", repo.FullName(), err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("创建任务失败,任务名称已存在!", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -823,14 +915,14 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
//todo: upload code (send to file_server todo this work?) | |||
if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { | |||
log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil { | |||
log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -839,7 +931,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
// if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | |||
log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("Failed to uploadCodeToObs", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -859,7 +951,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
err := json.Unmarshal([]byte(params), ¶meters) | |||
if err != nil { | |||
log.Error("Failed to Unmarshal params: %s (%v)", params, err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -878,7 +970,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
if isSaveParam == "on" { | |||
if form.ParameterTemplateName == "" { | |||
log.Error("ParameterTemplateName is empty") | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -902,7 +994,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
if err != nil { | |||
log.Error("Failed to CreateTrainJobConfig: %v", err) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -949,7 +1041,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
err = modelarts.GenerateTrainJobVersion(ctx, req, jobID) | |||
if err != nil { | |||
log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
ErrorDataPrepare(ctx, form) | |||
VersionErrorDataPrepare(ctx, form) | |||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
@@ -1220,6 +1312,18 @@ func canUserCreateTrainJob(uid int64) (bool, error) { | |||
return org.IsOrgMember(uid) | |||
} | |||
func canUserCreateTrainJobVersion(ctx *context.Context, jobID string) (bool, error) { | |||
var versionName = "V0001" | |||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
if err != nil { | |||
return false, err | |||
} | |||
if ctx.User.ID == task.User.ID { | |||
return true, nil | |||
} | |||
return false, err | |||
} | |||
func TrainJobGetConfigList(ctx *context.Context) { | |||
ctx.Data["PageIsTrainJob"] = true | |||
@@ -307,9 +307,9 @@ | |||
<!-- 任务名 --> | |||
<div class="five wide column"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 15px;"> | |||
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span> | |||
<span class="fitted text_over" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
<span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
</a> | |||
</div> | |||
@@ -380,7 +380,7 @@ | |||
{{end}} | |||
</form> | |||
</div> | |||
<div class="ui compact buttons" style="margin-right:10px;"> | |||
<div class="ui compact buttons"> | |||
<!-- 模型下载 --> | |||
<a class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank"> | |||
{{$.i18n.Tr "repo.download"}} | |||
@@ -399,11 +399,11 @@ | |||
<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 not .CanDel}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
<a id="model-delete-{{.JobID}}" class="ui basic blue button {{if not .CanDel}}disabled {{end}}" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
{{else}} | |||
<a class="ui compact disabled button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
<a class="ui basic blue button disabled" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
{{end}} | |||
@@ -93,7 +93,7 @@ | |||
<div class="ui tabular stackable menu navbar"> | |||
{{if .Permission.CanRead $.UnitTypeCode}} | |||
<div class="dropdown-menu"> | |||
<a class="{{if or .PageIsViewCode .PageIsReleaseList .PageIsWiki .PageIsActivity .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}"> | |||
<a class="{{if or .PageIsViewCode .PageIsReleaseList .PageIsWiki .PageIsActivity .PageIsViewCode}}active{{end}} item hover_active" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}"> | |||
<span>{{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}} <i class="dropdown icon"></i></span> | |||
</a> | |||
<div class="dropdown-content"> | |||
@@ -243,7 +243,7 @@ | |||
}) | |||
$('.question.circle.icon').hover(function(){ | |||
$(this).popup('show') | |||
$('.ui.popup.mini.top.center').css({"border-color":'rgba(50, 145, 248, 100)',"color":"rgba(3, 102, 214, 100)","border-radius":"5px"}) | |||
$('.ui.popup.mini.top.center').css({"border-color":'rgba(50, 145, 248, 100)',"color":"rgba(3, 102, 214, 100)","border-radius":"5px","border-shadow":"none"}) | |||
}); | |||
</script> |
@@ -280,9 +280,9 @@ | |||
<!-- 任务名 --> | |||
<div class="six wide column"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 15px;"> | |||
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span> | |||
<span class="fitted" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
</a> | |||
</div> | |||
@@ -352,11 +352,11 @@ | |||
<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" "CREATING" "WAITING" "STARTING" "STOPPING" }}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
<a id="model-delete-{{.JobID}}" class="ui basic blue button {{if eq .Status "RUNNING" "CREATING" "WAITING" "STARTING" "STOPPING" }}disabled {{end}}" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
{{else}} | |||
<a class="ui compact disabled button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
<a class="ui basic blue button disabled" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
{{end}} | |||
@@ -321,9 +321,9 @@ | |||
<!-- 任务名 --> | |||
<div class="three wide column padding0"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 12px;"> | |||
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span> | |||
<span class="fitted" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||
</a> | |||
</div> | |||
<!-- 版本数量 --> | |||
@@ -366,8 +366,9 @@ | |||
</div> | |||
<div class="three wide column text center padding0"> | |||
<div class="ui compact buttons"> | |||
<form id="stopForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/stop" method="post"> | |||
<!-- <div class="ui compact buttons"> | |||
<form id="stopForm-{{.JobID}}" action="/api/v1/repos{{$.Link}}/{{.JobID}}/stop_version" method="post"> | |||
<input type="hidden" name="version_name" value="{{.VersionName}}"> | |||
{{$.CsrfTokenHtml}} | |||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | |||
<a style="padding: 0.5rem 1rem;" 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();"> | |||
@@ -379,7 +380,7 @@ | |||
</a> | |||
{{end}} | |||
</form> | |||
</div> | |||
</div> --> | |||
<!-- 模型下载 --> | |||
<!-- <div class="ui compact buttons"> | |||
<a style="padding: 0.5rem;" class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank"> | |||
@@ -387,14 +388,27 @@ | |||
</a> | |||
</div> --> | |||
<!-- 删除任务 --> | |||
<div class="ui compact buttons"> | |||
{{$.CsrfTokenHtml}} | |||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | |||
<a style="padding: 0.5rem 1rem;" id="{{.VersionName}}-stop" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}} blue {{end}}button" onclick="stopVersion({{.VersionName}},{{.JobID}})"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
{{else}} | |||
<a style="padding: 0.5rem 1rem;" id="{{.VersionName}}-stop" class="ui basic disabled button"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
{{end}} | |||
</div> | |||
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | |||
{{$.CsrfTokenHtml}} | |||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" 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;"> | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="model-delete-{{.JobID}}" class="ui basic blue button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
{{else}} | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" class="ui compact disabled button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" class="ui basic button disabled" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||
{{$.i18n.Tr "repo.delete"}} | |||
</a> | |||
{{end}} | |||
@@ -527,33 +541,7 @@ | |||
$('#' + jobID+ '-text').text(status) | |||
} | |||
if(status==="RUNNING"){ | |||
$('#model-debug-'+jobID).removeClass('disabled') | |||
$('#model-debug-'+jobID).addClass('blue') | |||
// $('#duration-'+jobID).text(duration) | |||
} | |||
if(status!=="RUNNING"){ | |||
$('#model-debug-'+jobID).removeClass('blue') | |||
$('#model-debug-'+jobID).addClass('disabled') | |||
} | |||
if(status!=="KILLED" || status!=="FAILED"){ | |||
$('#stop-model-debug-'+jobID).removeClass('disabled') | |||
$('#stop-model-debug-'+jobID).addClass('blue') | |||
$('#model-delete-'+jobID).removeClass('red') | |||
$('#model-delete-'+jobID).addClass('disabled') | |||
} | |||
if(status=="KILLED" || status=="FAILED" || status=="KILLING" || status=="COMPLETED"){ | |||
$('#stop-model-debug-'+jobID).removeClass('blue') | |||
$('#stop-model-debug-'+jobID).addClass('disabled') | |||
$('#model-delete-'+jobID).removeClass('disabled') | |||
$('#model-delete-'+jobID).addClass('red') | |||
} | |||
if(status=="START_FAILED"){ | |||
$('#stop-model-debug-'+jobID).removeClass('blue') | |||
$('#stop-model-debug-'+jobID).addClass('disabled') | |||
} | |||
}).fail(function(err) { | |||
console.log(err); | |||
}); | |||
@@ -589,7 +577,36 @@ | |||
modal.style.display = "none"; | |||
} | |||
} | |||
function stopVersion(version_name,jobID){ | |||
const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'/stop_version' | |||
$.post(url,{version_name:version_name},(data)=>{ | |||
if(data.StatusOK===0){ | |||
$('#'+version_name+'-stop').removeClass('blue') | |||
$('#'+version_name+'-stop').addClass('disabled') | |||
refreshStatus(version_name,jobID) | |||
} | |||
}).fail(function(err) { | |||
console.log(err); | |||
}); | |||
} | |||
function refreshStatus(version_name,jobID){ | |||
const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+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); | |||
}); | |||
} | |||
// 显示弹窗,弹出相应的信息 | |||
function showmask() { | |||
$('#imageModal').css('display', 'none') | |||
@@ -159,12 +159,12 @@ | |||
<input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
<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> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
<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="unite min_title inline field"> | |||
<label for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
<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> | |||
<div class="ui divider"></div> | |||
@@ -173,8 +173,11 @@ | |||
<div class="required unite min_title inline field"> | |||
<label>{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||
<select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | |||
{{if .branch_name}} | |||
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | |||
{{end}} | |||
{{range $k, $v :=.Branches}} | |||
<option name="branch_name" value="{{$v}}">{{$v}}</option> | |||
{{end}} | |||
@@ -184,7 +187,7 @@ | |||
<div class="required unite min_title inline fields" style="width: 90%;"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||
<div class="field" style="flex: 1.5;"> | |||
<select class="ui dropdown width" id="trainjob_engines" > | |||
{{range .engines}} | |||
@@ -205,7 +208,7 @@ | |||
</div> | |||
<div class="inline unite min_title field required"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
{{if .bootFile}} | |||
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
{{else}} | |||
@@ -216,7 +219,7 @@ | |||
</span> | |||
</div> | |||
<div class="required unite min_title inline field"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||
<select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集"> | |||
{{if $.uuid}} | |||
<option name="attachment" value="{{$.uuid}}">{{$.datasetName}}</option> | |||
@@ -229,15 +232,32 @@ | |||
</div> | |||
<div class="inline unite min_title field"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
<input id="store_run_para" type="hidden" name="run_para_list"> | |||
<div class="dynamic field" style="margin-top: 1rem;"></div> | |||
<div class="dynamic field" style="margin-top: 1rem;"> | |||
{{if ne 0 (len .params)}} | |||
{{range $k ,$v := .params}} | |||
<div class="two fields width85" id="para{{$k}}"> | |||
<div class="field"> | |||
<input type="text" name="shipping_first-name" value={{$v.Label}} required> | |||
</div> | |||
<div class="field"> | |||
<input type="text" name="shipping_last-name" value={{$v.Value}} required> | |||
</div> | |||
<span> | |||
<i class="trash icon"></i> | |||
</span> | |||
</div> | |||
{{end}} | |||
{{end}} | |||
</div> | |||
</div> | |||
<div class="required field " style="display: none;"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | |||
{{range .resource_pools}} | |||
<option value="{{.ID}}">{{.Value}}</option> | |||
@@ -246,7 +266,7 @@ | |||
</div> | |||
<div class="required grouped fields" style="display: none;"> | |||
<label for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||
<label style="font-weight: normal;" for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||
<div class="field"> | |||
<div class="ui grid"> | |||
<div class="column"> | |||
@@ -262,7 +282,7 @@ | |||
</div> | |||
<div class="required unite min_title inline field" id="flaver_name"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
<select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | |||
{{range .flavor_infos}} | |||
<option name="flavor" value="{{.Code}}">{{.Value}}</option> | |||
@@ -270,7 +290,7 @@ | |||
</select> | |||
</div> | |||
<div class="inline required unite min_title field"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||
<div class="ui labeled input" style="width: 5%;"> | |||
@@ -38,7 +38,7 @@ | |||
<!-- 任务名 --> | |||
<div class="five wide column"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}"> | |||
<span class="fitted">{{svg "octicon-tasklist" 16}}</span> | |||
<span class="fitted">{{.JobName}}</span> | |||
</a> | |||
</div> | |||
@@ -226,9 +226,9 @@ td, th { | |||
</div> | |||
</div> | |||
</div> | |||
<div class="{{if eq $k 0}}active{{end}} content accordion-border"> | |||
<div class="{{if eq $k 0}}active{{end}} content"> | |||
<div class="content-pad"> | |||
<div class="ui pointing secondary menu"> | |||
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||
<a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||
<a class="item" data-tab="second{{$k}}" onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||
@@ -414,17 +414,14 @@ td, th { | |||
<div class="ui message message{{.VersionName}}" style="display: none;"> | |||
<div id="header"></div> | |||
</div> | |||
<div class="ui top attached segment" style="background: #f0f0f0;"> | |||
<!-- <div class="ui top attached segment" style="background: #f0f0f0;"> | |||
<div class="center aligned"> | |||
<label>{{$.i18n.Tr "repo.modelarts.log"}}:</label> | |||
<!-- <span class="fitted file_name">{{.}}</span> --> | |||
<!-- <input type="hidden" name="file_name" value> | |||
<input type="hidden" name="start_line" value> | |||
<input type="hidden" name="end_line" value> --> | |||
</div> | |||
</div> | |||
<div class="ui attached segment log" onscroll="logScroll({{.VersionName}})" id="log{{.VersionName}}" style="height: 300px !important; overflow: auto;"> | |||
</div> --> | |||
<div class="ui attached log" onscroll="logScroll({{.VersionName}})" id="log{{.VersionName}}" style="height: 300px !important; overflow: auto;"> | |||
<!-- <input type="hidden" class="version_name" name="version_name" value={{.VersionName}}> --> | |||
<input type="hidden" name="end_line" value> | |||
<input type="hidden" name="start_line" value> | |||
@@ -660,6 +657,12 @@ td, th { | |||
} | |||
} | |||
function downloadModelFile(version_name,parentDir,filename){ | |||
$.get(`/api/v1/repos/${userName}/${repoPath}/modelarts/train-job/${jobID}/model_download?version_name=${version_name}&file_name=${filename}`, (data) => { | |||
console.log(data) | |||
}) | |||
} | |||
function renderDir(data,version_name){ | |||
let html="" | |||
html += "<div class='ui grid' style='margin:0;'>" | |||
@@ -677,10 +680,10 @@ td, th { | |||
html += "<span class='octicon octicon-file-directory'>" | |||
html += "</span>" | |||
if(data.Dirs[i].IsDir){ | |||
html += `<a onclick="loadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].FileName}','folder')">` | |||
html += `<a onclick="loadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].ParenDir}','folder')">` | |||
html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | |||
}else{ | |||
html += `<a href='${location.href}/download_model?parentDir=&fileName=${data.Dirs[i].FileName}&jobName=${data.task.JobName}'>` | |||
html += `<a onclick="downloadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].ParenDir}')">` | |||
html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | |||
} | |||
html += '</a>' | |||
@@ -161,18 +161,18 @@ | |||
<input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
<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> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
<input type="hidden" style="width: 60%;" name="job_name" id="trainjob_job_name" value="{{.job_name}}"> | |||
<input style="width: 60%;" value="{{.job_name}}" tabindex="3" disabled > | |||
</div> | |||
<div class="required unite min_title inline field"> | |||
<label>{{.i18n.Tr "repo.modelarts.parents_version"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.parents_version"}}</label> | |||
<input id="parents_version" style="width: 60%;" value="" tabindex="3" disabled > | |||
</div> | |||
<div class="unite min_title inline field"> | |||
<label for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
<textarea style="width: 80%;" id="description" value="{{.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)">{{.description}}</textarea> | |||
</div> | |||
<div class="ui divider"></div> | |||
@@ -181,7 +181,7 @@ | |||
<div class="required unite min_title inline field"> | |||
<label>{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||
<select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | |||
{{if .branch_name}} | |||
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | |||
@@ -198,7 +198,7 @@ | |||
<div class="required unite min_title inline fields" style="width: 90%;"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||
<div class="field" style="flex: 1.5;"> | |||
<select class="ui dropdown width" id="trainjob_engines" > | |||
{{range .engines}} | |||
@@ -224,7 +224,7 @@ | |||
</div> | |||
<div class="inline unite min_title field required"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
{{if .boot_file}} | |||
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.boot_file}}" tabindex="3" autofocus required maxlength="255" > | |||
{{else}} | |||
@@ -235,7 +235,7 @@ | |||
</span> | |||
</div> | |||
<div class="required unite min_title inline field"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||
<select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集"> | |||
{{if .dataset_name}} | |||
<option name="attachment" value="{{.uuid}}">{{.dataset_name}}</option> | |||
@@ -250,7 +250,7 @@ | |||
</div> | |||
<div class="inline unite min_title field"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
<input id="store_run_para" type="hidden" name="run_para_list"> | |||
<div class="dynamic field" style="margin-top: 1rem;"> | |||
@@ -275,7 +275,7 @@ | |||
<div class="required field " style="display: none;"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | |||
{{range .resource_pools}} | |||
<option value="{{.ID}}">{{.Value}}</option> | |||
@@ -284,7 +284,7 @@ | |||
</div> | |||
<div class="required grouped fields" style="display: none;"> | |||
<label for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||
<label style="font-weight: normal;" for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||
<div class="field"> | |||
<div class="ui grid"> | |||
<div class="column"> | |||
@@ -300,7 +300,7 @@ | |||
</div> | |||
<div class="required unite min_title inline field" id="flaver_name"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||
<select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | |||
{{if .flavor_name}} | |||
<option name="flavor" value="{{.flavor_code}}">{{.flavor_name}}</option> | |||
@@ -313,7 +313,7 @@ | |||
</select> | |||
</div> | |||
<div class="inline required unite min_title field"> | |||
<label>{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||
<div class="ui labeled input" style="width: 5%;"> | |||
@@ -291,9 +291,28 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;} | |||
display: inline-block; | |||
margin-top: 4px; | |||
} | |||
.hover_active{ | |||
} | |||
.dropdown-menu:hover .dropdown-content { | |||
display: block; | |||
} | |||
.dropdown-menu:hover .hover_active { | |||
background: #fff !important; | |||
border-color: #d4d4d5 !important; | |||
font-weight: 700 !important; | |||
// margin-bottom: -1px; | |||
-webkit-box-shadow: none !important; | |||
box-shadow: none !important; | |||
border-radius: .28571429rem .28571429rem 0 0!important; | |||
color: rgba(0,0,0,.95); | |||
border-top-width: 1px; | |||
} | |||
.dropdown-menu:hover .dropdown-content { | |||
display: block; | |||
} | |||
.dropdown-content{ | |||
display: none; | |||
position: absolute; | |||