@@ -41,6 +41,7 @@ | |||
## 授权许可 | |||
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://git.openi.org.cn/OpenI/aiforge/src/branch/develop/LICENSE) 文件中。 | |||
## 需要帮助? | |||
如果您在使用或者开发过程中遇到问题,可以在以下渠道咨询: | |||
- 点击[这里](https://git.openi.org.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**) | |||
@@ -49,3 +50,8 @@ | |||
## 启智社区小白训练营: | |||
- 结合案例给大家详细讲解如何使用社区平台,帮助无技术背景的小白成长为启智社区达人 (https://git.openi.org.cn/zeizei/OpenI_Learning) | |||
## 平台引用 | |||
如果本平台对您的科研工作提供了帮助,可在论文致谢中加入: | |||
英文版:```Thanks for the support provided by OpenI Community (https://git.openi.org.cn).``` | |||
中文版:```感谢启智社区提供的技术支持(https://git.openi.org.cn)。``` |
@@ -44,12 +44,6 @@ | |||
-webkit-line-clamp: 2; | |||
-webkit-box-orient: vertical; | |||
} | |||
.ui.label{ | |||
font-weight: normal; | |||
} | |||
.active { | |||
color: #0366D6 !important; | |||
} | |||
.opacity5{ opacity:0.5;} | |||
.radius15{ border-radius:1.5rem !important; } | |||
@@ -287,70 +281,6 @@ | |||
position: relative; | |||
} | |||
/**seach**/ | |||
/**搜索导航条适配窄屏**/ | |||
.seachnav{ | |||
overflow-x: auto; | |||
overflow-y: hidden; | |||
scrollbar-width: none; /* firefox */ | |||
-ms-overflow-style: none; /* IE 10+ */ | |||
} | |||
.seachnav::-webkit-scrollbar { | |||
display: none; /* Chrome Safari */ | |||
} | |||
.ui.green.button, .ui.green.buttons .button{ | |||
background-color: #5BB973; | |||
} | |||
.seach .repos--seach{ | |||
padding-bottom: 0; | |||
border-bottom: none; | |||
} | |||
.seach .ui.secondary.pointing.menu{ | |||
border-bottom: none; | |||
} | |||
.seach .ui.secondary.pointing.menu .item > i{ | |||
margin-right: 5px; | |||
} | |||
.seach .ui.secondary.pointing.menu .active.item{ | |||
border-bottom-width: 2px; | |||
margin: 0 0 -1px; | |||
} | |||
.seach .ui.menu .active.item>.label { | |||
background: #1684FC; | |||
color: #FFF; | |||
} | |||
.seach .ui.menu .item>.label:not(.active.item>.label) { | |||
background: #e8e8e8; | |||
color: rgba(0,0,0,.6); | |||
} | |||
.highlight{ | |||
color: red; | |||
} | |||
.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content { | |||
width: calc(100% - 3.0em); | |||
margin-left: 0; | |||
} | |||
.seach .ui.list .list>.item .header, .seach .ui.list>.item .header{ | |||
margin-bottom: 0.5em; | |||
font-size: 1.4rem !important; | |||
font-weight: normal; | |||
} | |||
.seach .time, .seach .time a{ | |||
font-size: 12px; | |||
color: grey; | |||
} | |||
.seach .list .item.members .ui.avatar.image { | |||
width: 3.2em; | |||
height: 3.2em; | |||
} | |||
.ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content { | |||
width: calc(100% - 4.0em); | |||
margin-left: 0; | |||
} | |||
@media only screen and (max-width: 767px) { | |||
.am-mt-30{ margin-top: 1.5rem !important;} | |||
.ui.secondary.hometop.segment{ | |||
@@ -57,6 +57,7 @@ const ( | |||
ActionCreateInferenceTask // 28 | |||
ActionCreateBenchMarkTask //29 | |||
ActionCreateNewModelTask //30 | |||
ActionCreateGPUTrainTask //31 | |||
) | |||
// Action represents user operation type and other information to | |||
@@ -9,6 +9,7 @@ import ( | |||
"fmt" | |||
"io" | |||
"path" | |||
"strings" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/obs" | |||
@@ -18,6 +19,7 @@ import ( | |||
"code.gitea.io/gitea/modules/timeutil" | |||
gouuid "github.com/satori/go.uuid" | |||
"xorm.io/builder" | |||
"xorm.io/xorm" | |||
) | |||
@@ -38,6 +40,7 @@ type Attachment struct { | |||
UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added | |||
CommentID int64 | |||
Name string | |||
Description string `xorm:"TEXT"` | |||
DownloadCount int64 `xorm:"DEFAULT 0"` | |||
Size int64 `xorm:"DEFAULT 0"` | |||
IsPrivate bool `xorm:"DEFAULT false"` | |||
@@ -47,6 +50,7 @@ type Attachment struct { | |||
FileChunk *FileChunk `xorm:"-"` | |||
CanDel bool `xorm:"-"` | |||
Uploader *User `xorm:"-"` | |||
} | |||
type AttachmentUsername struct { | |||
@@ -54,6 +58,27 @@ type AttachmentUsername struct { | |||
Name string | |||
} | |||
type AttachmentInfo struct { | |||
Attachment `xorm:"extends"` | |||
Repo *Repository `xorm:"extends"` | |||
RelAvatarLink string `xorm:"extends"` | |||
UserName string `xorm:"extends"` | |||
} | |||
type AttachmentsOptions struct { | |||
ListOptions | |||
DatasetIDs []int64 | |||
DecompressState int | |||
Type int | |||
UploaderID int64 | |||
NeedDatasetIDs bool | |||
NeedIsPrivate bool | |||
IsPrivate bool | |||
JustNeedZipFile bool | |||
NeedRepoInfo bool | |||
Keyword string | |||
} | |||
func (a *Attachment) AfterUpdate() { | |||
if a.DatasetID > 0 { | |||
datasetIsPublicCount, err := x.Where("dataset_id = ? AND is_private = ?", a.DatasetID, false).Count(new(Attachment)) | |||
@@ -326,6 +351,18 @@ func DeleteAttachmentsByComment(commentID int64, remove bool) (int, error) { | |||
func UpdateAttachment(atta *Attachment) error { | |||
return updateAttachment(x, atta) | |||
} | |||
func UpdateAttachmentDescription(atta *Attachment) error { | |||
return updateAttachmentDescription(x, atta) | |||
} | |||
func updateAttachmentDescription(e Engine, atta *Attachment) error { | |||
var sess *xorm.Session | |||
sess = e.ID(atta.ID) | |||
_, err := sess.Cols("description").Update(atta) | |||
return err | |||
} | |||
func updateAttachment(e Engine, atta *Attachment) error { | |||
var sess *xorm.Session | |||
@@ -503,3 +540,98 @@ func GetAttachmentSizeByDatasetID(datasetID int64) (int64, error) { | |||
func GetAllAttachmentSize() (int64, error) { | |||
return x.SumInt(&Attachment{}, "size") | |||
} | |||
func Attachments(opts *AttachmentsOptions) ([]*AttachmentInfo, int64, error) { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
var cond = builder.NewCond() | |||
if opts.NeedDatasetIDs { | |||
cond = cond.And( | |||
builder.In("attachment.dataset_id", opts.DatasetIDs), | |||
) | |||
} | |||
if opts.UploaderID > 0 { | |||
cond = cond.And( | |||
builder.Eq{"attachment.uploader_id": opts.UploaderID}, | |||
) | |||
} | |||
if (opts.Type) >= 0 { | |||
cond = cond.And( | |||
builder.Eq{"attachment.type": opts.Type}, | |||
) | |||
} | |||
if opts.NeedIsPrivate { | |||
cond = cond.And( | |||
builder.Eq{"attachment.is_private": opts.IsPrivate}, | |||
) | |||
} | |||
if opts.JustNeedZipFile { | |||
var DecompressState []int32 | |||
DecompressState = append(DecompressState, DecompressStateDone, DecompressStateIng, DecompressStateFailed) | |||
cond = cond.And( | |||
builder.In("attachment.decompress_state", DecompressState), | |||
) | |||
} | |||
var count int64 | |||
var err error | |||
if len(opts.Keyword) == 0 { | |||
count, err = sess.Where(cond).Count(new(Attachment)) | |||
} else { | |||
lowerKeyWord := strings.ToLower(opts.Keyword) | |||
cond = cond.And(builder.Or(builder.Like{"LOWER(attachment.name)", lowerKeyWord}, builder.Like{"LOWER(attachment.description)", lowerKeyWord})) | |||
count, err = sess.Table(&Attachment{}).Where(cond).Count(new(AttachmentInfo)) | |||
} | |||
if err != nil { | |||
return nil, 0, fmt.Errorf("Count: %v", err) | |||
} | |||
if opts.Page >= 0 && opts.PageSize > 0 { | |||
var start int | |||
if opts.Page == 0 { | |||
start = 0 | |||
} else { | |||
start = (opts.Page - 1) * opts.PageSize | |||
} | |||
sess.Limit(opts.PageSize, start) | |||
} | |||
sess.OrderBy("attachment.created_unix DESC") | |||
attachments := make([]*AttachmentInfo, 0, setting.UI.DatasetPagingNum) | |||
if err := sess.Table(&Attachment{}).Where(cond). | |||
Find(&attachments); err != nil { | |||
return nil, 0, fmt.Errorf("Find: %v", err) | |||
} | |||
if opts.NeedRepoInfo { | |||
for _, attachment := range attachments { | |||
dataset, err := GetDatasetByID(attachment.DatasetID) | |||
if err != nil { | |||
return nil, 0, fmt.Errorf("GetDatasetByID failed error: %v", err) | |||
} | |||
repo, err := GetRepositoryByID(dataset.RepoID) | |||
if err == nil { | |||
attachment.Repo = repo | |||
} else { | |||
return nil, 0, fmt.Errorf("GetRepositoryByID failed error: %v", err) | |||
} | |||
user, err := GetUserByID(attachment.UploaderID) | |||
if err == nil { | |||
attachment.RelAvatarLink = user.RelAvatarLink() | |||
attachment.UserName = user.Name | |||
} else { | |||
return nil, 0, fmt.Errorf("GetUserByID failed error: %v", err) | |||
} | |||
} | |||
} | |||
return attachments, count, nil | |||
} |
@@ -0,0 +1,16 @@ | |||
package models | |||
type BaseMessage struct { | |||
Code int | |||
Message string | |||
} | |||
var BaseOKMessage = BaseMessage{ | |||
0, "", | |||
} | |||
func BaseErrorMessage(message string) BaseMessage { | |||
return BaseMessage{ | |||
1, message, | |||
} | |||
} |
@@ -1,6 +1,7 @@ | |||
package models | |||
import ( | |||
"code.gitea.io/gitea/modules/util" | |||
"encoding/json" | |||
"fmt" | |||
"strconv" | |||
@@ -20,8 +21,16 @@ type JobType string | |||
type ModelArtsJobStatus string | |||
const ( | |||
TypeCloudBrainOne int = iota | |||
TypeCloudBrainTwo | |||
TypeCloudBrainAll = -1 | |||
) | |||
const ( | |||
NPUResource = "NPU" | |||
GPUResource = "CPU/GPU" | |||
AllResource = "all" | |||
//notebook storage category | |||
EVSCategory = "EVS" | |||
@@ -86,6 +95,8 @@ const ( | |||
ModelArtsTrainJobCheckRunning ModelArtsJobStatus = "CHECK_RUNNING" //审核作业正在运行中 | |||
ModelArtsTrainJobCheckRunningCompleted ModelArtsJobStatus = "CHECK_RUNNING_COMPLETED" //审核作业已经完成 | |||
ModelArtsTrainJobCheckFailed ModelArtsJobStatus = "CHECK_FAILED" //审核作业失败 | |||
DURATION_STR_ZERO = "00:00:00" | |||
) | |||
type Cloudbrain struct { | |||
@@ -102,15 +113,15 @@ type Cloudbrain struct { | |||
ContainerIp string | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||
Duration int64 | |||
TrainJobDuration string | |||
Image string //镜像名称 | |||
GpuQueue string //GPU类型即GPU队列 | |||
ResourceSpecId int //GPU规格id | |||
DeletedAt time.Time `xorm:"deleted"` | |||
CanDebug bool `xorm:"-"` | |||
CanDel bool `xorm:"-"` | |||
CanModify bool `xorm:"-"` | |||
Duration int64 `xorm:"DEFAULT 0"` //运行时长 单位秒 | |||
TrainJobDuration string `xorm:"DEFAULT '00:00:00'"` | |||
Image string //镜像名称 | |||
GpuQueue string //GPU类型即GPU队列 | |||
ResourceSpecId int //GPU规格id | |||
DeletedAt time.Time `xorm:"deleted"` | |||
CanDebug bool `xorm:"-"` | |||
CanDel bool `xorm:"-"` | |||
CanModify bool `xorm:"-"` | |||
Type int | |||
BenchmarkTypeID int | |||
BenchmarkChildTypeID int | |||
@@ -150,6 +161,64 @@ type Cloudbrain struct { | |||
Repo *Repository `xorm:"-"` | |||
BenchmarkTypeName string `xorm:"-"` | |||
BenchmarkTypeRankLink string `xorm:"-"` | |||
StartTime timeutil.TimeStamp | |||
EndTime timeutil.TimeStamp | |||
} | |||
func (task *Cloudbrain) ComputeAndSetDuration() { | |||
var d int64 | |||
if task.StartTime == 0 { | |||
d = 0 | |||
} else if task.EndTime == 0 { | |||
if !task.IsTerminal() { | |||
d = time.Now().Unix() - task.StartTime.AsTime().Unix() | |||
} | |||
} else { | |||
d = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() | |||
} | |||
if d < 0 { | |||
d = 0 | |||
} | |||
task.Duration = d | |||
task.TrainJobDuration = ConvertDurationToStr(d) | |||
} | |||
func (task *Cloudbrain) IsTerminal() bool { | |||
status := task.Status | |||
return status == string(ModelArtsTrainJobCompleted) || status == string(ModelArtsTrainJobFailed) || status == string(ModelArtsTrainJobKilled) || status == string(ModelArtsStopped) || status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded) | |||
} | |||
func ConvertDurationToStr(duration int64) string { | |||
if duration == 0 { | |||
return DURATION_STR_ZERO | |||
} | |||
return util.AddZero(duration/3600) + ":" + util.AddZero(duration%3600/60) + ":" + util.AddZero(duration%60) | |||
} | |||
func IsTrainJobTerminal(status string) bool { | |||
return status == string(ModelArtsTrainJobCompleted) || status == string(ModelArtsTrainJobFailed) || status == string(ModelArtsTrainJobKilled) | |||
} | |||
func IsModelArtsDebugJobTerminal(status string) bool { | |||
return status == string(ModelArtsStopped) | |||
} | |||
func IsCloudBrainOneDebugJobTerminal(status string) bool { | |||
return status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded) | |||
} | |||
func ParseAndSetDurationFromCloudBrainOne(result JobResultPayload, task *Cloudbrain) { | |||
isActivated := result.JobStatus.CreatedTime > 0 | |||
if task.StartTime == 0 && isActivated { | |||
task.StartTime = timeutil.TimeStamp(result.JobStatus.CreatedTime / 1000) | |||
} | |||
if task.EndTime == 0 && IsCloudBrainOneDebugJobTerminal(task.Status) && isActivated { | |||
if result.JobStatus.CompletedTime > 0 { | |||
task.EndTime = timeutil.TimeStamp(result.JobStatus.CompletedTime / 1000) | |||
} | |||
} | |||
task.ComputeAndSetDuration() | |||
} | |||
type CloudbrainInfo struct { | |||
@@ -319,7 +388,7 @@ type JobResultPayload struct { | |||
AppProgress string `json:"appProgress"` | |||
AppTrackingURL string `json:"appTrackingUrl"` | |||
AppLaunchedTime int64 `json:"appLaunchedTime"` | |||
AppCompletedTime interface{} `json:"appCompletedTime"` | |||
AppCompletedTime int64 `json:"appCompletedTime"` | |||
AppExitCode int `json:"appExitCode"` | |||
AppExitDiagnostics string `json:"appExitDiagnostics"` | |||
AppExitType interface{} `json:"appExitType"` | |||
@@ -1019,6 +1088,7 @@ type GetTrainJobResult struct { | |||
NasShareAddr string `json:"nas_share_addr"` | |||
DatasetName string | |||
ModelMetricList string `json:"model_metric_list"` //列表里包含f1_score,recall,precision,accuracy,若有的话 | |||
StartTime int64 `json:"start_time"` //训练作业开始时间。 | |||
} | |||
type GetTrainJobLogResult struct { | |||
@@ -1283,6 +1353,7 @@ func CloudbrainsVersionList(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int, e | |||
} | |||
func CreateCloudbrain(cloudbrain *Cloudbrain) (err error) { | |||
cloudbrain.TrainJobDuration = DURATION_STR_ZERO | |||
if _, err = x.Insert(cloudbrain); err != nil { | |||
return err | |||
} | |||
@@ -1327,13 +1398,13 @@ func GetCloudbrainByJobIDAndIsLatestVersion(jobID string, isLatestVersion string | |||
func GetCloudbrainsNeededStopByUserID(userID int64) ([]*Cloudbrain, error) { | |||
cloudBrains := make([]*Cloudbrain, 0) | |||
err := x.Cols("job_id", "status", "type", "job_type", "version_id").Where("user_id=? AND status !=?", userID, string(JobStopped)).Find(&cloudBrains) | |||
err := x.Cols("job_id", "status", "type", "job_type", "version_id", "start_time").Where("user_id=? AND status !=?", userID, string(JobStopped)).Find(&cloudBrains) | |||
return cloudBrains, err | |||
} | |||
func GetCloudbrainsNeededStopByRepoID(repoID int64) ([]*Cloudbrain, error) { | |||
cloudBrains := make([]*Cloudbrain, 0) | |||
err := x.Cols("job_id", "status", "type", "job_type", "version_id").Where("repo_id=? AND status !=?", repoID, string(JobStopped)).Find(&cloudBrains) | |||
err := x.Cols("job_id", "status", "type", "job_type", "version_id", "start_time").Where("repo_id=? AND status !=?", repoID, string(JobStopped)).Find(&cloudBrains) | |||
return cloudBrains, err | |||
} | |||
@@ -1377,7 +1448,7 @@ func UpdateTrainJobVersion(job *Cloudbrain) error { | |||
func updateJobTrainVersion(e Engine, job *Cloudbrain) error { | |||
var sess *xorm.Session | |||
sess = e.Where("job_id = ? AND version_name=?", job.JobID, job.VersionName) | |||
_, err := sess.Cols("status", "train_job_duration").Update(job) | |||
_, err := sess.Cols("status", "train_job_duration", "duration", "start_time", "end_time").Update(job) | |||
return err | |||
} | |||
@@ -1427,6 +1498,15 @@ func GetCloudBrainUnStoppedJob() ([]*Cloudbrain, error) { | |||
Find(&cloudbrains) | |||
} | |||
func GetStoppedJobWithNoDurationJob() ([]*Cloudbrain, error) { | |||
cloudbrains := make([]*Cloudbrain, 0) | |||
return cloudbrains, x. | |||
In("status", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded). | |||
Where("train_job_duration is null or train_job_duration = '' "). | |||
Limit(100). | |||
Find(&cloudbrains) | |||
} | |||
func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) { | |||
count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ? and type = ?", jobType, userID, TypeCloudBrainOne).Count(new(Cloudbrain)) | |||
return int(count), err | |||
@@ -1457,7 +1537,7 @@ func UpdateInferenceJob(job *Cloudbrain) error { | |||
func updateInferenceJob(e Engine, job *Cloudbrain) error { | |||
var sess *xorm.Session | |||
sess = e.Where("job_id = ?", job.JobID) | |||
_, err := sess.Cols("status", "train_job_duration").Update(job) | |||
_, err := sess.Cols("status", "train_job_duration", "duration", "start_time", "end_time").Update(job) | |||
return err | |||
} | |||
func RestartCloudbrain(old *Cloudbrain, new *Cloudbrain) (err error) { | |||
@@ -22,6 +22,7 @@ type Dataset struct { | |||
Category string | |||
Description string `xorm:"TEXT"` | |||
DownloadTimes int64 | |||
NumStars int `xorm:"INDEX NOT NULL DEFAULT 0"` | |||
License string | |||
Task string | |||
ReleaseID int64 `xorm:"INDEX"` | |||
@@ -35,6 +36,11 @@ type Dataset struct { | |||
Attachments []*Attachment `xorm:"-"` | |||
} | |||
type DatasetWithStar struct { | |||
Dataset | |||
IsStaring bool | |||
} | |||
func (d *Dataset) IsPrivate() bool { | |||
switch d.Status { | |||
case DatasetStatusPrivate: | |||
@@ -91,33 +97,37 @@ type SearchDatasetOptions struct { | |||
OwnerID int64 | |||
RepoID int64 | |||
IncludePublic bool | |||
Category string | |||
Task string | |||
License string | |||
ListOptions | |||
SearchOrderBy | |||
IsOwner bool | |||
} | |||
func CreateDataset(dataset *Dataset) (err error) { | |||
if _, err = x.Insert(dataset); err != nil { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
if err := sess.Begin(); err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func CreateDefaultDatasetToRepo(repo *Repository) (err error) { | |||
dataset := &Dataset{RepoID: repo.ID} | |||
has, err := x.Get(dataset) | |||
datasetByRepoId := &Dataset{RepoID: dataset.RepoID} | |||
has, err := sess.Get(datasetByRepoId) | |||
if err != nil { | |||
return err | |||
} | |||
if !has { | |||
dataset.Status = DatasetStatusPrivate | |||
dataset.Title = repo.Name | |||
if err = CreateDataset(dataset); err != nil { | |||
return err | |||
} | |||
if has { | |||
return fmt.Errorf("The dataset already exists.") | |||
} | |||
return nil | |||
if _, err = sess.Insert(dataset); err != nil { | |||
return err | |||
} | |||
return sess.Commit() | |||
} | |||
func SearchDataset(opts *SearchDatasetOptions) (DatasetList, int64, error) { | |||
@@ -130,7 +140,18 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||
cond = cond.And(builder.Neq{"dataset.status": DatasetStatusDeleted}) | |||
if len(opts.Keyword) > 0 { | |||
cond = cond.And(builder.Like{"dataset.title", opts.Keyword}) | |||
cond = cond.And(builder.Or(builder.Like{"dataset.title", opts.Keyword}, builder.Like{"dataset.description", opts.Keyword})) | |||
} | |||
if len(opts.Category) > 0 { | |||
cond = cond.And(builder.Eq{"dataset.category": opts.Category}) | |||
} | |||
if len(opts.Task) > 0 { | |||
cond = cond.And(builder.Eq{"dataset.task": opts.Task}) | |||
} | |||
if len(opts.License) > 0 { | |||
cond = cond.And(builder.Eq{"dataset.license": opts.License}) | |||
} | |||
if opts.RepoID > 0 { | |||
@@ -139,12 +160,13 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||
if opts.IncludePublic { | |||
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic}) | |||
cond = cond.And(builder.Eq{"attachment.is_private": false}) | |||
if opts.OwnerID > 0 { | |||
if len(opts.Keyword) == 0 { | |||
cond = cond.Or(builder.Eq{"repository.owner_id": opts.OwnerID}) | |||
} else { | |||
subCon := builder.NewCond() | |||
subCon = subCon.And(builder.Eq{"repository.owner_id": opts.OwnerID}, builder.Like{"dataset.title", opts.Keyword}) | |||
subCon = subCon.And(builder.Eq{"repository.owner_id": opts.OwnerID}, builder.Or(builder.Like{"dataset.title", opts.Keyword}, builder.Like{"dataset.description", opts.Keyword})) | |||
cond = cond.Or(subCon) | |||
} | |||
@@ -153,6 +175,7 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||
cond = cond.And(builder.Eq{"repository.owner_id": opts.OwnerID}) | |||
if !opts.IsOwner { | |||
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic}) | |||
cond = cond.And(builder.Eq{"attachment.is_private": false}) | |||
} | |||
} | |||
@@ -169,14 +192,20 @@ func SearchDatasetByCondition(opts *SearchDatasetOptions, cond builder.Cond) (Da | |||
defer sess.Close() | |||
datasets := make(DatasetList, 0, opts.PageSize) | |||
selectColumnsSql := "distinct dataset.id,dataset.title, dataset.status, dataset.category, dataset.description, dataset.download_times, dataset.license, dataset.task, dataset.release_id, dataset.user_id, dataset.repo_id, dataset.created_unix,dataset.updated_unix,dataset.num_stars" | |||
count, err := sess.Join("INNER", "repository", "repository.id = dataset.repo_id").Where(cond).Count(new(Dataset)) | |||
count, err := sess.Distinct("dataset.id").Join("INNER", "repository", "repository.id = dataset.repo_id"). | |||
Join("INNER", "attachment", "attachment.dataset_id=dataset.id"). | |||
Where(cond).Count(new(Dataset)) | |||
if err != nil { | |||
return nil, 0, fmt.Errorf("Count: %v", err) | |||
} | |||
sess.Select("dataset.*").Join("INNER", "repository", "repository.id = dataset.repo_id").Where(cond).OrderBy(opts.SearchOrderBy.String()) | |||
sess.Select(selectColumnsSql).Join("INNER", "repository", "repository.id = dataset.repo_id"). | |||
Join("INNER", "attachment", "attachment.dataset_id=dataset.id"). | |||
Where(cond).OrderBy(opts.SearchOrderBy.String()) | |||
if opts.PageSize > 0 { | |||
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) | |||
} | |||
@@ -231,13 +260,23 @@ func getDatasetAttachments(e Engine, typeCloudBrain int, isSigned bool, user *Us | |||
sort.Sort(sortedRels) | |||
// Select attachments | |||
err = e. | |||
Asc("dataset_id"). | |||
In("dataset_id", sortedRels.ID). | |||
And("type = ?", typeCloudBrain). | |||
Find(&attachments, Attachment{}) | |||
if err != nil { | |||
return err | |||
if typeCloudBrain == -1 { | |||
err = e. | |||
Asc("dataset_id"). | |||
In("dataset_id", sortedRels.ID). | |||
Find(&attachments, Attachment{}) | |||
if err != nil { | |||
return err | |||
} | |||
} else { | |||
err = e. | |||
Asc("dataset_id"). | |||
In("dataset_id", sortedRels.ID). | |||
And("type = ?", typeCloudBrain). | |||
Find(&attachments, Attachment{}) | |||
if err != nil { | |||
return err | |||
} | |||
} | |||
// merge join | |||
@@ -301,9 +340,6 @@ func GetDatasetByID(id int64) (*Dataset, error) { | |||
} | |||
func GetDatasetByRepo(repo *Repository) (*Dataset, error) { | |||
if err := CreateDefaultDatasetToRepo(repo); err != nil { | |||
return nil, err | |||
} | |||
dataset := &Dataset{RepoID: repo.ID} | |||
has, err := x.Get(dataset) | |||
if err != nil { | |||
@@ -312,10 +348,16 @@ func GetDatasetByRepo(repo *Repository) (*Dataset, error) { | |||
if has { | |||
return dataset, nil | |||
} else { | |||
return nil, errors.New("Not Found") | |||
return nil, ErrNotExist{repo.ID} | |||
} | |||
} | |||
func GetDatasetStarByUser(user *User) ([]*DatasetStar, error) { | |||
datasetStars := make([]*DatasetStar, 0) | |||
err := x.Cols("id", "uid", "dataset_id", "created_unix").Where("uid=?", user.ID).Find(&datasetStars) | |||
return datasetStars, err | |||
} | |||
func DeleteDataset(datasetID int64, uid int64) error { | |||
var err error | |||
sess := x.NewSession() | |||
@@ -0,0 +1,70 @@ | |||
package models | |||
import "code.gitea.io/gitea/modules/timeutil" | |||
type DatasetStar struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
UID int64 `xorm:"UNIQUE(s)"` | |||
DatasetID int64 `xorm:"UNIQUE(s)"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
} | |||
// StarRepo or unstar repository. | |||
func StarDataset(userID, datasetID int64, star bool) error { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
if err := sess.Begin(); err != nil { | |||
return err | |||
} | |||
if star { | |||
if isDatasetStaring(sess, userID, datasetID) { | |||
return nil | |||
} | |||
if _, err := sess.Insert(&DatasetStar{UID: userID, DatasetID: datasetID}); err != nil { | |||
return err | |||
} | |||
if _, err := sess.Exec("UPDATE `dataset` SET num_stars = num_stars + 1 WHERE id = ?", datasetID); err != nil { | |||
return err | |||
} | |||
if _, err := sess.Exec("UPDATE `user` SET num_dataset_stars = num_dataset_stars + 1 WHERE id = ?", userID); err != nil { | |||
return err | |||
} | |||
} else { | |||
if !isDatasetStaring(sess, userID, datasetID) { | |||
return nil | |||
} | |||
if _, err := sess.Delete(&DatasetStar{0, userID, datasetID, 0}); err != nil { | |||
return err | |||
} | |||
if _, err := sess.Exec("UPDATE `dataset` SET num_stars = num_stars - 1 WHERE id = ?", datasetID); err != nil { | |||
return err | |||
} | |||
if _, err := sess.Exec("UPDATE `user` SET num_dataset_stars = num_dataset_stars - 1 WHERE id = ?", userID); err != nil { | |||
return err | |||
} | |||
} | |||
return sess.Commit() | |||
} | |||
func IsDatasetStaringByRepoId(userID, repoID int64) bool { | |||
dataset, _ := GetDatasetByRepo(&Repository{ID: repoID}) | |||
if dataset == nil { | |||
return false | |||
} | |||
return isDatasetStaring(x, userID, dataset.ID) | |||
} | |||
func IsDatasetStaring(userID, datasetID int64) bool { | |||
return isDatasetStaring(x, userID, datasetID) | |||
} | |||
func isDatasetStaring(e Engine, userID, datasetID int64) bool { | |||
has, _ := e.Get(&DatasetStar{0, userID, datasetID, 0}) | |||
return has | |||
} |
@@ -0,0 +1,186 @@ | |||
DROP FOREIGN TABLE public.dataset_es; | |||
CREATE FOREIGN TABLE public.dataset_es | |||
( | |||
id bigint NOT NULL, | |||
title character varying(255), | |||
status integer, | |||
category character varying(255), | |||
description text, | |||
download_times bigint, | |||
license character varying(255), | |||
task character varying(255), | |||
release_id bigint, | |||
user_id bigint, | |||
repo_id bigint, | |||
created_unix bigint, | |||
updated_unix bigint, | |||
file_name text, | |||
file_desc text | |||
)SERVER multicorn_es | |||
OPTIONS | |||
( | |||
host '192.168.207.94', | |||
port '9200', | |||
index 'dataset-es-index', | |||
rowid_column 'id', | |||
default_sort '_id' | |||
) | |||
; | |||
DELETE FROM public.dataset_es; | |||
INSERT INTO public.dataset_es( | |||
id, | |||
title, | |||
status, | |||
category, | |||
description, | |||
download_times, | |||
license, task, | |||
release_id, | |||
user_id, | |||
repo_id, | |||
created_unix, | |||
updated_unix, | |||
file_name, | |||
file_desc | |||
) | |||
SELECT | |||
b.id, | |||
b.title, | |||
b.status, | |||
b.category, | |||
b.description, | |||
b.download_times, | |||
b.license, | |||
b.task, | |||
b.release_id, | |||
b.user_id, | |||
b.repo_id, | |||
b.created_unix, | |||
b.updated_unix, | |||
(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false), | |||
(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false) | |||
FROM public.dataset b,public.repository c where b.repo_id=c.id and c.is_private=false; | |||
DROP TRIGGER IF EXISTS es_insert_dataset on public.dataset; | |||
CREATE OR REPLACE FUNCTION public.insert_dataset_data() RETURNS trigger AS | |||
$def$ | |||
DECLARE | |||
privateValue boolean=false; | |||
BEGIN | |||
select into privateValue is_private from public.repository where id=NEW.repo_id; | |||
if not privateValue then | |||
INSERT INTO public.dataset_es( | |||
id, | |||
title, | |||
status, | |||
category, | |||
description, | |||
download_times, | |||
license, | |||
task, | |||
release_id, | |||
user_id, | |||
repo_id, | |||
created_unix, | |||
updated_unix) | |||
VALUES ( | |||
NEW.id, | |||
NEW.title, | |||
NEW.status, | |||
NEW.category, | |||
NEW.description, | |||
NEW.download_times, | |||
NEW.license, | |||
NEW.task, | |||
NEW.release_id, | |||
NEW.user_id, | |||
NEW.repo_id, | |||
NEW.created_unix, | |||
NEW.updated_unix | |||
); | |||
end if; | |||
RETURN NEW; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_insert_dataset | |||
AFTER INSERT ON public.dataset | |||
FOR EACH ROW EXECUTE PROCEDURE insert_dataset_data(); | |||
ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_insert_dataset; | |||
DROP TRIGGER IF EXISTS es_udpate_dataset_file_name on public.attachment; | |||
CREATE OR REPLACE FUNCTION public.udpate_dataset_file_name() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
if (TG_OP = 'UPDATE') then | |||
update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id; | |||
elsif (TG_OP = 'INSERT') then | |||
update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id; | |||
elsif (TG_OP = 'DELETE') then | |||
update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id; | |||
update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id; | |||
end if; | |||
return NEW; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_udpate_dataset_file_name | |||
AFTER INSERT OR UPDATE OR DELETE ON public.attachment | |||
FOR EACH ROW EXECUTE PROCEDURE udpate_dataset_file_name(); | |||
ALTER TABLE public.attachment ENABLE ALWAYS TRIGGER es_udpate_dataset_file_name; | |||
DROP TRIGGER IF EXISTS es_update_dataset on public.dataset; | |||
CREATE OR REPLACE FUNCTION public.update_dataset() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
UPDATE public.dataset_es | |||
SET description=NEW.description, | |||
title=NEW.title, | |||
category=NEW.category, | |||
task=NEW.task, | |||
download_times=NEW.download_times, | |||
updated_unix=NEW.updated_unix, | |||
file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false), | |||
file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false) | |||
where id=NEW.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_update_dataset | |||
AFTER UPDATE ON public.dataset | |||
FOR EACH ROW EXECUTE PROCEDURE update_dataset(); | |||
ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_update_dataset; | |||
DROP TRIGGER IF EXISTS es_delete_dataset on public.dataset; | |||
CREATE OR REPLACE FUNCTION public.delete_dataset() RETURNS trigger AS | |||
$def$ | |||
declare | |||
BEGIN | |||
DELETE FROM public.dataset_es where id=OLD.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_delete_dataset | |||
AFTER DELETE ON public.dataset | |||
FOR EACH ROW EXECUTE PROCEDURE delete_dataset(); | |||
ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_delete_dataset; |
@@ -0,0 +1,215 @@ | |||
DROP FOREIGN TABLE public.issue_es; | |||
CREATE FOREIGN TABLE public.issue_es | |||
( | |||
id bigint NOT NULL, | |||
repo_id bigint, | |||
index bigint, | |||
poster_id bigint, | |||
original_author character varying(255), | |||
original_author_id bigint, | |||
name character varying(255) , | |||
content text, | |||
comment text, | |||
milestone_id bigint, | |||
priority integer, | |||
is_closed boolean, | |||
is_pull boolean, | |||
pr_id bigint, | |||
num_comments integer, | |||
ref character varying(255), | |||
deadline_unix bigint, | |||
created_unix bigint, | |||
updated_unix bigint, | |||
closed_unix bigint, | |||
is_locked boolean NOT NULL, | |||
amount bigint, | |||
is_transformed boolean NOT NULL | |||
)SERVER multicorn_es | |||
OPTIONS | |||
( | |||
host '192.168.207.94', | |||
port '9200', | |||
index 'issue-es-index', | |||
rowid_column 'id', | |||
default_sort '_id' | |||
) | |||
; | |||
delete from public.issue_es; | |||
INSERT INTO public.issue_es( | |||
id, | |||
repo_id, | |||
index, | |||
poster_id, | |||
original_author, | |||
original_author_id, | |||
name, | |||
content, | |||
milestone_id, | |||
priority, | |||
is_closed, | |||
is_pull, | |||
num_comments, | |||
ref, | |||
deadline_unix, | |||
created_unix, | |||
updated_unix, | |||
closed_unix, | |||
is_locked, | |||
amount, | |||
is_transformed,comment,pr_id) | |||
SELECT | |||
b.id, | |||
b.repo_id, | |||
b.index, | |||
b.poster_id, | |||
b.original_author, | |||
b.original_author_id, | |||
b.name, | |||
b.content, | |||
b.milestone_id, | |||
b.priority, | |||
b.is_closed, | |||
b.is_pull, | |||
b.num_comments, | |||
b.ref, | |||
b.deadline_unix, | |||
b.created_unix, | |||
b.updated_unix, | |||
b.closed_unix, | |||
b.is_locked, | |||
b.amount, | |||
b.is_transformed, | |||
(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id), | |||
(select id from public.pull_request d where b.id=d.issue_id and b.is_pull=true) | |||
FROM public.issue b,public.repository c where b.repo_id=c.id and c.is_private=false; | |||
CREATE OR REPLACE FUNCTION public.insert_issue_data() RETURNS trigger AS | |||
$def$ | |||
DECLARE | |||
privateValue boolean=false; | |||
BEGIN | |||
select into privateValue is_private from public.repository where id=NEW.repo_id; | |||
if not privateValue then | |||
INSERT INTO public.issue_es( | |||
id, | |||
repo_id, | |||
index, | |||
poster_id, | |||
original_author, | |||
original_author_id, | |||
name, | |||
content, | |||
milestone_id, | |||
priority, | |||
is_closed, | |||
is_pull, | |||
num_comments, | |||
ref, | |||
deadline_unix, | |||
created_unix, | |||
updated_unix, | |||
closed_unix, | |||
is_locked, | |||
amount, | |||
is_transformed) | |||
VALUES ( | |||
NEW.id, | |||
NEW.repo_id, | |||
NEW.index, | |||
NEW.poster_id, | |||
NEW.original_author, | |||
NEW.original_author_id, | |||
NEW.name, | |||
NEW.content, | |||
NEW.milestone_id, | |||
NEW.priority, | |||
NEW.is_closed, | |||
NEW.is_pull, | |||
NEW.num_comments, | |||
NEW.ref, | |||
NEW.deadline_unix, | |||
NEW.created_unix, | |||
NEW.updated_unix, | |||
NEW.closed_unix, | |||
NEW.is_locked, | |||
NEW.amount, | |||
NEW.is_transformed | |||
); | |||
end if; | |||
RETURN NEW; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
DROP TRIGGER IF EXISTS es_insert_issue on public.issue; | |||
CREATE TRIGGER es_insert_issue | |||
AFTER INSERT ON public.issue | |||
FOR EACH ROW EXECUTE PROCEDURE insert_issue_data(); | |||
ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_insert_issue; | |||
CREATE OR REPLACE FUNCTION public.udpate_issue_comment() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
if (TG_OP = 'DELETE') then | |||
update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=OLD.issue_id) where id=OLD.issue_id; | |||
elsif (TG_OP = 'UPDATE') then | |||
update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.issue_id) where id=NEW.issue_id; | |||
end if; | |||
return null; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
DROP TRIGGER IF EXISTS es_udpate_issue_comment on public.comment; | |||
CREATE TRIGGER es_udpate_issue_comment | |||
AFTER DELETE OR UPDATE ON public.comment | |||
FOR EACH ROW EXECUTE PROCEDURE udpate_issue_comment(); | |||
ALTER TABLE public.comment ENABLE ALWAYS TRIGGER es_udpate_issue_comment; | |||
CREATE OR REPLACE FUNCTION public.update_issue() RETURNS trigger AS | |||
$def$ | |||
declare | |||
BEGIN | |||
UPDATE public.issue_es | |||
SET content=NEW.content, | |||
name=NEW.name, | |||
is_closed=NEW.is_closed, | |||
num_comments=NEW.num_comments, | |||
comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.id) | |||
where id=NEW.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
DROP TRIGGER IF EXISTS es_update_issue on public.issue; | |||
CREATE TRIGGER es_update_issue | |||
AFTER UPDATE ON public.issue | |||
FOR EACH ROW EXECUTE PROCEDURE update_issue(); | |||
ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_update_issue; | |||
CREATE OR REPLACE FUNCTION public.delete_issue() RETURNS trigger AS | |||
$def$ | |||
declare | |||
BEGIN | |||
DELETE FROM public.issue_es where id=OLD.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
DROP TRIGGER IF EXISTS es_delete_issue on public.issue; | |||
CREATE TRIGGER es_delete_issue | |||
AFTER DELETE ON public.issue | |||
FOR EACH ROW EXECUTE PROCEDURE delete_issue(); | |||
ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_delete_issue; |
@@ -0,0 +1,532 @@ | |||
-- 要处理项目从私有变为公有,并且从公有变成私有的情况 | |||
DROP FOREIGN table if exists public.repository_es; | |||
CREATE FOREIGN TABLE public.repository_es ( | |||
id bigint NOT NULL, | |||
owner_id bigint, | |||
owner_name character varying(255), | |||
lower_name character varying(255) NOT NULL, | |||
name character varying(255) NOT NULL, | |||
description text, | |||
website character varying(2048), | |||
original_service_type integer, | |||
original_url character varying(2048), | |||
default_branch character varying(255), | |||
num_watches integer, | |||
num_stars integer, | |||
num_forks integer, | |||
num_issues integer, | |||
num_closed_issues integer, | |||
num_pulls integer, | |||
num_closed_pulls integer, | |||
num_milestones integer DEFAULT 0 NOT NULL, | |||
num_closed_milestones integer DEFAULT 0 NOT NULL, | |||
is_private boolean, | |||
is_empty boolean, | |||
is_archived boolean, | |||
is_mirror boolean, | |||
status integer DEFAULT 0 NOT NULL, | |||
is_fork boolean DEFAULT false NOT NULL, | |||
fork_id bigint, | |||
is_template boolean DEFAULT false NOT NULL, | |||
template_id bigint, | |||
size bigint DEFAULT 0 NOT NULL, | |||
is_fsck_enabled boolean DEFAULT true NOT NULL, | |||
close_issues_via_commit_in_any_branch boolean DEFAULT false NOT NULL, | |||
topics text, | |||
avatar character varying(64), | |||
created_unix bigint, | |||
updated_unix bigint, | |||
contract_address character varying(255), | |||
block_chain_status integer DEFAULT 0 NOT NULL, | |||
balance character varying(255) DEFAULT '0'::character varying NOT NULL, | |||
clone_cnt bigint DEFAULT 0 NOT NULL, | |||
license character varying(100), | |||
download_cnt bigint DEFAULT 0 NOT NULL, | |||
num_commit bigint DEFAULT 0 NOT NULL, | |||
git_clone_cnt bigint DEFAULT 0 NOT NULL, | |||
creator_id bigint NOT NULL DEFAULT 0, | |||
repo_type integer NOT NULL DEFAULT 0, | |||
lang character varying(2048), | |||
alias character varying(255), | |||
lower_alias character varying(255) | |||
) SERVER multicorn_es | |||
OPTIONS | |||
( | |||
host '192.168.207.94', | |||
port '9200', | |||
index 'repository-es-index', | |||
rowid_column 'id', | |||
default_sort '_id' | |||
) | |||
; | |||
delete from public.repository_es; | |||
INSERT INTO public.repository_es (id, | |||
owner_id, | |||
owner_name, | |||
lower_name, | |||
name, | |||
description, | |||
website, | |||
original_service_type, | |||
original_url, | |||
default_branch, | |||
num_watches, | |||
num_stars, | |||
num_forks, | |||
num_issues, | |||
num_closed_issues, | |||
num_pulls, | |||
num_closed_pulls, | |||
num_milestones, | |||
num_closed_milestones, | |||
is_private, | |||
is_empty, | |||
is_archived, | |||
is_mirror, | |||
status, | |||
is_fork, | |||
fork_id, | |||
is_template, | |||
template_id, | |||
size, | |||
is_fsck_enabled, | |||
close_issues_via_commit_in_any_branch, | |||
topics, | |||
avatar, | |||
created_unix, | |||
updated_unix, | |||
contract_address, | |||
block_chain_status, | |||
balance, | |||
clone_cnt, | |||
num_commit, | |||
git_clone_cnt, | |||
creator_id, | |||
repo_type, | |||
lang, | |||
alias, | |||
lower_alias | |||
) | |||
SELECT | |||
id, | |||
owner_id, | |||
owner_name, | |||
lower_name, | |||
name, | |||
description, | |||
website, | |||
original_service_type, | |||
original_url, | |||
default_branch, | |||
num_watches, | |||
num_stars, | |||
num_forks, | |||
num_issues, | |||
num_closed_issues, | |||
num_pulls, | |||
num_closed_pulls, | |||
num_milestones, | |||
num_closed_milestones, | |||
is_private, | |||
is_empty, | |||
is_archived, | |||
is_mirror, | |||
status, | |||
is_fork, | |||
fork_id, | |||
is_template, | |||
template_id, | |||
size, | |||
is_fsck_enabled, | |||
close_issues_via_commit_in_any_branch, | |||
topics, | |||
avatar, | |||
created_unix, | |||
updated_unix, | |||
contract_address, | |||
block_chain_status, | |||
balance, | |||
clone_cnt, | |||
num_commit, | |||
git_clone_cnt, | |||
creator_id, | |||
repo_type, | |||
(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id), | |||
alias, | |||
lower_alias | |||
FROM public.repository b where b.is_private=false; | |||
DROP TRIGGER IF EXISTS es_insert_repository on public.repository; | |||
CREATE OR REPLACE FUNCTION public.insert_repository_data() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
if not NEW.is_private then | |||
INSERT INTO public.repository_es (id, | |||
owner_id, | |||
owner_name, | |||
lower_name, | |||
name, | |||
description, | |||
website, | |||
original_service_type, | |||
original_url, | |||
default_branch, | |||
num_watches, | |||
num_stars, | |||
num_forks, | |||
num_issues, | |||
num_closed_issues, | |||
num_pulls, | |||
num_closed_pulls, | |||
num_milestones, | |||
num_closed_milestones, | |||
is_private, | |||
is_empty, | |||
is_archived, | |||
is_mirror, | |||
status, | |||
is_fork, | |||
fork_id, | |||
is_template, | |||
template_id, | |||
size, | |||
is_fsck_enabled, | |||
close_issues_via_commit_in_any_branch, | |||
topics, | |||
avatar, | |||
created_unix, | |||
updated_unix, | |||
contract_address, | |||
block_chain_status, | |||
balance, | |||
clone_cnt, | |||
num_commit, | |||
git_clone_cnt, | |||
creator_id, | |||
repo_type, | |||
alias, | |||
lower_alias) VALUES | |||
(NEW.id, | |||
NEW.owner_id, | |||
NEW.owner_name, | |||
NEW.lower_name, | |||
NEW.name, | |||
NEW.description, | |||
NEW.website, | |||
NEW.original_service_type, | |||
NEW.original_url, | |||
NEW.default_branch, | |||
NEW.num_watches, | |||
NEW.num_stars, | |||
NEW.num_forks, | |||
NEW.num_issues, | |||
NEW.num_closed_issues, | |||
NEW.num_pulls, | |||
NEW.num_closed_pulls, | |||
NEW.num_milestones, | |||
NEW.num_closed_milestones, | |||
NEW.is_private, | |||
NEW.is_empty, | |||
NEW.is_archived, | |||
NEW.is_mirror, | |||
NEW.status, | |||
NEW.is_fork, | |||
NEW.fork_id, | |||
NEW.is_template, | |||
NEW.template_id, | |||
NEW.size, | |||
NEW.is_fsck_enabled, | |||
NEW.close_issues_via_commit_in_any_branch, | |||
NEW.topics, | |||
NEW.avatar, | |||
NEW.created_unix, | |||
NEW.updated_unix, | |||
NEW.contract_address, | |||
NEW.block_chain_status, | |||
NEW.balance, | |||
NEW.clone_cnt, | |||
NEW.num_commit, | |||
NEW.git_clone_cnt, | |||
NEW.creator_id, | |||
NEW.repo_type, | |||
NEW.alias, | |||
NEW.lower_alias); | |||
end if; | |||
RETURN NEW; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_insert_repository | |||
AFTER INSERT ON public.repository | |||
FOR EACH ROW EXECUTE PROCEDURE insert_repository_data(); | |||
ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_insert_repository; | |||
DROP TRIGGER IF EXISTS es_update_repository on public.repository; | |||
CREATE OR REPLACE FUNCTION public.update_repository() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
if OLD.is_private != NEW.is_private then | |||
if OLD.is_private and not NEW.is_private then | |||
--insert | |||
INSERT INTO public.repository_es (id, | |||
owner_id, | |||
owner_name, | |||
lower_name, | |||
name, | |||
description, | |||
website, | |||
original_service_type, | |||
original_url, | |||
default_branch, | |||
num_watches, | |||
num_stars, | |||
num_forks, | |||
num_issues, | |||
num_closed_issues, | |||
num_pulls, | |||
num_closed_pulls, | |||
num_milestones, | |||
num_closed_milestones, | |||
is_private, | |||
is_empty, | |||
is_archived, | |||
is_mirror, | |||
status, | |||
is_fork, | |||
fork_id, | |||
is_template, | |||
template_id, | |||
size, | |||
is_fsck_enabled, | |||
close_issues_via_commit_in_any_branch, | |||
topics, | |||
avatar, | |||
created_unix, | |||
updated_unix, | |||
contract_address, | |||
block_chain_status, | |||
balance, | |||
clone_cnt, | |||
num_commit, | |||
git_clone_cnt, | |||
creator_id, | |||
repo_type, | |||
lang, | |||
alias, | |||
lower_alias) | |||
SELECT | |||
id, | |||
owner_id, | |||
owner_name, | |||
lower_name, | |||
name, | |||
description, | |||
website, | |||
original_service_type, | |||
original_url, | |||
default_branch, | |||
num_watches, | |||
num_stars, | |||
num_forks, | |||
num_issues, | |||
num_closed_issues, | |||
num_pulls, | |||
num_closed_pulls, | |||
num_milestones, | |||
num_closed_milestones, | |||
is_private, | |||
is_empty, | |||
is_archived, | |||
is_mirror, | |||
status, | |||
is_fork, | |||
fork_id, | |||
is_template, | |||
template_id, | |||
size, | |||
is_fsck_enabled, | |||
close_issues_via_commit_in_any_branch, | |||
topics, | |||
avatar, | |||
created_unix, | |||
updated_unix, | |||
contract_address, | |||
block_chain_status, | |||
balance, | |||
clone_cnt, | |||
num_commit, | |||
git_clone_cnt, | |||
creator_id, | |||
repo_type, | |||
(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id), | |||
alias, | |||
lower_alias | |||
FROM public.repository b where b.id=NEW.id; | |||
INSERT INTO public.dataset_es( | |||
id, | |||
title, | |||
status, | |||
category, | |||
description, | |||
download_times, | |||
license, task, | |||
release_id, | |||
user_id, | |||
repo_id, | |||
created_unix, | |||
updated_unix,file_name) | |||
SELECT | |||
b.id, | |||
b.title, | |||
b.status, | |||
b.category, | |||
b.description, | |||
b.download_times, | |||
b.license, | |||
b.task, | |||
b.release_id, | |||
b.user_id, | |||
b.repo_id, | |||
b.created_unix, | |||
b.updated_unix,(select array_to_string(array_agg(name order by created_unix desc),',') from public.attachment a where a.dataset_id=b.id and a.is_private=false) | |||
FROM public.dataset b where b.repo_id=NEW.id; | |||
INSERT INTO public.issue_es( | |||
id, | |||
repo_id, | |||
index, | |||
poster_id, | |||
original_author, | |||
original_author_id, | |||
name, | |||
content, | |||
milestone_id, | |||
priority, | |||
is_closed, | |||
is_pull, | |||
num_comments, | |||
ref, | |||
deadline_unix, | |||
created_unix, | |||
updated_unix, | |||
closed_unix, | |||
is_locked, | |||
amount, | |||
is_transformed,comment,pr_id) | |||
SELECT | |||
b.id, | |||
b.repo_id, | |||
b.index, | |||
b.poster_id, | |||
b.original_author, | |||
b.original_author_id, | |||
b.name, | |||
b.content, | |||
b.milestone_id, | |||
b.priority, | |||
b.is_closed, | |||
b.is_pull, | |||
b.num_comments, | |||
b.ref, | |||
b.deadline_unix, | |||
b.created_unix, | |||
b.updated_unix, | |||
b.closed_unix, | |||
b.is_locked, | |||
b.amount, | |||
b.is_transformed, | |||
(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id), | |||
(select id from public.pull_request d where d.issue_id=b.id) | |||
FROM public.issue b where b.repo_id=NEW.id; | |||
end if; | |||
if not OLD.is_private and NEW.is_private then | |||
delete from public.issue_es where repo_id=NEW.id; | |||
delete from public.dataset_es where repo_id=NEW.id; | |||
delete from public.repository_es where id=NEW.id; | |||
end if; | |||
end if; | |||
if not NEW.is_private then | |||
raise notice 'update repo,the updated_unix is %',NEW.updated_unix; | |||
update public.repository_es SET description=NEW.description, | |||
name=NEW.name, | |||
lower_name=NEW.lower_name, | |||
owner_name=NEW.owner_name, | |||
website=NEW.website, | |||
updated_unix=NEW.updated_unix, | |||
num_watches=NEW.num_watches, | |||
num_stars=NEW.num_stars, | |||
num_forks=NEW.num_forks, | |||
topics=NEW.topics, | |||
alias = NEW.alias, | |||
lower_alias = NEW.lower_alias, | |||
avatar=NEW.avatar | |||
where id=NEW.id; | |||
end if; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_update_repository | |||
AFTER UPDATE ON public.repository | |||
FOR EACH ROW EXECUTE PROCEDURE update_repository(); | |||
ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_update_repository; | |||
DROP TRIGGER IF EXISTS es_delete_repository on public.repository; | |||
CREATE OR REPLACE FUNCTION public.delete_repository() RETURNS trigger AS | |||
$def$ | |||
declare | |||
BEGIN | |||
delete from public.issue_es where repo_id=OLD.id; | |||
delete from public.dataset_es where repo_id=OLD.id; | |||
DELETE FROM public.repository_es where id=OLD.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_delete_repository | |||
AFTER DELETE ON public.repository | |||
FOR EACH ROW EXECUTE PROCEDURE delete_repository(); | |||
ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_delete_repository; | |||
DROP TRIGGER IF EXISTS es_udpate_repository_lang on public.language_stat; | |||
CREATE OR REPLACE FUNCTION public.udpate_repository_lang() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
if (TG_OP = 'UPDATE') then | |||
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id; | |||
elsif (TG_OP = 'INSERT') then | |||
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id; | |||
elsif (TG_OP = 'DELETE') then | |||
if exists(select 1 from public.repository where id=OLD.repo_id) then | |||
update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=OLD.repo_id) where id=OLD.repo_id; | |||
end if; | |||
end if; | |||
return null; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_udpate_repository_lang | |||
AFTER INSERT OR UPDATE OR DELETE ON public.language_stat | |||
FOR EACH ROW EXECUTE PROCEDURE udpate_repository_lang(); | |||
ALTER TABLE public.language_stat ENABLE ALWAYS TRIGGER es_udpate_repository_lang; |
@@ -0,0 +1,308 @@ | |||
DROP FOREIGN table if exists public.user_es; | |||
CREATE FOREIGN TABLE public.user_es | |||
( | |||
id bigint NOT NULL , | |||
lower_name character varying(255) NULL, | |||
name character varying(255) NULL, | |||
full_name character varying(255), | |||
email character varying(255), | |||
keep_email_private boolean, | |||
email_notifications_preference character varying(20) , | |||
passwd character varying(255) , | |||
passwd_hash_algo character varying(255) , | |||
must_change_password boolean NOT NULL DEFAULT false, | |||
login_type integer, | |||
login_source bigint NOT NULL DEFAULT 0, | |||
login_name character varying(255) , | |||
type integer, | |||
location character varying(255), | |||
website character varying(255), | |||
rands character varying(10), | |||
salt character varying(10), | |||
language character varying(5), | |||
description character varying(255), | |||
created_unix bigint, | |||
updated_unix bigint, | |||
last_login_unix bigint, | |||
last_repo_visibility boolean, | |||
max_repo_creation integer, | |||
is_active boolean, | |||
is_admin boolean, | |||
is_restricted boolean NOT NULL DEFAULT false, | |||
allow_git_hook boolean, | |||
allow_import_local boolean, | |||
allow_create_organization boolean DEFAULT true, | |||
prohibit_login boolean NOT NULL DEFAULT false, | |||
avatar character varying(2048) , | |||
avatar_email character varying(255), | |||
use_custom_avatar boolean, | |||
num_followers integer, | |||
num_following integer NOT NULL DEFAULT 0, | |||
num_stars integer, | |||
num_repos integer, | |||
num_teams integer, | |||
num_members integer, | |||
visibility integer NOT NULL DEFAULT 0, | |||
repo_admin_change_team_access boolean NOT NULL DEFAULT false, | |||
diff_view_style character varying(255), | |||
theme character varying(255), | |||
token character varying(1024) , | |||
public_key character varying(255), | |||
private_key character varying(255), | |||
is_operator boolean NOT NULL DEFAULT false, | |||
num_dataset_stars integer NOT NULL DEFAULT 0 | |||
) SERVER multicorn_es | |||
OPTIONS | |||
( | |||
host '192.168.207.94', | |||
port '9200', | |||
index 'user-es-index', | |||
rowid_column 'id', | |||
default_sort '_id' | |||
) | |||
; | |||
delete from public.user_es; | |||
INSERT INTO public.user_es( | |||
id, | |||
lower_name, | |||
name, | |||
full_name, | |||
email, | |||
keep_email_private, | |||
email_notifications_preference, | |||
must_change_password, | |||
login_type, | |||
login_source, | |||
login_name, | |||
type, | |||
location, | |||
website, | |||
rands, | |||
language, | |||
description, | |||
created_unix, | |||
updated_unix, | |||
last_login_unix, | |||
last_repo_visibility, | |||
max_repo_creation, | |||
is_active, | |||
is_restricted, | |||
allow_git_hook, | |||
allow_import_local, | |||
allow_create_organization, | |||
prohibit_login, | |||
avatar, | |||
avatar_email, | |||
use_custom_avatar, | |||
num_followers, | |||
num_following, | |||
num_stars, | |||
num_repos, | |||
num_teams, | |||
num_members, | |||
visibility, | |||
repo_admin_change_team_access, | |||
diff_view_style, | |||
theme, | |||
is_operator, | |||
num_dataset_stars) | |||
SELECT | |||
id, | |||
lower_name, | |||
name, | |||
full_name, | |||
email, | |||
keep_email_private, | |||
email_notifications_preference, | |||
must_change_password, | |||
login_type, | |||
login_source, | |||
login_name, | |||
type, | |||
location, | |||
website, | |||
rands, | |||
language, | |||
description, | |||
created_unix, | |||
updated_unix, | |||
last_login_unix, | |||
last_repo_visibility, | |||
max_repo_creation, | |||
is_active, | |||
is_restricted, | |||
allow_git_hook, | |||
allow_import_local, | |||
allow_create_organization, | |||
prohibit_login, | |||
avatar, | |||
avatar_email, | |||
use_custom_avatar, | |||
num_followers, | |||
num_following, | |||
num_stars, | |||
num_repos, | |||
num_teams, | |||
num_members, | |||
visibility, | |||
repo_admin_change_team_access, | |||
diff_view_style, | |||
theme, | |||
is_operator, | |||
num_dataset_stars | |||
FROM public.user; | |||
DROP TRIGGER IF EXISTS es_insert_user on public.user; | |||
CREATE OR REPLACE FUNCTION public.insert_user_data() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
INSERT INTO public."user_es"( | |||
id, | |||
lower_name, | |||
name, | |||
full_name, | |||
email, | |||
keep_email_private, | |||
email_notifications_preference, | |||
must_change_password, | |||
login_type, | |||
login_source, | |||
login_name, | |||
type, | |||
location, | |||
website, | |||
rands, | |||
language, | |||
description, | |||
created_unix, | |||
updated_unix, | |||
last_login_unix, | |||
last_repo_visibility, | |||
max_repo_creation, | |||
is_active, | |||
is_restricted, | |||
allow_git_hook, | |||
allow_import_local, | |||
allow_create_organization, | |||
prohibit_login, | |||
avatar, | |||
avatar_email, | |||
use_custom_avatar, | |||
num_followers, | |||
num_following, | |||
num_stars, | |||
num_repos, | |||
num_teams, | |||
num_members, | |||
visibility, | |||
repo_admin_change_team_access, | |||
diff_view_style, | |||
theme, | |||
is_operator, | |||
num_dataset_stars) | |||
VALUES ( | |||
NEW.id, | |||
NEW.lower_name, | |||
NEW.name, | |||
NEW.full_name, | |||
NEW.email, | |||
NEW.keep_email_private, | |||
NEW.email_notifications_preference, | |||
NEW.must_change_password, | |||
NEW.login_type, | |||
NEW.login_source, | |||
NEW.login_name, | |||
NEW.type, | |||
NEW.location, | |||
NEW.website, | |||
NEW.rands, | |||
NEW.language, | |||
NEW.description, | |||
NEW.created_unix, | |||
NEW.updated_unix, | |||
NEW.last_login_unix, | |||
NEW.last_repo_visibility, | |||
NEW.max_repo_creation, | |||
NEW.is_active, | |||
NEW.is_restricted, | |||
NEW.allow_git_hook, | |||
NEW.allow_import_local, | |||
NEW.allow_create_organization, | |||
NEW.prohibit_login, | |||
NEW.avatar, | |||
NEW.avatar_email, | |||
NEW.use_custom_avatar, | |||
NEW.num_followers, | |||
NEW.num_following, | |||
NEW.num_stars, | |||
NEW.num_repos, | |||
NEW.num_teams, | |||
NEW.num_members, | |||
NEW.visibility, | |||
NEW.repo_admin_change_team_access, | |||
NEW.diff_view_style, | |||
NEW.theme, | |||
NEW.is_operator, | |||
NEW.num_dataset_stars | |||
); | |||
RETURN NEW; | |||
END; | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_insert_user | |||
AFTER INSERT ON public.user | |||
FOR EACH ROW EXECUTE PROCEDURE insert_user_data(); | |||
ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_insert_user; | |||
DROP TRIGGER IF EXISTS es_update_user on public.user; | |||
CREATE OR REPLACE FUNCTION public.update_user() RETURNS trigger AS | |||
$def$ | |||
BEGIN | |||
UPDATE public.user_es | |||
SET description=NEW.description, | |||
name=NEW.name, | |||
full_name=NEW.full_name, | |||
location=NEW.location, | |||
website=NEW.website, | |||
email=NEW.email, | |||
num_dataset_stars=NEW.num_dataset_stars, | |||
updated_unix=NEW.updated_unix | |||
where id=NEW.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_update_user | |||
AFTER UPDATE ON public.user | |||
FOR EACH ROW EXECUTE PROCEDURE update_user(); | |||
ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_update_user; | |||
DROP TRIGGER IF EXISTS es_delete_user on public.user; | |||
CREATE OR REPLACE FUNCTION public.delete_user() RETURNS trigger AS | |||
$def$ | |||
declare | |||
BEGIN | |||
DELETE FROM public.user_es where id=OLD.id; | |||
return new; | |||
END | |||
$def$ | |||
LANGUAGE plpgsql; | |||
CREATE TRIGGER es_delete_user | |||
AFTER DELETE ON public.user | |||
FOR EACH ROW EXECUTE PROCEDURE delete_user(); | |||
ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_delete_user; |
@@ -13,11 +13,6 @@ const ( | |||
FileUploaded | |||
) | |||
const ( | |||
TypeCloudBrainOne int = iota | |||
TypeCloudBrainTwo | |||
) | |||
type FileChunk struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
UUID string `xorm:"uuid UNIQUE"` | |||
@@ -129,6 +129,7 @@ func init() { | |||
new(LanguageStat), | |||
new(EmailHash), | |||
new(Dataset), | |||
new(DatasetStar), | |||
new(Cloudbrain), | |||
new(FileChunk), | |||
new(BlockChain), | |||
@@ -137,6 +138,7 @@ func init() { | |||
new(OfficialTag), | |||
new(OfficialTagRepos), | |||
new(WechatBindLog), | |||
new(SearchRecord), | |||
) | |||
tablesStatistic = append(tablesStatistic, | |||
@@ -6,13 +6,14 @@ | |||
package models | |||
import ( | |||
"code.gitea.io/gitea/modules/git" | |||
"context" | |||
"crypto/md5" | |||
"errors" | |||
"fmt" | |||
"html/template" | |||
"math/rand" | |||
"code.gitea.io/gitea/modules/git" | |||
"xorm.io/xorm" | |||
"code.gitea.io/gitea/modules/blockchain" | |||
@@ -1280,10 +1281,6 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, opts ...Cr | |||
return fmt.Errorf("copyDefaultWebhooksToRepo: %v", err) | |||
} | |||
if err = CreateDefaultDatasetToRepo(repo); err != nil { | |||
return fmt.Errorf("models.CreateDefaultDatasetToRepo: %v", err) | |||
} | |||
return nil | |||
} | |||
@@ -1601,6 +1598,36 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e | |||
if err != nil { | |||
return err | |||
} | |||
//If repo has become private, we need set dataset and dataset_file to private | |||
_, err = e.Where("repo_id = ? and status <> 2", repo.ID).Cols("status").Update(&Dataset{ | |||
Status: 0, | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
dataset, err := GetDatasetByRepo(repo) | |||
if err != nil && !IsErrNotExist(err) { | |||
return err | |||
} | |||
if dataset != nil { | |||
_, err = e.Where("dataset_id = ?", dataset.ID).Cols("is_private").Update(&Attachment{ | |||
IsPrivate: true, | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
} | |||
} else { | |||
//If repo has become public, we need set dataset to public | |||
_, err = e.Where("repo_id = ? and status <> 2", repo.ID).Cols("status").Update(&Dataset{ | |||
Status: 1, | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
} | |||
// Create/Remove git-daemon-export-ok for git-daemon... | |||
@@ -2691,7 +2718,7 @@ func ReadLatestFileInRepo(userName, repoName, refName, treePath string) (*RepoFi | |||
log.Error("ReadLatestFileInRepo error when OpenRepository,error=%v", err) | |||
return nil, err | |||
} | |||
commitID, err := gitRepo.GetBranchCommitID(refName) | |||
_, err = gitRepo.GetBranchCommitID(refName) | |||
if err != nil { | |||
log.Error("ReadLatestFileInRepo error when GetBranchCommitID,error=%v", err) | |||
return nil, err | |||
@@ -2723,5 +2750,9 @@ func ReadLatestFileInRepo(userName, repoName, refName, treePath string) (*RepoFi | |||
if n >= 0 { | |||
buf = buf[:n] | |||
} | |||
return &RepoFile{CommitId: commitID, Content: buf}, nil | |||
commitId := "" | |||
if blob != nil { | |||
commitId = fmt.Sprint(blob.ID) | |||
} | |||
return &RepoFile{CommitId: commitId, Content: buf}, nil | |||
} |
@@ -190,7 +190,8 @@ type SearchRepoOptions struct { | |||
// None -> include all repos | |||
// True -> include just courses | |||
// False -> include just no courses | |||
Course util.OptionalBool | |||
Course util.OptionalBool | |||
OnlySearchPrivate bool | |||
} | |||
//SearchOrderBy is used to sort the result | |||
@@ -219,12 +220,15 @@ const ( | |||
SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC" | |||
SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC" | |||
SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC" | |||
SearchOrderByWatches SearchOrderBy = "num_watches DESC" | |||
) | |||
// SearchRepositoryCondition creates a query condition according search repository options | |||
func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
var cond = builder.NewCond() | |||
if opts.OnlySearchPrivate { | |||
cond = cond.And(builder.Eq{"is_private": true}) | |||
} | |||
if opts.Private { | |||
if opts.Actor != nil && !opts.Actor.IsAdmin && opts.Actor.ID != opts.OwnerID { | |||
// OK we're in the context of a User | |||
@@ -337,7 +341,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
if !opts.TopicOnly { | |||
var likes = builder.NewCond() | |||
for _, v := range strings.Split(opts.Keyword, ",") { | |||
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) | |||
likes = likes.Or(builder.Like{"lower_alias", strings.ToLower(v)}) | |||
likes = likes.Or(builder.Like{"alias", v}) | |||
if opts.IncludeDescription { | |||
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) | |||
@@ -0,0 +1,83 @@ | |||
package models | |||
import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"xorm.io/xorm" | |||
) | |||
type SearchRecord struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
//user | |||
Keyword string `xorm:"NOT NULL"` | |||
// | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
} | |||
func SaveSearchKeywordToDb(keyword string) error { | |||
record := &SearchRecord{ | |||
Keyword: keyword, | |||
} | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
_, err := sess.Insert(record) | |||
if err != nil { | |||
log.Info("insert error." + err.Error()) | |||
return err | |||
} | |||
return nil | |||
} | |||
func setIssueQueryCondition(sess *xorm.Session, Keyword string, isPull bool, userId int64) { | |||
sess.And("issue.poster_id=?", userId) | |||
sess.And("issue.is_pull=?", isPull) | |||
sess.And("(issue.name like '%" + Keyword + "%' or issue.content like '%" + Keyword + "%')") | |||
sess.Join("INNER", "repository", "issue.repo_id = repository.id").And("repository.is_private = ?", true) | |||
} | |||
func SearchPrivateIssueOrPr(Page int, PageSize int, Keyword string, isPull bool, userId int64) ([]*Issue, int64, error) { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
setIssueQueryCondition(sess, Keyword, isPull, userId) | |||
count, err := sess.Count(new(Issue)) | |||
if err != nil { | |||
return nil, 0, err | |||
} | |||
setIssueQueryCondition(sess, Keyword, isPull, userId) | |||
sess.Desc("issue.created_unix") | |||
sess.Limit(PageSize, (Page-1)*PageSize) | |||
issues := make([]*Issue, 0) | |||
if err := sess.Find(&issues); err != nil { | |||
return nil, 0, err | |||
} else { | |||
return issues, count, nil | |||
} | |||
} | |||
func setDataSetQueryCondition(sess *xorm.Session, Keyword string, userId int64) { | |||
sess.And("dataset.user_id=?", userId) | |||
sess.And("(dataset.title like '%" + Keyword + "%' or dataset.description like '%" + Keyword + "%')") | |||
sess.Join("INNER", "repository", "dataset.repo_id = repository.id").And("repository.is_private = ?", true) | |||
} | |||
func SearchDatasetBySQL(Page int, PageSize int, Keyword string, userId int64) ([]*Dataset, int64, error) { | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
setDataSetQueryCondition(sess, Keyword, userId) | |||
count, err := sess.Count(new(Dataset)) | |||
if err != nil { | |||
return nil, 0, err | |||
} | |||
setDataSetQueryCondition(sess, Keyword, userId) | |||
sess.Desc("dataset.created_unix") | |||
sess.Limit(PageSize, (Page-1)*PageSize) | |||
datasets := make([]*Dataset, 0) | |||
if err := sess.Find(&datasets); err != nil { | |||
return nil, 0, err | |||
} else { | |||
return datasets, count, nil | |||
} | |||
} |
@@ -153,10 +153,11 @@ type User struct { | |||
UseCustomAvatar bool | |||
// Counters | |||
NumFollowers int | |||
NumFollowing int `xorm:"NOT NULL DEFAULT 0"` | |||
NumStars int | |||
NumRepos int | |||
NumFollowers int | |||
NumFollowing int `xorm:"NOT NULL DEFAULT 0"` | |||
NumStars int | |||
NumDatasetStars int `xorm:"NOT NULL DEFAULT 0"` | |||
NumRepos int | |||
// For organization | |||
NumTeams int | |||
@@ -20,6 +20,9 @@ type CreateCloudBrainForm struct { | |||
ResourceSpecId int `form:"resource_spec_id" binding:"Required"` | |||
BenchmarkTypeID int `form:"benchmark_types_id"` | |||
BenchmarkChildTypeID int `form:"benchmark_child_types_id"` | |||
BootFile string `form:"boot_file"` | |||
Params string `form:"run_para_list"` | |||
BranchName string `form:"branch_name"` | |||
} | |||
type CommitImageCloudBrainForm struct { | |||
@@ -9,11 +9,10 @@ import ( | |||
type CreateDatasetForm struct { | |||
Title string `binding:"Required"` | |||
Category string `binding:"Required"` | |||
Description string `binding:"Required;MaxSize(254)"` | |||
Description string `binding:"Required"` | |||
License string `binding:"Required;MaxSize(64)"` | |||
Task string `binding:"Required;MaxSize(64)"` | |||
ReleaseID int64 `xorm:"INDEX"` | |||
Private bool | |||
Files []string | |||
} | |||
@@ -25,11 +24,23 @@ type EditDatasetForm struct { | |||
ID int64 `binding:"Required"` | |||
Title string `binding:"Required"` | |||
Category string `binding:"Required"` | |||
Description string `binding:"Required;MaxSize(254)"` | |||
Description string `binding:"Required"` | |||
License string `binding:"Required;MaxSize(64)"` | |||
Task string `binding:"Required;MaxSize(64)"` | |||
Private bool | |||
ReleaseID int64 `xorm:"INDEX"` | |||
ReleaseID int64 `xorm:"INDEX"` | |||
Files []string | |||
Type string `binding:"Required"` | |||
Type string `binding:"Required"` | |||
} | |||
func (f *EditDatasetForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | |||
return validate(errs, ctx.Data, f, ctx.Locale) | |||
} | |||
type EditAttachmentForm struct { | |||
ID int64 `binding:"Required"` | |||
Description string | |||
} | |||
func (f *EditAttachmentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | |||
return validate(errs, ctx.Data, f, ctx.Locale) | |||
} |
@@ -15,14 +15,13 @@ import ( | |||
) | |||
const ( | |||
Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple; | |||
service ssh stop; | |||
jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"` | |||
Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"` | |||
//CommandBenchmark = `echo "start benchmark";python /code/test.py;echo "end benchmark"` | |||
CommandBenchmark = `echo "start benchmark";cd /benchmark && bash run_bk.sh;echo "end benchmark"` | |||
CodeMountPath = "/code" | |||
DataSetMountPath = "/dataset" | |||
ModelMountPath = "/model" | |||
LogFile = "log.txt" | |||
BenchMarkMountPath = "/benchmark" | |||
BenchMarkResourceID = 1 | |||
Snn4imagenetMountPath = "/snn4imagenet" | |||
@@ -32,10 +31,13 @@ const ( | |||
SubTaskName = "task1" | |||
Success = "S000" | |||
DefaultBranchName = "master" | |||
) | |||
var ( | |||
ResourceSpecs *models.ResourceSpecs | |||
ResourceSpecs *models.ResourceSpecs | |||
TrainResourceSpecs *models.ResourceSpecs | |||
) | |||
func isAdminOrOwnerOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool { | |||
@@ -147,7 +149,7 @@ func AdminOrJobCreaterRightForTrain(ctx *context.Context) { | |||
} | |||
func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||
func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description, branchName, bootFile, params string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||
dataActualPath := setting.Attachment.Minio.RealPath + | |||
setting.Attachment.Minio.Bucket + "/" + | |||
setting.Attachment.Minio.BasePath + | |||
@@ -155,13 +157,27 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
uuid | |||
var resourceSpec *models.ResourceSpec | |||
if ResourceSpecs == nil { | |||
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||
} | |||
for _, spec := range ResourceSpecs.ResourceSpec { | |||
if resourceSpecId == spec.Id { | |||
resourceSpec = spec | |||
var versionCount int | |||
if jobType == string(models.JobTypeTrain) { | |||
versionCount = 1 | |||
if TrainResourceSpecs == nil { | |||
json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs) | |||
} | |||
for _, spec := range TrainResourceSpecs.ResourceSpec { | |||
if resourceSpecId == spec.Id { | |||
resourceSpec = spec | |||
} | |||
} | |||
} else { | |||
if ResourceSpecs == nil { | |||
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||
} | |||
for _, spec := range ResourceSpecs.ResourceSpec { | |||
if resourceSpecId == spec.Id { | |||
resourceSpec = spec | |||
} | |||
} | |||
} | |||
if resourceSpec == nil { | |||
@@ -169,6 +185,15 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
return errors.New("no such resourceSpec") | |||
} | |||
var datasetName string | |||
attach, err := models.GetAttachmentByUUID(uuid) | |||
if err != nil { | |||
//for benchmark, do not return error | |||
log.Error("GetAttachmentByUUID failed:%v", err) | |||
} else { | |||
datasetName = attach.Name | |||
} | |||
jobResult, err := CreateJob(jobName, models.CreateJobParams{ | |||
JobName: jobName, | |||
RetryCount: 1, | |||
@@ -263,13 +288,19 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
BenchmarkTypeID: benchmarkTypeID, | |||
BenchmarkChildTypeID: benchmarkChildTypeID, | |||
Description: description, | |||
IsLatestVersion: "1", | |||
VersionCount: versionCount, | |||
BranchName: branchName, | |||
BootFile: bootFile, | |||
DatasetName: datasetName, | |||
Parameters: params, | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
task, err := models.GetCloudbrainByName(jobName) | |||
task, err := models.GetCloudbrainByJobID(jobID) | |||
if err != nil { | |||
log.Error("GetCloudbrainByName failed: %v", err.Error()) | |||
return err | |||
@@ -278,6 +309,8 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||
if string(models.JobTypeBenchmark) == jobType { | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateBenchMarkTask) | |||
} else if string(models.JobTypeTrain) == jobType { | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, displayJobName, models.ActionCreateGPUTrainTask) | |||
} else { | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugGPUTask) | |||
} | |||
@@ -407,8 +440,10 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e | |||
return err | |||
} | |||
idString := strconv.FormatInt(newTask.ID, 10) | |||
*newID = idString | |||
stringId := strconv.FormatInt(newTask.ID, 10) | |||
*newID = stringId | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, task.DisplayJobName, models.ActionCreateDebugGPUTask) | |||
return nil | |||
} |
@@ -475,6 +475,8 @@ func RepoAssignment() macaron.Handler { | |||
if ctx.IsSigned { | |||
ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.ID, repo.ID) | |||
ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.ID, repo.ID) | |||
ctx.Data["IsStaringDataset"] = models.IsDatasetStaringByRepoId(ctx.User.ID, repo.ID) | |||
} | |||
if repo.IsFork { | |||
@@ -0,0 +1,17 @@ | |||
package dataset | |||
func GetResourceType(cloudbrainType int) string { | |||
if cloudbrainType == 0 { | |||
return "CPU/GPU" | |||
} else { | |||
return "NPU" | |||
} | |||
} | |||
func GetStatusText(isPrivate bool) string { | |||
if isPrivate { | |||
return "dataset.private" | |||
} else { | |||
return "dataset.public" | |||
} | |||
} |
@@ -51,10 +51,11 @@ const ( | |||
DataUrl = "data_url" | |||
ResultUrl = "result_url" | |||
CkptUrl = "ckpt_url" | |||
DeviceTarget = "device_target" | |||
Ascend = "Ascend" | |||
PerPage = 10 | |||
IsLatestVersion = "1" | |||
NotLatestVersion = "0" | |||
DebugType = -1 | |||
VersionCount = 1 | |||
SortByCreateTime = "create_time" | |||
@@ -165,6 +165,7 @@ var ( | |||
ExplorePagingNum int | |||
ContributorPagingNum int | |||
IssuePagingNum int | |||
DatasetPagingNum int | |||
RepoSearchPagingNum int | |||
MembersPagingNum int | |||
FeedMaxCommitNum int | |||
@@ -207,6 +208,7 @@ var ( | |||
ExplorePagingNum: 20, | |||
ContributorPagingNum: 50, | |||
IssuePagingNum: 10, | |||
DatasetPagingNum: 5, | |||
RepoSearchPagingNum: 10, | |||
MembersPagingNum: 20, | |||
FeedMaxCommitNum: 5, | |||
@@ -435,7 +437,7 @@ var ( | |||
//home page | |||
RecommentRepoAddr string | |||
ESSearchURL string | |||
//notice config | |||
UserNameOfNoticeRepo string | |||
RepoNameOfNoticeRepo string | |||
@@ -450,16 +452,18 @@ var ( | |||
DecompressOBSTaskName string | |||
//cloudbrain config | |||
CBAuthUser string | |||
CBAuthPassword string | |||
RestServerHost string | |||
JobPath string | |||
CBCodePathPrefix string | |||
JobType string | |||
GpuTypes string | |||
DebugServerHost string | |||
ResourceSpecs string | |||
MaxDuration int64 | |||
CBAuthUser string | |||
CBAuthPassword string | |||
RestServerHost string | |||
JobPath string | |||
CBCodePathPrefix string | |||
JobType string | |||
GpuTypes string | |||
DebugServerHost string | |||
ResourceSpecs string | |||
MaxDuration int64 | |||
TrainGpuTypes string | |||
TrainResourceSpecs string | |||
//benchmark config | |||
IsBenchmarkEnabled bool | |||
@@ -512,9 +516,9 @@ var ( | |||
ProfileID string | |||
PoolInfos string | |||
Flavor string | |||
DebugHost string | |||
ImageInfos string | |||
Capacity int | |||
DebugHost string | |||
ImageInfos string | |||
Capacity int | |||
//train-job | |||
ResourcePools string | |||
Engines string | |||
@@ -1263,6 +1267,7 @@ func NewContext() { | |||
sec = Cfg.Section("homepage") | |||
RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/") | |||
ESSearchURL = sec.Key("ESSearchURL").MustString("http://192.168.207.94:9200") | |||
sec = Cfg.Section("notice") | |||
UserNameOfNoticeRepo = sec.Key("USER_NAME").MustString("OpenIOSSG") | |||
@@ -1283,6 +1288,8 @@ func NewContext() { | |||
GpuTypes = sec.Key("GPU_TYPES").MustString("") | |||
ResourceSpecs = sec.Key("RESOURCE_SPECS").MustString("") | |||
MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400) | |||
TrainGpuTypes = sec.Key("TRAIN_GPU_TYPES").MustString("") | |||
TrainResourceSpecs = sec.Key("TRAIN_RESOURCE_SPECS").MustString("") | |||
sec = Cfg.Section("benchmark") | |||
IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false) | |||
@@ -23,6 +23,8 @@ import ( | |||
"time" | |||
"unicode" | |||
"code.gitea.io/gitea/modules/dataset" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/modules/emoji" | |||
@@ -86,20 +88,22 @@ func NewFuncMap() []template.FuncMap { | |||
"AllowedReactions": func() []string { | |||
return setting.UI.Reactions | |||
}, | |||
"AvatarLink": models.AvatarLink, | |||
"Safe": Safe, | |||
"SafeJS": SafeJS, | |||
"Str2html": Str2html, | |||
"TimeSince": timeutil.TimeSince, | |||
"TimeSinceUnix": timeutil.TimeSinceUnix, | |||
"TimeSinceUnix1": timeutil.TimeSinceUnix1, | |||
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort, | |||
"RawTimeSince": timeutil.RawTimeSince, | |||
"FileSize": base.FileSize, | |||
"PrettyNumber": base.PrettyNumber, | |||
"Subtract": base.Subtract, | |||
"EntryIcon": base.EntryIcon, | |||
"MigrationIcon": MigrationIcon, | |||
"AvatarLink": models.AvatarLink, | |||
"Safe": Safe, | |||
"SafeJS": SafeJS, | |||
"Str2html": Str2html, | |||
"TimeSince": timeutil.TimeSince, | |||
"TimeSinceUnix": timeutil.TimeSinceUnix, | |||
"TimeSinceUnix1": timeutil.TimeSinceUnix1, | |||
"AttachmentResourceType": dataset.GetResourceType, | |||
"AttachmentStatus": dataset.GetStatusText, | |||
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort, | |||
"RawTimeSince": timeutil.RawTimeSince, | |||
"FileSize": base.FileSize, | |||
"PrettyNumber": base.PrettyNumber, | |||
"Subtract": base.Subtract, | |||
"EntryIcon": base.EntryIcon, | |||
"MigrationIcon": MigrationIcon, | |||
"Add": func(a, b int) int { | |||
return a + b | |||
}, | |||
@@ -340,11 +344,13 @@ func NewTextFuncMap() []texttmpl.FuncMap { | |||
"AppDomain": func() string { | |||
return setting.Domain | |||
}, | |||
"TimeSince": timeutil.TimeSince, | |||
"TimeSinceUnix": timeutil.TimeSinceUnix, | |||
"TimeSinceUnix1": timeutil.TimeSinceUnix1, | |||
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort, | |||
"RawTimeSince": timeutil.RawTimeSince, | |||
"TimeSince": timeutil.TimeSince, | |||
"TimeSinceUnix": timeutil.TimeSinceUnix, | |||
"TimeSinceUnix1": timeutil.TimeSinceUnix1, | |||
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort, | |||
"RawTimeSince": timeutil.RawTimeSince, | |||
"AttachmentResourceType": dataset.GetResourceType, | |||
"AttachmentStatus": dataset.GetStatusText, | |||
"DateFmtLong": func(t time.Time) string { | |||
return t.Format(time.RFC1123Z) | |||
}, | |||
@@ -746,5 +752,5 @@ func licenses() []string { | |||
// Dataset tasks | |||
func tasks() []string { | |||
return []string{"machine_translation", "question_answering_system", "information_retrieval", "knowledge_graph", "text_annotation", "text_categorization", "emotion_analysis", "language_modeling", "speech_recognition", "automatic_digest", "information_extraction", "description_generation", "image_classification", "face_recognition", "image_search", "target_detection", "image_description_generation", "vehicle_license_plate_recognition", "medical_image_analysis", "unmanned", "unmanned_security", "drone", "vr_ar", "2_d_vision", "2.5_d_vision", "3_d_reconstruction", "image_processing", "video_processing", "visual_input_system", "speech_coding", "speech_enhancement", "speech_recognition", "speech_synthesis"} | |||
return []string{"machine_translation", "question_answering_system", "information_retrieval", "knowledge_graph", "text_annotation", "text_categorization", "emotion_analysis", "language_modeling", "speech_recognition", "automatic_digest", "information_extraction", "description_generation", "image_classification", "face_recognition", "image_search", "target_detection", "image_description_generation", "vehicle_license_plate_recognition", "medical_image_analysis", "unmanned", "unmanned_security", "drone", "vr_ar", "2_d_vision", "2.5_d_vision", "3_d_reconstruction", "image_processing", "video_processing", "visual_input_system", "speech_coding", "speech_enhancement", "speech_synthesis"} | |||
} |
@@ -254,6 +254,18 @@ page_dev_yunlao_desc3=Developers can freely choose the corresponding computing r | |||
page_dev_yunlao_desc4=If your model requires more computing resources, you can also apply for it separately. | |||
page_dev_yunlao_apply=Apply Separately | |||
search=Search | |||
search_repo=Repository | |||
search_dataset=DataSet | |||
search_issue=Issue | |||
search_pr=Pull Request | |||
search_user=User | |||
search_org=Organization | |||
search_finded=Find | |||
search_related=related | |||
search_maybe=maybe | |||
search_ge= | |||
[explore] | |||
repos = Repositories | |||
select_repos = Select the project | |||
@@ -723,8 +735,13 @@ alert = To initiate a cloud brain task, please upload the dataset in zip format. | |||
dataset = Dataset | |||
dataset_setting= Dataset Setting | |||
title = Name | |||
title_format_err=Name can only contain number,letter,'-','_' or '.', and can be up to 100 characters long. | |||
description = Description | |||
description_format_err=Description's length can be up to 1024 characters long. | |||
create_dataset = Create Dataset | |||
create_dataset_fail=Failed to create dataset. | |||
query_dataset_fail=Failed to query dataset. | |||
edit_attachment_fail=Failed to update description. | |||
show_dataset= Dataset | |||
edit_dataset= Edit Dataset | |||
update_dataset= Update Dataset | |||
@@ -743,7 +760,8 @@ private = private | |||
public = public | |||
dir = directory | |||
back = back | |||
copy_url=copy download url | |||
copy_url=Copy Download Url | |||
copy_md5 = Copy MD5 | |||
directory=preview of the datasets | |||
create_label_task=create label task | |||
visibility = visibility | |||
@@ -794,12 +812,49 @@ category.computer_vision= computer vision | |||
category.natural_language_processing= natural language processing | |||
category.speech_processing= speech processing | |||
category.computer_vision_natural_language_processing= computer vision and natural language processing | |||
attachment.delete= delete this version of dataset | |||
attachment.delete= Delete this version of dataset | |||
attachment.delete_desc= Are you sure you will delete this version of dataset, once deleted can not be recovery | |||
public= public | |||
private= private | |||
delete= delete | |||
delete= Delete | |||
select_dataset=Select Dataset | |||
current_project=Current Project | |||
owner_dataset=Owner Dataset | |||
public_dataset=Public Dataset | |||
I_liked = I Liked | |||
use = Use | |||
create_new_dataset = Create New Dataset | |||
dataset_name = Dataset Name | |||
dataset_description = Dataset Description | |||
select_category = Select Category | |||
select_task = Select Research Direction/Application Area | |||
dataset_name_tooltips = Please enter letters, numbers, _ and - up to 100 characters. | |||
dataset_no_create = No dataset has been created yet | |||
dataset_explain = Dataset: CloudBrain I provides CPU/GPU resources, Cloudbrain II provides Ascend NPU resources, and the data set used for debugging also needs to be uploaded to the corresponding environment; | |||
dataset_instructions_for_use = Instructions for use: You can refer to Qizhi AI Collaboration Platform | |||
dataset_camp_course = Newcomer Training Camp Course; | |||
dataset_upload = Upload | |||
dataset_file_name = File Name | |||
dataset_available_clusters = Available Clusters | |||
dataset_upload_time = Upload Time | |||
download = Download | |||
modify_description = Modify Description | |||
set_public = Set Public | |||
set_private = Set Private | |||
annotation = Annotation | |||
upload_dataset_file = Upload Dataset File | |||
file_description = File Description | |||
data_upload = Dataset Upload | |||
illustrate = Illustrate | |||
illustrate.only = Only Datasets In | |||
illustrate.zip = zip/tar.gz Format | |||
illustrate.fisrt_end = Can Initiate Cloudbrain Tasks | |||
modify_dataset = Modify Dataset | |||
modify_dataset_description = Modify Dataset Description | |||
search_dataset = Search Dataset Files | |||
unzip_tooltips = If it has not been decompressed for a long time, please check whether the compressed package has encrypted files or file errors | |||
zip_failed = Decompression failed, please check whether the compressed package is encrypted or contact technical support | |||
dataset_desc = The description should not exceed 1024 characters | |||
[repo] | |||
owner = Owner | |||
repo_name = Repository Name | |||
@@ -829,7 +884,7 @@ repo_label_helpe = Press Enter to complete | |||
issue_labels = Issue Labels | |||
issue_labels_helper = Select an issue label set. | |||
license = License | |||
license_helper = Select a license file. | |||
license_helper = Select a license file | |||
readme = README | |||
readme_helper = Select a README file template. | |||
auto_init = Initialize Repository (Adds .gitignore, License and README) | |||
@@ -870,7 +925,7 @@ gpu_type_all=All | |||
model_download=Model Download | |||
submit_image=Submit Image | |||
download=Download | |||
score=score | |||
score=Score | |||
cloudbrain=Cloudbrain | |||
cloudbrain.new=New cloudbrain | |||
@@ -885,7 +940,7 @@ cloudbrain1 = cloudbrain1 | |||
cloudbrain2 = cloudbrain2 | |||
cloudbrain_selection = select cloudbrain | |||
cloudbrain_platform_selection = Select the cloudbrain platform you want to use: | |||
confirm_choice = confirm | |||
confirm_choice = Confirm | |||
cloudbran1_tips = Only data in zip format can create cloudbrain tasks | |||
cloudbrain_creator=Creator | |||
cloudbrain_task = Task Name | |||
@@ -967,7 +1022,8 @@ modelarts.train_job.parameter_value=Parameter Value | |||
modelarts.train_job.resource_setting=resource_setting | |||
modelarts.train_job.resource_setting_info=resource_setting_info | |||
modelarts.train_job.resource_pool=resource_pool | |||
modelarts.train_job.resource_type=resource_type | |||
modelarts.train_job.resource_type=Resource Type | |||
modelarts.train_job.train_dataset=Train Dataset | |||
modelarts.train_job.standard=Standard | |||
modelarts.train_job.NAS_address=NAS Address | |||
modelarts.train_job.NAS_mount_path=NAS Mount Path | |||
@@ -1095,6 +1151,7 @@ unstar = Unstar | |||
star = Star | |||
fork = Fork | |||
download_archive = Download Repository | |||
star_fail=Failed to %s the dataset. | |||
no_desc = No Description | |||
no_label = No labels | |||
@@ -2746,10 +2803,11 @@ reject_pull_request = `suggested changes for <a href="%s/pulls/%s">%s#%[2]s</a>` | |||
upload_dataset=`upload dataset <a href="%s/datasets?type=%s">%s</a>` | |||
task_gpudebugjob=`created CPU/GPU type debugging task<a href="%s/cloudbrain/%s">%s</a>` | |||
task_npudebugjob=`created NPU type debugging task <a href="%s/modelarts/notebook/%s">%s</a>` | |||
task_trainjob=`created training task<a href="%s/modelarts/train-job/%s">%s</a>` | |||
task_nputrainjob=`created NPU training task<a href="%s/modelarts/train-job/%s">%s</a>` | |||
task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>` | |||
task_benchmark=`created profiling task <a href="%s/cloudbrain/benchmark/%s">%s</a>` | |||
task_createmodel=`created new model <a href="%s/modelmanage/show_model_info?name=%s">%s</a>` | |||
task_gputrainjob=`created CPU/GPU training task<a href="%s/cloudbrain/train-job/%s">%s</a>` | |||
[tool] | |||
ago = %s ago | |||
@@ -256,6 +256,18 @@ page_dev_yunlao_desc3=开发者可以根据使用需求,自由选择相应计 | |||
page_dev_yunlao_desc4=如果您的模型需要更多的计算资源,也可以单独申请 | |||
page_dev_yunlao_apply=单独申请 | |||
search=搜索 | |||
search_repo=项目 | |||
search_dataset=数据集 | |||
search_issue=任务 | |||
search_pr=合并请求 | |||
search_user=用户 | |||
search_org=组织 | |||
search_finded=找到 | |||
search_related=相关 | |||
search_maybe=约为 | |||
search_ge=个 | |||
[explore] | |||
repos=项目 | |||
select_repos=精选项目 | |||
@@ -726,8 +738,14 @@ alert=如果要发起云脑任务,请上传zip格式的数据集 | |||
dataset=数据集 | |||
dataset_setting=数据集设置 | |||
title=名称 | |||
title_format_err=名称最多允许输入100个字符,只允许字母,数字,中划线 (‘-’),下划线 (‘_’) 和点 (‘.’) 。 | |||
description=描述 | |||
description_format_err=描述最多允许输入1024个字符。 | |||
create_dataset=创建数据集 | |||
create_dataset_fail=创建数据集失败。 | |||
query_dataset_fail=查询数据集失败。 | |||
edit_attachment_fail=修改描述失败。 | |||
show_dataset=数据集 | |||
edit_dataset=编辑数据集 | |||
update_dataset=更新数据集 | |||
@@ -803,6 +821,44 @@ attachment.delete_desc= 你确定要删除该版本的数据集么?一旦删 | |||
public=公有 | |||
private=私有 | |||
delete=删除 | |||
select_dataset=选择数据集 | |||
current_project=当前项目 | |||
owner_dataset=我的数据集 | |||
public_dataset=公开数据集 | |||
I_liked=我收藏的 | |||
use=使用 | |||
create_new_dataset = 新建数据集 | |||
dataset_name=数据集名称 | |||
dataset_description = 数据集描述 | |||
select_category = 选择分类 | |||
select_task = 选择研究方向/应用领域 | |||
dataset_name_tooltips = 请输入字母、数字、_和-,最长100个字符。 | |||
dataset_no_create = 还未创建过数据集 | |||
dataset_explain = 数据集:云脑1提供 CPU / GPU 资源,云脑2提供 Ascend NPU 资源,调试使用的数据集也需要上传到对应的环境; | |||
dataset_instructions_for_use = 使用说明:可以参考启智AI协作平台 | |||
dataset_camp_course = 小白训练营课程 | |||
dataset_upload = 上传 | |||
dataset_file_name = 文件名称 | |||
dataset_available_clusters = 可用集群 | |||
dataset_upload_time = 上传时间 | |||
download = 下载 | |||
modify_description = 修改描述 | |||
set_public = 设为公开 | |||
set_private = 设为私有 | |||
annotation = 标注 | |||
upload_dataset_file = 上传数据集文件 | |||
file_description = 文件描述 | |||
data_upload = 数据上传 | |||
illustrate = 说明 | |||
illustrate.only = 只有 | |||
illustrate.zip = zip/tar.gz格式 | |||
illustrate.fisrt_end = 的数据集才能发起云脑任务 | |||
modify_dataset = 修改数据集 | |||
modify_dataset_description = 修改数据集文件描述 | |||
search_dataset = 搜索数据集文件 | |||
unzip_tooltips = 如果长时间未解压,请检查压缩包是否有加密文件或者文件错误 | |||
zip_failed = 解压失败,请检查压缩包是否有加密或者联系技术支持人员。 | |||
dataset_desc = 描述字数不超过1024个字符 | |||
[repo] | |||
owner=拥有者 | |||
@@ -833,7 +889,7 @@ repo_label_helpe=输入完成后回车键完成标签确定。 | |||
issue_labels=任务标签 | |||
issue_labels_helper=选择一个任务标签集 | |||
license=授权许可 | |||
license_helper=选择授权许可文件。 | |||
license_helper=选择授权许可文件 | |||
readme=自述 | |||
readme_helper=选择自述文件模板。 | |||
auto_init=初始化存储库 (添加. gitignore、许可证和自述文件) | |||
@@ -1101,6 +1157,8 @@ unstar=取消点赞 | |||
star=点赞 | |||
fork=派生 | |||
download_archive=下载此项目 | |||
star_fail=%s失败。 | |||
no_desc=暂无描述 | |||
no_label = 暂无标签 | |||
@@ -2751,10 +2809,11 @@ reject_pull_request=`建议变更 <a href="%s/pulls/%s">%s#%[2]s</a>` | |||
upload_dataset=`上传了数据集文件 <a href="%s/datasets?type=%s">%s</a>` | |||
task_gpudebugjob=`创建了CPU/GPU类型调试任务 <a href="%s/cloudbrain/%s">%s</a>` | |||
task_npudebugjob=`创建了NPU类型调试任务 <a href="%s/modelarts/notebook/%s">%s</a>` | |||
task_trainjob=`创建了训练任务 <a href="%s/modelarts/train-job/%s">%s</a>` | |||
task_nputrainjob=`创建了NPU类型训练任务 <a href="%s/modelarts/train-job/%s">%s</a>` | |||
task_inferencejob=`创建了推理任务 <a href="%s/modelarts/inference-job/%s">%s</a>` | |||
task_benchmark=`创建了评测任务 <a href="%s/cloudbrain/benchmark/%s">%s</a>` | |||
task_createmodel=`导入了新模型 <a href="%s/modelmanage/show_model_info?name=%s">%s</a>` | |||
task_gputrainjob=`创建了CPU/GPU类型训练任务 <a href="%s/cloudbrain/train-job/%s">%s</a>` | |||
[tool] | |||
ago=%s前 | |||
@@ -135,7 +135,7 @@ socket.onmessage = function (e) { | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
} | |||
else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30"){ | |||
else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30" || record.OpType == "31"){ | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||
} | |||
@@ -175,6 +175,8 @@ function getTaskLink(record){ | |||
re = re + "/cloudbrain/benchmark/" + record.Content; | |||
}else if(record.OpType == 30){ | |||
re = re + "/modelmanage/show_model_info?name=" + record.RefName; | |||
}else if(record.OpType == 31){ | |||
re = re + "/cloudbrain/train-job/" + record.Content; | |||
} | |||
re = encodeURI(re); | |||
return re; | |||
@@ -321,10 +323,11 @@ var actionNameZH={ | |||
"24":"上传了数据集文件", | |||
"25":"创建了CPU/GPU类型调试任务", | |||
"26":"创建了NPU类型调试任务", | |||
"27":"创建了训练任务", | |||
"27":"创建了NPU类型训练任务", | |||
"28":"创建了推理任务", | |||
"29":"创建了评测任务", | |||
"30":"导入了新模型" | |||
"30":"导入了新模型", | |||
"31":"创建了CPU/GPU类型训练任务" | |||
}; | |||
var actionNameEN={ | |||
@@ -346,10 +349,11 @@ var actionNameEN={ | |||
"24":" upload dataset ", | |||
"25":" created CPU/GPU type debugging task ", | |||
"26":" created NPU type debugging task ", | |||
"27":" created training task", | |||
"27":" created NPU type training task", | |||
"28":" created reasoning task", | |||
"29":" created profiling task", | |||
"30":" created new model" | |||
"30":" created new model", | |||
"31":" created CPU/GPU type training task", | |||
}; | |||
var repoAndOrgZH={ | |||
@@ -620,10 +620,10 @@ function showfilelist(){ | |||
for (var i=0;i<labeltastresult.length;i++){ | |||
var fname = labeltastresult[i].pic_image_field.substring(labeltastresult[i].pic_image_field.lastIndexOf('/') + 1); | |||
console.log(labeltastresult[i]) | |||
//console.log(labeltastresult[i]) | |||
if(labeltastresult[i].pic_image_field.length > 70){ | |||
var tmpIndex = labeltastresult[i].pic_image_field.indexOf("/",70); | |||
console.log(tmpIndex) | |||
//console.log(tmpIndex) | |||
if(tmpIndex != -1){ | |||
fname = labeltastresult[i].pic_image_field.substring(tmpIndex + 1); | |||
fname = fname.substring(fname.indexOf('/')+1); | |||
@@ -679,7 +679,7 @@ function breadFiles(){ | |||
fname_full_path = tableData[fileindex].pic_image_field.substring(tmp_index + 1); | |||
} | |||
var fname_path = fname_full_path.split('/') | |||
console.log(fname_path) | |||
//console.log(fname_path) | |||
// var filename_text = tableData[fileindex].pic_image_field.substring(tableData[fileindex].pic_image_field.lastIndexOf('/')+1) | |||
var html_breadFile = '' | |||
// var source_name = filename_title+'.zip' | |||
@@ -41,7 +41,7 @@ func CloudBrains(ctx *context.Context) { | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
debugType := modelarts.DebugType | |||
debugType := models.TypeCloudBrainAll | |||
if listType == models.GPUResource { | |||
debugType = models.TypeCloudBrainOne | |||
} else if listType == models.NPUResource { | |||
@@ -121,7 +121,7 @@ func DownloadCloudBrains(ctx *context.Context) { | |||
Page: page, | |||
PageSize: 1, | |||
}, | |||
Type: modelarts.DebugType, | |||
Type: models.TypeCloudBrainAll, | |||
NeedRepoInfo: false, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
}) | |||
@@ -151,7 +151,7 @@ func DownloadCloudBrains(ctx *context.Context) { | |||
Page: page, | |||
PageSize: pageSize, | |||
}, | |||
Type: modelarts.DebugType, | |||
Type: models.TypeCloudBrainAll, | |||
NeedRepoInfo: true, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
}) | |||
@@ -62,10 +62,10 @@ import ( | |||
"net/http" | |||
"strings" | |||
"code.gitea.io/gitea/routers/authentication" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/auth" | |||
"code.gitea.io/gitea/modules/cloudbrain" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
@@ -77,6 +77,7 @@ import ( | |||
"code.gitea.io/gitea/routers/api/v1/repo" | |||
_ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation | |||
"code.gitea.io/gitea/routers/api/v1/user" | |||
"code.gitea.io/gitea/routers/authentication" | |||
repo_ext "code.gitea.io/gitea/routers/repo" | |||
"gitea.com/macaron/binding" | |||
@@ -890,6 +891,13 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Group("/cloudbrain", func() { | |||
m.Get("/:id", repo.GetCloudbrainTask) | |||
m.Get("/:id/log", repo.CloudbrainGetLog) | |||
m.Group("/train-job", func() { | |||
m.Group("/:jobid", func() { | |||
m.Get("", repo.GetModelArtsTrainJobVersion) | |||
m.Get("/model_list", repo.CloudBrainModelList) | |||
m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.CloudBrainStop) | |||
}) | |||
}) | |||
}, reqRepoReader(models.UnitTypeCloudBrain)) | |||
m.Group("/modelarts", func() { | |||
m.Group("/notebook", func() { | |||
@@ -6,15 +6,18 @@ | |||
package repo | |||
import ( | |||
"encoding/json" | |||
"net/http" | |||
"sort" | |||
"strings" | |||
"time" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/cloudbrain" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/storage" | |||
routerRepo "code.gitea.io/gitea/routers/repo" | |||
) | |||
// cloudbrain get job task by jobid | |||
@@ -62,7 +65,7 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
log.Error("GetJob failed:", err) | |||
return | |||
} | |||
result, err := models.ConvertToJobResultPayload(jobResult.Payload) | |||
result, _ := models.ConvertToJobResultPayload(jobResult.Payload) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
log.Error("ConvertToJobResultPayload failed:", err) | |||
@@ -70,16 +73,16 @@ func GetCloudbrainTask(ctx *context.APIContext) { | |||
} | |||
job.Status = result.JobStatus.State | |||
taskRoles := result.TaskRoles | |||
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) { | |||
taskRoles := result.TaskRoles | |||
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
job.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
job.Status = taskRes.TaskStatuses[0].State | |||
} | |||
if result.JobStatus.State != string(models.JobWaiting) { | |||
models.ParseAndSetDurationFromCloudBrainOne(result, job) | |||
err = models.UpdateJob(job) | |||
if err != nil { | |||
log.Error("UpdateJob failed:", err) | |||
@@ -152,3 +155,55 @@ func CloudbrainGetLog(ctx *context.Context) { | |||
return | |||
} | |||
func CloudBrainModelList(ctx *context.APIContext) { | |||
var ( | |||
err error | |||
) | |||
var jobID = ctx.Params(":jobid") | |||
var versionName = ctx.Query("version_name") | |||
parentDir := ctx.Query("parentDir") | |||
dirArray := strings.Split(parentDir, "/") | |||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
if err != nil { | |||
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | |||
return | |||
} | |||
//get dirs | |||
dirs, err := routerRepo.GetModelDirs(task.JobName, parentDir) | |||
if err != nil { | |||
log.Error("GetModelDirs failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("GetModelDirs failed:", err) | |||
return | |||
} | |||
var fileInfos []storage.FileInfo | |||
err = json.Unmarshal([]byte(dirs), &fileInfos) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"]) | |||
ctx.ServerError("json.Unmarshal failed:", err) | |||
return | |||
} | |||
for i, fileInfo := range fileInfos { | |||
temp, _ := time.Parse("2006-01-02 15:04:05", fileInfo.ModTime) | |||
fileInfos[i].ModTime = temp.Local().Format("2006-01-02 15:04:05") | |||
} | |||
sort.Slice(fileInfos, func(i, j int) bool { | |||
return fileInfos[i].ModTime > fileInfos[j].ModTime | |||
}) | |||
ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
"JobID": jobID, | |||
"VersionName": versionName, | |||
"StatusOK": 0, | |||
"Path": dirArray, | |||
"Dirs": fileInfos, | |||
"task": task, | |||
"PageIsCloudBrain": true, | |||
}) | |||
} |
@@ -10,13 +10,13 @@ import ( | |||
"strconv" | |||
"strings" | |||
"code.gitea.io/gitea/modules/util" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/cloudbrain" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/modelarts" | |||
"code.gitea.io/gitea/modules/storage" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
routerRepo "code.gitea.io/gitea/routers/repo" | |||
) | |||
@@ -67,8 +67,14 @@ func GetModelArtsNotebook2(ctx *context.APIContext) { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
if job.StartTime == 0 && result.Lease.UpdateTime > 0 { | |||
job.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000) | |||
} | |||
job.Status = result.Status | |||
if job.EndTime == 0 && models.IsModelArtsDebugJobTerminal(job.Status) { | |||
job.EndTime = timeutil.TimeStampNow() | |||
} | |||
job.ComputeAndSetDuration() | |||
err = models.UpdateJob(job) | |||
if err != nil { | |||
log.Error("UpdateJob failed:", err) | |||
@@ -128,26 +134,61 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(job.VersionID, 10)) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
job.Duration = result.Duration | |||
job.TrainJobDuration = result.TrainJobDuration | |||
if job.Type == models.TypeCloudBrainOne { | |||
jobResult, err := cloudbrain.GetJob(job.JobID) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
log.Error("GetJob failed:", err) | |||
return | |||
} | |||
result, err := models.ConvertToJobResultPayload(jobResult.Payload) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
log.Error("ConvertToJobResultPayload failed:", err) | |||
return | |||
} | |||
if result.Duration != 0 { | |||
job.TrainJobDuration = util.AddZero(result.Duration/3600000) + ":" + util.AddZero(result.Duration%3600000/60000) + ":" + util.AddZero(result.Duration%60000/1000) | |||
job.Status = result.JobStatus.State | |||
if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) { | |||
taskRoles := result.TaskRoles | |||
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
job.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
job.Status = taskRes.TaskStatuses[0].State | |||
} | |||
if result.JobStatus.State != string(models.JobWaiting) { | |||
err = models.UpdateJob(job) | |||
if err != nil { | |||
log.Error("UpdateJob failed:", err) | |||
} | |||
} | |||
} else { | |||
job.TrainJobDuration = "00:00:00" | |||
} | |||
result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(job.VersionID, 10)) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
err = models.UpdateTrainJobVersion(job) | |||
if err != nil { | |||
log.Error("UpdateJob failed:", err) | |||
if job.StartTime == 0 && result.StartTime > 0 { | |||
job.StartTime = timeutil.TimeStamp(result.StartTime / 1000) | |||
} | |||
job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
job.Duration = result.Duration / 1000 | |||
job.TrainJobDuration = result.TrainJobDuration | |||
job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | |||
if job.EndTime == 0 && models.IsTrainJobTerminal(job.Status) && job.StartTime > 0 { | |||
job.EndTime = job.StartTime.Add(job.Duration) | |||
} | |||
err = models.UpdateTrainJobVersion(job) | |||
if err != nil { | |||
log.Error("UpdateJob failed:", err) | |||
} | |||
} | |||
ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
@@ -366,16 +407,15 @@ func GetModelArtsInferenceJob(ctx *context.APIContext) { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
if job.StartTime == 0 && result.StartTime > 0 { | |||
job.StartTime = timeutil.TimeStamp(result.StartTime / 1000) | |||
} | |||
job.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
job.Duration = result.Duration | |||
job.TrainJobDuration = result.TrainJobDuration | |||
job.Duration = result.Duration / 1000 | |||
job.TrainJobDuration = models.ConvertDurationToStr(job.Duration) | |||
if result.Duration != 0 { | |||
job.TrainJobDuration = util.AddZero(result.Duration/3600000) + ":" + util.AddZero(result.Duration%3600000/60000) + ":" + util.AddZero(result.Duration%60000/1000) | |||
} else { | |||
job.TrainJobDuration = "00:00:00" | |||
if job.EndTime == 0 && models.IsTrainJobTerminal(job.Status) && job.StartTime > 0 { | |||
job.EndTime = job.StartTime.Add(job.Duration) | |||
} | |||
err = models.UpdateInferenceJob(job) | |||
@@ -274,10 +274,11 @@ func ExploreDatasets(ctx *context.Context) { | |||
// ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | |||
var ( | |||
datasets []*models.Dataset | |||
count int64 | |||
err error | |||
orderBy models.SearchOrderBy | |||
datasets []*models.Dataset | |||
datasetsWithStar []*models.DatasetWithStar | |||
count int64 | |||
err error | |||
orderBy models.SearchOrderBy | |||
) | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
@@ -301,6 +302,10 @@ func ExploreDatasets(ctx *context.Context) { | |||
orderBy = models.SearchOrderBySizeReverse | |||
case "downloadtimes": | |||
orderBy = models.SearchOrderByDownloadTimes | |||
case "moststars": | |||
orderBy = models.SearchOrderByStarsReverse | |||
case "feweststars": | |||
orderBy = models.SearchOrderByStars | |||
default: | |||
ctx.Data["SortType"] = "recentupdate" | |||
orderBy = models.SearchOrderByRecentUpdated | |||
@@ -308,6 +313,9 @@ func ExploreDatasets(ctx *context.Context) { | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
category := ctx.Query("category") | |||
task := ctx.Query("task") | |||
license := ctx.Query("license") | |||
var ownerID int64 | |||
if ctx.User != nil && !ctx.User.IsAdmin { | |||
ownerID = ctx.User.ID | |||
@@ -316,25 +324,40 @@ func ExploreDatasets(ctx *context.Context) { | |||
Keyword: keyword, | |||
IncludePublic: true, | |||
SearchOrderBy: orderBy, | |||
Category: category, | |||
Task: task, | |||
License: license, | |||
OwnerID: ownerID, | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.ExplorePagingNum, | |||
PageSize: 30, | |||
}, | |||
} | |||
datasets, count, err = models.SearchDataset(opts) | |||
if err != nil { | |||
ctx.ServerError("SearchDatasets", err) | |||
return | |||
} | |||
for _, dataset := range datasets { | |||
if !ctx.IsSigned { | |||
datasetsWithStar = append(datasetsWithStar, &models.DatasetWithStar{Dataset: *dataset, IsStaring: false}) | |||
} else { | |||
datasetsWithStar = append(datasetsWithStar, &models.DatasetWithStar{Dataset: *dataset, IsStaring: models.IsDatasetStaring(ctx.User.ID, dataset.ID)}) | |||
} | |||
} | |||
pager := context.NewPagination(int(count), opts.PageSize, page, 5) | |||
ctx.Data["Keyword"] = opts.Keyword | |||
ctx.Data["Category"] = category | |||
ctx.Data["Task"] = task | |||
ctx.Data["License"] = license | |||
pager.SetDefaultParams(ctx) | |||
ctx.Data["Page"] = pager | |||
ctx.Data["Datasets"] = datasets | |||
ctx.Data["Datasets"] = datasetsWithStar | |||
ctx.Data["Total"] = count | |||
ctx.Data["PageIsDatasets"] = true | |||
ctx.HTML(200, tplExploreDataset) | |||
@@ -71,6 +71,8 @@ func NewServices() { | |||
log.Info("decompression.NewContext() succeed.") | |||
labelmsg.Init() | |||
log.Info("labelmsg.Init() succeed.") | |||
InitESClient() | |||
log.Info("ES Client succeed.") | |||
} | |||
// In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology | |||
@@ -6,6 +6,7 @@ | |||
package private | |||
import ( | |||
"code.gitea.io/gitea/routers/repo" | |||
"strings" | |||
"code.gitea.io/gitea/modules/log" | |||
@@ -45,6 +46,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | |||
m.Post("/tool/repo_stat/:date", RepoStatisticManually) | |||
m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | |||
m.Post("/task/history_handle/duration", repo.HandleTaskWithNoDuration) | |||
}, CheckInternalToken) | |||
} |
@@ -15,6 +15,10 @@ import ( | |||
"strconv" | |||
"strings" | |||
"code.gitea.io/gitea/modules/auth" | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/labelmsg" | |||
@@ -30,8 +34,10 @@ import ( | |||
const ( | |||
//result of decompress | |||
DecompressSuccess = "0" | |||
DecompressFailed = "1" | |||
DecompressSuccess = "0" | |||
DecompressFailed = "1" | |||
tplAttachmentUpload base.TplName = "repo/attachment/upload" | |||
tplAttachmentEdit base.TplName = "repo/attachment/edit" | |||
) | |||
type CloudBrainDataset struct { | |||
@@ -63,6 +69,40 @@ func renderAttachmentSettings(ctx *context.Context) { | |||
ctx.Data["AttachmentMaxFiles"] = setting.Attachment.MaxFiles | |||
} | |||
func UploadAttachmentUI(ctx *context.Context) { | |||
ctx.Data["datasetId"] = ctx.Query("datasetId") | |||
ctx.Data["PageIsDataset"] = true | |||
ctx.HTML(200, tplAttachmentUpload) | |||
} | |||
func EditAttachmentUI(ctx *context.Context) { | |||
id, _ := strconv.ParseInt(ctx.Params(":id"), 10, 64) | |||
ctx.Data["PageIsDataset"] = true | |||
attachment, _ := models.GetAttachmentByID(id) | |||
if attachment == nil { | |||
ctx.Error(404, "The attachment does not exits.") | |||
} | |||
ctx.Data["Attachment"] = attachment | |||
ctx.HTML(200, tplAttachmentEdit) | |||
} | |||
func EditAttachment(ctx *context.Context, form auth.EditAttachmentForm) { | |||
err := models.UpdateAttachmentDescription(&models.Attachment{ | |||
ID: form.ID, | |||
Description: form.Description, | |||
}) | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.edit_attachment_fail"))) | |||
} | |||
ctx.JSON(http.StatusOK, models.BaseOKMessage) | |||
} | |||
// UploadAttachment response for uploading issue's attachment | |||
func UploadAttachment(ctx *context.Context) { | |||
if !setting.Attachment.Enabled { | |||
@@ -241,14 +281,20 @@ func GetAttachment(ctx *context.Context) { | |||
} | |||
if dataSet != nil { | |||
isPermit, err := models.GetUserDataSetPermission(dataSet, ctx.User) | |||
if err != nil { | |||
ctx.Error(http.StatusInternalServerError, "GetUserDataSetPermission", err.Error()) | |||
return | |||
} | |||
if !isPermit { | |||
ctx.Error(http.StatusNotFound) | |||
if !ctx.IsSigned { | |||
ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL) | |||
ctx.Redirect(setting.AppSubURL + "/user/login") | |||
return | |||
} else { | |||
isPermit, err := models.GetUserDataSetPermission(dataSet, ctx.User) | |||
if err != nil { | |||
ctx.Error(http.StatusInternalServerError, "GetUserDataSetPermission", err.Error()) | |||
return | |||
} | |||
if !isPermit { | |||
ctx.Error(http.StatusNotFound) | |||
return | |||
} | |||
} | |||
} | |||
@@ -387,11 +433,17 @@ func AddAttachment(ctx *context.Context) { | |||
ctx.Error(404, "attachment has not been uploaded") | |||
return | |||
} | |||
datasetId := ctx.QueryInt64("dataset_id") | |||
dataset, err := models.GetDatasetByID(datasetId) | |||
if err != nil { | |||
ctx.Error(404, "dataset does not exist.") | |||
return | |||
} | |||
attachment, err := models.InsertAttachment(&models.Attachment{ | |||
UUID: uuid, | |||
UploaderID: ctx.User.ID, | |||
IsPrivate: true, | |||
IsPrivate: dataset.IsPrivate(), | |||
Name: fileName, | |||
Size: ctx.QueryInt64("size"), | |||
DatasetID: ctx.QueryInt64("dataset_id"), | |||
@@ -798,6 +850,9 @@ func CompleteMultipart(ctx *context.Context) { | |||
typeCloudBrain := ctx.QueryInt("type") | |||
fileName := ctx.Query("file_name") | |||
log.Warn("uuid:" + uuid) | |||
log.Warn("typeCloudBrain:" + strconv.Itoa(typeCloudBrain)) | |||
err := checkTypeCloudBrain(typeCloudBrain) | |||
if err != nil { | |||
ctx.ServerError("checkTypeCloudBrain failed", err) | |||
@@ -835,22 +890,24 @@ func CompleteMultipart(ctx *context.Context) { | |||
ctx.Error(500, fmt.Sprintf("UpdateFileChunk: %v", err)) | |||
return | |||
} | |||
dataset, _ := models.GetDatasetByID(ctx.QueryInt64("dataset_id")) | |||
log.Warn("insert attachment to datasetId:" + strconv.FormatInt(dataset.ID, 10)) | |||
attachment, err := models.InsertAttachment(&models.Attachment{ | |||
UUID: uuid, | |||
UploaderID: ctx.User.ID, | |||
IsPrivate: true, | |||
Name: fileName, | |||
Size: ctx.QueryInt64("size"), | |||
DatasetID: ctx.QueryInt64("dataset_id"), | |||
Type: typeCloudBrain, | |||
UUID: uuid, | |||
UploaderID: ctx.User.ID, | |||
IsPrivate: dataset.IsPrivate(), | |||
Name: fileName, | |||
Size: ctx.QueryInt64("size"), | |||
DatasetID: ctx.QueryInt64("dataset_id"), | |||
Description: ctx.Query("description"), | |||
Type: typeCloudBrain, | |||
}) | |||
if err != nil { | |||
ctx.Error(500, fmt.Sprintf("InsertAttachment: %v", err)) | |||
return | |||
} | |||
dataset, _ := models.GetDatasetByID(attachment.DatasetID) | |||
repository, _ := models.GetRepositoryByID(dataset.RepoID) | |||
notification.NotifyOtherTask(ctx.User, repository, fmt.Sprint(attachment.Type), attachment.Name, models.ActionUploadAttachment) | |||
@@ -2,6 +2,7 @@ package repo | |||
import ( | |||
"bufio" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
@@ -36,6 +37,9 @@ const ( | |||
tplCloudBrainBenchmarkIndex base.TplName = "repo/cloudbrain/benchmark/index" | |||
tplCloudBrainBenchmarkNew base.TplName = "repo/cloudbrain/benchmark/new" | |||
tplCloudBrainBenchmarkShow base.TplName = "repo/cloudbrain/benchmark/show" | |||
tplCloudBrainTrainJobNew base.TplName = "repo/cloudbrain/trainjob/new" | |||
tplCloudBrainTrainJobShow base.TplName = "repo/cloudbrain/trainjob/show" | |||
) | |||
var ( | |||
@@ -44,6 +48,7 @@ var ( | |||
benchmarkTypes *models.BenchmarkTypes | |||
benchmarkGpuInfos *models.GpuInfos | |||
benchmarkResourceSpecs *models.ResourceSpecs | |||
trainGpuInfos *models.GpuInfos | |||
) | |||
const BENCHMARK_TYPE_CODE = "repo.cloudbrain.benchmark.types" | |||
@@ -142,6 +147,11 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { | |||
} | |||
ctx.Data["gpu_types"] = gpuInfos.GpuInfo | |||
if trainGpuInfos == nil { | |||
json.Unmarshal([]byte(setting.TrainGpuTypes), &trainGpuInfos) | |||
} | |||
ctx.Data["train_gpu_types"] = trainGpuInfos.GpuInfo | |||
if benchmarkGpuInfos == nil { | |||
json.Unmarshal([]byte(setting.BenchmarkGpuTypes), &benchmarkGpuInfos) | |||
} | |||
@@ -156,12 +166,22 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { | |||
json.Unmarshal([]byte(setting.ResourceSpecs), &cloudbrain.ResourceSpecs) | |||
} | |||
ctx.Data["resource_specs"] = cloudbrain.ResourceSpecs.ResourceSpec | |||
if cloudbrain.TrainResourceSpecs == nil { | |||
json.Unmarshal([]byte(setting.TrainResourceSpecs), &cloudbrain.TrainResourceSpecs) | |||
} | |||
ctx.Data["train_resource_specs"] = cloudbrain.TrainResourceSpecs.ResourceSpec | |||
ctx.Data["params"] = "" | |||
ctx.Data["branchName"] = ctx.Repo.BranchName | |||
ctx.Data["snn4imagenet_path"] = cloudbrain.Snn4imagenetMountPath | |||
ctx.Data["is_snn4imagenet_enabled"] = setting.IsSnn4imagenetEnabled | |||
ctx.Data["brainscore_path"] = cloudbrain.BrainScoreMountPath | |||
ctx.Data["is_brainscore_enabled"] = setting.IsBrainScoreEnabled | |||
ctx.Data["cloudbraintype"] = models.TypeCloudBrainOne | |||
return nil | |||
} | |||
@@ -181,38 +201,52 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
image := form.Image | |||
uuid := form.Attachment | |||
jobType := form.JobType | |||
command := cloudbrain.Command | |||
gpuQueue := form.GpuType | |||
codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath | |||
resourceSpecId := form.ResourceSpecId | |||
branchName := form.BranchName | |||
repo := ctx.Repo.Repository | |||
tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName) | |||
tpl := tplCloudBrainNew | |||
command := cloudbrain.Command | |||
if jobType == string(models.JobTypeTrain) { | |||
tpl = tplCloudBrainTrainJobNew | |||
commandTrain, err := getTrainJobCommand(form) | |||
if err != nil { | |||
log.Error("getTrainJobCommand failed: %v", err) | |||
ctx.RenderWithErr(err.Error(), tpl, &form) | |||
return | |||
} | |||
command = commandTrain | |||
} | |||
tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) | |||
if err == nil { | |||
if len(tasks) != 0 { | |||
log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("the job name did already exist", tplCloudBrainNew, &form) | |||
ctx.RenderWithErr("the job name did already exist", tpl, &form) | |||
return | |||
} | |||
} else { | |||
if !models.IsErrJobNotExist(err) { | |||
log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
ctx.RenderWithErr("system error", tpl, &form) | |||
return | |||
} | |||
} | |||
if !jobNamePattern.MatchString(displayJobName) { | |||
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainNew, &form) | |||
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) | |||
return | |||
} | |||
if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) { | |||
if jobType != string(models.JobTypeBenchmark) && jobType != string(models.JobTypeDebug) && jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) && jobType != string(models.JobTypeTrain) { | |||
log.Error("jobtype error:", jobType, ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("jobtype error", tplCloudBrainNew, &form) | |||
ctx.RenderWithErr("jobtype error", tpl, &form) | |||
return | |||
} | |||
@@ -220,18 +254,21 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
if err != nil { | |||
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("system error", tplCloudBrainNew, &form) | |||
ctx.RenderWithErr("system error", tpl, &form) | |||
return | |||
} else { | |||
if count >= 1 { | |||
log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplCloudBrainNew, &form) | |||
ctx.RenderWithErr("you have already a running or waiting task, can not create more", tpl, &form) | |||
return | |||
} | |||
} | |||
downloadCode(repo, codePath) | |||
if branchName == "" { | |||
branchName = cloudbrain.DefaultBranchName | |||
} | |||
downloadCode(repo, codePath, branchName) | |||
uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") | |||
modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" | |||
@@ -265,15 +302,19 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||
err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, | |||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params, | |||
0, 0, resourceSpecId) | |||
if err != nil { | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | |||
ctx.RenderWithErr(err.Error(), tpl, &form) | |||
return | |||
} | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
if jobType == string(models.JobTypeTrain) { | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=all") | |||
} else { | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
} | |||
} | |||
func CloudBrainRestart(ctx *context.Context) { | |||
@@ -339,18 +380,29 @@ func CloudBrainRestart(ctx *context.Context) { | |||
} | |||
func CloudBrainBenchMarkShow(ctx *context.Context) { | |||
cloudBrainShow(ctx, tplCloudBrainBenchmarkShow) | |||
cloudBrainShow(ctx, tplCloudBrainBenchmarkShow, models.JobTypeBenchmark) | |||
} | |||
func CloudBrainShow(ctx *context.Context) { | |||
cloudBrainShow(ctx, tplCloudBrainShow) | |||
cloudBrainShow(ctx, tplCloudBrainShow, models.JobTypeDebug) | |||
} | |||
func CloudBrainTrainJobShow(ctx *context.Context) { | |||
cloudBrainShow(ctx, tplCloudBrainTrainJobShow, models.JobTypeTrain) | |||
} | |||
func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.JobType) { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
var ID = ctx.Params(":id") | |||
debugListType := ctx.Query("debugListType") | |||
task, err := models.GetCloudbrainByID(ID) | |||
var task *models.Cloudbrain | |||
var err error | |||
if jobType == models.JobTypeTrain { | |||
task, err = models.GetCloudbrainByJobID(ctx.Params(":jobid")) | |||
} else { | |||
task, err = models.GetCloudbrainByID(ctx.Params(":id")) | |||
} | |||
if err != nil { | |||
log.Info("error:" + err.Error()) | |||
ctx.Data["error"] = err.Error() | |||
@@ -365,6 +417,16 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
jobRes.Resource.Memory = strings.ReplaceAll(jobRes.Resource.Memory, "Mi", "MB") | |||
spec := "GPU数:" + strconv.Itoa(jobRes.Resource.NvidiaComGpu) + ",CPU数:" + strconv.Itoa(jobRes.Resource.CPU) + ",内存(MB):" + jobRes.Resource.Memory | |||
ctx.Data["resource_spec"] = spec | |||
if task.JobType == string(models.JobTypeTrain) { | |||
if trainGpuInfos == nil { | |||
json.Unmarshal([]byte(setting.TrainGpuTypes), &trainGpuInfos) | |||
} | |||
for _, resourceType := range trainGpuInfos.GpuInfo { | |||
if resourceType.Queue == jobRes.Config.GpuType { | |||
ctx.Data["resource_type"] = resourceType.Value | |||
} | |||
} | |||
} | |||
taskRoles := jobRes.TaskRoles | |||
if jobRes.JobStatus.State != string(models.JobFailed) { | |||
@@ -373,6 +435,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
task.Status = taskRes.TaskStatuses[0].State | |||
task.ContainerID = taskRes.TaskStatuses[0].ContainerID | |||
task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP | |||
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
ctx.Data["error"] = err.Error() | |||
@@ -398,12 +461,6 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
task.User = user | |||
} | |||
var duration int64 | |||
if task.Status == string(models.JobRunning) { | |||
duration = time.Now().Unix() - int64(task.CreatedUnix) | |||
} else { | |||
duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix) | |||
} | |||
if task.BenchmarkTypeID > 0 { | |||
for _, benchmarkType := range GetBenchmarkTypes(ctx).BenchmarkType { | |||
if task.BenchmarkTypeID == benchmarkType.Id { | |||
@@ -418,8 +475,42 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
} | |||
} | |||
} | |||
if task.TrainJobDuration == "" { | |||
if task.Duration == 0 { | |||
var duration int64 | |||
if task.Status == string(models.JobRunning) { | |||
duration = time.Now().Unix() - int64(task.CreatedUnix) | |||
} else { | |||
duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix) | |||
} | |||
task.Duration = duration | |||
} | |||
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
} | |||
ctx.Data["duration"] = task.TrainJobDuration | |||
if len(task.Parameters) > 0 { | |||
var parameters models.Parameters | |||
err := json.Unmarshal([]byte(task.Parameters), ¶meters) | |||
if err != nil { | |||
log.Error("Failed to Unmarshal Parameters: %s (%v)", task.Parameters, err) | |||
task.Parameters = "" | |||
} else { | |||
if len(parameters.Parameter) > 0 { | |||
paramTemp := "" | |||
for _, Parameter := range parameters.Parameter { | |||
param := Parameter.Label + " = " + Parameter.Value + "; " | |||
paramTemp = paramTemp + param | |||
} | |||
task.Parameters = paramTemp[:len(paramTemp)-2] | |||
} else { | |||
task.Parameters = "" | |||
} | |||
} | |||
} | |||
ctx.Data["duration"] = util.AddZero(duration/3600000) + ":" + util.AddZero(duration%3600000/60000) + ":" + util.AddZero(duration%60000/1000) | |||
ctx.Data["task"] = task | |||
ctx.Data["jobName"] = task.JobName | |||
ctx.Data["displayJobName"] = task.DisplayJobName | |||
@@ -427,6 +518,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||
version_list_task = append(version_list_task, task) | |||
ctx.Data["version_list_task"] = version_list_task | |||
ctx.Data["debugListType"] = debugListType | |||
ctx.Data["canDownload"] = cloudbrain.CanDeleteJob(ctx, task) | |||
ctx.HTML(200, tpName) | |||
} | |||
@@ -482,6 +574,10 @@ func CloudBrainStop(ctx *context.Context) { | |||
} | |||
task.Status = string(models.JobStopped) | |||
if task.EndTime == 0 { | |||
task.EndTime = timeutil.TimeStampNow() | |||
} | |||
task.ComputeAndSetDuration() | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||
@@ -494,11 +590,12 @@ func CloudBrainStop(ctx *context.Context) { | |||
break | |||
} | |||
ctx.JSON(200, map[string]string{ | |||
ctx.JSON(200, map[string]interface{}{ | |||
"result_code": resultCode, | |||
"error_msg": errorMsg, | |||
"status": status, | |||
"id": ID, | |||
"StatusOK": 0, | |||
}) | |||
} | |||
@@ -575,6 +672,10 @@ func logErrorAndUpdateJobStatus(err error, taskInfo *models.Cloudbrain) { | |||
log.Warn("Failed to stop cloudBrain job:"+taskInfo.JobID, err) | |||
} else { | |||
taskInfo.Status = string(models.JobStopped) | |||
if taskInfo.EndTime == 0 { | |||
taskInfo.EndTime = timeutil.TimeStampNow() | |||
} | |||
taskInfo.ComputeAndSetDuration() | |||
err = models.UpdateJob(taskInfo) | |||
if err != nil { | |||
log.Warn("UpdateJob failed", err) | |||
@@ -746,8 +847,8 @@ func GetRate(ctx *context.Context) { | |||
} | |||
} | |||
func downloadCode(repo *models.Repository, codePath string) error { | |||
if err := git.Clone(repo.RepoPath(), codePath, git.CloneRepoOptions{}); err != nil { | |||
func downloadCode(repo *models.Repository, codePath, branchName string) error { | |||
if err := git.Clone(repo.RepoPath(), codePath, git.CloneRepoOptions{Branch: branchName}); err != nil { | |||
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err) | |||
return err | |||
} | |||
@@ -945,7 +1046,7 @@ func SyncCloudbrainStatus() { | |||
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
task.Status = taskRes.TaskStatuses[0].State | |||
if task.Status != string(models.JobWaiting) { | |||
task.Duration = time.Now().Unix() - taskRes.TaskStatuses[0].StartAt.Unix() | |||
models.ParseAndSetDurationFromCloudBrainOne(jobRes, task) | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
@@ -966,6 +1067,10 @@ func SyncCloudbrainStatus() { | |||
continue | |||
} | |||
task.Status = string(models.JobStopped) | |||
if task.EndTime == 0 { | |||
task.EndTime = timeutil.TimeStampNow() | |||
} | |||
task.ComputeAndSetDuration() | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
@@ -984,14 +1089,20 @@ func SyncCloudbrainStatus() { | |||
if result != nil { | |||
task.Status = result.Status | |||
if task.StartTime == 0 && result.Lease.UpdateTime > 0 { | |||
task.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000) | |||
} | |||
if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) { | |||
task.EndTime = timeutil.TimeStampNow() | |||
} | |||
task.ComputeAndSetDuration() | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
continue | |||
} | |||
} | |||
} else if task.JobType == string(models.JobTypeTrain) { | |||
} else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) { | |||
result, err := modelarts.GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10)) | |||
if err != nil { | |||
log.Error("GetTrainJob(%s) failed:%v", task.JobName, err) | |||
@@ -1000,16 +1111,160 @@ func SyncCloudbrainStatus() { | |||
if result != nil { | |||
task.Status = modelarts.TransTrainJobStatus(result.IntStatus) | |||
task.Duration = result.Duration | |||
task.Duration = result.Duration / 1000 | |||
task.TrainJobDuration = result.TrainJobDuration | |||
if result.Duration != 0 { | |||
task.TrainJobDuration = util.AddZero(result.Duration/3600000) + ":" + util.AddZero(result.Duration%3600000/60000) + ":" + util.AddZero(result.Duration%60000/1000) | |||
if task.StartTime == 0 && result.StartTime > 0 { | |||
task.StartTime = timeutil.TimeStamp(result.StartTime / 1000) | |||
} | |||
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
if task.EndTime == 0 && models.IsTrainJobTerminal(task.Status) && task.StartTime > 0 { | |||
task.EndTime = task.StartTime.Add(task.Duration) | |||
} | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
continue | |||
} | |||
} | |||
} else { | |||
log.Error("task.JobType(%s) is error:%s", task.JobName, task.JobType) | |||
} | |||
} else { | |||
log.Error("task.Type(%s) is error:%d", task.JobName, task.Type) | |||
} | |||
} | |||
return | |||
} | |||
func HandleTaskWithNoDuration(ctx *context.Context) { | |||
log.Info("HandleTaskWithNoDuration start") | |||
count := 0 | |||
start := time.Now().Unix() | |||
for { | |||
cloudBrains, err := models.GetStoppedJobWithNoDurationJob() | |||
if err != nil { | |||
log.Error("HandleTaskWithNoTrainJobDuration failed:", err.Error()) | |||
break | |||
} | |||
if len(cloudBrains) == 0 { | |||
log.Info("HandleTaskWithNoTrainJobDuration:no task need handle") | |||
break | |||
} | |||
handleNoDurationTask(cloudBrains) | |||
count += len(cloudBrains) | |||
if len(cloudBrains) < 100 { | |||
log.Info("HandleTaskWithNoTrainJobDuration:task less than 100") | |||
break | |||
} | |||
if time.Now().Unix()-start > 600 { | |||
log.Info("HandleTaskWithNoDuration : time out") | |||
ctx.JSON(200, fmt.Sprintf("task stop for time out,count=%d", count)) | |||
return | |||
} | |||
} | |||
log.Info("HandleTaskWithNoTrainJobDuration:count=%d", count) | |||
ctx.JSON(200, fmt.Sprintf("success,count=%d", count)) | |||
} | |||
func handleNoDurationTask(cloudBrains []*models.Cloudbrain) { | |||
for _, task := range cloudBrains { | |||
time.Sleep(time.Millisecond * 100) | |||
log.Info("Handle job ,%+v", task) | |||
if task.Type == models.TypeCloudBrainOne { | |||
result, err := cloudbrain.GetJob(task.JobID) | |||
if err != nil { | |||
log.Error("GetJob(%s) failed:%v", task.JobName, err) | |||
updateDefaultDuration(task) | |||
continue | |||
} | |||
if result != nil { | |||
if result.Msg != "success" { | |||
updateDefaultDuration(task) | |||
continue | |||
} | |||
jobRes, err := models.ConvertToJobResultPayload(result.Payload) | |||
if err != nil || len(jobRes.TaskRoles) == 0 { | |||
updateDefaultDuration(task) | |||
continue | |||
} | |||
taskRoles := jobRes.TaskRoles | |||
taskRes, err := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | |||
if err != nil || len(taskRes.TaskStatuses) == 0 { | |||
updateDefaultDuration(task) | |||
continue | |||
} | |||
task.Status = taskRes.TaskStatuses[0].State | |||
log.Info("task startTime = %v endTime= %v ,jobId=%d", jobRes.JobStatus.StartTime, jobRes.JobStatus.EndTime, task.ID) | |||
if jobRes.JobStatus.CreatedTime > 0 { | |||
task.StartTime = timeutil.TimeStamp(jobRes.JobStatus.CreatedTime / 1000) | |||
if jobRes.JobStatus.CompletedTime > 0 { | |||
task.EndTime = timeutil.TimeStamp(jobRes.JobStatus.CompletedTime / 1000) | |||
} else { | |||
task.TrainJobDuration = "00:00:00" | |||
task.EndTime = task.UpdatedUnix | |||
} | |||
} else { | |||
task.StartTime = 0 | |||
task.EndTime = 0 | |||
} | |||
if task.EndTime < task.StartTime { | |||
log.Info("endTime[%v] is less than starTime[%v],jobId=%d", task.EndTime, task.StartTime, task.ID) | |||
st := task.StartTime | |||
task.StartTime = task.EndTime | |||
task.EndTime = st | |||
} | |||
task.Duration = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() | |||
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
} | |||
} | |||
} else if task.Type == models.TypeCloudBrainTwo { | |||
if task.JobType == string(models.JobTypeDebug) { | |||
//result, err := modelarts.GetJob(task.JobID) | |||
result, err := modelarts.GetNotebook2(task.JobID) | |||
if err != nil { | |||
log.Error("GetJob(%s) failed:%v", task.JobName, err) | |||
updateDefaultDuration(task) | |||
continue | |||
} | |||
if result != nil { | |||
task.Status = result.Status | |||
startTime := result.Lease.CreateTime | |||
duration := result.Lease.Duration / 1000 | |||
if startTime > 0 { | |||
task.StartTime = timeutil.TimeStamp(startTime / 1000) | |||
task.EndTime = task.StartTime.Add(duration) | |||
} | |||
task.ComputeAndSetDuration() | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
continue | |||
} | |||
} | |||
} else if task.JobType == string(models.JobTypeTrain) || task.JobType == string(models.JobTypeInference) { | |||
result, err := modelarts.GetTrainJob(task.JobID, strconv.FormatInt(task.VersionID, 10)) | |||
if err != nil { | |||
log.Error("GetTrainJob(%s) failed:%v", task.JobName, err) | |||
updateDefaultDuration(task) | |||
continue | |||
} | |||
if result != nil { | |||
startTime := result.StartTime / 1000 | |||
if startTime > 0 { | |||
task.StartTime = timeutil.TimeStamp(startTime) | |||
task.EndTime = task.StartTime.Add(result.Duration / 1000) | |||
} | |||
task.ComputeAndSetDuration() | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
@@ -1024,8 +1279,17 @@ func SyncCloudbrainStatus() { | |||
log.Error("task.Type(%s) is error:%d", task.JobName, task.Type) | |||
} | |||
} | |||
} | |||
return | |||
func updateDefaultDuration(task *models.Cloudbrain) { | |||
log.Info("updateDefaultDuration: taskId=%d", task.ID) | |||
task.StartTime = task.CreatedUnix | |||
task.EndTime = task.UpdatedUnix | |||
task.ComputeAndSetDuration() | |||
err := models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||
} | |||
} | |||
func CloudBrainBenchmarkIndex(ctx *context.Context) { | |||
@@ -1055,13 +1319,19 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) { | |||
for i, task := range ciTasks { | |||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||
var duration int64 | |||
if task.Status == string(models.JobRunning) { | |||
duration = time.Now().Unix() - int64(task.Cloudbrain.CreatedUnix) | |||
} else { | |||
duration = int64(task.Cloudbrain.UpdatedUnix) - int64(task.Cloudbrain.CreatedUnix) | |||
if ciTasks[i].TrainJobDuration == "" { | |||
if ciTasks[i].Duration == 0 { | |||
var duration int64 | |||
if task.Status == string(models.JobRunning) { | |||
duration = time.Now().Unix() - int64(task.Cloudbrain.CreatedUnix) | |||
} else { | |||
duration = int64(task.Cloudbrain.UpdatedUnix) - int64(task.Cloudbrain.CreatedUnix) | |||
} | |||
ciTasks[i].Duration = duration | |||
} | |||
ciTasks[i].TrainJobDuration = models.ConvertDurationToStr(ciTasks[i].Duration) | |||
} | |||
ciTasks[i].TrainJobDuration = util.AddZero(duration/3600000) + ":" + util.AddZero(duration%3600000/60000) + ":" + util.AddZero(duration%60000/1000) | |||
ciTasks[i].BenchmarkTypeName = "" | |||
if task.BenchmarkTypeID > 0 { | |||
for _, benchmarkType := range GetBenchmarkTypes(ctx).BenchmarkType { | |||
@@ -1278,7 +1548,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
} | |||
os.RemoveAll(codePath) | |||
if err := downloadCode(repo, codePath); err != nil { | |||
if err := downloadCode(repo, codePath, cloudbrain.DefaultBranchName); err != nil { | |||
log.Error("downloadCode failed, %v", err, ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("system error", tplCloudBrainBenchmarkNew, &form) | |||
@@ -1343,7 +1613,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||
err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, childInfo.Attachment, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, | |||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, cloudbrain.DefaultBranchName, "", "", | |||
benchmarkTypeID, benchmarkChildTypeID, resourceSpecId) | |||
if err != nil { | |||
cloudBrainNewDataPrepare(ctx) | |||
@@ -1369,10 +1639,66 @@ func BenchmarkDel(ctx *context.Context) { | |||
} | |||
} | |||
func CloudBrainTrainJobNew(ctx *context.Context) { | |||
err := cloudBrainNewDataPrepare(ctx) | |||
if err != nil { | |||
ctx.ServerError("get new train-job info failed", err) | |||
return | |||
} | |||
ctx.HTML(http.StatusOK, tplCloudBrainTrainJobNew) | |||
} | |||
func getTrainJobCommand(form auth.CreateCloudBrainForm) (string, error) { | |||
var command string | |||
bootFile := form.BootFile | |||
params := form.Params | |||
if !strings.HasSuffix(bootFile, ".py") { | |||
log.Error("bootFile(%s) format error", bootFile) | |||
return command, errors.New("bootFile format error") | |||
} | |||
var parameters models.Parameters | |||
var param string | |||
if len(params) != 0 { | |||
err := json.Unmarshal([]byte(params), ¶meters) | |||
if err != nil { | |||
log.Error("Failed to Unmarshal params: %s (%v)", params, err) | |||
return command, err | |||
} | |||
for _, parameter := range parameters.Parameter { | |||
param += " --" + parameter.Label + "=" + parameter.Value | |||
} | |||
} | |||
command += "python /code/" + bootFile + param + " > " + cloudbrain.ModelMountPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile | |||
return command, nil | |||
} | |||
func CloudBrainTrainJobDel(ctx *context.Context) { | |||
var listType = ctx.Query("listType") | |||
if err := deleteCloudbrainJob(ctx); err != nil { | |||
log.Error("deleteCloudbrainJob failed: %v", err, ctx.Data["msgID"]) | |||
ctx.ServerError(err.Error(), err) | |||
return | |||
} | |||
var isAdminPage = ctx.Query("isadminpage") | |||
if ctx.IsUserSiteAdmin() && isAdminPage == "true" { | |||
ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") | |||
} else { | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=" + listType) | |||
} | |||
} | |||
func GetBenchmarkTypes(ctx *context.Context) *models.BenchmarkTypes { | |||
var lang = ctx.Locale.Language() | |||
if benchmarkTypesMap[lang] == nil { | |||
var val = i18n.Tr(lang, BENCHMARK_TYPE_CODE) | |||
//use config | |||
val = setting.BenchmarkTypes | |||
var tempType *models.BenchmarkTypes | |||
if err := json.Unmarshal([]byte(val), &tempType); err != nil { | |||
log.Error("json.Unmarshal BenchmarkTypes(%s) failed:%v", val, err, ctx.Data["MsgID"]) | |||
@@ -1,7 +1,14 @@ | |||
package repo | |||
import ( | |||
"encoding/json" | |||
"fmt" | |||
"net/http" | |||
"regexp" | |||
"sort" | |||
"strconv" | |||
"strings" | |||
"unicode/utf8" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/auth" | |||
@@ -12,9 +19,14 @@ import ( | |||
) | |||
const ( | |||
tplIndex base.TplName = "repo/datasets/index" | |||
tplIndex base.TplName = "repo/datasets/index" | |||
tplDatasetCreate base.TplName = "repo/datasets/create" | |||
tplDatasetEdit base.TplName = "repo/datasets/edit" | |||
taskstplIndex base.TplName = "repo/datasets/tasks/index" | |||
) | |||
var titlePattern = regexp.MustCompile(`^[A-Za-z0-9-_\\.]{1,100}$`) | |||
// MustEnableDataset check if repository enable internal dataset | |||
func MustEnableDataset(ctx *context.Context) { | |||
if !ctx.Repo.CanRead(models.UnitTypeDatasets) { | |||
@@ -84,43 +96,34 @@ func QueryDataSet(ctx *context.Context) []*models.Attachment { | |||
attachments := newFilterPrivateAttachments(ctx, dataset.Attachments, repo) | |||
ctx.Data["SortType"] = ctx.Query("sort") | |||
switch ctx.Query("sort") { | |||
case "newest": | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix > attachments[j].CreatedUnix | |||
}) | |||
case "oldest": | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix < attachments[j].CreatedUnix | |||
}) | |||
default: | |||
ctx.Data["SortType"] = "newest" | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix > attachments[j].CreatedUnix | |||
}) | |||
} | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix > attachments[j].CreatedUnix | |||
}) | |||
return attachments | |||
} | |||
func DatasetIndex(ctx *context.Context) { | |||
log.Info("dataset index 1") | |||
MustEnableDataset(ctx) | |||
ctx.Data["PageIsDataset"] = true | |||
repo := ctx.Repo.Repository | |||
dataset, err := models.GetDatasetByRepo(repo) | |||
ctx.Data["CanWrite"] = ctx.Repo.CanWrite(models.UnitTypeDatasets) | |||
if err != nil { | |||
log.Error("query dataset, not found repo.") | |||
ctx.NotFound("GetDatasetByRepo", err) | |||
log.Warn("query dataset, not found.") | |||
ctx.HTML(200, tplIndex) | |||
return | |||
} | |||
cloudbrainType := -1 | |||
if ctx.Query("type") != "" { | |||
if ctx.Query("type") == "" { | |||
log.Error("query dataset, not found param type") | |||
ctx.NotFound("type error", nil) | |||
return | |||
cloudbrainType = ctx.QueryInt("type") | |||
} | |||
err = models.GetDatasetAttachments(ctx.QueryInt("type"), ctx.IsSigned, ctx.User, dataset) | |||
err = models.GetDatasetAttachments(cloudbrainType, ctx.IsSigned, ctx.User, dataset) | |||
if err != nil { | |||
ctx.ServerError("GetDatasetAttachments", err) | |||
return | |||
@@ -128,53 +131,138 @@ func DatasetIndex(ctx *context.Context) { | |||
attachments := newFilterPrivateAttachments(ctx, dataset.Attachments, repo) | |||
ctx.Data["SortType"] = ctx.Query("sort") | |||
switch ctx.Query("sort") { | |||
case "newest": | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix > attachments[j].CreatedUnix | |||
}) | |||
case "oldest": | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix < attachments[j].CreatedUnix | |||
}) | |||
default: | |||
ctx.Data["SortType"] = "newest" | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix > attachments[j].CreatedUnix | |||
}) | |||
sort.Slice(attachments, func(i, j int) bool { | |||
return attachments[i].CreatedUnix > attachments[j].CreatedUnix | |||
}) | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
pagesize := ctx.QueryInt("pagesize") | |||
if pagesize <= 0 { | |||
pagesize = 10 | |||
} | |||
pager := context.NewPagination(len(attachments), pagesize, page, 5) | |||
pageAttachments := getPageAttachments(attachments, page, pagesize) | |||
//load attachment creator | |||
for _, attachment := range pageAttachments { | |||
uploader, _ := models.GetUserByID(attachment.UploaderID) | |||
attachment.Uploader = uploader | |||
} | |||
ctx.Data["Page"] = pager | |||
ctx.Data["PageIsDataset"] = true | |||
ctx.Data["Title"] = ctx.Tr("dataset.show_dataset") | |||
ctx.Data["Link"] = ctx.Repo.RepoLink + "/datasets" | |||
ctx.Data["dataset"] = dataset | |||
ctx.Data["Attachments"] = attachments | |||
ctx.Data["Attachments"] = pageAttachments | |||
ctx.Data["IsOwner"] = true | |||
ctx.Data["StoreType"] = setting.Attachment.StoreType | |||
ctx.Data["Type"] = ctx.QueryInt("type") | |||
ctx.Data["Type"] = cloudbrainType | |||
renderAttachmentSettings(ctx) | |||
ctx.HTML(200, tplIndex) | |||
} | |||
func getPageAttachments(attachments []*models.Attachment, page int, pagesize int) []*models.Attachment { | |||
begin := (page - 1) * pagesize | |||
end := (page) * pagesize | |||
if begin > len(attachments)-1 { | |||
return nil | |||
} | |||
if end > len(attachments)-1 { | |||
return attachments[begin:] | |||
} else { | |||
return attachments[begin:end] | |||
} | |||
} | |||
func CreateDataset(ctx *context.Context) { | |||
MustEnableDataset(ctx) | |||
ctx.Data["PageIsDataset"] = true | |||
ctx.HTML(200, tplDatasetCreate) | |||
} | |||
func EditDataset(ctx *context.Context) { | |||
MustEnableDataset(ctx) | |||
ctx.Data["PageIsDataset"] = true | |||
datasetId, _ := strconv.ParseInt(ctx.Params(":id"), 10, 64) | |||
dataset, _ := models.GetDatasetByID(datasetId) | |||
if dataset == nil { | |||
ctx.Error(http.StatusNotFound, "") | |||
return | |||
} | |||
ctx.Data["Dataset"] = dataset | |||
ctx.HTML(200, tplDatasetEdit) | |||
} | |||
func CreateDatasetPost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
dataset := &models.Dataset{} | |||
if !titlePattern.MatchString(form.Title) { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.title_format_err"))) | |||
return | |||
} | |||
if utf8.RuneCountInString(form.Description) > 1024 { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.description_format_err"))) | |||
return | |||
} | |||
dataset.RepoID = ctx.Repo.Repository.ID | |||
dataset.UserID = ctx.User.ID | |||
dataset.Category = form.Category | |||
dataset.Task = form.Task | |||
dataset.Title = form.Title | |||
dataset.License = form.License | |||
dataset.Description = form.Description | |||
dataset.DownloadTimes = 0 | |||
if ctx.Repo.Repository.IsPrivate { | |||
dataset.Status = 0 | |||
} else { | |||
dataset.Status = 1 | |||
} | |||
err := models.CreateDataset(dataset) | |||
if err != nil { | |||
log.Error("fail to create dataset", err) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.create_dataset_fail"))) | |||
} else { | |||
ctx.JSON(http.StatusOK, models.BaseOKMessage) | |||
} | |||
} | |||
func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) { | |||
ctx.Data["PageIsDataset"] = true | |||
ctx.Data["Title"] = ctx.Tr("dataset.edit_dataset") | |||
if !titlePattern.MatchString(form.Title) { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.title_format_err"))) | |||
return | |||
} | |||
if utf8.RuneCountInString(form.Description) > 1024 { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.description_format_err"))) | |||
return | |||
} | |||
rel, err := models.GetDatasetByID(form.ID) | |||
ctx.Data["dataset"] = rel | |||
if err != nil { | |||
ctx.ServerError("GetDataset", err) | |||
return | |||
} | |||
if ctx.HasError() { | |||
ctx.Data["Error"] = true | |||
ctx.HTML(200, tplIndex) | |||
log.Error("failed to query dataset", err) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.query_dataset_fail"))) | |||
return | |||
} | |||
@@ -184,9 +272,236 @@ func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) { | |||
rel.Task = form.Task | |||
rel.License = form.License | |||
if err = models.UpdateDataset(models.DefaultDBContext(), rel); err != nil { | |||
ctx.Data["Error"] = true | |||
ctx.HTML(200, tplIndex) | |||
log.Error("%v", err) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("dataset.query_dataset_fail"))) | |||
} | |||
ctx.Redirect(ctx.Repo.RepoLink + "/datasets?type=" + form.Type) | |||
ctx.JSON(http.StatusOK, models.BaseOKMessage) | |||
} | |||
func DatasetAction(ctx *context.Context) { | |||
var err error | |||
datasetId, _ := strconv.ParseInt(ctx.Params(":id"), 10, 64) | |||
switch ctx.Params(":action") { | |||
case "star": | |||
err = models.StarDataset(ctx.User.ID, datasetId, true) | |||
case "unstar": | |||
err = models.StarDataset(ctx.User.ID, datasetId, false) | |||
} | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("repo.star_fail", ctx.Params(":action")))) | |||
} else { | |||
ctx.JSON(http.StatusOK, models.BaseOKMessage) | |||
} | |||
} | |||
func CurrentRepoDataset(ctx *context.Context) { | |||
page := ctx.QueryInt("page") | |||
cloudbrainType := ctx.QueryInt("type") | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
repo := ctx.Repo.Repository | |||
var datasetIDs []int64 | |||
dataset, err := models.GetDatasetByRepo(repo) | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("GetDatasetByRepo failed", err))) | |||
return | |||
} | |||
datasetIDs = append(datasetIDs, dataset.ID) | |||
datasets, count, err := models.Attachments(&models.AttachmentsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.DatasetPagingNum, | |||
}, | |||
Keyword: keyword, | |||
NeedDatasetIDs: true, | |||
DatasetIDs: datasetIDs, | |||
Type: cloudbrainType, | |||
NeedIsPrivate: false, | |||
JustNeedZipFile: true, | |||
NeedRepoInfo: true, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("datasets", err) | |||
return | |||
} | |||
data, err := json.Marshal(datasets) | |||
if err != nil { | |||
log.Error("json.Marshal failed:", err.Error()) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": err.Error(), | |||
"data": "", | |||
}) | |||
return | |||
} | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "0", | |||
"data": string(data), | |||
"count": strconv.FormatInt(count, 10), | |||
}) | |||
} | |||
func MyDatasets(ctx *context.Context) { | |||
page := ctx.QueryInt("page") | |||
cloudbrainType := ctx.QueryInt("type") | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
uploaderID := ctx.User.ID | |||
datasets, count, err := models.Attachments(&models.AttachmentsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.DatasetPagingNum, | |||
}, | |||
Keyword: keyword, | |||
NeedDatasetIDs: false, | |||
UploaderID: uploaderID, | |||
Type: cloudbrainType, | |||
NeedIsPrivate: false, | |||
JustNeedZipFile: true, | |||
NeedRepoInfo: true, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("datasets", err) | |||
return | |||
} | |||
data, err := json.Marshal(datasets) | |||
if err != nil { | |||
log.Error("json.Marshal failed:", err.Error()) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": err.Error(), | |||
"data": "", | |||
}) | |||
return | |||
} | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "0", | |||
"data": string(data), | |||
"count": strconv.FormatInt(count, 10), | |||
}) | |||
} | |||
func PublicDataset(ctx *context.Context) { | |||
page := ctx.QueryInt("page") | |||
cloudbrainType := ctx.QueryInt("type") | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
datasets, count, err := models.Attachments(&models.AttachmentsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.DatasetPagingNum, | |||
}, | |||
Keyword: keyword, | |||
NeedDatasetIDs: false, | |||
NeedIsPrivate: true, | |||
IsPrivate: false, | |||
Type: cloudbrainType, | |||
JustNeedZipFile: true, | |||
NeedRepoInfo: true, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("datasets", err) | |||
return | |||
} | |||
data, err := json.Marshal(datasets) | |||
if err != nil { | |||
log.Error("json.Marshal failed:", err.Error()) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": err.Error(), | |||
"data": "", | |||
}) | |||
return | |||
} | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "0", | |||
"data": string(data), | |||
"count": strconv.FormatInt(count, 10), | |||
}) | |||
} | |||
func MyFavoriteDataset(ctx *context.Context) { | |||
page := ctx.QueryInt("page") | |||
cloudbrainType := ctx.QueryInt("type") | |||
keyword := strings.Trim(ctx.Query("q"), " ") | |||
var datasetIDs []int64 | |||
datasetStars, err := models.GetDatasetStarByUser(ctx.User) | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("GetDatasetStarByUser failed", err))) | |||
log.Error("GetDatasetStarByUser failed:", err.Error()) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": err.Error(), | |||
"data": "", | |||
}) | |||
return | |||
} | |||
for i, _ := range datasetStars { | |||
datasetIDs = append(datasetIDs, datasetStars[i].DatasetID) | |||
} | |||
datasets, count, err := models.Attachments(&models.AttachmentsOptions{ | |||
ListOptions: models.ListOptions{ | |||
Page: page, | |||
PageSize: setting.UI.DatasetPagingNum, | |||
}, | |||
Keyword: keyword, | |||
NeedDatasetIDs: true, | |||
DatasetIDs: datasetIDs, | |||
NeedIsPrivate: true, | |||
IsPrivate: false, | |||
Type: cloudbrainType, | |||
JustNeedZipFile: true, | |||
NeedRepoInfo: true, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("datasets", err) | |||
return | |||
} | |||
data, err := json.Marshal(datasets) | |||
if err != nil { | |||
log.Error("json.Marshal failed:", err.Error()) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": err.Error(), | |||
"data": "", | |||
}) | |||
return | |||
} | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "0", | |||
"data": string(data), | |||
"count": strconv.FormatInt(count, 10), | |||
}) | |||
} | |||
func GetDatasetStatus(ctx *context.Context) { | |||
var ( | |||
err error | |||
) | |||
UUID := ctx.Params(":uuid") | |||
attachment, err := models.GetAttachmentByUUID(UUID) | |||
if err != nil { | |||
log.Error("GetDatasetStarByUser failed:", err.Error()) | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "-1", | |||
"error_msg": err.Error(), | |||
"data": "", | |||
}) | |||
return | |||
} | |||
ctx.JSON(200, map[string]string{ | |||
"result_code": "0", | |||
"UUID": UUID, | |||
"AttachmentStatus": fmt.Sprint(attachment.DecompressState), | |||
}) | |||
} |
@@ -2,6 +2,8 @@ package repo | |||
import ( | |||
"archive/zip" | |||
"code.gitea.io/gitea/modules/notification" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"encoding/json" | |||
"errors" | |||
"io" | |||
@@ -46,20 +48,26 @@ const ( | |||
) | |||
func DebugJobIndex(ctx *context.Context) { | |||
debugListType := ctx.Query("debugListType") | |||
ctx.Data["ListType"] = debugListType | |||
listType := ctx.Query("debugListType") | |||
ctx.Data["ListType"] = listType | |||
MustEnableCloudbrain(ctx) | |||
repo := ctx.Repo.Repository | |||
page := ctx.QueryInt("page") | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
debugType := modelarts.DebugType | |||
typeCloudBrain := models.TypeCloudBrainAll | |||
jobTypeNot := false | |||
if debugListType == models.GPUResource { | |||
debugType = models.TypeCloudBrainOne | |||
} else if debugListType == models.NPUResource { | |||
debugType = models.TypeCloudBrainTwo | |||
if listType == models.GPUResource { | |||
typeCloudBrain = models.TypeCloudBrainOne | |||
} else if listType == models.NPUResource { | |||
typeCloudBrain = models.TypeCloudBrainTwo | |||
} else if listType == models.AllResource { | |||
typeCloudBrain = models.TypeCloudBrainAll | |||
} else { | |||
log.Error("listType(%s) error", listType) | |||
ctx.ServerError("listType error", errors.New("listType error")) | |||
return | |||
} | |||
var jobTypes []string | |||
@@ -70,7 +78,7 @@ func DebugJobIndex(ctx *context.Context) { | |||
PageSize: setting.UI.IssuePagingNum, | |||
}, | |||
RepoID: repo.ID, | |||
Type: debugType, | |||
Type: typeCloudBrain, | |||
JobTypeNot: jobTypeNot, | |||
JobTypes: jobTypes, | |||
}) | |||
@@ -92,7 +100,7 @@ func DebugJobIndex(ctx *context.Context) { | |||
ctx.Data["Tasks"] = ciTasks | |||
ctx.Data["CanCreate"] = cloudbrain.CanCreateOrDebugJob(ctx) | |||
ctx.Data["RepoIsEmpty"] = repo.IsEmpty | |||
ctx.Data["debugListType"] = debugListType | |||
ctx.Data["debugListType"] = listType | |||
ctx.HTML(200, tplDebugJobIndex) | |||
} | |||
@@ -133,6 +141,8 @@ func notebookNewDataPrepare(ctx *context.Context) error { | |||
} | |||
ctx.Data["flavors"] = modelarts.FlavorInfos.FlavorInfo | |||
ctx.Data["cloudbraintype"] = models.TypeCloudBrainTwo | |||
return nil | |||
} | |||
@@ -407,16 +417,46 @@ func NotebookManage(ctx *context.Context) { | |||
break | |||
} | |||
task.Status = res.Status | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
resultCode = "-1" | |||
errorMsg = "system error" | |||
break | |||
} | |||
status = res.Status | |||
if action == models.ActionStart { | |||
newTask := &models.Cloudbrain{ | |||
Status: status, | |||
UserID: task.UserID, | |||
RepoID: task.RepoID, | |||
JobID: task.JobID, | |||
JobName: task.JobName, | |||
DisplayJobName: task.DisplayJobName, | |||
JobType: task.JobType, | |||
Type: task.Type, | |||
Uuid: task.Uuid, | |||
Image: task.Image, | |||
ComputeResource: task.ComputeResource, | |||
Description: task.Description, | |||
} | |||
status = task.Status | |||
err = models.RestartCloudbrain(task, newTask) | |||
if err != nil { | |||
log.Error("RestartCloudbrain(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
resultCode = "-1" | |||
errorMsg = "system error" | |||
break | |||
} | |||
ID = strconv.FormatInt(newTask.ID, 10) | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, ID, task.DisplayJobName, models.ActionCreateDebugNPUTask) | |||
} else { | |||
task.Status = res.Status | |||
if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) { | |||
task.EndTime = timeutil.TimeStampNow() | |||
} | |||
task.ComputeAndSetDuration() | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
resultCode = "-1" | |||
errorMsg = "system error" | |||
break | |||
} | |||
} | |||
break | |||
} | |||
@@ -473,6 +513,26 @@ func TrainJobIndex(ctx *context.Context) { | |||
page = 1 | |||
} | |||
listType := ctx.Query("listType") | |||
if len(listType) == 0 { | |||
listType = models.AllResource | |||
} | |||
ctx.Data["ListType"] = listType | |||
typeCloudBrain := models.TypeCloudBrainAll | |||
if listType == models.GPUResource { | |||
typeCloudBrain = models.TypeCloudBrainOne | |||
} else if listType == models.NPUResource { | |||
typeCloudBrain = models.TypeCloudBrainTwo | |||
} else if listType == models.AllResource { | |||
typeCloudBrain = models.TypeCloudBrainAll | |||
} | |||
//else { | |||
// log.Error("listType(%s) error", listType) | |||
// ctx.ServerError("listType error", errors.New("listType error")) | |||
// return | |||
//} | |||
var jobTypes []string | |||
jobTypes = append(jobTypes, string(models.JobTypeTrain)) | |||
tasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
@@ -481,7 +541,7 @@ func TrainJobIndex(ctx *context.Context) { | |||
PageSize: setting.UI.IssuePagingNum, | |||
}, | |||
RepoID: repo.ID, | |||
Type: models.TypeCloudBrainTwo, | |||
Type: typeCloudBrain, | |||
JobTypeNot: false, | |||
JobTypes: jobTypes, | |||
IsLatestVersion: modelarts.IsLatestVersion, | |||
@@ -494,11 +554,16 @@ func TrainJobIndex(ctx *context.Context) { | |||
for i, task := range tasks { | |||
tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||
tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | |||
tasks[i].ComputeResource = models.NPUResource | |||
if task.Cloudbrain.Type == models.TypeCloudBrainOne { | |||
tasks[i].ComputeResource = models.GPUResource | |||
} else if task.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||
tasks[i].ComputeResource = models.NPUResource | |||
} | |||
} | |||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | |||
pager.SetDefaultParams(ctx) | |||
pager.AddParam(ctx, "listType", "ListType") | |||
ctx.Data["Page"] = pager | |||
ctx.Data["PageIsCloudBrain"] = true | |||
@@ -580,6 +645,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
return err | |||
} | |||
ctx.Data["config_list"] = configList.ParaConfigs | |||
ctx.Data["cloudbraintype"] = models.TypeCloudBrainTwo | |||
return nil | |||
} | |||
@@ -746,6 +812,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
ctx.Data["uuid"] = task.Uuid | |||
ctx.Data["flavor_code"] = task.FlavorCode | |||
ctx.Data["engine_id"] = task.EngineID | |||
ctx.Data["cloudbraintype"] = models.TypeCloudBrainTwo | |||
configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
if err != nil { | |||
@@ -953,17 +1020,9 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
return | |||
} | |||
//todo: del local code? | |||
var parameters models.Parameters | |||
param := make([]models.Parameter, 0) | |||
param = append(param, models.Parameter{ | |||
Label: modelarts.TrainUrl, | |||
Value: outputObsPath, | |||
}, models.Parameter{ | |||
Label: modelarts.DataUrl, | |||
Value: dataPath, | |||
}) | |||
existDeviceTarget := false | |||
if len(params) != 0 { | |||
err := json.Unmarshal([]byte(params), ¶meters) | |||
if err != nil { | |||
@@ -974,6 +1033,9 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
} | |||
for _, parameter := range parameters.Parameter { | |||
if parameter.Label == modelarts.DeviceTarget { | |||
existDeviceTarget = true | |||
} | |||
if parameter.Label != modelarts.TrainUrl && parameter.Label != modelarts.DataUrl { | |||
param = append(param, models.Parameter{ | |||
Label: parameter.Label, | |||
@@ -982,9 +1044,22 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
} | |||
} | |||
} | |||
if !existDeviceTarget { | |||
param = append(param, models.Parameter{ | |||
Label: modelarts.DeviceTarget, | |||
Value: modelarts.Ascend, | |||
}) | |||
} | |||
//save param config | |||
if isSaveParam == "on" { | |||
saveparams := append(param, models.Parameter{ | |||
Label: modelarts.TrainUrl, | |||
Value: outputObsPath, | |||
}, models.Parameter{ | |||
Label: modelarts.DataUrl, | |||
Value: dataPath, | |||
}) | |||
if form.ParameterTemplateName == "" { | |||
log.Error("ParameterTemplateName is empty") | |||
trainJobNewDataPrepare(ctx) | |||
@@ -1006,7 +1081,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
EngineID: int64(engineID), | |||
LogUrl: logObsPath, | |||
PoolID: poolID, | |||
Parameter: param, | |||
Parameter: saveparams, | |||
}) | |||
if err != nil { | |||
@@ -1032,7 +1107,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
LogUrl: logObsPath, | |||
PoolID: poolID, | |||
Uuid: uuid, | |||
Parameters: parameters.Parameter, | |||
Parameters: param, | |||
CommitID: commitID, | |||
IsLatestVersion: isLatestVersion, | |||
BranchName: branch_name, | |||
@@ -1168,13 +1243,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
var parameters models.Parameters | |||
param := make([]models.Parameter, 0) | |||
param = append(param, models.Parameter{ | |||
Label: modelarts.TrainUrl, | |||
Value: outputObsPath, | |||
}, models.Parameter{ | |||
Label: modelarts.DataUrl, | |||
Value: dataPath, | |||
}) | |||
existDeviceTarget := true | |||
if len(params) != 0 { | |||
err := json.Unmarshal([]byte(params), ¶meters) | |||
if err != nil { | |||
@@ -1183,8 +1252,10 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
for _, parameter := range parameters.Parameter { | |||
if parameter.Label == modelarts.DeviceTarget { | |||
existDeviceTarget = true | |||
} | |||
if parameter.Label != modelarts.TrainUrl && parameter.Label != modelarts.DataUrl { | |||
param = append(param, models.Parameter{ | |||
Label: parameter.Label, | |||
@@ -1193,9 +1264,22 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
} | |||
} | |||
} | |||
if !existDeviceTarget { | |||
param = append(param, models.Parameter{ | |||
Label: modelarts.DeviceTarget, | |||
Value: modelarts.Ascend, | |||
}) | |||
} | |||
//save param config | |||
if isSaveParam == "on" { | |||
saveparams := append(param, models.Parameter{ | |||
Label: modelarts.TrainUrl, | |||
Value: outputObsPath, | |||
}, models.Parameter{ | |||
Label: modelarts.DataUrl, | |||
Value: dataPath, | |||
}) | |||
if form.ParameterTemplateName == "" { | |||
log.Error("ParameterTemplateName is empty") | |||
versionErrorDataPrepare(ctx, form) | |||
@@ -1217,7 +1301,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
EngineID: int64(engineID), | |||
LogUrl: logObsPath, | |||
PoolID: poolID, | |||
Parameter: parameters.Parameter, | |||
Parameter: saveparams, | |||
}) | |||
if err != nil { | |||
@@ -1228,12 +1312,6 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
} | |||
} | |||
if err != nil { | |||
log.Error("getFlavorNameByEngineID(%s) failed:%v", engineID, err.Error()) | |||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
return | |||
} | |||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, PreVersionName) | |||
if err != nil { | |||
log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error()) | |||
@@ -1257,7 +1335,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
PoolID: poolID, | |||
Uuid: uuid, | |||
Params: form.Params, | |||
Parameters: parameters.Parameter, | |||
Parameters: param, | |||
PreVersionId: task.VersionID, | |||
CommitID: commitID, | |||
BranchName: branch_name, | |||
@@ -1535,6 +1613,7 @@ func trainJobGetLog(jobID string) (*models.GetTrainJobLogFileNamesResult, *model | |||
func TrainJobDel(ctx *context.Context) { | |||
var jobID = ctx.Params(":jobid") | |||
var listType = ctx.Query("listType") | |||
repo := ctx.Repo.Repository | |||
var jobTypes []string | |||
@@ -1576,12 +1655,13 @@ func TrainJobDel(ctx *context.Context) { | |||
if ctx.IsUserSiteAdmin() && isAdminPage == "true" { | |||
ctx.Redirect(setting.AppSubURL + "/admin" + "/cloudbrains") | |||
} else { | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=" + listType) | |||
} | |||
} | |||
func TrainJobStop(ctx *context.Context) { | |||
var jobID = ctx.Params(":jobid") | |||
var listType = ctx.Query("listType") | |||
task := ctx.Cloudbrain | |||
_, err := modelarts.StopTrainJob(jobID, strconv.FormatInt(task.VersionID, 10)) | |||
@@ -1591,7 +1671,7 @@ func TrainJobStop(ctx *context.Context) { | |||
return | |||
} | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job?listType=" + listType) | |||
} | |||
func canUserCreateTrainJob(uid int64) (bool, error) { | |||
@@ -1782,7 +1862,6 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
return | |||
} | |||
//todo: del local code? | |||
var parameters models.Parameters | |||
param := make([]models.Parameter, 0) | |||
param = append(param, models.Parameter{ | |||
@@ -1792,6 +1871,7 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
Label: modelarts.CkptUrl, | |||
Value: "s3:/" + ckptUrl, | |||
}) | |||
existDeviceTarget := false | |||
if len(params) != 0 { | |||
err := json.Unmarshal([]byte(params), ¶meters) | |||
if err != nil { | |||
@@ -1802,6 +1882,9 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
} | |||
for _, parameter := range parameters.Parameter { | |||
if parameter.Label == modelarts.DeviceTarget { | |||
existDeviceTarget = true | |||
} | |||
if parameter.Label != modelarts.TrainUrl && parameter.Label != modelarts.DataUrl { | |||
param = append(param, models.Parameter{ | |||
Label: parameter.Label, | |||
@@ -1810,6 +1893,12 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference | |||
} | |||
} | |||
} | |||
if !existDeviceTarget { | |||
param = append(param, models.Parameter{ | |||
Label: modelarts.DeviceTarget, | |||
Value: modelarts.Ascend, | |||
}) | |||
} | |||
req := &modelarts.GenerateInferenceJobReq{ | |||
JobName: jobName, | |||
@@ -1977,6 +2066,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error { | |||
New: MODEL_LATEST, | |||
}) | |||
ctx.Data["MODEL_COUNT"] = model_count | |||
ctx.Data["cloudbraintype"] = models.TypeCloudBrainTwo | |||
return nil | |||
} | |||
@@ -2246,7 +2336,7 @@ func SetJobCount(ctx *context.Context) { | |||
repoId := ctx.Repo.Repository.ID | |||
_, jobCount, err := models.Cloudbrains(&models.CloudbrainsOptions{ | |||
RepoID: repoId, | |||
Type: modelarts.DebugType, | |||
Type: models.TypeCloudBrainAll, | |||
}) | |||
if err != nil { | |||
ctx.ServerError("Get job faild:", err) | |||
@@ -245,10 +245,6 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
// This section doesn't require repo_name/RepoName to be set in the form, don't show it | |||
// as an error on the UI for this action | |||
ctx.Data["Err_RepoName"] = nil | |||
if err := models.CreateDefaultDatasetToRepo(repo); err != nil { | |||
ctx.ServerError("CreateDefaultDatasetToRepo", err) | |||
return | |||
} | |||
if form.EnableDataset && !models.UnitTypeDatasets.UnitGlobalDisabled() { | |||
units = append(units, models.RepoUnit{ | |||
@@ -323,6 +323,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Get("/action/notification", routers.ActionNotification) | |||
m.Get("/recommend/org", routers.RecommendOrgFromPromote) | |||
m.Get("/recommend/repo", routers.RecommendRepoFromPromote) | |||
m.Post("/all/search/", routers.Search) | |||
m.Get("/all/search/", routers.EmptySearch) | |||
m.Get("/all/dosearch/", routers.SearchApi) | |||
m.Get("/home/term", routers.HomeTerm) | |||
m.Group("/explore", func() { | |||
m.Get("", func(ctx *context.Context) { | |||
@@ -587,6 +590,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/delete", repo.DeleteAttachment) | |||
m.Get("/get_pre_url", repo.GetPresignedPutObjectURL) | |||
m.Post("/add", repo.AddAttachment) | |||
m.Post("/edit", bindIgnErr(auth.EditAttachmentForm{}), repo.EditAttachment) | |||
m.Post("/private", repo.UpdatePublicAttachment) | |||
m.Get("/get_chunks", repo.GetSuccessChunks) | |||
m.Get("/new_multipart", repo.NewMultipart) | |||
@@ -979,7 +984,24 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Group("/datasets", func() { | |||
m.Get("", reqRepoDatasetReader, repo.DatasetIndex) | |||
m.Post("", reqRepoDatasetWriter, bindIgnErr(auth.EditDatasetForm{}), repo.EditDatasetPost) | |||
m.Put("/:id/:action", reqRepoDatasetReader, repo.DatasetAction) | |||
m.Get("/create", reqRepoDatasetWriter, repo.CreateDataset) | |||
m.Post("/create", reqRepoDatasetWriter, bindIgnErr(auth.CreateDatasetForm{}), repo.CreateDatasetPost) | |||
m.Get("/edit/:id", reqRepoDatasetWriter, repo.EditDataset) | |||
m.Post("/edit", reqRepoDatasetWriter, bindIgnErr(auth.EditDatasetForm{}), repo.EditDatasetPost) | |||
m.Get("/current_repo", repo.CurrentRepoDataset) | |||
m.Get("/my_datasets", repo.MyDatasets) | |||
m.Get("/public_datasets", repo.PublicDataset) | |||
m.Get("/my_favorite", repo.MyFavoriteDataset) | |||
m.Group("/status", func() { | |||
m.Get("/:uuid", repo.GetDatasetStatus) | |||
}) | |||
m.Group("/attachments", func() { | |||
m.Get("/upload", repo.UploadAttachmentUI) | |||
m.Get("/edit/:id", repo.EditAttachmentUI) | |||
}, reqSignIn) | |||
m.Group("/dirs", func() { | |||
m.Get("/:uuid", reqRepoDatasetReader, repo.DirIndex) | |||
@@ -1017,6 +1039,19 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainBenchmarkCreate) | |||
m.Get("/get_child_types", repo.GetChildTypes) | |||
}) | |||
m.Group("/train-job", func() { | |||
m.Group("/:jobid", func() { | |||
m.Get("", reqRepoCloudBrainReader, repo.CloudBrainTrainJobShow) | |||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainTrainJobDel) | |||
//m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | |||
m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadModel) | |||
//m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobNewVersion) | |||
//m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | |||
}) | |||
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.CloudBrainTrainJobNew) | |||
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) | |||
}) | |||
}, context.RepoRef()) | |||
m.Group("/modelmanage", func() { | |||
m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | |||
@@ -10,7 +10,7 @@ import ( | |||
"github.com/elliotchance/orderedmap" | |||
) | |||
var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 25, 26, 27, 28, 29, 30} | |||
var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 25, 26, 27, 28, 29, 30, 31} | |||
type ClientsManager struct { | |||
Clients *orderedmap.OrderedMap | |||
@@ -215,10 +215,10 @@ var _hmt = _hmt || []; | |||
localStorage.setItem("isCloseNotice",true) | |||
} | |||
function isShowNotice(){ | |||
var current_notice = localStorage.getItem("notice") | |||
var current_notice = localStorage.getItem("notices") | |||
if (current_notice != "{{.notice.CommitId}}"){ | |||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||
if (current_notice != "{{.notices.CommitId}}"){ | |||
localStorage.setItem('notices',"{{.notices.CommitId}}"); | |||
isNewNotice=true; | |||
localStorage.setItem("isCloseNotice",false) | |||
}else{ | |||
@@ -216,10 +216,10 @@ var _hmt = _hmt || []; | |||
localStorage.setItem("isCloseNotice",true) | |||
} | |||
function isShowNotice(){ | |||
var current_notice = localStorage.getItem("notice") | |||
var current_notice = localStorage.getItem("notices") | |||
if (current_notice != "{{.notice.CommitId}}"){ | |||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||
if (current_notice != "{{.notices.CommitId}}"){ | |||
localStorage.setItem('notices',"{{.notices.CommitId}}"); | |||
isNewNotice=true; | |||
localStorage.setItem("isCloseNotice",false) | |||
}else{ | |||
@@ -220,10 +220,10 @@ var _hmt = _hmt || []; | |||
localStorage.setItem("isCloseNotice",true) | |||
} | |||
function isShowNotice(){ | |||
var current_notice = localStorage.getItem("notice") | |||
var current_notice = localStorage.getItem("notices") | |||
if (current_notice != "{{.notice.CommitId}}"){ | |||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||
if (current_notice != "{{.notices.CommitId}}"){ | |||
localStorage.setItem('notices',"{{.notices.CommitId}}"); | |||
isNewNotice=true; | |||
localStorage.setItem("isCloseNotice",false) | |||
}else{ | |||
@@ -95,9 +95,9 @@ | |||
{{if .IsSigned}} | |||
<div class="right stackable menu"> | |||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||
<input type="hidden" name="sort" value="hot"> | |||
@@ -199,9 +199,9 @@ | |||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
<div class="right stackable menu"> | |||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||
<input type="hidden" name="sort" value="hot"> | |||
@@ -93,9 +93,9 @@ | |||
{{if .IsSigned}} | |||
<div class="right stackable menu"> | |||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||
@@ -196,9 +196,9 @@ | |||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
<div class="right stackable menu"> | |||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||
@@ -96,9 +96,9 @@ | |||
{{if .IsSigned}} | |||
<div class="right stackable menu"> | |||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||
@@ -199,9 +199,9 @@ | |||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
<div class="right stackable menu"> | |||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||
<form id="searchForm" class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/all/search/" method="post"> | |||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." | |||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||
@@ -217,10 +217,10 @@ var _hmt = _hmt || []; | |||
localStorage.setItem("isCloseNotice",true) | |||
} | |||
function isShowNotice(){ | |||
var current_notice = localStorage.getItem("notice") | |||
var current_notice = localStorage.getItem("notices") | |||
if (current_notice != "{{.notice.CommitId}}"){ | |||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||
if (current_notice != "{{.notices.CommitId}}"){ | |||
localStorage.setItem('notices',"{{.notices.CommitId}}"); | |||
isNewNotice=true; | |||
localStorage.setItem("isCloseNotice",false) | |||
}else{ | |||
@@ -0,0 +1,138 @@ | |||
<div class="dataset-repolink" id="dataset-repolink-init" style="display: none;" data-repolink="{{.RepoLink}}" data-cloudranin-type="{{.cloudbraintype}}"></div> | |||
<div class="inline {{if eq .cloudbraintype 0}} required {{end}} field" id="dataset-base"> | |||
<label>{{.i18n.Tr "dataset.dataset"}}</label> | |||
<input type="hidden" name="attachment" :value="dataset_uuid"> | |||
{{if eq .cloudbraintype 0}} | |||
<input class="disabled" type="text" :value="dataset_name" required onfocus="this.blur();"> | |||
{{else}} | |||
<input class="disabled" type="text" :value="dataset_name"> | |||
{{end}} | |||
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus"> {{.i18n.Tr "dataset.select_dataset"}}</el-button> | |||
<el-dialog | |||
title="{{.i18n.Tr "dataset.select_dataset"}}" | |||
:visible.sync="dialogVisible" | |||
width="50%" | |||
> | |||
<div class="ui icon input" style="z-index: 9999;position: absolute;right: 50px;height:30px;"> | |||
<i class="search icon" style="cursor: pointer;pointer-events:auto" @click="searchDataset()"></i> | |||
<input type="text" placeholder="{{.i18n.Tr "dataset.search_dataset"}}" v-model="searchDataItem" @keyup.enter="searchDataset()"> | |||
</div> | |||
<el-tabs v-model="activeName" @tab-click="handleClick('{{.RepoLink}}',activeName,{{.cloudbraintype}})"> | |||
<el-tab-pane label="{{.i18n.Tr "dataset.current_project"}}" name="first"> | |||
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in currentRepoDataset" :key="index"> | |||
<div style="width: 90%;"> | |||
<div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias} </span><span class="panel_dataset_name">${dataset.Name} </span></div> | |||
<div style="margin-top: 8px;display: flex;"> | |||
<a :title="dataset.UserName" style="cursor: default;"> | |||
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
</a> | |||
<span class="panel_datset_desc">${dataset.Description}</span> | |||
</div> | |||
</div> | |||
<div> | |||
<button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
<span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
<i class="CREATING"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
</span> | |||
<span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
<i class="FAILED"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
</span> | |||
</div> | |||
</div> | |||
</el-tab-pane> | |||
<el-tab-pane label="{{.i18n.Tr "dataset.owner_dataset"}}" name="second"> | |||
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in myDataset" :key="index"> | |||
<div style="width: 90%;"> | |||
<div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias}</span><span class="panel_dataset_name">${dataset.Name}</span></div> | |||
<div style="margin-top: 8px;display: flex;"> | |||
<a :title="dataset.UserName" style="cursor: default;"> | |||
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
</a> | |||
<span class="panel_datset_desc">${dataset.Description}</span> | |||
</div> | |||
</div> | |||
<div> | |||
<button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
<span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
<i class="CREATING"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
</span> | |||
<span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
<i class="FAILED"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
</span> | |||
</div> | |||
</div> | |||
</el-tab-pane> | |||
<el-tab-pane label="{{.i18n.Tr "dataset.public_dataset"}}" name="third"> | |||
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in publicDataset" :key="index"> | |||
<div style="width: 90%;"> | |||
<div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias}</span><span class="panel_dataset_name">${dataset.Name}</span></div> | |||
<div style="margin-top: 8px;display: flex;"> | |||
<a :title="dataset.UserName" style="cursor: default;"> | |||
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
</a> | |||
<span class="panel_datset_desc">${dataset.Description}</span> | |||
</div> | |||
</div> | |||
<div> | |||
<button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
<span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
<i class="CREATING"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
</span> | |||
<span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
<i class="FAILED"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
</span> | |||
</div> | |||
</div> | |||
</el-tab-pane> | |||
<el-tab-pane label="{{.i18n.Tr "dataset.I_liked"}}" name="fourth"> | |||
<div style="display: flex;align-items: center;justify-content: space-between;padding: 1rem 0;border-bottom:1px solid #F5F5F5" v-for="(dataset,index) in myFavoriteDataset" :key="index"> | |||
<div style="width: 90%;"> | |||
<div style="display: flex;align-items: center;"><span class="panel_creator_reponam">${dataset.Repo.OwnerName}/${dataset.Repo.Alias}</span><span class="panel_dataset_name">${dataset.Name}</span></div> | |||
<div style="margin-top: 8px;display: flex;"> | |||
<a :title="dataset.UserName" style="cursor: default;"> | |||
<img class="ui avatar mini image" style="width: 20px;height: 20px;" :src="dataset.RelAvatarLink"> | |||
</a> | |||
<span class="panel_datset_desc">${dataset.Description}</span> | |||
</div> | |||
</div> | |||
<div> | |||
<button v-if="dataset.DecompressState===1" class="ui primary basic button mini" @click.stop.prevent="selectDataset(dataset.UUID,dataset.Name)">{{.i18n.Tr "dataset.use"}}</button> | |||
<span v-if="dataset.DecompressState===2" style="display: flex;align-items: center;"> | |||
<i class="CREATING"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color: #5A5A5A;" data-tooltip="{{$.i18n.Tr "dataset.unzip_tooltips"}}" data-inverted="" data-variation="mini" data-position="left center">解压中</span> | |||
</span> | |||
<span v-if="dataset.DecompressState===3" style="display: flex;align-items: center;"> | |||
<i class="FAILED"></i> | |||
<span style="margin-left: 0.4em;font-size: 12px;color:red;" data-tooltip="{{$.i18n.Tr "dataset.zip_failed"}}" data-inverted="" data-variation="mini" data-position="left center">解压失败</span> | |||
</span> | |||
</div> | |||
</div> | |||
</el-tab-pane> | |||
</el-tabs> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-size="5" | |||
layout="total,prev, pager, next" | |||
:total="totalnums"> | |||
</el-pagination> | |||
</div> | |||
</el-dialog> | |||
</div> |
@@ -0,0 +1,69 @@ | |||
<div class="computer only four wide computer column"> | |||
<div class="ui grid"> | |||
<div class="ui sixteen wide column"> | |||
<h2 class="ui medium header" style="margin-top: 0;visibility: hidden;" > | |||
{{.i18n.Tr "datasets"}} | |||
</h2> | |||
<div id="task-square-range-value" style="display: none;"> | |||
{{range $task := tasks}} | |||
<div class="item" data-task='{{$task}}'></div> | |||
{{end}} | |||
</div> | |||
<div id="square-link" style="display: none;" data-link="{{$.Link}}"></div> | |||
<div id="licenses-square-range-value" style="display: none;"> | |||
{{range $license := licenses}} | |||
<div class="item" data-license="{{$license}}"></div> | |||
{{end}} | |||
</div> | |||
<div class="mg-b-2"> | |||
<div class="flex mg-b-1"> | |||
<h3 class="font-medium"> | |||
{{.i18n.Tr "dataset.category"}} | |||
{{if $.Category}} | |||
<span class="mg-l-1 underline text-gray-400 text-sm clear_dataset_value" data-clear-value="category"style="cursor: pointer;" >Clear</span> | |||
{{end}} | |||
</h3> | |||
</div> | |||
<div class="flex flex-wrap"> | |||
{{range $category := categories}} | |||
{{$Cate := $.i18n.Tr (printf "dataset.category.%s" $category)}} | |||
<a class="tag {{if eq $category $.Category}} tag-active {{else}} tag-gray{{end}}" href="{{$.Link}}?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$category}}&task={{$.Task}}&license={{$.License}}"><span>{{$Cate}}</span></a> | |||
{{end}} | |||
</div> | |||
</div> | |||
<div class="mg-b-2"> | |||
<div class="flex mg-b-1"> | |||
<h3 class="font-medium"> | |||
{{.i18n.Tr "dataset.task"}} | |||
{{if $.Task}} | |||
<span class="mg-l-1 underline text-gray-400 text-sm clear_dataset_value" data-clear-value="task" style="cursor: pointer;" >Clear</span> | |||
{{end}} | |||
</h3> | |||
</div> | |||
<div class="flex flex-wrap history-content"> | |||
{{range $task := tasks}} | |||
{{$Task := $.i18n.Tr (printf "dataset.task.%s" $task)}} | |||
<a class="tag {{if eq $task $.Task}} tag-active {{else}} tag-gray{{end}}" href="{{$.Link}}?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$task}}&license={{$.License}}"><span>{{$Task}}</span></a> | |||
{{end}} | |||
</div> | |||
</div> | |||
<div class="mg-b-2"> | |||
<div class="flex mg-b-1"> | |||
<h3 class="font-medium"> | |||
{{.i18n.Tr "repo.license"}} | |||
{{if $.License}} | |||
<span class="mg-l-1 underline text-gray-400 text-sm clear_dataset_value" data-clear-value="license" style="cursor: pointer;" >Clear</span> | |||
{{end}} | |||
</h3> | |||
</div> | |||
<div class="flex flex-wrap"> | |||
{{range $license := licenses}} | |||
<a class="tag {{if eq $license $.License}} tag-active {{else}} tag-gray {{end}}" href="{{$.Link}}?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{$license}}"><span>{{$license}}</span></a> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -25,7 +25,7 @@ | |||
{{range .Datasets}} | |||
<div class="item"> | |||
<div class="ui header"> | |||
<a class="name" href="{{.Repo.Link}}/datasets?type=0"> | |||
<a class="name" href="{{.Repo.Link}}/datasets"> | |||
{{.Repo.OwnerName}} / {{.Repo.Alias}} | |||
</a> | |||
<div class="ui right metas"> | |||
@@ -1,15 +1,216 @@ | |||
{{template "base/head" .}} | |||
<style> | |||
.mg-b-1{ | |||
margin-bottom: 1rem; | |||
} | |||
.mg-b-2{ | |||
margin-bottom: 2rem; | |||
} | |||
.mg-l-1{ | |||
margin-left: 1rem; | |||
} | |||
.text-gray-400 { | |||
--tw-text-opacity: 1; | |||
color: rgba(156,163,175,var(--tw-text-opacity)); | |||
} | |||
.text-sm { | |||
font-size: .875rem; | |||
line-height: 1.25rem; | |||
} | |||
.underline { | |||
text-decoration: underline; | |||
} | |||
.flex{ | |||
display: flex; | |||
} | |||
.font-medium{ | |||
font-weight: 500; | |||
} | |||
.flex-wrap{ | |||
flex-wrap: wrap; | |||
} | |||
.tag { | |||
background-image: linear-gradient(to bottom,var(--tw-gradient-stops)); | |||
border-color: transparent; | |||
border-radius: 0.5rem; | |||
border-width: 1px; | |||
font-size: .875rem; | |||
line-height: 1.25rem; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
white-space: nowrap; | |||
} | |||
.tag-red { | |||
--tw-gradient-from: #fef2f2; | |||
--tw-gradient-stops: var(--tw-gradient-from),var(--tw-gradient-to,hsla(0,86%,97%,0)); | |||
--tw-gradient-to: #fef2f2; | |||
--tw-text-opacity: 1; | |||
color: rgba(153,27,27,var(--tw-text-opacity)); | |||
} | |||
.tag-purple { | |||
--tw-gradient-from: #f5f3ff; | |||
--tw-gradient-stops: var(--tw-gradient-from),var(--tw-gradient-to,rgba(245,243,255,0)); | |||
--tw-gradient-to: #f5f3ff; | |||
--tw-text-opacity: 1; | |||
color: rgba(91,33,182,var(--tw-text-opacity)); | |||
} | |||
.tag-blue { | |||
--tw-gradient-from: #eff6ff; | |||
--tw-gradient-stops: var(--tw-gradient-from),var(--tw-gradient-to,rgba(239,246,255,0)); | |||
--tw-gradient-to: #eff6ff; | |||
--tw-text-opacity: 1; | |||
color: rgba(30,64,175,var(--tw-text-opacity)); | |||
} | |||
.tag.inactive { | |||
filter: grayscale(100%); | |||
opacity: .5; | |||
} | |||
.tag.tag-active{ | |||
background-color: #0366d6; | |||
color: #ffffff; | |||
} | |||
.tag-gray{ | |||
background-color: #f8f9fa; | |||
color: #415058; | |||
} | |||
.tag { | |||
align-items: center; | |||
display: inline-flex; | |||
flex: none; | |||
height: 2rem; | |||
margin-bottom: 0.35rem; | |||
margin-right: 0.35rem; | |||
max-width: 100%; | |||
} | |||
.tag>span { | |||
padding: 0.75rem; | |||
font-size: 14px; | |||
} | |||
.repo_dataset_header{ | |||
font-size: 12px; | |||
color: #3291F8; | |||
} | |||
.heart-stroke{ | |||
stroke: #666; | |||
stroke-width: 2; | |||
fill: #fff | |||
} | |||
.stars_active{ | |||
fill: #FA8C16 !important; | |||
stroke:#FA8C16 !important | |||
} | |||
</style> | |||
<div class="explore repositories"> | |||
{{template "explore/dataset_search" .}} | |||
<div class="ui container"> | |||
<div class="ui grid"> | |||
{{template "explore/navbar" .}} | |||
<div class="ui sixteen wide mobile ten wide tablet ten wide computer column"> | |||
{{template "explore/dataset_list" .}} | |||
{{template "base/paginate" .}} | |||
</div> | |||
<div class="ui sixteen wide mobile six wide tablet three wide computer column"> | |||
{{template "explore/repo_right" .}} | |||
<div> | |||
<div class="ui container"> | |||
<div class="ui grid"> | |||
{{template "explore/dataset_left" .}} | |||
<div class="ui sixteen wide mobile sixteen wide tablet twelve wide computer column"> | |||
<div class="ui row"> | |||
<h2 class="ui left floated medium header"> | |||
{{.i18n.Tr "datasets"}} | |||
</h2> | |||
<div class="ui right floated secondary filter menu"> | |||
<!-- Sort --> | |||
<div class="ui right dropdown type jump item"> | |||
<span class="text"> | |||
{{.i18n.Tr "repo.issues.filter_sort"}} | |||
<i class="dropdown icon"></i> | |||
</span> | |||
<div class="menu"> | |||
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> | |||
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||
<!-- <a class="{{if eq .SortType "downloadtimes"}}active{{end}} item" href="{{$.Link}}?sort=downloadtimes&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.downloadtimes"}}</a> --> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{if .Datasets}} | |||
<div id="datasets-square-range-value" style="display: none;"> | |||
{{range .Datasets}} | |||
<div class="item" data-num-stars="{{.NumStars}}" data-star-active="{{.IsStaring}}"></div> | |||
{{end}} | |||
</div> | |||
{{end}} | |||
<div class="ui row" style="clear: both;" id="dataset-base"> | |||
<div class="ui two cards"> | |||
{{range $k, $v :=.Datasets}} | |||
<div class="ui card" @click="gotoDataset('{{.Repo.Link}}/datasets')" style="cursor: pointer;box-shadow: 0px 4px 4px 0px rgba(232,232,232,0.6);border: 1px solid rgba(232, 232, 232, 1);"> | |||
<div class="content" style="border-bottom: none;"> | |||
<div class="repo_dataset_header" style="display: flex;align-items: center;justify-content: space-between;"> | |||
<a href="{{.Repo.Link}}/datasets" style="font-size: 12px;color: #3291F8;height: 24px;">{{.Repo.OwnerName}} / {{.Repo.Alias}}</a> | |||
{{if $.IsSigned}} | |||
<span style="display: flex;align-items: center;justify-content: flex-end;cursor: pointer;" @click.stop="postSquareStar({{.ID}},'{{.Repo.Link}}/datasets',{{$k}})"> | |||
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;"> | |||
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke" :class='{stars_active:starActives[{{$k}}]}'><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg> | |||
</div> | |||
<span style="line-height: 1;color: #101010;">${starItems[{{$k}}]}</span> | |||
</span> | |||
{{else}} | |||
<span style="display: flex;align-items: center;justify-content: flex-end;cursor: pointer;"> | |||
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;"> | |||
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke" :class='{stars_active:starActives[{{$k}}]}'><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg> | |||
</div> | |||
<span style="line-height: 1;color: #101010;">${starItems[{{$k}}]}</span> | |||
</span> | |||
{{end}} | |||
</div> | |||
<div style="font-size: 16px;color:#0366D6;font-family: SourceHanSansSC-medium;height: 27px;font-weight: bold;">{{.Title}}</div> | |||
{{if or (.Category) (.Task) (.License)}} | |||
<div style="font-size: 12px;margin-top: 5px;height: 24px;"> | |||
{{if .Category}} | |||
{{$category := .Category}} | |||
<a class="ui repo-topic label topic" href="{{$.Link}}?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{.Category}}&task={{$.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.category.%s" $category)}}</a> | |||
{{end}} | |||
{{if .Task}} | |||
{{$task := .Task}} | |||
<a class="ui repo-topic label topic" href="{{$.Link}}?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.task.%s" $task)}}</a> | |||
{{end}} | |||
{{if .License}} | |||
<a class="ui repo-topic label topic" href="{{$.Link}}?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{.License}}">{{.License}}</a> | |||
{{end}} | |||
</div> | |||
{{end}} | |||
<div class="description" style="-webkit-box-orient: vertical;-webkit-line-clamp: 2;display: -webkit-box;overflow: hidden;color:#999999;font-size: 14px;margin-top: 10px;"> | |||
<p>{{.Description}}</p> | |||
</div> | |||
</div> | |||
<div class="extra content" style="border-top: none !important;"> | |||
<div style="display: flex;align-items: center;"> | |||
<a href="{{AppSubUrl}}/{{.Repo.OwnerName}}" title="{{.Repo.OwnerName}}"> | |||
<img class="ui avatar image" style="width: 22px;height:22px;" src="/user/avatar/{{.Repo.OwnerName}}/-1"> | |||
</a> | |||
<span style="color: #999999;font-size: 14px;;">创建于:{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[30]" | |||
:page-size="30" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -10,7 +10,19 @@ | |||
<div class="ui sixteen wide mobile twelve wide tablet ten wide computer column"> | |||
{{template "explore/repo_list" .}} | |||
{{template "base/paginate" .}} | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[20]" | |||
:page-size="20" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="computer only ui three wide computer column"> | |||
{{template "explore/repo_right" .}} | |||
@@ -0,0 +1,95 @@ | |||
{{template "base/head" .}} | |||
<div class="explore seach"> | |||
<div class="repos--seach"> | |||
<div class="ui container"> | |||
<div id="search_div" class="ui two column centered grid"> | |||
<div class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin-top:1.2rem;margin-bottom: 1.2rem;"> | |||
<div class="ui fluid action input"> | |||
<input name="q" id="keyword_input" value="{{.Keyword}}" placeholder="{{.i18n.Tr "home.search"}}..." autofocus=""> | |||
<input type="hidden" name="topic" value=""> | |||
<input type="hidden" name="tab" value=""> | |||
<input type="hidden" name="sort" value="hot"> | |||
<button class="ui green button" onclick="search()">{{.i18n.Tr "home.search"}}</button> | |||
</div> | |||
</div> | |||
</div> | |||
<div id="search_label_div" style="display:none"> | |||
</div> | |||
</div> | |||
<div class="ui container seachnav"> | |||
<div class="ui secondary pointing menu"> | |||
<a id="repo_item" class="item" href="javascript:searchItem(1,10);"> | |||
{{.i18n.Tr "home.search_repo"}} | |||
<span class="ui circular mini label" id="repo_total"></span> | |||
</a> | |||
<a id="dataset_item" class="item" href="javascript:searchItem(5,50);"> | |||
{{.i18n.Tr "home.search_dataset"}} | |||
<span class="ui circular mini label" id="dataset_total"></span> | |||
</a> | |||
<a id="issue_item" class="item" href="javascript:searchItem(2,20);"> | |||
{{.i18n.Tr "home.search_issue"}} | |||
<span class="ui circular mini label" id="issue_total"></span> | |||
</a> | |||
<a id="pr_item" class="item" href="javascript:searchItem(6,60);"> | |||
{{.i18n.Tr "home.search_pr"}} | |||
<span class="ui circular mini label" id="pr_total"></span> | |||
</a> | |||
<a id="user_item" class="item" href="javascript:searchItem(3,30);"> | |||
{{.i18n.Tr "home.search_user"}} | |||
<span class="ui circular mini label" id="user_total"></span> | |||
</a> | |||
<a id="org_item" class="item" href="javascript:searchItem(4,40);"> | |||
{{.i18n.Tr "home.search_org"}} <span class="ui circular mini label" id="org_total"></span> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui container"> | |||
<span id="find_id">{{.i18n.Tr "home.search_finded"}}</span><span id="find_title"></span> | |||
<div class="ui right floated secondary filter menu"> | |||
<!-- Sort --> | |||
<div class="ui right dropdown type jump item"> | |||
<span class="text"> | |||
{{.i18n.Tr "repo.issues.filter_sort"}} | |||
<i class="dropdown icon"></i> | |||
</span> | |||
<div class="menu" id="sort_type"> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui divider" style="margin-top: 1.25rem;"></div> | |||
<div class="ui very relaxed divided list" id="child_search_item"> | |||
</div><!--seach list end--> | |||
<div class="center page buttons" style="margin: 0px auto 15px"> | |||
<div class="ui borderless mini pagination menu" id="page_menu"> | |||
</div> | |||
</div> | |||
<div id="tipmsg"></div> | |||
</div> | |||
</div> | |||
<script src="/self/js/jquery.min.js" type="text/javascript"></script> | |||
<script src="/home/search.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||
<div class="am-mt-30"></div> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,45 @@ | |||
<div id="mask"> | |||
<div id="loadingPage"> | |||
<div class="rect1"></div> | |||
<div class="rect2"></div> | |||
<div class="rect3"></div> | |||
<div class="rect4"></div> | |||
<div class="rect5"></div> | |||
</div> | |||
</div> | |||
{{template "base/head" .}} | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="ui container"> | |||
<input type="hidden" id="dataset-file-desc" value="{{.Attachment.Description}}"> | |||
<div style="width: 80%;margin: auto;"> | |||
<h4 class="ui top attached header"> | |||
{{$.i18n.Tr "dataset.modify_dataset_description"}} | |||
</h4> | |||
<div class="ui attached segment" style="padding: 2em 3em;"> | |||
<div class="ui form" id="dataset-base"> | |||
<el-form label-width="140px"> | |||
{{.CsrfTokenHtml}} | |||
<el-form-item label='{{$.i18n.Tr "dataset.dataset_available_clusters"}}:' prop="title"> | |||
<span style="display: flex;color: #3291F8;"><i class="ri-archive-drawer-line" style="margin-right: 10px;"></i>{{.Attachment.Type | AttachmentResourceType}}</span> | |||
<!-- <span>请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。</span> --> | |||
</el-form-item> | |||
<el-form-item label='{{$.i18n.Tr "dataset.file"}}:' prop="description"> | |||
<span>{{.Attachment.Name}}</span> | |||
</el-form-item> | |||
<el-form-item label='{{$.i18n.Tr "dataset.file_description"}}:' prop="description"> | |||
<el-input type="textarea" :rows="3" maxlength="255" placeholder="{{$.i18n.Tr "repo.modelarts.train_job.new_place"}}" v-model="descfile"></el-input> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button style="background-color: #21ba45;" type="success" @click="editDatasetFile({{.Attachment.ID}},'{{$.RepoLink}}')">确定</el-button> | |||
<el-button type="info" @click="cancelDataset('','{{$.RepoLink}}')">取消</el-button> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,73 @@ | |||
{{template "base/head" .}} | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="ui container"> | |||
<input type="hidden" id="postPath" value="{{.Link}}"> | |||
<div style="width: 80%;margin: auto;"> | |||
<h4 class="ui top attached header"> | |||
{{$.i18n.Tr "dataset.upload_dataset_file"}} | |||
</h4> | |||
<div class="ui attached segment" style="padding: 2em 3em;"> | |||
<div class="ui form" id="dataset-base"> | |||
<el-form label-width="140px"> | |||
{{.CsrfTokenHtml}} | |||
<el-form-item label='{{$.i18n.Tr "dataset.dataset_available_clusters"}}:' prop="title"> | |||
<el-button :class="{active:type==0}" size="small" style="margin: 0;border-radius: 0.28571429rem 0 0 0.28571429rem;" @click="uploadGpu">CPU/GPU</el-button> | |||
<el-button :class="{active:type==1}" size="small" style="margin: 0 0 0 -4px;border-radius: 0 0.28571429rem 0.28571429rem 0;" @click="uploadNpu">NPU</el-button> | |||
<!-- <span>请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。</span> --> | |||
</el-form-item> | |||
<el-form-item label='{{$.i18n.Tr "dataset.file_description"}}:' prop="description"> | |||
<el-input type="textarea" :rows="3" maxlength="255" placeholder="{{$.i18n.Tr "repo.modelarts.train_job.new_place"}}" v-model="desc"></el-input> | |||
</el-form-item> | |||
<el-form-item label='{{$.i18n.Tr "dataset.data_upload"}}:' prop="category"> | |||
<minio-uploader :uploadtype="type" :desc="desc"></minio-uploader> | |||
</el-form-item> | |||
<div style='display:none;' | |||
id="minioUploader-params" | |||
data-uuid="{{.uuid}}" | |||
data-add-url="{{.Repository.OwnerName}}/attachments/add" | |||
data-accepts="{{.AttachmentAllowedTypes}}" | |||
data-remove-url="{{AppSubUrl}}/attachments/delete" | |||
data-csrf="{{.CsrfToken}}" | |||
dataset-id={{.dataset.ID}} | |||
data-max-file="100" | |||
data-dataset-id="{{.dataset.ID}}" | |||
data-max-size="{{.AttachmentMaxSize}}" | |||
data-default-message="{{.i18n.Tr "dropzone.default_message"}}" | |||
data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" | |||
data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" | |||
data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}" | |||
data-file-status='{{.i18n.Tr "dropzone.file_status"}}' | |||
data-file-init-status='{{.i18n.Tr "dropzone.file_init_status"}}' | |||
data-waitting-uploading='{{.i18n.Tr "dropzone.waitting_uploading"}}' | |||
data-md5-computing='{{.i18n.Tr "dropzone.md5_computing"}}' | |||
data-obs-connecting='{{.i18n.Tr "dropzone.obs-connecting"}}' | |||
data-loading-file='{{.i18n.Tr "dropzone.loading_file"}}' | |||
data-upload-complete='{{.i18n.Tr "dropzone.upload_complete"}}' | |||
data-uploading='{{.i18n.Tr "dropzone.uploading"}}' | |||
data-failed='{{.i18n.Tr "dropzone.failed"}}' | |||
data-repopath='{{AppSubUrl}}{{$.RepoLink}}/datasets' | |||
data-cancel='{{.i18n.Tr "cancel"}}' | |||
data-upload='{{.i18n.Tr "dataset.dataset_upload"}}' | |||
> | |||
</div> | |||
<div id="datasetId" datasetId="{{.datasetId}}"></div> | |||
</el-form> | |||
</div> | |||
</div> | |||
</div> | |||
<div style="width: 80%;margin: auto;padding-top: 2em;"> | |||
<!-- <p>说明:<br> | |||
- 只有<span class="text blue">zip格式</span>zip格式的数据集才能发起云脑任务;<br> | |||
- 云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。 | |||
</p> --> | |||
<p style="color: 505559;">{{$.i18n.Tr "dataset.illustrate"}}:</p> | |||
<p style="line-height: 1.5;color: #101010;">{{$.i18n.Tr "dataset.illustrate.only"}}<span class="text red"> {{$.i18n.Tr "dataset.illustrate.zip"}} </span>{{$.i18n.Tr "dataset.illustrate.fisrt_end"}};</br> | |||
{{$.i18n.Tr "dataset.dataset_explain"}}</p> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -155,7 +155,7 @@ | |||
{{end}} | |||
</form> | |||
<a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}" href="{{$.RepoLink}}/cloudbrain/{{.Cloudbrain.ID}}/rate" target="_blank"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
{{$.i18n.Tr "repo.score"}} | |||
</a> | |||
<!-- 删除任务 --> | |||
@@ -185,7 +185,19 @@ | |||
</div> | |||
--> | |||
{{template "base/paginate" .}} | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[10]" | |||
:page-size="10" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -196,7 +196,13 @@ td, th { | |||
<span class="accordion-panel-title-content"> | |||
<span> | |||
<div class="ac-display-inblock title_text acc-margin-bottom"> | |||
<span class="cti-mgRight-sm">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
<span class="cti-mgRight-sm"> | |||
{{if not (eq .StartTime 0)}} | |||
<td>{{TimeSinceUnix1 .StartTime}}</td> | |||
{{else}} | |||
<td>{{TimeSinceUnix1 .CreatedUnix}}<td> | |||
{{end}} | |||
</span> | |||
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
<span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
@@ -252,7 +258,13 @@ td, th { | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
<span style="font-size: 12px;" class=""> | |||
{{if not (eq .StartTime 0)}} | |||
{{TimeSinceUnix1 .StartTime}} | |||
{{else}} | |||
{{TimeSinceUnix1 .CreatedUnix}} | |||
{{end}} | |||
</span> | |||
</div> | |||
</td> | |||
</tr> | |||
@@ -101,6 +101,7 @@ | |||
} | |||
</style> | |||
<div id="mask"> | |||
@@ -116,6 +117,7 @@ | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="repository new repo ui middle very relaxed page grid"> | |||
<div class="column"> | |||
{{template "base/alert" .}} | |||
<div class="ui negative message" id="messageInfo"> | |||
@@ -200,17 +202,8 @@ | |||
{{end}} | |||
</datalist> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "cloudbrain.dataset"}}</label> | |||
<select id="cloudbrain_dataset" class="ui search dropdown" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}" style='width:385px' name="attachment" required> | |||
{{range .attachments}} | |||
<option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
{{end}} | |||
</select> | |||
</div> | |||
{{template "custom/select_dataset" .}} | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "cloudbrain.resource_specification"}}</label> | |||
<select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' name="resource_spec_id"> | |||
@@ -354,4 +347,5 @@ | |||
$('#store_category').attr("value", selected_value) | |||
}) | |||
</script> |
@@ -74,11 +74,19 @@ | |||
</tr> | |||
<tr> | |||
<td> 开始时间 </td> | |||
<td>{{.JobStatus.StartTime}}</td> | |||
{{if not (eq $.task.StartTime 0)}} | |||
<td>{{TimeSinceUnix1 $.task.StartTime}}</td> | |||
{{else}} | |||
<td>无<td> | |||
{{end}} | |||
</tr> | |||
<tr> | |||
<td> 结束时间 </td> | |||
<td>{{.JobStatus.EndTime}}</td> | |||
{{if not (eq $.task.EndTime 0)}} | |||
<td>{{TimeSinceUnix1 $.task.EndTime}}</td> | |||
{{else}} | |||
<td>无<td> | |||
{{end}} | |||
</tr> | |||
<tr> | |||
<td> ExitCode </td> | |||
@@ -0,0 +1,451 @@ | |||
{{template "base/head" .}} | |||
<style> | |||
.unite{ | |||
font-family: SourceHanSansSC-medium !important; | |||
color: rgba(16, 16, 16, 100) !important; | |||
} | |||
.title{ | |||
font-size: 16px !important; | |||
padding-left: 3rem !important; | |||
} | |||
.min_title{ | |||
font-size: 14px !important; | |||
padding-left: 6rem !important; | |||
margin-bottom: 2rem !important; | |||
} | |||
.width{ | |||
width:100% !important; | |||
} | |||
.width80{ | |||
width: 80.7% !important; | |||
margin-left: 10px; | |||
} | |||
.width806{ | |||
width: 80.6% !important; | |||
margin-left: -2px; | |||
} | |||
.width85{ | |||
width: 85% !important; | |||
margin-left: 4.5rem !important; | |||
} | |||
.width81{ | |||
margin-left: 1.5rem !important; | |||
width: 81% !important; | |||
} | |||
.add{font-size: 18px; | |||
padding: 0.5rem; | |||
border: 1px solid rgba(187, 187, 187, 100); | |||
border-radius: 0px 5px 5px 0px; | |||
line-height: 21px; | |||
text-align: center; | |||
color: #C2C7CC; | |||
} | |||
.min{ | |||
font-size: 18px; | |||
padding: 0.5rem; | |||
border: 1px solid rgba(187, 187, 187, 100); | |||
border-radius: 5px 0px 0px 5px; | |||
line-height: 21px; | |||
text-align: center; | |||
color: #C2C7CC; | |||
} | |||
</style> | |||
<!-- <div class="ui page dimmer"> | |||
<div class="ui text loader">{{.i18n.Tr "loading"}}</div> | |||
</div> --> | |||
<div id="mask"> | |||
<div id="loadingPage"> | |||
<div class="rect1"></div> | |||
<div class="rect2"></div> | |||
<div class="rect3"></div> | |||
<div class="rect4"></div> | |||
<div class="rect5"></div> | |||
</div> | |||
</div> | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="ui container"> | |||
{{template "base/alert" .}} | |||
<h4 class="ui top attached header"> | |||
{{.i18n.Tr "repo.modelarts.train_job.new"}} | |||
</h4> | |||
<div class="ui attached segment"> | |||
<!-- equal width --> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
{{.CsrfTokenHtml}} | |||
<input type="hidden" name="action" value="update"> | |||
<input type="hidden" id="ai_engine_name" name="engine_names" value=""> | |||
<input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
<div class="required unite min_title inline field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | |||
<div class="ui blue mini menu compact selectcloudbrain"> | |||
<a class="active item" href="{{.RepoLink}}/cloudbrain/train-job/create"> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
<path fill="none" d="M0 0h24v24H0z"/> | |||
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
</svg> | |||
CPU/GPU | |||
</a> | |||
<a class="item" href="{{.RepoLink}}/modelarts/train-job/create"> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
<path fill="none" d="M0 0h24v24H0z"/> | |||
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
</svg> | |||
Ascend NPU</a> | |||
</div> | |||
</div> | |||
<div class="required unite min_title inline field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
<input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="64"> | |||
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span> | |||
</div> | |||
<div class="unite min_title inline field"> | |||
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 255)"></textarea> | |||
</div> | |||
<div class="ui divider"></div> | |||
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:</h4> | |||
<div class="required unite min_title inline field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||
<select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | |||
{{if .branch_name}} | |||
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | |||
{{range $k, $v :=.Branches}} | |||
{{ if ne $v $.branch_name }} | |||
<option name="branch_name" value="{{$v}}">{{$v}}</option> | |||
{{end}} | |||
{{end}} | |||
{{else}} | |||
<option name="branch_name" value="{{.branchName}}">{{.branchName}}</option> | |||
{{range $k, $v :=.Branches}} | |||
{{ if ne $v $.branchName }} | |||
<option name="branch_name" value="{{$v}}">{{$v}}</option> | |||
{{end}} | |||
{{end}} | |||
{{end}} | |||
</select> | |||
</div> | |||
<div class="inline required field" style="display: none;"> | |||
<label>{{.i18n.Tr "cloudbrain.task_type"}}</label> | |||
<select id="cloudbrain_job_type" class="ui search dropdown" placeholder="选择任务类型" style='width:385px' name="job_type"> | |||
<option name="job_type" value="TRAIN">TRAIN</option> | |||
</select> | |||
</div> | |||
<div class="required unite min_title inline field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label> | |||
<select id="cloudbrain_gpu_type" class="ui search width806 dropdown" placeholder="选择GPU类型" style='width:385px' name="gpu_type"> | |||
{{range .train_gpu_types}} | |||
<option value="{{.Queue}}">{{.Value}}</option> | |||
{{end}} | |||
</select> | |||
</div> | |||
<div class="required unite min_title inline field" style="position: relative;"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.mirror"}} </label> | |||
<input class="width81" type="text" list="cloudbrain_image" placeholder="{{.i18n.Tr "cloudbrain.choose_mirror"}}" name="image" required autofocus maxlength="255"> | |||
<i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||
<datalist class="ui search" id="cloudbrain_image" name="image"> | |||
{{range .images}} | |||
<option name="image" value="{{.Place}}">{{.PlaceView}}</option> | |||
{{end}} | |||
{{range .public_images}} | |||
<option name="image" value="{{.Place}}">{{.PlaceView}}</option> | |||
{{end}} | |||
</datalist> | |||
</div> | |||
<div class="inline unite min_title field required"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||
{{if .bootFile}} | |||
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||
{{else}} | |||
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="" tabindex="3" autofocus required maxlength="255" > | |||
{{end}} | |||
<span> | |||
<i class="question circle icon link" data-content={{.i18n.Tr "repo.modelarts.train_job.boot_file_helper"}} data-position="right center" data-variation="mini"></i> | |||
</span> | |||
<a href="https://git.openi.org.cn/OpenIOSSG/MNIST_PytorchExample_GPU" target="_blank">查看样例</a> | |||
</div> | |||
<div class="required unite min_title inline field" style="position: relative;"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.dataset"}}</label> | |||
<select id="cloudbrain_dataset" class="ui search dropdown width80" placeholder="选择数据集" style='width:385px' name="attachment" required> | |||
{{range .attachments}} | |||
<option name="attachment" value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
{{end}} | |||
</select> | |||
<span class="tooltips">训练脚本存储在/code中,数据集存储在/dataset中,训练输出请存储在/model中以供后续下载。</span> | |||
</div> | |||
<div class="inline unite min_title field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||
<input id="store_run_para" type="hidden" name="run_para_list"> | |||
<div class="dynamic field" style="margin-top: 1rem;"> | |||
{{if .params}} | |||
{{if ne 0 (len .params)}} | |||
{{range $k ,$v := .params}} | |||
<div class="two fields width85" id="para{{$k}}"> | |||
<div class="field"> | |||
<input type="text" name="shipping_first-name" value={{$v.Label}} required> | |||
</div> | |||
<div class="field"> | |||
<input type="text" name="shipping_last-name" value={{$v.Value}} required> | |||
</div> | |||
<span> | |||
<i class="trash icon"></i> | |||
</span> | |||
</div> | |||
{{end}} | |||
{{end}} | |||
{{end}} | |||
</div> | |||
</div> | |||
<div class="required inline unite min_title field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label> | |||
<select id="cloudbrain_resource_spec" class="ui search dropdown" placeholder="选择资源规格" style='width:385px' name="resource_spec_id"> | |||
{{range .train_resource_specs}} | |||
<option name="resource_spec_id" value="{{.Id}}">GPU数:{{.GpuNum}},CPU数:{{.CpuNum}},内存(MB):{{.MemMiB}},共享内存(MB):{{.ShareMemMiB}}</option> | |||
{{end}} | |||
</select> | |||
</div> | |||
<div class="inline unite min_title field"> | |||
<button class="ui create_train_job green button"> | |||
{{.i18n.Tr "repo.cloudbrain.new"}} | |||
</button> | |||
<a class="ui button" href="{{.RepoLink}}/modelarts/train-job">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
</div> | |||
<!-- 模态框 --> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
<script> | |||
//let url_href = window.location.pathname.split('create')[0] | |||
//$(".ui.button").attr('href',url_href) | |||
$('select.dropdown') | |||
.dropdown(); | |||
$('.menu .item') | |||
.tab(); | |||
let sever_num = $('#trainjob_work_server_num') | |||
$('.add').click(function(){ | |||
sever_num.val(parseInt(sever_num.val())+1) | |||
if(sever_num.val()>=26){ | |||
sever_num.val(parseInt(sever_num.val())-1) | |||
} | |||
}) | |||
$('.min').click(function(){ | |||
sever_num.val(parseInt(sever_num.val())-1) | |||
if(sever_num.val()<=0){ | |||
sever_num.val(parseInt(sever_num.val())+1) | |||
} | |||
}) | |||
// 参数增加、删除、修改、保存 | |||
function Add_parameter(i){ | |||
value = '<div class="two fields width85" id= "para'+ i +'">' + | |||
'<div class="field">' + | |||
'<input type="text" name="shipping_first-name" required placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_name"}}> ' + | |||
'</div> ' + | |||
'<div class="field"> ' + | |||
'<input type="text" name="shipping_last-name" required placeholder={{.i18n.Tr "repo.modelarts.train_job.parameter_value"}}>' + | |||
'</div>'+ | |||
'<span>' + | |||
'<i class="trash icon">' + | |||
'</i>' + | |||
'</span>' + | |||
'</div>' | |||
$(".dynamic.field").append(value) | |||
} | |||
$('#add_run_para').click(function(){ | |||
var len = $(".dynamic.field .two.fields").length | |||
Add_parameter(len) | |||
}); | |||
$(".dynamic.field").on("click",".trash.icon", function() { | |||
var index = $(this).parent().parent().index() | |||
$(this).parent().parent().remove() | |||
var len = $(".dynamic.field .two.fields").length | |||
$(".dynamic.field .two.fields").each(function(){ | |||
var cur_index = $(this).index() | |||
$(this).attr('id', 'para' + cur_index) | |||
}) | |||
}); | |||
$('.ui.parameter.green.button').click(function(){ | |||
var parameters = []; | |||
$('table tr').each(function() { | |||
$(this).find('td:eq(1)').each(function(){ | |||
parameters.push($(this).text()); | |||
}) | |||
$(this).find('input').each(function(){ | |||
parameters.push($(this).text()) | |||
}) | |||
}); | |||
$('.ui.parameter.modal') | |||
.modal('hide'); | |||
for(var i = 2; i < parameters.length; i++){ | |||
switch(i) { | |||
// 数据集uuid待完成 | |||
// case (2): | |||
// console.log(1) | |||
// break; | |||
// $("#trainjob_datasets").val(parameters[i]); | |||
// console.log($("#trainjob_datasets").val()) | |||
case (3): | |||
$("input[name='boot_file']").val(parameters[i]); | |||
break; | |||
case (4): | |||
var para = parameters[i].split(" ") | |||
for(var j = 0; j < para.length; j++){ | |||
var para_name = para[j].split('=')[0] | |||
var para_value = para[j].split('=')[1] | |||
var len = $(".dynamic.field .two.fields").length | |||
Add_parameter(len) | |||
var pid = 'para' + len | |||
$(".dynamic.field"+ " #" + pid + "").find("input[name=shipping_first-name]").val(para_name) | |||
$(".dynamic.field"+ " #" + pid + "").find("input[name=shipping_last-name]").val(para_value) | |||
} | |||
break; | |||
// 数据集pool_id待完成 | |||
// case (5): | |||
// $("select[name='pool_id']").val(parameters[i]); | |||
// break; | |||
case (6): | |||
$("input[name='work_server_number']").val(parameters[i]); | |||
break; | |||
} | |||
} | |||
}) | |||
$('.ui.save.checkbox').click(function(){ | |||
$(this).checkbox({ | |||
onChange: function(){ | |||
if ($('.ui.save.checkbox').checkbox('is checked')){ | |||
$('#save_para').removeClass("disabled") | |||
}else{ | |||
$('#save_para').addClass("disabled") | |||
} | |||
} | |||
}); | |||
}) | |||
$('.question.circle.icon').hover(function(){ | |||
$(this).popup('show') | |||
}); | |||
$(".item.active.parameter_config").click(function(){ | |||
$('.ui.parameter.modal') | |||
.modal('setting', 'closable', false) | |||
.modal('show'); | |||
}) | |||
$('.ui.deny.button').click(function(){ | |||
$('.ui.parameter.modal') | |||
.modal('hide'); | |||
}) | |||
$('select.dropdown') | |||
.dropdown(); | |||
function validate(){ | |||
$('.ui.form') | |||
.form({ | |||
on: 'blur', | |||
fields: { | |||
boot_file: { | |||
identifier : 'boot_file', | |||
rules: [ | |||
{ | |||
type: 'regExp[/.+\.py$/g]', | |||
} | |||
] | |||
}, | |||
display_job_name:{ | |||
identifier : 'display_job_name', | |||
rules: [ | |||
{ | |||
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]', | |||
} | |||
] | |||
}, | |||
attachment:{ | |||
identifier : 'attachment', | |||
rules: [ | |||
{ | |||
type: 'empty', | |||
} | |||
] | |||
}, | |||
work_server_number: { | |||
identifier : 'work_server_number', | |||
rules: [ | |||
{ | |||
type : 'integer[1..25]', | |||
} | |||
] | |||
} | |||
}, | |||
onSuccess: function(){ | |||
// $('.ui.page.dimmer').dimmer('show') | |||
document.getElementById("mask").style.display = "block" | |||
}, | |||
onFailure: function(e){ | |||
return false; | |||
} | |||
}) | |||
} | |||
document.onreadystatechange = function() { | |||
if (document.readyState === "complete") { | |||
document.getElementById("mask").style.display = "none" | |||
} | |||
} | |||
function send_run_para(){ | |||
var run_parameters = [] | |||
var msg = {} | |||
$(".dynamic.field .two.fields").each(function(){ | |||
var para_name = $(this).find('input[name=shipping_first-name]').val() | |||
var para_value = $(this).find('input[name=shipping_last-name]').val() | |||
run_parameters.push({"label": para_name, "value": para_value}) | |||
}) | |||
msg["parameter"] = run_parameters | |||
msg = JSON.stringify(msg) | |||
$('#store_run_para').val(msg) | |||
} | |||
function get_name(){ | |||
let name1=$("#engine_name .text").text() | |||
let name2=$("#flaver_name .text").text() | |||
$("input#ai_engine_name").val(name1) | |||
$("input#ai_flaver_name").val(name2) | |||
} | |||
$('.ui.create_train_job.green.button').click(function(e) { | |||
get_name() | |||
send_run_para() | |||
validate() | |||
}) | |||
</script> |
@@ -0,0 +1,653 @@ | |||
{{template "base/head" .}} | |||
<style> | |||
.according-panel-heading{ | |||
box-sizing: border-box; | |||
padding: 8px 16px; | |||
color: #252b3a; | |||
background-color: #f2f5fc; | |||
line-height: 1.5; | |||
cursor: pointer; | |||
-moz-user-select: none; | |||
-webkit-user-select: none; | |||
-ms-user-select: none; | |||
-khtml-user-select: none; | |||
user-select: none; | |||
} | |||
.accordion-panel-title { | |||
margin-top: 0; | |||
margin-bottom: 0; | |||
color: #252b3a; | |||
} | |||
.accordion-panel-title-content{ | |||
vertical-align: middle; | |||
display: inline-block; | |||
width: calc(100% - 32px); | |||
cursor: default; | |||
} | |||
.acc-margin-bottom { | |||
margin-bottom: 5px; | |||
} | |||
.title_text { | |||
font-size: 12px; | |||
} | |||
.ac-display-inblock { | |||
display: inline-block; | |||
} | |||
.cti-mgRight-sm { | |||
margin-right: 8px; | |||
} | |||
.ac-text-normal { | |||
font-size: 14px; | |||
color: #575d6c; | |||
} | |||
.uc-accordionTitle-black { | |||
color: #333; | |||
} | |||
.accordion-border{ | |||
border:1px solid #cce2ff; | |||
} | |||
.padding0{ | |||
padding: 0 !important; | |||
} | |||
.content-pad{ | |||
padding: 15px 35px; | |||
} | |||
.content-margin{ | |||
margin:10px 5px ; | |||
} | |||
.tab_2_content { | |||
min-height: 360px; | |||
margin-left: 10px; | |||
} | |||
.ac-grid { | |||
display: block; | |||
*zoom: 1; | |||
} | |||
.ac-grid-col { | |||
float: left; | |||
width: 100%; | |||
} | |||
.ac-grid-col2 .ac-grid-col { | |||
width: 50%; | |||
} | |||
.ti-form { | |||
text-align: left; | |||
max-width: 100%; | |||
vertical-align: middle; | |||
} | |||
.ti-form>tbody { | |||
font-size: 12px; | |||
} | |||
.ti-form>tbody, .ti-form>tbody>tr { | |||
vertical-align: inherit; | |||
} | |||
.ti-text-form-label { | |||
padding-bottom: 20px; | |||
padding-right: 20px; | |||
color: #8a8e99; | |||
font-size: 12px; | |||
white-space: nowrap !important; | |||
width: 80px; | |||
line-height: 30px; | |||
} | |||
.ti-text-form-content{ | |||
line-height: 30px; | |||
padding-bottom: 20px; | |||
} | |||
.ti-form>tbody>tr>td { | |||
vertical-align: top; | |||
white-space: normal; | |||
} | |||
td, th { | |||
padding: 0; | |||
} | |||
.ac-grid-col .text-span { | |||
width: 450px; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
white-space: nowrap; | |||
} | |||
.redo-color{ | |||
color: #3291F8; | |||
} | |||
.ti-action-menu-item:not(:last-child){ | |||
margin-right: 10px; | |||
padding-right: 11px; | |||
text-decoration: none!important; | |||
color: #526ecc; | |||
cursor: pointer; | |||
display: inline-block; | |||
-moz-user-select: none; | |||
-webkit-user-select: none; | |||
-ms-user-select: none; | |||
-khtml-user-select: none; | |||
user-select: none; | |||
position: relative; | |||
} | |||
.ti-action-menu-item:not(:last-child):after { | |||
content: ""; | |||
display: inline-block; | |||
position: absolute; | |||
height: 12px; | |||
right: 0; | |||
top: 50%; | |||
-webkit-transform: translateY(-6px); | |||
-ms-transform: translateY(-6px); | |||
-o-transform: translateY(-6px); | |||
transform: translateY(-6px); | |||
border-right: 1px solid #dfe1e6; | |||
} | |||
.text-width80{ | |||
width: 100px; | |||
line-height: 30px; | |||
} | |||
.border-according{ | |||
border: 1px solid #dfe1e6; | |||
} | |||
.disabled { | |||
cursor: default; | |||
pointer-events: none; | |||
color: rgba(0,0,0,.6) !important; | |||
opacity: .45 !important; | |||
} | |||
.pad20{ | |||
border:0px !important; | |||
} | |||
.model_file_bread{ | |||
margin-bottom: -0.5rem !important; | |||
padding-left: 1rem; | |||
padding-top: 0.5rem ; | |||
} | |||
</style> | |||
<div id="mask"> | |||
<div id="loadingPage"> | |||
<div class="rect1"></div> | |||
<div class="rect2"></div> | |||
<div class="rect3"></div> | |||
<div class="rect4"></div> | |||
<div class="rect5"></div> | |||
</div> | |||
</div> | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="ui container"> | |||
<h4 class="ui header" id="vertical-segment"> | |||
<div class="ui breadcrumb"> | |||
<a class="section" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
{{.i18n.Tr "repo.cloudbrain"}} | |||
</a> | |||
<div class="divider"> / </div> | |||
<a class="section" href="{{$.RepoLink}}/modelarts/train-job"> | |||
{{$.i18n.Tr "repo.modelarts.train_job"}} | |||
</a> | |||
<div class="divider"> / </div> | |||
<div class="active section">{{.displayJobName}}</div> | |||
</div> | |||
</h4> | |||
{{range $k ,$v := .version_list_task}} | |||
<div class="ui accordion border-according" id="accordion{{.VersionName}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
<input type="hidden" id="jobId_input" name="jobId_input" value="{{.JobID}}"> | |||
<div class="{{if eq $k 0}}active{{end}} title padding0"> | |||
<div class="according-panel-heading"> | |||
<div class="accordion-panel-title"> | |||
<i class="dropdown icon"></i> | |||
<span class="accordion-panel-title-content"> | |||
<span> | |||
<div class="ac-display-inblock title_text acc-margin-bottom"> | |||
<span class="cti-mgRight-sm">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
<span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
</span> | |||
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span> | |||
<span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{$.duration}}</span> | |||
</div> | |||
</span> | |||
</span> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="{{if eq $k 0}}active{{end}} content"> | |||
<div class="content-pad"> | |||
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||
<a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||
<a class="item" data-tab="second{{$k}}" onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a> | |||
<a class="item" data-tab="third{{$k}}" onclick="loadModelFile({{.VersionName}},'','','init')">{{$.i18n.Tr "repo.model_download"}}</a> | |||
</div> | |||
<div class="ui tab active" data-tab="first{{$k}}"> | |||
<div style="padding-top: 10px;"> | |||
<div class="tab_2_content"> | |||
<div class="ac-grid ac-grid-col2"> | |||
<div class="ac-grid-col"> | |||
<table class="ti-form"> | |||
<tbody class="ti-text-form"> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.cloudbrain_task"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
{{.DisplayJobName}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.status"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w" id="{{.VersionName}}-status"> | |||
{{.Status}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.start_time"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w" id="{{.VersionName}}-duration"> | |||
{{$.duration}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.resource_type"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
{{$.resource_type}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.standard"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
{{$.resource_spec}} | |||
</div> | |||
</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</div> | |||
<div class="ac-grid-col"> | |||
<table class="ti-form"> | |||
<tbody class="ti-text-form"> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
镜像 | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w" id="{{.VersionName}}-mirror"> | |||
{{.Image}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.code_version"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
{{.BranchName}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.start_file"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
{{.BootFile}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
{{.DatasetName}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80" > | |||
{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w" title="{{.Parameters}}"> | |||
{{.Parameters}} | |||
</div> | |||
</td> | |||
</tr> | |||
<tr class="ti-no-ng-animate"> | |||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
{{$.i18n.Tr "repo.modelarts.train_job.description"}} | |||
</td> | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w" title="{{.Description}}"> | |||
{{.Description}} | |||
</div> | |||
</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui tab" data-tab="second{{$k}}"> | |||
<div> | |||
<div class="ui message message{{.VersionName}}" style="display: none;"> | |||
<div id="header"></div> | |||
</div> | |||
<div class="ui attached log" id="log{{.VersionName}}" style="height: 300px !important; overflow: auto;"> | |||
<input type="hidden" name="end_line" value> | |||
<input type="hidden" name="start_line" value> | |||
<pre id="log_file{{.VersionName}}"></pre> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui tab" data-tab="third{{$k}}"> | |||
<input type="hidden" name="model{{.VersionName}}" value="-1"> | |||
<input type="hidden" name="modelback{{.VersionName}}" value="-1"> | |||
<div class='ui breadcrumb model_file_bread' id='file_breadcrumb{{.VersionName}}'> | |||
<div class="active section">{{.VersionName}}</div> | |||
<div class="divider"> / </div> | |||
</div> | |||
<div id="dir_list{{.VersionName}}"> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} {{template "base/paginate" .}} | |||
</div> | |||
<!-- 确认模态框 --> | |||
<div id="deletemodel"> | |||
<div class="ui basic modal"> | |||
<div class="ui icon header"> | |||
<i class="trash icon"></i> 删除任务 | |||
</div> | |||
<div class="content"> | |||
<p>你确认删除该任务么?此任务一旦删除不可恢复。</p> | |||
</div> | |||
<div class="actions"> | |||
<div class="ui red basic inverted cancel button"> | |||
<i class="remove icon"></i> 取消操作 | |||
</div> | |||
<div class="ui green basic inverted ok button"> | |||
<i class="checkmark icon"></i> 确定操作 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
<script> | |||
$('.menu .item').tab() | |||
$(document).ready(function(){ | |||
$('.ui.accordion').accordion({selector:{trigger:'.icon'}}); | |||
}); | |||
$(document).ready(function(){ | |||
$('.secondary.menu .item').tab(); | |||
}); | |||
let userName | |||
let repoPath | |||
let jobID | |||
let downlaodFlag = {{$.canDownload}} | |||
let taskID = {{$.task.ID}} | |||
let realJobName = {{$.task.JobName}} | |||
$(document).ready(function(){ | |||
let url = window.location.href; | |||
let urlArr = url.split('/') | |||
userName = urlArr.slice(-5)[0] | |||
repoPath = urlArr.slice(-4)[0] | |||
jobID = urlArr.slice(-1)[0] | |||
}) | |||
function stopBubbling(e) { | |||
e = window.event || e; | |||
if (e.stopPropagation) { | |||
e.stopPropagation(); //阻止事件 冒泡传播 | |||
} else { | |||
e.cancelBubble = true; //ie兼容 | |||
} | |||
} | |||
let timeid = window.setInterval(loadJobStatus, 30000); | |||
$(document).ready(loadJobStatus); | |||
function loadLog(version_name){ | |||
document.getElementById("mask").style.display = "block" | |||
$.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${taskID}/log?version_name=${version_name}&lines=50&order=asc`, (data) => { | |||
$('input[name=end_line]').val(data.EndLine) | |||
$('input[name=start_line]').val(data.StartLine) | |||
$(`#log_file${version_name}`).text(data.Content) | |||
document.getElementById("mask").style.display = "none" | |||
}).fail(function(err) { | |||
console.log(err); | |||
document.getElementById("mask").style.display = "none" | |||
}); | |||
} | |||
function loadModelFile(version_name,parents,filename,init){ | |||
parents = parents || '' | |||
filename = filename || '' | |||
init = init || '' | |||
console.log("start") | |||
$.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/train-job/${jobID}/model_list?version_name=${version_name}&parentDir=${parents}`, (data) => { | |||
$(`#dir_list${version_name}`).empty() | |||
renderDir(data,version_name) | |||
if(init==="init"){ | |||
$(`input[name=model${version_name}]`).val("") | |||
$(`input[name=modelback${version_name}]`).val(version_name) | |||
$(`#file_breadcrumb${version_name}`).empty() | |||
let htmlBread = "" | |||
htmlBread += `<div class='active section'>${version_name}</div>` | |||
htmlBread += "<div class='divider'> / </div>" | |||
$(`#file_breadcrumb${version_name}`).append(htmlBread) | |||
}else{ | |||
renderBrend(version_name,parents,filename,init) | |||
} | |||
}).fail(function(err) { | |||
console.log(err,version_name); | |||
}); | |||
} | |||
function renderBrend(version_name,parents,filename,init){ | |||
if(init=="folder"){ | |||
let htmlBrend = "" | |||
let sectionName=$(`#file_breadcrumb${version_name} .active.section`).text() | |||
let parents1 = $(`input[name=model${version_name}]`).val() | |||
let filename1 = $(`input[name=modelback${version_name}]`).val() | |||
if(parents1===""){ | |||
$(`#file_breadcrumb${version_name} .active.section`).replaceWith(`<a class='section' onclick="loadModelFile('${version_name}','${parents1}','','init')">${sectionName}</a>`) | |||
}else{ | |||
$(`#file_breadcrumb${version_name} .active.section`).replaceWith(`<a class='section' onclick="loadModelFile('${version_name}','${parents1}','${filename1}')">${sectionName}</a>`) | |||
} | |||
htmlBrend += `<div class='active section'>${filename}</div>` | |||
htmlBrend += "<div class='divider'> / </div>" | |||
$(`#file_breadcrumb${version_name}`).append(htmlBrend) | |||
$(`input[name=model${version_name}]`).val(parents) | |||
$(`input[name=modelback${version_name}]`).val(filename) | |||
}else{ | |||
$(`input[name=model${version_name}]`).val(parents) | |||
$(`input[name=modelback${version_name}]`).val(filename) | |||
$(`#file_breadcrumb${version_name} a.section:contains(${filename})`).nextAll().remove() | |||
$(`#file_breadcrumb${version_name} a.section:contains(${filename})`).replaceWith(`<div class='active section'>${filename}</div>`) | |||
$(`#file_breadcrumb${version_name} div.section:contains(${filename})`).append("<div class='divider'> / </div>") | |||
} | |||
} | |||
function renderDir(data,version_name){ | |||
let html="" | |||
html += "<div class='ui grid' style='margin:0;'>" | |||
html += "<div class='row' style='padding: 0;'>" | |||
html += "<div class='ui sixteen wide column' style='padding:1rem;'>" | |||
html += "<div class='dir list'>" | |||
html += "<table id='repo-files-table' class='ui single line table pad20'>" | |||
html += '<tbody>' | |||
// html += "</tbody>" | |||
for(let i=0;i<data.Dirs.length;i++){ | |||
let dirs_size = renderSize(data.Dirs[i].Size) | |||
html += "<tr>" | |||
html += "<td class='name six wid'>" | |||
html += "<span class='truncate'>" | |||
html += "<span class='octicon octicon-file-directory'>" | |||
html += "</span>" | |||
if(data.Dirs[i].IsDir){ | |||
html += `<a onclick="loadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].FileName}','folder')">` | |||
html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | |||
}else{ | |||
if(downlaodFlag){ | |||
html += `<a href="${location.href}/download_model?version_name=${version_name}&fileName=${data.Dirs[i].FileName}&parentDir=${data.Dirs[i].ParenDir}&jobName=${realJobName}">` | |||
} | |||
else{ | |||
html += `<a class="disabled">` | |||
} | |||
html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | |||
} | |||
html += '</a>' | |||
html += "</span>" | |||
html += "</td>" | |||
html += "<td class='message seven wide'>" | |||
if(data.Dirs[i].IsDir){ | |||
html += "<span class='truncate has-emoji'></span>" | |||
}else{ | |||
html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||
} | |||
html += "</td>" | |||
html += "<td class='text right age three wide'>" | |||
html += "<span class='truncate has-emoji'>" + data.Dirs[i].ModTime + "</span>" | |||
html += "</td>" | |||
html += "</tr>" | |||
} | |||
html += "</tbody>" | |||
html += "</table>" | |||
html += "</div>" | |||
html += "</div>" | |||
html += "</div>" | |||
html += "</div>" | |||
$(`#dir_list${version_name}`).append(html) | |||
} | |||
function renderSize(value){ | |||
if(null==value||value==''){ | |||
return "0 Bytes"; | |||
} | |||
var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"); | |||
var index=0; | |||
var srcsize = parseFloat(value); | |||
index=Math.floor(Math.log(srcsize)/Math.log(1024)); | |||
var size =srcsize/Math.pow(1024,index); | |||
size=size.toFixed(0);//保留的小数位数 | |||
return size+unitArr[index]; | |||
} | |||
function loadJobStatus() { | |||
$(".ui.accordion.border-according").each((index, job) => { | |||
const jobID = job.dataset.jobid; | |||
const repoPath = job.dataset.repopath; | |||
const versionname = job.dataset.version | |||
// ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'] | |||
// if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||
// || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||
// || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||
// return | |||
// } | |||
let status = $(`#${versionname}-status-span`).text() | |||
if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED','SUCCEEDED'].includes(status)){ | |||
return | |||
} | |||
let stopArray=["KILLED","FAILED","START_FAILED","KILLING","COMPLETED","SUCCEEDED"] | |||
$.get(`/api/v1/repos/${repoPath}/cloudbrain/${taskID}?version_name=${versionname}`, (data) => { | |||
//$(`#${versionname}-duration-span`).text(data.JobDuration) | |||
$(`#${versionname}-status-span span`).text(data.JobStatus) | |||
$(`#${versionname}-status-span i`).attr("class",data.JobStatus) | |||
// detail status and duration | |||
//$('#'+versionname+'-duration').text(data.JobDuration) | |||
$('#'+versionname+'-status').text(data.JobStatus) | |||
if(stopArray.includes(data.JobStatus)){ | |||
$('#'+versionname+'-stop').addClass('disabled') | |||
} | |||
if(data.JobStatus==="COMPLETED"){ | |||
$('#'+versionname+'-create-model').removeClass('disabled').addClass('blue') | |||
} | |||
}).fail(function(err) { | |||
console.log(err); | |||
}); | |||
}); | |||
}; | |||
function refreshStatus(version_name){ | |||
$.get(`/api/v1/repos/${userName}/${repoPath}/cloudbrain/${taskID}?version_name=${versionname}`,(data)=>{ | |||
// header status and duration | |||
//$(`#${version_name}-duration-span`).text(data.JobDuration) | |||
$(`#${version_name}-status-span span`).text(data.JobStatus) | |||
$(`#${version_name}-status-span i`).attr("class",data.JobStatus) | |||
// detail status and duration | |||
//$('#'+version_name+'-duration').text(data.JobDuration) | |||
$('#'+version_name+'-status').text(data.JobStatus) | |||
loadLog(version_name) | |||
}).fail(function(err) { | |||
console.log(err); | |||
}); | |||
stopBubbling(arguments.callee.caller.arguments[0]) | |||
} | |||
</script> |
@@ -0,0 +1,69 @@ | |||
<style> | |||
#dataset-base>.field>label{ | |||
width:120px !important; | |||
text-align:right !important; | |||
} | |||
</style> | |||
<div id="mask"> | |||
<div id="loadingPage"> | |||
<div class="rect1"></div> | |||
<div class="rect2"></div> | |||
<div class="rect3"></div> | |||
<div class="rect4"></div> | |||
<div class="rect5"></div> | |||
</div> | |||
</div> | |||
{{template "base/head" .}} | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="ui container"> | |||
<input type="hidden" id="postPath" value="{{.Link}}"> | |||
<div style="width: 80%;margin: auto;"> | |||
<h4 class="ui top attached header"> | |||
{{.i18n.Tr "dataset.create_new_dataset"}} | |||
</h4> | |||
<div class="ui attached segment" style="padding: 2em 3em;"> | |||
<div class="ui form" id="dataset-base"> | |||
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="140px"> | |||
{{.CsrfTokenHtml}} | |||
<el-form-item label='{{.i18n.Tr "dataset.dataset_name"}}' prop="title"> | |||
<el-input v-model="ruleForm.title"></el-input> | |||
<span style="font-size: 12px;color: #888;line-height: 1;margin-top: 0.5em;display: inline-block;">{{.i18n.Tr "dataset.dataset_name_tooltips"}}</span> | |||
<!-- <span>请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。</span> --> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "dataset.dataset_description"}}' prop="description"> | |||
<el-input type="textarea" :rows="3" maxlength="1024" placeholder="{{.i18n.Tr "dataset.dataset_desc"}}" v-model="ruleForm.description"></el-input> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "dataset.category"}}' prop="category"> | |||
<el-select v-model="ruleForm.category" placeholder='{{.i18n.Tr "dataset.select_category"}}' style="width: 60%;"> | |||
{{range $category := categories}} | |||
<el-option label='{{$.i18n.Tr (printf "dataset.category.%s" $category)}}' value='{{$category}}'></el-option> | |||
{{end}} | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "dataset.task"}}' prop="task"> | |||
<el-select v-model="ruleForm.task" placeholder='{{.i18n.Tr "dataset.select_task"}}' style="width: 60%;"> | |||
{{range $task := tasks}} | |||
<el-option label='{{$.i18n.Tr (printf "dataset.task.%s" $task)}}' value='{{$task}}'></el-option> | |||
{{end}} | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "repo.license"}}' prop="license"> | |||
<el-select v-model="ruleForm.license" placeholder='{{.i18n.Tr "repo.license_helper"}}' style="width: 60%;"> | |||
{{range $license := licenses}} | |||
<el-option label='{{$license}}' value='{{$license}}'></el-option> | |||
{{end}} | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button style="background-color: #21ba45;" type="success" @click="createDataset('ruleForm')">{{.i18n.Tr "repo.confirm_choice"}}</el-button> | |||
<el-button type="info" @click="cancelDataset('create','')">{{.i18n.Tr "cancel"}}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,72 @@ | |||
<style> | |||
#dataset-base>.field>label{ | |||
width:120px !important; | |||
text-align:right !important; | |||
} | |||
</style> | |||
<div id="mask"> | |||
<div id="loadingPage"> | |||
<div class="rect1"></div> | |||
<div class="rect2"></div> | |||
<div class="rect3"></div> | |||
<div class="rect4"></div> | |||
<div class="rect5"></div> | |||
</div> | |||
</div> | |||
{{template "base/head" .}} | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<div class="ui container"> | |||
<input type="hidden" id="postPath" value="{{.Link}}"> | |||
<div style="width: 80%;margin: auto;"> | |||
<h4 class="ui top attached header"> | |||
{{.i18n.Tr "dataset.modify_dataset"}} | |||
</h4> | |||
<div id="dataset-edit-value" style="display: none;" data-edit-id="{{.Dataset.ID}}" data-edit-title="{{.Dataset.Title}}" data-edit-description="{{.Dataset.Description}}" | |||
data-edit-category="{{.Dataset.Category}}" data-edit-task="{{.Dataset.Task}}" data-edit-license="{{.Dataset.License}}"> | |||
</div> | |||
<div class="ui attached segment" style="padding: 2em 3em;"> | |||
<div class="ui form" id="dataset-base"> | |||
<el-form :model="ruleForm1" :rules="rules" ref="ruleForm" label-width="140px"> | |||
{{.CsrfTokenHtml}} | |||
<el-form-item label='{{.i18n.Tr "dataset.dataset_name"}}' prop="title"> | |||
<el-input v-model="ruleForm1.title"></el-input> | |||
<span style="font-size: 12px;color: #888;line-height: 1;margin-top: 0.5em;display: inline-block;">{{.i18n.Tr "dataset.dataset_name_tooltips"}}</span> | |||
<!-- <span>请输入字母、数字、_和-,最长64个字符,且不能以中划线(-)结尾。</span> --> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "dataset.dataset_description"}}' prop="description"> | |||
<el-input type="textarea" :rows="3" maxlength="1024" placeholder="{{.i18n.Tr "dataset.dataset_desc"}}" v-model="ruleForm1.description"></el-input> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "dataset.category"}}' prop="category"> | |||
<el-select v-model="ruleForm1.category" placeholder='{{.i18n.Tr "dataset.select_category"}}' style="width: 60%;"> | |||
{{range $category := categories}} | |||
<el-option label='{{$.i18n.Tr (printf "dataset.category.%s" $category)}}' value='{{$category}}'></el-option> | |||
{{end}} | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "dataset.task"}}' prop="task"> | |||
<el-select v-model="ruleForm1.task" placeholder='{{.i18n.Tr "dataset.select_task"}}' style="width: 60%;"> | |||
{{range $task := tasks}} | |||
<el-option label='{{$.i18n.Tr (printf "dataset.task.%s" $task)}}' value='{{$task}}'></el-option> | |||
{{end}} | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item label='{{.i18n.Tr "repo.license"}}' prop="license"> | |||
<el-select v-model="ruleForm1.license" placeholder='{{.i18n.Tr "repo.license_helper"}}' style="width: 60%;"> | |||
{{range $license := licenses}} | |||
<el-option label='{{$license}}' value='{{$license}}'></el-option> | |||
{{end}} | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button style="background-color: #21ba45;" type="success" @click="editDataset('ruleForm',{{.Dataset.ID}})">{{.i18n.Tr "repo.confirm_choice"}}</el-button> | |||
<el-button type="info" @click="cancelDataset('edit','')">{{.i18n.Tr "cancel"}}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -6,145 +6,341 @@ | |||
margin: -1px; | |||
background: #FFF !important; | |||
} | |||
.dataset_title{ | |||
font-size: 14px; | |||
max-width: 80%; | |||
display: inline-block !important; | |||
margin-left: 6px !important; | |||
padding-right: 0 !important; | |||
} | |||
.wrapper { | |||
display: flex; | |||
overflow: hidden; | |||
padding: 0 1rem; | |||
} | |||
.exp{ | |||
display: none; | |||
} | |||
.exp:checked+.text{ | |||
max-height: none; | |||
} | |||
.exp:checked+.text::after{ | |||
visibility: hidden; | |||
} | |||
.exp:checked+.text .btn::before{ | |||
visibility: hidden; | |||
} | |||
.exp:checked+.text .btn::after{ | |||
content:'{{$.i18n.Tr "org.fold"}}' | |||
} | |||
.wrapper>.text { | |||
font-family: SourceHanSansSC-regular; | |||
font-size: 14px; | |||
color: #101010; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
text-align: justify; | |||
position: relative; | |||
line-height: 1.5; | |||
max-height: 3em; | |||
transition: .3s max-height; | |||
word-wrap: break-word; | |||
word-break: break-all; | |||
} | |||
.wrapper>.text::before { | |||
content: ''; | |||
height: calc(100% - 20px); | |||
float: right; | |||
} | |||
.wrapper>.text::after { | |||
content: ''; | |||
width: 999vw; | |||
height: 999vw; | |||
position: absolute; | |||
box-shadow: inset calc(100px - 999vw) calc(30px - 999vw) 0 0 #fff; | |||
margin-left: -100px; | |||
} | |||
.btn{ | |||
position: relative; | |||
float: right; | |||
clear: both; | |||
margin-left: 20px; | |||
font-size: 14px; | |||
padding: 0 8px; | |||
background: #3F51B5; | |||
line-height: 20px; | |||
border-radius: 4px; | |||
color: #fff; | |||
cursor: pointer; | |||
/* margin-top: -30px; */ | |||
} | |||
.btn::after{ | |||
content:'{{$.i18n.Tr "org.unfold"}}' | |||
} | |||
.btn::before{ | |||
content: '...'; | |||
position: absolute; | |||
left: -5px; | |||
color: #333; | |||
transform: translateX(-100%) | |||
} | |||
.el-button--text{color:#0366d6 ;} | |||
.heart-stroke{ | |||
stroke: #666; | |||
stroke-width: 2; | |||
fill: #fff | |||
} | |||
.stars_active{ | |||
fill: #FA8C16 !important; | |||
stroke:#FA8C16 !important | |||
} | |||
.diy-popper{ | |||
max-width: 400px; | |||
} | |||
</style> | |||
<div class="repository release dataset-list view"> | |||
<div class="repository"> | |||
{{template "repo/header" .}} | |||
<script> | |||
$(document).ready(function() { | |||
const params = new URLSearchParams(window.location.search); | |||
if (params.get('type') == 0){ | |||
$('.contorl_component').attr("id", 'minioUploader') | |||
}else{ | |||
$('.contorl_component').attr("id", 'obsUploader') | |||
} | |||
}); | |||
</script> | |||
<form class="ui container" action="{{.Link}}" method="post"> | |||
<input name="id" value="{{.dataset.ID}}" type="hidden" /> | |||
<!-- | |||
<span class="alert" style="font-size:20px;color:red"> | |||
<strong>{{.i18n.Tr "dataset.alert"}}</strong> | |||
</span> | |||
--> | |||
<div id="datasetId" datasetId="{{.dataset.ID}}"> | |||
{{.CsrfTokenHtml}} | |||
{{template "base/alert" .}} | |||
<div class="ui stackable grid {{if .Error}}hide{{end}}" id="dataset-content"> | |||
<div class="row"> | |||
<div class="column sixteen {{if .Permission.CanWrite $.UnitTypeDatasets}}twelve{{end}} wide"> | |||
<h2>{{.dataset.Title}}</h2> | |||
</div> | |||
{{if .Permission.CanWrite $.UnitTypeDatasets}} | |||
<div class="column four wide right aligned"> | |||
<a class="ui green button" href="javascript:void(0)" id="dataset-edit"> | |||
{{.i18n.Tr "dataset.edit"}} | |||
</a> | |||
</div> | |||
{{end}} | |||
</div> | |||
<div class="row"> | |||
<div class="column sixteen wide"> | |||
{{if .dataset.Description }} | |||
<span class="no-description text-italic">{{.dataset.Description}}</span> | |||
{{else}} | |||
<span class="no-description text-italic">{{.Repository.DescriptionHTML}}</span> | |||
{{if .dataset}} | |||
<div id="dataset-range-value" data-num-stars="{{.dataset.NumStars}}" data-star-active="{{$.IsStaringDataset}}" style="display: none;"> | |||
{{range .Attachments}} | |||
<div class="item" data-private="{{.IsPrivate}}" data-decompress-state="{{.DecompressState}}"></div> | |||
{{end}} | |||
</div> | |||
<div id="dataset-base"> | |||
<div class="ui container"> | |||
<div class="ui mobile reversed stackable grid"> | |||
<div class="row"> | |||
<div class="column thirteen wide"><h2>{{.dataset.Title}}</h2></div> | |||
<div class="column three wide right aligned"> | |||
<span style="display: flex;align-items: center;justify-content: flex-end;height: 36px;"> | |||
{{if $.IsSigned}} | |||
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;" @click="postStar({{.dataset.ID}},'{{.Link}}')"> | |||
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke" :class='{stars_active:star_active}'><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg> | |||
</div> | |||
<span style="line-height: 1;">${num_stars}</span> | |||
{{else}} | |||
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;"> | |||
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke" :class='{stars_active:star_active}'><path d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z"></path></svg> | |||
</div> | |||
<span style="line-height: 1;">${num_stars}</span> | |||
{{end}} | |||
<a style="margin-left:30px;" href="{{.RepoLink}}/datasets/edit/{{.dataset.ID}}" class="ui primary basic mini {{if not $.CanWrite}} disabled {{end}} button">{{.i18n.Tr "repo.modelarts.modify"}}</a> | |||
</span> | |||
</div> | |||
{{if or (.dataset.Category) (.dataset.Task) (.dataset.License)}} | |||
<div class="column thirteen wide"> | |||
{{if .dataset.Category}} | |||
{{$category := .dataset.Category}} | |||
<a class="ui repo-topic label topic" href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{.dataset.Category}}&task={{$.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.category.%s" $category)}}</a> | |||
{{end}} | |||
{{if .dataset.Task}} | |||
{{$task := .dataset.Task}} | |||
<a class="ui repo-topic label topic" href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{.dataset.Task}}&license={{$.License}}">{{$.i18n.Tr (printf "dataset.task.%s" $task)}}</a> | |||
{{end}} | |||
{{if .dataset.License}} | |||
<a class="ui repo-topic label topic" href="{{AppSubUrl}}/explore/datasets?sort={{$.SortType}}&q={{$.Keyword}}&tab={{$.TabName}}&category={{$.Category}}&task={{$.Task}}&license={{.dataset.License}}">{{.dataset.License}}</a> | |||
{{end}} | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui grid form segment success {{if not .Error}}hide{{end}}" id="dataset-content-edit"> | |||
<label class="d-block">{{.i18n.Tr "dataset.title"}}</label> | |||
<div class="sixteen wide column"> | |||
<input name="title" placeholder='{{.i18n.Tr "dataset.title"}}' value="{{.dataset.Title}}" autofocus required maxlength="255"> | |||
</div> | |||
<label class="d-block">{{.i18n.Tr "dataset.description"}}</label> | |||
<div class="sixteen wide column"> | |||
<textarea name="description" rows="3">{{.dataset.Description}}</textarea> | |||
</div> | |||
<input name="type" value="{{.Type}}" type="hidden" /> | |||
<div class="sixteen wide column"> | |||
<a class="ui button" id="cancel">{{.i18n.Tr "cancel"}}</a> | |||
<button class="ui green button" id="submit">{{.i18n.Tr "dataset.update_dataset"}}</button> | |||
</div> | |||
</div> | |||
<div class="ui blue mini menu selectcloudbrain"> | |||
<a class="{{if eq .Type 0}}active {{end}}item" href="{{.RepoLink}}/datasets?type=0">{{svg "octicon-server" 16}} CPU / GPU</a> | |||
<a class="{{if eq .Type 1}}active {{end}}item" href="{{.RepoLink}}/datasets?type=1">{{svg "octicon-server" 16}} Ascend NPU</a> | |||
</div> | |||
<div class="ui stackable grid"> | |||
<div class="twelve wide column"> | |||
<div class="ui sixteen wide column"> | |||
<div class="ui two column stackable grid"> | |||
<div class="column"> | |||
<strong>{{if eq .Type 0}}{{.i18n.Tr "repo.cloudbrain1"}}{{else}}{{.i18n.Tr "repo.cloudbrain2"}}{{end}}-{{.i18n.Tr "datasets"}}</strong> | |||
</div> | |||
<div class="column right aligned" style="z-index:1"> | |||
<div class="ui right dropdown type jump item"> | |||
<span class="text"> | |||
{{.i18n.Tr "repo.issues.filter_sort"}}<i class="dropdown icon"></i> | |||
</span> | |||
<div class="menu"> | |||
<a class="item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}&type={{.Type}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||
<a class="item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}&type={{.Type}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||
{{if .dataset.Description}} | |||
<div class="row" style="padding-top: 0;"> | |||
<div class=" wrapper"> | |||
<input id="exp1" class="exp" type="checkbox"> | |||
<div class="text"> | |||
<label class="btn" for="exp1"></label> | |||
{{.dataset.Description}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="dataset list"> | |||
{{template "repo/datasets/dataset_list" .}} | |||
{{end}} | |||
<div class="row"> | |||
<div class="column ten wide"></div> | |||
<div class="column six wide right aligned"> | |||
<el-select v-model="datasetType" style="width: 40%;" size="small" @change="changeDatasetType"> | |||
<i slot="prefix" style="display: inline-block;color: #101010;" class="el-input__icon ri-archive-drawer-line"></i> | |||
<el-option label="{{$.i18n.Tr "repo.gpu_type_all"}}" value="-1"></el-option> | |||
<el-option label="CPU/GPU" value="0"></el-option> | |||
<el-option label="NPU" value="1"></el-option> | |||
</el-select> | |||
<el-button icon="el-icon-upload" {{if not $.CanWrite}} disabled {{end}} type="primary" size="small" @click="gotoUpload('{{.RepoLink}}',{{.dataset.ID}})">{{$.i18n.Tr "dataset.dataset_upload"}}</el-button> | |||
</div> | |||
</div> | |||
<div class="dataset ui middle very relaxed page"> | |||
<div class="column"> | |||
{{if .Permission.CanWrite $.UnitTypeDatasets}} | |||
<div style='display:none;' | |||
id="minioUploader-params" | |||
data-uuid="{{.uuid}}" | |||
data-add-url="{{AppSubUrl}}/attachments/add" | |||
data-accepts="{{.AttachmentAllowedTypes}}" | |||
data-remove-url="{{AppSubUrl}}/attachments/delete" | |||
data-csrf="{{.CsrfToken}}" | |||
dataset-id={{.dataset.ID}} | |||
data-max-file="100" | |||
data-dataset-id="{{.dataset.ID}}" | |||
data-max-size="{{.AttachmentMaxSize}}" | |||
data-default-message="{{.i18n.Tr "dropzone.default_message"}}" | |||
data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" | |||
data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" | |||
data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}" | |||
data-file-status='{{.i18n.Tr "dropzone.file_status"}}' | |||
data-file-init-status='{{.i18n.Tr "dropzone.file_init_status"}}' | |||
data-waitting-uploading='{{.i18n.Tr "dropzone.waitting_uploading"}}' | |||
data-md5-computing='{{.i18n.Tr "dropzone.md5_computing"}}' | |||
data-obs-connecting='{{.i18n.Tr "dropzone.obs-connecting"}}' | |||
data-loading-file='{{.i18n.Tr "dropzone.loading_file"}}' | |||
data-upload-complete='{{.i18n.Tr "dropzone.upload_complete"}}' | |||
data-uploading='{{.i18n.Tr "dropzone.uploading"}}' | |||
data-failed='{{.i18n.Tr "dropzone.failed"}}' | |||
> | |||
</div> | |||
<div class="contorl_component"></div> | |||
{{end}} | |||
<div class="row"> | |||
<div class="ui sixteen wide column dataset"> | |||
<div class="ui grid stackable" style="background: #f0f0f0;;"> | |||
<div class="row"> | |||
<!-- 数据集名称 --> | |||
<div class="four wide column" style="width: 24% !important;"> | |||
<span style="margin:0 6px">{{$.i18n.Tr "dataset.dataset_file_name"}}</span> | |||
</div> | |||
<div class="one wide column text center" style="width: 7.25% !important;"> | |||
{{$.i18n.Tr "repo.model.manage.size"}} | |||
</div> | |||
<div class="two wide column text center"> | |||
{{$.i18n.Tr "dataset.dataset_available_clusters"}} | |||
</div> | |||
<div class="one wide column text center"> | |||
{{$.i18n.Tr "repo.modelarts.status"}} | |||
</div> | |||
<div class="one wide column text center"> | |||
{{$.i18n.Tr "repo.cloudbrain_creator"}} | |||
</div> | |||
<div class="three wide column text center"> | |||
{{$.i18n.Tr "dataset.dataset_upload_time"}} | |||
</div> | |||
<div class="four wide column text center"> | |||
{{$.i18n.Tr "repo.cloudbrain_operate"}} | |||
</div> | |||
</div> | |||
</div> | |||
{{range $k, $v :=.Attachments}} | |||
<div class="ui grid stackable item" id="{{.FileChunk.UUID}}"> | |||
<div class="row"> | |||
<!-- 数据集名称 --> | |||
<div class="four wide column" style="width: 24% !important;display: flex;align-items: center;"> | |||
{{if .Description}} | |||
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper"> | |||
<div slot="content" >{{.Description}}</br><span><i class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}</span></div> | |||
<a class="dataset_title title" href="{{.DownloadURL}}" title="{{.Name}}" style="border: none;"> | |||
{{.Name}} | |||
</a> | |||
</el-tooltip> | |||
{{else}} | |||
<el-tooltip class="item" effect="dark" placement="top" popper-class="diy-popper"> | |||
<div slot="content" ><span><i class="ri-download-line"></i>{{$.i18n.Tr "dataset.download"}}:{{.DownloadCount}}</span></div> | |||
<a class="dataset_title title" href="{{.DownloadURL}}" title="{{.Name}}" style="border: none;"> | |||
{{.Name}} | |||
</a> | |||
</el-tooltip> | |||
{{end}} | |||
<i class="ri-lock-2-line" style="color: #fa8c16;" v-if="privates[{{$k}}]"></i> | |||
<!-- <i class="COMPLETED" v-if="zipStatus[{{$k}}]==1"></i> | |||
<i class="WAITING" v-if="zipStatus[{{$k}}]==2"></i> | |||
<i class="FAILED" v-if="zipStatus[{{$k}}]==3"></i> --> | |||
</div> | |||
<div class="one wide column text center" style="width: 7.25% !important;"> | |||
{{.Size | FileSize}} | |||
</div> | |||
<div class="two wide column text center"> | |||
{{.Type | AttachmentResourceType}} | |||
</div> | |||
<div class="one wide column text center"> | |||
{{$x:=.IsPrivate | AttachmentStatus}} | |||
<span style="color: #fa8c16;" v-if="privates[{{$k}}]">{{$.i18n.Tr "home.show_private"}}</span> | |||
<span style="color: #13c28d;" v-else="privates[{{$k}}]">{{$.i18n.Tr "org.settings.visibility.public"}}</span> | |||
</div> | |||
<div class="one wide column text center"> | |||
{{if .Uploader.Name}} | |||
<a href="{{AppSubUrl}}/{{.Uploader.Name}}" title="{{.Uploader.Name}}"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/{{.Uploader.Name}}/-1"></a> | |||
{{else}} | |||
<a title="Ghost"><img class="ui avatar image" src="{{AppSubUrl}}/user/avatar/Ghost/-1"></a> | |||
{{end}} | |||
</div> | |||
<div class="three wide column text center"> | |||
{{.CreatedUnix | TimeSinceUnix1}} | |||
</div> | |||
<div class="four wide column text right"> | |||
<!-- <el-button type="text">下载</el-button> | |||
<el-button type="text">预览</el-button> | |||
<el-button type="text">标注</el-button> | |||
<el-button type="text"> | |||
<el-popover | |||
placement="right" | |||
width="400" | |||
trigger="click"> | |||
<span>asdasd</span> | |||
<el-button slot="reference" type="text"><i class="ri-more-line"></i></el-button> | |||
</el-popover> | |||
</el-button> --> | |||
<div class="ui compact buttons"> | |||
<a class="ui basic blue button" href="{{.DownloadURL}}">{{$.i18n.Tr "dataset.download"}}</a> | |||
{{if eq .DecompressState 1}} | |||
<a class="ui basic blue button" href="datasets/dirs/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{$.i18n.Tr "preview"}}</a> | |||
{{end}} | |||
{{if and (.CanDel) (not $.Repository.IsPrivate)}} | |||
<span class="ui basic blue button" style="color: #13c28d !important;" @click="setPrivate('{{.FileChunk.UUID}}',false,{{$k}})" v-if="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_public"}}</span> | |||
<span class="ui basic blue button" style="color: #fa8c16 !important;" @click="setPrivate('{{.FileChunk.UUID}}',true,{{$k}})" v-else="privates[{{$k}}]">{{$.i18n.Tr "dataset.set_private"}}</span> | |||
{{end}} | |||
<!-- {{if $.CanRead}} | |||
<a class="ui basic blue button" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'>标注</a> | |||
{{else}} | |||
<a class="ui basic disabled button">标注</a> | |||
{{end}} --> | |||
<a class="ui basic blue button"> | |||
<el-dropdown size="medium"> | |||
<span class="el-dropdown-link"> | |||
{{$.i18n.Tr "repo.more"}}<i class="el-icon-arrow-down el-icon--right"></i> | |||
</span> | |||
<el-dropdown-menu slot="dropdown"> | |||
<el-dropdown-item class="clipboard" data-clipboard-text="{{.DownloadURL}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_url"}}</el-dropdown-item> | |||
<el-dropdown-item class="clipboard" data-clipboard-text="{{.FileChunk.Md5}}" data-clipboard-action="copy">{{$.i18n.Tr "dataset.copy_md5"}}</el-dropdown-item> | |||
{{if and ($.CanWrite) (eq .DecompressState 1) }} | |||
<el-dropdown-item @click.native="gotoAnnotate('{{$.RepoLink}}','{{.UUID}}',{{.Type}})">{{$.i18n.Tr "dataset.annotation"}}</el-dropdown-item> | |||
{{end}} | |||
{{if .CanDel}} | |||
<el-dropdown-item @click.native="gotoDatasetEidt('{{$.RepoLink}}',{{.ID}})">{{$.i18n.Tr "dataset.modify_description"}}</el-dropdown-item> | |||
<el-dropdown-item style="color: red;" @click.native="delDataset('{{.FileChunk.UUID}}')">{{$.i18n.Tr "dataset.delete"}}</el-dropdown-item> | |||
{{end}} | |||
</el-dropdown-menu> | |||
</el-dropdown> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="four wide column"> | |||
{{template "repo/datasets/right_side" .}} | |||
</div> | |||
</div> | |||
</form> | |||
</div> | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[10]" | |||
:page-size="10" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
{{else}} | |||
<div class="ui placeholder segment bgtask-none"> | |||
<div class="ui icon header bgtask-header-pic"></div> | |||
<div class="bgtask-content-header">{{.i18n.Tr "dataset.dataset_no_create"}}</div> | |||
{{if $.CanWrite}} | |||
<a class="ui green button" href="{{.RepoLink}}/datasets/create">{{.i18n.Tr "dataset.create_new_dataset"}}</a> | |||
{{end}} | |||
<div class="bgtask-content"> | |||
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_explain"}}</div> | |||
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_instructions_for_use"}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">{{.i18n.Tr "dataset.dataset_camp_course"}}</a></div> | |||
</div> | |||
</div> | |||
{{end}} | |||
</div> | |||
<div class="ui small basic delete modal" id="data-dataset-delete-modal"> | |||
<div class="ui icon header"> | |||
<i class="trash icon"></i> | |||
<div class="ui icon header"> | |||
<i class="trash icon"></i> | |||
{{.i18n.Tr "dataset.attachment.delete"}} | |||
</div> | |||
<div class="content"> | |||
<p>{{.i18n.Tr "dataset.attachment.delete_desc" | Str2html}}</p> | |||
</div> | |||
{{template "base/delete_modal_actions" .}} | |||
</div> | |||
<div class="content"> | |||
<p>{{.i18n.Tr "dataset.attachment.delete_desc" | Str2html}}</p> | |||
</div> | |||
{{template "base/delete_modal_actions" .}} | |||
</div> | |||
{{template "base/footer" .}} |
@@ -443,7 +443,20 @@ | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} {{template "base/paginate" .}} | |||
{{end}} | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[10]" | |||
:page-size="10" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -138,7 +138,7 @@ | |||
{{end}} | |||
{{if .Permission.CanRead $.UnitTypeDatasets}} | |||
<a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets?type=0"> | |||
<a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets"> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M20.083 15.2l1.202.721a.5.5 0 0 1 0 .858l-8.77 5.262a1 1 0 0 1-1.03 0l-8.77-5.262a.5.5 0 0 1 0-.858l1.202-.721L12 20.05l8.083-4.85zm0-4.7l1.202.721a.5.5 0 0 1 0 .858L12 17.65l-9.285-5.571a.5.5 0 0 1 0-.858l1.202-.721L12 15.35l8.083-4.85zm-7.569-9.191l8.771 5.262a.5.5 0 0 1 0 .858L12 13 2.715 7.429a.5.5 0 0 1 0-.858l8.77-5.262a1 1 0 0 1 1.03 0zM12 3.332L5.887 7 12 10.668 18.113 7 12 3.332z"/></svg> | |||
{{.i18n.Tr "datasets"}} | |||
</a> | |||
@@ -186,7 +186,20 @@ | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} {{template "base/paginate" .}} | |||
{{end}} | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[10]" | |||
:page-size="10" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -232,7 +232,13 @@ td, th { | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .CreatedUnix}}</span> | |||
<span style="font-size: 12px;" class=""> | |||
{{if not (eq .StartTime 0)}} | |||
{{TimeSinceUnix1 .StartTime}} | |||
{{else}} | |||
{{TimeSinceUnix1 .CreatedUnix}} | |||
{{end}} | |||
</span> | |||
</div> | |||
</td> | |||
</tr> | |||
@@ -59,17 +59,7 @@ | |||
{{end}} | |||
</select> | |||
</div> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "cloudbrain.dataset"}}</label> | |||
<input type="text" list="cloudbrain_dataset" placeholder="{{.i18n.Tr "cloudbrain.select_dataset"}}" name="" id="answerInput" autofocus maxlength="36"> | |||
<datalist id="cloudbrain_dataset" class="ui search" style='width:385px' name="attachment"> | |||
{{range .attachments}} | |||
<option name="attachment" data-value="{{.UUID}}">{{.Attachment.Name}}</option> | |||
{{end}} | |||
</datalist> | |||
<input type="hidden" name="attachment" id="answerInput-hidden"> | |||
</div> | |||
{{template "custom/select_dataset" .}} | |||
<!--<div class="inline required field"> | |||
<label>工作环境</label> | |||
@@ -99,8 +89,8 @@ | |||
<div class="inline field"> | |||
<label></label> | |||
<button class="ui green button"> | |||
{{.i18n.Tr "repo.cloudbrain.new"}} | |||
</button> | |||
{{.i18n.Tr "repo.cloudbrain.new"}} | |||
</button> | |||
<a class="ui button cancel" href="{{.RepoLink}}/debugjob?debugListType=all">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | |||
</div> | |||
</div> | |||
@@ -149,7 +139,6 @@ | |||
$('select.dropdown') | |||
.dropdown(); | |||
$(function() { | |||
$("#cloudbrain_job_type").change(function() { | |||
if ($(this).val() == 'BENCHMARK') { | |||
@@ -159,20 +148,11 @@ | |||
} | |||
}) | |||
}) | |||
document.querySelector('input[list]').addEventListener('input',function(e){ | |||
var input = e.target, | |||
list = input.getAttribute('list'), | |||
options = document.querySelectorAll('#'+list+' option'), | |||
hiddenInput = document.getElementById(input.getAttribute('id')+'-hidden'), | |||
inputValue = input.value; | |||
hiddenInput.value = inputValue; | |||
for (let i=0;i<options.length;i++){ | |||
var option = options[i] | |||
if(option.innerText===inputValue){ | |||
hiddenInput.value = option.getAttribute('data-value'); | |||
break | |||
} | |||
} | |||
}) | |||
$(document).ready(function(){ | |||
$(document).keydown(function(event){ | |||
if(event.keyCode==13){ | |||
event.preventDefault(); | |||
} | |||
}); | |||
}); | |||
</script> |
@@ -39,8 +39,18 @@ | |||
</div> | |||
</div> | |||
<div class="column right aligned"> | |||
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;"> | |||
{{svg "octicon-server" 16}} | |||
<div class="default text" style="color: rgba(0,0,0,.87);"></div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="all">{{$.i18n.Tr "repo.gpu_type_all"}}</div> | |||
<div class="item" data-value="CPU/GPU">CPU/GPU</div> | |||
<div class="item" data-value="NPU">NPU</div> | |||
</div> | |||
</div> | |||
{{if .Permission.CanWrite $.UnitTypeCloudBrain}} | |||
<a class="ui green button" href="{{.RepoLink}}/modelarts/train-job/create">{{$.i18n.Tr "repo.modelarts.train_job.new_train"}}</a> | |||
<a class="ui green button" href="{{.RepoLink}}/cloudbrain/train-job/create">{{$.i18n.Tr "repo.modelarts.train_job.new_train"}}</a> | |||
{{else}} | |||
<a class="ui disabled button" >{{$.i18n.Tr "repo.modelarts.train_job.new_train"}}</a> | |||
{{end}} | |||
@@ -102,7 +112,7 @@ | |||
<!-- 任务名 --> | |||
<div class="three wide column padding0"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
<a class="title" href='{{if eq .ComputeResource "NPU" }}{{$.Link}}/{{.JobID}}{{else}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{end}}' title="{{.DisplayJobName}}" style="font-size: 14px;"> | |||
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span> | |||
</a> | |||
@@ -143,7 +153,7 @@ | |||
<div class="ui compact buttons"> | |||
{{$.CsrfTokenHtml}} | |||
{{if .CanDel}} | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{.JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}} blue {{end}}button" data-repopath="{{$.RepoRelPath}}/modelarts/train-job" data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{.JobID}}" class="ui basic ai_stop_version {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED" "SUCCEEDED" "STOPPED"}}disabled {{else}} blue {{end}}button" data-repopath='{{$.RepoRelPath}}{{if eq .ComputeResource "NPU"}}/modelarts/train-job{{else}}/cloudbrain/train-job{{end}}' data-jobid="{{.JobID}}" data-version="{{.VersionName}}"> | |||
{{$.i18n.Tr "repo.stop"}} | |||
</a> | |||
{{else}} | |||
@@ -154,7 +164,8 @@ | |||
</div> | |||
<!-- 删除任务 --> | |||
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | |||
<form class="ui compact buttons" id="delForm-{{.JobID}}" action='{{if eq .ComputeResource "NPU" }}{{$.Link}}/{{.JobID}}{{else}}{{$.RepoLink}}/cloudbrain/train-job/{{.JobID}}{{end}}/del' method="post"> | |||
<input type="hidden" name="listType" value="{{$.ListType}}"> | |||
{{$.CsrfTokenHtml}} | |||
{{if .CanDel}} | |||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{.JobID}}" class="ui basic ai_delete blue button" style="border-radius: .28571429rem;"> | |||
@@ -169,7 +180,20 @@ | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} {{template "base/paginate" .}} | |||
{{end}} | |||
<div id="app" style="margin-top: 2rem;"> | |||
<div class="center"> | |||
<el-pagination | |||
background | |||
@current-change="handleCurrentChange" | |||
:current-page="page" | |||
:page-sizes="[10]" | |||
:page-size="10" | |||
layout="total, sizes, prev, pager, next, jumper" | |||
:total="{{.Page.Paginater.Total}}"> | |||
</el-pagination> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -206,3 +230,27 @@ | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
<script> | |||
let url = {{$.RepoLink}}; | |||
let all = {{$.i18n.Tr "repo.gpu_type_all"}} | |||
$(document).ready(function(){ | |||
const params = new URLSearchParams(location.search) | |||
if(!location.search){ | |||
$('.default.text').text(all) | |||
}else{ | |||
if(params.has('listType') && params.get('listType')=='all'){ | |||
$('.default.text').text(all) | |||
} | |||
else{ | |||
$('.default.text').text(params.get('listType')) | |||
} | |||
} | |||
$('.ui.selection.dropdown').dropdown({ | |||
onChange:function(value){ | |||
location.href = `${url}/modelarts/train-job?listType=${value}` | |||
} | |||
}) | |||
}) | |||
</script> |
@@ -79,6 +79,24 @@ | |||
<input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | |||
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | |||
<div class="required unite min_title inline field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | |||
<div class="ui blue mini menu compact selectcloudbrain"> | |||
<a class="item" href="{{.RepoLink}}/cloudbrain/train-job/create"> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
<path fill="none" d="M0 0h24v24H0z"/> | |||
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
</svg> | |||
CPU/GPU | |||
</a> | |||
<a class="active item" href="{{.RepoLink}}/modelarts/train-job/create"> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||
<path fill="none" d="M0 0h24v24H0z"/> | |||
<path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | |||
</svg> | |||
Ascend NPU</a> | |||
</div> | |||
</div> | |||
<div class="required unite min_title inline field"> | |||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||
<input style="width: 60%;" name="display_job_name" id="display_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}" tabindex="3" onkeyup="this.value=this.value.replace(/[, ]/g,'')" autofocus required maxlength="64"> | |||
<span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span> | |||
@@ -395,7 +413,7 @@ | |||
identifier : 'display_job_name', | |||
rules: [ | |||
{ | |||
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[^-]$/]', | |||
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]', | |||
} | |||
] | |||
}, | |||
@@ -223,7 +223,12 @@ td, th { | |||
</div> | |||
<div class="ac-display-inblock title_text acc-margin-bottom"> | |||
<span class="cti-mgRight-sm">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
<span class="cti-mgRight-sm"> | |||
{{if not (eq .Cloudbrain.StartTime 0)}} | |||
{{TimeSinceUnix1 .Cloudbrain.StartTime}} | |||
{{else}} | |||
{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}} | |||
{{end}}</span> | |||
<span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.current_version"}}:{{.VersionName}}</span> | |||
<span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.parent_version"}}:{{.PreVersionName}}</span> | |||
<span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
@@ -293,7 +298,12 @@ td, th { | |||
<td class="ti-text-form-content"> | |||
<div class="text-span text-span-w"> | |||
<span style="font-size: 12px;" class="">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
<span style="font-size: 12px;" class=""> | |||
{{if not (eq .Cloudbrain.StartTime 0)}} | |||
{{TimeSinceUnix1 .Cloudbrain.StartTime}} | |||
{{else}} | |||
{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}} | |||
{{end}}</span> | |||
</div> | |||
</td> | |||
</tr> | |||
@@ -221,7 +221,7 @@ | |||
} | |||
function loadTrainList(){ | |||
$.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => { | |||
console.log(data) | |||
const n_length = data.length | |||
let train_html='' | |||
for (let i=0;i<n_length;i++){ | |||
@@ -77,13 +77,15 @@ | |||
{{else if eq .GetOpType 26}} | |||
{{$.i18n.Tr "action.task_npudebugjob" .GetRepoLink .Content .RefName | Str2html}} | |||
{{else if eq .GetOpType 27}} | |||
{{$.i18n.Tr "action.task_trainjob" .GetRepoLink .Content .RefName | Str2html}} | |||
{{$.i18n.Tr "action.task_nputrainjob" .GetRepoLink .Content .RefName | Str2html}} | |||
{{else if eq .GetOpType 28}} | |||
{{$.i18n.Tr "action.task_inferencejob" .GetRepoLink .Content .RefName | Str2html}} | |||
{{else if eq .GetOpType 29}} | |||
{{$.i18n.Tr "action.task_benchmark" .GetRepoLink .Content .RefName | Str2html}} | |||
{{else if eq .GetOpType 30}} | |||
{{$.i18n.Tr "action.task_createmodel" .GetRepoLink .RefName .RefName | Str2html}} | |||
{{else if eq .GetOpType 31}} | |||
{{$.i18n.Tr "action.task_gputrainjob" .GetRepoLink .Content .RefName | Str2html}} | |||
{{end}} | |||
</p> | |||
{{if or (eq .GetOpType 5) (eq .GetOpType 18)}} | |||
@@ -129,6 +131,8 @@ | |||
<span class="text grey"><i class="ri-vip-crown-line icon big"></i></span> | |||
{{else if eq .GetOpType 30}} | |||
<span class="text grey"><i class="ri-picture-in-picture-exit-line icon big"></i></span> | |||
{{else if eq .GetOpType 31}} | |||
<span class="text grey"><i class="ri-character-recognition-line icon big"></i></span> | |||
{{else}} | |||
<span class="text grey">{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32}}</span> | |||
{{end}} | |||
@@ -8,9 +8,11 @@ | |||
{{ file_status_text }} | |||
<strong class="success text red">{{ status }}</strong> | |||
</p> | |||
<p>说明:<br> | |||
<el-button style="background-color: #21ba45;" type="success" :disabled="btnFlag" @click="onFileAdded">{{upload}}</el-button> | |||
<el-button type="info" @click="cancelDataset">{{cancel}}</el-button> | |||
<!-- <p>说明:<br> | |||
- 只有zip格式的数据集才能发起云脑任务;<br> | |||
- 云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p> | |||
- 云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p> --> | |||
</div> | |||
</template> | |||
@@ -24,9 +26,19 @@ import qs from 'qs'; | |||
import createDropzone from '../features/dropzone.js'; | |||
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; | |||
const CloudBrainType = 0; | |||
// const uploadtype = 0; | |||
export default { | |||
props:{ | |||
uploadtype:{ | |||
type:Number, | |||
required:true | |||
}, | |||
desc:{ | |||
type:String, | |||
default:'' | |||
} | |||
}, | |||
data() { | |||
return { | |||
dropzoneUploader: null, | |||
@@ -36,7 +48,12 @@ export default { | |||
progress: 0, | |||
status: '', | |||
dropzoneParams: {}, | |||
file_status_text: '' | |||
file_status_text: '', | |||
file:{}, | |||
repoPath:'', | |||
btnFlag:false, | |||
cancel:'', | |||
upload:'', | |||
}; | |||
}, | |||
@@ -44,33 +61,47 @@ export default { | |||
this.dropzoneParams = $('div#minioUploader-params'); | |||
this.file_status_text = this.dropzoneParams.data('file-status'); | |||
this.status = this.dropzoneParams.data('file-init-status'); | |||
let previewTemplate = ''; | |||
previewTemplate += '<div class="dz-preview dz-file-preview">\n '; | |||
previewTemplate += ' <div class="dz-details">\n '; | |||
previewTemplate += ' <div class="dz-filename">'; | |||
previewTemplate += | |||
' <span data-dz-name data-dz-thumbnail></span>'; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-size" data-dz-size style="white-space: nowrap"></div>\n '; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-progress ui active progress">'; | |||
previewTemplate += | |||
' <div class="dz-upload bar" data-dz-uploadprogress><div class="progress"></div></div>\n '; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-success-mark">'; | |||
previewTemplate += ' <span>上传成功</span>'; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-error-mark">'; | |||
previewTemplate += ' <span>上传失败</span>'; | |||
previewTemplate += ' </div>\n '; | |||
previewTemplate += ' <div class="dz-error-message">'; | |||
previewTemplate += ' <span data-dz-errormessage></span>'; | |||
previewTemplate += ' </div>\n'; | |||
previewTemplate += '</div>'; | |||
this.repoPath = this.dropzoneParams.data('repopath'); | |||
this.cancel = this.dropzoneParams.data('cancel'); | |||
this.upload = this.dropzoneParams.data('upload'); | |||
// let previewTemplate = ''; | |||
// previewTemplate += '<div class="dz-preview dz-file-preview">\n '; | |||
// previewTemplate += ' <div class="dz-details">\n '; | |||
// previewTemplate += ' <div class="dz-filename">'; | |||
// previewTemplate += | |||
// ' <span data-dz-name data-dz-thumbnail></span>'; | |||
// previewTemplate += ' </div>\n '; | |||
// previewTemplate += ' <div class="dz-size" data-dz-size style="white-space: nowrap"></div>\n '; | |||
// previewTemplate += ' </div>\n '; | |||
// previewTemplate += ' <div class="dz-progress ui active progress">'; | |||
// previewTemplate += | |||
// ' <div class="dz-upload bar" data-dz-uploadprogress><div class="progress"></div></div>\n '; | |||
// previewTemplate += ' </div>\n '; | |||
// previewTemplate += ' <div class="dz-success-mark">'; | |||
// previewTemplate += ' <span>上传成功</span>'; | |||
// previewTemplate += ' </div>\n '; | |||
// previewTemplate += ' <div class="dz-error-mark">'; | |||
// previewTemplate += ' <span>上传失败</span>'; | |||
// previewTemplate += ' </div>\n '; | |||
// previewTemplate += ' <div class="dz-error-message">'; | |||
// previewTemplate += ' <span data-dz-errormessage></span>'; | |||
// previewTemplate += ' </div>\n'; | |||
// previewTemplate += '</div>'; | |||
let previewTemplate = '' | |||
previewTemplate += '<div class="dz-preview dz-file-preview" style="width:100%;background: none;">' | |||
previewTemplate += '<div class="dz-details" style="opacity: 1;">' | |||
previewTemplate += '<div class="dz-filename"><span data-dz-name></span></div>' | |||
previewTemplate += '<div class="dz-size" data-dz-size></div>' | |||
previewTemplate += '<div class="dz-progress ui active progress" style="top: 75%;width: 80%;left: 15%;"><div class="dz-upload bar" data-dz-uploadprogress><div class="progress"></div></div></div>' | |||
// previewTemplate += '<img data-dz-thumbnail />' | |||
previewTemplate += '</div>' | |||
previewTemplate += '<div class="dz-success-mark"><span>✔</span></div>' | |||
previewTemplate += '<div class="dz-error-mark"><span>✘</span></div>' | |||
previewTemplate += '<div class="dz-error-message"><span data-dz-errormessage></span></div>' | |||
previewTemplate += '</div>' | |||
const $dropzone = $('div#dataset'); | |||
console.log('createDropzone'); | |||
const dropzoneUploader = await createDropzone($dropzone[0], { | |||
url: '/todouploader', | |||
maxFiles: this.maxFiles, | |||
@@ -84,10 +115,7 @@ export default { | |||
previewTemplate | |||
}); | |||
dropzoneUploader.on('addedfile', (file) => { | |||
setTimeout(() => { | |||
// eslint-disable-next-line no-unused-expressions | |||
file.accepted && this.onFileAdded(file); | |||
}, 200); | |||
this.file = file | |||
}); | |||
dropzoneUploader.on('maxfilesexceeded', function (file) { | |||
if (this.files[0].status !== 'success') { | |||
@@ -102,14 +130,23 @@ export default { | |||
this.dropzoneUploader = dropzoneUploader; | |||
}, | |||
methods: { | |||
cancelDataset(){ | |||
location.href = this.repoPath | |||
this.dropzoneUploader.removeAllFiles(true) | |||
}, | |||
resetStatus() { | |||
this.progress = 0; | |||
this.status = ''; | |||
console.log(this.uploadtype) | |||
}, | |||
updateProgress(file, progress) { | |||
console.log("progress---",progress) | |||
file.previewTemplate.querySelector( | |||
'.dz-upload' | |||
).style.width = `${progress}%`; | |||
).style.width = `${progress}%` | |||
file.previewTemplate.querySelector( | |||
'.dz-upload' | |||
).style.background = '#409eff'; | |||
}, | |||
emitDropzoneSuccess(file) { | |||
file.status = 'success'; | |||
@@ -122,18 +159,24 @@ export default { | |||
this.dropzoneUploader.emit('error', file); | |||
// this.dropzoneUploader.emit('complete', file); | |||
}, | |||
onFileAdded(file) { | |||
file.datasetId = document | |||
onFileAdded() { | |||
this.btnFlag = true | |||
this.file.datasetId = document | |||
.getElementById('datasetId') | |||
.getAttribute('datasetId'); | |||
this.resetStatus(); | |||
this.computeMD5(file); | |||
console.log(this.file,!this.file?.upload) | |||
if(!this.file?.upload){ | |||
this.btnFlag = false | |||
return | |||
} | |||
this.computeMD5(this.file); | |||
}, | |||
finishUpload(file) { | |||
this.emitDropzoneSuccess(file); | |||
setTimeout(() => { | |||
window.location.reload(); | |||
window.location.href = this.repoPath | |||
}, 1000); | |||
}, | |||
@@ -249,7 +292,7 @@ export default { | |||
file_name: file.name, | |||
size: file.size, | |||
dataset_id: file.datasetId, | |||
type: CloudBrainType, | |||
type: this.uploadtype, | |||
_csrf: csrf | |||
}) | |||
); | |||
@@ -260,6 +303,8 @@ export default { | |||
const params = { | |||
params: { | |||
md5: file.uniqueIdentifier, | |||
type: this.uploadtype, | |||
file_name: file.name, | |||
_csrf: csrf | |||
} | |||
}; | |||
@@ -282,13 +327,15 @@ export default { | |||
}, | |||
async newMultiUpload(file) { | |||
console.log(this.uploadtype,this) | |||
const res = await axios.get('/attachments/new_multipart', { | |||
params: { | |||
totalChunkCounts: file.totalChunkCounts, | |||
md5: file.uniqueIdentifier, | |||
size: file.size, | |||
fileType: file.type, | |||
type: CloudBrainType, | |||
type: this.uploadtype, | |||
file_name: file.name, | |||
_csrf: csrf | |||
} | |||
}); | |||
@@ -306,6 +353,7 @@ export default { | |||
fileReader = new FileReader(), | |||
time = new Date().getTime(); | |||
let currentChunk = 0; | |||
let _this = this | |||
function loadNext() { | |||
const start = currentChunk * chunkSize; | |||
@@ -329,7 +377,8 @@ export default { | |||
uploadID: file.uploadID, | |||
size: partSize, | |||
chunkNumber: currentChunk + 1, | |||
type: CloudBrainType, | |||
type: _this.uploadtype, | |||
file_name: file.name, | |||
_csrf: csrf | |||
} | |||
}); | |||
@@ -343,14 +392,27 @@ export default { | |||
} | |||
async function uploadMinioNewMethod(url,e){ | |||
async function uploadMinioNewMethod(url,e){ | |||
var xhr = new XMLHttpRequest(); | |||
xhr.open('PUT', url, false); | |||
xhr.setRequestHeader('Content-Type', 'text/plain') | |||
xhr.send(e.target.result); | |||
var etagValue = xhr.getResponseHeader('etag'); | |||
//console.log(etagValue); | |||
etags[currentChunk] = etagValue; | |||
xhr.open('PUT', url, false); | |||
if(_this.uploadtype===0){ | |||
xhr.setRequestHeader('Content-Type', 'text/plain') | |||
xhr.send(e.target.result); | |||
var etagValue = xhr.getResponseHeader('etag'); | |||
etags[currentChunk] = etagValue; | |||
} | |||
else if(_this.uploadtype===1){ | |||
xhr.setRequestHeader('Content-Type', '') | |||
xhr.send(e.target.result); | |||
var etagValue = xhr.getResponseHeader('ETag'); | |||
//console.log(etagValue); | |||
etags[currentChunk] = etagValue; | |||
} | |||
} | |||
async function updateChunk(currentChunk) { | |||
@@ -395,6 +457,7 @@ export default { | |||
} | |||
async function completeUpload() { | |||
console.log(_this.uploadtype) | |||
return await axios.post( | |||
'/attachments/complete_multipart', | |||
qs.stringify({ | |||
@@ -403,8 +466,9 @@ export default { | |||
file_name: file.name, | |||
size: file.size, | |||
dataset_id: file.datasetId, | |||
type: CloudBrainType, | |||
_csrf: csrf | |||
type: _this.uploadtype, | |||
_csrf: csrf, | |||
description:_this.desc | |||
}) | |||
); | |||
} | |||
@@ -430,6 +494,7 @@ export default { | |||
1}/${chunks}个分片上传` | |||
); | |||
this.progress = Math.ceil((currentChunk / chunks) * 100); | |||
console.log("((currentChunk / chunks) * 100).toFixed(2)",((currentChunk / chunks) * 100).toFixed(2)) | |||
this.updateProgress(file, ((currentChunk / chunks) * 100).toFixed(2)); | |||
this.status = `${this.dropzoneParams.data('uploading')} ${( | |||
(currentChunk / chunks) * | |||
@@ -443,6 +508,7 @@ export default { | |||
file.size | |||
} 用时:${(new Date().getTime() - time) / 1000} s` | |||
); | |||
this.updateProgress(file, 100); | |||
this.progress = 100; | |||
this.status = this.dropzoneParams.data('upload-complete'); | |||
this.finishUpload(file); | |||
@@ -455,7 +521,7 @@ export default { | |||
<style> | |||
.dropzone-wrapper { | |||
margin: 2em auto; | |||
margin: 0; | |||
} | |||
.ui .dropzone { | |||
border: 2px dashed #0087f5; | |||
@@ -473,4 +539,8 @@ export default { | |||
border-bottom: 1px solid #dadce0; | |||
min-height: 0; | |||
} | |||
.upload-info{ | |||
margin-top: 1em; | |||
margin-bottom: 3em; | |||
} | |||
</style> |
@@ -460,7 +460,7 @@ export default { | |||
<style> | |||
.dropzone-wrapper { | |||
margin: 2em auto; | |||
margin: 0; | |||
} | |||
.ui .dropzone { | |||
border: 2px dashed #0087f5; | |||
@@ -478,4 +478,7 @@ export default { | |||
border-bottom: 1px solid #dadce0; | |||
min-height: 0; | |||
} | |||
.upload-info{ | |||
margin-top: 0.2em; | |||
} | |||
</style> |
@@ -150,21 +150,21 @@ | |||
align="center"> | |||
</el-table-column> | |||
<el-table-column | |||
prop="isMirror" | |||
prop="isFork" | |||
label="派生" | |||
align="center"> | |||
<template slot-scope="scope"> | |||
{{scope.row.isMirror|changeType}} | |||
</template> | |||
</el-table-column> | |||
{{scope.row.isFork|changeType}} | |||
</template> | |||
</el-table-column> | |||
<el-table-column | |||
prop="isFork" | |||
prop="isMirror" | |||
label="镜像" | |||
align="center"> | |||
<template slot-scope="scope"> | |||
{{scope.row.isFork|changeType}} | |||
{{scope.row.isMirror|changeType}} | |||
</template> | |||
</el-table-column> | |||
</el-table-column> | |||
<el-table-column | |||
prop="createUnix" | |||
label="项目创建时间" | |||
@@ -43,7 +43,7 @@ import Contributors from './components/Contributors.vue' | |||
import Model from './components/Model.vue'; | |||
import WxAutorize from './components/WxAutorize.vue' | |||
import initCloudrain from './features/cloudrbanin.js' | |||
// import $ from 'jquery.js' | |||
Vue.use(ElementUI); | |||
Vue.prototype.$axios = axios; | |||
@@ -2918,6 +2918,7 @@ $(document).ready(async () => { | |||
initVueApp(); | |||
initVueUploader(); | |||
initObsUploader(); | |||
initVueDataset(); | |||
initVueEditAbout(); | |||
initVueEditTopic(); | |||
initVueContributors(); | |||
@@ -3658,6 +3659,594 @@ function initVueEditAbout() { | |||
}); | |||
} | |||
function initVueDataset() { | |||
const el = document.getElementById('dataset-base'); | |||
if (!el) { | |||
return; | |||
} | |||
let link=$('#square-link').data('link') | |||
let repolink = $('.dataset-repolink').data('repolink') | |||
let cloudbrainType = $('.dataset-repolink').data('cloudranin-type') | |||
const clearBtn = document.getElementsByClassName("clear_dataset_value"); | |||
const params = new URLSearchParams(location.search) | |||
for (let i = 0; i < clearBtn.length; i++) { | |||
clearBtn[i].addEventListener('click',function(e){ | |||
let searchType=e.target.getAttribute("data-clear-value") | |||
if(params.has(searchType)){ | |||
params.delete(searchType) | |||
let clearSearch = params.toString() | |||
location.href = link + '?' + clearSearch | |||
} | |||
}) | |||
} | |||
const items = [] | |||
const zipStatus = [] | |||
$('#dataset-range-value').find('.item').each(function(){ | |||
items.push($(this).data('private')) | |||
zipStatus.push($(this).data('decompress-state')) | |||
}) | |||
let num_stars = $('#dataset-range-value').data('num-stars') | |||
let star_active = $('#dataset-range-value').data('star-active') | |||
const ruleForm = {} | |||
if(document.getElementById('dataset-edit-value')){ | |||
let $this = $('#dataset-edit-value') | |||
ruleForm.title = $this.data('edit-title') || '' | |||
ruleForm.description = $this.data('edit-description') || '' | |||
ruleForm.category = $this.data('edit-category') || '' | |||
ruleForm.task = $this.data('edit-task') || '' | |||
ruleForm.license = $this.data('edit-license') || '' | |||
ruleForm.id = $this.data('edit-id')|| '' | |||
ruleForm._csrf = csrf | |||
} | |||
const starItems = [] | |||
const starActives = [] | |||
$('#datasets-square-range-value').find('.item').each(function(){ | |||
starItems.push($(this).data('num-stars')) | |||
starActives.push($(this).data('star-active')) | |||
}) | |||
const taskLists = [] | |||
const licenseLists = [] | |||
$('#task-square-range-value').find('.item').each(function(){ | |||
taskLists.push($(this).data('task')) | |||
}) | |||
$('#task-square-range-value').find('.item').each(function(){ | |||
licenseLists.push($(this).data('license')) | |||
}) | |||
let dataset_file_desc | |||
if(document.getElementById('dataset-file-desc')){ | |||
dataset_file_desc = document.getElementById('dataset-file-desc').value | |||
} | |||
// getEditInit(){ | |||
// if($('#dataset-edit-value')){ | |||
// $this = $('#dataset-edit-value') | |||
// this.ruleForm.title = $this.data('edit-title') || '' | |||
// this.ruleForm.description = $this.data('edit-description') || '' | |||
// this.ruleForm.category = $this.data('edit-category') || '' | |||
// this.ruleForm.task = $this.data('edit-task') || '' | |||
// this.ruleForm.license = $this.data('edit-license') || '' | |||
// this.ruleForm.id = $this.data('edit-id')|| '' | |||
// } | |||
// }, | |||
new Vue({ | |||
delimiters: ['${', '}'], | |||
el, | |||
data: { | |||
suburl: AppSubUrl, | |||
url:'', | |||
type:0, | |||
desc:'', | |||
descfile:'', | |||
datasetType:'', | |||
privates:[], | |||
zipStatus:[], | |||
starItems:[], | |||
starActives:[], | |||
taskLists:[], | |||
taskShow:[], | |||
licenseLists:[], | |||
licenseShow:[], | |||
hasMoreBthHis: false, | |||
showMoreHis:false, | |||
star_active:false, | |||
num_stars:0, | |||
dialogVisible:false, | |||
activeName: 'first', | |||
searchDataItem:'', | |||
currentRepoDataset:[], | |||
myDataset:[], | |||
publicDataset:[], | |||
myFavoriteDataset:[], | |||
page:1, | |||
totalnums:0, | |||
repolink:'', | |||
cloudbrainType:0, | |||
dataset_uuid:'', | |||
dataset_name:'', | |||
loadingDataIndex:true, | |||
timer:null, | |||
ruleForm:{ | |||
title:'', | |||
description:'', | |||
category:'', | |||
task:'', | |||
license:'', | |||
_csrf:csrf, | |||
}, | |||
ruleForm1:{ | |||
title:'', | |||
description:'', | |||
category:'', | |||
task:'', | |||
license:'', | |||
_csrf:'', | |||
id:'' | |||
}, | |||
rules: { | |||
title: [ | |||
{ required: true, message: '请输入数据集名称', trigger: 'blur' }, | |||
{ min: 1, max: 100, message: '长度在 1 到 100 个字符', trigger: 'blur' }, | |||
// {required:true,message:'test',pattern:'/^[a-zA-Z0-9-_]{1,100}[^-]$/',trigger:'blur'}, | |||
{ validator: (rule, value, callback) => { | |||
if (/^[a-zA-Z0-9-_.]{0,100}$/.test(value) == false) { | |||
callback(new Error("输入不符合数据集名称规则")); | |||
} else { | |||
callback(); | |||
} | |||
}, trigger: 'blur'} | |||
], | |||
description: [ | |||
{ required: true, message: '请输入数据集描述详情', trigger: 'blur' } | |||
], | |||
category: [ | |||
{ required: true, message: '请选择分类', trigger: 'change' } | |||
], | |||
task: [ | |||
{ required: true, message: '请选择研究方向/应用领域', trigger: 'change' } | |||
], | |||
// license: [ | |||
// { required: true, message: '请选择活动区域', trigger: 'change' } | |||
// ] | |||
}, | |||
}, | |||
components: { | |||
MinioUploader, | |||
ObsUploader | |||
}, | |||
mounted(){ | |||
// if(document.getElementById('postPath')){ | |||
// this.url = document.getElementById('postPath').value | |||
// } | |||
// this.privates = items | |||
// this.num_stars = num_stars | |||
// this.star_active = star_active | |||
// this.ruleForm1 = ruleForm | |||
// // this.getEditInit() | |||
// this.getTypeList() | |||
this.getTypeList() | |||
if(!!document.getElementById('dataset-repolink-init')){ | |||
this.getCurrentRepoDataset(this.repolink,this.cloudbrainType) | |||
} | |||
}, | |||
created(){ | |||
if(document.getElementById('postPath')){ | |||
this.url = document.getElementById('postPath').value | |||
} | |||
this.privates = items | |||
this.zipStatus = zipStatus | |||
this.num_stars = num_stars | |||
this.star_active = star_active | |||
this.ruleForm1 = ruleForm | |||
// this.getEditInit() | |||
this.starItems = starItems | |||
this.starActives = starActives | |||
this.taskLists = taskLists | |||
this.licenseLists = licenseLists | |||
this.descfile = dataset_file_desc | |||
this.repolink = repolink | |||
this.cloudbrainType = cloudbrainType | |||
}, | |||
methods:{ | |||
handleCurrentChange(val) { | |||
this.page = val | |||
switch(this.activeName){ | |||
case 'first': | |||
this.getCurrentRepoDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'second': | |||
this.getMyDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'third': | |||
this.getPublicDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'fourth': | |||
this.getStarDataset(this.repolink,this.cloudbrainType) | |||
break | |||
} | |||
}, | |||
createDataset(formName){ | |||
let _this = this | |||
this.$refs[formName].validate((valid)=>{ | |||
if(valid){ | |||
document.getElementById("mask").style.display = "block" | |||
_this.$axios.post(_this.url,_this.qs.stringify(_this.ruleForm)).then((res)=>{ | |||
if(res.data.Code===0){ | |||
document.getElementById("mask").style.display = "none" | |||
location.href = _this.url.split('/create')[0]+'?type=-1' | |||
}else{ | |||
console.log(res.data.Message) | |||
} | |||
document.getElementById("mask").style.display = "none" | |||
}).catch(error=>{ | |||
console.log(error) | |||
}) | |||
} | |||
else{ | |||
return false | |||
} | |||
}) | |||
}, | |||
cancelDataset(getpage,attachment){ | |||
if(getpage && !attachment){ | |||
if(getpage==='create'){ | |||
location.href = this.url.split('/create')[0]+'?type=-1' | |||
}else if(getpage==='edit'){ | |||
location.href = this.url.split('/edit')[0]+'?type=-1' | |||
}else{ | |||
location.href='/' | |||
} | |||
} | |||
else{ | |||
location.href = `${AppSubUrl}${attachment}/datasets` | |||
} | |||
}, | |||
gotoUpload(repolink,datsetId){ | |||
location.href = `${AppSubUrl}${repolink}/datasets/attachments/upload?datasetId=${datsetId}` | |||
}, | |||
gotoDataset(datsetUrl){ | |||
location.href = datsetUrl | |||
}, | |||
gotoAnnotate(repolink,uuid,type){ | |||
location.href = `${AppSubUrl}${repolink}/datasets/label/${uuid}?type=${type}` | |||
}, | |||
uploadGpu(){ | |||
this.type=0 | |||
}, | |||
uploadNpu(){ | |||
this.type=1 | |||
}, | |||
setPrivate(uuid,privateFlag,index){ | |||
const params = {_csrf:csrf,file:uuid,is_private:privateFlag} | |||
this.$axios.post('/attachments/private',this.qs.stringify(params)).then((res)=>{ | |||
this.$set(this.privates,index,privateFlag) | |||
}).catch(error=>{ | |||
console.log(error) | |||
}) | |||
}, | |||
delDataset(uuid){ | |||
let _this = this | |||
const params = {_csrf:csrf,file:uuid} | |||
$('#data-dataset-delete-modal') | |||
.modal({ | |||
closable: false, | |||
onApprove() { | |||
_this.$axios.post('/attachments/delete',_this.qs.stringify(params)).then((res)=>{ | |||
// $('#'+uuid).hide() | |||
location.reload() | |||
}).catch(error=>{ | |||
console.log(error) | |||
}) | |||
} | |||
}) | |||
.modal('show'); | |||
}, | |||
// getEditInit(){ | |||
// if($('#dataset-edit-value')){ | |||
// $this = $('#dataset-edit-value') | |||
// this.ruleForm.title = $this.data('edit-title') || '' | |||
// this.ruleForm.description = $this.data('edit-description') || '' | |||
// this.ruleForm.category = $this.data('edit-category') || '' | |||
// this.ruleForm.task = $this.data('edit-task') || '' | |||
// this.ruleForm.license = $this.data('edit-license') || '' | |||
// this.ruleForm.id = $this.data('edit-id')|| '' | |||
// } | |||
// }, | |||
editDataset(formName,id){ | |||
let _this = this | |||
this.url = this.url.split(`/${id}`)[0] | |||
this.$refs[formName].validate((valid)=>{ | |||
if(valid){ | |||
document.getElementById("mask").style.display = "block" | |||
_this.$axios.post(_this.url,_this.qs.stringify(_this.ruleForm1)).then((res)=>{ | |||
if(res.data.Code===0){ | |||
document.getElementById("mask").style.display = "none" | |||
location.href = _this.url.split('/edit')[0]+'?type=-1' | |||
}else{ | |||
console.log(res.data.Message) | |||
} | |||
document.getElementById("mask").style.display = "none" | |||
}).catch((err)=>{ | |||
console.log(err) | |||
}) | |||
} | |||
else{ | |||
return false | |||
} | |||
}) | |||
}, | |||
editDatasetFile(id,backurl){ | |||
let url = '/attachments/edit' | |||
const params={id:id,description:this.descfile,_csrf:csrf} | |||
// document.getElementById("mask").style.display = "block" | |||
this.$axios.post(url,this.qs.stringify(params)).then((res)=>{ | |||
if(res.data.Code===0){ | |||
location.href = `${AppSubUrl}${backurl}/datasets` | |||
}else{ | |||
console.log(res.data.Message) | |||
} | |||
}).catch((err)=>{ | |||
console.log(err) | |||
}) | |||
}, | |||
postStar(id,link){ | |||
if(this.star_active){ | |||
let url = link+'/'+ id + '/unstar' | |||
this.$axios.put(url).then((res)=>{ | |||
if(res.data.Code===0){ | |||
this.star_active = false | |||
this.num_stars = this.num_stars -1 | |||
} | |||
}) | |||
}else{ | |||
let url = link+'/'+ id + '/star' | |||
this.$axios.put(url).then((res)=>{ | |||
if(res.data.Code===0){ | |||
this.star_active = true | |||
this.num_stars = this.num_stars + 1 | |||
} | |||
}) | |||
} | |||
}, | |||
postSquareStar(id,link,index){ | |||
if(this.starActives[index]){ | |||
let url = link+'/'+ id + '/unstar' | |||
this.$axios.put(url).then((res)=>{ | |||
if(res.data.Code===0){ | |||
this.$set(this.starActives,index,false) | |||
this.$set(this.starItems,index,this.starItems[index]-1) | |||
} | |||
}) | |||
}else{ | |||
let url = link+'/'+ id + '/star' | |||
this.$axios.put(url).then((res)=>{ | |||
if(res.data.Code===0){ | |||
this.$set(this.starActives,index,true) | |||
this.$set(this.starItems,index,this.starItems[index]+1) | |||
} | |||
}) | |||
} | |||
}, | |||
getTypeList(){ | |||
const params = new URLSearchParams(window.location.search) | |||
if( window.location.search && params.has('type')){ | |||
if(params.get('type')==0){ | |||
this.datasetType = '0' | |||
} | |||
if(params.get('type')==1){ | |||
this.datasetType = '1' | |||
} | |||
if(params.get('type')==-1){ | |||
this.datasetType = '-1' | |||
} | |||
}else { | |||
this.datasetType = '-1' | |||
} | |||
}, | |||
changeDatasetType(val){ | |||
const searchParams = new URLSearchParams(window.location.search) | |||
if (!window.location.search) { | |||
window.location.href = window.location.href + '?type='+val | |||
} else if (searchParams.has('type')) { | |||
window.location.href = window.location.href.replace(/type=([0-9]|-[0-9])/g,'type='+val) | |||
} else { | |||
window.location.href=window.location.href+'&type='+val | |||
} | |||
}, | |||
gotoDatasetEidt(repolink,id){ | |||
location.href = `${repolink}/datasets/attachments/edit/${id}` | |||
}, | |||
handleClick(repoLink, tabName,type) { | |||
if(tabName=="first"){ | |||
this.page=1 | |||
this.searchDataItem='' | |||
this.getCurrentRepoDataset(repoLink,type) | |||
} | |||
if(tabName=="second"){ | |||
this.page=1 | |||
this.searchDataItem='' | |||
this.getMyDataset(repoLink,type) | |||
} | |||
if(tabName=="third"){ | |||
this.page=1 | |||
this.searchDataItem='' | |||
this.getPublicDataset(repoLink,type) | |||
} | |||
if(tabName=="fourth"){ | |||
this.page=1 | |||
this.searchDataItem='' | |||
this.getStarDataset(repoLink,type) | |||
} | |||
}, | |||
polling (checkStatuDataset,repoLink) { | |||
this.timer = window.setInterval(() => { | |||
setTimeout(() => { | |||
this.getDatasetStatus(checkStatuDataset,repoLink) | |||
},0) | |||
},15000) | |||
}, | |||
getDatasetStatus(checkStatuDataset,repoLink){ | |||
const getmap = checkStatuDataset.map((item)=>{ | |||
let url = `${AppSubUrl}${repolink}/datasets/status/${item.UUID}` | |||
return this.$axios.get(url) | |||
}) | |||
this.$axios.all(getmap) | |||
.then((res)=>{ | |||
let flag = res.some((item)=>{ | |||
return item.data.AttachmentStatus == 1 | |||
}) | |||
flag && clearInterval(this.timer) | |||
flag && this.refreshStatusDataset() | |||
} | |||
) | |||
}, | |||
refreshStatusDataset(){ | |||
switch(this.activeName){ | |||
case 'first': | |||
this.getCurrentRepoDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'second': | |||
this.getMyDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'third': | |||
this.getPublicDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'fourth': | |||
this.getStarDataset(this.repolink,this.cloudbrainType) | |||
break | |||
} | |||
}, | |||
getCurrentRepoDataset(repoLink,type){ | |||
clearInterval(this.timer) | |||
this.loadingDataIndex = true | |||
let url = repoLink + '/datasets/current_repo' | |||
this.$axios.get(url,{ | |||
params:{ | |||
type:type, | |||
page:this.page, | |||
q:this.searchDataItem | |||
} | |||
}).then((res)=>{ | |||
this.currentRepoDataset = JSON.parse(res.data.data) | |||
const checkStatuDataset = this.currentRepoDataset.filter(item=>item.DecompressState===2) | |||
if(checkStatuDataset.length>0){ | |||
this.polling(checkStatuDataset,repoLink) | |||
} | |||
this.totalnums = parseInt(res.data.count) | |||
this.loadingDataIndex = false | |||
}) | |||
}, | |||
getMyDataset(repoLink,type){ | |||
clearInterval(this.timer) | |||
this.loadingDataIndex = true | |||
let url = repoLink + '/datasets/my_datasets' | |||
this.$axios.get(url,{ | |||
params:{ | |||
type:type, | |||
page:this.page, | |||
q:this.searchDataItem | |||
} | |||
}).then((res)=>{ | |||
this.myDataset = JSON.parse(res.data.data) | |||
const checkStatuDataset = this.myDataset.filter(item=>item.DecompressState===2) | |||
if(checkStatuDataset.length>0){ | |||
this.polling(checkStatuDataset,repoLink) | |||
} | |||
this.totalnums = parseInt(res.data.count) | |||
this.loadingDataIndex = false | |||
}) | |||
}, | |||
getPublicDataset(repoLink,type){ | |||
clearInterval(this.timer) | |||
this.loadingDataIndex = true | |||
let url = repoLink + '/datasets/public_datasets' | |||
this.$axios.get(url,{ | |||
params:{ | |||
type:type, | |||
page:this.page, | |||
q:this.searchDataItem | |||
} | |||
}).then((res)=>{ | |||
this.publicDataset = JSON.parse(res.data.data) | |||
const checkStatuDataset = this.publicDataset.filter(item=>item.DecompressState===2) | |||
if(checkStatuDataset.length>0){ | |||
this.polling(checkStatuDataset,repoLink) | |||
} | |||
this.totalnums = parseInt(res.data.count) | |||
this.loadingDataIndex = false | |||
}) | |||
}, | |||
getStarDataset(repoLink,type){ | |||
clearInterval(this.timer) | |||
this.loadingDataIndex = true | |||
let url = repoLink + '/datasets/my_favorite' | |||
this.$axios.get(url,{ | |||
params:{ | |||
type:type, | |||
page:this.page, | |||
q:this.searchDataItem | |||
} | |||
}).then((res)=>{ | |||
this.myFavoriteDataset = JSON.parse(res.data.data) | |||
const checkStatuDataset = this.myFavoriteDataset.filter(item=>item.DecompressState===2) | |||
if(checkStatuDataset.length>0){ | |||
this.polling(checkStatuDataset,repoLink) | |||
} | |||
this.totalnums= parseInt(res.data.count) | |||
this.loadingDataIndex = false | |||
}) | |||
}, | |||
selectDataset(uuid,name){ | |||
this.dataset_uuid = uuid | |||
this.dataset_name = name | |||
this.dialogVisible = false | |||
}, | |||
searchDataset(){ | |||
switch(this.activeName){ | |||
case 'first': | |||
this.page = 1 | |||
this.getCurrentRepoDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'second': | |||
this.page = 1 | |||
this.getMyDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'third': | |||
this.page = 1 | |||
this.getPublicDataset(this.repolink,this.cloudbrainType) | |||
break | |||
case 'fourth': | |||
this.page = 1 | |||
this.getStarDataset(this.repolink,this.cloudbrainType) | |||
break | |||
} | |||
} | |||
}, | |||
}); | |||
} | |||
function initVueEditTopic() { | |||
const el = document.getElementById('topic_edit1'); | |||
@@ -222,3 +222,38 @@ | |||
} | |||
} | |||
} | |||
.panel_creator_reponam{ | |||
display: inline-block; | |||
border-radius: 4px; | |||
padding: 4px; | |||
font-size: 12px; | |||
text-align: center; | |||
background-color: rgba(161, 220, 255, 0.2); | |||
color: #101010; | |||
} | |||
.panel_dataset_name{ | |||
font-size: 15px; | |||
color: #0366D6; | |||
text-align: center; | |||
margin-left: 1rem; | |||
} | |||
.panel_datset_desc{ | |||
white-space: nowrap; | |||
display: inline-block; | |||
overflow: hidden; | |||
width: 90%; | |||
text-overflow: ellipsis; | |||
} | |||
.el-dialog__body{ | |||
padding-top:0 | |||
} | |||
#dataset-base{ | |||
.active{ | |||
color: #0087f5!important; | |||
border: 1px solid #0087f5!important; | |||
/* margin: -1px!important; */ | |||
background: #fff!important; | |||
} | |||
} |
@@ -375,6 +375,10 @@ display: block; | |||
font-size: 18px; | |||
margin-bottom: 1rem; | |||
} | |||
.bgtask-content-button{ | |||
margin-top: 1em; | |||
margin-bottom: 1em; | |||
} | |||
.selectcloudbrain .active.item{ | |||
color: #0087f5 !important; | |||
@@ -624,6 +628,32 @@ display: block; | |||
.a_margin{ | |||
margin: 0px !important; | |||
} | |||
/*pages*/ | |||
.ui.borderless.pagination {border:none} | |||
.ui.pagination.menu .item { | |||
min-width: 32px; | |||
text-align: center; | |||
height: 32px; | |||
border-radius: .28571429rem; | |||
margin: 0 5px; | |||
background-color: #F2F2F2; | |||
} | |||
.ui.pagination.menu>.item:first-child, .ui.pagination.menu .item:last-child { | |||
background-color: #FFF !important; | |||
} | |||
.ui.ui.menu .item.disabled{ | |||
background-color: #F2F2F2; | |||
} | |||
.ui.pagination.menu .active.item { | |||
background-color: #3291F8; | |||
color: #FFF; | |||
} | |||
.ui.pagination.menu .item>.input { | |||
margin: 0em .5em; | |||
width: 3em; | |||
height: 32px; | |||
} | |||
@media only screen and (max-width: 767px) { | |||
.following.bar #navbar .brand{ | |||
padding-top: 6px; | |||
@@ -779,4 +809,87 @@ display: block; | |||
border: none !important; | |||
color: #0366d6 !important; | |||
box-shadow: -15px 0px 10px #fff; | |||
} | |||
/**seach**/ | |||
/**搜索导航条适配窄屏**/ | |||
.seachnav{ | |||
overflow-x: auto; | |||
overflow-y: hidden; | |||
scrollbar-width: none; /* firefox */ | |||
-ms-overflow-style: none; /* IE 10+ */ | |||
} | |||
.seachnav::-webkit-scrollbar { | |||
display: none; /* Chrome Safari */ | |||
} | |||
.ui.green.button, .ui.green.buttons .button{ | |||
background-color: #5BB973; | |||
} | |||
.seach .repos--seach{ | |||
padding-bottom: 0; | |||
border-bottom: none; | |||
} | |||
.seach .ui.secondary.pointing.menu{ | |||
border-bottom: none; | |||
} | |||
.seach .ui.secondary.pointing.menu .item > i{ | |||
margin-right: 5px; | |||
} | |||
.seach .ui.secondary.pointing.menu .active.item{ | |||
border-bottom-width: 2px; | |||
margin: 0 0 -1px; | |||
} | |||
.seach .ui.menu .active.item>.label { | |||
background: #1684FC; | |||
color: #FFF; | |||
} | |||
.seach .ui.menu .item>.label:not(.active.item>.label) { | |||
background: #e8e8e8; | |||
color: rgba(0,0,0,.6); | |||
} | |||
.highlight{ | |||
color: red; | |||
} | |||
.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content { | |||
width: calc(100% - 4.0em); | |||
margin-left: 0; | |||
} | |||
.seach .ui.list .list>.item .header, .seach .ui.list>.item .header{ | |||
margin-bottom: 0.5em; | |||
font-size: 1.4rem !important; | |||
font-weight: normal; | |||
} | |||
.seach .time, .seach .time a{ | |||
font-size: 12px; | |||
color: grey; | |||
} | |||
.seach .list .item.members .ui.avatar.image { | |||
width: 3.2em; | |||
height: 3.2em; | |||
} | |||
.ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content { | |||
width: calc(100% - 4.0em); | |||
margin-left: 0; | |||
} | |||
.searchlabel{ | |||
color: rgba(16, 16, 16, 100); | |||
font-size: 24px; | |||
text-align: left; | |||
font-family: SourceHanSansSC-medium; | |||
} | |||
.hiddenSearch{ | |||
margin: auto; | |||
display: none; | |||
} | |||
#tipmsg { | |||
display: none; | |||
z-index: 9999; | |||
width:150; | |||
height: 80; | |||
} |