@@ -46,6 +46,7 @@ type Attachment struct { | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | CreatedUnix timeutil.TimeStamp `xorm:"created"` | ||||
FileChunk *FileChunk `xorm:"-"` | FileChunk *FileChunk `xorm:"-"` | ||||
CanDel bool `xorm:"-"` | |||||
} | } | ||||
type AttachmentUsername struct { | type AttachmentUsername struct { | ||||
@@ -378,7 +379,7 @@ func GetUnDecompressAttachments() ([]*Attachment, error) { | |||||
func getUnDecompressAttachments(e Engine) ([]*Attachment, error) { | func getUnDecompressAttachments(e Engine) ([]*Attachment, error) { | ||||
attachments := make([]*Attachment, 0, 10) | attachments := make([]*Attachment, 0, 10) | ||||
return attachments, e.Where("decompress_state = ? and dataset_id != 0 and attachment.type = ? and name like '%.zip'", DecompressStateInit, TypeCloudBrainOne).Find(&attachments) | |||||
return attachments, e.Where("decompress_state = ? and dataset_id != 0 and attachment.type = ? and (name like '%.zip' or name like '%.tar.gz' or name like '%.tgz')", DecompressStateInit, TypeCloudBrainOne).Find(&attachments) | |||||
} | } | ||||
func GetAllPublicAttachments() ([]*AttachmentUsername, error) { | func GetAllPublicAttachments() ([]*AttachmentUsername, error) { | ||||
@@ -437,3 +438,29 @@ func getModelArtsUserAttachments(e Engine, userID int64) ([]*AttachmentUsername, | |||||
func GetModelArtsUserAttachments(userID int64) ([]*AttachmentUsername, error) { | func GetModelArtsUserAttachments(userID int64) ([]*AttachmentUsername, error) { | ||||
return getModelArtsUserAttachments(x, userID) | return getModelArtsUserAttachments(x, userID) | ||||
} | } | ||||
func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { | |||||
if !isSigned { | |||||
return false | |||||
} | |||||
dataset, err := GetDatasetByID(attach.DatasetID) | |||||
if err != nil { | |||||
log.Error("GetDatasetByID failed:%v", err.Error()) | |||||
return false | |||||
} | |||||
repo, _ := GetRepositoryByID(dataset.RepoID) | |||||
if err != nil { | |||||
log.Error("GetRepositoryByID failed:%v", err.Error()) | |||||
return false | |||||
} | |||||
permission, _ := GetUserRepoPermission(repo, user) | |||||
if err != nil { | |||||
log.Error("GetUserRepoPermission failed:%v", err.Error()) | |||||
return false | |||||
} | |||||
if user.ID == attach.UploaderID || user.IsAdmin || permission.AccessMode >= AccessModeAdmin { | |||||
return true | |||||
} | |||||
return false | |||||
} |
@@ -3,6 +3,7 @@ package models | |||||
import ( | import ( | ||||
"encoding/json" | "encoding/json" | ||||
"fmt" | "fmt" | ||||
"strings" | |||||
"time" | "time" | ||||
"xorm.io/xorm" | "xorm.io/xorm" | ||||
@@ -176,6 +177,10 @@ func ConvertToTaskPod(input map[string]interface{}) (TaskPod, error) { | |||||
err := json.Unmarshal(data, &taskPod) | err := json.Unmarshal(data, &taskPod) | ||||
taskPod.TaskStatuses[0].StartTime = time.Unix(taskPod.TaskStatuses[0].StartAt.Unix()+8*3600, 0).UTC().Format("2006-01-02 15:04:05") | taskPod.TaskStatuses[0].StartTime = time.Unix(taskPod.TaskStatuses[0].StartAt.Unix()+8*3600, 0).UTC().Format("2006-01-02 15:04:05") | ||||
taskPod.TaskStatuses[0].FinishedTime = time.Unix(taskPod.TaskStatuses[0].FinishedAt.Unix()+8*3600, 0).UTC().Format("2006-01-02 15:04:05") | taskPod.TaskStatuses[0].FinishedTime = time.Unix(taskPod.TaskStatuses[0].FinishedAt.Unix()+8*3600, 0).UTC().Format("2006-01-02 15:04:05") | ||||
//if the task is not finished or stopped,the cloudbrain renturns 0001-01-01 08:00:00, the finishedTime shows with - | |||||
if strings.HasPrefix(taskPod.TaskStatuses[0].FinishedTime, "0001") { | |||||
taskPod.TaskStatuses[0].FinishedTime = "-" | |||||
} | |||||
return taskPod, err | return taskPod, err | ||||
} | } | ||||
@@ -196,11 +196,11 @@ func (s datasetMetaSearch) Less(i, j int) bool { | |||||
return s.ID[i] < s.ID[j] | return s.ID[i] < s.ID[j] | ||||
} | } | ||||
func GetDatasetAttachments(typeCloudBrain int, rels ...*Dataset) (err error) { | |||||
return getDatasetAttachments(x, typeCloudBrain, rels...) | |||||
func GetDatasetAttachments(typeCloudBrain int, isSigned bool, user *User, rels ...*Dataset) (err error) { | |||||
return getDatasetAttachments(x, typeCloudBrain, isSigned, user, rels...) | |||||
} | } | ||||
func getDatasetAttachments(e Engine, typeCloudBrain int, rels ...*Dataset) (err error) { | |||||
func getDatasetAttachments(e Engine, typeCloudBrain int, isSigned bool, user *User, rels ...*Dataset) (err error) { | |||||
if len(rels) == 0 { | if len(rels) == 0 { | ||||
return | return | ||||
} | } | ||||
@@ -243,6 +243,7 @@ func getDatasetAttachments(e Engine, typeCloudBrain int, rels ...*Dataset) (err | |||||
return err | return err | ||||
} | } | ||||
attachment.FileChunk = fileChunks[0] | attachment.FileChunk = fileChunks[0] | ||||
attachment.CanDel = CanDelAttachment(isSigned, user, attachment) | |||||
sortedRels.Rel[currentIndex].Attachments = append(sortedRels.Rel[currentIndex].Attachments, attachment) | sortedRels.Rel[currentIndex].Attachments = append(sortedRels.Rel[currentIndex].Attachments, attachment) | ||||
} | } | ||||
@@ -47,7 +47,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m | |||||
// No need for init mirror. | // No need for init mirror. | ||||
if !opts.IsMirror { | if !opts.IsMirror { | ||||
repoPath := models.RepoPath(u.Name, repo.Name) | repoPath := models.RepoPath(u.Name, repo.Name) | ||||
if err = initRepository(ctx, repoPath, u, repo, opts); err != nil { | |||||
if err = initRepository(ctx, repoPath, doer, u, repo, opts); err != nil { | |||||
if err2 := os.RemoveAll(repoPath); err2 != nil { | if err2 := os.RemoveAll(repoPath); err2 != nil { | ||||
log.Error("initRepository: %v", err) | log.Error("initRepository: %v", err) | ||||
return fmt.Errorf( | return fmt.Errorf( | ||||
@@ -176,7 +176,7 @@ func checkInitRepository(repoPath string) (err error) { | |||||
} | } | ||||
// InitRepository initializes README and .gitignore if needed. | // InitRepository initializes README and .gitignore if needed. | ||||
func initRepository(ctx models.DBContext, repoPath string, u *models.User, repo *models.Repository, opts models.CreateRepoOptions) (err error) { | |||||
func initRepository(ctx models.DBContext, repoPath string, doer *models.User, u *models.User, repo *models.Repository, opts models.CreateRepoOptions) (err error) { | |||||
if err = checkInitRepository(repoPath); err != nil { | if err = checkInitRepository(repoPath); err != nil { | ||||
return err | return err | ||||
} | } | ||||
@@ -195,8 +195,14 @@ func initRepository(ctx models.DBContext, repoPath string, u *models.User, repo | |||||
} | } | ||||
// Apply changes and commit. | // Apply changes and commit. | ||||
if err = initRepoCommit(tmpDir, repo, u, opts.DefaultBranch); err != nil { | |||||
return fmt.Errorf("initRepoCommit: %v", err) | |||||
if u.IsOrganization() { | |||||
if err = initRepoCommit(tmpDir, repo, doer, opts.DefaultBranch); err != nil { | |||||
return fmt.Errorf("initRepoCommit: %v", err) | |||||
} | |||||
} else { | |||||
if err = initRepoCommit(tmpDir, repo, u, opts.DefaultBranch); err != nil { | |||||
return fmt.Errorf("initRepoCommit: %v", err) | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -13,8 +13,8 @@ const ( | |||||
DecompressTaskName = "Decompress" | DecompressTaskName = "Decompress" | ||||
) | ) | ||||
func SendDecompressTask(ctx context.Context, uuid string) error { | |||||
args := []tasks.Arg{{Name: "uuid", Type: "string", Value: uuid}} | |||||
func SendDecompressTask(ctx context.Context, uuid string, name string) error { | |||||
args := []tasks.Arg{{Name: "uuid", Type: "string", Value: uuid}, {Name: "name", Type: "string", Value: name}} | |||||
task, err := tasks.NewSignature(DecompressTaskName, args) | task, err := tasks.NewSignature(DecompressTaskName, args) | ||||
if err != nil { | if err != nil { | ||||
log.Error("NewSignature failed:", err.Error()) | log.Error("NewSignature failed:", err.Error()) | ||||
@@ -712,7 +712,17 @@ function loadimg(){ | |||||
reset_var(); | reset_var(); | ||||
var picturePath = labeltastresult[fileindex].pic_image_field; | var picturePath = labeltastresult[fileindex].pic_image_field; | ||||
img.src = ip + "/getgiteaimage?filename=" + picturePath; | img.src = ip + "/getgiteaimage?filename=" + picturePath; | ||||
var html = picturePath.substring(picturePath.lastIndexOf("/") + 1) + " "+ "(" + (tablePageData.current * pageSize + fileindex + 1) + "/" + tablePageData.total + ")" | |||||
var picIndex = picturePath.indexOf("/",70); | |||||
if(picIndex != -1){ | |||||
float_text_name = picturePath.substring(picIndex + 1); | |||||
float_text_name = float_text_name.substring(float_text_name.indexOf('/')+1); | |||||
}else{ | |||||
float_text_name = picturePath.substring(picturePath.lastIndexOf("/") + 1) | |||||
} | |||||
var html = float_text_name + " "+ "(" + (tablePageData.current * pageSize + fileindex + 1) + "/" + tablePageData.total + ")" | |||||
document.getElementById("float_text").innerHTML = html; | document.getElementById("float_text").innerHTML = html; | ||||
} | } | ||||
function save(){ | function save(){ | ||||
@@ -1640,22 +1650,31 @@ function showfilelist(){ | |||||
var htmlstr=""; | var htmlstr=""; | ||||
for (var i=0;i<labeltastresult.length;i++){ | for (var i=0;i<labeltastresult.length;i++){ | ||||
var fname = labeltastresult[i].pic_image_field.substring(labeltastresult[i].pic_image_field.lastIndexOf('/') + 1); | var fname = labeltastresult[i].pic_image_field.substring(labeltastresult[i].pic_image_field.lastIndexOf('/') + 1); | ||||
if(labeltastresult[i].pic_image_field.length > 70){ | |||||
var tmpIndex = labeltastresult[i].pic_image_field.indexOf("/",70); | |||||
console.log(tmpIndex) | |||||
if(tmpIndex != -1){ | |||||
fname = labeltastresult[i].pic_image_field.substring(tmpIndex + 1); | |||||
fname = fname.substring(fname.indexOf('/')+1); | |||||
} | |||||
} | |||||
var isfinished = labeltastresult[i].label_status; | var isfinished = labeltastresult[i].label_status; | ||||
if(isVerified()){ | |||||
isfinished = labeltastresult[i].verify_status - 1; | |||||
} | |||||
if(isVerified()){ | |||||
isfinished = labeltastresult[i].verify_status - 1; | |||||
} | |||||
var lablebg=" style=\"cursor:pointer\""; | var lablebg=" style=\"cursor:pointer\""; | ||||
var classStr = "style=\"color:#FF6200;background: transparent;border: 0;\""; | var classStr = "style=\"color:#FF6200;background: transparent;border: 0;\""; | ||||
var finish="未完成"; | var finish="未完成"; | ||||
if (isfinished=="0"){finish="已完成";classStr = "style=\"color:#27c24c;background: transparent;border: 0;\"";} | if (isfinished=="0"){finish="已完成";classStr = "style=\"color:#27c24c;background: transparent;border: 0;\"";} | ||||
if (i==fileindex){lablebg=" style=\"color:#fff;cursor:pointer;\"";classStr = "style=\"color:#04B3E5;background: transparent;border: 0;\"";finish="标注中"} | if (i==fileindex){lablebg=" style=\"color:#fff;cursor:pointer;\"";classStr = "style=\"color:#04B3E5;background: transparent;border: 0;\"";finish="标注中"} | ||||
if(isVerified()){ | |||||
htmlstr = htmlstr+"<tr onclick=\"clickfilelist("+i+");\""+ lablebg+"> <td width=\"70\"" +"style=\"vertical-align:middle\""+ classStr + ">"+"<button"+classStr+" type=\"button\" onclick=\"changeVerifyStatus("+i+");\" style=\"border:none;background:none\">"+finish +"</button>"+"</td><td>"+ fname+ "</td></tr>"; | |||||
}else{ | |||||
htmlstr = htmlstr+"<tr onclick=\"clickfilelist("+i+");\""+lablebg+"><td>"+fname+"</td><td width=\"110\""+"style=\"vertical-align:middle\">"+"<button onclick=\"changeStatus("+i+");\" "+ classStr +" style=\"border:none;background:none\">"+finish +"</button>"+"</td></tr>"; | |||||
} | |||||
if(isVerified()){ | |||||
htmlstr = htmlstr+"<tr onclick=\"clickfilelist("+i+");\""+ lablebg+"> <td width=\"70\"" +"style=\"vertical-align:middle\""+ classStr + ">"+"<button"+classStr+" type=\"button\" onclick=\"changeVerifyStatus("+i+");\" style=\"border:none;background:none\">"+finish +"</button>"+"</td><td>"+ fname+ "</td></tr>"; | |||||
}else{ | |||||
htmlstr = htmlstr+"<tr onclick=\"clickfilelist("+i+");\""+lablebg+"><td>"+fname+"</td><td width=\"110\""+"style=\"vertical-align:middle\">"+"<button onclick=\"changeStatus("+i+");\" "+ classStr +" style=\"border:none;background:none\">"+finish +"</button>"+"</td></tr>"; | |||||
} | |||||
}; | |||||
} | |||||
document.getElementById("filelist").innerHTML=htmlstr; | document.getElementById("filelist").innerHTML=htmlstr; | ||||
} | } | ||||
@@ -2834,8 +2853,8 @@ function isJSON(str) { | |||||
img.onload = function(){ | img.onload = function(){ | ||||
loadFinished = false; | loadFinished = false; | ||||
// 初始设置画布大小,最大值宽和高 | // 初始设置画布大小,最大值宽和高 | ||||
canvas.width = maxWidth;//document.getElementById("tool0").offsetWidth; | |||||
canvas.height = maxHeight;//document.getElementById("tool0").offsetWidth/1280*720; | |||||
canvas.width = img.width;// maxWidth document.getElementById("tool0").offsetWidth; | |||||
canvas.height =img.height;//maxHeight document.getElementById("tool0").offsetWidth/1280*720; | |||||
//调整画布大小 | //调整画布大小 | ||||
if ((img.width/img.height)<(canvas.width/canvas.height)){ | if ((img.width/img.height)<(canvas.width/canvas.height)){ | ||||
canvas.width=canvas.height * img.width / img.height; | canvas.width=canvas.height * img.width / img.height; | ||||
@@ -318,7 +318,7 @@ function label_task_create(task_name, relate_task_id, taskType,assign_user_id,la | |||||
success:function(res){ | success:function(res){ | ||||
console.log(res); | console.log(res); | ||||
if(res.code == 0){ | if(res.code == 0){ | ||||
alert("人工校验任务创建成功!"); | |||||
alert("人工标注任务创建成功!"); | |||||
createsucced = true; | createsucced = true; | ||||
} | } | ||||
else{ | else{ | ||||
@@ -128,7 +128,9 @@ func DeleteAttachment(ctx *context.Context) { | |||||
ctx.Error(400, err.Error()) | ctx.Error(400, err.Error()) | ||||
return | return | ||||
} | } | ||||
if !ctx.IsSigned || (ctx.User.ID != attach.UploaderID) { | |||||
//issue 214: mod del-dataset permission | |||||
if !models.CanDelAttachment(ctx.IsSigned, ctx.User, attach) { | |||||
ctx.Error(403) | ctx.Error(403) | ||||
return | return | ||||
} | } | ||||
@@ -146,7 +148,7 @@ func DeleteAttachment(ctx *context.Context) { | |||||
_, err = models.DeleteFileChunkById(attach.UUID) | _, err = models.DeleteFileChunkById(attach.UUID) | ||||
if err != nil { | if err != nil { | ||||
ctx.Error(500, fmt.Sprintf("DeleteAttachment: %v", err)) | |||||
ctx.Error(500, fmt.Sprintf("DeleteFileChunkById: %v", err)) | |||||
return | return | ||||
} | } | ||||
ctx.JSON(200, map[string]string{ | ctx.JSON(200, map[string]string{ | ||||
@@ -384,9 +386,9 @@ func AddAttachment(ctx *context.Context) { | |||||
} | } | ||||
if attachment.DatasetID != 0 { | if attachment.DatasetID != 0 { | ||||
if strings.HasSuffix(attachment.Name, ".zip") { | |||||
if isCanDecompress(attachment.Name) { | |||||
if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
err = worker.SendDecompressTask(contexExt.Background(), uuid) | |||||
err = worker.SendDecompressTask(contexExt.Background(), uuid, attachment.Name) | |||||
if err != nil { | if err != nil { | ||||
log.Error("SendDecompressTask(%s) failed:%s", uuid, err.Error()) | log.Error("SendDecompressTask(%s) failed:%s", uuid, err.Error()) | ||||
} else { | } else { | ||||
@@ -406,6 +408,13 @@ func AddAttachment(ctx *context.Context) { | |||||
}) | }) | ||||
} | } | ||||
func isCanDecompress(name string) bool { | |||||
if strings.HasSuffix(name, ".zip") || strings.HasSuffix(name, ".tar.gz") || strings.HasSuffix(name, ".tgz") { | |||||
return true | |||||
} | |||||
return false | |||||
} | |||||
func UpdateAttachmentDecompressState(ctx *context.Context) { | func UpdateAttachmentDecompressState(ctx *context.Context) { | ||||
uuid := ctx.Query("uuid") | uuid := ctx.Query("uuid") | ||||
result := ctx.Query("result") | result := ctx.Query("result") | ||||
@@ -766,9 +775,9 @@ func CompleteMultipart(ctx *context.Context) { | |||||
} | } | ||||
if attachment.DatasetID != 0 { | if attachment.DatasetID != 0 { | ||||
if strings.HasSuffix(attachment.Name, ".zip") { | |||||
if isCanDecompress(attachment.Name) { | |||||
if typeCloudBrain == models.TypeCloudBrainOne { | if typeCloudBrain == models.TypeCloudBrainOne { | ||||
err = worker.SendDecompressTask(contexExt.Background(), uuid) | |||||
err = worker.SendDecompressTask(contexExt.Background(), uuid, attachment.Name) | |||||
if err != nil { | if err != nil { | ||||
log.Error("SendDecompressTask(%s) failed:%s", uuid, err.Error()) | log.Error("SendDecompressTask(%s) failed:%s", uuid, err.Error()) | ||||
} else { | } else { | ||||
@@ -838,7 +847,7 @@ func HandleUnDecompressAttachment() { | |||||
} | } | ||||
for _, attach := range attachs { | for _, attach := range attachs { | ||||
err = worker.SendDecompressTask(contexExt.Background(), attach.UUID) | |||||
err = worker.SendDecompressTask(contexExt.Background(), attach.UUID, attach.Name) | |||||
if err != nil { | if err != nil { | ||||
log.Error("SendDecompressTask(%s) failed:%s", attach.UUID, err.Error()) | log.Error("SendDecompressTask(%s) failed:%s", attach.UUID, err.Error()) | ||||
} else { | } else { | ||||
@@ -67,7 +67,7 @@ func CloudBrainIndex(ctx *context.Context) { | |||||
timestamp := time.Now().Unix() | timestamp := time.Now().Unix() | ||||
for i, task := range ciTasks { | for i, task := range ciTasks { | ||||
if task.Status == string(models.JobRunning) && (timestamp-int64(task.CreatedUnix) > 30) { | |||||
if task.Status == string(models.JobRunning) && (timestamp-int64(task.CreatedUnix) > 10) { | |||||
ciTasks[i].CanDebug = true | ciTasks[i].CanDebug = true | ||||
} else { | } else { | ||||
ciTasks[i].CanDebug = false | ciTasks[i].CanDebug = false | ||||
@@ -267,6 +267,7 @@ func CloudBrainShow(ctx *context.Context) { | |||||
if result != nil { | if result != nil { | ||||
jobRes, _ := models.ConvertToJobResultPayload(result.Payload) | jobRes, _ := models.ConvertToJobResultPayload(result.Payload) | ||||
jobRes.Resource.Memory = strings.ReplaceAll(jobRes.Resource.Memory, "Mi", "MB") | |||||
ctx.Data["result"] = jobRes | ctx.Data["result"] = jobRes | ||||
taskRoles := jobRes.TaskRoles | taskRoles := jobRes.TaskRoles | ||||
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | ||||
@@ -76,7 +76,7 @@ func QueryDataSet(ctx *context.Context) []*models.Attachment { | |||||
ctx.NotFound("type error", nil) | ctx.NotFound("type error", nil) | ||||
return nil | return nil | ||||
} | } | ||||
err = models.GetDatasetAttachments(ctx.QueryInt("type"), dataset) | |||||
err = models.GetDatasetAttachments(ctx.QueryInt("type"), ctx.IsSigned, ctx.User, dataset) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetDatasetAttachments", err) | ctx.ServerError("GetDatasetAttachments", err) | ||||
return nil | return nil | ||||
@@ -120,7 +120,7 @@ func DatasetIndex(ctx *context.Context) { | |||||
ctx.NotFound("type error", nil) | ctx.NotFound("type error", nil) | ||||
return | return | ||||
} | } | ||||
err = models.GetDatasetAttachments(ctx.QueryInt("type"), dataset) | |||||
err = models.GetDatasetAttachments(ctx.QueryInt("type"), ctx.IsSigned, ctx.User, dataset) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetDatasetAttachments", err) | ctx.ServerError("GetDatasetAttachments", err) | ||||
return | return | ||||
@@ -39,7 +39,8 @@ func DeleteAllUnzipFile(attachment *models.Attachment, parentDir string) { | |||||
uuid := attachment.UUID | uuid := attachment.UUID | ||||
dirArray := strings.Split(parentDir, "/") | dirArray := strings.Split(parentDir, "/") | ||||
if !strings.HasSuffix(attachment.Name, ".zip") { | |||||
//if !strings.HasSuffix(attachment.Name, ".zip") { | |||||
if !isCanDecompress(attachment.Name) { | |||||
log.Error("The file is not zip file, can not query the dir") | log.Error("The file is not zip file, can not query the dir") | ||||
return | return | ||||
} else if attachment.DecompressState != models.DecompressStateDone { | } else if attachment.DecompressState != models.DecompressStateDone { | ||||
@@ -69,7 +70,7 @@ func DeleteAllUnzipFile(attachment *models.Attachment, parentDir string) { | |||||
log.Info("fileName=" + fileInfo.FileName) | log.Info("fileName=" + fileInfo.FileName) | ||||
log.Info("parentDir=" + fileInfo.ParenDir) | log.Info("parentDir=" + fileInfo.ParenDir) | ||||
if fileInfo.IsDir { | if fileInfo.IsDir { | ||||
DeleteAllUnzipFile(attachment, fileInfo.FileName) | |||||
DeleteAllUnzipFile(attachment, fileInfo.ParenDir) | |||||
} else { | } else { | ||||
absolutepath := path.Join(attachment.RelativePath()+attachment.UUID, fileInfo.ParenDir) | absolutepath := path.Join(attachment.RelativePath()+attachment.UUID, fileInfo.ParenDir) | ||||
log.Info("absolutepath=" + absolutepath) | log.Info("absolutepath=" + absolutepath) | ||||
@@ -127,7 +128,8 @@ func DirIndex(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
if !strings.HasSuffix(attachment.Name, ".zip") { | |||||
//if !strings.HasSuffix(attachment.Name, ".zip") { | |||||
if !isCanDecompress(attachment.Name) { | |||||
log.Error("The file is not zip file, can not query the dir") | log.Error("The file is not zip file, can not query the dir") | ||||
ctx.ServerError("The file is not zip file, can not query the dir", errors.New("The file is not zip file, can not query the dir")) | ctx.ServerError("The file is not zip file, can not query the dir", errors.New("The file is not zip file, can not query the dir")) | ||||
return | return | ||||
@@ -2,6 +2,13 @@ | |||||
{{template "base/head" .}} | {{template "base/head" .}} | ||||
<style> | <style> | ||||
.label_after::after{ | |||||
margin: -.2em 0 0 .2em; | |||||
content: '\00a0'; | |||||
} | |||||
.selectcloudbrain .active.item{ | .selectcloudbrain .active.item{ | ||||
color: #0087f5 !important; | color: #0087f5 !important; | ||||
border: 1px solid #0087f5; | border: 1px solid #0087f5; | ||||
@@ -232,13 +239,13 @@ | |||||
<div class="ui two column stackable grid"> | <div class="ui two column stackable grid"> | ||||
<div class="column"> | <div class="column"> | ||||
</div> | </div> | ||||
<div class="column right aligned"> | |||||
<!-- <div class="column right aligned"> | |||||
<div class="ui right dropdown type jump item"> | <div class="ui right dropdown type jump item"> | ||||
<span class="text"> | <span class="text"> | ||||
{{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> | {{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> | ||||
</span> | </span> | ||||
</div> | </div> | ||||
</div> | |||||
</div> --> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -320,37 +327,40 @@ | |||||
<!-- 镜像列表弹窗 --> | <!-- 镜像列表弹窗 --> | ||||
<div id="imageModal" class="modal" style="display: none;"> | <div id="imageModal" class="modal" style="display: none;"> | ||||
<div class="modal-content"> | <div class="modal-content"> | ||||
<span class="close">×</span> | |||||
<!-- 表格 --> | <!-- 表格 --> | ||||
<form id="commitImageForm" action="{{$.Link}}/{{.JobID}}/commit_image" method="post" target="iframeContent"> | |||||
{{$.CsrfTokenHtml}} | |||||
<p>提交任务镜像</p> | |||||
<div class="ui divider"></div> | |||||
<div class="inline required field dis"> | |||||
<label>镜像标签:</label> | |||||
<input name="tag" id="image_tag" tabindex="3" autofocus required maxlength="255" style="width:75%"> | |||||
</div> | |||||
<div class="inline required field" style="position:relative;height:180px;"> | |||||
<div style="height:20px;width:75px;"> | |||||
<label>镜像描述:</label> | |||||
<div class="ui form"> | |||||
<form id="commitImageForm" action="{{$.Link}}/{{.JobID}}/commit_image" method="post" target="iframeContent"> | |||||
{{$.CsrfTokenHtml}} | |||||
<div class="row"> | |||||
<p style="display: inline;">提交任务镜像</p> | |||||
<span class="close">×</span> | |||||
</div> | </div> | ||||
<div style="position:absolute;left:75px;top:0;width:75%"> | |||||
<textarea name="description" rows="10" style="width:100%"></textarea> | |||||
<div class="ui divider"></div> | |||||
<div class="inline required field dis"> | |||||
<label>镜像标签:</label> | |||||
<input name="tag" id="image_tag" tabindex="3" autofocus required maxlength="255" style="width:75%"> | |||||
</div> | </div> | ||||
</div> | |||||
<div class="ui divider"></div> | |||||
<div class="inline field"> | |||||
<label></label> | |||||
<button class="ui green button" onclick="showmask()"> | |||||
{{$.i18n.Tr "repo.cloudbrain.commit_image"}} | |||||
</button> | |||||
</div> | |||||
</form> | |||||
<div class="inline field"> | |||||
<label class="label_after">镜像描述:</label> | |||||
<textarea name="description" rows="8" style="width:75%;margin-left: 0.2em;"></textarea> | |||||
</div> | |||||
<div class="ui divider"></div> | |||||
<div class="inline field"> | |||||
<label></label> | |||||
<button class="ui green button" onclick="showmask()"> | |||||
{{$.i18n.Tr "repo.cloudbrain.commit_image"}} | |||||
</button> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -431,7 +441,8 @@ | |||||
} | } | ||||
// 加载任务状态 | // 加载任务状态 | ||||
$(document).ready(function() { | |||||
var timeid = window.setInterval(loadJobStatus, 15000); | |||||
function loadJobStatus() { | |||||
$(".job-status").each((index, job) => { | $(".job-status").each((index, job) => { | ||||
const jobID = job.dataset.jobid; | const jobID = job.dataset.jobid; | ||||
const repoPath = job.dataset.repopath; | const repoPath = job.dataset.repopath; | ||||
@@ -442,13 +453,17 @@ | |||||
$.get(`/api/v1/repos/${repoPath}/cloudbrain/${jobID}`, (data) => { | $.get(`/api/v1/repos/${repoPath}/cloudbrain/${jobID}`, (data) => { | ||||
const jobID = data.JobID | const jobID = data.JobID | ||||
const status = data.JobStatus | const status = data.JobStatus | ||||
$('#' + jobID).text(status) | |||||
// console.log(data) | |||||
if (status != job.textContent.trim()) { | |||||
//$('#' + jobID).text(status) | |||||
//if (status == 'STOPPED') { | |||||
window.location.reload() | |||||
//} | |||||
} | |||||
}).fail(function(err) { | }).fail(function(err) { | ||||
console.log(err); | console.log(err); | ||||
}); | }); | ||||
}); | }); | ||||
}); | |||||
}; | |||||
// 获取弹窗 | // 获取弹窗 | ||||
var modal = document.getElementById('imageModal'); | var modal = document.getElementById('imageModal'); | ||||
@@ -482,6 +497,11 @@ | |||||
// 显示弹窗,弹出相应的信息 | // 显示弹窗,弹出相应的信息 | ||||
function showmask() { | function showmask() { | ||||
var image_tag = !$('#image_tag').val() | |||||
console.log("image_tag",image_tag) | |||||
if(image_tag){ | |||||
return | |||||
} | |||||
$('#imageModal').css('display', 'none') | $('#imageModal').css('display', 'none') | ||||
$('#mask').css('display', 'block') | $('#mask').css('display', 'block') | ||||
@@ -177,8 +177,9 @@ | |||||
</div> | </div> | ||||
<div class="inline required field"> | <div class="inline required field"> | ||||
<label>数据集(只有zip格式的数据集才能发起云脑任务)</label> | |||||
<select id="cloudbrain_dataset" class="ui search dropdown" placeholder="选择数据集" style='width:385px' name="attachment"> | |||||
<label>数据集</label> | |||||
<select id="cloudbrain_dataset" class="ui search dropdown" placeholder="选择数据集" style='width:385px' name="attachment" required> | |||||
{{range .attachments}} | {{range .attachments}} | ||||
<option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | <option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | ||||
{{end}} | {{end}} | ||||
@@ -241,15 +242,14 @@ | |||||
let url_href = window.location.pathname.split('create')[0] | let url_href = window.location.pathname.split('create')[0] | ||||
$(".ui.button").attr('href',url_href) | $(".ui.button").attr('href',url_href) | ||||
let form = document.getElementById('form_id'); | let form = document.getElementById('form_id'); | ||||
let value_image = $("input[name='image']").val() | |||||
console.log("value_image",$("input[name='image']").val()) | |||||
$('#messageInfo').css('display','none') | $('#messageInfo').css('display','none') | ||||
form.onsubmit = function(e){ | form.onsubmit = function(e){ | ||||
let value_task = $("input[name='job_name']").val() | let value_task = $("input[name='job_name']").val() | ||||
let value_image = $("input[name='image']").val() | let value_image = $("input[name='image']").val() | ||||
let value_data = $("input[name='attachment']").val() | |||||
let re = /^[a-z0-9][a-z0-9-_]{1,36}$/ | let re = /^[a-z0-9][a-z0-9-_]{1,36}$/ | ||||
let flag = re.test(value_task) | let flag = re.test(value_task) | ||||
if(!flag){ | if(!flag){ | ||||
@@ -258,13 +258,10 @@ | |||||
$('#messageInfo p').text(str) | $('#messageInfo p').text(str) | ||||
return false | return false | ||||
} | } | ||||
if(!value_image){ | |||||
if(!value_image || !value_data){ | |||||
return false | return false | ||||
} | } | ||||
let min_value_task = value_task.toLowerCase() | let min_value_task = value_task.toLowerCase() | ||||
console.log(min_value_task) | |||||
$("input[name='job_name']").attr("value",min_value_task) | $("input[name='job_name']").attr("value",min_value_task) | ||||
document.getElementById("mask").style.display = "block" | document.getElementById("mask").style.display = "block" | ||||
@@ -24,22 +24,6 @@ | |||||
<td class="four wide"> 状态 </td> | <td class="four wide"> 状态 </td> | ||||
<td> {{.State}} </td> | <td> {{.State}} </td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td> 开始时间 </td> | |||||
<td>{{.StartTime}}</td> | |||||
</tr> | |||||
<tr> | |||||
<td> 结束时间 </td> | |||||
<td>{{.FinishedTime}}</td> | |||||
</tr> | |||||
<tr> | |||||
<td> ExitCode </td> | |||||
<td>{{.ExitCode}}</td> | |||||
</tr> | |||||
<tr> | |||||
<td> 退出信息 </td> | |||||
<td>{{.ExitDiagnostics| nl2br}}</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
{{end}} | {{end}} | ||||
@@ -73,7 +57,7 @@ | |||||
</thead> | </thead> | ||||
<tbody> | <tbody> | ||||
<tr> | <tr> | ||||
<td class="four wide"> 状态 </td> | |||||
<td class="four wide"> 平台 </td> | |||||
<td> {{.Platform}} </td> | <td> {{.Platform}} </td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
@@ -31,7 +31,7 @@ | |||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
{{if $.Permission.CanWrite $.UnitTypeDatasets}} | {{if $.Permission.CanWrite $.UnitTypeDatasets}} | ||||
{{if $.Repository.IsPrivate}} | |||||
{{if (not .CanDel) or $.Repository.IsPrivate}} | |||||
<div class="two wide column"> | <div class="two wide column"> | ||||
<a class="ui button mini" disabled='true' data-tooltip='{{$.i18n.Tr "dataset.how_to_public"}}'>{{$.i18n.Tr "dataset.private"}}</a> | <a class="ui button mini" disabled='true' data-tooltip='{{$.i18n.Tr "dataset.how_to_public"}}'>{{$.i18n.Tr "dataset.private"}}</a> | ||||
</div> | </div> | ||||
@@ -45,7 +45,7 @@ | |||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
<div class="two wide column right aligned"> | |||||
<div class="two wide column right aligned" style="{{if not .CanDel}}visibility: hidden;{{end}}"> | |||||
<a class="ui red button mini" href="javascript:void(0)" data-uuid={{.UUID}} data-dataset-delete data-remove-url="{{AppSubUrl}}/attachments/delete" data-csrf="{{$.CsrfToken}}">{{$.i18n.Tr "dataset.delete"}}</a> | <a class="ui red button mini" href="javascript:void(0)" data-uuid={{.UUID}} data-dataset-delete data-remove-url="{{AppSubUrl}}/attachments/delete" data-csrf="{{$.CsrfToken}}">{{$.i18n.Tr "dataset.delete"}}</a> | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
@@ -144,11 +144,12 @@ | |||||
{{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}} | {{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
{{if .IsSigned}} | |||||
<a class="{{if .PageIsBlockChain}}active{{end}} item " href="{{.RepoLink}}/blockchain"> | <a class="{{if .PageIsBlockChain}}active{{end}} item " href="{{.RepoLink}}/blockchain"> | ||||
{{svg "octicon-law" 16}} | {{svg "octicon-law" 16}} | ||||
{{.i18n.Tr "repo.balance"}} | {{.i18n.Tr "repo.balance"}} | ||||
</a> | </a> | ||||
{{end}} | |||||
{{template "custom/extra_tabs" .}} | {{template "custom/extra_tabs" .}} | ||||
@@ -232,13 +232,13 @@ | |||||
<div class="ui two column stackable grid"> | <div class="ui two column stackable grid"> | ||||
<div class="column"> | <div class="column"> | ||||
</div> | </div> | ||||
<div class="column right aligned"> | |||||
<!-- <div class="column right aligned"> | |||||
<div class="ui right dropdown type jump item"> | <div class="ui right dropdown type jump item"> | ||||
<span class="text"> | <span class="text"> | ||||
{{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> | {{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> | ||||
</span> | </span> | ||||
</div> | </div> | ||||
</div> | |||||
</div> --> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -418,7 +418,8 @@ | |||||
} | } | ||||
// 加载任务状态 | // 加载任务状态 | ||||
$(document).ready(function() { | |||||
var timeid = window.setInterval(loadJobStatus, 15000); | |||||
function loadJobStatus() { | |||||
$(".job-status").each((index, job) => { | $(".job-status").each((index, job) => { | ||||
const jobID = job.dataset.jobid; | const jobID = job.dataset.jobid; | ||||
const repoPath = job.dataset.repopath; | const repoPath = job.dataset.repopath; | ||||
@@ -429,13 +430,17 @@ | |||||
$.get(`/api/v1/repos/${repoPath}/modelarts/${jobID}`, (data) => { | $.get(`/api/v1/repos/${repoPath}/modelarts/${jobID}`, (data) => { | ||||
const jobID = data.JobID | const jobID = data.JobID | ||||
const status = data.JobStatus | const status = data.JobStatus | ||||
$('#' + jobID).text(status) | |||||
// console.log(data) | |||||
if (status != job.textContent.trim()) { | |||||
//$('#' + jobID).text(status) | |||||
//if (status == 'STOPPED') { | |||||
window.location.reload() | |||||
//} | |||||
} | |||||
}).fail(function(err) { | }).fail(function(err) { | ||||
console.log(err); | console.log(err); | ||||
}); | }); | ||||
}); | }); | ||||
}); | |||||
}; | |||||
// 获取弹窗 | // 获取弹窗 | ||||
var modal = document.getElementById('imageModal'); | var modal = document.getElementById('imageModal'); | ||||
@@ -100,7 +100,10 @@ | |||||
<div class="repository new repo ui middle very relaxed page grid"> | <div class="repository new repo ui middle very relaxed page grid"> | ||||
<div class="column"> | <div class="column"> | ||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<form class="ui form" action="{{.Link}}" method="post"> | |||||
<div class="ui positive message" id="messageInfo"> | |||||
<p></p> | |||||
</div> | |||||
<form class="ui form" id="form_id" action="{{.Link}}" method="post"> | |||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
<h3 class="ui top attached header"> | <h3 class="ui top attached header"> | ||||
{{.i18n.Tr "repo.cloudbrain.new"}} | {{.i18n.Tr "repo.cloudbrain.new"}} | ||||
@@ -125,11 +128,11 @@ | |||||
<div class="inline required field"> | <div class="inline required field"> | ||||
<label>工作环境</label> | <label>工作环境</label> | ||||
<input name="de" id="cloudbrain_de" value="{{.env}}" tabindex="3" autofocus required maxlength="255" readonly="readonly"> | |||||
<input name="de" id="cloudbrain_de" value="{{.env}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||||
</div> | </div> | ||||
<div class="inline required field"> | <div class="inline required field"> | ||||
<label>类型</label> | <label>类型</label> | ||||
<input name="job_type" id="cloudbrain_job_type" value="{{.notebook_type}}" tabindex="3" autofocus required maxlength="255" readonly="readonly"> | |||||
<input name="job_type" id="cloudbrain_job_type" value="{{.notebook_type}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||||
</div> | </div> | ||||
<div class="inline required field"> | <div class="inline required field"> | ||||
<label>规格</label> | <label>规格</label> | ||||
@@ -142,7 +145,7 @@ | |||||
</div> | </div> | ||||
<div class="inline required field"> | <div class="inline required field"> | ||||
<label>数据集存放路径</label> | <label>数据集存放路径</label> | ||||
<input name="dataset_path" id="cloudbrain_dataset_path" value="{{.dataset_path}}" tabindex="3" autofocus required maxlength="255" readonly="readonly"> | |||||
<input name="dataset_path" id="cloudbrain_dataset_path" value="{{.dataset_path}}" tabindex="3" disabled autofocus required maxlength="255" readonly="readonly"> | |||||
</div> | </div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>描述</label> | <label>描述</label> | ||||
@@ -150,7 +153,7 @@ | |||||
</div> | </div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label></label> | <label></label> | ||||
<button class="ui green button" onclick="showmask()"> | |||||
<button class="ui green button"> | |||||
{{.i18n.Tr "repo.cloudbrain.new"}} | {{.i18n.Tr "repo.cloudbrain.new"}} | ||||
</button> | </button> | ||||
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | <a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | ||||
@@ -163,10 +166,38 @@ | |||||
{{template "base/footer" .}} | {{template "base/footer" .}} | ||||
<script> | <script> | ||||
// 点击按钮后遮罩层显示 | |||||
function showmask() { | |||||
// 取消创建跳转 | |||||
let url_href = window.location.pathname.split('create')[0] | |||||
$(".ui.button").attr('href',url_href) | |||||
// 判断必填选项是否填写正确 | |||||
let form = document.getElementById('form_id'); | |||||
$('#messageInfo').css('display','none') | |||||
form.onsubmit = function(e){ | |||||
let value_task = $("input[name='job_name']").val() | |||||
let re = /^[a-z0-9][a-z0-9-_]{1,36}$/ | |||||
let flag = re.test(value_task) | |||||
if(!flag){ | |||||
$('#messageInfo').css('display','block') | |||||
let str = '只能以小写字母或数字开头且只包含小写字母、数字、_和-、最长36个字符。' | |||||
$('#messageInfo p').text(str) | |||||
return false | |||||
} | |||||
let min_value_task = value_task.toLowerCase() | |||||
$("input[name='job_name']").attr("value",min_value_task) | |||||
document.getElementById("mask").style.display = "block" | document.getElementById("mask").style.display = "block" | ||||
} | } | ||||
// 点击按钮后遮罩层显示 | |||||
// function showmask() { | |||||
// document.getElementById("mask").style.display = "block" | |||||
// } | |||||
// 页面加载完毕后遮罩层隐藏 | // 页面加载完毕后遮罩层隐藏 | ||||
document.onreadystatechange = function() { | document.onreadystatechange = function() { | ||||
@@ -223,7 +223,7 @@ export default { | |||||
} | } | ||||
//不同数据集上传同一个文件 | //不同数据集上传同一个文件 | ||||
if (file.datasetID != '') { | if (file.datasetID != '') { | ||||
if (Number(file.datasetID) != file.datasetId) { | |||||
if (file.datasetName != "" && file.realName != "") { | |||||
var info = "该文件已上传,对应数据集(" + file.datasetName + ")-文件(" + file.realName + ")"; | var info = "该文件已上传,对应数据集(" + file.datasetName + ")-文件(" + file.realName + ")"; | ||||
window.alert(info); | window.alert(info); | ||||
window.location.reload(); | window.location.reload(); | ||||
@@ -219,8 +219,8 @@ export default { | |||||
await addAttachment(file); | await addAttachment(file); | ||||
} | } | ||||
//不同数据集上传同一个文件 | //不同数据集上传同一个文件 | ||||
if (file.datasetID != '') { | |||||
if (Number(file.datasetID) != file.datasetId) { | |||||
if (file.datasetID != '' ) { | |||||
if (file.datasetName != "" && file.realName != "") { | |||||
var info = "该文件已上传,对应数据集(" + file.datasetName + ")-文件(" + file.realName + ")"; | var info = "该文件已上传,对应数据集(" + file.datasetName + ")-文件(" + file.realName + ")"; | ||||
window.alert(info); | window.alert(info); | ||||
window.location.reload(); | window.location.reload(); | ||||