Browse Source

Merge remote-tracking branch 'origin/V20220830' into zouap

pull/2755/head
zouap 2 years ago
parent
commit
4cc264149b
23 changed files with 1346 additions and 122 deletions
  1. +3
    -2
      models/cloudbrain.go
  2. +11
    -6
      models/dataset.go
  3. +88
    -0
      models/dataset_reference.go
  4. +1
    -0
      models/models.go
  5. +8
    -0
      modules/auth/dataset.go
  6. +43
    -0
      modules/context/permission_json.go
  7. +18
    -0
      modules/dataset/dataset.go
  8. +5
    -2
      modules/setting/repository.go
  9. +27
    -24
      modules/templates/helper.go
  10. +8
    -0
      options/locale/locale_en-US.ini
  11. +11
    -0
      options/locale/locale_zh-CN.ini
  12. +1
    -1
      routers/api/v1/repo/cloudbrain_dashboard.go
  13. +5
    -14
      routers/home.go
  14. +115
    -11
      routers/repo/dataset.go
  15. +9
    -0
      routers/routes/routes.go
  16. +19
    -0
      services/repository/dataset.go
  17. +83
    -61
      templates/repo/datasets/index.tmpl
  18. +8
    -0
      templates/repo/datasets/reference.tmpl
  19. +1
    -1
      templates/repo/header.tmpl
  20. +735
    -0
      web_src/js/components/dataset/referenceDataset.vue
  21. +9
    -0
      web_src/js/components/dataset/selectDataset.vue
  22. +123
    -0
      web_src/js/features/i18nVue.js
  23. +15
    -0
      web_src/js/index.js

+ 3
- 2
models/cloudbrain.go View File

@@ -8,13 +8,14 @@ import (
"strings"
"time"

"code.gitea.io/gitea/modules/util"

"xorm.io/builder"
"xorm.io/xorm"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
)

type CloudbrainStatus string
@@ -142,7 +143,7 @@ type Cloudbrain struct {
VersionID int64 //版本id
VersionName string `xorm:"INDEX"` //当前版本
Uuid string //数据集id
DatasetName string
DatasetName string `xorm:"varchar(2000)"`
VersionCount int //任务的当前版本数量,不包括删除的
IsLatestVersion string //是否是最新版本,1是,0否
CommitID string //提交的仓库代码id


+ 11
- 6
models/dataset.go View File

@@ -6,6 +6,8 @@ import (
"sort"
"strings"

"code.gitea.io/gitea/modules/setting"

"code.gitea.io/gitea/modules/log"

"code.gitea.io/gitea/modules/timeutil"
@@ -178,7 +180,7 @@ type SearchDatasetOptions struct {
Category string
Task string
License string
DatasetIDs []int64 // 目前只在StarByMe为true时起作用
DatasetIDs []int64
ListOptions
SearchOrderBy
IsOwner bool
@@ -188,6 +190,7 @@ type SearchDatasetOptions struct {
JustNeedZipFile bool
NeedAttachment bool
UploadAttachmentByMe bool
QueryReference bool
}

func CreateDataset(dataset *Dataset) (err error) {
@@ -258,7 +261,7 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond {
}
}
if len(opts.DatasetIDs) > 0 {
if opts.StarByMe {
if opts.StarByMe || (opts.RepoID == 0 && opts.QueryReference) {
cond = cond.And(builder.In("dataset.id", opts.DatasetIDs))
} else {
subCon := builder.NewCond()
@@ -329,13 +332,15 @@ func SearchDatasetByCondition(opts *SearchDatasetOptions, cond builder.Cond) (Da
return nil, 0, fmt.Errorf("Count: %v", err)
}

sess.Select(selectColumnsSql).Join("INNER", "repository", "repository.id = dataset.repo_id").
builderQuery := builder.Dialect(setting.Database.Type).Select("id", "title", "status", "category", "description", "download_times", "license", "task", "release_id", "user_id", "repo_id", "created_unix", "updated_unix", "num_stars", "recommend", "use_count").From(builder.Dialect(setting.Database.Type).Select(selectColumnsSql).From("dataset").Join("INNER", "repository", "repository.id = dataset.repo_id").
Join("INNER", "attachment", "attachment.dataset_id=dataset.id").
Where(cond).OrderBy(opts.SearchOrderBy.String())
Where(cond), "d").OrderBy(opts.SearchOrderBy.String())

if opts.PageSize > 0 {
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
builderQuery.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
if err = sess.Find(&datasets); err != nil {

if err = sess.SQL(builderQuery).Find(&datasets); err != nil {
return nil, 0, fmt.Errorf("Dataset: %v", err)
}



+ 88
- 0
models/dataset_reference.go View File

@@ -0,0 +1,88 @@
package models

import (
"strconv"
"strings"

"code.gitea.io/gitea/modules/timeutil"
)

type DatasetReference struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX unique"`
DatasetID string `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
}

func GetDatasetIdsByRepoID(repoID int64) []int64 {
var datasets []int64
var datasetIds []string
_ = x.Table("dataset_reference").Where("repo_id=?", repoID).
Cols("dataset_reference.dataset_id").Find(&datasetIds)
if len(datasetIds) > 0 {
for _, datasetIdStr := range strings.Split(datasetIds[0], ",") {
datasetId, err := strconv.ParseInt(datasetIdStr, 10, 64)
if err != nil {
continue
}
datasets = append(datasets, datasetId)
}
}

return datasets
}

func HasReferenceDataset(repoID int64) bool {

var datasetIds []string
_ = x.Table("dataset_reference").Where("repo_id=?", repoID).
Cols("dataset_reference.dataset_id").Find(&datasetIds)
return len(datasetIds) > 0
}

func getReferenceDatasetStr(repoID int64) string {

var datasetIds []string
_ = x.Table("dataset_reference").Where("repo_id=?", repoID).
Cols("dataset_reference.dataset_id").Find(&datasetIds)
if len(datasetIds) > 0 {
return datasetIds[0]
}
return ""
}

func DeleteReferenceDatasetIdsByRepoID(repoID int64) error {

_, err := x.Exec("delete from dataset_reference where repo_id=?", repoID)
return err
}

func NewDatasetIdsByRepoID(repoID int64, datasetIds []int64) error {
if len(datasetIds) == 0 { //关联数据集数组为空
DeleteReferenceDatasetIdsByRepoID(repoID)
}
var datasetsStrArray []string
for _, datasetId := range datasetIds {
datasetsStrArray = append(datasetsStrArray, strconv.FormatInt(datasetId, 10))
}

newDatasetStr := strings.Join(datasetsStrArray, ",")
oldDatasetStr := getReferenceDatasetStr(repoID)
if newDatasetStr == oldDatasetStr { //关联数据集无变化,不需要处理
return nil
}
if oldDatasetStr != "" { //已经存在关联数据集
_, err := x.Exec("update dataset_reference set dataset_id=? where repo_id=?", newDatasetStr, repoID)

return err
} else {
datasetReference := DatasetReference{
DatasetID: newDatasetStr,
RepoID: repoID,
}

_, err := x.Insert(datasetReference)
return err
}

}

+ 1
- 0
models/models.go View File

@@ -146,6 +146,7 @@ func init() {
new(SearchRecord),
new(AiModelConvert),
new(CloudbrainTemp),
new(DatasetReference),
)

tablesStatistic = append(tablesStatistic,


+ 8
- 0
modules/auth/dataset.go View File

@@ -44,3 +44,11 @@ type EditAttachmentForm struct {
func (f *EditAttachmentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

type ReferenceDatasetForm struct {
DatasetID []int64 `binding:"Required"`
}

func (f *ReferenceDatasetForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

+ 43
- 0
modules/context/permission_json.go View File

@@ -0,0 +1,43 @@
package context

import (
"net/http"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"gitea.com/macaron/macaron"
)

func RequireRepoReaderJson(unitType models.UnitType) macaron.Handler {
return func(ctx *Context) {
if !ctx.Repo.CanRead(unitType) {
if log.IsTrace() {
if ctx.IsSigned {
log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
"User in Repo has Permissions: %-+v",
ctx.User,
unitType,
ctx.Repo.Repository,
ctx.Repo.Permission)
} else {
log.Trace("Permission Denied: Anonymous user cannot read %-v in Repo %-v\n"+
"Anonymous user in Repo has Permissions: %-+v",
unitType,
ctx.Repo.Repository,
ctx.Repo.Permission)
}
}
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("error.no_right")))
return
}
}
}

func RequireRepoWriterJson(unitType models.UnitType) macaron.Handler {
return func(ctx *Context) {
if !ctx.Repo.CanWrite(unitType) {
ctx.JSON(http.StatusOK, models.BaseErrorMessage(ctx.Tr("error.no_right")))
return
}
}
}

+ 18
- 0
modules/dataset/dataset.go View File

@@ -1,5 +1,7 @@
package dataset

import "code.gitea.io/gitea/models"

func GetResourceType(cloudbrainType int) string {
if cloudbrainType == 0 {
return "CPU/GPU"
@@ -15,3 +17,19 @@ func GetStatusText(isPrivate bool) string {
return "dataset.public"
}
}

func IsShowDataSetOfCurrentRepo(repoID int64) bool {
repo := models.Repository{
ID: repoID,
}

dataset, _ := models.GetDatasetByRepo(&repo)
if dataset != nil {
return true
}
if models.HasReferenceDataset(repoID) {
return false
}
return true

}

+ 5
- 2
modules/setting/repository.go View File

@@ -193,8 +193,9 @@ var (
Wiki: []string{"never"},
},
}
RepoRootPath string
ScriptType = "bash"
RepoRootPath string
RepoMaxReferenceDatasetNum int
ScriptType = "bash"
)

func newRepository() {
@@ -210,6 +211,8 @@ func newRepository() {
Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool()
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1)
RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gitea-repositories"))
RepoMaxReferenceDatasetNum = sec.Key("MAX_REF_DATASET_NUM").MustInt(20)

forcePathSeparator(RepoRootPath)
if !filepath.IsAbs(RepoRootPath) {
RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath)


+ 27
- 24
modules/templates/helper.go View File

@@ -97,23 +97,24 @@ func NewFuncMap() []template.FuncMap {
"AllowedReactions": func() []string {
return setting.UI.Reactions
},
"AvatarLink": models.AvatarLink,
"Safe": Safe,
"SafeJS": SafeJS,
"Str2html": Str2html,
"subOne": subOne,
"TimeSince": timeutil.TimeSince,
"TimeSinceUnix": timeutil.TimeSinceUnix,
"TimeSinceUnix1": timeutil.TimeSinceUnix1,
"AttachmentResourceType": dataset.GetResourceType,
"AttachmentStatus": dataset.GetStatusText,
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort,
"RawTimeSince": timeutil.RawTimeSince,
"FileSize": base.FileSize,
"PrettyNumber": base.PrettyNumber,
"Subtract": base.Subtract,
"EntryIcon": base.EntryIcon,
"MigrationIcon": MigrationIcon,
"AvatarLink": models.AvatarLink,
"Safe": Safe,
"SafeJS": SafeJS,
"Str2html": Str2html,
"subOne": subOne,
"TimeSince": timeutil.TimeSince,
"TimeSinceUnix": timeutil.TimeSinceUnix,
"TimeSinceUnix1": timeutil.TimeSinceUnix1,
"AttachmentResourceType": dataset.GetResourceType,
"AttachmentStatus": dataset.GetStatusText,
"IsShowDataSetOfCurrentRepo": dataset.IsShowDataSetOfCurrentRepo,
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort,
"RawTimeSince": timeutil.RawTimeSince,
"FileSize": base.FileSize,
"PrettyNumber": base.PrettyNumber,
"Subtract": base.Subtract,
"EntryIcon": base.EntryIcon,
"MigrationIcon": MigrationIcon,
"Add": func(a, b int) int {
return a + b
},
@@ -357,13 +358,15 @@ func NewTextFuncMap() []texttmpl.FuncMap {
"AppDomain": func() string {
return setting.Domain
},
"TimeSince": timeutil.TimeSince,
"TimeSinceUnix": timeutil.TimeSinceUnix,
"TimeSinceUnix1": timeutil.TimeSinceUnix1,
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort,
"RawTimeSince": timeutil.RawTimeSince,
"AttachmentResourceType": dataset.GetResourceType,
"AttachmentStatus": dataset.GetStatusText,
"TimeSince": timeutil.TimeSince,
"TimeSinceUnix": timeutil.TimeSinceUnix,
"TimeSinceUnix1": timeutil.TimeSinceUnix1,
"TimeSinceUnixShort": timeutil.TimeSinceUnixShort,
"RawTimeSince": timeutil.RawTimeSince,
"AttachmentResourceType": dataset.GetResourceType,
"AttachmentStatus": dataset.GetStatusText,
"IsShowDataSetOfCurrentRepo": dataset.IsShowDataSetOfCurrentRepo,

"DateFmtLong": func(t time.Time) string {
return t.Format(time.RFC1123Z)
},


+ 8
- 0
options/locale/locale_en-US.ini View File

@@ -98,6 +98,7 @@ error500= Sorry, the site has encountered some problems, we are trying to <stron
[error]
occurred = An error has occurred
report_message = An error has occurred
no_right=You have no right to do the operation.

[install]
install = Installation
@@ -837,6 +838,8 @@ category = Category
no_category = No Category
task = Task
no_task = No Task
reference_dataset_fail=Failed to reference dataset, please try again later.
cancel_reference_dataset_fail=Failed to cancel reference dataset, please try again later.
license = License
no_license = No License
file = Dataset File
@@ -949,6 +952,11 @@ unzip_failed=Unzip Failed
unzip_stared=Unzipping
unzip_status=Unzip Status
collection_num=Collection Nums
current_dataset=Current Dataset
linked_dataset=Linked Dataset
unfavorite=Unfavorite
favorite=Favorite
disassociate=Disassociate
[repo]
owner = Owner
repo_name = Repository Name


+ 11
- 0
options/locale/locale_zh-CN.ini View File

@@ -99,6 +99,7 @@ error500=抱歉,站点遇到一些问题,我们正尝试<strong>修复网页
[error]
occurred=发生错误
report_message=发生错误
no_right=您没有权限执行本操作。

[install]
install=安装页面
@@ -832,6 +833,10 @@ create_dataset=创建数据集
create_dataset_fail=创建数据集失败。
query_dataset_fail=查询数据集失败。
edit_attachment_fail=修改描述失败。

reference_dataset_fail=关联数据集失败,请稍后再试。
cancel_reference_dataset_fail=取消关联数据集失败,请稍后再试。

download_url=数据集下载地址
download_copy=复制链接
download_oper=操作
@@ -953,6 +958,12 @@ unzip_failed=解压失败
unzip_stared=解压中
unzip_status=解压状态
collection_num=收藏数量
current_dataset=当前数据集
linked_dataset=关联数据集
unfavorite=取消收藏
favorite=收藏
disassociate=取消关联

[repo]
owner=拥有者
repo_name=项目名称


+ 1
- 1
routers/api/v1/repo/cloudbrain_dashboard.go View File

@@ -764,7 +764,7 @@ func GetCloudbrainsDetailData(ctx *context.Context) {

taskDetail.WaitTime = repo.GetCloudbrainWaitTime(ciTasks[i].Cloudbrain)

if ciTasks[i].Cloudbrain.DeletedAt != nilTime {
if ciTasks[i].Cloudbrain.DeletedAt != nilTime || ciTasks[i].Repo == nil {
taskDetail.IsDelete = true
} else {
taskDetail.IsDelete = false


+ 5
- 14
routers/home.go View File

@@ -296,11 +296,10 @@ func ExploreDatasets(ctx *context.Context) {
// ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled

var (
datasets []*models.Dataset
datasetsWithStar []*models.DatasetWithStar
count int64
err error
orderBy models.SearchOrderBy
datasets []*models.Dataset
count int64
err error
orderBy models.SearchOrderBy
)
page := ctx.QueryInt("page")
if page <= 0 {
@@ -379,14 +378,6 @@ func ExploreDatasets(ctx *context.Context) {
ctx.ServerError("SearchDatasets", err)
return
}
for _, dataset := range datasets {
if !ctx.IsSigned {
datasetsWithStar = append(datasetsWithStar, &models.DatasetWithStar{Dataset: *dataset, IsStaring: false})
} else {
datasetsWithStar = append(datasetsWithStar, &models.DatasetWithStar{Dataset: *dataset, IsStaring: models.IsDatasetStaring(ctx.User.ID, dataset.ID)})
}

}

pager := context.NewPagination(int(count), opts.PageSize, page, 5)
ctx.Data["Keyword"] = opts.Keyword
@@ -397,7 +388,7 @@ func ExploreDatasets(ctx *context.Context) {
pager.SetDefaultParams(ctx)
ctx.Data["Page"] = pager

ctx.Data["Datasets"] = datasetsWithStar
ctx.Data["Datasets"] = repository.ConvertToDatasetWithStar(ctx, datasets)
ctx.Data["Total"] = count
ctx.Data["PageIsDatasets"] = true
ctx.HTML(200, tplExploreDataset)


+ 115
- 11
routers/repo/dataset.go View File

@@ -9,6 +9,8 @@ import (
"strings"
"unicode/utf8"

"code.gitea.io/gitea/services/repository"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
@@ -22,6 +24,7 @@ const (
tplDatasetCreate base.TplName = "repo/datasets/create"
tplDatasetEdit base.TplName = "repo/datasets/edit"
taskstplIndex base.TplName = "repo/datasets/tasks/index"
tplReference base.TplName = "repo/datasets/reference"
)

// MustEnableDataset check if repository enable internal dataset
@@ -267,6 +270,37 @@ func CreateDatasetPost(ctx *context.Context, form auth.CreateDatasetForm) {
}

}
func ReferenceDatasetDelete(ctx *context.Context) {
repoID := ctx.Repo.Repository.ID
datasetId, _ := strconv.ParseInt(ctx.Params(":id"), 10, 64)

oldDatasetIds := models.GetDatasetIdsByRepoID(repoID)

var newDatasetIds []int64

for _, tempDatasetId := range oldDatasetIds {
if datasetId != tempDatasetId {
newDatasetIds = append(newDatasetIds, tempDatasetId)
}
}
err := models.NewDatasetIdsByRepoID(repoID, newDatasetIds)
if err != nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessage("dataset.cancel_reference_dataset_fail"))
}
ctx.JSON(http.StatusOK, models.BaseOKMessage)

}

func ReferenceDatasetPost(ctx *context.Context, form auth.ReferenceDatasetForm) {
repoID := ctx.Repo.Repository.ID
err := models.NewDatasetIdsByRepoID(repoID, form.DatasetID)
if err != nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessage("dataset.reference_dataset_fail"))
}

ctx.JSON(http.StatusOK, models.BaseOKMessage)

}

func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) {
ctx.Data["PageIsDataset"] = true
@@ -412,18 +446,17 @@ func MyDatasets(ctx *context.Context) {

func datasetMultiple(ctx *context.Context, opts *models.SearchDatasetOptions) {
page := ctx.QueryInt("page")
cloudbrainType := ctx.QueryInt("type")
keyword := strings.Trim(ctx.Query("q"), " ")
orderBy := models.SearchOrderByRecentUpdated
opts.Keyword = keyword
opts.SearchOrderBy = orderBy
if opts.SearchOrderBy.String() == "" {
opts.SearchOrderBy = models.SearchOrderByRecentUpdated
}

opts.RecommendOnly = ctx.QueryBool("recommend")
opts.CloudBrainType = cloudbrainType
opts.ListOptions = models.ListOptions{
Page: page,
PageSize: setting.UI.DatasetPagingNum,
}
opts.NeedAttachment = true
opts.JustNeedZipFile = true
opts.User = ctx.User

@@ -449,22 +482,52 @@ func datasetMultiple(ctx *context.Context, opts *models.SearchDatasetOptions) {
"data": string(data),
"count": strconv.FormatInt(count, 10),
})

}

func CurrentRepoDatasetMultiple(ctx *context.Context) {

datasetIds := models.GetDatasetIdsByRepoID(ctx.Repo.Repository.ID)
searchOrderBy := getSearchOrderByInValues(datasetIds)
opts := &models.SearchDatasetOptions{
RepoID: ctx.Repo.Repository.ID,
RepoID: ctx.Repo.Repository.ID,
NeedAttachment: true,
CloudBrainType: ctx.QueryInt("type"),
DatasetIDs: datasetIds,
SearchOrderBy: searchOrderBy,
}

datasetMultiple(ctx, opts)

}

func getSearchOrderByInValues(datasetIds []int64) models.SearchOrderBy {
if len(datasetIds) == 0 {
return ""
}
searchOrderBy := "CASE id "
for i, id := range datasetIds {
searchOrderBy += fmt.Sprintf(" WHEN %d THEN %d", id, i+1)
}
searchOrderBy += " ELSE 0 END"
return models.SearchOrderBy(searchOrderBy)
}

func MyDatasetsMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
UploadAttachmentByMe: true,
NeedAttachment: true,
CloudBrainType: ctx.QueryInt("type"),
}
datasetMultiple(ctx, opts)

}

func ReferenceDatasetAvailable(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
PublicOnly: true,
NeedAttachment: false,
CloudBrainType: models.TypeCloudBrainAll,
}
datasetMultiple(ctx, opts)

@@ -473,7 +536,9 @@ func MyDatasetsMultiple(ctx *context.Context) {
func PublicDatasetMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
PublicOnly: true,
PublicOnly: true,
NeedAttachment: true,
CloudBrainType: ctx.QueryInt("type"),
}
datasetMultiple(ctx, opts)

@@ -482,11 +547,50 @@ func PublicDatasetMultiple(ctx *context.Context) {
func MyFavoriteDatasetMultiple(ctx *context.Context) {

opts := &models.SearchDatasetOptions{
StarByMe: true,
DatasetIDs: models.GetDatasetIdsStarByUser(ctx.User.ID),
StarByMe: true,
DatasetIDs: models.GetDatasetIdsStarByUser(ctx.User.ID),
NeedAttachment: true,
CloudBrainType: ctx.QueryInt("type"),
}
datasetMultiple(ctx, opts)
}
func ReferenceDataset(ctx *context.Context) {
MustEnableDataset(ctx)
ctx.Data["PageIsDataset"] = true
ctx.Data["MaxReferenceDatasetNum"] = setting.RepoMaxReferenceDatasetNum
ctx.Data["CanWrite"] = ctx.Repo.CanWrite(models.UnitTypeDatasets)
ctx.HTML(200, tplReference)

}

func ReferenceDatasetData(ctx *context.Context) {
MustEnableDataset(ctx)
datasetIds := models.GetDatasetIdsByRepoID(ctx.Repo.Repository.ID)
var datasets models.DatasetList
var err error
if len(datasetIds) > 0 {

opts := &models.SearchDatasetOptions{
DatasetIDs: datasetIds,
NeedAttachment: false,
CloudBrainType: models.TypeCloudBrainAll,
ListOptions: models.ListOptions{
Page: 1,
PageSize: setting.RepoMaxReferenceDatasetNum,
},
SearchOrderBy: getSearchOrderByInValues(datasetIds),
QueryReference: true,
}
datasets, _, err = models.SearchDataset(opts)
if err != nil {
ctx.ServerError("SearchDatasets", err)
return
}
}

ctx.JSON(http.StatusOK, repository.ConvertToDatasetWithStar(ctx, datasets))

}

func PublicDataset(ctx *context.Context) {
page := ctx.QueryInt("page")


+ 9
- 0
routers/routes/routes.go View File

@@ -676,6 +676,9 @@ func RegisterRoutes(m *macaron.Macaron) {
reqRepoIssuesOrPullsReader := context.RequireRepoReaderOr(models.UnitTypeIssues, models.UnitTypePullRequests)
reqRepoDatasetReader := context.RequireRepoReader(models.UnitTypeDatasets)
reqRepoDatasetWriter := context.RequireRepoWriter(models.UnitTypeDatasets)
reqRepoDatasetReaderJson := context.RequireRepoReaderJson(models.UnitTypeDatasets)
reqRepoDatasetWriterJson := context.RequireRepoWriterJson(models.UnitTypeDatasets)

reqRepoCloudBrainReader := context.RequireRepoReader(models.UnitTypeCloudBrain)
reqRepoCloudBrainWriter := context.RequireRepoWriter(models.UnitTypeCloudBrain)
reqRepoModelManageReader := context.RequireRepoReader(models.UnitTypeModelManage)
@@ -1032,10 +1035,14 @@ func RegisterRoutes(m *macaron.Macaron) {

m.Group("/datasets", func() {
m.Get("", reqRepoDatasetReader, repo.DatasetIndex)
m.Get("/reference_datasets", reqRepoDatasetReader, repo.ReferenceDataset)
m.Get("/reference_datasets_data", reqRepoDatasetReaderJson, repo.ReferenceDatasetData)
m.Delete("/reference_datasets/:id", reqRepoDatasetWriterJson, repo.ReferenceDatasetDelete)
m.Put("/:id/:action", reqRepoDatasetReader, repo.DatasetAction)
m.Get("/create", reqRepoDatasetWriter, repo.CreateDataset)
m.Post("/create", reqRepoDatasetWriter, bindIgnErr(auth.CreateDatasetForm{}), repo.CreateDatasetPost)
m.Get("/edit/:id", reqRepoDatasetWriter, repo.EditDataset)
m.Post("/reference_datasets", reqRepoDatasetWriterJson, bindIgnErr(auth.ReferenceDatasetForm{}), repo.ReferenceDatasetPost)
m.Post("/edit", reqRepoDatasetWriter, bindIgnErr(auth.EditDatasetForm{}), repo.EditDatasetPost)
m.Get("/current_repo", repo.CurrentRepoDataset)
m.Get("/my_datasets", repo.MyDatasets)
@@ -1045,6 +1052,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/current_repo_m", repo.CurrentRepoDatasetMultiple)
m.Get("/my_datasets_m", repo.MyDatasetsMultiple)
m.Get("/public_datasets_m", repo.PublicDatasetMultiple)

m.Get("/reference_datasets_available", repo.ReferenceDatasetAvailable)
m.Get("/my_favorite_m", repo.MyFavoriteDatasetMultiple)

m.Group("/status", func() {


+ 19
- 0
services/repository/dataset.go View File

@@ -0,0 +1,19 @@
package repository

import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
)

func ConvertToDatasetWithStar(ctx *context.Context, datasets []*models.Dataset) []*models.DatasetWithStar {
var datasetsWithStar []*models.DatasetWithStar
for _, dataset := range datasets {
if !ctx.IsSigned {
datasetsWithStar = append(datasetsWithStar, &models.DatasetWithStar{Dataset: *dataset, IsStaring: false})
} else {
datasetsWithStar = append(datasetsWithStar, &models.DatasetWithStar{Dataset: *dataset, IsStaring: models.IsDatasetStaring(ctx.User.ID, dataset.ID)})
}

}
return datasetsWithStar
}

+ 83
- 61
templates/repo/datasets/index.tmpl View File

@@ -20,7 +20,6 @@
.wrapper {
display: flex;
overflow: hidden;
padding: 0 1rem;
}

.exp {
@@ -40,7 +39,8 @@
}

.exp:checked+.text .btn::after {
content:'{{$.i18n.Tr "org.fold"}}'
content:'{{$.i18n.Tr "org.fold"}}';
color: #3291f8;
}

.wrapper>.text {
@@ -80,7 +80,7 @@
margin-left: 20px;
font-size: 14px;
padding: 0 8px;
background: #3F51B5;
background-color: transparent;
line-height: 20px;
border-radius: 4px;
color: #fff;
@@ -89,7 +89,8 @@
}

.btn::after {
content:'{{$.i18n.Tr "org.unfold"}}'
content:'{{$.i18n.Tr "org.unfold"}}';
color: #3291f8;
}

.btn::before {
@@ -132,6 +133,15 @@
border: 5px solid transparent;
border-top-color: #c0c4cc;
}
.dataset-flavor-button{
display: flex;
align-items: center;
padding: 0.5rem;
border: 1px solid rgba(34,36,38,0.15);
border-top-right-radius: 0;
border-bottom-right-radius: 0;
box-shadow: none
}
</style>
<div class="repository">
{{template "repo/header" .}}
@@ -142,44 +152,59 @@
<div class="item" data-private="{{.IsPrivate}}" data-decompress-state="{{.DecompressState}}"></div>
{{end}}
</div>

<div id="dataset-base">
<div class="ui container">
<div class="ui mobile reversed stackable grid">
<div class="row">
<div class="column thirteen wide">
<h2 class="nowrap">{{.dataset.Title}}</h2>
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/datasets">{{$.i18n.Tr "dataset.current_dataset"}}</a>
<a class="item" href="{{.RepoLink}}/datasets/reference_datasets">{{$.i18n.Tr "dataset.linked_dataset"}}</a>
</div>
<div class="column three wide right aligned">
<span style="display: flex;align-items: center;justify-content: flex-end;height: 36px;">
{{if $.IsSigned}}
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;"
@click="postStar({{.dataset.ID}},'{{.Link}}')">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke"
:class='{stars_active:star_active}'>
<path
d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z">
</path>
</svg>
</div>
<span style="line-height: 1;">${num_stars}</span>
{{else}}
<div style="line-height: 1;margin-right: 4px;margin-bottom: -2px;padding: 0 10px;">
<svg width="1.4em" height="1.4em" viewBox="0 0 32 32" class="heart-stroke"
:class='{stars_active:star_active}'>
<path
d="M4.4 6.54c-1.761 1.643-2.6 3.793-2.36 6.056.24 2.263 1.507 4.521 3.663 6.534a29110.9 29110.9 0 0010.296 9.633l10.297-9.633c2.157-2.013 3.424-4.273 3.664-6.536.24-2.264-.599-4.412-2.36-6.056-1.73-1.613-3.84-2.29-6.097-1.955-1.689.25-3.454 1.078-5.105 2.394l-.4.319-.398-.319c-1.649-1.316-3.414-2.143-5.105-2.394a7.612 7.612 0 00-1.113-.081c-1.838 0-3.541.694-4.983 2.038z">
</path>
</svg>
</div>
<span style="line-height: 1;">${num_stars}</span>
{{end}}
<a style="margin-left:30px;" href="{{.RepoLink}}/datasets/edit/{{.dataset.ID}}"
class="ui primary basic mini {{if not $.CanWrite}} disabled {{end}} button">{{.i18n.Tr "repo.modelarts.modify"}}</a>
</span>
</div>
<div class="row" style="align-items: center;">
<h2 class="nowrap" style="margin: 0;">{{.dataset.Title}}</h2>
<!-- border-top-right-radius: 0;
border-bottom-right-radius: 0; -->
<div style="margin-left: 1.5rem;">
{{if $.IsSigned}}
<button v-if="star_active" class="ui mini basic button" style="display: flex;align-items: center;padding: 0.5rem;border: #888888;border-top-right-radius: 0;border-bottom-right-radius: 0;margin-right: -1px;" @click="postStar({{.dataset.ID}},'{{.Link}}')">
<i class="ri-heart-fill" style="color: #FA8C16;"></i>
<span style="margin-left: 0.3rem;font-size: 0.7rem;">{{$.i18n.Tr "dataset.unfavorite"}}</span>
</button>
<button v-else class="ui mini basic button" style="display: flex;align-items: center;padding:0.5rem;border: #888888;border-top-right-radius: 0;border-bottom-right-radius: 0;margin-right: -1px;" @click="postStar({{.dataset.ID}},'{{.Link}}')">
<i class="ri-heart-line" ></i>
<span style="margin-left: 0.3rem;font-size: 0.7rem;">{{$.i18n.Tr "dataset.favorite"}}</span>
</button>
{{else}}
<button v-if="star_active" class="ui mini basic button" style="display: flex;align-items: center;padding: 0.5rem;border: #888888;border-top-right-radius: 0;border-bottom-right-radius: 0;margin-right: -1px;">
<i class="ri-heart-fill" ></i>
<span style="margin-left: 0.3rem;font-size: 0.7rem;">{{$.i18n.Tr "dataset.unfavorite"}}</span>
</button>
<button v-else class="ui mini basic button" style="display: flex;align-items: center;padding:0.5rem;border: #888888;border-top-right-radius: 0;border-bottom-right-radius: 0;margin-right: -1px;">
<i class="ri-heart-line" style="color: #FA8C16;"></i>
<span style="margin-left: 0.3rem;font-size: 0.7rem;">{{$.i18n.Tr "dataset.favorite"}}</span>
</button>
{{end}}
</div>
<a class="ui mini basic button" style="display: flex;align-items: center;padding: 0.5rem;border: #888888;border-top-left-radius: 0;border-bottom-left-radius: 0;">
${num_stars}
</a>
<a style="margin-left:15px;padding: 0.5rem 1.5rem;" href="{{.RepoLink}}/datasets/edit/{{.dataset.ID}}" class="ui primary basic mini {{if not $.CanWrite}} disabled {{end}} button">{{.i18n.Tr "repo.modelarts.modify"}}</a>
</div>
{{if .dataset.Description}}
<div class="row" style="padding: 0;">
<div class="wrapper">
<input id="exp1" class="exp" type="checkbox">
<div class="text">
<label class="btn" for="exp1"></label>
{{.dataset.Description}}
</div>
</div>
</div>
{{end}}
<div class="row" style="align-items: center;">
{{if or (.dataset.Category) (.dataset.Task) (.dataset.License)}}
<div class="column thirteen wide">
<div class="column ten wide" style="padding:0">
{{if .dataset.Category}}
{{$category := .dataset.Category}}
<a class="ui repo-topic label topic"
@@ -196,21 +221,7 @@
{{end}}
</div>
{{end}}
</div>
{{if .dataset.Description}}
<div class="row" style="padding-top: 0;">
<div class=" wrapper">
<input id="exp1" class="exp" type="checkbox">
<div class="text">
<label class="btn" for="exp1"></label>
{{.dataset.Description}}
</div>
</div>
</div>
{{end}}
<div class="row">
<div class="column ten wide"></div>
<div class="column six wide right aligned">
<div class="column six wide right aligned" style="padding:0">
<el-select v-model="datasetType" style="width: 40%;" size="small" @change="changeDatasetType">
<i slot="prefix" style="display: inline-block;color: #101010;"
class="el-input__icon ri-archive-drawer-line"></i>
@@ -222,7 +233,7 @@
@click="gotoUpload('{{.RepoLink}}',{{.dataset.ID}})">{{$.i18n.Tr "dataset.dataset_upload"}}</el-button>
</div>
</div>
<div class="row">
<div class="row" style="padding-top: 0;">
<div class="ui sixteen wide column dataset">
<div class="ui grid stackable" style="background: #f0f0f0;;">
<div class="row">
@@ -387,16 +398,27 @@
</div>
</div>
{{else}}
<div class="ui placeholder segment bgtask-none">
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{.i18n.Tr "dataset.dataset_no_create"}}</div>
{{if $.CanWrite}}
<a class="ui green button" href="{{.RepoLink}}/datasets/create">{{.i18n.Tr "dataset.create_new_dataset"}}</a>
{{end}}
<div class="bgtask-content">
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_explain"}}</div>
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_instructions_for_use"}}<a
href="https://git.openi.org.cn/zeizei/OpenI_Learning">{{.i18n.Tr "dataset.dataset_camp_course"}}</a></div>
<div class="ui container">
<div class="ui stackable grid">
<div class="row" style="justify-content: space-between">
<div class="ui blue small menu compact selectcloudbrain">
<a class="active item" href="{{.RepoLink}}/datasets">{{$.i18n.Tr "dataset.current_dataset"}}</a>
<a class="item" href="{{.RepoLink}}/datasets/reference_datasets">{{$.i18n.Tr "dataset.linked_dataset"}}</a>
</div>
{{if $.CanWrite}}
<a class="ui green button" href="{{.RepoLink}}/datasets/create">{{$.i18n.Tr "dataset.new_dataset"}}</a>
{{end}}
</div>
</div>
<div class="ui placeholder segment bgtask-none">
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{.i18n.Tr "dataset.dataset_no_create"}}</div>
<div class="bgtask-content">
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_explain"}}</div>
<div class="bgtask-content-txt">{{.i18n.Tr "dataset.dataset_instructions_for_use"}}<a
href="https://git.openi.org.cn/zeizei/OpenI_Learning">{{.i18n.Tr "dataset.dataset_camp_course"}}</a></div>
</div>
</div>
</div>
{{end}}


+ 8
- 0
templates/repo/datasets/reference.tmpl View File

@@ -0,0 +1,8 @@
{{template "base/head" .}}

<div class="repository">
{{template "repo/header" .}}
<div class="reference-dataset" data-repolink="{{.RepoLink}}" data-canwrite="{{.CanWrite}}" data-is-sign="{{$.IsSigned}}" data-max-reference-num="{{.MaxReferenceDatasetNum}}" data-address="{{IsShowDataSetOfCurrentRepo $.Repository.ID}}"></div>
<div id="reference-dataset"></div>
</div>
{{template "base/footer" .}}

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

@@ -138,7 +138,7 @@
{{end}}

{{if .Permission.CanRead $.UnitTypeDatasets}}
<a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets">
<a class="{{if .PageIsDataset}}active{{end}} item" id="header-dataset" href="{{.RepoLink}}{{if IsShowDataSetOfCurrentRepo $.Repository.ID}}/datasets{{else}}/datasets/reference_datasets{{end}}">
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M20.083 15.2l1.202.721a.5.5 0 0 1 0 .858l-8.77 5.262a1 1 0 0 1-1.03 0l-8.77-5.262a.5.5 0 0 1 0-.858l1.202-.721L12 20.05l8.083-4.85zm0-4.7l1.202.721a.5.5 0 0 1 0 .858L12 17.65l-9.285-5.571a.5.5 0 0 1 0-.858l1.202-.721L12 15.35l8.083-4.85zm-7.569-9.191l8.771 5.262a.5.5 0 0 1 0 .858L12 13 2.715 7.429a.5.5 0 0 1 0-.858l8.77-5.262a1 1 0 0 1 1.03 0zM12 3.332L5.887 7 12 10.668 18.113 7 12 3.332z"/></svg>
{{.i18n.Tr "datasets"}}
</a>


+ 735
- 0
web_src/js/components/dataset/referenceDataset.vue View File

@@ -0,0 +1,735 @@
<template>
<div>
<template v-if="showFlag">
<div v-loading="loadingLinkPage">
<div class="ui container">
<div class="ui mobile reversed stackable grid">
<div class="row" style="justify-content: space-between">
<div class="ui blue small menu compact selectcloudbrain">
<a class="item" :href="`${repoLink}/datasets`">{{
i18n.current_dataset
}}</a>
<a
class="active item"
:href="`${repoLink}/datasets/reference_datasets`"
>{{ i18n.linked_datasets }}</a
>
</div>
<button
style="margin-right: 2rem"
class="ui green button"
:class="{ disabled: !canWrite }"
@click="openDataset()"
>
{{ i18n.linked_datasets }}
</button>
</div>
<div class="row">
<div class="ui two cards" style="width: 100%">
<div
class="ui card refer-dataset-card"
v-for="(item, index) in datasetList"
:key="index"
@click="gotoDataset(item)"
>
<div class="content" style="border-bottom: none">
<div class="refer-dataset-card-content">
<div class="refer-dataset-card-title">
<span
:title="item.Title"
class="nowrap"
style="display: inline-block; max-width: 90%"
>{{ item.Title }}</span
><img
v-if="item.Recommend"
src="/img/jian.svg"
style="margin-left: 0.5rem"
/>
</div>
<template v-if="item.IsStaring">
<div style="display: flex">
<button
class="ui mini basic button dataset-card-flavor"
@click.stop="postStar(item, isSigned)"
>
<i class="ri-heart-fill" style="color: #fa8c16"></i>
<span style="margin-left: 0.3rem">{{
i18n.unfavorite
}}</span>
</button>
<a class="ui mini basic button card-flavor-num">
{{ item.NumStars }}
</a>
</div>
</template>
<template v-else>
<div style="display: flex">
<button
class="ui mini basic button dataset-card-flavor"
@click.stop="postStar(item, isSigned)"
>
<i class="ri-heart-line"></i>
<span style="margin-left: 0.3rem">{{
i18n.favorite
}}</span>
</button>
<a class="ui mini basic button card-flavor-num">
{{ item.NumStars }}
</a>
</div>
</template>
</div>
<div style="font-size: 12px; margin-top: 5px">
<a
v-if="item.Category"
:href="'/explore/datasets?category=' + item.Category"
class="ui repo-topic label topic"
>{{ i18n[item.Category] || item.Category }}</a
>
<a
v-if="item.Task"
:href="'/explore/datasets?task=' + item.Task"
class="ui repo-topic label topic"
>{{ i18n[item.Task] || item.Task }}</a
>
<a
v-if="item.License"
:href="'/explore/datasets?license=' + item.License"
class="ui repo-topic label topic"
>{{ item.License }}</a
>
</div>
<div class="description card-flavor-desc">
<p>{{ item.Description }}</p>
</div>
</div>
<div
class="extra content"
style="border-top: none !important"
>
<div style="display: flex; align-items: center">
<a
:href="'/' + item.Repo.OwnerName"
:title="item.Repo.OwnerName"
>
<img
class="ui avatar image"
style="width: 22px; height: 22px"
:src="'/user/avatar/' + item.Repo.OwnerName + '/-1'"
/>
</a>
<span
style="
color: #999999;
font-size: 12px;
margin-left: 0.5rem;
"
>{{ item.CreatedUnix | transformTimestamp }}</span
>
<span
style="
display: flex;
align-items: center;
justify-content: center;
margin: 0 1rem;
"
:title="i18n.citations"
>
<i class="ri-link"></i>
<span
style="
color: #101010;
font-size: 12px;
margin-left: 0.2rem;
"
>{{ item.UseCount }}</span
>
</span>
<span
style="display: flex; align-items: center; flex: 1"
:title="i18n.downloads"
>
<i class="ri-download-line"></i>
<span
style="
color: #101010;
font-size: 12px;
margin-left: 0.2rem;
"
>{{ item.DownloadTimes }}</span
>
</span>
<button
class="ui mini button"
:class="{ disabled1: !canWrite }"
@click.stop="
cancelReferData(item.ID, item.Title, canWrite)
"
>
{{ i18n.disassociate }}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<div class="ui container">
<div class="ui mobile reversed stackable grid">
<div class="row" style="justify-content: space-between">
<div class="ui blue small menu compact selectcloudbrain">
<a class="item" :href="`${repoLink}/datasets`">{{
i18n.current_dataset
}}</a>
<a
class="active item"
:href="`${repoLink}/datasets/reference_datasets`"
>{{ i18n.linked_datasets }}</a
>
</div>
<button class="ui green button" @click="openDataset()">
{{ i18n.linked_datasets }}
</button>
</div>
</div>
<div class="ui placeholder segment bgtask-none">
<div class="ui icon header bgtask-header-pic"></div>
<div class="bgtask-content-header">{{ i18n.not_link_dataset }}</div>
<div class="bgtask-content">
<div class="bgtask-content-txt">
{{ i18n.no_link_dataset_tips1 }}
</div>
<div class="bgtask-content-txt">
{{ i18n.dataset_instructions_for_use
}}<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">{{
i18n.dataset_camp_course
}}</a>
</div>
</div>
</div>
</div>
</template>

<el-dialog
:title="i18n.linked_datasets"
:visible.sync="dialogVisible"
:width="dialogWidth"
@closed="refreshData"
>
<div class="ui icon input dataset-search-vue">
<i
class="search icon"
style="cursor: pointer; pointer-events: auto"
@click="searchName"
></i>
<input
type="text"
:placeholder="i18n.search_dataset"
v-model="search"
@keydown.enter.stop.prevent="searchName"
/>
</div>
<el-row>
<el-col
:span="17"
style="
padding-right: 1rem;
border-right: 1px solid #f5f5f6;
position: relative;
"
>
<el-tabs v-model="activeName">
<el-tab-pane :label="i18n.public_dataset" name="first">
<el-row v-loading="loadingPublicPage">
<el-checkbox-group
v-model="checkList"
style="font-size: 14px; line-height: 1"
>
<div
v-for="(item, index) in publicDatasetList"
:key="index"
class="select-data-wrap"
>
<div class="dataset-header-vue">
<el-checkbox
:label="item.ID"
@change="(checked) => changeCheckbox(checked, item)"
:title="item.Title"
class="select-data-title"
style="display: flex; align-items: end"
><span class="ref-data-title">
<span
style="overflow: hidden; text-overflow: ellipsis"
>
{{ item.Title }}
</span>
<img
v-if="item.Recommend"
src="/img/jian.svg"
style="margin-left: 0.5rem"
/> </span
></el-checkbox>
<a
class="select-data-title select-data-href"
:href="`/${item.Repo.OwnerName}/${item.Repo.Name}/datasets`"
:title="`${item.Repo.OwnerName}/${item.Repo.Alias}`"
style="font-size: 12px"
>{{ item.Repo.OwnerName }}/{{ item.Repo.Alias }}</a
>
</div>
<div class="data-multiple-wrap" :title="item.Description">
{{ item.Description }}
</div>
</div>
</el-checkbox-group>
</el-row>
<div
class="ui container"
style="margin-top: 25px; text-align: center"
>
<el-pagination
background
@current-change="currentChange"
:current-page="currentPage"
:page-size="5"
layout="total, prev, pager, next"
:total="totalNum"
>
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</el-col>
<el-col
:span="7"
style="
display: flex;
flex-direction: column;
height: 100%;
right: 0;
position: absolute;
padding: 0 1.5rem;
"
>
<div
style="
font-size: 14px;
height: 40px;
text-align: left;
color: #0066ff;
line-height: 40px;
"
>
{{ i18n.selected_data_file }}
</div>
<div
style="
flex: 1;
margin-top: 1.5rem;
margin-bottom: 1rem;
overflow-y: auto;
"
>
<el-checkbox-group v-model="checkList">
<el-checkbox
v-for="(item, index) in selectDatasetArray"
:key="index"
:label="item.ID"
:title="item.Title"
@change="(checked) => changeCheckSelected(checked, item)"
style="display: flex; margin: 0.5rem 0"
><span class="select-data-right">{{
item.Title
}}</span></el-checkbox
>
</el-checkbox-group>
</div>
<div style="text-align: end">
<el-button
@click.native="confirmDataset"
size="small"
style="
background: #389e0d;
color: #fff;
border: 1px solid #389e0d;
"
>{{ i18n.sure }}</el-button
>
</div>
</el-col>
</el-row>
</el-dialog>
</div>
</template>

<script>
const { _AppSubUrl, _StaticUrlPrefix, csrf } = window.config;

export default {
components: {},
data() {
return {
dialogWidth: "65%",
dialogVisible: false,
activeName: "first",
repoLink: "",
datasetList: [],
test: false,
checkList: [],
publicDatasetList: [],
showFlag: true,
search: "",
selectDatasetArray: [],
paramsPublics: { page: 1, q: "" },

i18n: {},

totalNum: 0,
currentPage: 1,
loadingLinkPage: false,
loadingPublicPage: false,
canWrite: true,
isSigned: false,
maxReferenceNum: 20,
isCurrentUrl: true,
};
},
methods: {
openDataset() {
this.checkList = this.datasetList.map((item) => {
this.selectDatasetArray.push({ ID: item.ID, Title: item.Title });
return item.ID;
});
this.dialogVisible = true;
this.getDatasetList();
},
refreshData() {
this.checkList = [];
this.selectDatasetArray = [];
},
gotoDataset(item) {
window.open(`/${item.Repo.OwnerName}/${item.Repo.Name}/datasets`);
},
currentChange(page) {
this.paramsPublics.page = page;
this.getDatasetList();
},
searchName() {
this.paramsPublics.q = this.search;
this.paramsPublics.page = 1;
this.getDatasetList();
},
cancelReferData(id, name, canWrite) {
if (!canWrite) {
return;
}
let url = `${this.repoLink}/datasets/reference_datasets/${id}`;
this.$axios
.delete(url)
.then((res) => {
if (res.data.Code === 0) {
this.$message.success(this.i18n.cancel_link_dataset.format(name));
let index = this.datasetList.findIndex((item) => {
return item.ID === id;
});
this.datasetList.splice(index, 1);
if (this.datasetList.length === 0) {
this.showFlag = false;
}
} else {
this.$message.error(res.data.Message);
}
})
.catch((err) => {
this.$message.error(this.i18n.dataset_link_failed);
console.log(err);
});
},
confirmDataset() {
this.submitReferDataset();
this.dialogVisible = false;
},
changeCheckbox(checked, item) {
if (this.checkList.length > this.maxReferenceNum) {
this.checkList.pop();
this.$message.error(
this.i18n.dataset_over_nums.format(this.maxReferenceNum)
);
return;
}
if (this.checkList.length === this.maxReferenceNum && !checked) {
this.$message.error(
this.i18n.dataset_over_nums.format(this.maxReferenceNum)
);
return;
}
if (checked) {
this.selectDatasetArray.push({ ID: item.ID, Title: item.Title });
} else {
let index = this.selectDatasetArray.findIndex((element) => {
return element.ID === item.ID;
});
this.selectDatasetArray.splice(index, 1);
}
},
changeCheckSelected(checked, item) {
if (!checked) {
let index = this.selectDatasetArray.findIndex((element) => {
return element.ID === item.ID;
});
this.selectDatasetArray.splice(index, 1);
}
},
postStar(item, isSigned) {
if (!isSigned) {
return;
}
if (item.IsStaring) {
let url = `${this.repoLink}/datasets/${item.ID}/unstar`;
this.$axios.put(url).then((res) => {
if (res.data.Code === 0) {
this.datasetList.forEach((element, i) => {
if (element.ID === item.ID) {
this.datasetList[i].NumStars -= 1;
this.datasetList[i].IsStaring = !this.datasetList[i].IsStaring;
}
});
}
});
} else {
let url = `${this.repoLink}/datasets/${item.ID}/star`;
this.$axios.put(url).then((res) => {
if (res.data.Code === 0) {
this.datasetList.forEach((element, i) => {
if (element.ID === item.ID) {
this.datasetList[i].NumStars += 1;
this.datasetList[i].IsStaring = !this.datasetList[i].IsStaring;
}
});
}
});
}
},

getSelectDatasetList() {
this.loadingLinkPage = true;
let url = `${this.repoLink}/datasets/reference_datasets_data`;
this.$axios.get(url).then((res) => {
this.loadingLinkPage = false;
if (!res.data) {
this.showFlag = false;
this.datasetList = [];
return;
} else {
this.datasetList = res.data;
this.datasetList.length
? (this.showFlag = true)
: (this.showFlag = false);
}
});
},
getDatasetList() {
this.loadingPublicPage = true;
let url = `${this.repoLink}/datasets/reference_datasets_available`;
this.$axios
.get(url, {
params: this.paramsPublics,
})
.then((res) => {
this.publicDatasetList = JSON.parse(res.data.data);
this.totalNum = parseInt(res.data.count);
this.loadingPublicPage = false;
});
},
submitReferDataset() {
if (this.checkList.length > this.maxReferenceNum) {
this.$message.error(
this.i18n.dataset_over_nums.format(this.maxReferenceNum)
);
return;
}
let url = `${this.repoLink}/datasets/reference_datasets`;
let data = this.qs.stringify(
{
_csrf: csrf,
dataset_id: this.checkList,
},
{ arrayFormat: "repeat" }
);
this.$axios
.post(url, data)
.then((res) => {
if (res.data.Code === 0) {
this.$message.success(this.i18n.dataset_link_success);
this.getSelectDatasetList();
} else {
this.$message.error(res.data.Message);
}
})
.catch((err) => {
this.$message.error(this.i18n.dataset_link_failed);
console.log(err);
});
},
},

filters: {
transformTimestamp(timestamp) {
const date = new Date(parseInt(timestamp) * 1000);
const Y = date.getFullYear() + "-";
const M =
(date.getMonth() + 1 < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1) + "-";
const D =
(date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";

const dateString = Y + M + D;
return dateString;
},
},
watch: {
search(val) {
if (!val) {
this.searchName();
}
},
showFlag(val) {
if (!val || this.isCurrentUrl) {
document
.getElementById("header-dataset")
.setAttribute("href", this.repoLink + "/datasets");
} else {
document
.getElementById("header-dataset")
.setAttribute("href", this.repoLink + "/datasets/reference_datasets");
}
},
},
mounted() {
this.getSelectDatasetList();
},
created() {
this.repoLink = $(".reference-dataset").data("repolink") || "";
this.canWrite = $(".reference-dataset").data("canwrite");
this.isSigned = $(".reference-dataset").data("is-sign");
this.maxReferenceNum = $(".reference-dataset").data("max-reference-num");
this.isCurrentUrl = $(".reference-dataset").data("address");
if (document.documentElement.attributes["lang"].nodeValue == "en-US") {
this.i18n = this.$locale.US;
} else {
this.i18n = this.$locale.CN;
}
},
beforeDestroy() {},
};
</script>

<style scoped>
.dataset-search-vue {
z-index: 9999;
position: absolute;
right: 31%;
height: 30px;
top: 60px;
}
.refer-dataset-card {
cursor: pointer;
box-shadow: 0px 4px 4px 0px rgba(232, 232, 232, 0.6);
border: 1px solid rgba(232, 232, 232, 1);
}
.refer-dataset-card .refer-dataset-card-content {
font-size: 16px;
color: #0366d6;
font-family: SourceHanSansSC-medium;
height: 34px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: space-between;
}
.refer-dataset-card-title {
display: flex;
align-items: center;
max-width: 80%;
width: 100%;
}
.dataset-card-flavor {
display: flex;
align-items: center;
padding: 0.3rem 0.5rem;
border: #888888;
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
margin-right: -1px;
}
.card-flavor-num {
padding: 0.5rem;
border: #888888;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
cursor: default !important;
}
.card-flavor-desc {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
display: -webkit-box;
overflow: hidden;
color: #999999;
font-size: 14px;
margin-top: 10px;
}
.select-data-wrap {
padding: 1rem 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.select-data-title {
flex: 1;
overflow: hidden;
}
.select-data-title .ref-data-title {
font-size: 18px;
color: #454545;
font-weight: 700;
display: flex;
align-items: baseline;
max-width: 100%;
}
.select-data-href {
text-align: right;
text-overflow: ellipsis;
max-width: 35%;
word-break: initial;
margin-left: 1rem;
}
/deep/ .el-checkbox-group .el-checkbox .el-checkbox__label {
display: flex;
max-width: 90%;
}
.select-data-right {
overflow: hidden;
vertical-align: middle;
text-overflow: ellipsis;
max-width: 100%;
display: inline-block;
}
.data-multiple-wrap {
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
display: -webkit-box;
max-width: 100%;
overflow: hidden;
padding-top: 1rem;
color: #888888;
font: 12px;
line-height: 20px;
margin-left: 2rem;
}
.disabled1 {
opacity: 0.45 !important;
}
</style>

+ 9
- 0
web_src/js/components/dataset/selectDataset.vue View File

@@ -141,6 +141,15 @@
class="dataset-repolink dataset-nowrap"
@click.stop="return false;"
>
<i
class="ri-links-line"
style="color: #21ba45; margin-right: 0.3rem"
title="关联数据集"
v-if="
'/' + data.Repo.OwnerName + '/' + data.Repo.Name !==
repoLink
"
></i>
<a
:href="
'/' +


+ 123
- 0
web_src/js/features/i18nVue.js View File

@@ -0,0 +1,123 @@
export const i18nVue = {
CN: {
computer_vision: "计算机视觉",
natural_language_processing: "自然语言处理",
speech_processing: "语音处理",
computer_vision_natural_language_processing: "计算机视觉、自然语言处理",
machine_translation: "机器翻译",
question_answering_system: "问答系统",
information_retrieval: "信息检索",
knowledge_graph: "知识图谱",
text_annotation: "文本标注",
text_categorization: "文本分类",
emotion_analysis: "情感分析",
language_modeling: "语言建模",
speech_recognition: "语音识别",
automatic_digest: "自动文摘",
information_extraction: "信息抽取",
description_generation: "说明生成",
image_classification: "图像分类",
face_recognition: "人脸识别",
image_search: "图像搜索",
target_detection: "目标检测",
image_description_generation: "图像描述生成",
vehicle_license_plate_recognition: "车辆车牌识别",
medical_image_analysis: "医学图像分析",
unmanned: "无人驾驶",
unmanned_security: "无人安防",
drone: "无人机",
vr_ar: "VR/AR",
"2_d_vision": "2-D视觉",
"2_5_d_vision": "2.5-D视觉",
"3_d_reconstruction": "3D重构",
image_processing: "图像处理",
video_processing: "视频处理",
visual_input_system: "视觉输入系统",
speech_coding: "语音编码",
speech_enhancement: "语音增强",
speech_recognition: "语音识别",
speech_synthesis: "语音合成",
current_dataset: "当前数据集",
linked_datasets: "关联数据集",
unfavorite: "取消收藏",
favorite: "收藏",
disassociate: "取消关联",
public_dataset: "公开数据集",
selected_data_file: "已选数据集",
sure: "确定",
search_dataset: "搜数据集名称/描述...",
citations: "引用次数",
downloads: "下载次数",
not_link_dataset: "还未关联过数据集",
no_link_dataset_tips1:
"您可以通过单击新建关联数据集按钮,将平台上公开数据集展示在这里。",
dataset_instructions_for_use: "使用说明:可以参考启智AI协作平台",
dataset_camp_course: "小白训练营课程",
dataset_link_success: "关联数据集成功!",
dataset_link_failed: "关联数据集失败!",
dataset_over_nums: "关联超过?个数据集",
cancel_link_dataset: "取消?关联数据集成功!",
},
US: {
computer_vision: "computer vision",
natural_language_processing: "natural language processing",
speech_processing: "speech processing",
computer_vision_natural_language_processing:
"computer vision and natural language processing",
machine_translation: "machine translation",
question_answering_system: "question answering system",
information_retrieval: "information retrieval",
knowledge_graph: "knowledge graph",
text_annotation: "text annotation",
text_categorization: "text categorization",
emotion_analysis: "emotion analysis",
language_modeling: "language modeling",
speech_recognition: "speech recognition",
automatic_digest: "automatic digest",
information_extraction: "information extraction",
description_generation: "description generation",
image_classification: "image classification",
face_recognition: "face recognition",
image_search: "image search",
target_detection: "target detection",
image_description_generation: "image description generation",
vehicle_license_plate_recognition: "vehicle license plate recognition",
medical_image_analysis: "medical image analysis",
unmanned: "unmanned",
unmanned_security: "unmanned security",
drone: "drone",
vr_ar: "VR/AR",
"2_d_vision": "2.D vision",
"2.5_d_vision": "2.5D vision",
"3_d_reconstruction": "3Dreconstruction",
image_processing: "image processing",
video_processing: "video processing",
visual_input_system: "visual input system",
speech_coding: "speech coding",
speech_enhancement: "speech enhancement",
speech_recognition: "speech recognition",
speech_synthesis: "speech synthesis",
current_dataset: "Current Dataset",
linked_datasets: "Linked Datasets",
unfavorite: "Unfavorite",
favorite: "Favorite",
disassociate: "Disassociate",
public_dataset: "Public Dataset",
selected_data_file: "Selected DataSets",
sure: "Ok",
search_dataset: "Search dataset name/description ...",
citations: "Citations",
downloads: "Downloads",
not_link_dataset: "No datasets have been associated yet",
no_link_dataset_tips1:
"You can display public datasets on the platform here by clicking the New Linked Dataset button.",

dataset_instructions_for_use:
"Instructions for use: You can refer to Qizhi AI Collaboration Platform ",
dataset_camp_course: "Newcomer Training Camp Course",
dataset_link_success: "Linked dataset succeeded!",
dataset_link_failed: "Linked dataset Failed!",
dataset_over_nums: "Linked over ? datasets!",
cancel_link_dataset: "Cancel ? Linked dataset succeeded!",
},
};

+ 15
- 0
web_src/js/index.js View File

@@ -46,15 +46,19 @@ import initCloudrain from "./features/cloudrbanin.js";
import initCloudrainSow from "./features/cloudbrainShow.js";
import initImage from "./features/images.js";
import selectDataset from "./components/dataset/selectDataset.vue";
import referenceDataset from "./components/dataset/referenceDataset.vue";
// import $ from 'jquery.js'
import router from "./router/index.js";
import { Message } from "element-ui";

import { i18nVue } from "./features/i18nVue.js";

Vue.use(ElementUI);
Vue.prototype.$axios = axios;
Vue.prototype.$Cookies = Cookies;
Vue.prototype.qs = qs;
Vue.prototype.$message = Message;
Vue.prototype.$locale = i18nVue;
const { AppSubUrl, StaticUrlPrefix, csrf } = window.config;

Object.defineProperty(Vue.prototype, "$echarts", {
@@ -2900,6 +2904,7 @@ $(document).ready(async () => {
initVueDataAnalysis();
initVueWxAutorize();
initVueselectDataset();
initVuereferenceDataset();
initTeamSettings();
initCtrlEnterSubmit();
initNavbarContentToggle();
@@ -4532,6 +4537,16 @@ function initVueselectDataset() {
render: (h) => h(selectDataset),
});
}
function initVuereferenceDataset() {
const el = document.getElementById("reference-dataset");
if (!el) {
return;
}
new Vue({
el: el,
render: (h) => h(referenceDataset),
});
}
window.timeAddManual = function () {
$(".mini.modal")
.modal({


Loading…
Cancel
Save