Browse Source

Merge pull request 'V20210927合入develop' (#478) from V20210927 into develop

Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/478
tags/v1.21.12.1
lewis 4 years ago
parent
commit
c05cce2f0c
30 changed files with 377 additions and 281 deletions
  1. +28
    -1
      models/attachment.go
  2. +5
    -0
      models/cloudbrain.go
  3. +4
    -3
      models/dataset.go
  4. +16
    -0
      models/user.go
  5. +1
    -1
      modules/repository/create.go
  6. +9
    -3
      modules/repository/init.go
  7. +2
    -2
      modules/worker/task.go
  8. +42
    -17
      public/self/js/Director/detection.js
  9. +1
    -1
      public/self/labelTaskPage.js
  10. +16
    -7
      routers/repo/attachment.go
  11. +2
    -1
      routers/repo/cloudbrain.go
  12. +2
    -2
      routers/repo/dataset.go
  13. +5
    -3
      routers/repo/dir.go
  14. +17
    -10
      routers/repo/view.go
  15. +2
    -1
      templates/explore/repo_list.tmpl
  16. +1
    -1
      templates/org/create.tmpl
  17. +98
    -86
      templates/repo/cloudbrain/index.tmpl
  18. +9
    -11
      templates/repo/cloudbrain/new.tmpl
  19. +1
    -17
      templates/repo/cloudbrain/show.tmpl
  20. +1
    -1
      templates/repo/create.tmpl
  21. +23
    -14
      templates/repo/datasets/dataset_list.tmpl
  22. +2
    -1
      templates/repo/header.tmpl
  23. +1
    -1
      templates/repo/migrate.tmpl
  24. +39
    -81
      templates/repo/modelarts/index.tmpl
  25. +39
    -8
      templates/repo/modelarts/new.tmpl
  26. +1
    -1
      web_src/js/components/MinioUploader.vue
  27. +2
    -2
      web_src/js/components/ObsUploader.vue
  28. +2
    -3
      web_src/less/_dataset.less
  29. +4
    -2
      web_src/less/_organization.less
  30. +2
    -0
      web_src/less/_repository.less

+ 28
- 1
models/attachment.go View File

@@ -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
}

+ 5
- 0
models/cloudbrain.go View File

@@ -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
} }




+ 4
- 3
models/dataset.go View File

@@ -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)
} }




+ 16
- 0
models/user.go View File

@@ -1543,6 +1543,22 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
return newCommits return newCommits
} }


// GetUserByActivateEmail returns the user object by given e-mail if exists.
/*This function will search email table only*/
func GetUserByActivateEmail(email string) (*User, error) {
ctx := DefaultDBContext()
var users []User
if err := ctx.e.Join("INNER", "email_address", "email_address.uid = \"user\".id").
Where("email_address.email= ?", email).
Find(&users); err != nil {
return nil,err
}
if len(users) >= 1 {
return &users[0],nil
}else {
return nil, errors.New("cannot find user by email")
}
}
// GetUserByEmail returns the user object by given e-mail if exists. // GetUserByEmail returns the user object by given e-mail if exists.
func GetUserByEmail(email string) (*User, error) { func GetUserByEmail(email string) (*User, error) {
return GetUserByEmailContext(DefaultDBContext(), email) return GetUserByEmailContext(DefaultDBContext(), email)


+ 1
- 1
modules/repository/create.go View File

@@ -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(


+ 9
- 3
modules/repository/init.go View File

@@ -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)
}
} }
} }




+ 2
- 2
modules/worker/task.go View File

@@ -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())


+ 42
- 17
public/self/js/Director/detection.js View File

@@ -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) + "&nbsp;&nbsp;"+ "(" + (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 + "&nbsp;&nbsp;&nbsp;&nbsp;"+ "(" + (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;
} }


@@ -2657,7 +2676,7 @@ function setPage(pageData,pageSize){


canvas = document.getElementById("myCanvas"); canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d"); context = canvas.getContext("2d");
maxWidth = document.getElementById("showPic").offsetWidth;
maxWidth = document.getElementById("showPic").offsetWidth-56;
maxHeight = document.getElementById("showPic").offsetHeight-100; maxHeight = document.getElementById("showPic").offsetHeight-100;
canvas.width = maxWidth; canvas.width = maxWidth;
canvas.height = maxHeight; canvas.height = maxHeight;
@@ -2834,14 +2853,20 @@ 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)){
canvas.width=canvas.height * img.width / img.height;
// if ((img.width/img.height)>(maxWidth/maxWidth)){
// canvas.width=canvas.height * img.width / img.height;
// }
// else{
// canvas.height=canvas.width * img.height / img.width;
// }
if(canvas.width>maxWidth){
canvas.width = maxWidth
} }
else{
canvas.height=canvas.width * img.height / img.width;
if(canvas.height>maxHeight){
canvas.height=maxHeight
} }


maxIdNum=0; maxIdNum=0;


+ 1
- 1
public/self/labelTaskPage.js View File

@@ -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{


+ 16
- 7
routers/repo/attachment.go View File

@@ -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 {


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

@@ -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{}))


+ 2
- 2
routers/repo/dataset.go View File

@@ -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


+ 5
- 3
routers/repo/dir.go View File

@@ -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


+ 17
- 10
routers/repo/view.go View File

@@ -15,6 +15,7 @@ import (
"net/url" "net/url"
"path" "path"
"strings" "strings"
"time"


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
@@ -588,39 +589,45 @@ func Home(ctx *context.Context) {
//get repo contributors info //get repo contributors info
contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath())
if err == nil && contributors != nil { if err == nil && contributors != nil {
startTime := time.Now()
var contributorInfos []*ContributorInfo var contributorInfos []*ContributorInfo
contributorInfoHash:= make(map[string]*ContributorInfo)
for _, c := range contributors { for _, c := range contributors {
if strings.Compare(c.Email,"") == 0 { if strings.Compare(c.Email,"") == 0 {
continue continue
} }
// get user info from committer email // get user info from committer email
user, err := models.GetUserByEmail(c.Email)
user, err := models.GetUserByActivateEmail(c.Email)
if err == nil { if err == nil {
// committer is system user, get info through user's primary email // committer is system user, get info through user's primary email
existedContributorInfo := getContributorInfo(contributorInfos,user.Email)
if existedContributorInfo != nil {
if existedContributorInfo,ok:=contributorInfoHash[user.Email];ok {
// existed: same primary email, different committer name // existed: same primary email, different committer name
existedContributorInfo.CommitCnt += c.CommitCnt existedContributorInfo.CommitCnt += c.CommitCnt
}else{ }else{
// new committer info // new committer info
contributorInfos = append(contributorInfos, &ContributorInfo{
var newContributor = &ContributorInfo{
user, user.Email,c.CommitCnt, user, user.Email,c.CommitCnt,
})
}
contributorInfos = append(contributorInfos, newContributor )
contributorInfoHash[user.Email] = newContributor
} }
} else { } else {
// committer is not system user // committer is not system user
existedContributorInfo := getContributorInfo(contributorInfos,c.Email)
if existedContributorInfo != nil {
if existedContributorInfo,ok:=contributorInfoHash[c.Email];ok {
// existed: same primary email, different committer name // existed: same primary email, different committer name
existedContributorInfo.CommitCnt += c.CommitCnt existedContributorInfo.CommitCnt += c.CommitCnt
}else{ }else{
contributorInfos = append(contributorInfos, &ContributorInfo{
nil, c.Email,c.CommitCnt,
})
var newContributor = &ContributorInfo{
user, c.Email,c.CommitCnt,
}
contributorInfos = append(contributorInfos, newContributor)
contributorInfoHash[c.Email] = newContributor
} }
} }
} }
ctx.Data["ContributorInfo"] = contributorInfos ctx.Data["ContributorInfo"] = contributorInfos
var duration = time.Since(startTime)
log.Info("getContributorInfo cost: %v seconds",duration.Seconds())
} }
if ctx.Repo.Repository.IsBeingCreated() { if ctx.Repo.Repository.IsBeingCreated() {
task, err := models.GetMigratingTask(ctx.Repo.Repository.ID) task, err := models.GetMigratingTask(ctx.Repo.Repository.ID)


+ 2
- 1
templates/explore/repo_list.tmpl View File

@@ -39,6 +39,7 @@
</style> </style>


<div class="ui secondary pointing tabular top attached borderless menu navbar"> <div class="ui secondary pointing tabular top attached borderless menu navbar">
{{if .PageIsExplore}}
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?sort=hot&q={{$.Keyword}}&tab={{$.TabName}}"> <a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?sort=hot&q={{$.Keyword}}&tab={{$.TabName}}">
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> <svg class="svg octicon-repo" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-repo" /> <use xlink:href="#octicon-repo" />
@@ -51,7 +52,7 @@
</svg> </svg>
活跃{{.i18n.Tr "explore.repos"}} 活跃{{.i18n.Tr "explore.repos"}}
</a> </a>
{{end}}
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}"> <a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">
<svg class="svg octicon-organization" width="16" height="16" aria-hidden="true"> <svg class="svg octicon-organization" width="16" height="16" aria-hidden="true">
<use xlink:href="#octicon-organization" /> <use xlink:href="#octicon-organization" />


+ 1
- 1
templates/org/create.tmpl View File

@@ -1,5 +1,5 @@
{{template "base/head" .}} {{template "base/head" .}}
<div class="organization new org">
<div class="organization new org" style="margin-top: 25px;">
<div class="ui middle very relaxed page grid"> <div class="ui middle very relaxed page grid">
<div class="column"> <div class="column">
<form class="ui form" action="{{.Link}}" method="post"> <form class="ui form" action="{{.Link}}" method="post">


+ 98
- 86
templates/repo/cloudbrain/index.tmpl View File

@@ -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>


@@ -249,111 +256,105 @@
<div class="row"> <div class="row">


<!-- 任务名 --> <!-- 任务名 -->
<div class="four wide column">
<div class="six wide column">
<a class="title" href="{{$.Link}}/{{.JobID}}"> <a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">{{svg "octicon-tasklist" 16}}</span> <span class="fitted">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted">{{.JobName}}</span> <span class="fitted">{{.JobName}}</span>
</a> </a>
</div> </div>


<!--任务状态 -->
<div class="two wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}}
</div>

<!-- 任务创建时间 -->
<div class="three wide column"> <div class="three wide column">
<span class="ui text center">{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}</span>
<!--任务状态 -->
<span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}}
</span>
<!-- 任务创建时间 -->
<span class="">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>
</div> </div>


<!-- 评分 -->
<div class="one wide column">
<div class="ui text center clipboard">
<a class="title" onclick="stop(this)" href="{{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}}{{$.Link}}/{{.JobID}}/rate{{else}}javascript:void(0);{{end}}" style="{{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}}{{else}}color:#CCCCCC{{end}}">
<span class="fitted">评分</span>
</a>
</div>
</div>
<div class="seven wide column text right">
<div class="ui compact buttons" style="margin-right:10px;">
{{if and (ne .Status "WAITING") (ne .JobType "DEBUG")}}
<a class="ui basic button" href="{{$.Link}}/{{.JobID}}/rate" target="_blank">
评分
</a>
{{end}}


<!-- 删除镜像 -->
<div class="one wide column">
<div class="ui text center clipboard">
<form id="delForm-{{.JobID}}" action="{{if ne .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post">
<!-- 调试 -->
<a class="ui basic {{if not .CanDebug}}disabled {{else}}blue {{end}}button" href="{{$.Link}}/{{.JobID}}/debug" target="_blank">
调试
</a>
<form id="stopForm-{{.JobID}}" action="{{if eq .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/stop{{end}}" method="post" style="margin-left:-1px;">
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
<a class="fitted" onclick="assertDelete(this)" style="{{if ne .Status "STOPPED"}}color:#CCCCCC{{end}}; font-size:16px; font-weight:bold">删除</a>
</form>
</div>
</div>

<!-- 调试 -->
<div class="one wide column">
<div class="ui text center clipboard">
<a class="title" onclick="stop(this)" href="{{if not .CanDebug}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/debug{{end}}" style="{{if not .CanDebug}}color:#CCCCCC{{end}}">
<span class="fitted">调试</span>
</a>
<a class="ui basic {{if eq .Status "STOPPED"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();">
停止
</a>
</form>
</div> </div>
</div>
<div class="ui compact buttons" style="margin-right:10px;">
<!-- 模型下载 -->
<a class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank">
模型下载
</a>
<!-- 接收结果 -->
<iframe src="" frameborder="0" name="iframeContent" style="display: none;"></iframe>
<a class="imageBtn ui basic {{if not .CanDebug}}disabled {{else}}blue {{end}}button" value="{{.CanDebug}}">提交镜像</a>


<!-- 停止 -->
<div class="one wide column">
<div class="ui text center clipboard">
<form id="stopForm-{{.JobID}}" action="{{if eq .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/stop{{end}}" method="post">
{{$.CsrfTokenHtml}}
<a class="fitted" onclick="document.getElementById('stopForm-{{.JobID}}').submit();" style="{{if eq .Status "STOPPED"}}color:#CCCCCC{{end}}; font-size:16px; font-weight:bold">停止</a>
</form>
</div> </div>
</div>

<!-- 模型下载 -->
<div class="two wide column">
<span class="ui text clipboard">
<a class="title" href="{{$.Link}}/{{.JobID}}/models">
<span class="fitted">模型下载</span>
<!-- 删除镜像 -->
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{if ne .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post">
{{$.CsrfTokenHtml}}
<a class="ui compact {{if ne .Status "STOPPED"}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
删除
</a> </a>
</span>
</form>
</div> </div>

<!-- 接收结果 -->
<iframe src="" frameborder="0" name="iframeContent" style="display: none;"></iframe>
<a class="imageBtn" style="{{if not .CanDebug}}color:#CCCCCC;cursor:pointer;pointer-events:none;{{end}}; font-size:16px; font-weight:bold" value="{{.CanDebug}}">提交镜像</a>

<!-- 镜像列表弹窗 --> <!-- 镜像列表弹窗 -->
<div id="imageModal" class="modal" style="display: none;"> <div id="imageModal" class="modal" style="display: none;">
<div class="modal-content">
<span class="close">&times;</span>
<div class="modal-content">


<!-- 表格 --> <!-- 表格 -->
<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">&times;</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>




</div> </div>
</div> </div>
{{end}} {{template "base/paginate" .}} {{end}} {{template "base/paginate" .}}
@@ -431,7 +432,9 @@
} }


// 加载任务状态 // 加载任务状态
$(document).ready(function() {
var timeid = window.setInterval(loadJobStatus, 15000);
$(document).ready(loadJobStatus);
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 +445,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 +489,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')




+ 9
- 11
templates/repo/cloudbrain/new.tmpl View File

@@ -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,11 @@
$('#messageInfo p').text(str) $('#messageInfo p').text(str)
return false return false
} }
if(!value_image){
return false
}
// if(!value_image || !value_data){
// console.log("------------------------")
// 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"


+ 1
- 17
templates/repo/cloudbrain/show.tmpl View File

@@ -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>


+ 1
- 1
templates/repo/create.tmpl View File

@@ -1,5 +1,5 @@
{{template "base/head" .}} {{template "base/head" .}}
<div class="repository new repo">
<div class="repository new repo" style="margin-top: 40px;">
<div class="ui middle very relaxed page grid"> <div class="ui middle very relaxed page grid">
<div class="column"> <div class="column">
<form class="ui form" action="{{.Link}}" method="post"> <form class="ui form" action="{{.Link}}" method="post">


+ 23
- 14
templates/repo/datasets/dataset_list.tmpl View File

@@ -30,24 +30,33 @@
<a class="ui text center" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a> <a class="ui text center" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
</div> </div>
{{end}} {{end}}
{{if $.Permission.CanWrite $.UnitTypeDatasets}}
{{if $.Repository.IsPrivate}}
<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>
{{if not .CanDel}}
<div class="two wide column">
<a class="ui button mini" disabled='true'>{{if .IsPrivate}} {{$.i18n.Tr "dataset.private"}} {{else}} {{$.i18n.Tr "dataset.public"}} {{end}}</a>
</div>
{{else}}
{{if $.Permission.CanWrite $.UnitTypeDatasets}}
{{if $.Repository.IsPrivate}}
<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>
</div>
{{ else }}
<div class="two wide column">
<div class="ui buttons mini">
<a class="ui button mini {{if .IsPrivate}}positive active{{end}}" href="javascript:void(0)" data-dataset-status="true-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="true" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.private"}}</a>
<div class="or"></div>
<a class="ui button mini {{if not .IsPrivate}}positive active{{end}}" href="javascript:void(0)" data-dataset-status="false-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="false" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.public"}}</a>
</div>
</div>
{{end}}
<div class="two wide column right aligned">
<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>
{{ else }}
{{else}}
<div class="two wide column"> <div class="two wide column">
<div class="ui buttons mini">
<a class="ui button mini {{if .IsPrivate}}positive active{{end}}" href="javascript:void(0)" data-dataset-status="true-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="true" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.private"}}</a>
<div class="or"></div>
<a class="ui button mini {{if not .IsPrivate}}positive active{{end}}" href="javascript:void(0)" data-dataset-status="false-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="false" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.public"}}</a>
</div>
<a class="ui button mini" disabled='true'>{{if .IsPrivate}} {{$.i18n.Tr "dataset.private"}} {{else}} {{$.i18n.Tr "dataset.public"}} {{end}}</a>
</div> </div>
{{end}} {{end}}

<div class="two wide column right aligned">
<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>
{{end}} {{end}}
</div> </div>
</div> </div>


+ 2
- 1
templates/repo/header.tmpl View File

@@ -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" .}}




+ 1
- 1
templates/repo/migrate.tmpl View File

@@ -1,5 +1,5 @@
{{template "base/head" .}} {{template "base/head" .}}
<div class="repository new migrate">
<div class="repository new migrate" style="margin-top: 40px;">
<div class="ui middle very relaxed page grid"> <div class="ui middle very relaxed page grid">
<div class="column"> <div class="column">
<form class="ui form" action="{{.Link}}" method="post"> <form class="ui form" action="{{.Link}}" method="post">


+ 39
- 81
templates/repo/modelarts/index.tmpl View File

@@ -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>


@@ -247,99 +247,51 @@
{{range .Tasks}} {{range .Tasks}}
<div class="ui grid stackable item"> <div class="ui grid stackable item">
<div class="row"> <div class="row">
<!-- 任务名 --> <!-- 任务名 -->
<div class="four wide column">
<div class="six wide column">
<a class="title" href="{{$.Link}}/{{.JobID}}"> <a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">{{svg "octicon-tasklist" 16}}</span> <span class="fitted">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted">{{.JobName}}</span> <span class="fitted">{{.JobName}}</span>
</a> </a>
</div> </div>


<!--任务状态 -->
<div class="three wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}}
</div>

<!-- 任务创建时间 -->
<div class="three wide column"> <div class="three wide column">
<span class="ui text center">{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}</span>
</div>

<!-- 查看 -->
<div class="one wide column">
<span class="ui text clipboard">
<a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">查看</span>
</a>
<!--任务状态 -->
<span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}}
</span> </span>
<!-- 任务创建时间 -->
<span class="">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>
</div> </div>


<!-- 删除任务 -->
<div class="one wide column">
<div class="ui text center clipboard">
<form id="delForm-{{.JobID}}" action="{{if ne .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post">
<div class="seven wide column text right">
<div class="ui compact buttons" style="margin-right:10px;">
<a class="ui basic blue button" href="{{$.Link}}/{{.JobID}}">
查看
</a>
<a class="ui basic {{if not .CanDebug}}disabled {{else}}blue {{end}}button" href="{{$.Link}}/{{.JobID}}/debug">
调试
</a>
<form id="stopForm-{{.JobID}}" action="{{if ne .Status "RUNNING"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/stop{{end}}" method="post" style="margin-left:-1px;">
{{$.CsrfTokenHtml}} {{$.CsrfTokenHtml}}
<a class="fitted" onclick="assertDelete(this)" style="{{if ne .Status "STOPPED"}}color:#CCCCCC{{end}}; font-size:16px; font-weight:bold">删除</a>
<a class="ui basic {{if ne .Status "RUNNING"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();">
停止
</a>
</form> </form>
</div> </div>
</div>


<!-- 调试 -->
<div class="one wide column">
<div class="ui text center clipboard">
<a class="title" onclick="stop(this)" href="{{if not .CanDebug}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/debug{{end}}" style="{{if not .CanDebug}}color:#CCCCCC{{end}}">
<span class="fitted">调试</span>
</a>
</div>
<!-- 删除任务 -->
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{if ne .Status "STOPPED"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/del{{end}}" method="post">
{{$.CsrfTokenHtml}}
<a class="ui compact {{if ne .Status "STOPPED"}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;">
删除
</a>
</form>
</div> </div>


<!-- 停止 -->
<div class="one wide column">
<div class="ui text center clipboard">
<form id="stopForm-{{.JobID}}" action="{{if ne .Status "RUNNING"}}javascript:void(0){{else}}{{$.Link}}/{{.JobID}}/stop{{end}}" method="post">
{{$.CsrfTokenHtml}}
<a class="fitted" onclick="document.getElementById('stopForm-{{.JobID}}').submit();" style="{{if ne .Status "RUNNING"}}color:#CCCCCC{{end}}; font-size:16px; font-weight:bold">停止</a>
</form>
</div>
</div>

<!-- 镜像列表弹窗 -->
<div id="imageModal" class="modal" style="display: none;">
<div class="modal-content">
<span class="close">&times;</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>
<div style="position:absolute;left:75px;top:0;width:75%">
<textarea name="description" rows="10" style="width:100%"></textarea>
</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>
</div>


</div> </div>
</div> </div>
@@ -418,7 +370,9 @@
} }


// 加载任务状态 // 加载任务状态
$(document).ready(function() {
var timeid = window.setInterval(loadJobStatus, 15000);
$(document).ready(loadJobStatus);
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 +383,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');


+ 39
- 8
templates/repo/modelarts/new.tmpl View File

@@ -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"}}
@@ -117,7 +120,7 @@
<input type="text" list="cloudbrain_dataset" placeholder="选择数据集" name="" id="answerInput" autofocus maxlength="36"> <input type="text" list="cloudbrain_dataset" placeholder="选择数据集" name="" id="answerInput" autofocus maxlength="36">
<datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment"> <datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment">
{{range .attachments}} {{range .attachments}}
<option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option>
<option name="attachment" data-value="{{.UUID}}">{{.Attachment.Name}}</option>
{{end}} {{end}}
</datalist> </datalist>
<input type="hidden" name="attachment" id="answerInput-hidden"> <input type="hidden" name="attachment" id="answerInput-hidden">
@@ -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() {


+ 1
- 1
web_src/js/components/MinioUploader.vue View File

@@ -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();


+ 2
- 2
web_src/js/components/ObsUploader.vue View File

@@ -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();


+ 2
- 3
web_src/less/_dataset.less View File

@@ -143,10 +143,9 @@
} }
} }
.item { .item {
padding-top: 15px;
padding-bottom: 10px;
border-bottom: 1px dashed #aaaaaa;
border-bottom: 1px solid rgba(34,36,38,.15);
} }
.ui.grid > .row { .ui.grid > .row {
align-items: center; align-items: center;
} }


+ 4
- 2
web_src/less/_organization.less View File

@@ -79,9 +79,11 @@
&.profile { &.profile {
.members { .members {
.ui.avatar { .ui.avatar {
width: 48px;
height: 48px;
width: 44px;
height: 44px;
margin-right: 5px; margin-right: 5px;
margin-bottom: 5px;
border-radius: 22px;
} }
} }
} }


+ 2
- 0
web_src/less/_repository.less View File

@@ -2764,6 +2764,8 @@ tbody.commit-list {
.text { .text {
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
height: 36px;
line-height: 36px;
} }
} }




Loading…
Cancel
Save