diff --git a/custom/public/css/git.openi.css b/custom/public/css/git.openi.css
index 3d7e15ada..3a4eff8e4 100755
--- a/custom/public/css/git.openi.css
+++ b/custom/public/css/git.openi.css
@@ -72,9 +72,7 @@
z-index: 10;
}
.ui.secondary.c2net.segment{
- /* background: #f8faff;
- border: none;*/
- margin-bottom: 5em;
+ padding-bottom: 3em;
padding-top: 2em;
color: rgba(0,0,0,.87);
background-image: linear-gradient(to bottom left,var(--tw-gradient-stops));
@@ -176,7 +174,7 @@
}
.homeorg, .homepro, .homemodel, .i-env{
position: relative;
- padding-bottom: 5em;
+ padding-bottom: 3em;
}
.homenews::before{
content: '';
@@ -203,7 +201,7 @@
padding: 0;
}
.newslist{
- height: 300px;
+ height: 260px;
overflow: hidden;
}
@@ -278,7 +276,7 @@
z-index: 9;
}
.homeorg-list .card{
- background-image: linear-gradient(#FFF, #FFF 60%, #DFF0EF) !important;
+ /* background-image: linear-gradient(#FFF, #FFF 60%, #DFF0EF) !important; */
box-shadow: none !important;
}
.homeorg-list .card .ui.small.header .content{
@@ -299,7 +297,7 @@
background-color: #FFF;
box-shadow: 0px 5px 10px 0px rgba(105, 192, 255, .3);
border: 1px solid rgba(105, 192, 255, .4);
- min-height: 10.8em;
+ /* min-height: 10.8em; */
}
.homepro-list .ui.card>.content>.header{
line-height: 40px !important;
@@ -307,7 +305,7 @@
.homepro-list .swiper-pagination-bullet-active, .homeorg-list .swiper-pagination-bullet-active{
width: 40px;
- border-radius: 4px;
+ border-radius: 4px;
}
.i-env > div{
position: relative;
@@ -317,6 +315,15 @@
}
@media only screen and (max-width: 767px) {
+ .mobile-margin-left-20 {
+ margin-left: 20px !important;
+ }
+ .mobile-text-align-center {
+ text-align: center !important;
+ }
+ .mobile-justify-content-center {
+ justify-content: center !important;
+ }
.am-mt-30{ margin-top: 1.5rem !important;}
.ui.secondary.hometop.segment{
margin-bottom: 5.0rem;
@@ -341,7 +348,7 @@
background: #FFF;
}
.homeorg{
- padding-left: 3.5em;
+ /* padding-left: 3.5em; */
}
.homeorg-tit::after {
left: -2.3em;
diff --git a/custom/public/img/home-banner-01-en.jpg b/custom/public/img/home-banner-01-en.jpg
new file mode 100644
index 000000000..59001d4f0
Binary files /dev/null and b/custom/public/img/home-banner-01-en.jpg differ
diff --git a/custom/public/img/home-banner-01.jpg b/custom/public/img/home-banner-01.jpg
new file mode 100644
index 000000000..1aa0563c4
Binary files /dev/null and b/custom/public/img/home-banner-01.jpg differ
diff --git a/custom/public/img/home-bg-ps.png b/custom/public/img/home-bg-ps.png
new file mode 100644
index 000000000..27e6ae1a1
Binary files /dev/null and b/custom/public/img/home-bg-ps.png differ
diff --git a/custom/public/img/logo-footer.svg b/custom/public/img/logo-footer.svg
new file mode 100644
index 000000000..3be0e5b18
--- /dev/null
+++ b/custom/public/img/logo-footer.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/custom/public/img/logo-w.svg b/custom/public/img/logo-w.svg
index 867acc1e2..133f63d23 100644
--- a/custom/public/img/logo-w.svg
+++ b/custom/public/img/logo-w.svg
@@ -1 +1,45 @@
-logo-w
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/dataset.go b/models/dataset.go
index 972503641..4c1dc24db 100755
--- a/models/dataset.go
+++ b/models/dataset.go
@@ -122,22 +122,22 @@ func (datasets DatasetList) loadAttachmentAttributes(opts *SearchDatasetOptions)
for i := range datasets {
if attachment.DatasetID == datasets[i].ID {
- if !attachment.IsPrivate{
+ if !attachment.IsPrivate {
datasets[i].Attachments = append(datasets[i].Attachments, attachment)
- }else{
+ } else {
permission, ok := permissionMap[datasets[i].ID]
if !ok {
permission = false
datasets[i].Repo.GetOwner()
if !permission {
- if datasets[i].Repo.OwnerID==opts.User.ID{
+ if datasets[i].Repo.OwnerID == opts.User.ID {
permission = true
- }else{
+ } else {
isCollaborator, _ := datasets[i].Repo.IsCollaborator(opts.User.ID)
- isInRepoTeam,_:=datasets[i].Repo.IsInRepoTeam(opts.User.ID)
+ isInRepoTeam, _ := datasets[i].Repo.IsInRepoTeam(opts.User.ID)
- if isCollaborator ||isInRepoTeam {
+ if isCollaborator || isInRepoTeam {
permission = true
}
}
@@ -603,3 +603,11 @@ func UpdateDatasetCreateUser(ID int64, user *User) error {
}
return nil
}
+
+func QueryDatasetGroupByTask() ([]map[string]interface{}, error) {
+ rows, err := x.QueryInterface("SELECT count(*) as total,task FROM public.dataset where task <>'' group by task order by total desc limit 7")
+ if err != nil {
+ return nil, err
+ }
+ return rows, nil
+}
diff --git a/models/repo_activity_custom.go b/models/repo_activity_custom.go
index b6fffca0e..26b2ea14f 100644
--- a/models/repo_activity_custom.go
+++ b/models/repo_activity_custom.go
@@ -263,7 +263,11 @@ func GetAllUserKPIStats(startTime time.Time, endTime time.Time) (map[string]*git
log.Warn("get user kpi status err:"+repository.RepoPath(), err1.Error())
continue
}
-
+ // if repository.Name == "yolov5" {
+ // log.Info("repoName=" + repository.Name + " owner=" + repository.RepoPath())
+ // authorsOneRepoJson, _ := json.Marshal(authorsOneRepo)
+ // log.Info("authorsOneRepoJson=" + string(authorsOneRepoJson))
+ // }
for key, value := range authorsOneRepo {
if _, ok := authors[key]; !ok {
authors[key] = &git.UserKPIStats{
diff --git a/models/resource_specification.go b/models/resource_specification.go
index 7a11edd05..2f815818b 100644
--- a/models/resource_specification.go
+++ b/models/resource_specification.go
@@ -298,6 +298,15 @@ func ResourceSpecOffShelf(id int64) (int64, error) {
return n, err
}
+func GetResourceSpecificationByIds(ids []int64) ([]*Specification, error) {
+ r := make([]*Specification, 0)
+ err := x.In("resource_specification.id", ids).
+ Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id").
+ Find(&r)
+ return r, err
+
+}
+
func GetResourceSpecification(r *ResourceSpecification) (*ResourceSpecification, error) {
has, err := x.Get(r)
if err != nil {
diff --git a/models/user.go b/models/user.go
index b21858e37..c421455bc 100755
--- a/models/user.go
+++ b/models/user.go
@@ -346,7 +346,7 @@ func (u *User) DashboardLink() string {
if u.IsOrganization() {
return setting.AppSubURL + "/org/" + u.Name + "/dashboard/"
}
- return setting.AppSubURL + "/"
+ return setting.AppSubURL + "/dashboard"
}
// HomeLink returns the user or organization home page link.
diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go
index 8d4e57670..f8a6525d2 100755
--- a/modules/cloudbrain/cloudbrain.go
+++ b/modules/cloudbrain/cloudbrain.go
@@ -145,7 +145,7 @@ func isAdminOrImageCreater(ctx *context.Context, image *models.Image, err error)
func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {
var id = ctx.Params(":id")
- job, err := models.GetCloudbrainByID(id)
+ job, err := GetCloudBrainByIdOrJobId(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -161,7 +161,7 @@ func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {
func AdminOrJobCreaterRight(ctx *context.Context) {
var id = ctx.Params(":id")
- job, err := models.GetCloudbrainByID(id)
+ job, err := GetCloudBrainByIdOrJobId(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -177,7 +177,7 @@ func AdminOrJobCreaterRight(ctx *context.Context) {
func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
- job, err := models.GetCloudbrainByJobID(jobID)
+ job, err := GetCloudBrainByIdOrJobId(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -193,7 +193,7 @@ func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {
func AdminOrJobCreaterRightForTrain(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
- job, err := models.GetCloudbrainByJobID(jobID)
+ job, err := GetCloudBrainByIdOrJobId(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -652,3 +652,16 @@ func IsElementExist(s []string, str string) bool {
}
return false
}
+
+func GetCloudBrainByIdOrJobId(id string) (*models.Cloudbrain,error) {
+ _, err := strconv.ParseInt(id, 10, 64)
+ var job *models.Cloudbrain
+ if err != nil {
+
+ job, err = models.GetCloudbrainByJobID(id)
+ } else {
+ job, err = models.GetCloudbrainByID(id)
+
+ }
+ return job,err
+}
diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go
index dd502dfd0..b59be307b 100755
--- a/modules/modelarts/modelarts.go
+++ b/modules/modelarts/modelarts.go
@@ -1,13 +1,18 @@
package modelarts
import (
+ "encoding/base64"
"encoding/json"
"errors"
"fmt"
+ "io/ioutil"
+ "net/http"
"path"
"strconv"
"strings"
+ "code.gitea.io/gitea/modules/cloudbrain"
+
"code.gitea.io/gitea/modules/modelarts_cd"
"code.gitea.io/gitea/models"
@@ -23,7 +28,7 @@ const (
//notebook
storageTypeOBS = "obs"
autoStopDuration = 4 * 60 * 60
- autoStopDurationMs = 4 * 60 * 60 * 1000
+ AutoStopDurationMs = 4 * 60 * 60 * 1000
MORDELART_USER_IMAGE_ENGINE_ID = -1
DataSetMountPath = "/home/ma-user/work"
NotebookEnv = "Python3"
@@ -276,7 +281,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin
return nil
}
-func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error {
+func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification, bootFile string,autoStopDurationInMs int64) (string, error) {
if poolInfos == nil {
json.Unmarshal([]byte(setting.PoolInfos), &poolInfos)
}
@@ -284,14 +289,14 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
imageName, err := GetNotebookImageName(imageId)
if err != nil {
log.Error("GetNotebookImageName failed: %v", err.Error())
- return err
+ return "", err
}
createTime := timeutil.TimeStampNow()
jobResult, err := createNotebook2(models.CreateNotebook2Params{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
- Duration: autoStopDurationMs,
+ Duration: autoStopDurationInMs,
ImageID: imageId,
PoolID: poolInfos.PoolInfo[0].PoolId,
Feature: models.NotebookFeature,
@@ -316,10 +321,10 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
})
if errTemp != nil {
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error())
- return errTemp
+ return "", errTemp
}
}
- return err
+ return "", err
}
task := &models.Cloudbrain{
Status: jobResult.Status,
@@ -334,6 +339,7 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
Uuid: uuid,
ComputeResource: models.NPUResource,
Image: imageName,
+ BootFile: bootFile,
Description: description,
CreatedUnix: createTime,
UpdatedUnix: createTime,
@@ -342,12 +348,12 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc
err = models.CreateCloudbrain(task)
if err != nil {
- return err
+ return "", err
}
stringId := strconv.FormatInt(task.ID, 10)
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask)
- return nil
+ return jobResult.ID, nil
}
func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (jobId string, err error) {
@@ -907,6 +913,11 @@ func HandleNotebookInfo(task *models.Cloudbrain) error {
if task.FlavorCode == "" {
task.FlavorCode = result.Flavor
}
+
+ if oldStatus != task.Status && task.Status == string(models.ModelArtsRunning) && task.BootFile != "" {
+ uploadNoteBookFile(task, result)
+
+ }
err = models.UpdateJob(task)
if err != nil {
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err)
@@ -917,6 +928,81 @@ func HandleNotebookInfo(task *models.Cloudbrain) error {
return nil
}
+func uploadNoteBookFile(task *models.Cloudbrain, result *models.GetNotebook2Result) {
+ jupyterUrl := result.Url + "?token=" + result.Token
+
+ cookies, xsrf := getCookiesAndCsrf(jupyterUrl)
+ if xsrf == "" {
+ log.Error("browser jupyterUrl failed:%v", task.DisplayJobName)
+ } else {
+
+ codePath := setting.JobPath + task.JobName + cloudbrain.CodeMountPath
+ fileContents, err := ioutil.ReadFile(codePath + "/" + task.BootFile)
+ if err != nil {
+ log.Error("read jupyter file failed:%v", task.DisplayJobName, err)
+ }
+
+ base64Content := base64.StdEncoding.EncodeToString(fileContents)
+ client := getRestyClient()
+ uploadUrl := getJupyterBaseUrl(result.Url) + "api/contents/" + path.Base(task.BootFile)
+ res, err := client.R().
+ SetCookies(cookies).
+ SetHeader("X-XSRFToken", xsrf).
+ SetBody(map[string]interface{}{
+ "type": "file",
+ "format": "base64",
+ "name": path.Base(task.BootFile),
+ "path": path.Base(task.BootFile),
+ "content": base64Content}).
+ Put(uploadUrl)
+ if err != nil {
+ log.Error("upload jupyter file failed:%v", task.DisplayJobName, err)
+ } else if res.StatusCode() != http.StatusCreated {
+ log.Error("upload jupyter file failed:%v", task.DisplayJobName, err)
+ }
+
+ }
+
+}
+
+func getJupyterBaseUrl(url string) string {
+ jupyterUrlLength := len(url)
+ baseUrl := url[0 : jupyterUrlLength-len(path.Base(url))]
+ return baseUrl
+}
+
+func getCookiesAndCsrf(jupyterUrl string) ([]*http.Cookie, string) {
+ log.Info("jupyter url:"+jupyterUrl)
+ var cookies []*http.Cookie
+ const retryTimes = 10
+ for i := 0; i < retryTimes; i++ {
+ res, err := http.Get(jupyterUrl)
+ if err != nil {
+ log.Error("browser jupyterUrl failed.",err)
+ if i==retryTimes-1{
+ return cookies, ""
+ }
+
+ } else {
+ cookies = res.Cookies()
+ xsrf := ""
+ for _, cookie := range cookies {
+ if cookie.Name == "_xsrf" {
+ xsrf = cookie.Value
+ break
+ }
+
+ }
+ if xsrf != "" {
+ return cookies, xsrf
+ }
+
+ }
+ }
+ return cookies, ""
+
+}
+
func SyncTempStatusJob() {
jobs, err := models.GetCloudBrainTempJobs()
if err != nil {
diff --git a/modules/modelarts/resty.go b/modules/modelarts/resty.go
index c38300606..3ccba9011 100755
--- a/modules/modelarts/resty.go
+++ b/modules/modelarts/resty.go
@@ -280,7 +280,7 @@ sendjob:
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetResult(&result).
- Post(HOST + "/v1/" + setting.ProjectID + urlNotebook2 + "/" + jobID + "/" + param.Action + "?duration=" + strconv.Itoa(autoStopDurationMs))
+ Post(HOST + "/v1/" + setting.ProjectID + urlNotebook2 + "/" + jobID + "/" + param.Action + "?duration=" + strconv.Itoa(AutoStopDurationMs))
if err != nil {
return &result, fmt.Errorf("resty ManageNotebook2: %v", err)
diff --git a/modules/modelarts_cd/modelarts.go b/modules/modelarts_cd/modelarts.go
index 330b048ca..93032fa89 100755
--- a/modules/modelarts_cd/modelarts.go
+++ b/modules/modelarts_cd/modelarts.go
@@ -88,18 +88,18 @@ type Parameters struct {
} `json:"parameter"`
}
-func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error {
+func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification, bootFile string,autoStopDurationInMs int64) (string, error) {
imageName, err := GetNotebookImageName(imageId)
if err != nil {
log.Error("GetNotebookImageName failed: %v", err.Error())
- return err
+ return "", err
}
createTime := timeutil.TimeStampNow()
jobResult, err := createNotebook(models.CreateNotebookWithoutPoolParams{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
- Duration: autoStopDurationMs,
+ Duration: autoStopDurationInMs,
ImageID: imageId,
Feature: models.NotebookFeature,
Volume: models.VolumeReq{
@@ -123,10 +123,10 @@ func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, descr
})
if errTemp != nil {
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error())
- return errTemp
+ return "", errTemp
}
}
- return err
+ return "", err
}
task := &models.Cloudbrain{
Status: jobResult.Status,
@@ -145,16 +145,17 @@ func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, descr
CreatedUnix: createTime,
UpdatedUnix: createTime,
Spec: spec,
+ BootFile: bootFile,
}
err = models.CreateCloudbrain(task)
if err != nil {
- return err
+ return "", err
}
stringId := strconv.FormatInt(task.ID, 10)
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask)
- return nil
+ return jobResult.ID, nil
}
func GetNotebookImageName(imageId string) (string, error) {
@@ -175,41 +176,3 @@ func GetNotebookImageName(imageId string) (string, error) {
return imageName, nil
}
-
-/*
-func HandleNotebookInfo(task *models.Cloudbrain) error {
-
- result, err := GetNotebook(task.JobID)
- if err != nil {
- log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err)
- return err
- }
-
- if result != nil {
- oldStatus := task.Status
- task.Status = result.Status
- if task.StartTime == 0 && result.Lease.UpdateTime > 0 {
- task.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000)
- }
- if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) {
- task.EndTime = timeutil.TimeStampNow()
- }
- task.CorrectCreateUnix()
- task.ComputeAndSetDuration()
- if oldStatus != task.Status {
- notification.NotifyChangeCloudbrainStatus(task, oldStatus)
- }
- if task.FlavorCode == "" {
- task.FlavorCode = result.Flavor
- }
- err = models.UpdateJob(task)
- if err != nil {
- log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err)
- return err
- }
- }
-
- return nil
-}
-
-*/
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index e237d5a8a..374e6a99d 100755
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -715,6 +715,21 @@ var (
TeamName string
}{}
+ FileNoteBook = struct {
+ ProjectName string
+ ImageGPU string
+ SpecIdGPU int64
+ SpecIdCPU int64
+ ImageIdNPU string
+ SpecIdNPU int64
+ ImageIdNPUCD string
+ SpecIdNPUCD int64
+ ImageCPUDescription string
+ ImageGPUDescription string
+ ImageNPUDescription string
+ ImageNPUCDDescription string
+ }{}
+
ModelConvert = struct {
GPU_PYTORCH_IMAGE string
GpuQueue string
@@ -1580,6 +1595,20 @@ func NewContext() {
Course.OrgName = sec.Key("org_name").MustString("")
Course.TeamName = sec.Key("team_name").MustString("")
+ sec = Cfg.Section("file_notebook")
+ FileNoteBook.ProjectName = sec.Key("project_name").MustString("openi-notebook")
+ FileNoteBook.ImageIdNPU = sec.Key("imageid_npu").MustString("")
+ FileNoteBook.ImageGPU = sec.Key("image_gpu").MustString("")
+ FileNoteBook.SpecIdCPU = sec.Key("specid_cpu").MustInt64(-1)
+ FileNoteBook.SpecIdGPU = sec.Key("specid_gpu").MustInt64(-1)
+ FileNoteBook.SpecIdNPU = sec.Key("specid_npu").MustInt64(-1)
+ FileNoteBook.ImageIdNPUCD = sec.Key("imageid_npu_cd").MustString("")
+ FileNoteBook.SpecIdNPUCD = sec.Key("specid_npu_cd").MustInt64(-1)
+ FileNoteBook.ImageCPUDescription = sec.Key("image_cpu_desc").MustString("")
+ FileNoteBook.ImageGPUDescription = sec.Key("image_gpu_desc").MustString("")
+ FileNoteBook.ImageNPUDescription = sec.Key("image_npu_desc").MustString("")
+ FileNoteBook.ImageNPUCDDescription = sec.Key("image_npu_cd_desc").MustString("")
+
getGrampusConfig()
getModelartsCDConfig()
getModelConvertConfig()
diff --git a/modules/structs/cloudbrain.go b/modules/structs/cloudbrain.go
index 866c85dad..9ea5601c9 100644
--- a/modules/structs/cloudbrain.go
+++ b/modules/structs/cloudbrain.go
@@ -41,6 +41,14 @@ type CreateTrainJobOption struct {
SpecId int64 `json:"spec_id" binding:"Required"`
}
+type CreateFileNotebookJobOption struct {
+ Type int `json:"type"` //0 CPU 1 GPU 2 NPU
+ File string `json:"file" binding:"Required"`
+ BranchName string `json:"branch_name" binding:"Required"`
+ OwnerName string `json:"owner_name" binding:"Required"`
+ ProjectName string `json:"project_name" binding:"Required"`
+}
+
type Cloudbrain struct {
ID int64 `json:"id"`
JobID string `json:"job_id"`
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 3e424454b..c314127f1 100755
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -151,6 +151,9 @@ func NewFuncMap() []template.FuncMap {
"EscapePound": func(str string) string {
return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
},
+ "IpynbBool":func(str string) bool{
+ return strings.Contains(str, ".ipynb")
+ },
"nl2br": func(text string) template.HTML {
return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", " ", -1))
},
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 908bd37b1..b6c9ee404 100755
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -24,6 +24,7 @@ enable_javascript = This website works better with JavaScript.
toc = Table of Contents
return=Back OpenI
calculation_points = Calculation Points
+notice_announcement = Notice Announcement
username = Username
email = Email Address
@@ -236,7 +237,7 @@ page_title=Explore Better AI
page_small_title=OpenI AI Development Cooperation Platform
page_description=The one-stop collaborative development environment for AI field provides AI development pipeline integrating code development, data management, model debugging, reasoning and evaluation
page_use=Use Now
-page_only_dynamic=Only show the dynamics of open source projects
+page_only_dynamic=The dynamics of open source projects
page_recommend_org=Recommended Organizations
page_recommend_org_desc=These excellent organizations are using the OpenI AI Collaboration Platform for collaborative development of projects. To show your organization here,
page_recommend_org_commit=Click here to submit.
@@ -283,6 +284,7 @@ search_ge=
wecome_AI_plt = Welcome to OpenI AI Collaboration Platform!
explore_AI = Explore better AI, come here to find more interesting
datasets = Datasets
+datasets_descr = Open source dataset base, seamlessly integrated with your project. View all
repositories = Repositories
use_plt__fuction = To use the AI collaboration functions provided by this platform, such as: hosting code, sharing data, debugging algorithms or training models, start with
provide_resoure = Computing resources of CPU/GPU/NPU are provided freely for various types of AI tasks.
@@ -290,6 +292,12 @@ activity = Activity
no_events = There are no events related
or_t = or
powerdby=Powered_by Pengcheng CloudBrain、China Computing NET(C²NET)、
+experience_officer=Experience Officer
+openi_experience_officer_plan=OpenI AI experience officer growth plan
+more_benefits=, More benefits
+org_see=See
+more_notice=More notices
+vedio_detail=Video details
[explore]
repos = Repositories
@@ -1012,6 +1020,8 @@ readme = README
readme_helper = Select a README file template.
auto_init = Initialize Repository (Adds .gitignore, License and README)
create_repo = Create Repository
+failed_to_create_repo=Failed to create repository, please try again later.
+failed_to_create_notebook_repo=Failed to create %s repository, please check whether you have the same name project, if yes please update or delete it first.
create_course = Publish Course
failed_to_create_course=Failed to publish course, please try again later.
default_branch = Default Branch
@@ -1046,6 +1056,10 @@ model_experience = Model Experience
model_noright=You have no right to do the operation.
model_rename=Duplicate model name, please modify model name.
+notebook_file_not_exist=Notebook file does not exist.
+notebook_select_wrong=Please select a Notebook(.ipynb) file first.
+notebook_file_no_right=You have no right to access the Notebook(.ipynb) file.
+
date=Date
repo_add=Project Increment
repo_total=Project Total
@@ -1225,7 +1239,7 @@ cloudbrain.benchmark.evaluate_test=Test Script
cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"Target detection","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"Target re-identification","second":[{"id":1,"value":"Vehicle re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"Image-based person re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"Multi-target tracking","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]}
cloudbrain.morethanonejob=You already have a running or waiting task, create it after that task is over.
cloudbrain.morethanonejob1=You have created an equivalent task that is waiting or running, please wait for the task to finish before creating it.
-cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in Home > Cloudbrain Task .
+cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in Home > Cloudbrain Task .
modelarts.infer_job_model = Model
modelarts.infer_job_model_file = Model File
@@ -1445,6 +1459,7 @@ blame = Blame
normal_view = Normal View
line = line
lines = lines
+notebook_open = Open in Notebook
editor.new_file = New File
editor.upload_file = Upload File
@@ -3198,6 +3213,9 @@ foot.copyright= Copyright: New Generation Artificial Intelligence Open Source Op
Platform_Tutorial = Tutorial
foot.advice_feedback = Feedback
resource_description = Resource Note
+foot.openi_subscription_number = OpenI subscription number
+foot.user_communication_group = User communication group
+
[cloudbrain]
all_resource_cluster=All Cluster
all_ai_center=All Computing NET
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 889a9298a..495063a1f 100755
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -24,6 +24,7 @@ enable_javascript=使用 JavaScript能使本网站更好的工作。
toc=目录
return=返回OpenI
calculation_points=算力积分
+notice_announcement=通知公告
username=用户名
email=电子邮件地址
@@ -238,7 +239,7 @@ page_title=探索更好的AI
page_small_title=启智AI协作平台
page_description=面向AI领域的一站式协同开发环境,提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线
page_use=立即使用
-page_only_dynamic=仅展示开源项目动态
+page_only_dynamic=社区开源项目动态
page_recommend_org=推荐组织
page_recommend_org_desc=这些优秀的组织正在使用启智AI开发协作平台;你的组织也想展示到这里,
page_recommend_org_commit=点此提交
@@ -285,6 +286,7 @@ search_ge=个
wecome_AI_plt=欢迎来到启智AI协作平台!
explore_AI = 探索更好的AI,来这里发现更有意思的
datasets = 数据集
+datasets_descr=开源数据集大本营,同你的项目无缝集成。查看所有
repositories = 项目
use_plt__fuction = 使用本平台提供的AI协作功能,如:托管代码、共享数据、调试算法或训练模型,请先
provide_resoure = 平台目前提供CPU、GPU、NPU的普惠算力资源,可进行多种类型的AI任务。
@@ -293,7 +295,12 @@ activity = 活动
no_events = 还没有与您相关的活动
or_t = 或
powerdby=Powered_by 鹏城实验室云脑、中国算力网(C²NET)、
-
+experience_officer=体验官
+openi_experience_officer_plan=启智社区体验官成长计划
+more_benefits=,超多福利大放送
+org_see=。查看
+more_notice=更多通知
+vedio_detail=详细介绍视频
[explore]
repos=项目
@@ -1018,6 +1025,8 @@ readme=自述
readme_helper=选择自述文件模板。
auto_init=初始化存储库 (添加. gitignore、许可证和自述文件)
create_repo=创建项目
+failed_to_create_repo=创建项目失败,请稍后再试。
+failed_to_create_notebook_repo=创建项目%s失败,请检查您是否有同名的项目,如果有请先手工修改或删除后重试。
create_course=发布课程
failed_to_create_course=发布课程失败,请稍后再试。
default_branch=默认分支
@@ -1046,6 +1055,9 @@ model_experience = 模型体验
model_noright=您没有操作权限。
model_rename=模型名称重复,请修改模型名称
+notebook_file_not_exist=Notebook文件不存在。
+notebook_select_wrong=请先选择Notebook(.ipynb)文件。
+notebook_file_no_right=您没有这个Notebook文件的读权限。
date=日期
repo_add=新增项目
@@ -1464,6 +1476,8 @@ normal_view=普通视图
line=行
lines=行
+notebook_open = 在Notebook中打开
+
editor.new_file=新建文件
editor.upload_file=上传文件
editor.edit_file=编辑文件
@@ -3216,6 +3230,8 @@ foot.copyright= 版权所有:新一代人工智能开源开放平台(OpenI
Platform_Tutorial=新手指引
foot.advice_feedback = 意见反馈
resource_description = 资源说明
+foot.openi_subscription_number = 启智社区订阅号
+foot.user_communication_group = 用户交流群
[cloudbrain]
all_resource_cluster=全部集群
diff --git a/public/home/home.js b/public/home/home.js
index 853c3ef23..43eab17e0 100755
--- a/public/home/home.js
+++ b/public/home/home.js
@@ -9,16 +9,20 @@ if(isEmpty(token)){
var swiperNewMessage = new Swiper(".newslist", {
direction: "vertical",
- slidesPerView: 9,
+ slidesPerView: 6,
loop: true,
+ spaceBetween: 8,
autoplay: {
delay: 2500,
disableOnInteraction: false,
},
});
-var swiperEvent = new Swiper(".event-list", {
- slidesPerView: 3,
- spaceBetween: 30,
+
+var swiperRepo = new Swiper(".homepro-list", {
+ slidesPerView: 1,
+ // slidesPerColumn: 2,
+ // slidesPerColumnFill:'row',
+ spaceBetween: 20,
pagination: {
el: ".swiper-pagination",
clickable: true,
@@ -27,49 +31,130 @@ var swiperEvent = new Swiper(".event-list", {
delay: 2500,
disableOnInteraction: false,
},
+ breakpoints: {
+ 768: {
+ slidesPerView: 2,
+ },
+ 1024: {
+ slidesPerView: 2,
+ },
+ 1200: {
+ slidesPerView: 3,
+ },
+ 1440: {
+ slidesPerView: 3,
+ },
+ 1840: {
+ slidesPerView: 3,
+ },
+ 1920: {
+ slidesPerView: 3,
+ },
+ },
});
-var swiperRepo = new Swiper(".homepro-list", {
+
+var swiperOrg = new Swiper(".homeorg-list", {
slidesPerView: 1,
slidesPerColumn: 2,
slidesPerColumnFill:'row',
- spaceBetween: 30,
+ spaceBetween: 25,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
autoplay: {
- delay: 2500,
+ delay: 4500,
disableOnInteraction: false,
},
breakpoints: {
768: {
- slidesPerView: 2,
+ slidesPerView: 3,
+ slidesPerColumn: 2,
},
1024: {
slidesPerView: 3,
+ slidesPerColumn: 2,
+ },
+ 1200: {
+ slidesPerView: 4,
+ slidesPerColumn: 2,
+ },
+ 1440: {
+ slidesPerView: 4,
+ slidesPerColumn: 2,
+ },
+ 1840: {
+ slidesPerView: 4,
+ slidesPerColumn: 2,
+ },
+ 1920: {
+ slidesPerView: 4,
+ slidesPerColumn: 2,
},
},
});
-var swiperOrg = new Swiper(".homeorg-list", {
+var swiperUserExp = new Swiper(".home-user-exp-list", {
slidesPerView: 1,
- slidesPerColumn: 4,
+ spaceBetween: 0,
+ navigation: {
+ nextEl: '.homeuserexp .swiper-prev',
+ prevEl: '.homeuserexp .swiper-next',
+ },
+ autoplay: {
+ delay: 2500,
+ disableOnInteraction: false,
+ },
+ breakpoints: {
+ 768: {
+ slidesPerView: 2,
+ },
+ 1200: {
+ slidesPerView: 3,
+ },
+ 1440: {
+ slidesPerView: 4,
+ },
+ 1840: {
+ slidesPerView: 4,
+ },
+ 1920: {
+ slidesPerView: 5,
+ },
+ },
+});
+
+var swiperDataset = new Swiper(".home-dataset-list", {
+ slidesPerView: 2,
+ slidesPerColumn: 1,
slidesPerColumnFill:'row',
- spaceBetween: 15,
+ spaceBetween: 30,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
autoplay: {
- delay: 4500,
+ delay: 2500,
disableOnInteraction: false,
},
breakpoints: {
+ 676: {
+ slidesPerView: 3,
+ },
768: {
- slidesPerView: 2,
+ slidesPerView: 4,
},
- 1024: {
- slidesPerView: 3,
+ 1320: {
+ slidesPerView: 5,
+ },
+ 1520: {
+ slidesPerView: 6,
+ },
+ 1720: {
+ slidesPerView: 7,
+ },
+ 1920: {
+ slidesPerView: 7,
},
},
});
@@ -85,7 +170,7 @@ document.onreadystatechange = function () {
if(document.readyState != "complete"){
return;
}
- console.log("Start to open WebSocket." + document.readyState);
+ console.log("Start to open WebSocket." + document.readyState);
queryRecommendData();
var output = document.getElementById("newmessage");
@@ -101,6 +186,7 @@ document.onreadystatechange = function () {
};
socket.onmessage = function (e) {
+ if (!output) return;
var data =JSON.parse(e.data)
var html = "";
if (data != null){
@@ -177,18 +263,17 @@ document.onreadystatechange = function () {
var time = getTime(record.CreatedUnix,currentTime);
html += " " + time;
}
- html += "";
+ html += "";
html += "";
}
}
output.innerHTML = html;
+ $('#homenews p').show();
swiperNewMessage.updateSlides();
swiperNewMessage.updateProgress();
};
}
-
-
function getTaskLink(record){
var re = getRepoLink(record);
if(record.OpType == 24){
@@ -223,7 +308,7 @@ function getMsg(record){
}else{
console.log("act user is null.");
}
- html += " "
+ html += "
"
html += "
"
html += "
" + name + " "
return html;
@@ -236,6 +321,7 @@ function getRepotext(record){
return record.Repo.OwnerName + "/" + record.Repo.Name;
}
}
+
function getRepoLink(record){
return encodeURI(record.Repo.OwnerName + "/" + record.Repo.Name);
@@ -437,10 +523,6 @@ function getAction(opType,isZh){
}
}
-
-
-
-
function queryRecommendData(){
$.ajax({
type:"GET",
@@ -453,7 +535,10 @@ function queryRecommendData(){
success:function(json){
displayOrg(json.org);
displayRepo(json.repo);
- displayActivity(json.image);
+ displayActivity(json.activity);
+ displayDataset(json.dataset);
+ displayUserExp(json.user_experience);
+ LetterAvatar && LetterAvatar.transform();
},
error:function(response) {
}
@@ -463,49 +548,99 @@ function queryRecommendData(){
function displayActivity(json){
var activityDiv = document.getElementById("recommendactivity");
+ if (!activityDiv) return;
var html = "";
if (json != null && json.length > 0){
for(var i = 0; i < json.length;i++){
- var record = json[i]
- html += "
";
- html += "
";
- html += " "
+ var record = json[i];
+ var name = isZh ? (record["name"] || '') : (record["name_en"] || record["name"]);
+ html += "";
}
+ var swiperEvent = new Swiper(".event-list", {
+ slidesPerView: 1,
+ spaceBetween: 30,
+ // pagination: {
+ // el: ".swiper-pagination",
+ // clickable: true,
+ // },
+ autoplay: {
+ delay: 2500,
+ disableOnInteraction: false,
+ },
+ breakpoints: {
+ 768: {
+ slidesPerView: Math.min(2, json.length),
+ },
+ 1024: {
+ slidesPerView: Math.min(3, json.length),
+ },
+ 1200: {
+ slidesPerView: Math.min(3, json.length),
+ },
+ 1440: {
+ slidesPerView: Math.min(4, json.length),
+ },
+ 1840: {
+ slidesPerView: Math.min(4, json.length),
+ },
+ 1920: {
+ slidesPerView: Math.min(4, json.length),
+ },
+ },
+ });
+ activityDiv.innerHTML = html;
+ swiperEvent.updateSlides();
+ swiperEvent.updateProgress();
}
- activityDiv.innerHTML = html;
- swiperEvent.updateSlides();
- swiperEvent.updateProgress();
}
function displayRepo(json){
var orgRepo = document.getElementById("recommendrepo");
var html = "";
if (json != null && json.length > 0){
- for(var i = 0; i < json.length;i++){
- var record = json[i]
- html += "";
- html += "
";
- html += "
";
- html += "
";
- html += " " + record["NumStars"] + " " + record["NumForks"];
- html += " ";
- html += "
";
- html += " ";
- html += "
" + record["Description"] + "
";
- html += "
"
- if(record["Topics"] != null){
- for(var j = 0; j < record["Topics"].length; j++){
- topic = record["Topics"][j];
- url = "/explore/repos?q=" + (topic) + "&topic="
- html += "
" + topic + " ";
- }
+ var repoMap = {};
+ for (var i = 0, iLen = json.length; i < iLen; i++) {
+ var repo = json[i];
+ var labelSearch = repo.Label;
+ var label = isZh ? repo.Label : repo.Label_en;
+ if (repoMap[label]) {
+ repoMap[label].push(repo);
+ } else {
+ repoMap[label] = [repo];
}
- html += "
";
- html += "
";
- html += "
";
- html += "
";
+ }
+
+ for (var label in repoMap) {
+ var repos = repoMap[label];
+ html += ``;
+ for (var i = 0, iLen = repos.length; i < iLen; i++) {
+ if (i >= 4) break;
+ var repo = repos[i];
+ //
${repo["NumStars"]}
${repo["NumForks"]}
+ html += `
+
+ ${repo["Avatar"] ? `
` : `
`}
+
+
${repo["Description"]}
+ `;
+ // if (repo["Topics"] != null) {
+ // for(var j = 0; j < repo["Topics"].length; j++){
+ // var topic = repo["Topics"][j];
+ // var url = "/explore/repos?q=" + (topic) + "&topic="
+ // html += `
${topic} `;
+ // }
+ // }
+ html += `
+
+
`;
+ }
+ html += '
'
}
}
orgRepo.innerHTML = html;
@@ -513,7 +648,6 @@ function displayRepo(json){
swiperRepo.updateProgress();
}
-
function getRepoOrOrg(key,isZhLang,numbers=1){
if(numbers > 1){
key+="1";
@@ -537,7 +671,7 @@ function displayOrg(json){
html += " ";
html += " ";
html += "
" + record["Name"] + " " + record["FullName"];
- html += "
" + record["NumRepos"] +" " + getRepoOrOrg(1,isZh,record["NumRepos"]) + " ・ " + record["NumMembers"] +" " + getRepoOrOrg(2,isZh,record["NumMembers"]) + " ・ " + record["NumTeams"] + " " + getRepoOrOrg(3,isZh,record["NumTeams"]) + "
";
+ html += "
" + record["NumRepos"] +" " + getRepoOrOrg(1,isZh,record["NumRepos"]) + " ・ " + record["NumMembers"] +" " + getRepoOrOrg(2,isZh,record["NumMembers"]) + " ・ " + record["NumTeams"] + " " + getRepoOrOrg(3,isZh,record["NumTeams"]) + "
";
html += "
";
html += " ";
html += "
";
@@ -548,3 +682,173 @@ function displayOrg(json){
orgDiv.innerHTML = html;
swiperOrg.updateSlides();
}
+
+function displayDataset(data) {
+ var homeDatasetEl = document.getElementById("home_dataset");
+ if (!homeDatasetEl) return;
+ var html = '';
+ var svgStrMap = {
+ '0': '
',
+ '1': '
',
+ '2': '
',
+ '3': '
',
+ '4': '
',
+ '5': '
',
+ '6': '
',
+ }
+ for (var i = 0, iLen = data.length; i < iLen; i++) {
+ var dataI = data[i];
+ html += `
`
+ }
+ homeDatasetEl.innerHTML = html;
+ swiperDataset.updateSlides();
+ swiperDataset.updateProgress();
+}
+
+function displayUserExp(data) {
+ var homeUserExpEl = document.getElementById("home_user-exp");
+ if (!homeUserExpEl) return;
+ var html = '';
+ for (var i = 0, iLen = data.length; i < iLen; i++) {
+ var dataI = data[i];
+ html += `
+
+
+
${dataI.fullname || dataI.name}
+
+
+
`
+ }
+ homeUserExpEl.innerHTML = html;
+ swiperUserExp.updateSlides();
+ swiperUserExp.updateProgress();
+}
+
+function getNotice() {
+ $.ajax({
+ type:"GET",
+ url:"/dashboard/invitation",
+ headers: { authorization:token, },
+ dataType:"json",
+ data: {
+ filename: 'notice/notice.json',
+ },
+ success:function(json){
+ if (json) {
+ try {
+ var noticeList = JSON.parse(json).Notices || [];
+ var noticeEls = $('._hm-recommend-info-area-1 a._hm-notice');
+ for (var i = 0, iLen = noticeEls.length; i < iLen; i++) {
+ var noticeEl = noticeEls.eq(i);
+ var noticeObj = noticeList[i];
+ if (noticeObj) {
+ var title = isZh ? noticeObj.Title : (noticeObj.Title_en || noticeObj.Title);
+ noticeEl.attr('href', noticeObj.Link);
+ noticeEl.find('span').text(title).attr('title', title);
+ noticeEl.show();
+ } else {
+ noticeEl.hide();
+ }
+ }
+ } catch (e) {
+ console.info(e);
+ }
+ }
+ },
+ error:function(response) {
+ }
+ });
+}
+
+function getRecommendModule() {
+ $.ajax({
+ type:"GET",
+ url:"/dashboard/invitation",
+ headers: { authorization:token, },
+ dataType:"json",
+ data: {
+ filename: 'home/newfunction',
+ },
+ success:function(json){
+ if (json) {
+ try {
+ var recommendModuleList = JSON.parse(json) || [];
+ var recommendModuleEls = $('._hm-recommend-info-area a._hm-link');
+ for (var i = 0, iLen = recommendModuleEls.length; i < iLen; i++) {
+ var recommendModuleEl = recommendModuleEls.eq(i);
+ var recommendModuleObj = recommendModuleList[i];
+ if (recommendModuleObj) {
+ recommendModuleEl.attr('href', recommendModuleObj.image_link);
+ recommendModuleEl.text(isZh ? recommendModuleObj.name : (recommendModuleObj.name_en || recommendModuleObj.name));
+ } else {
+ }
+ }
+ } catch (e) {
+ console.info(e);
+ }
+ }
+ },
+ error:function(response) {
+ }
+ });
+}
+
+function initHomeTopBanner() {
+ var homeSlideTimer = null;
+ var homeSlideDuration = 8000;
+ function homeSlide(direction) {
+ var slidePages = $('._hm-pg-c ._hm-pg');
+ var currentPage = slidePages.filter('._hm-pg-show');
+ var currentIndex = currentPage.index();
+ var next = direction == 'left' ? currentIndex - 1 : currentIndex + 1;
+ if (next < 0) next = slidePages.length - 1;
+ if (next == slidePages.length) next = 0;
+ slidePages.removeClass('_hm-pg-show');
+ slidePages.eq(next).addClass('_hm-pg-show');
+ }
+
+ function startSlide() {
+ homeSlideTimer && clearTimeout(homeSlideTimer);
+ homeSlideTimer = setTimeout(function() {
+ homeSlide('right');
+ startSlide();
+ }, homeSlideDuration);
+ }
+
+ function stopSlide() {
+ homeSlideTimer && clearTimeout(homeSlideTimer);
+ }
+
+ $('._hm-slide-btn').on('click', function () {
+ if ($(this).hasClass('_hm-slide-btn-left')) {
+ homeSlide('left');
+ } else {
+ homeSlide('right');
+ }
+ startSlide();
+ });
+ $('._hm-pg #homenews').on('mouseenter', function() {
+ stopSlide();
+ }).on('mouseleave', function() {
+ startSlide();
+ });
+ setTimeout(function() { startSlide(); }, 500);
+}
+
+initHomeTopBanner();
+getNotice();
+getRecommendModule();
diff --git a/public/img/search.svg b/public/img/search.svg
index ec91b07dd..a4d965f9a 100644
--- a/public/img/search.svg
+++ b/public/img/search.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 2afbb9b7d..14badfdb4 100755
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -737,6 +737,12 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/my_favorite", repo.MyFavoriteDatasetMultiple)
}, reqToken(), repoAssignment())
+ m.Group("/file_notebook", func() {
+ m.Get("", reqToken(), repo.GetFileNoteBookInfo)
+ m.Post("/create", reqToken(), reqWeChat(), bind(api.CreateFileNotebookJobOption{}), repo.CreateFileNoteBook)
+
+ })
+
m.Group("/repos", func() {
m.Get("/search", repo.Search)
diff --git a/routers/api/v1/repo/cloudbrain.go b/routers/api/v1/repo/cloudbrain.go
index 68baf3287..f1b2751f8 100755
--- a/routers/api/v1/repo/cloudbrain.go
+++ b/routers/api/v1/repo/cloudbrain.go
@@ -78,6 +78,75 @@ func CloudBrainShow(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, models.BaseMessageWithDataApi{Code: 0, Message: "", Data: convert.ToCloudBrain(task)})
+}
+func CreateFileNoteBook(ctx *context.APIContext, option api.CreateFileNotebookJobOption) {
+ cloudbrainTask.FileNotebookCreate(ctx.Context, option)
+}
+
+func GetFileNoteBookInfo(ctx *context.APIContext) {
+ //image description spec description waiting count
+
+ specs, err := models.GetResourceSpecificationByIds([]int64{setting.FileNoteBook.SpecIdCPU, setting.FileNoteBook.SpecIdGPU, setting.FileNoteBook.SpecIdNPU, setting.FileNoteBook.SpecIdNPUCD})
+ if err != nil {
+ log.Error("Fail to query specifications", err)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_query_fail")))
+ return
+ }
+
+ var specCPU, specGpu, specNPU, specNPUCD *api.SpecificationShow
+ var specGpuQueueCode string
+ for _, spec := range specs {
+ if spec.ID == setting.FileNoteBook.SpecIdCPU {
+ specCPU = convert.ToSpecification(spec)
+ } else if spec.ID == setting.FileNoteBook.SpecIdGPU {
+ specGpu = convert.ToSpecification(spec)
+ specGpuQueueCode = spec.QueueCode
+ } else if spec.ID == setting.FileNoteBook.SpecIdNPU {
+ specNPU = convert.ToSpecification(spec)
+ } else if spec.ID == setting.FileNoteBook.SpecIdNPUCD {
+ specNPUCD = convert.ToSpecification(spec)
+ }
+ }
+
+ waitCountNpu := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
+
+ queuesMap, err := cloudbrain.GetQueuesDetail()
+ if err != nil {
+ log.Error("Fail to query gpu queues waiting count", err)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_query_fail")))
+ return
+ }
+ waitCountGPU := (*queuesMap)[specGpuQueueCode]
+ if !setting.ModelartsCD.Enabled{
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "code": 0,
+ "projectName":setting.FileNoteBook.ProjectName,
+ "specCpu": specCPU,
+ "specGpu": specGpu,
+ "specNpu": specNPU,
+ "waitCountGpu": waitCountGPU,
+ "waitCountNpu": waitCountNpu,
+ "imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
+ "imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
+ "imageNpuDescription": setting.FileNoteBook.ImageNPUDescription,
+
+ })
+ } else{
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "code": 0,
+ "projectName":setting.FileNoteBook.ProjectName,
+ "specCpu": specCPU,
+ "specGpu": specGpu,
+ "specNpu": specNPUCD,
+ "waitCountGpu": waitCountGPU,
+ "waitCountNpu": waitCountNpu,
+ "imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
+ "imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
+ "imageNpuDescription": setting.FileNoteBook.ImageNPUCDDescription,
+ })
+
+ }
+
}
func CreateCloudBrain(ctx *context.APIContext, option api.CreateTrainJobOption) {
@@ -141,10 +210,11 @@ func GetCloudbrainTask(ctx *context.APIContext) {
)
ID := ctx.Params(":id")
- job, err := models.GetCloudbrainByID(ID)
+
+ job,err := cloudbrain.GetCloudBrainByIdOrJobId(ID)
+
if err != nil {
ctx.NotFound(err)
- log.Error("GetCloudbrainByID failed:", err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
@@ -566,7 +636,6 @@ func CloudbrainDownloadLogFile(ctx *context.Context) {
url, err := storage.Attachments.PresignedGetURL(prefix+"/"+fileName, fileName)
if err != nil {
log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
- ctx.ServerError("Get minio get SignedUrl failed", err)
return
}
log.Info("fileName=" + fileName)
@@ -650,7 +719,7 @@ func CloudbrainGetLog(ctx *context.APIContext) {
result = getLogFromModelDir(job.JobName, startLine, endLine, resultPath)
if result == nil {
log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"])
- ctx.ServerError(err.Error(), err)
+ //ctx.ServerError(err.Error(), err)
return
}
}
@@ -865,7 +934,7 @@ func CloudBrainModelConvertList(ctx *context.APIContext) {
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"])
- ctx.ServerError("json.Unmarshal failed:", err)
+ //ctx.ServerError("json.Unmarshal failed:", err)
return
}
@@ -896,7 +965,7 @@ func CloudBrainModelConvertList(ctx *context.APIContext) {
models, err := storage.GetObsListObject(job.ID, "output/", parentDir, versionName)
if err != nil {
log.Info("get TrainJobListModel failed:", err)
- ctx.ServerError("GetObsListObject:", err)
+ //ctx.ServerError("GetObsListObject:", err)
return
}
@@ -941,7 +1010,7 @@ func CloudBrainModelList(ctx *context.APIContext) {
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"])
- ctx.ServerError("json.Unmarshal failed:", err)
+ //ctx.ServerError("json.Unmarshal failed:", err)
return
}
diff --git a/routers/api/v1/repo/modelarts.go b/routers/api/v1/repo/modelarts.go
index e0db9eda3..127ddd835 100755
--- a/routers/api/v1/repo/modelarts.go
+++ b/routers/api/v1/repo/modelarts.go
@@ -6,6 +6,7 @@
package repo
import (
+ "code.gitea.io/gitea/modules/cloudbrain"
"encoding/json"
"net/http"
"path"
@@ -37,11 +38,14 @@ func GetModelArtsNotebook2(ctx *context.APIContext) {
)
ID := ctx.Params(":id")
- job, err := models.GetCloudbrainByID(ID)
+
+ job,err := cloudbrain.GetCloudBrainByIdOrJobId(ID)
+
if err != nil {
ctx.NotFound(err)
return
}
+
err = modelarts.HandleNotebookInfo(job)
if err != nil {
ctx.NotFound(err)
diff --git a/routers/home.go b/routers/home.go
index aab760611..092b30fe3 100755
--- a/routers/home.go
+++ b/routers/home.go
@@ -7,6 +7,7 @@ package routers
import (
"bytes"
+ "encoding/json"
"net/http"
"strconv"
"strings"
@@ -672,7 +673,7 @@ func NotFound(ctx *context.Context) {
}
func getRecommendOrg() ([]map[string]interface{}, error) {
- url := setting.RecommentRepoAddr + "organizations"
+ url := setting.RecommentRepoAddr + "home/organizations"
result, err := repository.RecommendFromPromote(url)
if err != nil {
@@ -745,7 +746,7 @@ func GetMapInfo(ctx *context.Context) {
}
func GetRankUser(index string) ([]map[string]interface{}, error) {
- url := setting.RecommentRepoAddr + "user_rank_" + index
+ url := setting.RecommentRepoAddr + "user_rank/user_rank_" + index
result, err := repository.RecommendFromPromote(url)
if err != nil {
@@ -756,13 +757,25 @@ func GetRankUser(index string) ([]map[string]interface{}, error) {
tmpIndex := strings.Index(userRank, " ")
userName := userRank
score := 0
+ label := ""
if tmpIndex != -1 {
userName = userRank[0:tmpIndex]
- tmpScore, err := strconv.Atoi(userRank[tmpIndex+1:])
- if err != nil {
- log.Info("convert to int error.")
+ left := userRank[tmpIndex+1:]
+ tmpIndex1 := strings.Index(left, " ")
+ if tmpIndex1 != -1 {
+ tmpScore, err := strconv.Atoi(left[0:tmpIndex1])
+ if err != nil {
+ log.Info("convert to int error.")
+ }
+ score = tmpScore
+ label = left[tmpIndex1+1:]
+ } else {
+ tmpScore, err := strconv.Atoi(left[tmpIndex+1:])
+ if err != nil {
+ log.Info("convert to int error.")
+ }
+ score = tmpScore
}
- score = tmpScore
}
user, err := models.GetUserByName(userName)
if err == nil {
@@ -772,6 +785,7 @@ func GetRankUser(index string) ([]map[string]interface{}, error) {
userMap["FullName"] = user.FullName
userMap["HomeLink"] = user.HomeLink()
userMap["ID"] = user.ID
+ userMap["Label"] = label
userMap["Avatar"] = user.RelAvatarLink()
userMap["Score"] = score
resultOrg = append(resultOrg, userMap)
@@ -792,25 +806,54 @@ func GetUserRankFromPromote(ctx *context.Context) {
ctx.JSON(200, resultUserRank)
}
+func getMapContent(fileName string) []map[string]string {
+ url := setting.RecommentRepoAddr + fileName
+ result, err := repository.RecommendContentFromPromote(url)
+ remap := make([]map[string]string, 0)
+ if err == nil {
+ json.Unmarshal([]byte(result), &remap)
+ }
+ return remap
+}
+
+func HomeNoticeTmpl(ctx *context.Context) {
+ ctx.Data["url_params"] = ""
+ ctx.HTML(200, "notice")
+}
+
func RecommendHomeInfo(ctx *context.Context) {
resultOrg, err := getRecommendOrg()
if err != nil {
log.Info("error." + err.Error())
}
- resultRepo, err := repository.GetRecommendRepoFromPromote("projects")
+ repoMap := getMapContent("home/projects")
+ resultRepo, err := repository.GetRecommendRepoFromPromote(repoMap)
if err != nil {
log.Info("error." + err.Error())
}
- resultImage, err := getImageInfo("picture_info")
- if err != nil {
- log.Info("error." + err.Error())
- }
-
+ resultActivityInfo := getMapContent("home/activity_info")
mapInterface := make(map[string]interface{})
mapInterface["org"] = resultOrg
mapInterface["repo"] = resultRepo
- mapInterface["image"] = resultImage
- //mapInterface["cloudbrain"] = resultCloudBrain
+ mapInterface["activity"] = resultActivityInfo
+
+ user_experience := getMapContent("home/user_experience")
+ for _, amap := range user_experience {
+ userId := amap["userid"]
+ userIntId, _ := strconv.Atoi(userId)
+ user, err := models.GetUserByID(int64(userIntId))
+ if err == nil {
+ amap["name"] = user.Name
+ amap["fullname"] = user.FullName
+ amap["detail"] = user.Description
+ amap["avatar"] = user.AvatarLink()
+ }
+ }
+ mapInterface["user_experience"] = user_experience
+ dataset, err := models.QueryDatasetGroupByTask()
+ if err == nil {
+ mapInterface["dataset"] = dataset
+ }
ctx.JSON(http.StatusOK, mapInterface)
}
@@ -824,4 +867,4 @@ func HomePrivacy(ctx *context.Context) {
func HomeResoruceDesc(ctx *context.Context) {
ctx.HTML(200, tplResoruceDesc)
-}
\ No newline at end of file
+}
diff --git a/routers/repo/ai_model_convert.go b/routers/repo/ai_model_convert.go
index 962c76aae..405f0ef89 100644
--- a/routers/repo/ai_model_convert.go
+++ b/routers/repo/ai_model_convert.go
@@ -828,5 +828,4 @@ func ModelConvertDownloadModel(ctx *context.Context) {
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect)
}
}
-
}
diff --git a/routers/repo/aisafety.go b/routers/repo/aisafety.go
index b638a486b..6176fcda5 100644
--- a/routers/repo/aisafety.go
+++ b/routers/repo/aisafety.go
@@ -11,7 +11,8 @@ import (
"os"
"strconv"
"strings"
- "time"
+
+ cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/aisafety"
@@ -483,7 +484,6 @@ func isTaskNotFinished(status string) bool {
}
func AiSafetyCreateForGetGPU(ctx *context.Context) {
- t := time.Now()
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["IsCreate"] = true
ctx.Data["type"] = models.TypeCloudBrainOne
@@ -497,7 +497,7 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) {
log.Info("GPUBaseDataSetUUID=" + setting.ModelSafetyTest.GPUBaseDataSetUUID)
log.Info("GPUCombatDataSetName=" + setting.ModelSafetyTest.GPUCombatDataSetName)
log.Info("GPUCombatDataSetUUID=" + setting.ModelSafetyTest.GPUCombatDataSetUUID)
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
prepareCloudbrainOneSpecs(ctx)
queuesDetail, _ := cloudbrain.GetQueuesDetail()
@@ -514,12 +514,11 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) {
}
func AiSafetyCreateForGetNPU(ctx *context.Context) {
- t := time.Now()
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["IsCreate"] = true
ctx.Data["type"] = models.TypeCloudBrainTwo
ctx.Data["compute_resource"] = models.NPUResource
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.NPUBaseDataSetName
diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go
index 7d96d1b58..d3d76f440 100755
--- a/routers/repo/cloudbrain.go
+++ b/routers/repo/cloudbrain.go
@@ -15,6 +15,8 @@ import (
"time"
"unicode/utf8"
+ cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
+
"code.gitea.io/gitea/modules/urfs_client/urchin"
"code.gitea.io/gitea/modules/dataset"
@@ -92,28 +94,9 @@ func MustEnableCloudbrain(ctx *context.Context) {
}
}
-func cutString(str string, lens int) string {
- if len(str) < lens {
- return str
- }
- return str[:lens]
-}
-
-func jobNamePrefixValid(s string) string {
- lowStr := strings.ToLower(s)
- re := regexp.MustCompile(`[^a-z0-9_\\-]+`)
-
- removeSpecial := re.ReplaceAllString(lowStr, "")
-
- re = regexp.MustCompile(`^[_\\-]+`)
- return re.ReplaceAllString(removeSpecial, "")
-
-}
-
func cloudBrainNewDataPrepare(ctx *context.Context, jobType string) error {
ctx.Data["PageIsCloudBrain"] = true
- t := time.Now()
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
ctx.Data["command"] = cloudbrain.GetCloudbrainDebugCommand()
@@ -696,7 +679,7 @@ func CloudBrainRestart(ctx *context.Context) {
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
- resultCode = "-1"
+ resultCode = "2"
errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
@@ -759,43 +742,13 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
return
}
if task.Status == string(models.JobWaiting) || task.Status == string(models.JobRunning) {
- result, err := cloudbrain.GetJob(task.JobID)
+ task, err = cloudbrainTask.SyncCloudBrainOneStatus(task)
if err != nil {
log.Info("error:" + err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return
}
- if result != nil {
- jobRes, _ := models.ConvertToJobResultPayload(result.Payload)
- taskRoles := jobRes.TaskRoles
- taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
- ctx.Data["taskRes"] = taskRes
- ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics
- oldStatus := task.Status
- task.Status = taskRes.TaskStatuses[0].State
- task.ContainerIp = ""
- task.ContainerID = taskRes.TaskStatuses[0].ContainerID
- models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)
-
- if task.DeletedAt.IsZero() { //normal record
- if oldStatus != task.Status {
- notification.NotifyChangeCloudbrainStatus(task, oldStatus)
- }
- err = models.UpdateJob(task)
- if err != nil {
- ctx.Data["error"] = err.Error()
- return
- }
- } else { //deleted record
-
- }
-
- ctx.Data["result"] = jobRes
- } else {
- log.Info("error:" + err.Error())
- return
- }
}
user, err := models.GetUserByID(task.UserID)
@@ -889,7 +842,13 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
func CloudBrainDebug(ctx *context.Context) {
task := ctx.Cloudbrain
debugUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
- ctx.Redirect(debugUrl)
+ if task.BootFile!=""{
+ ctx.Redirect(getFileUrl(debugUrl,task.BootFile))
+
+ }else{
+ ctx.Redirect(debugUrl)
+ }
+
}
func prepareSpec4Show(ctx *context.Context, task *models.Cloudbrain) {
diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go
index de7bb454d..8f3182758 100755
--- a/routers/repo/grampus.go
+++ b/routers/repo/grampus.go
@@ -10,7 +10,6 @@ import (
"path"
"strconv"
"strings"
- "time"
"code.gitea.io/gitea/modules/urfs_client/urchin"
"code.gitea.io/gitea/routers/response"
@@ -77,8 +76,7 @@ func GrampusTrainJobNPUNew(ctx *context.Context) {
func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) error {
ctx.Data["PageIsCloudBrain"] = true
- t := time.Now()
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
//get valid images
diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go
index fabf7e555..b992734e4 100755
--- a/routers/repo/modelarts.go
+++ b/routers/repo/modelarts.go
@@ -15,6 +15,8 @@ import (
"time"
"unicode/utf8"
+ cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
+
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"
"code.gitea.io/gitea/modules/dataset"
@@ -128,8 +130,7 @@ func NotebookNew(ctx *context.Context) {
func notebookNewDataPrepare(ctx *context.Context) error {
ctx.Data["PageIsCloudBrain"] = true
- t := time.Now()
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID)
@@ -239,9 +240,9 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm
}
if setting.ModelartsCD.Enabled {
- err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec)
+ _, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec, "",modelarts.AutoStopDurationMs)
} else {
- err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec)
+ _, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec, "",modelarts.AutoStopDurationMs)
}
if err != nil {
@@ -387,8 +388,33 @@ func NotebookDebug2(ctx *context.Context) {
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
return
}
+ if task.BootFile!=""{
+ ctx.Redirect(getFileUrl(result.Url,task.BootFile) + "?token="+ result.Token)
+ }else{
+ ctx.Redirect(result.Url + "?token=" + result.Token)
+ }
+
- ctx.Redirect(result.Url + "?token=" + result.Token)
+}
+
+func getFileUrl(url string,filename string) string{
+ middle:=""
+ if url[len(url)-3:]=="lab" || url[len(url)-4:]=="lab/" {
+ if url[len(url)-1] == '/' {
+ middle="tree/"
+ } else {
+ middle= "/tree/"
+ }
+ }else{
+ if url[len(url)-1] == '/' {
+ middle = "lab/tree/"
+ } else {
+ middle= "/lab/tree/"
+ }
+ }
+
+
+ return url+middle+path.Base(filename)
}
func NotebookRestart(ctx *context.Context) {
@@ -420,7 +446,8 @@ func NotebookRestart(ctx *context.Context) {
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
- errorMsg = "you have already a running or waiting task, can not create more"
+ resultCode="2"
+ errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
}
@@ -714,8 +741,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error {
// return
//}
- t := time.Now()
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID)
@@ -2351,8 +2377,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error {
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["newInference"] = true
- t := time.Now()
- var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+ var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name)
ctx.Data["display_job_name"] = displayJobName
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID)
diff --git a/routers/routes/routes.go b/routers/routes/routes.go
index a988e4849..60f0365ea 100755
--- a/routers/routes/routes.go
+++ b/routers/routes/routes.go
@@ -359,6 +359,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/all/dosearch/", routers.SearchApi)
m.Post("/user/login/kanban", user.SignInPostAPI)
m.Get("/home/term", routers.HomeTerm)
+ m.Get("/home/notice", routers.HomeNoticeTmpl)
m.Get("/home/privacy", routers.HomePrivacy)
m.Get("/extension/tuomin/upload", modelapp.ProcessImageUI)
m.Post("/extension/tuomin/upload", reqSignIn, modelapp.ProcessImage)
@@ -1273,8 +1274,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/modelsafety", func() {
m.Group("/:id", func() {
- m.Get("/show", reqRepoCloudBrainWriter, repo.GetAiSafetyTaskTmpl)
- m.Get("", reqRepoCloudBrainWriter, repo.GetAiSafetyTask)
+ m.Get("/show", reqRepoCloudBrainReader, repo.GetAiSafetyTaskTmpl)
+ m.Get("", reqRepoCloudBrainReader, repo.GetAiSafetyTask)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.StopAiSafetyTask)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.DelAiSafetyTask)
})
diff --git a/services/cloudbrain/cloudbrainTask/notebook.go b/services/cloudbrain/cloudbrainTask/notebook.go
new file mode 100644
index 000000000..6b2fcf707
--- /dev/null
+++ b/services/cloudbrain/cloudbrainTask/notebook.go
@@ -0,0 +1,362 @@
+package cloudbrainTask
+
+import (
+ "fmt"
+ "net/http"
+ "path"
+
+ "code.gitea.io/gitea/modules/modelarts"
+ "code.gitea.io/gitea/modules/modelarts_cd"
+
+ "code.gitea.io/gitea/modules/git"
+
+ "code.gitea.io/gitea/modules/cloudbrain"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/redis/redis_key"
+ "code.gitea.io/gitea/modules/redis/redis_lock"
+ "code.gitea.io/gitea/modules/storage"
+ "code.gitea.io/gitea/services/cloudbrain/resource"
+ "code.gitea.io/gitea/services/reward/point/account"
+
+ "code.gitea.io/gitea/modules/setting"
+ cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
+ repo_service "code.gitea.io/gitea/services/repository"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/context"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
+)
+
+const NoteBookExtension = ".ipynb"
+
+func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) {
+
+ if ctx.Written() {
+ return
+ }
+
+ if path.Ext(option.File) != NoteBookExtension {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong")))
+ return
+ }
+
+ isNotebookFileExist, _ := isNoteBookFileExist(ctx, option)
+ if !isNotebookFileExist {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
+ return
+ }
+
+ sourceRepo, err := models.GetRepositoryByOwnerAndName(option.OwnerName, option.ProjectName)
+ if err != nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
+ return
+ }
+
+ permission, err := models.GetUserRepoPermission(sourceRepo, ctx.User)
+ if err != nil {
+ log.Error("Get permission failed", err)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
+ return
+ }
+
+ if !permission.CanRead(models.UnitTypeCode) {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
+ return
+ }
+
+ //create repo if not exist
+ repo, err := models.GetRepositoryByName(ctx.User.ID, setting.FileNoteBook.ProjectName)
+ if repo == nil {
+ repo, err = repo_service.CreateRepository(ctx.User, ctx.User, models.CreateRepoOptions{
+ Name: setting.FileNoteBook.ProjectName,
+ Alias: "",
+ Description: "",
+ IssueLabels: "",
+ Gitignores: "",
+ License: "",
+ Readme: "Default",
+ IsPrivate: false,
+ AutoInit: true,
+ DefaultBranch: "master",
+ })
+ }
+ if err != nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.failed_to_create_notebook_repo",setting.FileNoteBook.ProjectName)))
+ return
+ }
+ if option.Type <= 1 {
+ cloudBrainFileNoteBookCreate(ctx, option, repo, sourceRepo)
+ } else {
+ modelartsFileNoteBookCreate(ctx, option, repo, sourceRepo)
+ }
+
+}
+
+func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
+
+ displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
+ jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
+ jobType := string(models.JobTypeDebug)
+
+ lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
+ defer lock.UnLock()
+ isOk, err := lock.Lock(models.CloudbrainKeyDuration)
+ if !isOk {
+ log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
+ return
+ }
+
+ tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
+ if err == nil {
+ if len(tasks) != 0 {
+ log.Error("the job name did already exist", ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
+ return
+ }
+ } else {
+ if !models.IsErrJobNotExist(err) {
+ log.Error("system error, %v", err, ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
+ return
+ }
+ }
+
+ count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
+ if err != nil {
+ log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
+ return
+ } else {
+ if count >= 1 {
+ log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK,models.BaseMessageApi{
+ Code: 2,
+ Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
+ })
+ return
+ }
+ }
+
+ errStr := uploadCodeFile(sourceRepo, getCodePath(jobName), option.BranchName, option.File, jobName)
+ if errStr != "" {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
+ return
+ }
+ command := cloudbrain.GetCloudbrainDebugCommand()
+ specId := setting.FileNoteBook.SpecIdGPU
+ if option.Type == 0 {
+ specId = setting.FileNoteBook.SpecIdCPU
+ }
+ spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
+ JobType: models.JobType(jobType),
+ ComputeResource: models.GPU,
+ Cluster: models.OpenICluster,
+ AiCenterCode: models.AICenterOfCloudBrainOne})
+ if err != nil || spec == nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
+ return
+ }
+
+ if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
+ log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
+ return
+ }
+ ctx.Repo = &context.Repository{
+ Repository: repo,
+ }
+
+ req := cloudbrain.GenerateCloudBrainTaskReq{
+ Ctx: ctx,
+ DisplayJobName: displayJobName,
+ JobName: jobName,
+ Image: setting.FileNoteBook.ImageGPU,
+ Command: command,
+ Uuids: "",
+ DatasetNames: "",
+ DatasetInfos: nil,
+ CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
+ ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
+ BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
+ Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
+ BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
+ JobType: jobType,
+ Description: getDescription(option),
+ BranchName: option.BranchName,
+ BootFile: option.File,
+ Params: "{\"parameter\":[]}",
+ CommitID: "",
+ BenchmarkTypeID: 0,
+ BenchmarkChildTypeID: 0,
+ ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"),
+ Spec: spec,
+ }
+
+ jobId, err := cloudbrain.GenerateTask(req)
+ if err != nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
+ return
+ }
+ ctx.JSON(http.StatusOK, models.BaseMessageApi{
+ Code: 0,
+ Message: jobId,
+ })
+
+}
+
+func getCodePath(jobName string) string {
+ return setting.JobPath + jobName + cloudbrain.CodeMountPath
+}
+
+func getDescription(option api.CreateFileNotebookJobOption) string {
+ return option.OwnerName + "/" + option.ProjectName + "/" + option.File
+}
+
+func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
+ displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
+ jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
+
+ lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName))
+ isOk, err := lock.Lock(models.CloudbrainKeyDuration)
+ if !isOk {
+ log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
+ return
+ }
+ defer lock.UnLock()
+
+ count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))
+
+ if err != nil {
+ log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])
+
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
+ return
+ } else {
+ if count >= 1 {
+ log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK,models.BaseMessageApi{
+ Code: 2,
+ Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
+ })
+ return
+ }
+ }
+
+ tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName)
+ if err == nil {
+ if len(tasks) != 0 {
+ log.Error("the job name did already exist", ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
+ return
+ }
+ } else {
+ if !models.IsErrJobNotExist(err) {
+ log.Error("system error, %v", err, ctx.Data["MsgID"])
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
+ return
+ }
+ }
+
+ err = downloadCode(sourceRepo, getCodePath(jobName), option.BranchName)
+ if err != nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
+ return
+ }
+
+ var aiCenterCode = models.AICenterOfCloudBrainTwo
+ var specId = setting.FileNoteBook.SpecIdNPU
+ if setting.ModelartsCD.Enabled {
+ aiCenterCode = models.AICenterOfChengdu
+ specId = setting.FileNoteBook.SpecIdNPUCD
+ }
+ spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
+ JobType: models.JobTypeDebug,
+ ComputeResource: models.NPU,
+ Cluster: models.OpenICluster,
+ AiCenterCode: aiCenterCode})
+ if err != nil || spec == nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
+ return
+ }
+ if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
+ log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
+ return
+ }
+ ctx.Repo = &context.Repository{
+ Repository: repo,
+ }
+
+ var jobId string
+ if setting.ModelartsCD.Enabled {
+ jobId, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPUCD, spec, option.File,modelarts.AutoStopDurationMs/4)
+ } else {
+ jobId, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPU, spec, option.File,modelarts.AutoStopDurationMs/4)
+ }
+
+ if err != nil {
+ log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"])
+
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
+
+ return
+ }
+
+ ctx.JSON(http.StatusOK, models.BaseMessageApi{
+ Code: 0,
+ Message: jobId,
+ })
+
+}
+
+func isNoteBookFileExist(ctx *context.Context, option api.CreateFileNotebookJobOption) (bool, error) {
+ repoPathOfNoteBook := models.RepoPath(option.OwnerName, option.ProjectName)
+
+ gitRepoOfNoteBook, err := git.OpenRepository(repoPathOfNoteBook)
+ if err != nil {
+ log.Error("RepoRef Invalid repo "+repoPathOfNoteBook, err.Error())
+ return false, err
+ }
+ // We opened it, we should close it
+ defer func() {
+ // If it's been set to nil then assume someone else has closed it.
+ if gitRepoOfNoteBook != nil {
+ gitRepoOfNoteBook.Close()
+ }
+ }()
+ fileExist, err := fileExists(gitRepoOfNoteBook, option.File, option.BranchName)
+ if err != nil || !fileExist {
+ log.Error("Get file error:", err, ctx.Data["MsgID"])
+
+ return false, err
+ }
+ return true, nil
+}
+
+func uploadCodeFile(repo *models.Repository, codePath string, branchName string, filePath string, jobName string) string {
+ err := downloadCode(repo, codePath, branchName)
+ if err != nil {
+ return "cloudbrain.load_code_failed"
+ }
+
+ err = uploadOneFileToMinio(codePath, filePath, jobName, cloudbrain.CodeMountPath+"/")
+ if err != nil {
+ return "cloudbrain.load_code_failed"
+ }
+ return ""
+}
+
+func fileExists(gitRepo *git.Repository, path string, branch string) (bool, error) {
+
+ commit, err := gitRepo.GetBranchCommit(branch)
+ if err != nil {
+ return false, err
+ }
+ if _, err := commit.GetTreeEntryByPath(path); err != nil {
+ return false, err
+ }
+ return true, nil
+}
diff --git a/services/cloudbrain/cloudbrainTask/sync_status.go b/services/cloudbrain/cloudbrainTask/sync_status.go
index 67dc4d3b7..973b9bbc2 100644
--- a/services/cloudbrain/cloudbrainTask/sync_status.go
+++ b/services/cloudbrain/cloudbrainTask/sync_status.go
@@ -1,20 +1,21 @@
package cloudbrainTask
import (
- "net/http"
-
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/cloudbrain"
- "code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
+ "net/http"
+ "strconv"
)
var noteBookOKMap = make(map[int64]int, 20)
+var noteBookFailMap = make(map[int64]int, 20)
-//if a task notebook url can get two times, the notebook can browser.
+//if a task notebook url can get successfulCount times, the notebook can browser.
const successfulCount = 3
+const maxSuccessfulCount=10
func SyncCloudBrainOneStatus(task *models.Cloudbrain) (*models.Cloudbrain, error) {
jobResult, err := cloudbrain.GetJob(task.JobID)
@@ -62,21 +63,29 @@ func isNoteBookReady(task *models.Cloudbrain) bool {
return true
}
noteBookUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
- r := httplib.Get(noteBookUrl)
- res, err := r.Response()
+ res,err := http.Get(noteBookUrl)
if err != nil {
return false
}
+ log.Info("notebook success count:"+strconv.Itoa(noteBookOKMap[task.ID])+",fail count:"+strconv.Itoa(noteBookFailMap[task.ID]))
if res.StatusCode == http.StatusOK {
count := noteBookOKMap[task.ID]
- if count < successfulCount-1 {
+ if count==0{ //如果是第一次成功,把失败数重置为0
+ noteBookFailMap[task.ID]=0
+ }
+
+ if count < successfulCount-1 || (noteBookFailMap[task.ID]==0 && count < maxSuccessfulCount-1) {
noteBookOKMap[task.ID] = count + 1
return false
} else {
+ log.Info("notebook success count:"+strconv.Itoa(count)+",fail count:"+strconv.Itoa(noteBookFailMap[task.ID]))
delete(noteBookOKMap, task.ID)
+ delete(noteBookFailMap, task.ID)
return true
}
+ }else{
+ noteBookFailMap[task.ID]+=1
}
return false
diff --git a/services/cloudbrain/cloudbrainTask/train.go b/services/cloudbrain/cloudbrainTask/train.go
index 8e4673d66..00d01a7ce 100644
--- a/services/cloudbrain/cloudbrainTask/train.go
+++ b/services/cloudbrain/cloudbrainTask/train.go
@@ -810,6 +810,18 @@ func uploadCodeToMinio(codePath, jobName, parentDir string) error {
return nil
}
+func uploadOneFileToMinio(codePath, filePath, jobName, parentDir string) error {
+ destObject := setting.CBCodePathPrefix + jobName + parentDir + path.Base(filePath)
+ sourceFile := codePath + "/" + filePath
+ err := storage.Attachments.UploadObject(destObject, sourceFile)
+ if err != nil {
+ log.Error("UploadObject(%s) failed: %s", filePath, err.Error())
+ return err
+ }
+ return nil
+
+}
+
func readDir(dirname string) ([]os.FileInfo, error) {
f, err := os.Open(dirname)
if err != nil {
diff --git a/services/cloudbrain/util.go b/services/cloudbrain/util.go
index dc9177ecf..0a3096e3f 100644
--- a/services/cloudbrain/util.go
+++ b/services/cloudbrain/util.go
@@ -1,7 +1,11 @@
package cloudbrain
import (
+ "regexp"
+ "strconv"
"strings"
+ "time"
+
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
@@ -33,6 +37,28 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
}
+func GetDisplayJobName(username string) string {
+ t := time.Now()
+ return jobNamePrefixValid(cutString(username, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
+}
+
+func cutString(str string, lens int) string {
+ if len(str) < lens {
+ return str
+ }
+ return str[:lens]
+}
+
+func jobNamePrefixValid(s string) string {
+ lowStr := strings.ToLower(s)
+ re := regexp.MustCompile(`[^a-z0-9_\\-]+`)
+
+ removeSpecial := re.ReplaceAllString(lowStr, "")
+
+ re = regexp.MustCompile(`^[_\\-]+`)
+ return re.ReplaceAllString(removeSpecial, "")
+}
+
func GetAiCenterInfoByCenterCode(aiCenterCode string) *setting.C2NetSequenceInfo {
if setting.AiCenterCodeAndNameMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameMapInfo[aiCenterCode]; ok {
diff --git a/services/repository/repository.go b/services/repository/repository.go
index b4c047392..db25010ea 100644
--- a/services/repository/repository.go
+++ b/services/repository/repository.go
@@ -107,18 +107,13 @@ func GetRecommendCourseKeyWords() ([]string, error) {
}
-func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, error) {
+func GetRecommendRepoFromPromote(repoMap []map[string]string) ([]map[string]interface{}, error) {
resultRepo := make([]map[string]interface{}, 0)
- url := setting.RecommentRepoAddr + filename
- result, err := RecommendFromPromote(url)
-
- if err != nil {
-
- return resultRepo, err
- }
//resultRepo := make([]*models.Repository, 0)
- for _, repoName := range result {
+ for _, record := range repoMap {
+ repoName := record["project_url"]
+ //log.Info("repoName=" + repoName + " tmpIndex1=" + fmt.Sprint(tmpIndex1) + " len(repoName)=" + fmt.Sprint(len(repoName)))
tmpIndex := strings.Index(repoName, "/")
if tmpIndex == -1 {
log.Info("error repo name format.")
@@ -131,7 +126,8 @@ func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, err
repoMap["ID"] = fmt.Sprint(repo.ID)
repoMap["Name"] = repo.Name
repoMap["Alias"] = repo.Alias
-
+ repoMap["Label"] = record["class"]
+ repoMap["Label_en"] = record["class_en"]
repoMap["OwnerName"] = repo.OwnerName
repoMap["NumStars"] = repo.NumStars
repoMap["NumForks"] = repo.NumForks
diff --git a/templates/admin/cloudbrain/list.tmpl b/templates/admin/cloudbrain/list.tmpl
index 20e704a4d..94f80c0fa 100755
--- a/templates/admin/cloudbrain/list.tmpl
+++ b/templates/admin/cloudbrain/list.tmpl
@@ -238,6 +238,7 @@
{{$.i18n.Tr "repo.debug"}}
{{else}}
+ {{if not .BootFile}}
{{end}}
+ {{end}}
{{end}}
diff --git a/templates/base/footer_content.tmpl b/templates/base/footer_content.tmpl
index b4c8518c4..94940e7a9 100755
--- a/templates/base/footer_content.tmpl
+++ b/templates/base/footer_content.tmpl
@@ -1,15 +1,17 @@
-
+
-
+
+
+
+
-
+
+
+
+
+
{{.i18n.Tr "custom.foot.openi_subscription_number"}}
+
+
+
+
{{.i18n.Tr "custom.foot.user_communication_group"}}
+
+
+
+
+
{{.i18n.Tr "custom.foot.copyright"}}
京ICP备18004880号
{{.i18n.Tr "home.powerdby"}}
Trustie确实 {{.i18n.Tr "、Gitea"}}
@@ -69,4 +104,9 @@
+
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index 4ab9da231..f4766bc9d 100755
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -240,6 +240,7 @@ var _hmt = _hmt || [];
}
}
if (isShowNoticeTag){
+ if (!document.getElementById("notic_content")) return;
if(isNewNotice){
document.getElementById("notic_content").style.display='block'
}else{
diff --git a/templates/base/head_home.tmpl b/templates/base/head_home.tmpl
index a77d7b00a..6456e2a4a 100644
--- a/templates/base/head_home.tmpl
+++ b/templates/base/head_home.tmpl
@@ -247,6 +247,7 @@ var _hmt = _hmt || [];
}
}
if (isShowNoticeTag){
+ if (!document.getElementById("notic_content")) return;
if(isNewNotice){
document.getElementById("notic_content").style.display='block'
}else{
diff --git a/templates/base/head_navbar.tmpl b/templates/base/head_navbar.tmpl
index 50521516f..e598d7ca4 100755
--- a/templates/base/head_navbar.tmpl
+++ b/templates/base/head_navbar.tmpl
@@ -1,5 +1,5 @@
-
+
@@ -7,15 +7,18 @@
-
-
+
-
-
-
{{if .IsSigned}}
{{else}}
@@ -224,14 +234,14 @@
diff --git a/templates/base/head_notice.tmpl b/templates/base/head_notice.tmpl
index 43c581e6e..9bd35bcb6 100644
--- a/templates/base/head_notice.tmpl
+++ b/templates/base/head_notice.tmpl
@@ -1,5 +1,5 @@
{{if not .IsCourse}}
- {{ if .notices}}
+ {{ if (and .notices (not .PageIsHome)) }}
diff --git a/templates/custom/home/home_activity.tmpl b/templates/custom/home/home_activity.tmpl
new file mode 100644
index 000000000..447aaafe7
--- /dev/null
+++ b/templates/custom/home/home_activity.tmpl
@@ -0,0 +1,36 @@
+
+
+
+
{{.page_recommend_activity}}
+
{{.page_recommend_activity_desc}}
+
+
+
diff --git a/templates/custom/home/home_dataset.tmpl b/templates/custom/home/home_dataset.tmpl
new file mode 100644
index 000000000..9fb1a04f0
--- /dev/null
+++ b/templates/custom/home/home_dataset.tmpl
@@ -0,0 +1,85 @@
+
+
diff --git a/templates/custom/home/home_org.tmpl b/templates/custom/home/home_org.tmpl
new file mode 100644
index 000000000..14c976cb1
--- /dev/null
+++ b/templates/custom/home/home_org.tmpl
@@ -0,0 +1,20 @@
+
+
diff --git a/templates/custom/home/home_repo.tmpl b/templates/custom/home/home_repo.tmpl
new file mode 100644
index 000000000..0a5e45f25
--- /dev/null
+++ b/templates/custom/home/home_repo.tmpl
@@ -0,0 +1,21 @@
+
+
diff --git a/templates/custom/home/home_top.tmpl b/templates/custom/home/home_top.tmpl
new file mode 100644
index 000000000..3d5b58167
--- /dev/null
+++ b/templates/custom/home/home_top.tmpl
@@ -0,0 +1,1942 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
* {{.page_only_dynamic}}
+
+
+
+
+
+
{{.i18n.Tr "home.page_title"}}
+
{{.i18n.Tr "home.page_description"}}
+
+
+
+
+
+
+
+
+
+
{{.i18n.Tr "home.c2net_title"}}
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/custom/home/home_user_experience.tmpl b/templates/custom/home/home_user_experience.tmpl
new file mode 100644
index 000000000..edee8993d
--- /dev/null
+++ b/templates/custom/home/home_user_experience.tmpl
@@ -0,0 +1,133 @@
+
+
diff --git a/templates/explore/repos.tmpl b/templates/explore/repos.tmpl
index 23170b3d6..e55f0987e 100644
--- a/templates/explore/repos.tmpl
+++ b/templates/explore/repos.tmpl
@@ -1,9 +1,7 @@
-{{template "base/head_pro" .}}
+{{template "base/head_home" .}}
-
{{template "explore/repo_search" .}}
{{template "explore/repo_orgtop" .}}
-
{{template "explore/repo_left" .}}
diff --git a/templates/home.tmpl b/templates/home.tmpl
index c7485a214..c103bf1fc 100755
--- a/templates/home.tmpl
+++ b/templates/home.tmpl
@@ -1,91 +1,25 @@
{{template "base/head_home" .}}
-
+
+ {{template "custom/home/home_top" .}}
+
-
-
-
-
+ {{template "custom/home/home_org" .}}
-
-
{{.page_recommend_activity}}
-
{{.page_recommend_activity_desc}}
-
-
-
-
-
-
-
-
-
-
-
-
+
+ {{template "custom/home/home_repo" .}}
-
-
-
+
+ {{template "custom/home/home_dataset" .}}
+
+
+ {{template "custom/home/home_user_experience" .}}
+
+ {{template "custom/home/home_activity" .}}
+
+
+
-
+
+
-
-
+
{{.page_dev_env}}
{{.page_dev_env_desc}}
@@ -193,8 +127,10 @@
+
+
+
+
diff --git a/templates/notice.tmpl b/templates/notice.tmpl
new file mode 100644
index 000000000..564c96dd3
--- /dev/null
+++ b/templates/notice.tmpl
@@ -0,0 +1,81 @@
+
+{{template "base/head_home" .}}
+
+
+
{{.i18n.Tr "notice_announcement"}}
+
+
+
+{{template "base/footer" .}}
+
diff --git a/templates/repo/debugjob/index.tmpl b/templates/repo/debugjob/index.tmpl
index 20aacfb01..7345fa9bc 100755
--- a/templates/repo/debugjob/index.tmpl
+++ b/templates/repo/debugjob/index.tmpl
@@ -221,7 +221,7 @@
+ data-jobid="{{.Cloudbrain.ID}}" data-resource="{{.ComputeResource}}" data-bootfile="{{.BootFile}}">
{{.Status}}
@@ -266,6 +266,7 @@
{{$.i18n.Tr "repo.debug"}}
{{else}}
+ {{if not .BootFile}}
{{end}}
+ {{end}}
{{else}}
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
@@ -294,7 +296,9 @@
+ data-jobid="{{.Cloudbrain.ID}}"
+ {{if .BootFile}}data-bootfile="{{.BootFile}}"{{end}}>
+
{{$.i18n.Tr "repo.stop"}}
{{else}}
@@ -322,6 +326,7 @@
{{end}}
+ {{if not .BootFile}}
+ {{end}}
diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl
index f501fafa4..5bac6504c 100755
--- a/templates/repo/header.tmpl
+++ b/templates/repo/header.tmpl
@@ -52,13 +52,13 @@
{{if not .IsBeingCreated}}