| @@ -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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||