@@ -2,6 +2,7 @@ package models | |||
import ( | |||
"fmt" | |||
"sort" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"xorm.io/builder" | |||
@@ -129,3 +130,63 @@ func SearchDatasetByCondition(opts *SearchDatasetOptions, cond builder.Cond) (Da | |||
return repos, 0, nil | |||
} | |||
type datasetMetaSearch struct { | |||
ID []int64 | |||
Rel []*Dataset | |||
} | |||
func (s datasetMetaSearch) Len() int { | |||
return len(s.ID) | |||
} | |||
func (s datasetMetaSearch) Swap(i, j int) { | |||
s.ID[i], s.ID[j] = s.ID[j], s.ID[i] | |||
s.Rel[i], s.Rel[j] = s.Rel[j], s.Rel[i] | |||
} | |||
func (s datasetMetaSearch) Less(i, j int) bool { | |||
return s.ID[i] < s.ID[j] | |||
} | |||
func GeDatasetAttachments(rels ...*Dataset) (err error) { | |||
return geDatasetAttachments(x, rels...) | |||
} | |||
func geDatasetAttachments(e Engine, rels ...*Dataset) (err error) { | |||
if len(rels) == 0 { | |||
return | |||
} | |||
// To keep this efficient as possible sort all datasets by id, | |||
// select attachments by dataset id, | |||
// then merge join them | |||
// Sort | |||
var sortedRels = datasetMetaSearch{ID: make([]int64, len(rels)), Rel: make([]*Dataset, len(rels))} | |||
var attachments []*Attachment | |||
for index, element := range rels { | |||
element.Attachments = []*Attachment{} | |||
sortedRels.ID[index] = element.ID | |||
sortedRels.Rel[index] = element | |||
} | |||
sort.Sort(sortedRels) | |||
// Select attachments | |||
err = e. | |||
Asc("dataset_id"). | |||
In("dataset_id", sortedRels.ID). | |||
Find(&attachments, Attachment{}) | |||
if err != nil { | |||
return err | |||
} | |||
// merge join | |||
var currentIndex = 0 | |||
for _, attachment := range attachments { | |||
for sortedRels.ID[currentIndex] < attachment.DatasetID { | |||
currentIndex++ | |||
} | |||
sortedRels.Rel[currentIndex].Attachments = append(sortedRels.Rel[currentIndex].Attachments, attachment) | |||
} | |||
return | |||
} |
@@ -13,6 +13,7 @@ type CreateDatasetForm struct { | |||
License string `binding:"Required;MaxSize(64)"` | |||
Task string `binding:"Required;MaxSize(64)"` | |||
ReleaseID int64 `xorm:"INDEX"` | |||
Status bool | |||
Files []string | |||
} | |||
@@ -23,7 +24,8 @@ type EditDatasetForm struct { | |||
Description string `binding:"Required;MaxSize(254)"` | |||
License string `binding:"Required;MaxSize(64)"` | |||
Task string `binding:"Required;MaxSize(64)"` | |||
ReleaseID int64 `xorm:"INDEX"` | |||
Status bool | |||
ReleaseID int64 `xorm:"INDEX"` | |||
Files []string | |||
} | |||
@@ -621,6 +621,7 @@ email_notifications.disable = Disable Email Notifications | |||
email_notifications.submit = Set Email Preference | |||
[dataset] | |||
dataset = Dataset | |||
title = Name | |||
description = Description | |||
create_dataset = Create Dataset | |||
@@ -628,6 +629,16 @@ category = Category | |||
task = Task | |||
license = license | |||
file = Dataset File | |||
download = download | |||
edit = edit | |||
private = private | |||
public = public | |||
back = back | |||
visibility = visibility | |||
visibility_description = Only the owner or the organization members if they have rights, will be able to see it. | |||
visibility_helper = Make Dataset Private | |||
visibility_helper_forced = Your site administrator forces new datasets to be private. | |||
visibility_fork_helper = (Changing this will affect all forks.) | |||
[repo] | |||
owner = Owner | |||
@@ -620,13 +620,24 @@ email_notifications.disable=停用邮件通知 | |||
email_notifications.submit=邮件通知设置 | |||
[dataset] | |||
title = 名称 | |||
description = 描述 | |||
create_dataset = 创建数据集 | |||
category = 分类 | |||
task = 针对的具体任务 | |||
license = license | |||
file = 数据集文件 | |||
dataset=数据集 | |||
title=名称 | |||
description=描述 | |||
create_dataset=创建数据集 | |||
category=分类 | |||
task=针对的具体任务 | |||
license=license | |||
file=数据集文件 | |||
download=下载附件 | |||
edit=编辑 | |||
private=私有 | |||
public=公有 | |||
back=返回 | |||
visibility=可见性 | |||
visibility_description=只有组织所有人或拥有权利的组织成员才能看到。 | |||
visibility_helper=将数据集设为私有 | |||
visibility_helper_forced=站点管理员强制要求新数据集为私有。 | |||
visibility_fork_helper=(修改该值将会影响到所有派生数据集) | |||
[repo] | |||
owner=拥有者 | |||
@@ -88,6 +88,11 @@ func CreatePost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
return | |||
} | |||
status := 2 | |||
if form.Status { | |||
status = 1 | |||
} | |||
var err error | |||
opts := models.Dataset{ | |||
Title: form.Title, | |||
@@ -97,7 +102,7 @@ func CreatePost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
Task: form.Task, | |||
ReleaseID: form.ReleaseID, | |||
UserID: ctxUser.ID, | |||
Status: 0, | |||
Status: int32(status), | |||
} | |||
// if !opts.IsValid() { | |||
// ctx.RenderWithErr(ctx.Tr("repo.template.one_item"), tplCreate, form) | |||
@@ -131,17 +136,19 @@ func CreatePost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
func Show(ctx *context.Context) { | |||
ctx.Data["Title"] = ctx.Tr("dataset.show_dataset") | |||
rel, err := models.GetDatasetByID(ctx.ParamsInt64((":id"))) | |||
dataset, err := models.GetDatasetByID(ctx.ParamsInt64((":id"))) | |||
if err != nil { | |||
ctx.ServerError("GetDataset", err) | |||
return | |||
} | |||
ctx.Data["title"] = rel.Title | |||
ctx.Data["description"] = rel.Description | |||
ctx.Data["category"] = rel.Category | |||
ctx.Data["task"] = rel.Task | |||
ctx.Data["license"] = rel.License | |||
err = models.GeDatasetAttachments(dataset) | |||
if err != nil { | |||
ctx.ServerError("GetDatasetAttachments", err) | |||
return | |||
} | |||
ctx.Data["dataset"] = dataset | |||
ctx.HTML(200, tplShow) | |||
} | |||
@@ -181,6 +188,7 @@ func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) { | |||
ctx.Data["category"] = rel.Category | |||
ctx.Data["task"] = rel.Task | |||
ctx.Data["license"] = rel.License | |||
ctx.Data["status"] = rel.Status | |||
if ctx.HasError() { | |||
ctx.HTML(200, tplCreate) | |||
@@ -192,7 +200,13 @@ func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) { | |||
attachmentUUIDs = form.Files | |||
} | |||
status := 2 | |||
if form.Status { | |||
status = 1 | |||
} | |||
rel.Title = form.Title | |||
rel.Status = int32(status) | |||
rel.Description = form.Description | |||
rel.Category = form.Category | |||
rel.Task = form.Task | |||
@@ -15,17 +15,17 @@ | |||
</div> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.visibility"}}</label> | |||
<label>{{.i18n.Tr "dataset.visibility"}}</label> | |||
<div class="ui checkbox"> | |||
{{if .IsForcedPrivate}} | |||
<input name="private" type="checkbox" checked readonly> | |||
<label>{{.i18n.Tr "repo.visibility_helper_forced" | Safe}}</label> | |||
<input name="status" type="checkbox" checked readonly> | |||
<label>{{.i18n.Tr "dataset.visibility_helper_forced" | Safe}}</label> | |||
{{else}} | |||
<input name="private" type="checkbox" {{if .private}}checked{{end}}> | |||
<label>{{.i18n.Tr "repo.visibility_helper" | Safe}}</label> | |||
<input name="status" type="checkbox" {{if .private}}checked{{end}}> | |||
<label>{{.i18n.Tr "dataset.visibility_helper" | Safe}}</label> | |||
{{end}} | |||
</div> | |||
<span class="help">{{.i18n.Tr "repo.visibility_description"}}</span> | |||
<span class="help">{{.i18n.Tr "dataset.visibility_description"}}</span> | |||
</div> | |||
<div class="inline required field"> | |||
@@ -1,3 +1,68 @@ | |||
{{template "base/head" .}} | |||
<h1>{{.Title}}</h1> | |||
<div class="dataset"> | |||
<div class="ui container"> | |||
<h2 class="ui header"> | |||
{{$.i18n.Tr "dataset.dataset"}} | |||
<div class="ui right"> | |||
<a class="ui small white button" href="/datasets"> | |||
{{$.i18n.Tr "dataset.back"}} | |||
</a> | |||
<a class="ui small green button" href="/datasets/create"> | |||
{{$.i18n.Tr "dataset.create_dataset"}} | |||
</a> | |||
</div> | |||
</h2> | |||
<ul id="dataset-list"> | |||
<li class="ui grid"> | |||
<div class="ui four wide column meta"> | |||
{{if eq .dataset.Status 2 }} | |||
<span class="ui yellow label">{{$.i18n.Tr "dataset.public"}}</span> | |||
{{else}} | |||
<span class="ui green label">{{$.i18n.Tr "dataset.private"}}</span> | |||
{{end}} | |||
<span class="tag text blue"> | |||
<a href=""><i class="tag icon"></i> {{.dataset.Category}}</a> | |||
</span> | |||
<span class="tag text blue"> | |||
<a href=""><i class="tag icon"></i> {{.dataset.License}}</a> | |||
</span> | |||
<span class="tag text blue"> | |||
<a href=""><i class="tag icon"></i> {{.dataset.Task}}</a> | |||
</span> | |||
</div> | |||
<div class="ui twelve wide column detail"> | |||
<h3><a href="">{{.dataset.Title}}</a> | |||
<small>(<a href="/datasets/edit/{{.dataset.ID}}" rel="nofollow">{{$.i18n.Tr "dataset.edit"}}</a>)</small> | |||
</h3> | |||
<div class="markdown desc"> | |||
<p>{{.dataset.Description}}</p> | |||
</div> | |||
<div class="download"> | |||
<div class="ui accordion"> | |||
<h2 class="title active"> | |||
<i class="dropdown icon"></i> | |||
{{$.i18n.Tr "dataset.download"}} | |||
</h2> | |||
<div class="content active"> | |||
<ul class="list"> | |||
{{if .dataset.Attachments}} | |||
{{range .dataset.Attachments}} | |||
<li> | |||
<span class="ui text right" data-tooltip="{{$.i18n.Tr "repo.release.download_count" (.DownloadCount | PrettyNumber)}}" data-position="bottom right">{{svg "octicon-info" 16}}</span> | |||
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}"> | |||
<strong><span class="ui image" title='{{.Name}}'>{{svg "octicon-package" 16}}</span> {{.Name}}</strong> | |||
<span class="ui text grey right">{{.Size | FileSize}}</span> | |||
</a> | |||
</li> | |||
{{end}} | |||
{{end}} | |||
</ul> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</li> | |||
</ul> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -53,4 +53,86 @@ | |||
} | |||
} | |||
} | |||
#dataset-list { | |||
border-top: 1px solid #dddddd; | |||
margin-top: 20px; | |||
padding-top: 15px; | |||
> li { | |||
list-style: none; | |||
.meta, | |||
.detail { | |||
padding-top: 30px; | |||
padding-bottom: 40px; | |||
} | |||
.meta { | |||
text-align: right; | |||
position: relative; | |||
.tag:not(.icon) { | |||
display: block; | |||
margin-top: 15px; | |||
} | |||
.commit { | |||
display: block; | |||
margin-top: 10px; | |||
} | |||
} | |||
.detail { | |||
border-left: 1px solid #dddddd; | |||
.author { | |||
img { | |||
margin-bottom: -3px; | |||
} | |||
} | |||
.download { | |||
margin-top: 20px; | |||
> a { | |||
.svg { | |||
margin-left: 5px; | |||
margin-right: 5px; | |||
} | |||
} | |||
.list { | |||
padding-left: 0; | |||
border-top: 1px solid #eeeeee; | |||
li { | |||
list-style: none; | |||
display: block; | |||
padding-top: 8px; | |||
padding-bottom: 8px; | |||
border-bottom: 1px solid #eeeeee; | |||
a > .text.right { | |||
margin-right: 5px; | |||
} | |||
} | |||
} | |||
} | |||
.dot { | |||
width: 9px; | |||
height: 9px; | |||
background-color: #cccccc; | |||
z-index: 999; | |||
position: absolute; | |||
display: block; | |||
left: -5px; | |||
top: 40px; | |||
border-radius: 6px; | |||
border: 1px solid #ffffff; | |||
} | |||
} | |||
} | |||
} | |||
} |