@@ -1,6 +1,7 @@ | |||
package models | |||
import ( | |||
"errors" | |||
"fmt" | |||
"sort" | |||
@@ -25,10 +26,23 @@ type Dataset struct { | |||
Attachments []*Attachment `xorm:"-"` | |||
} | |||
func (d *Dataset) IsPrivate() bool { | |||
switch d.Status { | |||
case DatasetStatusPrivate: | |||
return true | |||
case DatasetStatusPublic: | |||
return false | |||
case DatasetStatusDeleted: | |||
return false | |||
default: | |||
return false | |||
} | |||
} | |||
type DatasetList []*Dataset | |||
const ( | |||
DatasetStatusPrivate int = iota | |||
DatasetStatusPrivate int32 = iota | |||
DatasetStatusPublic | |||
DatasetStatusDeleted | |||
) | |||
@@ -201,3 +215,18 @@ func GetDatasetByID(id int64) (*Dataset, error) { | |||
return rel, nil | |||
} | |||
func GetOwnerDatasetByID(id int64, user *User) (*Dataset, error) { | |||
dataset, err := GetDatasetByID(id) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if !dataset.IsPrivate() { | |||
return dataset, nil | |||
} | |||
if dataset.IsPrivate() && user.ID == dataset.UserID { | |||
return dataset, nil | |||
} | |||
return nil, errors.New("dataset not fount") | |||
} |
@@ -13,7 +13,7 @@ type CreateDatasetForm struct { | |||
License string `binding:"Required;MaxSize(64)"` | |||
Task string `binding:"Required;MaxSize(64)"` | |||
ReleaseID int64 `xorm:"INDEX"` | |||
IsPrivate bool | |||
Private bool | |||
Files []string | |||
} | |||
@@ -28,7 +28,7 @@ type EditDatasetForm struct { | |||
Description string `binding:"Required;MaxSize(254)"` | |||
License string `binding:"Required;MaxSize(64)"` | |||
Task string `binding:"Required;MaxSize(64)"` | |||
Status bool | |||
Private bool | |||
ReleaseID int64 `xorm:"INDEX"` | |||
Files []string | |||
} |
@@ -17,6 +17,7 @@ const ( | |||
tplDataSet base.TplName = "datasets/index" | |||
tplShow base.TplName = "datasets/show" | |||
tplCreate base.TplName = "datasets/create" | |||
tplEdit base.TplName = "datasets/edit" | |||
) | |||
type ListOptions struct { | |||
@@ -117,7 +118,7 @@ func CreatePost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
} | |||
status := models.DatasetStatusPublic | |||
if form.IsPrivate { | |||
if form.Private { | |||
status = models.DatasetStatusPrivate | |||
} | |||
@@ -130,7 +131,7 @@ func CreatePost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
Task: form.Task, | |||
ReleaseID: form.ReleaseID, | |||
UserID: ctxUser.ID, | |||
Status: int32(status), | |||
Status: status, | |||
} | |||
if err = models.CreateDataset(&opts); err != nil { | |||
@@ -156,7 +157,8 @@ func CreatePost(ctx *context.Context, form auth.CreateDatasetForm) { | |||
func Show(ctx *context.Context) { | |||
ctx.Data["Title"] = ctx.Tr("dataset.show_dataset") | |||
dataset, err := models.GetDatasetByID(ctx.ParamsInt64((":id"))) | |||
user := ctx.User | |||
dataset, err := models.GetOwnerDatasetByID(ctx.ParamsInt64((":id")), user) | |||
if err != nil { | |||
ctx.ServerError("GetDataset", err) | |||
return | |||
@@ -168,7 +170,10 @@ func Show(ctx *context.Context) { | |||
return | |||
} | |||
isOwner := dataset.UserID == user.ID | |||
ctx.Data["dataset"] = dataset | |||
ctx.Data["IsOwner"] = isOwner | |||
ctx.HTML(200, tplShow) | |||
} | |||
@@ -178,24 +183,24 @@ func EditDataset(ctx *context.Context) { | |||
ctx.Data["Title"] = ctx.Tr("dataset.edit_dataset") | |||
ctx.Data["PageIsEditDataset"] = true | |||
repo.RenderAttachmentSettings(ctx) | |||
rel, err := models.GetDatasetByID(ctx.ParamsInt64(":id")) | |||
rel, err := models.GetOwnerDatasetByID(ctx.ParamsInt64(":id"), ctx.User) | |||
if err != nil { | |||
ctx.ServerError("GetDataset", err) | |||
return | |||
} | |||
ctx.Data["ID"] = rel.ID | |||
ctx.Data["title"] = rel.Title | |||
ctx.Data["private"] = rel.IsPrivate() | |||
ctx.Data["description"] = rel.Description | |||
ctx.Data["category"] = rel.Category | |||
ctx.Data["task"] = rel.Task | |||
ctx.Data["license"] = rel.License | |||
ctx.HTML(200, tplCreate) | |||
ctx.HTML(200, tplEdit) | |||
} | |||
func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) { | |||
ctx.Data["Title"] = ctx.Tr("dataset.edit_dataset") | |||
ctx.Data["PageIsEditDataset"] = true | |||
rel, err := models.GetDatasetByID(ctx.ParamsInt64(":id")) | |||
if err != nil { | |||
@@ -208,7 +213,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 | |||
ctx.Data["private"] = rel.IsPrivate() | |||
if ctx.HasError() { | |||
ctx.HTML(200, tplCreate) | |||
@@ -220,13 +225,13 @@ func EditDatasetPost(ctx *context.Context, form auth.EditDatasetForm) { | |||
attachmentUUIDs = form.Files | |||
} | |||
status := 2 | |||
if form.Status { | |||
status = 1 | |||
status := models.DatasetStatusPublic | |||
if form.Private { | |||
status = models.DatasetStatusPrivate | |||
} | |||
rel.Title = form.Title | |||
rel.Status = int32(status) | |||
rel.Status = status | |||
rel.Description = form.Description | |||
rel.Category = form.Category | |||
rel.Task = form.Task | |||
@@ -12,114 +12,11 @@ | |||
{{end}} | |||
</h3> | |||
<div class="ui attached segment"> | |||
{{template "base/alert" .}} | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.title"}}</label> | |||
<input name="title" placeholder='{{.i18n.Tr "dataset.title"}}' value="{{.title}}" autofocus required maxlength="255"> | |||
</div> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "dataset.visibility"}}</label> | |||
<div class="ui checkbox"> | |||
{{if .IsForcedPrivate}} | |||
<input name="status" type="checkbox" checked readonly> | |||
<label>{{.i18n.Tr "dataset.visibility_helper_forced" | Safe}}</label> | |||
{{else}} | |||
<input name="status" type="checkbox" {{if .private}}checked{{end}}> | |||
<label>{{.i18n.Tr "dataset.visibility_helper" | Safe}}</label> | |||
{{end}} | |||
</div> | |||
<span class="help">{{.i18n.Tr "dataset.visibility_description"}}</span> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.description"}}</label> | |||
<textarea name="description">{{.description}}</textarea> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.category"}}</label> | |||
<div class="ui selection dropdown"> | |||
<input type="hidden" name="category" id="category" value="{{.category}}" required> | |||
<i class="dropdown icon"></i> | |||
<div class="default text" style="min-width:20vw">{{.i18n.Tr "dataset.category"}}</div> | |||
<div class="menu"> | |||
<div class="item" data-value="计算机视觉、自然语言处理"> | |||
计算机视觉、自然语言处理 | |||
</div> | |||
<div class="item" data-value="计算机视觉"> | |||
计算机视觉 | |||
</div> | |||
<div class="item" data-value="深度学习"> | |||
深度学习 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.task"}}</label> | |||
<div class="ui selection dropdown"> | |||
<input type="hidden" name="task" id="task" value="{{.task}}" required> | |||
<div class="default text" style="min-width:20vw">{{.i18n.Tr "dataset.task"}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="遥感图像理解"> | |||
遥感图像理解 | |||
</div> | |||
<div class="item" data-value="语音识别"> | |||
语音识别 | |||
</div> | |||
<div class="item" data-value="智能问答"> | |||
智能问答 | |||
</div> | |||
<div class="item" data-value="文本分类"> | |||
文本分类 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.license"}}</label> | |||
<div class="ui selection owner dropdown"> | |||
<input type="hidden" name="license" id="license" value="{{.license}}" required> | |||
<div class="default text" style="min-width:20vw">{{.i18n.Tr "dataset.license"}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="Creative Commons CC BY 4.0"> | |||
Creative Commons CC BY 4.0 | |||
</div> | |||
<div class="item" data-value="GFDL and CC BY-SA 3.0"> | |||
GFDL and CC BY-SA 3.0 | |||
</div> | |||
<div class="item" data-value="Apache 2.0"> | |||
Apache 2.0 | |||
</div> | |||
<div class="item" data-value="CC BY 2.0"> | |||
CC BY 2.0 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<br/> | |||
<div class="field required dataset-files"> | |||
<label>{{.i18n.Tr "dataset.file"}}</label> | |||
<div class="files"></div> | |||
<div class="ui dropzone" id="dataset" data-upload-url="{{AppSubUrl}}/attachments" data-accepts="{{.AttachmentAllowedTypes}}" data-max-file="1000" data-max-size="{{.AttachmentMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"> | |||
</div> | |||
</div> | |||
<br/> | |||
{{template "datasets/form" .}} | |||
<div class="inline field"> | |||
<label></label> | |||
<button class="ui green button"> | |||
{{if .PageIsEditDataset}} | |||
{{.i18n.Tr "dataset.update_dataset"}} | |||
{{else}} | |||
{{.i18n.Tr "dataset.create_dataset"}} | |||
{{end}} | |||
{{.i18n.Tr "dataset.create_dataset"}} | |||
</button> | |||
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | |||
</div> | |||
@@ -0,0 +1,24 @@ | |||
{{template "base/head" .}} | |||
<div class="dataset new"> | |||
<div class="ui middle very relaxed page grid"> | |||
<div class="column"> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
{{.CsrfTokenHtml}} | |||
<h3 class="ui top attached header"> | |||
{{.i18n.Tr "edit_dataset"}} | |||
</h3> | |||
<div class="ui attached segment"> | |||
{{template "datasets/form" .}} | |||
<div class="inline field"> | |||
<label></label> | |||
<button class="ui green button"> | |||
{{.i18n.Tr "dataset.update_dataset"}} | |||
</button> | |||
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | |||
</div> | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -0,0 +1,100 @@ | |||
{{template "base/alert" .}} | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.title"}}</label> | |||
<input name="title" placeholder='{{.i18n.Tr "dataset.title"}}' value="{{.title}}" autofocus required maxlength="255"> | |||
</div> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "dataset.visibility"}}</label> | |||
<div class="ui checkbox"> | |||
{{if .IsForcedPrivate}} | |||
<input name="private" 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 "dataset.visibility_helper" | Safe}}</label> | |||
{{end}} | |||
</div> | |||
<span class="help" style="display: none;">{{.i18n.Tr "dataset.visibility_description"}}</span> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.description"}}</label> | |||
<textarea name="description">{{.description}}</textarea> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.category"}}</label> | |||
<div class="ui selection dropdown"> | |||
<input type="hidden" name="category" id="category" value="{{.category}}" required> | |||
<i class="dropdown icon"></i> | |||
<div class="default text" style="min-width:20vw">{{.i18n.Tr "dataset.category"}}</div> | |||
<div class="menu"> | |||
<div class="item" data-value="计算机视觉、自然语言处理"> | |||
计算机视觉、自然语言处理 | |||
</div> | |||
<div class="item" data-value="计算机视觉"> | |||
计算机视觉 | |||
</div> | |||
<div class="item" data-value="深度学习"> | |||
深度学习 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.task"}}</label> | |||
<div class="ui selection dropdown"> | |||
<input type="hidden" name="task" id="task" value="{{.task}}" required> | |||
<div class="default text" style="min-width:20vw">{{.i18n.Tr "dataset.task"}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="遥感图像理解"> | |||
遥感图像理解 | |||
</div> | |||
<div class="item" data-value="语音识别"> | |||
语音识别 | |||
</div> | |||
<div class="item" data-value="智能问答"> | |||
智能问答 | |||
</div> | |||
<div class="item" data-value="文本分类"> | |||
文本分类 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline required field"> | |||
<label>{{.i18n.Tr "dataset.license"}}</label> | |||
<div class="ui selection owner dropdown"> | |||
<input type="hidden" name="license" id="license" value="{{.license}}" required> | |||
<div class="default text" style="min-width:20vw">{{.i18n.Tr "dataset.license"}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="Creative Commons CC BY 4.0"> | |||
Creative Commons CC BY 4.0 | |||
</div> | |||
<div class="item" data-value="GFDL and CC BY-SA 3.0"> | |||
GFDL and CC BY-SA 3.0 | |||
</div> | |||
<div class="item" data-value="Apache 2.0"> | |||
Apache 2.0 | |||
</div> | |||
<div class="item" data-value="CC BY 2.0"> | |||
CC BY 2.0 | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<br/> | |||
<div class="field required dataset-files"> | |||
<label>{{.i18n.Tr "dataset.file"}}</label> | |||
<div class="files"></div> | |||
<div class="ui dropzone" id="dataset" data-upload-url="{{AppSubUrl}}/attachments" data-accepts="{{.AttachmentAllowedTypes}}" data-max-file="1000" data-max-size="{{.AttachmentMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"> | |||
</div> | |||
</div> | |||
<br/> |