@@ -82,6 +82,7 @@ type AttachmentsOptions struct { | |||||
NeedRepoInfo bool | NeedRepoInfo bool | ||||
Keyword string | Keyword string | ||||
RecommendOnly bool | RecommendOnly bool | ||||
UserId int64 | |||||
} | } | ||||
func (a *Attachment) AfterUpdate() { | func (a *Attachment) AfterUpdate() { | ||||
@@ -24,6 +24,7 @@ type ModelArtsJobStatus string | |||||
const ( | const ( | ||||
TypeCloudBrainOne int = iota | TypeCloudBrainOne int = iota | ||||
TypeCloudBrainTwo | TypeCloudBrainTwo | ||||
TypeIntelligentNet | |||||
TypeCloudBrainAll = -1 | TypeCloudBrainAll = -1 | ||||
) | ) | ||||
@@ -328,6 +329,11 @@ type CloudbrainsOptions struct { | |||||
JobTypeNot bool | JobTypeNot bool | ||||
NeedRepoInfo bool | NeedRepoInfo bool | ||||
RepoIDList []int64 | RepoIDList []int64 | ||||
BeginTime time.Time | |||||
EndTime time.Time | |||||
ComputeResource string | |||||
BeginTimeUnix int64 | |||||
EndTimeUnix int64 | |||||
} | } | ||||
type TaskPod struct { | type TaskPod struct { | ||||
@@ -1183,6 +1189,11 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
builder.Eq{"cloudbrain.job_id": opts.JobID}, | builder.Eq{"cloudbrain.job_id": opts.JobID}, | ||||
) | ) | ||||
} | } | ||||
if (opts.ComputeResource) != "" { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.compute_resource": opts.ComputeResource}, | |||||
) | |||||
} | |||||
if (opts.Type) >= 0 { | if (opts.Type) >= 0 { | ||||
cond = cond.And( | cond = cond.And( | ||||
@@ -1318,6 +1329,9 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { | |||||
cond = cond.And( | cond = cond.And( | ||||
builder.Eq{"job_type": "TRAIN"}, | builder.Eq{"job_type": "TRAIN"}, | ||||
) | ) | ||||
cond = cond.And( | |||||
builder.In("type", 0, 1), | |||||
) | |||||
cloudbrains := make([]*CloudbrainInfo, 0) | cloudbrains := make([]*CloudbrainInfo, 0) | ||||
if err := sess.Select("job_id,display_job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | if err := sess.Select("job_id,display_job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | ||||
@@ -1504,6 +1518,11 @@ func UpdateJob(job *Cloudbrain) error { | |||||
return updateJob(x, job) | return updateJob(x, job) | ||||
} | } | ||||
func UpdateJobDurationWithDeleted(job *Cloudbrain) error { | |||||
_, err := x.Exec("update cloudbrain set start_time=?, end_time=?,train_job_duration=?,duration=? where id=?", job.StartTime, job.EndTime, job.TrainJobDuration, job.Duration, job.ID) | |||||
return err | |||||
} | |||||
func updateJob(e Engine, job *Cloudbrain) error { | func updateJob(e Engine, job *Cloudbrain) error { | ||||
_, err := e.ID(job.ID).AllCols().Update(job) | _, err := e.ID(job.ID).AllCols().Update(job) | ||||
return err | return err | ||||
@@ -1574,6 +1593,10 @@ func GetStoppedJobWithNoDurationJob() ([]*Cloudbrain, error) { | |||||
Limit(100). | Limit(100). | ||||
Find(&cloudbrains) | Find(&cloudbrains) | ||||
} | } | ||||
func GetStoppedJobWithNoStartTimeEndTime() ([]*Cloudbrain, error) { | |||||
cloudbrains := make([]*Cloudbrain, 0) | |||||
return cloudbrains, x.SQL("select * from cloudbrain where status in (?,?,?,?,?,?,?) and (start_time is null or end_time is null) limit 100", ModelArtsTrainJobCompleted, ModelArtsTrainJobFailed, ModelArtsTrainJobKilled, ModelArtsStopped, JobStopped, JobFailed, JobSucceeded).Find(&cloudbrains) | |||||
} | |||||
func GetCloudbrainCountByUserID(userID int64, jobType string) (int, error) { | 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)) | count, err := x.In("status", JobWaiting, JobRunning).And("job_type = ? and user_id = ? and type = ?", jobType, userID, TypeCloudBrainOne).Count(new(Cloudbrain)) | ||||
@@ -1650,13 +1673,80 @@ func RestartCloudbrain(old *Cloudbrain, new *Cloudbrain) (err error) { | |||||
func CloudbrainAll(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | func CloudbrainAll(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | defer sess.Close() | ||||
var cond = builder.NewCond() | var cond = builder.NewCond() | ||||
if opts.RepoID > 0 { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.repo_id": opts.RepoID}, | |||||
) | |||||
} | |||||
if opts.UserID > 0 { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.user_id": opts.UserID}, | |||||
) | |||||
} | |||||
if (opts.JobID) != "" { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.job_id": opts.JobID}, | |||||
) | |||||
} | |||||
if (opts.ComputeResource) != "" { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.compute_resource": opts.ComputeResource}, | |||||
) | |||||
} | |||||
if (opts.Type) >= 0 { | if (opts.Type) >= 0 { | ||||
cond = cond.And( | cond = cond.And( | ||||
builder.Eq{"cloudbrain.type": opts.Type}, | builder.Eq{"cloudbrain.type": opts.Type}, | ||||
) | ) | ||||
} | } | ||||
if len(opts.JobTypes) > 0 { | |||||
if opts.JobTypeNot { | |||||
cond = cond.And( | |||||
builder.NotIn("cloudbrain.job_type", opts.JobTypes), | |||||
) | |||||
} else { | |||||
cond = cond.And( | |||||
builder.In("cloudbrain.job_type", opts.JobTypes), | |||||
) | |||||
} | |||||
} | |||||
if (opts.IsLatestVersion) != "" { | |||||
cond = cond.And(builder.Or(builder.And(builder.Eq{"cloudbrain.is_latest_version": opts.IsLatestVersion}, builder.Eq{"cloudbrain.job_type": "TRAIN"}), builder.Neq{"cloudbrain.job_type": "TRAIN"})) | |||||
} | |||||
if len(opts.CloudbrainIDs) > 0 { | |||||
cond = cond.And(builder.In("cloudbrain.id", opts.CloudbrainIDs)) | |||||
} | |||||
if len(opts.JobStatus) > 0 { | |||||
if opts.JobStatusNot { | |||||
cond = cond.And( | |||||
builder.NotIn("cloudbrain.status", opts.JobStatus), | |||||
) | |||||
} else { | |||||
cond = cond.And( | |||||
builder.In("cloudbrain.status", opts.JobStatus), | |||||
) | |||||
} | |||||
} | |||||
if len(opts.RepoIDList) > 0 { | |||||
cond = cond.And( | |||||
builder.In("cloudbrain.repo_id", opts.RepoIDList), | |||||
) | |||||
} | |||||
if opts.BeginTimeUnix > 0 && opts.EndTimeUnix > 0 { | |||||
cond = cond.And( | |||||
builder.And(builder.Gte{"cloudbrain.created_unix": opts.BeginTimeUnix}, builder.Lte{"cloudbrain.created_unix": opts.EndTimeUnix}), | |||||
) | |||||
} | |||||
var count int64 | var count int64 | ||||
var err error | var err error | ||||
condition := "cloudbrain.user_id = `user`.id" | condition := "cloudbrain.user_id = `user`.id" | ||||
@@ -1708,3 +1798,44 @@ func CloudbrainAll(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
return cloudbrains, count, nil | return cloudbrains, count, nil | ||||
} | } | ||||
func CloudbrainAllStatic(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
var cond = builder.NewCond() | |||||
if (opts.Type) >= 0 { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.type": opts.Type}, | |||||
) | |||||
} | |||||
if opts.BeginTimeUnix > 0 && opts.EndTimeUnix > 0 { | |||||
cond = cond.And( | |||||
builder.And(builder.Gte{"cloudbrain.created_unix": opts.BeginTimeUnix}, builder.Lte{"cloudbrain.created_unix": opts.EndTimeUnix}), | |||||
) | |||||
} | |||||
var count int64 | |||||
var err error | |||||
count, err = sess.Unscoped().Where(cond).Count(new(Cloudbrain)) | |||||
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("cloudbrain.created_unix DESC") | |||||
cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum) | |||||
if err := sess.Cols("status", "type", "job_type", "train_job_duration", "duration", "compute_resource", "created_unix", "start_time", "end_time").Table(&Cloudbrain{}).Unscoped().Where(cond). | |||||
Find(&cloudbrains); err != nil { | |||||
return nil, 0, fmt.Errorf("Find: %v", err) | |||||
} | |||||
return cloudbrains, count, nil | |||||
} |
@@ -1,6 +1,191 @@ | |||||
package models | package models | ||||
import "code.gitea.io/gitea/modules/log" | |||||
import ( | |||||
"strconv" | |||||
"time" | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | |||||
"xorm.io/builder" | |||||
) | |||||
type TaskDetail struct { | |||||
ID int64 `json:"ID"` | |||||
JobID string `json:"JobID"` | |||||
JobName string `json:"JobName"` | |||||
DisplayJobName string `json:"DisplayJobName"` | |||||
Status string `json:"Status"` | |||||
JobType string `json:"JobType"` | |||||
CreatedUnix timeutil.TimeStamp `json:"CreatedUnix"` | |||||
WaitTime string `json:"WaitTime"` | |||||
RunTime string `json:"RunTime"` | |||||
StartTime timeutil.TimeStamp `json:"StartTime"` | |||||
EndTime timeutil.TimeStamp `json:"EndTime"` | |||||
ComputeResource string `json:"ComputeResource"` | |||||
Type int `json:"Type"` | |||||
UserName string `json:"UserName"` | |||||
RepoName string `json:"RepoName"` | |||||
RepoAlias string `json:"RepoAlias"` | |||||
RepoID int64 `json:"RepoID"` | |||||
IsDelete bool `json:"IsDelete"` | |||||
} | |||||
func GetDebugOnePeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and job_type ='" + string(JobTypeDebug) + "'" + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainOne) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetDebugOnePeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And job_type = ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), JobTypeDebug, TypeCloudBrainOne).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetTrainOnePeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and job_type ='" + string(JobTypeTrain) + "'" + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainOne) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetTrainOnePeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And job_type = ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), JobTypeTrain, TypeCloudBrainOne).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetBenchmarkOnePeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and job_type ='" + string(JobTypeBenchmark) + "'" + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainOne) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetBenchmarkOnePeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And job_type = ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), JobTypeBenchmark, TypeCloudBrainOne).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetDebugTwoPeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and job_type ='" + string(JobTypeDebug) + "'" + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainTwo) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetDebugTwoPeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And job_type = ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), JobTypeDebug, TypeCloudBrainTwo).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetTrainTwoPeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and job_type ='" + string(JobTypeTrain) + "'" + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainTwo) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetTrainTwoPeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And job_type = ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), JobTypeTrain, TypeCloudBrainTwo).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetInferenceTwoPeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and job_type ='" + string(JobTypeInference) + "'" + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainTwo) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetInferenceTwoPeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And job_type = ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), JobTypeInference, TypeCloudBrainTwo).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetCloudBrainOnePeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainOne) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetCloudBrainOnePeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), TypeCloudBrainOne).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetCloudBrainTwoPeriodCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + | |||||
" and type='" + strconv.Itoa(TypeCloudBrainTwo) + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetCloudBrainTwoPeriodDuration(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
total, err := x.Where("created_unix >= ? And created_unix < ? And type = ? ", strconv.FormatInt(beginTime.Unix(), 10), strconv.FormatInt(endTime.Unix(), 10), TypeCloudBrainTwo).SumInt(&Cloudbrain{}, "duration") | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
return total, nil | |||||
} | |||||
func GetTodayCreatorCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count(distinct user_id) FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetTodayCloudbrainCount(beginTime time.Time, endTime time.Time) (int64, error) { | |||||
countSql := "SELECT count FROM " + | |||||
"public.cloudbrain where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<=" + strconv.FormatInt(endTime.Unix(), 10) | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetCreatorCount() (int64, error) { | |||||
countSql := "SELECT count(distinct user_id) FROM public.cloudbrain" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetRecordBeginTime() ([]*CloudbrainInfo, error) { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
sess.OrderBy("cloudbrain.id ASC limit 1") | |||||
cloudbrains := make([]*CloudbrainInfo, 0) | |||||
if err := sess.Table(&Cloudbrain{}).Unscoped(). | |||||
Find(&cloudbrains); err != nil { | |||||
log.Info("find error.") | |||||
} | |||||
return cloudbrains, nil | |||||
} | |||||
func GetAllStatusCloudBrain() map[string]int { | func GetAllStatusCloudBrain() map[string]int { | ||||
sess := x.NewSession() | sess := x.NewSession() | ||||
@@ -20,3 +205,87 @@ func GetAllStatusCloudBrain() map[string]int { | |||||
} | } | ||||
return cloudBrainStatusResult | return cloudBrainStatusResult | ||||
} | } | ||||
func GetWaittingTop() ([]*CloudbrainInfo, error) { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
var cond = builder.NewCond() | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.status": string(JobWaiting)}, | |||||
) | |||||
sess.OrderBy("cloudbrain.created_unix ASC limit 10") | |||||
cloudbrains := make([]*CloudbrainInfo, 0, 10) | |||||
if err := sess.Table(&Cloudbrain{}).Where(cond). | |||||
Find(&cloudbrains); err != nil { | |||||
log.Info("find error.") | |||||
} | |||||
return cloudbrains, nil | |||||
} | |||||
func GetRunningTop() ([]*CloudbrainInfo, error) { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
var cond = builder.NewCond() | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.status": string(JobRunning)}, | |||||
) | |||||
sess.OrderBy("cloudbrain.duration DESC limit 10") | |||||
cloudbrains := make([]*CloudbrainInfo, 0, 10) | |||||
if err := sess.Table(&Cloudbrain{}).Where(cond). | |||||
Find(&cloudbrains); err != nil { | |||||
log.Info("find error.") | |||||
} | |||||
return cloudbrains, nil | |||||
} | |||||
func getCreatePeriodCount(dateBeginTime string, dateEndTime string, hourBeginTime string, hourEndTime string) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where to_char(to_timestamp(created_unix), 'YYYY-MM-DD') >= '" + dateBeginTime + | |||||
"' and to_char(to_timestamp(created_unix), 'YYYY-MM-DD') < '" + dateEndTime + | |||||
"' and to_char(to_timestamp(created_unix), 'HH24:MI:SS') >= '" + hourBeginTime + | |||||
"' and to_char(to_timestamp(created_unix), 'HH24:MI:SS') < '" + hourEndTime + "'" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
//SELECT * FROM xxx WHERE NOT ((endTime < hourBeginTime) OR (startTime > hourEndTime)) | |||||
func getRunPeriodCount(dateBeginTime string, dateEndTime string, hourBeginTime string, hourEndTime string) (int64, error) { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"public.cloudbrain where not ((to_char(to_timestamp(start_time), ' HH24:MI:SS') > '" + hourEndTime + | |||||
"') or (to_char(to_timestamp(end_time), 'HH24:MI:SS') < '" + hourBeginTime + "'))" + | |||||
" and (to_char(to_timestamp(start_time), 'YYYY-MM-DD') >= '" + dateBeginTime + | |||||
"' and to_char(to_timestamp(start_time), 'YYYY-MM-DD') < '" + dateEndTime + "')" | |||||
return x.SQL(countSql).Count() | |||||
} | |||||
func GetCreateHourPeriodCount(dateBeginTime string, dateEndTime string) (map[string]interface{}, error) { | |||||
//0 to 23 for each hour, | |||||
dateHourMap := make(map[string]interface{}) | |||||
var slice = []int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23} | |||||
for key, value := range slice { | |||||
hourBeginHour := util.AddZero(value) + ":00:00" | |||||
hourEndHour := util.AddZero(value+1) + ":00:00" | |||||
cout, err := getCreatePeriodCount(dateBeginTime, dateEndTime, hourBeginHour, hourEndHour) | |||||
if err != nil { | |||||
log.Error("Can not query getCreatePeriodCount.", err) | |||||
return nil, nil | |||||
} | |||||
dateHourMap[strconv.Itoa(key)] = cout | |||||
} | |||||
return dateHourMap, nil | |||||
} | |||||
func GetRunHourPeriodCount(dateBeginTime string, dateEndTime string) (map[string]interface{}, error) { | |||||
dateHourMap := make(map[string]interface{}) | |||||
var slice = []int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23} | |||||
for key, value := range slice { | |||||
hourBeginHour := util.AddZero(value) + ":00:00" | |||||
hourEndHour := util.AddZero(value+1) + ":00:00" | |||||
cout, err := getRunPeriodCount(dateBeginTime, dateEndTime, hourBeginHour, hourEndHour) | |||||
if err != nil { | |||||
log.Error("Can not query getRunPeriodCount.", err) | |||||
return nil, nil | |||||
} | |||||
dateHourMap[strconv.Itoa(key)] = cout | |||||
} | |||||
return dateHourMap, nil | |||||
} |
@@ -107,6 +107,7 @@ type SearchDatasetOptions struct { | |||||
Category string | Category string | ||||
Task string | Task string | ||||
License string | License string | ||||
DatasetIDs []int64 | |||||
ListOptions | ListOptions | ||||
SearchOrderBy | SearchOrderBy | ||||
IsOwner bool | IsOwner bool | ||||
@@ -177,6 +178,12 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||||
} | } | ||||
} | } | ||||
if len(opts.DatasetIDs) > 0 { | |||||
subCon := builder.NewCond() | |||||
subCon = subCon.And(builder.In("dataset.id", opts.DatasetIDs)) | |||||
cond = cond.Or(subCon) | |||||
} | |||||
return cond | return cond | ||||
} | } | ||||
@@ -447,3 +454,11 @@ func IncreaseDownloadCount(datasetID int64) error { | |||||
return nil | return nil | ||||
} | } | ||||
func GetCollaboratorDatasetIdsByUserID(userID int64) []int64 { | |||||
var datasets []int64 | |||||
_ = x.Table("dataset").Join("INNER", "collaboration", "dataset.repo_id = collaboration.repo_id and collaboration.mode>0 and collaboration.user_id=?", userID). | |||||
Cols("dataset.id").Find(&datasets) | |||||
return datasets | |||||
} |
@@ -6,7 +6,6 @@ | |||||
package models | package models | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/blockchain" | |||||
"container/list" | "container/list" | ||||
"context" | "context" | ||||
"crypto/md5" | "crypto/md5" | ||||
@@ -25,6 +24,8 @@ import ( | |||||
"time" | "time" | ||||
"unicode/utf8" | "unicode/utf8" | ||||
"code.gitea.io/gitea/modules/blockchain" | |||||
"code.gitea.io/gitea/modules/avatar" | "code.gitea.io/gitea/modules/avatar" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/generate" | "code.gitea.io/gitea/modules/generate" | ||||
@@ -1498,6 +1499,17 @@ func GetUsersByIDs(ids []int64) (UserList, error) { | |||||
return ous, err | return ous, err | ||||
} | } | ||||
func GetUsersByNames(names []string) (UserList, error) { | |||||
ous := make([]*User, 0, len(names)) | |||||
if len(names) == 0 { | |||||
return ous, nil | |||||
} | |||||
err := x.In("name", names). | |||||
Asc("name"). | |||||
Find(&ous) | |||||
return ous, err | |||||
} | |||||
// GetUserIDsByNames returns a slice of ids corresponds to names. | // GetUserIDsByNames returns a slice of ids corresponds to names. | ||||
func GetUserIDsByNames(names []string, ignoreNonExistent bool) ([]int64, error) { | func GetUserIDsByNames(names []string, ignoreNonExistent bool) ([]int64, error) { | ||||
ids := make([]int64, 0, len(names)) | ids := make([]int64, 0, len(names)) | ||||
@@ -187,7 +187,7 @@ func AdminOrImageCreaterRight(ctx *context.Context) { | |||||
} | } | ||||
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 { | |||||
func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description, branchName, bootFile, params, commitID string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error { | |||||
dataActualPath := setting.Attachment.Minio.RealPath + | dataActualPath := setting.Attachment.Minio.RealPath + | ||||
setting.Attachment.Minio.Bucket + "/" + | setting.Attachment.Minio.Bucket + "/" + | ||||
@@ -336,6 +336,7 @@ func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, | |||||
Parameters: params, | Parameters: params, | ||||
CreatedUnix: createTime, | CreatedUnix: createTime, | ||||
UpdatedUnix: createTime, | UpdatedUnix: createTime, | ||||
CommitID: commitID, | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
@@ -1131,7 +1131,7 @@ sendjob: | |||||
res, err := client.R(). | res, err := client.R(). | ||||
SetAuthToken(TOKEN). | SetAuthToken(TOKEN). | ||||
SetResult(&result). | SetResult(&result). | ||||
Get(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID + "/versions/" + versionID + "/pod/" + podName + "/metric-statistic") | |||||
Get(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID + "/versions/" + versionID + "/pod/" + podName + "/metric-statistic?statistic_type=each") | |||||
if err != nil { | if err != nil { | ||||
return nil, fmt.Errorf("resty GetTrainJobMetricStatistic: %v", err) | return nil, fmt.Errorf("resty GetTrainJobMetricStatistic: %v", err) | ||||
@@ -1020,13 +1020,16 @@ balance.total_view=余额总览 | |||||
balance.available=可用余额: | balance.available=可用余额: | ||||
cloudbrain1=云脑1 | cloudbrain1=云脑1 | ||||
cloudbrain2=云脑2 | cloudbrain2=云脑2 | ||||
intelligent_net=智算网络 | |||||
cloudbrain_selection=云脑选择 | cloudbrain_selection=云脑选择 | ||||
cloudbrain_platform_selection=选择您准备使用的云脑平台: | cloudbrain_platform_selection=选择您准备使用的云脑平台: | ||||
confirm_choice=确定 | confirm_choice=确定 | ||||
cloudbran1_tips=只有zip格式的数据集才能发起云脑任务 | cloudbran1_tips=只有zip格式的数据集才能发起云脑任务 | ||||
cloudbrain_creator=创建者 | cloudbrain_creator=创建者 | ||||
cloudbrain_type=支撑算力 | |||||
cloudbrain_untype=未知支撑算力 | |||||
cloudbrain_task=任务名称 | cloudbrain_task=任务名称 | ||||
cloudbrain_task_type=任务类型 | |||||
cloudbrain_task_type=云脑任务类型 | |||||
cloudbrain_task_name=云脑侧任务名称 | cloudbrain_task_name=云脑侧任务名称 | ||||
cloudbrain_operate=操作 | cloudbrain_operate=操作 | ||||
cloudbrain_status_createtime=状态/创建时间 | cloudbrain_status_createtime=状态/创建时间 | ||||
@@ -1060,6 +1063,7 @@ computing.success=加入成功 | |||||
modelarts.status=状态 | modelarts.status=状态 | ||||
modelarts.createtime=创建时间 | modelarts.createtime=创建时间 | ||||
modelarts.deletetime=删除时间 | |||||
modelarts.version_nums=版本数 | modelarts.version_nums=版本数 | ||||
modelarts.version=版本 | modelarts.version=版本 | ||||
modelarts.computing_resources=计算资源 | modelarts.computing_resources=计算资源 | ||||
@@ -1090,8 +1094,8 @@ modelarts.train_job.job_status=任务状态 | |||||
modelarts.train_job.job_name=任务名称 | modelarts.train_job.job_name=任务名称 | ||||
modelarts.train_job.version=任务版本 | modelarts.train_job.version=任务版本 | ||||
modelarts.train_job.start_time=开始运行时间 | modelarts.train_job.start_time=开始运行时间 | ||||
modelarts.train_job.end_time=运行结束时间 | |||||
modelarts.train_job.wait_time=等待时间 | |||||
modelarts.train_job.end_time=结束运行时间 | |||||
modelarts.train_job.wait_time=等待时长 | |||||
modelarts.train_job.dura_time=运行时长 | modelarts.train_job.dura_time=运行时长 | ||||
modelarts.train_job.description=任务描述 | modelarts.train_job.description=任务描述 | ||||
modelarts.train_job.parameter_setting=参数设置 | modelarts.train_job.parameter_setting=参数设置 | ||||
@@ -1416,7 +1420,7 @@ issues.label_templates.helper=选择标签模板 | |||||
issues.label_templates.use=使用标签集 | issues.label_templates.use=使用标签集 | ||||
issues.label_templates.fail_to_load_file=加载标签模板文件 '%s' 时发生错误:%v | issues.label_templates.fail_to_load_file=加载标签模板文件 '%s' 时发生错误:%v | ||||
issues.add_label_at=添加了标签 <div class="ui label" style="color: %s\; background-color: %s"> %s </div> %s | issues.add_label_at=添加了标签 <div class="ui label" style="color: %s\; background-color: %s"> %s </div> %s | ||||
issues.remove_label_at=删除了 <div class="ui label" style="color: %s\; background-color: %s">%s</div> label %s 标签 | |||||
issues.remove_label_at=删除了标签 <div class="ui label" style="color: %s\; background-color: %s">%s </div> %s | |||||
issues.add_milestone_at=` %[2]s 添加了里程碑 <b>%[1]s</b>` | issues.add_milestone_at=` %[2]s 添加了里程碑 <b>%[1]s</b>` | ||||
issues.change_milestone_at=`%[3]s 修改了里程碑从 <b>%[1]s</b> 到 <b>%[2]s</b>` | issues.change_milestone_at=`%[3]s 修改了里程碑从 <b>%[1]s</b> 到 <b>%[2]s</b>` | ||||
issues.remove_milestone_at=`%[2]s 删除了里程碑 <b>%[1]s</b>` | issues.remove_milestone_at=`%[2]s 删除了里程碑 <b>%[1]s</b>` | ||||
@@ -217,9 +217,9 @@ function refresh3DInfo(record){ | |||||
//console.log("cloudbrain two line length=" + lines.length); | //console.log("cloudbrain two line length=" + lines.length); | ||||
var span = $('.rotation3D__line').find("span")[1]; | var span = $('.rotation3D__line').find("span")[1]; | ||||
//console.log(span); | //console.log(span); | ||||
span.innerText =record.RefName; | |||||
//$('.rotation3D__line').find("span").eq(1).text(record.RefName) | |||||
//lines[1].find("span").text(record.RefName); | |||||
if(span != null){ | |||||
span.innerText =record.RefName; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -452,48 +452,12 @@ function queryRecommendData(){ | |||||
displayOrg(json.org); | displayOrg(json.org); | ||||
displayRepo(json.repo); | displayRepo(json.repo); | ||||
displayActivity(json.image); | displayActivity(json.image); | ||||
displayCloudBrain(json.cloudbrain) | |||||
}, | }, | ||||
error:function(response) { | error:function(response) { | ||||
} | } | ||||
}); | }); | ||||
// $.ajax({ | |||||
// type:"GET", | |||||
// url:"/recommend/repo", | |||||
// headers: { | |||||
// authorization:token, | |||||
// }, | |||||
// dataType:"json", | |||||
// async:false, | |||||
// success:function(json){ | |||||
// displayRepo(json); | |||||
// }, | |||||
// error:function(response) { | |||||
// } | |||||
// }); | |||||
// $.ajax({ | |||||
// type:"GET", | |||||
// url:"/recommend/imageinfo", | |||||
// headers: { | |||||
// authorization:token, | |||||
// }, | |||||
// dataType:"json", | |||||
// async:false, | |||||
// success:function(json){ | |||||
// displayActivity(json); | |||||
// }, | |||||
// error:function(response) { | |||||
// } | |||||
// }); | |||||
} | } | ||||
function displayCloudBrain(json){ | |||||
$('#completed_task').text(json.completed_task); | |||||
$('#running_task').text(json.running_task); | |||||
$('#wait_task').text(json.wait_task); | |||||
} | |||||
function displayActivity(json){ | function displayActivity(json){ | ||||
var activityDiv = document.getElementById("recommendactivity"); | var activityDiv = document.getElementById("recommendactivity"); | ||||
@@ -574,9 +574,18 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Group("/cloudbrainboard", func() { | m.Group("/cloudbrainboard", func() { | ||||
m.Get("/downloadAll", repo.DownloadCloudBrainBoard) | m.Get("/downloadAll", repo.DownloadCloudBrainBoard) | ||||
m.Group("/cloudbrain", func() { | m.Group("/cloudbrain", func() { | ||||
m.Get("/overview", repo.GetAllCloudbrainsOverview) | |||||
m.Get("/distribution", repo.GetAllCloudbrainsPeriodDistribution) | |||||
m.Get("/trend", repo.GetAllCloudbrainsTrend) | |||||
m.Get("/trend_detail_data", repo.GetAllCloudbrainsTrendDetail) | |||||
m.Get("/status_analysis", repo.GetCloudbrainsStatusAnalysis) | m.Get("/status_analysis", repo.GetCloudbrainsStatusAnalysis) | ||||
m.Get("/detail_data", repo.GetCloudbrainsDetailData) | |||||
m.Get("/hours_data", repo.GetCloudbrainsCreateHoursData) | |||||
m.Get("/waitting_top_data", repo.GetWaittingTop) | |||||
m.Get("/running_top_data", repo.GetRunningTop) | |||||
}) | }) | ||||
}, operationReq) | }, operationReq) | ||||
// Users | // Users | ||||
m.Group("/users", func() { | m.Group("/users", func() { | ||||
m.Get("/search", user.Search) | m.Get("/search", user.Search) | ||||
@@ -192,7 +192,6 @@ func GetProjectsSummaryData(ctx *context.Context) { | |||||
} | } | ||||
projectSummaryPeriodData := ProjectSummaryPeriodData{ | projectSummaryPeriodData := ProjectSummaryPeriodData{ | ||||
TotalCount: count - 1, | TotalCount: count - 1, | ||||
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT), | RecordBeginTime: recordBeginTime.Format(DATE_FORMAT), | ||||
@@ -203,7 +202,7 @@ func GetProjectsSummaryData(ctx *context.Context) { | |||||
} | } | ||||
func reverse(datas []*ProjectSummaryBaseData ) []*ProjectSummaryBaseData { | |||||
func reverse(datas []*ProjectSummaryBaseData) []*ProjectSummaryBaseData { | |||||
for i := 0; i < len(datas)/2; i++ { | for i := 0; i < len(datas)/2; i++ { | ||||
j := len(datas) - i - 1 | j := len(datas) - i - 1 | ||||
datas[i], datas[j] = datas[j], datas[i] | datas[i], datas[j] = datas[j], datas[i] | ||||
@@ -211,8 +210,6 @@ func reverse(datas []*ProjectSummaryBaseData ) []*ProjectSummaryBaseData { | |||||
return datas | return datas | ||||
} | } | ||||
func setStatisticsData(data *ProjectSummaryBaseData, v *models.SummaryStatistic, stats *models.SummaryStatistic) { | func setStatisticsData(data *ProjectSummaryBaseData, v *models.SummaryStatistic, stats *models.SummaryStatistic) { | ||||
data.NumReposAdd = v.NumRepos - stats.NumRepos | data.NumReposAdd = v.NumRepos - stats.NumRepos | ||||
data.NumRepoPublicAdd = v.NumRepoPublic - stats.NumRepoPublic | data.NumRepoPublicAdd = v.NumRepoPublic - stats.NumRepoPublic | ||||
@@ -890,12 +887,19 @@ func getTimePeroid(ctx *context.Context, recordBeginTime time.Time) (time.Time, | |||||
if queryType == "all" { | if queryType == "all" { | ||||
beginTime = recordBeginTimeTemp | beginTime = recordBeginTimeTemp | ||||
endTime = now | endTime = now | ||||
} else if queryType == "yesterday" { | |||||
} else if queryType == "today" { | |||||
endTime = now | endTime = now | ||||
beginTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location()) | beginTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location()) | ||||
} else if queryType == "yesterday" { | |||||
endTime = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) | |||||
beginTime = endTime.AddDate(0, 0, -1) | |||||
} else if queryType == "current_week" { | |||||
beginTime = now.AddDate(0, 0, -int(time.Now().Weekday())+2) //begin from monday | |||||
} else if queryType == "last_7day" { | |||||
beginTime = now.AddDate(0, 0, -7) | |||||
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) | |||||
endTime = now | |||||
} else if queryType == "last_30day" { | |||||
beginTime = now.AddDate(0, 0, -30) | |||||
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) | beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) | ||||
endTime = now | endTime = now | ||||
} else if queryType == "current_month" { | } else if queryType == "current_month" { | ||||
@@ -7,7 +7,6 @@ package routers | |||||
import ( | import ( | ||||
"bytes" | "bytes" | ||||
"fmt" | |||||
"net/http" | "net/http" | ||||
"strconv" | "strconv" | ||||
"strings" | "strings" | ||||
@@ -343,6 +342,12 @@ func ExploreDatasets(ctx *context.Context) { | |||||
if ctx.User != nil && !ctx.User.IsAdmin { | if ctx.User != nil && !ctx.User.IsAdmin { | ||||
ownerID = ctx.User.ID | ownerID = ctx.User.ID | ||||
} | } | ||||
var datasetsIds []int64 | |||||
if ownerID > 0 { | |||||
datasetsIds = models.GetCollaboratorDatasetIdsByUserID(ownerID) | |||||
} | |||||
opts := &models.SearchDatasetOptions{ | opts := &models.SearchDatasetOptions{ | ||||
Keyword: keyword, | Keyword: keyword, | ||||
IncludePublic: true, | IncludePublic: true, | ||||
@@ -351,6 +356,7 @@ func ExploreDatasets(ctx *context.Context) { | |||||
Task: task, | Task: task, | ||||
License: license, | License: license, | ||||
OwnerID: ownerID, | OwnerID: ownerID, | ||||
DatasetIDs: datasetsIds, | |||||
RecommendOnly: ctx.QueryBool("recommend"), | RecommendOnly: ctx.QueryBool("recommend"), | ||||
ListOptions: models.ListOptions{ | ListOptions: models.ListOptions{ | ||||
Page: page, | Page: page, | ||||
@@ -666,10 +672,19 @@ func getRecommendOrg() ([]map[string]interface{}, error) { | |||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} | } | ||||
names := make([]string, 0) | |||||
for _, userName := range result { | |||||
names = append(names, userName) | |||||
} | |||||
users, _ := models.GetUsersByNames(names) | |||||
userMap := make(map[string]*models.User, 0) | |||||
for _, user := range users { | |||||
userMap[user.Name] = user | |||||
} | |||||
resultOrg := make([]map[string]interface{}, 0) | resultOrg := make([]map[string]interface{}, 0) | ||||
for _, userName := range result { | for _, userName := range result { | ||||
user, err := models.GetUserByName(userName) | |||||
if err == nil { | |||||
user := userMap[userName] | |||||
if user != nil { | |||||
userMap := make(map[string]interface{}) | userMap := make(map[string]interface{}) | ||||
userMap["Name"] = user.Name | userMap["Name"] = user.Name | ||||
userMap["Description"] = user.Description | userMap["Description"] = user.Description | ||||
@@ -682,7 +697,7 @@ func getRecommendOrg() ([]map[string]interface{}, error) { | |||||
userMap["NumMembers"] = user.NumMembers | userMap["NumMembers"] = user.NumMembers | ||||
resultOrg = append(resultOrg, userMap) | resultOrg = append(resultOrg, userMap) | ||||
} else { | } else { | ||||
log.Info("query user error," + err.Error()) | |||||
log.Info("the user not exist," + userName) | |||||
} | } | ||||
} | } | ||||
return resultOrg, nil | return resultOrg, nil | ||||
@@ -751,15 +766,6 @@ func GetRankUser(index string) ([]map[string]interface{}, error) { | |||||
return resultOrg, nil | return resultOrg, nil | ||||
} | } | ||||
// func GetImageInfoFromPromote(ctx *context.Context) { | |||||
// imageInfo, err := GetImageInfo() | |||||
// if err != nil { | |||||
// ctx.ServerError("500", err) | |||||
// return | |||||
// } | |||||
// ctx.JSON(200, imageInfo) | |||||
// } | |||||
func GetUserRankFromPromote(ctx *context.Context) { | func GetUserRankFromPromote(ctx *context.Context) { | ||||
index := ctx.Params("index") | index := ctx.Params("index") | ||||
resultUserRank, err := GetRankUser(index) | resultUserRank, err := GetRankUser(index) | ||||
@@ -783,45 +789,15 @@ func RecommendHomeInfo(ctx *context.Context) { | |||||
if err != nil { | if err != nil { | ||||
log.Info("error." + err.Error()) | log.Info("error." + err.Error()) | ||||
} | } | ||||
resultCloudBrain, err := getCloudbrainNums() | |||||
if err != nil { | |||||
log.Info("error." + err.Error()) | |||||
} | |||||
mapInterface := make(map[string]interface{}) | mapInterface := make(map[string]interface{}) | ||||
mapInterface["org"] = resultOrg | mapInterface["org"] = resultOrg | ||||
mapInterface["repo"] = resultRepo | mapInterface["repo"] = resultRepo | ||||
mapInterface["image"] = resultImage | mapInterface["image"] = resultImage | ||||
mapInterface["cloudbrain"] = resultCloudBrain | |||||
//mapInterface["cloudbrain"] = resultCloudBrain | |||||
ctx.JSON(http.StatusOK, mapInterface) | ctx.JSON(http.StatusOK, mapInterface) | ||||
} | } | ||||
func getCloudbrainNums() (map[string]string, error) { | |||||
result := make(map[string]string) | |||||
cloudStatusMap := models.GetAllStatusCloudBrain() | |||||
result["completed_task"] = fmt.Sprint(cloudStatusMap["COMPLETED"]) | |||||
result["running_task"] = fmt.Sprint(cloudStatusMap["RUNNING"]) | |||||
result["wait_task"] = fmt.Sprint(cloudStatusMap["WAITING"]) | |||||
return result, nil | |||||
} | |||||
// func RecommendOrgFromPromote(ctx *context.Context) { | |||||
// resultOrg, err := GetRecommendOrg() | |||||
// if err != nil { | |||||
// ctx.ServerError("500", err) | |||||
// return | |||||
// } | |||||
// ctx.JSON(200, resultOrg) | |||||
// } | |||||
func RecommendRepoFromPromote(ctx *context.Context) { | |||||
result, err := repository.GetRecommendRepoFromPromote("projects") | |||||
if err != nil { | |||||
ctx.ServerError("500", err) | |||||
} else { | |||||
ctx.JSON(200, result) | |||||
} | |||||
} | |||||
func HomeTerm(ctx *context.Context) { | func HomeTerm(ctx *context.Context) { | ||||
ctx.HTML(200, tplHomeTerm) | ctx.HTML(200, tplHomeTerm) | ||||
} | } |
@@ -66,6 +66,14 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
return err | return err | ||||
} | } | ||||
} else if cloudType == models.TypeCloudBrainOne { | } else if cloudType == models.TypeCloudBrainOne { | ||||
var ResourceSpecs *models.ResourceSpecs | |||||
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||||
for _, tmp := range ResourceSpecs.ResourceSpec { | |||||
if tmp.Id == aiTask.ResourceSpecId { | |||||
flaverName := ctx.Tr("cloudbrain.gpu_num") + ": " + fmt.Sprint(tmp.GpuNum) + " " + ctx.Tr("cloudbrain.cpu_num") + ": " + fmt.Sprint(tmp.CpuNum) + " " + ctx.Tr("cloudbrain.memory") + "(MB): " + fmt.Sprint(tmp.MemMiB) + " " + ctx.Tr("cloudbrain.shared_memory") + "(MB): " + fmt.Sprint(tmp.ShareMemMiB) | |||||
aiTask.FlavorName = flaverName | |||||
} | |||||
} | |||||
modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl) | modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl) | ||||
if err != nil { | if err != nil { | ||||
log.Info("download model from CloudBrainOne faild." + err.Error()) | log.Info("download model from CloudBrainOne faild." + err.Error()) | ||||
@@ -97,7 +105,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
UserId: ctx.User.ID, | UserId: ctx.User.ID, | ||||
CodeBranch: aiTask.BranchName, | CodeBranch: aiTask.BranchName, | ||||
CodeCommitID: aiTask.CommitID, | CodeCommitID: aiTask.CommitID, | ||||
Engine: aiTask.EngineID, | |||||
Engine: int64(engine), | |||||
TrainTaskInfo: string(aiTaskJson), | TrainTaskInfo: string(aiTaskJson), | ||||
Accuracy: string(accuracyJson), | Accuracy: string(accuracyJson), | ||||
} | } | ||||
@@ -283,11 +283,13 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
mkModelPath(modelPath) | mkModelPath(modelPath) | ||||
uploadCodeToMinio(modelPath, jobName, cloudbrain.ModelMountPath+"/") | uploadCodeToMinio(modelPath, jobName, cloudbrain.ModelMountPath+"/") | ||||
commitID, _ := ctx.Repo.GitRepo.GetBranchCommitID(branchName) | |||||
err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | err = cloudbrain.GenerateTask(ctx, displayJobName, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params, | storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params, | ||||
0, 0, resourceSpecId) | |||||
commitID, 0, 0, resourceSpecId) | |||||
if err != nil { | if err != nil { | ||||
cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
ctx.RenderWithErr(err.Error(), tpl, &form) | ctx.RenderWithErr(err.Error(), tpl, &form) | ||||
@@ -1479,11 +1481,19 @@ func SyncCloudbrainStatus() { | |||||
} | } | ||||
func HandleTaskWithNoDuration(ctx *context.Context) { | func HandleTaskWithNoDuration(ctx *context.Context) { | ||||
mode := ctx.Query("mode") | |||||
log.Info("HandleTaskWithNoDuration start") | log.Info("HandleTaskWithNoDuration start") | ||||
count := 0 | count := 0 | ||||
start := time.Now().Unix() | start := time.Now().Unix() | ||||
for { | for { | ||||
cloudBrains, err := models.GetStoppedJobWithNoDurationJob() | |||||
var cloudBrains []*models.Cloudbrain | |||||
var err error | |||||
if mode == "1" { | |||||
cloudBrains, err = models.GetStoppedJobWithNoStartTimeEndTime() | |||||
} else { | |||||
cloudBrains, err = models.GetStoppedJobWithNoDurationJob() | |||||
} | |||||
if err != nil { | if err != nil { | ||||
log.Error("HandleTaskWithNoTrainJobDuration failed:", err.Error()) | log.Error("HandleTaskWithNoTrainJobDuration failed:", err.Error()) | ||||
break | break | ||||
@@ -1558,7 +1568,7 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) { | |||||
} | } | ||||
task.Duration = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() | task.Duration = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() | ||||
task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | task.TrainJobDuration = models.ConvertDurationToStr(task.Duration) | ||||
err = models.UpdateJob(task) | |||||
err = models.UpdateJobDurationWithDeleted(task) | |||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | ||||
} | } | ||||
@@ -1583,7 +1593,7 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) { | |||||
} | } | ||||
task.CorrectCreateUnix() | task.CorrectCreateUnix() | ||||
task.ComputeAndSetDuration() | task.ComputeAndSetDuration() | ||||
err = models.UpdateJob(task) | |||||
err = models.UpdateJobDurationWithDeleted(task) | |||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | ||||
continue | continue | ||||
@@ -1604,7 +1614,7 @@ func handleNoDurationTask(cloudBrains []*models.Cloudbrain) { | |||||
task.EndTime = task.StartTime.Add(result.Duration / 1000) | task.EndTime = task.StartTime.Add(result.Duration / 1000) | ||||
} | } | ||||
task.ComputeAndSetDuration() | task.ComputeAndSetDuration() | ||||
err = models.UpdateJob(task) | |||||
err = models.UpdateJobDurationWithDeleted(task) | |||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | ||||
continue | continue | ||||
@@ -1625,7 +1635,7 @@ func updateDefaultDuration(task *models.Cloudbrain) { | |||||
task.StartTime = task.CreatedUnix | task.StartTime = task.CreatedUnix | ||||
task.EndTime = task.UpdatedUnix | task.EndTime = task.UpdatedUnix | ||||
task.ComputeAndSetDuration() | task.ComputeAndSetDuration() | ||||
err := models.UpdateJob(task) | |||||
err := models.UpdateJobDurationWithDeleted(task) | |||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | ||||
} | } | ||||
@@ -1976,7 +1986,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo | |||||
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, cloudbrain.DefaultBranchName, "", "", | storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), string(models.JobTypeBenchmark), gpuQueue, form.Description, cloudbrain.DefaultBranchName, "", "", | ||||
benchmarkTypeID, benchmarkChildTypeID, resourceSpecId) | |||||
"", benchmarkTypeID, benchmarkChildTypeID, resourceSpecId) | |||||
if err != nil { | if err != nil { | ||||
cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
ctx.RenderWithErr(err.Error(), tplCloudBrainBenchmarkNew, &form) | ctx.RenderWithErr(err.Error(), tplCloudBrainBenchmarkNew, &form) | ||||
@@ -2074,7 +2084,7 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) | |||||
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | ||||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params, | storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, form.Description, branchName, form.BootFile, form.Params, | ||||
0, benchmarkChildTypeID, resourceSpecId) | |||||
"", 0, benchmarkChildTypeID, resourceSpecId) | |||||
if err != nil { | if err != nil { | ||||
cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
ctx.RenderWithErr(err.Error(), tpl, &form) | ctx.RenderWithErr(err.Error(), tpl, &form) | ||||
@@ -172,8 +172,8 @@ func DatasetIndex(ctx *context.Context) { | |||||
for _, attachment := range pageAttachments { | for _, attachment := range pageAttachments { | ||||
uploader, _ := models.GetUserByID(attachment.UploaderID) | uploader, _ := models.GetUserByID(attachment.UploaderID) | ||||
attachment.Uploader = uploader | attachment.Uploader = uploader | ||||
if !strings.HasSuffix(attachment.Name, ".zip") { | |||||
attachment.DecompressState = -1 //非zip文件 | |||||
if !strings.HasSuffix(attachment.Name, ".zip") && !strings.HasSuffix(attachment.Name, ".tar.gz") { | |||||
attachment.DecompressState = -1 //非压缩文件 | |||||
} | } | ||||
} | } | ||||
@@ -452,10 +452,11 @@ func PublicDataset(ctx *context.Context) { | |||||
} | } | ||||
func MyFavoriteDataset(ctx *context.Context) { | func MyFavoriteDataset(ctx *context.Context) { | ||||
page := ctx.QueryInt("page") | |||||
UserId := ctx.User.ID | |||||
cloudbrainType := ctx.QueryInt("type") | cloudbrainType := ctx.QueryInt("type") | ||||
keyword := strings.Trim(ctx.Query("q"), " ") | keyword := strings.Trim(ctx.Query("q"), " ") | ||||
var datasetIDs []int64 | |||||
var NotColDatasetIDs []int64 | |||||
var IsColDatasetIDs []int64 | |||||
datasetStars, err := models.GetDatasetStarByUser(ctx.User) | datasetStars, err := models.GetDatasetStarByUser(ctx.User) | ||||
if err != nil { | if err != nil { | ||||
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("GetDatasetStarByUser failed", err))) | ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("GetDatasetStarByUser failed", err))) | ||||
@@ -467,31 +468,82 @@ func MyFavoriteDataset(ctx *context.Context) { | |||||
}) | }) | ||||
return | return | ||||
} | } | ||||
for i, _ := range datasetStars { | |||||
datasetIDs = append(datasetIDs, datasetStars[i].DatasetID) | |||||
//If the dataset has been deleted, it will not be counted | |||||
for _, datasetStar := range datasetStars { | |||||
IsExist, repo, dataset, err := IsDatasetStarExist(datasetStar) | |||||
if err != nil { | |||||
log.Error("IsDatasetStarExist error:", err.Error()) | |||||
} | |||||
if IsExist { | |||||
DatasetIsCollaborator := DatasetIsCollaborator(ctx, dataset) | |||||
if repo.OwnerID == ctx.User.ID || DatasetIsCollaborator { | |||||
IsColDatasetIDs = append(IsColDatasetIDs, datasetStar.DatasetID) | |||||
} else { | |||||
NotColDatasetIDs = append(NotColDatasetIDs, datasetStar.DatasetID) | |||||
} | |||||
} | |||||
} | } | ||||
datasets, count, err := models.Attachments(&models.AttachmentsOptions{ | |||||
ListOptions: models.ListOptions{ | |||||
Page: page, | |||||
PageSize: setting.UI.DatasetPagingNum, | |||||
}, | |||||
NotColDatasets, NotColcount, err := models.Attachments(&models.AttachmentsOptions{ | |||||
Keyword: keyword, | Keyword: keyword, | ||||
NeedDatasetIDs: true, | NeedDatasetIDs: true, | ||||
DatasetIDs: datasetIDs, | |||||
DatasetIDs: NotColDatasetIDs, | |||||
NeedIsPrivate: true, | NeedIsPrivate: true, | ||||
IsPrivate: false, | IsPrivate: false, | ||||
Type: cloudbrainType, | Type: cloudbrainType, | ||||
JustNeedZipFile: true, | JustNeedZipFile: true, | ||||
NeedRepoInfo: true, | NeedRepoInfo: true, | ||||
RecommendOnly: ctx.QueryBool("recommend"), | RecommendOnly: ctx.QueryBool("recommend"), | ||||
UserId: UserId, | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("datasets", err) | ctx.ServerError("datasets", err) | ||||
return | return | ||||
} | } | ||||
//If is collaborator, there is no need to determine whether the dataset is private or public | |||||
IsColDatasets, IsColcount, err := models.Attachments(&models.AttachmentsOptions{ | |||||
Keyword: keyword, | |||||
NeedDatasetIDs: true, | |||||
DatasetIDs: IsColDatasetIDs, | |||||
NeedIsPrivate: false, | |||||
Type: cloudbrainType, | |||||
JustNeedZipFile: true, | |||||
NeedRepoInfo: true, | |||||
RecommendOnly: ctx.QueryBool("recommend"), | |||||
UserId: UserId, | |||||
}) | |||||
if err != nil { | |||||
ctx.ServerError("datasets", err) | |||||
return | |||||
} | |||||
for _, NotColDataset := range NotColDatasets { | |||||
IsColDatasets = append(IsColDatasets, NotColDataset) | |||||
} | |||||
datasets := IsColDatasets | |||||
count := NotColcount + IsColcount | |||||
sort.Slice(datasets, func(i, j int) bool { | |||||
return datasets[i].Attachment.CreatedUnix > datasets[j].Attachment.CreatedUnix | |||||
}) | |||||
data, err := json.Marshal(datasets) | |||||
page := ctx.QueryInt("page") | |||||
if page <= 0 { | |||||
page = 1 | |||||
} | |||||
pagesize := ctx.QueryInt("pagesize") | |||||
if pagesize <= 0 { | |||||
pagesize = 5 | |||||
} | |||||
pageDatasetsInfo := getPageDatasets(datasets, page, pagesize) | |||||
if pageDatasetsInfo == nil { | |||||
ctx.JSON(200, map[string]string{ | |||||
"result_code": "0", | |||||
"data": "[]", | |||||
"count": strconv.FormatInt(count, 10), | |||||
}) | |||||
return | |||||
} | |||||
data, err := json.Marshal(pageDatasetsInfo) | |||||
log.Info("data:", data) | |||||
if err != nil { | if err != nil { | ||||
log.Error("json.Marshal failed:", err.Error()) | log.Error("json.Marshal failed:", err.Error()) | ||||
ctx.JSON(200, map[string]string{ | ctx.JSON(200, map[string]string{ | ||||
@@ -508,6 +560,29 @@ func MyFavoriteDataset(ctx *context.Context) { | |||||
}) | }) | ||||
} | } | ||||
func getPageDatasets(AttachmentInfos []*models.AttachmentInfo, page int, pagesize int) []*models.AttachmentInfo { | |||||
begin := (page - 1) * pagesize | |||||
end := (page) * pagesize | |||||
if begin > len(AttachmentInfos)-1 { | |||||
return nil | |||||
} | |||||
if end > len(AttachmentInfos)-1 { | |||||
return AttachmentInfos[begin:] | |||||
} else { | |||||
return AttachmentInfos[begin:end] | |||||
} | |||||
} | |||||
func getTotalPage(total int64, pageSize int) int { | |||||
another := 0 | |||||
if int(total)%pageSize != 0 { | |||||
another = 1 | |||||
} | |||||
return int(total)/pageSize + another | |||||
} | |||||
func GetDatasetStatus(ctx *context.Context) { | func GetDatasetStatus(ctx *context.Context) { | ||||
@@ -533,3 +608,55 @@ func GetDatasetStatus(ctx *context.Context) { | |||||
"AttachmentStatus": fmt.Sprint(attachment.DecompressState), | "AttachmentStatus": fmt.Sprint(attachment.DecompressState), | ||||
}) | }) | ||||
} | } | ||||
func DatasetIsCollaborator(ctx *context.Context, dataset *models.Dataset) bool { | |||||
repo, err := models.GetRepositoryByID(dataset.RepoID) | |||||
if err != nil { | |||||
log.Error("query repo error:", err.Error()) | |||||
} else { | |||||
repo.GetOwner() | |||||
if ctx.User != nil { | |||||
if repo.Owner.IsOrganization() { | |||||
org := repo.Owner | |||||
org.Teams, err = org.GetUserTeams(ctx.User.ID) | |||||
if err != nil { | |||||
log.Error("GetUserTeams error:", err.Error()) | |||||
return false | |||||
} | |||||
if org.IsUserPartOfOrg(ctx.User.ID) { | |||||
for _, t := range org.Teams { | |||||
if t.IsMember(ctx.User.ID) && t.HasRepository(repo.ID) { | |||||
return true | |||||
} | |||||
} | |||||
isOwner, _ := models.IsOrganizationOwner(repo.OwnerID, ctx.User.ID) | |||||
if isOwner { | |||||
return isOwner | |||||
} | |||||
return false | |||||
} | |||||
} | |||||
isCollaborator, _ := repo.IsCollaborator(ctx.User.ID) | |||||
if isCollaborator { | |||||
return true | |||||
} | |||||
} | |||||
} | |||||
return false | |||||
} | |||||
func IsDatasetStarExist(datasetStar *models.DatasetStar) (bool, *models.Repository, *models.Dataset, error) { | |||||
dataset, err := models.GetDatasetByID(datasetStar.DatasetID) | |||||
if err != nil { | |||||
log.Error("query dataset error:", err.Error()) | |||||
return false, nil, nil, err | |||||
} else { | |||||
repo, err := models.GetRepositoryByID(dataset.RepoID) | |||||
if err != nil { | |||||
log.Error("GetRepositoryByID error:", err.Error()) | |||||
return false, nil, nil, err | |||||
} | |||||
return true, repo, dataset, nil | |||||
} | |||||
} |
@@ -1407,7 +1407,7 @@ func readDir(dirname string) ([]os.FileInfo, error) { | |||||
return nil, err | return nil, err | ||||
} | } | ||||
list, err := f.Readdir(100) | |||||
list, err := f.Readdir(0) | |||||
f.Close() | f.Close() | ||||
if err != nil { | if err != nil { | ||||
//todo: can not upload empty folder | //todo: can not upload empty folder | ||||
@@ -331,6 +331,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Post("/all/search/", routers.Search) | m.Post("/all/search/", routers.Search) | ||||
m.Get("/all/search/", routers.EmptySearch) | m.Get("/all/search/", routers.EmptySearch) | ||||
m.Get("/all/dosearch/", routers.SearchApi) | m.Get("/all/dosearch/", routers.SearchApi) | ||||
m.Post("/user/login/kanban", user.SignInPostAPI) | |||||
m.Get("/home/term", routers.HomeTerm) | m.Get("/home/term", routers.HomeTerm) | ||||
m.Group("/explore", func() { | m.Group("/explore", func() { | ||||
m.Get("", func(ctx *context.Context) { | m.Get("", func(ctx *context.Context) { | ||||
@@ -365,6 +366,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Group("/user", func() { | m.Group("/user", func() { | ||||
m.Get("/login", user.SignIn) | m.Get("/login", user.SignIn) | ||||
m.Get("/login/cloud_brain", user.SignInCloudBrain) | m.Get("/login/cloud_brain", user.SignInCloudBrain) | ||||
m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) | m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) | ||||
m.Group("", func() { | m.Group("", func() { | ||||
m.Combo("/login/openid"). | m.Combo("/login/openid"). | ||||
@@ -489,7 +489,7 @@ func makeRepoResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool, | |||||
if recordSource["avatar"] != nil { | if recordSource["avatar"] != nil { | ||||
avatarstr := recordSource["avatar"].(string) | avatarstr := recordSource["avatar"].(string) | ||||
if len(avatarstr) == 0 { | if len(avatarstr) == 0 { | ||||
record["avatar"] = setting.RepositoryAvatarFallbackImage | |||||
// record["avatar"] = setting.RepositoryAvatarFallbackImage | |||||
} else { | } else { | ||||
record["avatar"] = setting.AppSubURL + "/repo-avatars/" + avatarstr | record["avatar"] = setting.AppSubURL + "/repo-avatars/" + avatarstr | ||||
} | } | ||||
@@ -176,6 +176,41 @@ func SignInCloudBrain(ctx *context.Context) { | |||||
ctx.HTML(200, tplSignInCloudBrain) | ctx.HTML(200, tplSignInCloudBrain) | ||||
} | } | ||||
func SignInPostAPI(ctx *context.Context) { | |||||
ctx.Data["Title"] = ctx.Tr("sign_in") | |||||
UserName := ctx.Query("UserName") | |||||
Password := ctx.Query("Password") | |||||
log.Info("0000000") | |||||
orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers() | |||||
if err != nil { | |||||
ctx.ServerError("UserSignIn", err) | |||||
return | |||||
} | |||||
ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names | |||||
ctx.Data["OAuth2Providers"] = oauth2Providers | |||||
ctx.Data["Title"] = ctx.Tr("sign_in") | |||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" | |||||
ctx.Data["PageIsSignIn"] = true | |||||
ctx.Data["PageIsLogin"] = true | |||||
ctx.Data["IsCourse"] = ctx.QueryBool("course") | |||||
ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() | |||||
if ctx.HasError() { | |||||
ctx.HTML(200, tplSignIn) | |||||
return | |||||
} | |||||
u, err := models.UserSignIn(UserName, Password) | |||||
if err != nil { | |||||
ctx.ServerError("UserSignIn", err) | |||||
return | |||||
} | |||||
models.SaveLoginInfoToDb(ctx.Req.Request, u) | |||||
// If this user is enrolled in 2FA, we can't sign the user in just yet. | |||||
// Instead, redirect them to the 2FA authentication page. | |||||
//handleSignInFull(ctx, u, form.Remember, false) | |||||
handleSignInFullNotRedirect(ctx, u, true, false) | |||||
} | |||||
// SignInPost response for sign in request | // SignInPost response for sign in request | ||||
func SignInPost(ctx *context.Context, form auth.SignInForm) { | func SignInPost(ctx *context.Context, form auth.SignInForm) { | ||||
ctx.Data["Title"] = ctx.Tr("sign_in") | ctx.Data["Title"] = ctx.Tr("sign_in") | ||||
@@ -518,6 +553,68 @@ func handleSignIn(ctx *context.Context, u *models.User, remember bool) { | |||||
handleSignInFull(ctx, u, remember, true) | handleSignInFull(ctx, u, remember, true) | ||||
} | } | ||||
func handleSignInFullNotRedirect(ctx *context.Context, u *models.User, remember bool, obeyRedirect bool) string { | |||||
log.Info("enter here.") | |||||
if remember { | |||||
days := 86400 * setting.LogInRememberDays | |||||
ctx.SetCookie(setting.CookieUserName, u.Name, days, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) | |||||
ctx.SetSuperSecureCookie(base.EncodeMD5(u.Rands+u.Passwd), | |||||
setting.CookieRememberName, u.Name, days, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) | |||||
} | |||||
_ = ctx.Session.Delete("openid_verified_uri") | |||||
_ = ctx.Session.Delete("openid_signin_remember") | |||||
_ = ctx.Session.Delete("openid_determined_email") | |||||
_ = ctx.Session.Delete("openid_determined_username") | |||||
_ = ctx.Session.Delete("twofaUid") | |||||
_ = ctx.Session.Delete("twofaRemember") | |||||
_ = ctx.Session.Delete("u2fChallenge") | |||||
_ = ctx.Session.Delete("linkAccount") | |||||
if err := ctx.Session.Set("uid", u.ID); err != nil { | |||||
log.Error("Error setting uid %d in session: %v", u.ID, err) | |||||
} | |||||
if err := ctx.Session.Set("uname", u.Name); err != nil { | |||||
log.Error("Error setting uname %s session: %v", u.Name, err) | |||||
} | |||||
if err := ctx.Session.Release(); err != nil { | |||||
log.Error("Unable to store session: %v", err) | |||||
} | |||||
// If the user does not have a locale set, we save the current one. | |||||
if len(u.Language) == 0 { | |||||
if len(ctx.GetCookie("lang")) != 0 { | |||||
u.Language = ctx.GetCookie("lang") | |||||
} else { | |||||
u.Language = ctx.Locale.Language() | |||||
} | |||||
if err := models.UpdateUserCols(u, "language"); err != nil { | |||||
log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language)) | |||||
return setting.AppSubURL + "/dashboard" | |||||
} | |||||
} else { | |||||
// Language setting of the user use the one previously set | |||||
if len(ctx.GetCookie("lang")) != 0 { | |||||
u.Language = ctx.GetCookie("lang") | |||||
} | |||||
} | |||||
ctx.SetCookie("lang", u.Language, nil, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) | |||||
// Clear whatever CSRF has right now, force to generate a new one | |||||
ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true) | |||||
// Register last login | |||||
u.SetLastLogin() | |||||
if err := models.UpdateUserCols(u, "last_login_unix"); err != nil { | |||||
ctx.ServerError("UpdateUserCols", err) | |||||
return setting.AppSubURL + "/dashboard" | |||||
} | |||||
return setting.AppSubURL + "/dashboard" | |||||
} | |||||
func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyRedirect bool) string { | func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyRedirect bool) string { | ||||
if remember { | if remember { | ||||
days := 86400 * setting.LogInRememberDays | days := 86400 * setting.LogInRememberDays | ||||
@@ -131,11 +131,6 @@ func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, err | |||||
repoMap["ID"] = fmt.Sprint(repo.ID) | repoMap["ID"] = fmt.Sprint(repo.ID) | ||||
repoMap["Name"] = repo.Name | repoMap["Name"] = repo.Name | ||||
repoMap["Alias"] = repo.Alias | repoMap["Alias"] = repo.Alias | ||||
if repo.RepoType == models.RepoCourse { | |||||
//Load creator | |||||
repo.GetCreator() | |||||
repoMap["Creator"] = repo.Creator | |||||
} | |||||
repoMap["OwnerName"] = repo.OwnerName | repoMap["OwnerName"] = repo.OwnerName | ||||
repoMap["NumStars"] = repo.NumStars | repoMap["NumStars"] = repo.NumStars | ||||
@@ -199,7 +199,7 @@ | |||||
</span> | </span> | ||||
{{else}} | {{else}} | ||||
<span | <span | ||||
style="display: flex;align-items: center;justify-content: flex-end;cursor: pointer;font-size: 12px;font-weight: normal;flex: 1;"> | |||||
style="display: flex;align-items: center;justify-content: flex-end;cursor: pointer;font-size: 12px;font-weight: normal;flex: 1;margin-left: 1.5rem;"> | |||||
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;"> | <div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;"> | ||||
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" | <svg width="1.4em" height="1.4em" viewBox="0 0 32 32" | ||||
@@ -1,38 +1,46 @@ | |||||
<style> | <style> | ||||
.ui.repository.list>.item{ | |||||
position: relative; | |||||
border: 1px solid #E1E3E6; | |||||
border-radius: 0.8rem; | |||||
margin-bottom: 1.0rem; | |||||
padding: 1.0rem !important; | |||||
} | |||||
.ui.repository.list>.item .header { | |||||
.ui.repository.list>.item { | |||||
position: relative; | |||||
border: 1px solid #E1E3E6; | |||||
border-radius: 0.8rem; | |||||
margin-bottom: 1.0rem; | |||||
padding: 1.0rem !important; | |||||
} | |||||
.ui.repository.list>.item .header { | |||||
font-size: 1.4rem !important; | font-size: 1.4rem !important; | ||||
font-weight: 200; | |||||
} | |||||
.ui.list>.item>.content{ | |||||
margin-left: 36px; | |||||
} | |||||
.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content{ | |||||
width:calc(100% - 30px); | |||||
margin-left: 0; | |||||
} | |||||
.ui.repository.list>.item::before{ | |||||
position: absolute; | |||||
left: 0; | |||||
right: 0; | |||||
content: ""; | |||||
height: 1px; | |||||
background-color: #E1E3E6; | |||||
bottom: 2.8rem; | |||||
} | |||||
.repository .ui.mini.menu{ | |||||
font-weight: 200; | |||||
} | |||||
.ui.list>.item>.content { | |||||
margin-left: 36px; | |||||
} | |||||
.ui.list .list>.item>img.image+.content, | |||||
.ui.list>.item>img.image+.content { | |||||
width: calc(100% - 34px); | |||||
margin-left: 0; | |||||
} | |||||
.ui.repository.list>.item::before { | |||||
position: absolute; | |||||
left: 0; | |||||
right: 0; | |||||
content: ""; | |||||
height: 1px; | |||||
background-color: #E1E3E6; | |||||
bottom: 2.8rem; | |||||
} | |||||
.repository .ui.mini.menu { | |||||
font-size: .6rem; | font-size: .6rem; | ||||
} | } | ||||
.repository .ui.right.compact .item{ | |||||
padding-top: 0; | |||||
padding-bottom: 0; | |||||
} | |||||
.repository .ui.right.compact .item { | |||||
padding-top: 0; | |||||
padding-bottom: 0; | |||||
} | |||||
.ui.repository.list .item .time { | .ui.repository.list .item .time { | ||||
margin-top: 1.5rem; | margin-top: 1.5rem; | ||||
} | } | ||||
@@ -40,20 +48,23 @@ | |||||
<div class="ui secondary pointing tabular top attached borderless menu navbar"> | <div class="ui secondary pointing tabular top attached borderless menu navbar"> | ||||
{{if .PageIsExplore}} | {{if .PageIsExplore}} | ||||
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot&tab={{$.TabName}}"> | |||||
<a class="{{if eq .SortType "hot"}}active{{end}} item" | |||||
href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot&tab={{$.TabName}}"> | |||||
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> | <svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-repo" /> | <use xlink:href="#octicon-repo" /> | ||||
</svg> | </svg> | ||||
{{.i18n.Tr "explore.hot_repo"}} | {{.i18n.Tr "explore.hot_repo"}} | ||||
</a> | </a> | ||||
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active&tab={{$.TabName}}"> | |||||
<a class="{{if eq .SortType "active"}}active{{end}} item" | |||||
href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active&tab={{$.TabName}}"> | |||||
<svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> | <svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-inbox" /> | <use xlink:href="#octicon-inbox" /> | ||||
</svg> | </svg> | ||||
{{.i18n.Tr "explore.active_repo"}} | {{.i18n.Tr "explore.active_repo"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=recentupdate&tab={{$.TabName}}"> | |||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" | |||||
href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=recentupdate&tab={{$.TabName}}"> | |||||
<svg class="svg octicon-organization" width="16" height="16" aria-hidden="true"> | <svg class="svg octicon-organization" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-organization" /> | <use xlink:href="#octicon-organization" /> | ||||
</svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}} | </svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}} | ||||
@@ -64,19 +75,29 @@ | |||||
<div class="ui right dropdown type jump item"> | <div class="ui right dropdown type jump item"> | ||||
<span class="text"> | <span class="text"> | ||||
{{.i18n.Tr "repo.issues.filter_sort"}} | {{.i18n.Tr "repo.issues.filter_sort"}} | ||||
<i class="dropdown icon"></i> | |||||
<i class="dropdown icon"></i> | |||||
</span> | </span> | ||||
<div class="menu"> | <div class="menu"> | ||||
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&topic={{$.Topic}}&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}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||||
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&topic={{$.Topic}}&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}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||||
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a> | |||||
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a> | |||||
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a> | |||||
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a> | |||||
<a class="{{if eq .SortType "newest"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=newest&q={{$.Keyword}}&topic={{$.Topic}}&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}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||||
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&topic={{$.Topic}}&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}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||||
<a class="{{if eq .SortType "moststars"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a> | |||||
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a> | |||||
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a> | |||||
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" | |||||
href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -84,81 +105,89 @@ | |||||
<div class="ui repository list"> | <div class="ui repository list"> | ||||
{{range .Repos}} | {{range .Repos}} | ||||
<div class="item"> | |||||
{{if .RelAvatarLink}} | |||||
<img class="ui avatar image" src="{{.RelAvatarLink}}"> | |||||
{{end}} | |||||
<div class="content"> | |||||
<div class="ui header"> | |||||
<div class="ui grid"> | |||||
<div class="ui sixteen wide mobile ten wide tablet twelve wide computer column"> | |||||
<a class="name" href="{{.Link}}"> | |||||
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.DisplayName}}</strong> | |||||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | |||||
</a> | |||||
{{if .IsPrivate}} | |||||
<span class="middle text gold">{{svg "octicon-lock" 16}}</span> | |||||
{{else if .IsFork}} | |||||
<span class="middle">{{svg "octicon-repo-forked" 16}}</span> | |||||
{{else if .IsMirror}} | |||||
<span class="middle">{{svg "octicon-repo-clone" 16}}</span> | |||||
{{else if .Owner}} | |||||
{{if .Owner.Visibility.IsPrivate}} | |||||
<span class="text gold">{{svg "octicon-lock" 16}}</span> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
<div class="ui sixteen wide mobile six wide tablet four wide computer column"> | |||||
<div class="ui mini right compact menu"> | |||||
<div class="item"> | |||||
{{if .RelAvatarLink}} | |||||
<img class="ui avatar image" style="width: 28px;height: 28px;" src="{{.RelAvatarLink}}"> | |||||
{{else}} | |||||
<img class="ui avatar image" style="width: 28px;height: 28px;" avatar="{{.Owner.Name}}"> | |||||
{{end}} | |||||
<div class="content"> | |||||
<div class="ui header"> | |||||
<div class="ui grid"> | |||||
<div class="ui sixteen wide mobile ten wide tablet twelve wide computer column"> | |||||
<a class="name" href="{{.Link}}"> | |||||
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} | |||||
<span>/</span> {{end}}{{end}}<strong>{{.DisplayName}}</strong> | |||||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | |||||
</a> | |||||
{{if .IsPrivate}} | |||||
<span class="middle text gold">{{svg "octicon-lock" 16}}</span> | |||||
{{else if .IsFork}} | |||||
<span class="middle">{{svg "octicon-repo-forked" 16}}</span> | |||||
{{else if .IsMirror}} | |||||
<span class="middle">{{svg "octicon-repo-clone" 16}}</span> | |||||
{{else if .Owner}} | |||||
{{if .Owner.Visibility.IsPrivate}} | |||||
<span class="text gold">{{svg "octicon-lock" 16}}</span> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
<div class="ui sixteen wide mobile six wide tablet four wide computer column"> | |||||
<div class="ui mini right compact menu"> | |||||
{{if eq $.SortType "hot"}} | {{if eq $.SortType "hot"}} | ||||
<a class="item"> | |||||
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> | |||||
<path fill="currentColor" d="M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z" /> | |||||
</svg> | |||||
{{.Hot}} | |||||
</a> | |||||
<a class="item"> | |||||
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> | |||||
<path fill="currentColor" | |||||
d="M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z" /> | |||||
</svg> | |||||
{{.Hot}} | |||||
</a> | |||||
{{else if eq $.SortType "active"}} | {{else if eq $.SortType "active"}} | ||||
<a class="item"> | |||||
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> | |||||
<path fill="currentColor" d="M13.13 22.19L11.5 18.36C13.07 17.78 14.54 17 15.9 16.09L13.13 22.19M5.64 12.5L1.81 10.87L7.91 8.1C7 9.46 6.22 10.93 5.64 12.5M21.61 2.39C21.61 2.39 16.66 .269 11 5.93C8.81 8.12 7.5 10.53 6.65 12.64C6.37 13.39 6.56 14.21 7.11 14.77L9.24 16.89C9.79 17.45 10.61 17.63 11.36 17.35C13.5 16.53 15.88 15.19 18.07 13C23.73 7.34 21.61 2.39 21.61 2.39M14.54 9.46C13.76 8.68 13.76 7.41 14.54 6.63S16.59 5.85 17.37 6.63C18.14 7.41 18.15 8.68 17.37 9.46C16.59 10.24 15.32 10.24 14.54 9.46M8.88 16.53L7.47 15.12L8.88 16.53M6.24 22L9.88 18.36C9.54 18.27 9.21 18.12 8.91 17.91L4.83 22H6.24M2 22H3.41L8.18 17.24L6.76 15.83L2 20.59V22M2 19.17L6.09 15.09C5.88 14.79 5.73 14.47 5.64 14.12L2 17.76V19.17Z" /> | |||||
</svg> {{.Active}} | |||||
</a> | |||||
<a class="item"> | |||||
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> | |||||
<path fill="currentColor" | |||||
d="M13.13 22.19L11.5 18.36C13.07 17.78 14.54 17 15.9 16.09L13.13 22.19M5.64 12.5L1.81 10.87L7.91 8.1C7 9.46 6.22 10.93 5.64 12.5M21.61 2.39C21.61 2.39 16.66 .269 11 5.93C8.81 8.12 7.5 10.53 6.65 12.64C6.37 13.39 6.56 14.21 7.11 14.77L9.24 16.89C9.79 17.45 10.61 17.63 11.36 17.35C13.5 16.53 15.88 15.19 18.07 13C23.73 7.34 21.61 2.39 21.61 2.39M14.54 9.46C13.76 8.68 13.76 7.41 14.54 6.63S16.59 5.85 17.37 6.63C18.14 7.41 18.15 8.68 17.37 9.46C16.59 10.24 15.32 10.24 14.54 9.46M8.88 16.53L7.47 15.12L8.88 16.53M6.24 22L9.88 18.36C9.54 18.27 9.21 18.12 8.91 17.91L4.83 22H6.24M2 22H3.41L8.18 17.24L6.76 15.83L2 20.59V22M2 19.17L6.09 15.09C5.88 14.79 5.73 14.47 5.64 14.12L2 17.76V19.17Z" /> | |||||
</svg> {{.Active}} | |||||
</a> | |||||
{{else}} | {{else}} | ||||
<a class="item"> | |||||
{{svg "octicon-eye" 16}} {{.NumWatches}} | |||||
</a> | |||||
<a class="item"> | |||||
{{svg "octicon-git-branch" 16}} {{.NumForks}} | |||||
</a> | |||||
<a class="item"> | |||||
{{svg "octicon-eye" 16}} {{.NumWatches}} | |||||
</a> | |||||
<a class="item"> | |||||
{{svg "octicon-git-branch" 16}} {{.NumForks}} | |||||
</a> | |||||
{{end}} | {{end}} | ||||
<a class="item"> | |||||
{{svg "octicon-star" 16}} {{.NumStars}} | |||||
</a> | |||||
</div> | |||||
<a class="item"> | |||||
{{svg "octicon-star" 16}} {{.NumStars}} | |||||
</a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="description"> | |||||
{{if .DescriptionHTML}}<p class="has-emoji">{{.DescriptionHTML}}</p>{{end}} | |||||
{{if .Topics }} | |||||
<div class="ui tags"> | |||||
{{range .Topics}} | |||||
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}"><div class="ui small label topic">{{.}}</div></a>{{end}} | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
<div class="description"> | |||||
{{if .DescriptionHTML}}<p class="has-emoji">{{.DescriptionHTML}}</p>{{end}} | |||||
{{if .Topics }} | |||||
<div class="ui tags"> | |||||
{{range .Topics}} | |||||
{{if ne . "" }}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}"> | |||||
<div class="ui small label topic">{{.}}</div> | |||||
</a>{{end}} | |||||
{{end}} | {{end}} | ||||
<p class="time"> | |||||
{{$.i18n.Tr "org.repo_updated"}} {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}} | |||||
{{if .PrimaryLanguage }} | |||||
<span class="text grey"><i class="color-icon" style="background-color: {{.PrimaryLanguage.Color}}"></i>{{ .PrimaryLanguage.Language }}</span> | |||||
{{end}} | |||||
</p> | |||||
</div> | </div> | ||||
{{end}} | |||||
<p class="time"> | |||||
{{$.i18n.Tr "org.repo_updated"}} {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}} | |||||
{{if .PrimaryLanguage }} | |||||
<span class="text grey"><i class="color-icon" | |||||
style="background-color: {{.PrimaryLanguage.Color}}"></i>{{ .PrimaryLanguage.Language }}</span> | |||||
{{end}} | |||||
</p> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
{{else}} | {{else}} | ||||
<div> | <div> | ||||
{{$.i18n.Tr "explore.repo_no_results"}} | {{$.i18n.Tr "explore.repo_no_results"}} | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
</div> | |||||
</div> |
@@ -1,67 +1,72 @@ | |||||
{{template "base/head" .}} | {{template "base/head" .}} | ||||
<style> | <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; | |||||
} | |||||
.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; | |||||
} | |||||
.width85{ | |||||
width: 85% !important; | |||||
margin-left: 4.5rem !important; | |||||
} | |||||
.width81{ | |||||
margin-left: 1.5rem; | |||||
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; | |||||
} | |||||
.width85 { | |||||
width: 85% !important; | |||||
margin-left: 4.5rem !important; | |||||
} | |||||
.width81 { | |||||
margin-left: 1.5rem; | |||||
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> | </style> | ||||
<!-- <div class="ui page dimmer"> | <!-- <div class="ui page dimmer"> | ||||
<div class="ui text loader">{{.i18n.Tr "loading"}}</div> | <div class="ui text loader">{{.i18n.Tr "loading"}}</div> | ||||
</div> --> | </div> --> | ||||
<div id="mask"> | <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 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> | ||||
<div class="repository"> | <div class="repository"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
@@ -82,29 +87,41 @@ | |||||
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | ||||
<div class="ui blue mini menu compact selectcloudbrain"> | <div class="ui blue mini menu compact selectcloudbrain"> | ||||
<a class="item" href="{{.RepoLink}}/cloudbrain/train-job/create"> | <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 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> | </svg> | ||||
CPU/GPU | CPU/GPU | ||||
</a> | </a> | ||||
<a class="active item" href="{{.RepoLink}}/modelarts/train-job/create"> | <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 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> | </svg> | ||||
Ascend NPU</a> | Ascend NPU</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | ||||
<input style="width: 60%;" name="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"> | |||||
<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> | <span class="tooltips" style="display: block;">{{.i18n.Tr "cloudbrain.job_name_rule"}}</span> | ||||
</div> | </div> | ||||
<div class="unite min_title inline field"> | <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> | |||||
<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> | ||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
@@ -112,43 +129,45 @@ | |||||
<div class="required unite min_title inline field"> | <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> | |||||
<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> | ||||
<div class="required unite min_title inline fields" style="width: 90%;"> | <div class="required unite min_title inline fields" style="width: 90%;"> | ||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||||
<label | |||||
style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||||
<div class="field" style="flex: 1.5;"> | <div class="field" style="flex: 1.5;"> | ||||
<select class="ui dropdown width" id="trainjob_engines" > | |||||
<select class="ui dropdown width" id="trainjob_engines"> | |||||
{{range .engines}} | {{range .engines}} | ||||
<option value="{{.Value}}">{{.Value}}</option> | |||||
<option value="{{.Value}}">{{.Value}}</option> | |||||
{{end}} | {{end}} | ||||
</select> | </select> | ||||
</div> | </div> | ||||
<div class="field" style="flex: 2;" id="engine_name"> | <div class="field" style="flex: 2;" id="engine_name"> | ||||
<select class="ui dropdown width" id="trainjob_engine_versions" style='width: 100%;' name="engine_id"> | |||||
{{range .engine_versions}} | |||||
<option name="engine_id" value="{{.ID}}">{{.Value}}</option> | |||||
{{end}} | |||||
<select class="ui dropdown width" id="trainjob_engine_versions" style='width: 100%;' | |||||
name="engine_id"> | |||||
{{range .engine_versions}} | |||||
<option name="engine_id" value="{{.ID}}">{{.Value}}</option> | |||||
{{end}} | |||||
</select> | </select> | ||||
</div> | </div> | ||||
@@ -156,41 +175,49 @@ | |||||
</div> | </div> | ||||
<div class="inline unite min_title field required"> | <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: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | |||||
{{else}} | |||||
<input style="width: 48.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/MINIST_Example" target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||||
{{if .bootFile}} | |||||
<input style="width: 48.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" | |||||
tabindex="3" autofocus required maxlength="255"> | |||||
{{else}} | |||||
<input style="width: 48.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/MINIST_Example" | |||||
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a> | |||||
</div> | </div> | ||||
{{template "custom/select_dataset_train" .}} | {{template "custom/select_dataset_train" .}} | ||||
<span class="tooltips" style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | |||||
<span class="tooltips" | |||||
style="margin-left: 11.5rem;margin-bottom: 2rem;">{{.i18n.Tr "cloudbrain.dataset_path_rule"}}</span> | |||||
<div class="inline unite min_title field"> | <div class="inline unite min_title field"> | ||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | ||||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||||
<input id="store_run_para" type="hidden" name="run_para_list"> | |||||
<span id="add_run_para" | |||||
style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i | |||||
class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | |||||
<input id="store_run_para" type="hidden" name="run_para_list"> | |||||
<div class="dynamic field" style="margin-top: 1rem;"> | <div class="dynamic field" style="margin-top: 1rem;"> | ||||
{{if ne 0 (len .params)}} | |||||
{{if ne 0 (len .params)}} | |||||
{{range $k ,$v := .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 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> | </div> | ||||
<span> | |||||
<i class="trash icon"></i> | |||||
</span> | |||||
</div> | |||||
{{end}} | |||||
{{end}} | {{end}} | ||||
{{end}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -199,13 +226,14 @@ | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | ||||
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | <select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | ||||
{{range .resource_pools}} | {{range .resource_pools}} | ||||
<option value="{{.ID}}">{{.Value}}</option> | |||||
<option value="{{.ID}}">{{.Value}}</option> | |||||
{{end}} | {{end}} | ||||
</select> | </select> | ||||
</div> | </div> | ||||
<div class="required grouped fields" style="display: none;"> | <div class="required grouped fields" style="display: none;"> | ||||
<label style="font-weight: normal;" for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||||
<label style="font-weight: normal;" | |||||
for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||||
<div class="field"> | <div class="field"> | ||||
<div class="ui grid"> | <div class="ui grid"> | ||||
<div class="column"> | <div class="column"> | ||||
@@ -224,29 +252,31 @@ | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | ||||
<select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | <select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | ||||
{{range .flavor_infos}} | {{range .flavor_infos}} | ||||
<option name="flavor" value="{{.Code}}">{{.Value}}</option> | |||||
<option name="flavor" value="{{.Code}}">{{.Value}}</option> | |||||
{{end}} | {{end}} | ||||
</select> | </select> | ||||
</div> | </div> | ||||
<div class="inline required unite min_title field"> | <div class="inline required unite min_title field"> | ||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||||
<label | |||||
style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||||
<div class="ui labeled input" style="width: 5%;"> | <div class="ui labeled input" style="width: 5%;"> | ||||
<input style="border-radius: 0;text-align: center;"type="hidden" name="work_server_number" id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1" readonly> | |||||
<div class="field" id="trainjob_work_server_num_select" name="work_server_number_select"> | |||||
<select class="ui dropdown width" style='width: 100%;' name="work_server_id"> | |||||
<option name="server_id" value="1">1</option> | |||||
<option name="server_id" value="2">2</option> | |||||
</select> | |||||
</div> | |||||
<input style="border-radius: 0;text-align: center;" type="hidden" name="work_server_number" | |||||
id="trainjob_work_server_num" tabindex="3" autofocus required maxlength="255" value="1" | |||||
readonly> | |||||
<div class="field" id="trainjob_work_server_num_select" name="work_server_number_select"> | |||||
<select class="ui dropdown width" style='width: 100%;' name="work_server_id"> | |||||
<option name="server_id" value="1">1</option> | |||||
</select> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="inline unite min_title field"> | <div class="inline unite min_title field"> | ||||
<button class="ui create_train_job green button"> | <button class="ui create_train_job green button"> | ||||
{{.i18n.Tr "repo.cloudbrain.new"}} | |||||
{{.i18n.Tr "repo.cloudbrain.new"}} | |||||
</button> | </button> | ||||
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | <a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a> | ||||
</div> | </div> | ||||
@@ -261,7 +291,7 @@ | |||||
<script> | <script> | ||||
let url_href = window.location.pathname.split('create')[0] | let url_href = window.location.pathname.split('create')[0] | ||||
$(".ui.button").attr('href',url_href) | |||||
$(".ui.button").attr('href', url_href) | |||||
$('select.dropdown') | $('select.dropdown') | ||||
.dropdown(); | .dropdown(); | ||||
@@ -283,182 +313,182 @@ | |||||
// } | // } | ||||
// }) | // }) | ||||
// 参数增加、删除、修改、保存 | // 参数增加、删除、修改、保存 | ||||
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>' | |||||
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) | $(".dynamic.field").append(value) | ||||
} | } | ||||
$('#add_run_para').click(function(){ | |||||
$('#add_run_para').click(function () { | |||||
var len = $(".dynamic.field .two.fields").length | var len = $(".dynamic.field .two.fields").length | ||||
Add_parameter(len) | Add_parameter(len) | ||||
}); | }); | ||||
$(".dynamic.field").on("click",".trash.icon", function() { | |||||
$(".dynamic.field").on("click", ".trash.icon", function () { | |||||
var index = $(this).parent().parent().index() | var index = $(this).parent().parent().index() | ||||
$(this).parent().parent().remove() | $(this).parent().parent().remove() | ||||
var len = $(".dynamic.field .two.fields").length | var len = $(".dynamic.field .two.fields").length | ||||
$(".dynamic.field .two.fields").each(function(){ | |||||
$(".dynamic.field .two.fields").each(function () { | |||||
var cur_index = $(this).index() | var cur_index = $(this).index() | ||||
$(this).attr('id', 'para' + cur_index) | $(this).attr('id', 'para' + cur_index) | ||||
}) | }) | ||||
}); | }); | ||||
$('.ui.parameter.green.button').click(function(){ | |||||
$('.ui.parameter.green.button').click(function () { | |||||
var parameters = []; | var parameters = []; | ||||
$('table tr').each(function() { | |||||
$(this).find('td:eq(1)').each(function(){ | |||||
$('table tr').each(function () { | |||||
$(this).find('td:eq(1)').each(function () { | |||||
parameters.push($(this).text()); | parameters.push($(this).text()); | ||||
}) | }) | ||||
$(this).find('input').each(function(){ | |||||
$(this).find('input').each(function () { | |||||
parameters.push($(this).text()) | parameters.push($(this).text()) | ||||
}) | }) | ||||
}); | }); | ||||
$('.ui.parameter.modal') | $('.ui.parameter.modal') | ||||
.modal('hide'); | .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; | |||||
} | |||||
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(){ | |||||
$('.ui.save.checkbox').click(function () { | |||||
$(this).checkbox({ | $(this).checkbox({ | ||||
onChange: function(){ | |||||
if ($('.ui.save.checkbox').checkbox('is checked')){ | |||||
onChange: function () { | |||||
if ($('.ui.save.checkbox').checkbox('is checked')) { | |||||
$('#save_para').removeClass("disabled") | $('#save_para').removeClass("disabled") | ||||
}else{ | |||||
} else { | |||||
$('#save_para').addClass("disabled") | $('#save_para').addClass("disabled") | ||||
} | } | ||||
} | } | ||||
}); | }); | ||||
}) | }) | ||||
$('.question.circle.icon').hover(function(){ | |||||
$('.question.circle.icon').hover(function () { | |||||
$(this).popup('show') | $(this).popup('show') | ||||
}); | }); | ||||
$(".item.active.parameter_config").click(function(){ | |||||
$(".item.active.parameter_config").click(function () { | |||||
$('.ui.parameter.modal') | $('.ui.parameter.modal') | ||||
.modal('setting', 'closable', false) | .modal('setting', 'closable', false) | ||||
.modal('show'); | .modal('show'); | ||||
}) | }) | ||||
$('.ui.deny.button').click(function(){ | |||||
$('.ui.deny.button').click(function () { | |||||
$('.ui.parameter.modal') | $('.ui.parameter.modal') | ||||
.modal('hide'); | .modal('hide'); | ||||
}) | }) | ||||
$('select.dropdown') | $('select.dropdown') | ||||
.dropdown(); | .dropdown(); | ||||
function validate(){ | |||||
function validate() { | |||||
$('.ui.form') | $('.ui.form') | ||||
.form({ | |||||
on: 'blur', | |||||
fields: { | |||||
boot_file: { | |||||
identifier : 'boot_file', | |||||
rules: [ | |||||
{ | |||||
type: 'regExp[/.+\.py$/g]', | |||||
.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]', | |||||
} | |||||
] | |||||
} | } | ||||
] | |||||
}, | }, | ||||
display_job_name:{ | |||||
identifier : 'display_job_name', | |||||
rules: [ | |||||
{ | |||||
type: 'regExp[/^[a-zA-Z0-9-_]{1,64}[a-zA-Z0-9_]$/]', | |||||
} | |||||
] | |||||
onSuccess: function () { | |||||
// $('.ui.page.dimmer').dimmer('show') | |||||
document.getElementById("mask").style.display = "block" | |||||
}, | }, | ||||
attachment:{ | |||||
identifier : 'attachment', | |||||
rules: [ | |||||
{ | |||||
type: 'empty', | |||||
} | |||||
] | |||||
}, | |||||
work_server_number: { | |||||
identifier : 'work_server_number', | |||||
rules: [ | |||||
{ | |||||
type : 'integer[1..25]', | |||||
} | |||||
] | |||||
onFailure: function (e) { | |||||
return false; | |||||
} | } | ||||
}, | |||||
onSuccess: function(){ | |||||
// $('.ui.page.dimmer').dimmer('show') | |||||
document.getElementById("mask").style.display = "block" | |||||
}, | |||||
onFailure: function(e){ | |||||
return false; | |||||
} | |||||
}) | |||||
}) | |||||
} | } | ||||
document.onreadystatechange = function() { | |||||
document.onreadystatechange = function () { | |||||
if (document.readyState === "complete") { | if (document.readyState === "complete") { | ||||
document.getElementById("mask").style.display = "none" | document.getElementById("mask").style.display = "none" | ||||
} | } | ||||
} | } | ||||
function send_run_para(){ | |||||
function send_run_para() { | |||||
var run_parameters = [] | var run_parameters = [] | ||||
var msg = {} | var msg = {} | ||||
$(".dynamic.field .two.fields").each(function(){ | |||||
$(".dynamic.field .two.fields").each(function () { | |||||
var para_name = $(this).find('input[name=shipping_first-name]').val() | var para_name = $(this).find('input[name=shipping_first-name]').val() | ||||
var para_value = $(this).find('input[name=shipping_last-name]').val() | var para_value = $(this).find('input[name=shipping_last-name]').val() | ||||
run_parameters.push({"label": para_name, "value": para_value}) | |||||
run_parameters.push({ "label": para_name, "value": para_value }) | |||||
}) | }) | ||||
msg["parameter"] = run_parameters | msg["parameter"] = run_parameters | ||||
msg = JSON.stringify(msg) | msg = JSON.stringify(msg) | ||||
$('#store_run_para').val(msg) | $('#store_run_para').val(msg) | ||||
} | } | ||||
function get_name(){ | |||||
let name1=$("#engine_name .text").text() | |||||
let name2=$("#flaver_name .text").text() | |||||
function get_name() { | |||||
let name1 = $("#engine_name .text").text() | |||||
let name2 = $("#flaver_name .text").text() | |||||
$("input#ai_engine_name").val(name1) | $("input#ai_engine_name").val(name1) | ||||
$("input#ai_flaver_name").val(name2) | $("input#ai_flaver_name").val(name2) | ||||
@@ -467,9 +497,9 @@ | |||||
$("input#trainjob_work_server_num").val(val_server_num_select) | $("input#trainjob_work_server_num").val(val_server_num_select) | ||||
} | } | ||||
$('.ui.create_train_job.green.button').click(function(e) { | |||||
$('.ui.create_train_job.green.button').click(function (e) { | |||||
get_name() | get_name() | ||||
send_run_para() | send_run_para() | ||||
validate() | validate() | ||||
}) | }) | ||||
</script> | |||||
</script> |
@@ -597,8 +597,12 @@ | |||||
</div> | </div> | ||||
<div class="required inline field" id="verionname"> | <div class="required inline field" id="verionname"> | ||||
<label>模型版本</label> | <label>模型版本</label> | ||||
<input style="width: 45%;" id="version" name="Version" value="" readonly required | |||||
maxlength="255"> | |||||
<input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> | |||||
</div> | |||||
<div class="unite min_title inline field required"> | |||||
<label>模型框架</label> | |||||
<input type="hidden" id="Engine" name="Engine" required> | |||||
<input style="width: 45%;" id="Engine_name" name="Engine_name" readonly required maxlength="255"> | |||||
</div> | </div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>模型标签</label> | <label>模型标签</label> | ||||
@@ -671,6 +675,14 @@ | |||||
$('#JobName').val(obj.DisplayJobName).addClass('model_disabled') | $('#JobName').val(obj.DisplayJobName).addClass('model_disabled') | ||||
$('input[name="JobId"]').val(obj.JobID) | $('input[name="JobId"]').val(obj.JobID) | ||||
$('input[name="VersionName"]').val(obj.VersionName).addClass('model_disabled') | $('input[name="VersionName"]').val(obj.VersionName).addClass('model_disabled') | ||||
if(obj.EngineID ==122 || obj.EngineID ==35){ | |||||
$('input[name="Engine_name"]').val("MindSpore").addClass('model_disabled'); | |||||
$('input[name="Engine"]').val(2); | |||||
} | |||||
if(obj.EngineID ==121){ | |||||
$('input[name="Engine_name"]').val("TensorFlow").addClass('model_disabled'); | |||||
$('input[name="Engine"]').val(1); | |||||
} | |||||
$('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) | $('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) | ||||
createModelName() | createModelName() | ||||
}, | }, | ||||
@@ -692,6 +704,8 @@ | |||||
type: 'POST', | type: 'POST', | ||||
data: data, | data: data, | ||||
success: function (res) { | success: function (res) { | ||||
$('input[name="Engine_name"]').val(""); | |||||
$('input[name="Engine"]').val(""); | |||||
location.href = `/${userName}/${repoPath}/modelmanage/show_model` | location.href = `/${userName}/${repoPath}/modelmanage/show_model` | ||||
$('.ui.modal.second').modal('hide') | $('.ui.modal.second').modal('hide') | ||||
}, | }, | ||||
@@ -1,9 +1,9 @@ | |||||
<!-- 头部导航栏 --> | <!-- 头部导航栏 --> | ||||
{{template "base/head" .}} | {{template "base/head" .}} | ||||
<style> | <style> | ||||
.defaulttext{ | |||||
color: rgba(0,0,0,.87) | |||||
} | |||||
.inline .ui.dropdown .text { | |||||
color: rgba(0, 0, 0, .87) !important | |||||
} | |||||
</style> | </style> | ||||
<!-- 弹窗 --> | <!-- 弹窗 --> | ||||
<div id="mask"> | <div id="mask"> | ||||
@@ -28,26 +28,29 @@ | |||||
<div class="column"></div> | <div class="column"></div> | ||||
<div class="column right aligned"> | <div class="column right aligned"> | ||||
<!-- --> | <!-- --> | ||||
<a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | |||||
<a class="ui button {{if .Permission.CanWrite $.UnitTypeModelManage}} green {{else}} disabled {{end}}" | |||||
onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{if eq $.MODEL_COUNT 0}} | {{if eq $.MODEL_COUNT 0}} | ||||
<div class="ui placeholder segment bgtask-none"> | <div class="ui placeholder segment bgtask-none"> | ||||
<div class="ui icon header bgtask-header-pic"></div> | |||||
<div class="bgtask-content-header">未创建过模型</div> | |||||
<div class="bgtask-content"> | |||||
{{if $.RepoIsEmpty}} | |||||
<div class="bgtask-content-txt">代码版本:您还没有初始化代码仓库,请先<a href="{{.RepoLink}}">创建代码版本;</a></div> | |||||
{{end}} | |||||
{{if eq $.TRAIN_COUNT 0}} | |||||
<div class="bgtask-content-txt">训练任务:您还没创建过训练任务,请先创建<a href="{{.RepoLink}}/modelarts/train-job">训练任务</a>。</div> | |||||
{{end}} | |||||
<div class="bgtask-content-txt">使用说明:可以参考启智AI协作平台<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">小白训练营课程。</a></div> | |||||
<div class="ui icon header bgtask-header-pic"></div> | |||||
<div class="bgtask-content-header">未创建过模型</div> | |||||
<div class="bgtask-content"> | |||||
{{if $.RepoIsEmpty}} | |||||
<div class="bgtask-content-txt">代码版本:您还没有初始化代码仓库,请先<a href="{{.RepoLink}}">创建代码版本;</a></div> | |||||
{{end}} | |||||
{{if eq $.TRAIN_COUNT 0}} | |||||
<div class="bgtask-content-txt">训练任务:您还没创建过训练任务,请先创建<a | |||||
href="{{.RepoLink}}/modelarts/train-job">训练任务</a>。</div> | |||||
{{end}} | |||||
<div class="bgtask-content-txt">使用说明:可以参考启智AI协作平台<a | |||||
href="https://git.openi.org.cn/zeizei/OpenI_Learning">小白训练营课程。</a></div> | |||||
</div> | |||||
<div style="display: none;"> | |||||
<div id="model_list"></div> | |||||
</div> | |||||
</div> | |||||
<div style="display: none;"> | |||||
<div id="model_list"></div> | |||||
</div> | |||||
</div> | </div> | ||||
{{else}} | {{else}} | ||||
<!-- 中下列表展示区 --> | <!-- 中下列表展示区 --> | ||||
@@ -129,212 +132,220 @@ | |||||
</div> | </div> | ||||
<div class="required inline field" id="modelname"> | <div class="required inline field" id="modelname"> | ||||
<label>模型名称</label> | <label>模型名称</label> | ||||
<input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||||
<input style="width: 45%;" id="name" name="Name" required maxlength="25" | |||||
onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||||
</div> | </div> | ||||
<div class="required inline field" id="verionname"> | <div class="required inline field" id="verionname"> | ||||
<label>模型版本</label> | <label>模型版本</label> | ||||
<input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> | <input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> | ||||
</div> | </div> | ||||
<div class="unite min_title inline field required"> | <div class="unite min_title inline field required"> | ||||
<label>模型框架</label> | <label>模型框架</label> | ||||
<div class="ui dropdown selection search width70" id="choice_Engine"> | <div class="ui dropdown selection search width70" id="choice_Engine"> | ||||
<input type="hidden" id="Engine" name="Engine" required> | |||||
<div class="default defaulttext">选择模型框架</div> | |||||
<i class="dropdown icon"></i> | |||||
<div class="menu" id="job-Engine"> | |||||
</div> | |||||
<input type="hidden" id="Engine" name="Engine" required> | |||||
<div class="default text">选择模型框架</div> | |||||
<i class="dropdown icon"></i> | |||||
<div class="menu" id="job-Engine"> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>模型标签</label> | <label>模型标签</label> | ||||
<input style="width: 83%;margin-left: 7px;" id="label" name="Label" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'> | |||||
<input style="width: 83%;margin-left: 7px;" id="label" name="Label" maxlength="255" | |||||
placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'> | |||||
</div> | </div> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label for="description">模型描述</label> | <label for="description">模型描述</label> | ||||
<textarea style="width: 83%;margin-left: 7px;" id="Description" name="Description" rows="3" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.new_place"}}' onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea> | |||||
<textarea style="width: 83%;margin-left: 7px;" id="Description" name="Description" rows="3" | |||||
maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.new_place"}}' | |||||
onchange="this.value=this.value.substring(0, 255)" | |||||
onkeydown="this.value=this.value.substring(0, 255)" | |||||
onkeyup="this.value=this.value.substring(0, 256)"></textarea> | |||||
</div> | </div> | ||||
<div class="inline field" style="margin-left: 75px;"> | <div class="inline field" style="margin-left: 75px;"> | ||||
<button id="submitId" type="button" class="ui create_train_job green button" style="position: absolute;"> | |||||
{{.i18n.Tr "repo.model.manage.sava_model"}} | |||||
<button id="submitId" type="button" class="ui create_train_job green button" | |||||
style="position: absolute;"> | |||||
{{.i18n.Tr "repo.model.manage.sava_model"}} | |||||
</button> | </button> | ||||
</div> | </div> | ||||
</form> | </form> | ||||
<div class="actions" style="display: inline-block;margin-left: 180px;"> | <div class="actions" style="display: inline-block;margin-left: 180px;"> | ||||
<button class="ui button cancel" >{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | |||||
<button class="ui button cancel">{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
</div> | |||||
{{template "base/footer" .}} | |||||
{{template "base/footer" .}} | |||||
<script> | |||||
let repolink = {{.RepoLink}} | |||||
let repoId = {{$repository}} | |||||
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; | |||||
$('input[name="_csrf"]').val(csrf) | |||||
let modelData; | |||||
function createModelName(){ | |||||
let repoName = location.pathname.split('/')[2] | |||||
let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) | |||||
$('#name').val(modelName) | |||||
$('#version').val("0.0.1") | |||||
} | |||||
function showcreate(obj){ | |||||
$('.ui.modal.second') | |||||
.modal({ | |||||
centered: false, | |||||
onShow:function(){ | |||||
$('#model_header').text("导入新模型") | |||||
$('input[name="Version"]').addClass('model_disabled') | |||||
$('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"}) | |||||
$("#job-name").empty() | |||||
createModelName() | |||||
loadTrainList() | |||||
<script> | |||||
let repolink = {{.RepoLink }} | |||||
let repoId = {{ $repository }} | |||||
const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config; | |||||
$('input[name="_csrf"]').val(csrf) | |||||
let modelData; | |||||
function createModelName() { | |||||
let repoName = location.pathname.split('/')[2] | |||||
let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) | |||||
$('#name').val(modelName) | |||||
$('#version').val("0.0.1") | |||||
} | |||||
function showcreate(obj) { | |||||
$('.ui.modal.second') | |||||
.modal({ | |||||
centered: false, | |||||
onShow: function () { | |||||
$('#model_header').text("导入新模型") | |||||
$('input[name="Version"]').addClass('model_disabled') | |||||
$('.ui.dimmer').css({ "background-color": "rgb(136, 136, 136,0.7)" }) | |||||
$("#job-name").empty() | |||||
createModelName() | |||||
loadTrainList() | |||||
}, | |||||
onHide:function(){ | |||||
document.getElementById("formId").reset(); | |||||
$('#choice_model').dropdown('clear') | |||||
$('#choice_version').dropdown('clear') | |||||
$('#choice_Engine').dropdown('clear') | |||||
$('.ui.dimmer').css({"background-color":""}) | |||||
$('.ui.error.message').text() | |||||
$('.ui.error.message').css('display','none') | |||||
}, | |||||
onHide: function () { | |||||
document.getElementById("formId").reset(); | |||||
$('#choice_model').dropdown('clear') | |||||
$('#choice_version').dropdown('clear') | |||||
$('#choice_Engine').dropdown('clear') | |||||
$('.ui.dimmer').css({ "background-color": "" }) | |||||
$('.ui.error.message').text() | |||||
$('.ui.error.message').css('display', 'none') | |||||
} | |||||
}) | |||||
.modal('show') | |||||
} | |||||
} | |||||
}) | |||||
.modal('show') | |||||
} | |||||
$(function(){ | |||||
$('#choice_model').dropdown({ | |||||
onChange:function(value){ | |||||
$(".ui.dropdown.selection.search.width70").addClass("loading") | |||||
$('#choice_version').dropdown('clear') | |||||
$("#job-version").empty() | |||||
loadTrainVersion(value) | |||||
} | |||||
}) | |||||
$(function () { | |||||
$('#choice_model').dropdown({ | |||||
onChange: function (value) { | |||||
$(".ui.dropdown.selection.search.width70").addClass("loading") | |||||
$('#choice_version').dropdown('clear') | |||||
$("#job-version").empty() | |||||
loadTrainVersion(value) | |||||
} | |||||
}) | |||||
$('#choice_version').dropdown({ | |||||
onChange:function(value){ | |||||
console.log("model version:" + value); | |||||
if(modelData != null){ | |||||
for(var i=0; i < modelData.length;i++){ | |||||
if(modelData[i].VersionName == value){ | |||||
setEngine(modelData[i]) | |||||
break; | |||||
$('#choice_version').dropdown({ | |||||
onChange: function (value) { | |||||
console.log("model version:" + value); | |||||
if (modelData != null) { | |||||
for (var i = 0; i < modelData.length; i++) { | |||||
if (modelData[i].VersionName == value) { | |||||
setEngine(modelData[i]) | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | |||||
}) | |||||
}) | }) | ||||
}) | |||||
function versionAdd(version){ | |||||
let versionArray = version.split('.') | |||||
if(versionArray[2]=='9'){ | |||||
if(versionArray[1]=='9'){ | |||||
versionArray[0] = String(Number(versionArray[1])+1) | |||||
versionArray[1] = '0' | |||||
}else{ | |||||
versionArray[1]=String(Number(versionArray[1])+1) | |||||
function versionAdd(version) { | |||||
let versionArray = version.split('.') | |||||
if (versionArray[2] == '9') { | |||||
if (versionArray[1] == '9') { | |||||
versionArray[0] = String(Number(versionArray[1]) + 1) | |||||
versionArray[1] = '0' | |||||
} else { | |||||
versionArray[1] = String(Number(versionArray[1]) + 1) | |||||
} | |||||
versionArray[2] = '0' | |||||
} else { | |||||
versionArray[2] = String(Number(versionArray[2]) + 1) | |||||
} | } | ||||
versionArray[2]='0' | |||||
}else{ | |||||
versionArray[2]=String(Number(versionArray[2])+1) | |||||
return versionArray.join('.') | |||||
} | } | ||||
return versionArray.join('.') | |||||
} | |||||
function loadTrainList(){ | |||||
$.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => { | |||||
function loadTrainList() { | |||||
$.get(`${repolink}/modelmanage/query_train_job?repoId=${repoId}`, (data) => { | |||||
const n_length = data.length | |||||
let train_html='' | |||||
for (let i=0;i<n_length;i++){ | |||||
train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].DisplayJobName}</div>` | |||||
train_html += '</div>' | |||||
} | |||||
$("#job-name").append(train_html) | |||||
$(".ui.dropdown.selection.search.width83").removeClass("loading") | |||||
$('#choice_model .default.text').text(data[0].DisplayJobName) | |||||
$('#choice_model input[name="JobId"]').val(data[0].JobID) | |||||
loadTrainVersion() | |||||
}) | |||||
} | |||||
function loadTrainVersion(value){ | |||||
let JobID = !value ?$('#choice_model input[name="JobId"]').val(): value | |||||
$.get(`${repolink}/modelmanage/query_train_job_version?JobID=${JobID}`, (data) => { | |||||
const n_length = data.length | |||||
let train_html=''; | |||||
modelData = data; | |||||
for (let i=0;i<n_length;i++){ | |||||
train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>` | |||||
train_html += '</div>' | |||||
} | |||||
if(data.length){ | |||||
$("#job-version").append(train_html) | |||||
$(".ui.dropdown.selection.search.width70").removeClass("loading") | |||||
var versionName = data[0].VersionName; | |||||
if(versionName==null || versionName==""){ | |||||
versionName="V0001"; | |||||
const n_length = data.length | |||||
if(n_length > 0){ | |||||
let train_html = '' | |||||
for (let i = 0; i < n_length; i++) { | |||||
train_html += `<div class="item" data-value="${data[i].JobID}">${data[i].DisplayJobName}</div>` | |||||
train_html += '</div>' | |||||
} | |||||
$("#job-name").append(train_html) | |||||
$(".ui.dropdown.selection.search.width83").removeClass("loading") | |||||
$('#choice_model .default.text').text(data[0].DisplayJobName) | |||||
$('#choice_model input[name="JobId"]').val(data[0].JobID) | |||||
loadTrainVersion() | |||||
}else{ | |||||
$(".ui.dropdown.selection.search.width83").removeClass("loading") | |||||
} | |||||
}) | |||||
} | |||||
function loadTrainVersion(value) { | |||||
let JobID = !value ? $('#choice_model input[name="JobId"]').val() : value | |||||
$.get(`${repolink}/modelmanage/query_train_job_version?JobID=${JobID}`, (data) => { | |||||
const n_length = data.length | |||||
let train_html = ''; | |||||
modelData = data; | |||||
for (let i = 0; i < n_length; i++) { | |||||
train_html += `<div class="item" data-value="${data[i].VersionName}">${data[i].VersionName}</div>` | |||||
train_html += '</div>' | |||||
} | |||||
if (data.length) { | |||||
$("#job-version").append(train_html) | |||||
$(".ui.dropdown.selection.search.width70").removeClass("loading") | |||||
var versionName = data[0].VersionName; | |||||
if (versionName == null || versionName == "") { | |||||
versionName = "V0001"; | |||||
} | |||||
$('#choice_version .default.text').text(versionName) | |||||
$('#choice_version input[name="VersionName"]').val(versionName) | |||||
setEngine(data[0]) | |||||
} | } | ||||
$('#choice_version .default.text').text(versionName) | |||||
$('#choice_version input[name="VersionName"]').val(versionName) | |||||
console.log("1111111111"); | |||||
setEngine(data[0]) | |||||
} | |||||
}) | |||||
} | |||||
}) | |||||
} | |||||
function setEngine(modelVersion){ | |||||
console.log("modelVersion=" + modelVersion); | |||||
$('#choice_Engine').dropdown('clear') | |||||
$("#job-Engine").empty() | |||||
if(modelVersion.EngineName != null && modelVersion.EngineName != ""){ | |||||
srcEngine = modelVersion.EngineName.split('-')[0] | |||||
srcEngine = srcEngine.trim(); | |||||
let selectedText = "Pytorch"; | |||||
let selectedValue = 0; | |||||
let itemHtml = "<option class=\"item\" data-value=\"0\">Pytorch</option>"; | |||||
if(srcEngine =='TensorFlow'){ | |||||
selectedText ="TensorFlow"; | |||||
selectedValue = 1; | |||||
itemHtml += "<option class=\"active item\" data-value=\"1\">TensorFlow</option>"; | |||||
}else{ | |||||
itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>"; | |||||
} | |||||
if(srcEngine =='MindSpore'){ | |||||
selectedText ="MindSpore"; | |||||
selectedValue = 2; | |||||
itemHtml += "<option class=\"active item\" data-value=\"2\">MindSpore</option>"; | |||||
}else{ | |||||
itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>"; | |||||
function setEngine(modelVersion) { | |||||
console.log("modelVersion=" + modelVersion); | |||||
$('#choice_Engine').dropdown('clear') | |||||
$("#job-Engine").empty() | |||||
if (modelVersion.EngineName != null && modelVersion.EngineName != "") { | |||||
srcEngine = modelVersion.EngineName.split('-')[0] | |||||
srcEngine = srcEngine.trim(); | |||||
let selectedText = "Pytorch"; | |||||
let selectedValue = 0; | |||||
let itemHtml = "<option class=\"item\" data-value=\"0\">Pytorch</option>"; | |||||
if (srcEngine == 'TensorFlow') { | |||||
selectedText = "TensorFlow"; | |||||
selectedValue = 1; | |||||
itemHtml += "<option class=\"active item\" data-value=\"1\">TensorFlow</option>"; | |||||
} else { | |||||
itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>"; | |||||
} | |||||
if (srcEngine == 'MindSpore') { | |||||
selectedText = "MindSpore"; | |||||
selectedValue = 2; | |||||
itemHtml += "<option class=\"active item\" data-value=\"2\">MindSpore</option>"; | |||||
} else { | |||||
itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>"; | |||||
} | |||||
itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>" | |||||
$('#choice_Engine .default.text').text(selectedText) | |||||
$('#choice_Engine input[name="Engine"]').val(selectedValue) | |||||
$("#job-Engine").append(itemHtml); | |||||
$("#choice_Engine").addClass('disabled') | |||||
} else { | |||||
let itemHtml = "<option class=\"active item\" data-value=\"0\">Pytorch</option>"; | |||||
itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>" | |||||
itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>" | |||||
itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>" | |||||
$('#choice_Engine .default.text').text("Pytorch"); | |||||
$('#choice_Engine input[name="Engine"]').val(0) | |||||
$("#job-Engine").append(itemHtml); | |||||
$("#choice_Engine").removeClass('disabled'); | |||||
} | } | ||||
itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>" | |||||
$('#choice_Engine .default.defaulttext').text(selectedText) | |||||
$('#choice_Engine input[name="Engine"]').val(selectedValue) | |||||
$("#job-Engine").append(itemHtml); | |||||
$("#choice_Engine").addClass('disabled') | |||||
}else{ | |||||
let itemHtml = "<option class=\"active item\" data-value=\"0\">Pytorch</option>"; | |||||
itemHtml += "<option class=\"item\" data-value=\"1\">TensorFlow</option>" | |||||
itemHtml += "<option class=\"item\" data-value=\"2\">MindSpore</option>" | |||||
itemHtml += "<option class=\"item\" data-value=\"3\">Other</option>" | |||||
$('#choice_Engine .default.defaulttext').text("Pytorch"); | |||||
$('#choice_Engine input[name="Engine"]').val(0) | |||||
$("#job-Engine").append(itemHtml); | |||||
$("#choice_Engine").removeClass('disabled'); | |||||
} | } | ||||
} | |||||
</script> | |||||
</script> |
@@ -191,7 +191,6 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -353,7 +353,7 @@ export default { | |||||
return "Pytorch"; | return "Pytorch"; | ||||
}else if(model.Engine == 1 || model.Engine == 121){ | }else if(model.Engine == 1 || model.Engine == 121){ | ||||
return "TensorFlow"; | return "TensorFlow"; | ||||
}else if(model.Engine == 2 || model.Engine == 122){ | |||||
}else if(model.Engine == 2 || model.Engine == 122 || model.Engine == 35){ | |||||
return "MindSpore"; | return "MindSpore"; | ||||
}else{ | }else{ | ||||
return "Other" | return "Other" | ||||
@@ -5,8 +5,8 @@ | |||||
<label v-else>镜像</label> | <label v-else>镜像</label> | ||||
<span v-if="benchmarkNew"> </span> | <span v-if="benchmarkNew"> </span> | ||||
<input v-if="benchmarkNew" type="text" name="image" :value="imageAddress" style="width: 48.5%;" | <input v-if="benchmarkNew" type="text" name="image" :value="imageAddress" style="width: 48.5%;" | ||||
placeholder="选择镜像或输入镜像地址"> | |||||
<input v-else type="text" name="image" :value="imageAddress" placeholder="选择镜像或输入镜像地址"> | |||||
placeholder="选择镜像或输入镜像地址" required> | |||||
<input v-else type="text" name="image" :value="imageAddress" placeholder="选择镜像或输入镜像地址" required> | |||||
<el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;">选择镜像 | <el-button type="text" @click="dialogVisible = true" icon="el-icon-plus" style="color: #0366d6;">选择镜像 | ||||
</el-button> | </el-button> | ||||
<el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%"> | <el-dialog title="选择镜像" :visible.sync="dialogVisible" width="50%"> | ||||
@@ -5093,8 +5093,9 @@ function initChartsNpu() { | |||||
data: [] | data: [] | ||||
}, | }, | ||||
grid: { | grid: { | ||||
top: '30%', | |||||
top: '35%', | |||||
bottom: '2%', | bottom: '2%', | ||||
x: '2%', | |||||
containLabel: true | containLabel: true | ||||
}, | }, | ||||
tooltip: { | tooltip: { | ||||
@@ -5130,14 +5131,16 @@ function initChartsNpu() { | |||||
series: [] | series: [] | ||||
}; | }; | ||||
const sortBy = (arr, k) => arr.concat().sort((a, b) => (a[k] > b[k] ? 1 : a[k] < b[k] ? -1 : 0)); | |||||
$('.metric_chart').click(function (e) { | $('.metric_chart').click(function (e) { | ||||
let versionName = $(this).data('version') | let versionName = $(this).data('version') | ||||
let myCharts = echarts.init(document.getElementById(`metric-${versionName}`)) | let myCharts = echarts.init(document.getElementById(`metric-${versionName}`)) | ||||
$.get(`${window.config.AppSubUrl}/api/v1/repos/${userName}/${repoPath}/modelarts/train-job/${jobID}/metric_statistics?version_name=${versionName}&statistic_type=each`, (res) => { | |||||
$.get(`${window.config.AppSubUrl}/api/v1/repos/${userName}/${repoPath}/modelarts/train-job/${jobID}/metric_statistics?version_name=${versionName}&statistic_type=each&metrics=`, (res) => { | |||||
let filterDta = res.MetricsInfo.filter((item) => { | let filterDta = res.MetricsInfo.filter((item) => { | ||||
return !(['recvBytesRate', 'diskWriteRate', 'sendBytesRate', 'diskReadRate'].includes(item.metric)) | return !(['recvBytesRate', 'diskWriteRate', 'sendBytesRate', 'diskReadRate'].includes(item.metric)) | ||||
}) | }) | ||||
filterDta = sortBy(filterDta, "metric") | |||||
let legenData = filterDta.map((item) => { | let legenData = filterDta.map((item) => { | ||||
return item.metric | return item.metric | ||||
}) | }) | ||||