你确认删除该任务么?此任务一旦删除不可恢复。
+diff --git a/custom/public/css/git.openi.css b/custom/public/css/git.openi.css
index 502ba8d88..8e2c25b2d 100644
--- a/custom/public/css/git.openi.css
+++ b/custom/public/css/git.openi.css
@@ -44,6 +44,12 @@
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
+.ui.label{
+ font-weight: normal;
+}
+.active {
+ color: #0366D6 !important;
+}
.opacity5{ opacity:0.5;}
.radius15{ border-radius:1.5rem !important; }
@@ -250,9 +256,13 @@
box-shadow: none !important;
}
.homeorg-list .card .ui.small.header .content{
- width: calc(100% - 3.25em);
+ width: calc(100% - 3.75em);
}
-.homepro-list{
+.homepro-tit{
+ z-index: 9;
+ position: relative;
+}
+.homepro-list, .homeorg-list{
position: relative;
z-index: 9;
padding: 1.0em 1.0em 3.0em;
@@ -261,42 +271,156 @@
.homepro-list .ui.card{
border-radius: 15px;
background-color: #FFF;
- box-shadow: 0px 5px 10px 0px rgba(105, 192, 255, 30);
- border: 1px solid rgba(105, 192, 255, 40);
+ box-shadow: 0px 5px 10px 0px rgba(105, 192, 255, .3);
+ border: 1px solid rgba(105, 192, 255, .4);
min-height: 10.8em;
}
.homepro-list .ui.card>.content>.header{
line-height: 40px !important;
}
-.homepro-list .swiper-pagination-bullet-active{
+.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;
}
+/**seach**/
+/**搜索导航条适配窄屏**/
+.seachnav{
+ overflow-x: auto;
+ overflow-y: hidden;
+ scrollbar-width: none; /* firefox */
+ -ms-overflow-style: none; /* IE 10+ */
+}
+.seachnav::-webkit-scrollbar {
+ display: none; /* Chrome Safari */
+}
+.ui.green.button, .ui.green.buttons .button{
+ background-color: #5BB973;
+}
+.seach .repos--seach{
+ padding-bottom: 0;
+ border-bottom: none;
+}
+.seach .ui.secondary.pointing.menu{
+ border-bottom: none;
+}
+.seach .ui.secondary.pointing.menu .item > i{
+ margin-right: 5px;
+}
+.seach .ui.secondary.pointing.menu .active.item{
+ border-bottom-width: 2px;
+ margin: 0 0 -1px;
+}
+.seach .ui.menu .active.item>.label {
+ background: #1684FC;
+ color: #FFF;
+}
+.seach .ui.menu .item>.label:not(.active.item>.label) {
+ background: #e8e8e8;
+ color: rgba(0,0,0,.6);
+}
+
+.highlight{
+ color: red;
+}
+.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content {
+ width: calc(100% - 3.0em);
+ margin-left: 0;
+}
+
+.seach .ui.list .list>.item .header, .seach .ui.list>.item .header{
+ margin-bottom: 0.5em;
+ font-size: 1.4rem !important;
+ font-weight: normal;
+}
+.seach .time, .seach .time a{
+ font-size: 12px;
+ color: grey;
+}
+
+.seach .list .item.members .ui.avatar.image {
+ width: 3.2em;
+ height: 3.2em;
+}
+.ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content {
+ width: calc(100% - 4.0em);
+ margin-left: 0;
+}
+
@media only screen and (max-width: 767px) {
.am-mt-30{ margin-top: 1.5rem !important;}
.ui.secondary.hometop.segment{
- margin-bottom: 2.0rem;
+ margin-bottom: 5.0rem;
}
- .bannerpic, .i-code-pic{
+ .bannerpic{
display: none;
}
- .i-code h2::before {
- left: calc(-5.0rem + 6px);
+ #homenews{
+ bottom: -3em;
}
- .i-code h2.am-bw::before{
- left: calc(-4.0rem + 6px);
+ #homenews > p {
+ margin-left: 1.0em;
+ }
+ .homenews{
+ padding-left: 1.3em !important;
+ border-radius: 1.5em;
+ }
+ .homenews::before{
+ left: 2em;
+ }
+ .homepro-tit > p{
+ background: #FFF;
+ }
+ .homeorg{
+ padding-left: 3.5em;
+ }
+ .homeorg-tit::after {
+ left: -2.3em;
+ }
+ .homeorg-list{
+ margin: 0 0 2.0em !important;
+ }
+ .homeorg-list > .column{
+ width: 3em !important;
+ margin-left: -0.5em;
+ padding: 0.5rem 0 0 !important;
+ }
+ .homeorg-list .card{
+ background: none !important;
+ }
+ .homeorg-list .card > .content{
+ padding: 0 !important;
+ }
+
+ .homeorg-list > .column .card .ui.header>img{
+ width: 3.0em;
+ height: 3.0em;
+ border-radius: 2.0em;
+ border: 2px solid #FFF;
+ }
+ .homeorg-list > .column .card .ui.header > .content{
+ display: none;
}
.leftline01{
- width: calc(50% - 4.0rem);
+ width: 4.0em;
+ bottom: 4em;
+ border-radius: 0 0 0 3.0em;
}
- .leftline02{
- left: calc(50% - 1.0rem);
- top: calc(-3.5rem - 2px);
+ .leftline02, .leftline02-2{
+ left: 6.0em;
+ top: calc(-4.0em - 2px);
+ border-radius: 0 3.0em 3.0em 0;
+ width: calc(50% - 6.0em);
+ }
+ .leftline02-2 {
+ width: calc(50% - 8.0em);
+ }
+ .i-env .ui.cards>.card>.content .description{
+ display: none;
}
}
diff --git a/models/action.go b/models/action.go
index 4821910db..2a9d88399 100755
--- a/models/action.go
+++ b/models/action.go
@@ -49,6 +49,14 @@ const (
ActionApprovePullRequest // 21
ActionRejectPullRequest // 22
ActionCommentPull // 23
+
+ ActionUploadAttachment //24
+ ActionCreateDebugGPUTask //25
+ ActionCreateDebugNPUTask //26
+ ActionCreateTrainTask //27
+ ActionCreateInferenceTask // 28
+ ActionCreateBenchMarkTask //29
+ ActionCreateNewModelTask //30
)
// Action represents user operation type and other information to
diff --git a/models/attachment.go b/models/attachment.go
index fd1df9e43..c322d391b 100755
--- a/models/attachment.go
+++ b/models/attachment.go
@@ -88,12 +88,25 @@ func (a *Attachment) APIFormat() *api.Attachment {
Size: a.Size,
UUID: a.UUID,
DownloadURL: a.DownloadURL(),
+ S3DownloadURL: a.S3DownloadURL(),
}
}
// DownloadURL returns the download url of the attached file
func (a *Attachment) DownloadURL() string {
- return fmt.Sprintf("%sattachments/%s", setting.AppURL, a.UUID)
+ return fmt.Sprintf("%sattachments/%s?type=%d", setting.AppURL, a.UUID, a.Type)
+}
+
+// S3DownloadURL returns the s3 download url of the attached file
+func (a *Attachment) S3DownloadURL() string {
+ url := ""
+ if a.Type == TypeCloudBrainOne {
+ url, _ = storage.Attachments.PresignedGetURL(setting.Attachment.Minio.BasePath+AttachmentRelativePath(a.UUID), a.Name)
+ } else if a.Type == TypeCloudBrainTwo {
+ url, _ = storage.ObsGetPreSignedUrl(a.UUID, a.Name)
+ }
+
+ return url
}
// AttachmentRelativePath returns the relative path
diff --git a/models/cloudbrain.go b/models/cloudbrain.go
index 0a14ea7b4..8bb3357ae 100755
--- a/models/cloudbrain.go
+++ b/models/cloudbrain.go
@@ -102,7 +102,7 @@ type Cloudbrain struct {
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
Duration int64
TrainJobDuration string
- Image string //GPU镜像名称
+ Image string //镜像名称
GpuQueue string //GPU类型即GPU队列
ResourceSpecId int //GPU规格id
DeletedAt time.Time `xorm:"deleted"`
@@ -219,17 +219,20 @@ type GetImagesPayload struct {
type CloudbrainsOptions struct {
ListOptions
- RepoID int64 // include all repos if empty
- UserID int64
- JobID string
- SortType string
- CloudbrainIDs []int64
- // JobStatus CloudbrainStatus
+ RepoID int64 // include all repos if empty
+ UserID int64
+ JobID string
+ SortType string
+ CloudbrainIDs []int64
+ JobStatus []string
+ JobStatusNot bool
+ Keyword string
Type int
JobTypes []string
VersionName string
IsLatestVersion string
JobTypeNot bool
+ NeedRepoInfo bool
}
type TaskPod struct {
@@ -449,6 +452,16 @@ type FlavorInfo struct {
Desc string `json:"desc"`
}
+type ImageInfosModelArts struct {
+ ImageInfo []*ImageInfoModelArts `json:"image_info"`
+}
+
+type ImageInfoModelArts struct {
+ Id string `json:"id"`
+ Value string `json:"value"`
+ Desc string `json:"desc"`
+}
+
type PoolInfos struct {
PoolInfo []*PoolInfo `json:"pool_info"`
}
@@ -1072,16 +1085,39 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
}
if (opts.IsLatestVersion) != "" {
- cond = cond.And(
- builder.Eq{"cloudbrain.is_latest_version": 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))
}
- count, err := sess.Where(cond).Count(new(Cloudbrain))
+ 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),
+ )
+ }
+ }
+
+ var count int64
+ var err error
+ condition := "cloudbrain.user_id = `user`.id"
+ if len(opts.Keyword) == 0 {
+ count, err = sess.Where(cond).Count(new(Cloudbrain))
+ } else {
+ lowerKeyWord := strings.ToLower(opts.Keyword)
+
+ cond = cond.And(builder.Or(builder.Like{"LOWER(cloudbrain.job_name)", lowerKeyWord}, builder.Like{"`user`.lower_name", lowerKeyWord}))
+ count, err = sess.Table(&Cloudbrain{}).Where(cond).
+ Join("left", "`user`", condition).Count(new(CloudbrainInfo))
+
+ }
+
if err != nil {
return nil, 0, fmt.Errorf("Count: %v", err)
}
@@ -1099,11 +1135,25 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
sess.OrderBy("cloudbrain.created_unix DESC")
cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum)
if err := sess.Table(&Cloudbrain{}).Where(cond).
- Join("left", "`user`", "cloudbrain.user_id = `user`.id").
+ Join("left", "`user`", condition).
Find(&cloudbrains); err != nil {
return nil, 0, fmt.Errorf("Find: %v", err)
}
+ if opts.NeedRepoInfo {
+ var ids []int64
+ for _, task := range cloudbrains {
+ ids = append(ids, task.RepoID)
+ }
+ repositoryMap, err := GetRepositoriesMapByIDs(ids)
+ if err == nil {
+ for _, task := range cloudbrains {
+ task.Repo = repositoryMap[task.RepoID]
+ }
+ }
+
+ }
+
return cloudbrains, count, nil
}
diff --git a/models/repo_statistic.go b/models/repo_statistic.go
index d3eb65c30..809cb26c4 100755
--- a/models/repo_statistic.go
+++ b/models/repo_statistic.go
@@ -12,6 +12,7 @@ type RepoStatistic struct {
ID int64 `xorm:"pk autoincr" json:"-"`
RepoID int64 `xorm:"unique(s) NOT NULL" json:"repo_id"`
Name string `xorm:"INDEX" json:"name"`
+ Alias string `xorm:"INDEX" json:"alias"`
OwnerName string `json:"ownerName"`
IsPrivate bool `json:"isPrivate"`
IsMirror bool `json:"isMirror"`
@@ -63,6 +64,13 @@ type RepoStatistic struct {
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated" json:"-"`
}
+func (repo *RepoStatistic) DisplayName() string {
+ if repo.Alias == "" {
+ return repo.Name
+ }
+ return repo.Alias
+}
+
func DeleteRepoStatDaily(date string) error {
sess := xStatistic.NewSession()
defer sess.Close()
diff --git a/modules/auth/modelarts.go b/modules/auth/modelarts.go
index 821cd72f8..2d30de6ed 100755
--- a/modules/auth/modelarts.go
+++ b/modules/auth/modelarts.go
@@ -19,7 +19,8 @@ type CreateModelArtsNotebookForm struct {
JobName string `form:"job_name" binding:"Required"`
Attachment string `form:"attachment"`
Description string `form:"description"`
- Flavor string `form:"flavor"`
+ Flavor string `form:"flavor" binding:"Required"`
+ ImageId string `form:"image_id" binding:"Required"`
}
func (f *CreateModelArtsNotebookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go
index f15443b30..b86a2d3f4 100755
--- a/modules/cloudbrain/cloudbrain.go
+++ b/modules/cloudbrain/cloudbrain.go
@@ -1,16 +1,17 @@
package cloudbrain
import (
- "code.gitea.io/gitea/modules/storage"
"encoding/json"
"errors"
"strconv"
- "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/notification"
+ "code.gitea.io/gitea/modules/setting"
)
const (
@@ -221,13 +222,19 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath,
ComputeResource: models.GPUResource,
BenchmarkTypeID: benchmarkTypeID,
BenchmarkChildTypeID: benchmarkChildTypeID,
- Description: description,
+ Description: description,
})
if err != nil {
return err
}
+ if string(models.JobTypeBenchmark) == jobType {
+ notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, jobName, models.ActionCreateBenchMarkTask)
+ } else {
+ notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, jobName, models.ActionCreateDebugGPUTask)
+ }
+
return nil
}
diff --git a/modules/context/auth.go b/modules/context/auth.go
index 0c3ba3b1d..bf8a692f0 100755
--- a/modules/context/auth.go
+++ b/modules/context/auth.go
@@ -6,12 +6,14 @@
package context
import (
+ "encoding/base64"
+ "net/http"
+ "strings"
+
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
- "encoding/base64"
- "net/http"
"gitea.com/macaron/csrf"
"gitea.com/macaron/macaron"
@@ -96,7 +98,14 @@ func Toggle(options *ToggleOptions) macaron.Handler {
return
}
- ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+ tempUrl := ctx.Req.URL.RequestURI()
+
+ if strings.Contains(tempUrl, "action/star?") || strings.Contains(tempUrl, "action/watch?") {
+ redirectForStarAndWatch(ctx, tempUrl)
+
+ } else {
+ ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+ }
ctx.Redirect(setting.AppSubURL + "/user/login")
return
} else if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
@@ -195,6 +204,17 @@ func Toggle(options *ToggleOptions) macaron.Handler {
}
}
+func redirectForStarAndWatch(ctx *Context, tempUrl string) {
+ splits := strings.Split(tempUrl, "?")
+ if len(splits) > 1 {
+ redirectArguments := strings.Split(splits[1], "=")
+
+ if len(redirectArguments) > 0 && redirectArguments[0] == "redirect_to" {
+ ctx.SetCookie("redirect_to", setting.AppSubURL+strings.Replace(redirectArguments[1], "%2f", "/", -1), 0, setting.AppSubURL)
+ }
+ }
+}
+
func basicAuth(ctx *Context) bool {
var siteAuth = base64.StdEncoding.EncodeToString([]byte(setting.CBAuthUser + ":" + setting.CBAuthPassword))
auth := ctx.Req.Header.Get("Authorization")
diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go
index 301c4cb0e..6d60b4e24 100755
--- a/modules/modelarts/modelarts.go
+++ b/modules/modelarts/modelarts.go
@@ -2,6 +2,7 @@ package modelarts
import (
"encoding/json"
+ "errors"
"fmt"
"path"
"strconv"
@@ -9,14 +10,15 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
)
const (
//notebook
- storageTypeOBS = "obs"
- autoStopDuration = 4 * 60 * 60
+ storageTypeOBS = "obs"
+ autoStopDuration = 4 * 60 * 60
autoStopDurationMs = 4 * 60 * 60 * 1000
DataSetMountPath = "/home/ma-user/work"
@@ -63,6 +65,7 @@ const (
var (
poolInfos *models.PoolInfos
FlavorInfos *models.FlavorInfos
+ ImageInfos *models.ImageInfosModelArts
)
type GenerateTrainJobReq struct {
@@ -259,35 +262,42 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin
if err != nil {
return err
}
-
+ notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobResult.ID, jobName, models.ActionCreateDebugNPUTask)
return nil
}
-func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor string) error {
+func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor, imageId string) error {
if poolInfos == nil {
json.Unmarshal([]byte(setting.PoolInfos), &poolInfos)
}
+
+ imageName, err := GetNotebookImageName(imageId)
+ if err != nil {
+ log.Error("GetNotebookImageName failed: %v", err.Error())
+ return err
+ }
+
jobResult, err := createNotebook2(models.CreateNotebook2Params{
JobName: jobName,
Description: description,
Flavor: flavor,
Duration: autoStopDurationMs,
- ImageID: "59a6e9f5-93c0-44dd-85b0-82f390c5d53a",
+ ImageID: imageId,
PoolID: poolInfos.PoolInfo[0].PoolId,
Feature: models.NotebookFeature,
- Volume: models.VolumeReq{
- Capacity: 100,
- Category: models.EVSCategory,
- Ownership: models.ManagedOwnership,
+ Volume: models.VolumeReq{
+ Capacity: setting.Capacity,
+ Category: models.EVSCategory,
+ Ownership: models.ManagedOwnership,
},
- WorkspaceID: "0",
+ WorkspaceID: "0",
})
if err != nil {
log.Error("createNotebook2 failed: %v", err.Error())
return err
}
err = models.CreateCloudbrain(&models.Cloudbrain{
- Status: string(models.JobWaiting),
+ Status: jobResult.Status,
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
JobID: jobResult.ID,
@@ -296,12 +306,14 @@ func GenerateNotebook2(ctx *context.Context, jobName, uuid, description, flavor
Type: models.TypeCloudBrainTwo,
Uuid: uuid,
ComputeResource: models.NPUResource,
+ Image: imageName,
+ Description: description,
})
if err != nil {
return err
}
-
+ notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobResult.ID, jobName, models.ActionCreateDebugNPUTask)
return nil
}
@@ -335,12 +347,12 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error())
return err
}
-
+ jobId := strconv.FormatInt(jobResult.JobID, 10)
err = models.CreateCloudbrain(&models.Cloudbrain{
Status: TransTrainJobStatus(jobResult.Status),
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
- JobID: strconv.FormatInt(jobResult.JobID, 10),
+ JobID: jobId,
JobName: req.JobName,
JobType: string(models.JobTypeTrain),
Type: models.TypeCloudBrainTwo,
@@ -371,7 +383,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error
log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error())
return err
}
-
+ notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobId, req.JobName, models.ActionCreateTrainTask)
return nil
}
@@ -555,12 +567,12 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e
log.Error("GetAttachmentByUUID(%s) failed:%v", strconv.FormatInt(jobResult.JobID, 10), err.Error())
return err
}
-
+ jobID := strconv.FormatInt(jobResult.JobID, 10)
err = models.CreateCloudbrain(&models.Cloudbrain{
Status: TransTrainJobStatus(jobResult.Status),
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
- JobID: strconv.FormatInt(jobResult.JobID, 10),
+ JobID: jobID,
JobName: req.JobName,
JobType: string(models.JobTypeInference),
Type: models.TypeCloudBrainTwo,
@@ -583,6 +595,7 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e
EngineName: req.EngineName,
LabelName: req.LabelName,
IsLatestVersion: req.IsLatestVersion,
+ ComputeResource: models.NPUResource,
VersionCount: req.VersionCount,
TotalVersionCount: req.TotalVersionCount,
ModelName: req.ModelName,
@@ -595,6 +608,29 @@ func GenerateInferenceJob(ctx *context.Context, req *GenerateInferenceJobReq) (e
log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error())
return err
}
-
+ notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, jobID, req.JobName, models.ActionCreateInferenceTask)
return nil
}
+
+func GetNotebookImageName(imageId string) (string, error) {
+ var validImage = false
+ var imageName = ""
+
+ if ImageInfos == nil {
+ json.Unmarshal([]byte(setting.ImageInfos), &ImageInfos)
+ }
+
+ for _, imageInfo := range ImageInfos.ImageInfo {
+ if imageInfo.Id == imageId {
+ validImage = true
+ imageName = imageInfo.Value
+ }
+ }
+
+ if !validImage {
+ log.Error("the image id(%s) is invalid", imageId)
+ return imageName, errors.New("the image id is invalid")
+ }
+
+ return imageName, nil
+}
diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go
index 4bc296657..2ac73c2c3 100644
--- a/modules/notification/action/action.go
+++ b/modules/notification/action/action.go
@@ -330,3 +330,18 @@ func (a *actionNotifier) NotifySyncDeleteRef(doer *models.User, repo *models.Rep
log.Error("notifyWatchers: %v", err)
}
}
+
+func (a *actionNotifier) NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) {
+ if err := models.NotifyWatchers(&models.Action{
+ ActUserID: doer.ID,
+ ActUser: doer,
+ OpType: optype,
+ RepoID: repo.ID,
+ Repo: repo,
+ IsPrivate: repo.IsPrivate,
+ RefName: name,
+ Content: id,
+ }); err != nil {
+ log.Error("notifyWatchers: %v", err)
+ }
+}
diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go
index 8325f710c..8d6fdeb52 100644
--- a/modules/notification/base/notifier.go
+++ b/modules/notification/base/notifier.go
@@ -54,4 +54,6 @@ type Notifier interface {
NotifySyncPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *repository.PushCommits)
NotifySyncCreateRef(doer *models.User, repo *models.Repository, refType, refFullName string)
NotifySyncDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string)
+
+ NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType)
}
diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go
index a74c47980..0d3489882 100644
--- a/modules/notification/base/null.go
+++ b/modules/notification/base/null.go
@@ -154,3 +154,7 @@ func (*NullNotifier) NotifySyncCreateRef(doer *models.User, repo *models.Reposit
// NotifySyncDeleteRef places a place holder function
func (*NullNotifier) NotifySyncDeleteRef(doer *models.User, repo *models.Repository, refType, refFullName string) {
}
+
+func (*NullNotifier) NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) {
+
+}
diff --git a/modules/notification/notification.go b/modules/notification/notification.go
index d12024663..0fd6fa471 100644
--- a/modules/notification/notification.go
+++ b/modules/notification/notification.go
@@ -37,6 +37,13 @@ func NewContext() {
RegisterNotifier(action.NewNotifier())
}
+// NotifyUploadAttachment notifies attachment upload message to notifiers
+func NotifyOtherTask(doer *models.User, repo *models.Repository, id string, name string, optype models.ActionType) {
+ for _, notifier := range notifiers {
+ notifier.NotifyOtherTask(doer, repo, id, name, optype)
+ }
+}
+
// NotifyCreateIssueComment notifies issue comment related message to notifiers
func NotifyCreateIssueComment(doer *models.User, repo *models.Repository,
issue *models.Issue, comment *models.Comment) {
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 06cbd6de5..2a29dd700 100755
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -512,7 +512,9 @@ var (
ProfileID string
PoolInfos string
Flavor string
- DebugHost string
+ DebugHost string
+ ImageInfos string
+ Capacity int
//train-job
ResourcePools string
Engines string
@@ -1334,7 +1336,8 @@ func NewContext() {
ProfileID = sec.Key("PROFILE_ID").MustString("")
PoolInfos = sec.Key("POOL_INFOS").MustString("")
Flavor = sec.Key("FLAVOR").MustString("")
- DebugHost = sec.Key("DEBUG_SERVER_HOST").MustString("http://192.168.202.73")
+ ImageInfos = sec.Key("IMAGE_INFOS").MustString("")
+ Capacity = sec.Key("IMAGE_INFOS").MustInt(100)
ResourcePools = sec.Key("Resource_Pools").MustString("")
Engines = sec.Key("Engines").MustString("")
EngineVersions = sec.Key("Engine_Versions").MustString("")
diff --git a/modules/structs/attachment.go b/modules/structs/attachment.go
old mode 100644
new mode 100755
index 7becd9433..0f3c2ed6a
--- a/modules/structs/attachment.go
+++ b/modules/structs/attachment.go
@@ -16,9 +16,10 @@ type Attachment struct {
Size int64 `json:"size"`
DownloadCount int64 `json:"download_count"`
// swagger:strfmt date-time
- Created time.Time `json:"created_at"`
- UUID string `json:"uuid"`
- DownloadURL string `json:"browser_download_url"`
+ Created time.Time `json:"created_at"`
+ UUID string `json:"uuid"`
+ DownloadURL string `json:"browser_download_url"`
+ S3DownloadURL string
}
// EditAttachmentOptions options for editing attachments
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index b3ede3b06..5c0c600be 100755
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -864,9 +864,13 @@ confirm_choice = confirm
cloudbran1_tips = Only data in zip format can create cloudbrain tasks
cloudbrain_creator=Creator
cloudbrain_task = Task Name
+cloudbrain_task_type = Task Type
+cloudbrain_task_name=Cloud Brain Task Name
cloudbrain_operate = Operate
cloudbrain_status_createtime = Status/Createtime
cloudbrain_status_runtime = Running Time
+cloudbrain_jobname_err=Name must start with a lowercase letter or number,can include lowercase letter,number,_ and -,can not end with _, and can be up to 36 characters long.
+cloudbrain_query_fail=Failed to query cloudbrain information.
record_begintime_get_err=Can not get the record begin time.
parameter_is_wrong=The input parameter is wrong.
@@ -2059,6 +2063,9 @@ people = People
teams = Teams
lower_members = members
lower_repositories = repositories
+lower_member=member
+lower_repository = repository
+
create_new_team = New Team
create_team = Create Team
org_desc = Description
@@ -2078,6 +2085,9 @@ custom_select_courses = Customize selected courses
recommend_remain_pro = Remain
save_fail_tips = The upper limit is exceeded
select_again = Select more than 9, please select again!
+custom_select_projects = Customize selected projects
+customize = Customize
+selected_project=Selected Projects
form.name_reserved = The organization name '%s' is reserved.
form.name_pattern_not_allowed = The pattern '%s' is not allowed in an organization name.
@@ -2338,6 +2348,12 @@ datasets.owner=Owner
datasets.name=name
datasets.private=Private
+cloudbrain.all_task_types=All Task Types
+cloudbrain.all_computing_resources=All Computing Resources
+cloudbrain.all_status=All Status
+cloudbrain.download_report=Download Report
+cloudbrain.cloudbrain_name=Cloudbrain Name
+
hooks.desc = Webhooks automatically make HTTP POST requests to a server when certain openi events trigger. Webhooks defined here are defaults and will be copied into all new repositories. Read more in the webhooks guide.
hooks.add_webhook = Add Default Webhook
hooks.update_webhook = Update Default Webhook
@@ -2677,6 +2693,13 @@ mirror_sync_create = synced new reference %[2]s to %[2]s at %[3]s from mirror
approve_pull_request = `approved %s#%[2]s`
reject_pull_request = `suggested changes for %s#%[2]s`
+upload_dataset=`upload dataset %s`
+task_gpudebugjob=`created CPU/GPU type debugging task%s`
+task_npudebugjob=`created NPU type debugging task %s`
+task_trainjob=`created training task%s`
+task_inferencejob=`created reasoning task %s`
+task_benchmark=`created profiling task %s`
+task_createmodel=`created new model %s`
[tool]
ago = %s ago
@@ -2751,6 +2774,7 @@ head.dataset = Datasets
foot.council = Council
foot.technical_committee = Technical Committee
foot.join = Join OpenI
+foot.agreement=Use agreement
foot.news = News
foot.community_news = Community News
foot.member_news = Member news
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 86e88184c..42deebcb7 100755
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -868,10 +868,13 @@ confirm_choice=确定
cloudbran1_tips=只有zip格式的数据集才能发起云脑任务
cloudbrain_creator=创建者
cloudbrain_task=任务名称
+cloudbrain_task_type=任务类型
+cloudbrain_task_name=云脑侧任务名称
cloudbrain_operate=操作
cloudbrain_status_createtime=状态/创建时间
cloudbrain_status_runtime = 运行时长
cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。
+cloudbrain_query_fail=查询云脑任务失败。
record_begintime_get_err=无法获取统计开始时间。
parameter_is_wrong=输入参数错误,请检查输入参数。
@@ -2069,6 +2072,8 @@ people=组织成员
teams=组织团队
lower_members=名成员
lower_repositories=个项目
+lower_member=名成员
+lower_repository=个项目
create_new_team=新建团队
create_team=创建团队
org_desc=组织描述
@@ -2088,6 +2093,9 @@ custom_select_courses = 自定义精选课程
recommend_remain_pro = 还能推荐
save_fail_tips = 最多可选9个,保存失败
select_again = 选择超过9个,请重新选择!
+custom_select_projects = 自定义精选项目
+customize = 自定义
+selected_project=精选项目
form.name_reserved=组织名称 '%s' 是被保留的。
form.name_pattern_not_allowed=组织名称中不允许使用 "%s"。
@@ -2349,6 +2357,12 @@ datasets.owner=所有者
datasets.name=名称
datasets.private=私有
+cloudbrain.all_task_types=全部任务类型
+cloudbrain.all_computing_resources=全部计算资源
+cloudbrain.all_status=全部状态
+cloudbrain.download_report=下载此报告
+cloudbrain.cloudbrain_name=云脑侧名称
+
hooks.desc=当某些 openi 事件触发时, Web 钩子会自动向服务器发出 HTTP POST 请求。此处定义的 Web 钩子是默认值, 将复制到所有新建项目中。参阅 Web钩子指南 获取更多内容。
hooks.add_webhook=新增默认Web钩子
hooks.update_webhook=更新默认Web钩子
@@ -2415,7 +2429,7 @@ auths.sspi_auto_activate_users_helper=允许 SSPI 认证自动激活新用户
auths.sspi_strip_domain_names=从用户名中删除域名部分
auths.sspi_strip_domain_names_helper=如果选中此项,域名将从登录名中删除(例如,"DOMAIN\user"和"user@example.org",两者都将变成只是“用户”)。
auths.sspi_separator_replacement=要使用的分隔符代替\, / 和 @
-auths.sspi_separator_replacement_helper=用于替换下级登录名称分隔符的字符 (例如) "DOMAIN\user") 中的 \ 和用户主名字(如"user@example.org中的 @ )。
+auths.sspi_separator_replacement_helper=用于替换下级登录名称分隔符的字符 (例如) "DOMAIN\user") 中的 \ 和用户主名字(如"user@example.org"中的 @ )。
auths.sspi_default_language=默认语言
auths.sspi_default_language_helper=SSPI 认证方法为用户自动创建的默认语言。如果您想要自动检测到语言,请留空。
auths.tips=帮助提示
@@ -2688,6 +2702,13 @@ mirror_sync_create=从镜像同步了新的引用 %[2]s
mirror_sync_delete=从镜像同步并从 %[3]s 删除了引用 %[2]s
approve_pull_request=`同意了 %s#%[2]s`
reject_pull_request=`建议变更 %s#%[2]s`
+upload_dataset=`上传了数据集文件 %s`
+task_gpudebugjob=`创建了CPU/GPU类型调试任务 %s`
+task_npudebugjob=`创建了NPU类型调试任务 %s`
+task_trainjob=`创建了训练任务 %s`
+task_inferencejob=`创建了推理任务 %s`
+task_benchmark=`创建了评测任务 %s`
+task_createmodel=`导入了新模型 %s`
[tool]
ago=%s前
@@ -2762,6 +2783,7 @@ head.dataset=数据集
foot.council=理事会
foot.technical_committee=技术委员会
foot.join=加入启智
+foot.agreement=使用协议
foot.news=动态
foot.community_news=社区动态
foot.member_news=成员动态
diff --git a/package-lock.json b/package-lock.json
index e885641a8..f5a941869 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13879,6 +13879,130 @@
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
"dev": true
},
+ "ts-loader": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.0.0.tgz",
+ "integrity": "sha512-iissbnuJkqbB3YAmnWyEbmdNcGcoiiXopKHKyqdoCrFQVi9pnplXeveQDXJnQOCYNNcb2pjT2zzSYTX6c9QtAA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.3.0",
+ "enhanced-resolve": "^4.0.0",
+ "loader-utils": "^1.0.2",
+ "micromatch": "^3.1.4",
+ "semver": "^5.0.1"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
"tslib": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
@@ -13938,6 +14062,12 @@
"is-typedarray": "^1.0.0"
}
},
+ "typescript": {
+ "version": "4.5.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
+ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+ "dev": true
+ },
"ua-parser-js": {
"version": "0.7.21",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
diff --git a/package.json b/package.json
index 3b26e9721..0f93faaea 100644
--- a/package.json
+++ b/package.json
@@ -71,6 +71,8 @@
"script-loader": "0.7.2",
"stylelint": "13.3.3",
"stylelint-config-standard": "20.0.0",
+ "ts-loader": "4.0.0",
+ "typescript": "4.5.5",
"updates": "10.2.11"
},
"browserslist": [
diff --git a/public/home/home.js b/public/home/home.js
index f49c8248b..8f7d6a626 100644
--- a/public/home/home.js
+++ b/public/home/home.js
@@ -6,7 +6,6 @@ if(isEmpty(token)){
token = meta.attr("content");
}
}
-
var swiperNewMessage = new Swiper(".newslist", {
direction: "vertical",
slidesPerView: 10,
@@ -17,7 +16,7 @@ var swiperNewMessage = new Swiper(".newslist", {
},
});
var swiperRepo = new Swiper(".homepro-list", {
- slidesPerView: 3,
+ slidesPerView: 1,
slidesPerColumn: 2,
slidesPerColumnFill:'row',
spaceBetween: 30,
@@ -29,6 +28,37 @@ var swiperRepo = new Swiper(".homepro-list", {
delay: 2500,
disableOnInteraction: false,
},
+ breakpoints: {
+ 768: {
+ slidesPerView: 2,
+ },
+ 1024: {
+ slidesPerView: 3,
+ },
+ },
+});
+
+var swiperOrg = new Swiper(".homeorg-list", {
+ slidesPerView: 1,
+ slidesPerColumn: 4,
+ slidesPerColumnFill:'row',
+ spaceBetween: 15,
+ pagination: {
+ el: ".swiper-pagination",
+ clickable: true,
+ },
+ autoplay: {
+ delay: 4500,
+ disableOnInteraction: false,
+ },
+ breakpoints: {
+ 768: {
+ slidesPerView: 2,
+ },
+ 1024: {
+ slidesPerView: 3,
+ },
+ },
});
var output = document.getElementById("newmessage");
@@ -96,11 +126,14 @@ socket.onmessage = function (e) {
actionName = actionName.replace("{oldRepoName}",record.Content);
html += recordPrefix + actionName;
html += " " + getRepotext(record) + ""
+ }
+ else if(record.OpType == "24" || record.OpType == "25" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "29" || record.OpType == "30"){
+ html += recordPrefix + actionName;
+ html += " " + record.RefName + ""
}
else{
continue;
}
-
if(record.Repo != null){
var time = getTime(record.CreatedUnix,currentTime);
html += " " + time;
@@ -108,13 +141,32 @@ socket.onmessage = function (e) {
html += "";
html += "";
}
-
}
output.innerHTML = html;
swiperNewMessage.updateSlides();
swiperNewMessage.updateProgress();
};
+function getTaskLink(record){
+ var re = getRepoLink(record);
+ if(record.OpType == 24){
+ return re + "/datasets?type=" + record.Content;
+ }else if(record.OpType == 25){
+ return re + "/cloudbrain/" + record.RefName;
+ }else if(record.OpType == 26){
+ return re + "/modelarts/notebook/" + record.Content;
+ }else if(record.OpType == 27){
+ return re + "/modelarts/train-job/" + record.Content;
+ }else if(record.OpType == 28){
+ return re + "/modelarts/inference-job/" + record.Content;
+ }else if(record.OpType == 29){
+ return re + "/cloudbrain/benchmark/" + record.RefName;
+ }else if(record.OpType == 30){
+ return re + "/modelmanage/show_model_info?name=" + record.RefName;
+ }
+ return re;
+}
+
function getMsg(record){
var html ="";
html += "