diff --git a/README.md b/README.md index b7396e5f4..47f4bd515 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +Gogs - Go Git Service [![wercker status](https://app.wercker.com/status/ad0bdb0bc450ac6f09bc56b9640a50aa/s/ "wercker status")](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [![Build Status](https://drone.io/github.com/gogits/gogs/status.png)](https://drone.io/github.com/gogits/gogs/latest) +===================== + Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language. ![Demo](http://gowalker.org/public/gogs_demo.gif) diff --git a/models/issue.go b/models/issue.go index 2de656858..47ec4edd0 100644 --- a/models/issue.go +++ b/models/issue.go @@ -163,9 +163,29 @@ type Milestone struct { type Comment struct { Id int64 PosterId int64 + Poster *User `xorm:"-"` IssueId int64 CommitId int64 - Line int + Line int64 Content string Created time.Time `xorm:"created"` } + +// CreateComment creates comment of issue or commit. +func CreateComment(userId, issueId, commitId, line int64, content string) error { + _, err := orm.Insert(&Comment{ + PosterId: userId, + IssueId: issueId, + CommitId: commitId, + Line: line, + Content: content, + }) + return err +} + +// GetIssueComments returns list of comment by given issue id. +func GetIssueComments(issueId int64) ([]Comment, error) { + comments := make([]Comment, 0, 10) + err := orm.Asc("created").Find(&comments, &Comment{IssueId: issueId}) + return comments, err +} diff --git a/models/models.go b/models/models.go index ad19a929f..813725be4 100644 --- a/models/models.go +++ b/models/models.go @@ -72,7 +72,7 @@ func setEngine() { func NewEngine() { setEngine() if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch), - new(Action), new(Access), new(Issue)); err != nil { + new(Action), new(Access), new(Issue), new(Comment)); err != nil { fmt.Printf("sync database struct error: %v\n", err) os.Exit(2) } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 72d07d4ac..e53aebf63 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -113,8 +113,34 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { return } + // Get posters. + u, err := models.GetUserById(issue.PosterId) + if err != nil { + ctx.Handle(200, "issue.ViewIssue(get poster): %v", err) + return + } + issue.Poster = u + + // Get comments. + comments, err := models.GetIssueComments(issue.Id) + if err != nil { + ctx.Handle(200, "issue.ViewIssue(get comments): %v", err) + return + } + + // Get posters. + for i := range comments { + u, err := models.GetUserById(comments[i].PosterId) + if err != nil { + ctx.Handle(200, "issue.ViewIssue(get poster): %v", err) + return + } + comments[i].Poster = u + } + ctx.Data["Title"] = issue.Name ctx.Data["Issue"] = issue + ctx.Data["Comments"] = comments ctx.Data["IsRepoToolbarIssues"] = true ctx.Data["IsRepoToolbarIssuesList"] = false ctx.HTML(200, "issue/view") @@ -132,7 +158,7 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat if err == models.ErrIssueNotExist { ctx.Handle(404, "issue.UpdateIssue", err) } else { - ctx.Handle(200, "issue.UpdateIssue", err) + ctx.Handle(200, "issue.UpdateIssue(get issue)", err) } return } @@ -148,10 +174,48 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat issue.Labels = form.Labels issue.Content = form.Content if err = models.UpdateIssue(issue); err != nil { - ctx.Handle(200, "issue.UpdateIssue", err) + ctx.Handle(200, "issue.UpdateIssue(update issue)", err) return } ctx.Data["Title"] = issue.Name ctx.Data["Issue"] = issue } + +func Comment(ctx *middleware.Context, params martini.Params) { + index, err := base.StrTo(ctx.Query("issueIndex")).Int() + if err != nil { + ctx.Handle(404, "issue.Comment", err) + return + } + + issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, int64(index)) + if err != nil { + if err == models.ErrIssueNotExist { + ctx.Handle(404, "issue.Comment", err) + } else { + ctx.Handle(200, "issue.Comment(get issue)", err) + } + return + } + + content := ctx.Query("content") + if len(content) == 0 { + ctx.Handle(404, "issue.Comment", err) + return + } + + switch params["action"] { + case "new": + if err = models.CreateComment(ctx.User.Id, issue.Id, 0, 0, content); err != nil { + ctx.Handle(500, "issue.Comment(create comment)", err) + return + } + log.Trace("%s Comment created: %d", ctx.Req.RequestURI, issue.Id) + default: + ctx.Handle(404, "issue.Comment", err) + return + } + + ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", ctx.User.Name, ctx.Repo.Repository.Name, index)) +} diff --git a/templates/issue/view.tmpl b/templates/issue/view.tmpl index 381c79990..6b282513a 100644 --- a/templates/issue/view.tmpl +++ b/templates/issue/view.tmpl @@ -6,52 +6,39 @@
-
#448
- -

[Request]关于context中的Download方法

+
#{{.Issue.Index}}
+ +

{{.Issue.Name}}

- Open - linbaozhong opened this issue - 2 months ago · 1 comment + {{if .Issue.IsClosed}}Closed{{else}}Open{{end}} + {{.Issue.Poster.Name}} opened this issue + {{TimeSince .Issue.Created}} · {{.Issue.NumComments}} comments

-

context中的Download方法:

-

func (output *BeegoOutput) Download(file string)

-

建议在file参数后面增加一个可选参数filename.

-

如果filename不存在或为空,output.Header("Content-Disposition", "attachment; filename="+filepath.Base(file))

-

如果filename不为空,output.Header("Content-Disposition", "attachment; filename="+filename)

-

因为有时候,多数情况下,要下载的真实的文件名与显示和保存的本地的文件名是不一样的,希望显示的文件名更友好些

+

{{.Issue.Content}}

+ {{range .Comments}}
- +
- phpqinsir commented 3 days ago + {{.Poster.Name}} commented {{TimeSince .Created}}
-

@slene 看来也只能这样了。最主要是数组与切片的用法,我感觉不科学。因为要知道个数,然后个数与问号个数要对应。不能像PHP YII框架那样,直接传入一个数组,自己在里面把参数组装成1,2,3,4这种格式。希望,Beego框架能加上。那就太完美了。谢谢。

+

{{.Content}}

-
-
- -
-
- phpqinsir commented 3 days ago -
-
-

@slene 看来也只能这样了。最主要是数组与切片的用法,我感觉不科学。因为要知道个数,然后个数与问号个数要对应。不能像PHP YII框架那样,直接传入一个数组,自己在里面把参数组装成1,2,3,4这种格式。希望,Beego框架能加上。那就太完美了。谢谢。

-
-
+ {{end}}
- -
+ + + {{.CsrfTokenHtml}}
@@ -64,6 +51,7 @@
+
diff --git a/web.go b/web.go index 9423c3eec..6bc55908b 100644 --- a/web.go +++ b/web.go @@ -144,6 +144,7 @@ func runWeb(*cli.Context) { r.Get("/action/:action", repo.Action) r.Any("/issues/new", binding.BindIgnErr(auth.CreateIssueForm{}), repo.CreateIssue) r.Post("/issues/:index", binding.BindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue) + r.Post("/comment/:action", repo.Comment) }, reqSignIn, middleware.RepoAssignment(true)) m.Group("/:username/:reponame", func(r martini.Router) { r.Get("/commits/:branchname", repo.Commits)