Simplified create and find functions for review

Signed-off-by: Jonas Franz <info@jonasfranz.software>
This commit is contained in:
Jonas Franz 2018-05-10 20:41:31 +02:00
parent 9544c46052
commit 0f772d1bf4
No known key found for this signature in database
GPG Key ID: 506AEEBE80BEDECD
3 changed files with 95 additions and 43 deletions

View File

@ -360,6 +360,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
OldTitle: opts.OldTitle,
NewTitle: opts.NewTitle,
TreePath: opts.TreePath,
ReviewID: opts.ReviewID,
}
if _, err = e.Insert(comment); err != nil {
return nil, err
@ -579,6 +580,7 @@ type CreateCommentOptions struct {
CommitSHA string
LineNum int64
TreePath string
ReviewID int64
Content string
Attachments []string // UUIDs of attachments
}
@ -619,7 +621,7 @@ func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content stri
}
// CreateCodeComment creates a plain code comment at the specified line / path
func CreateCodeComment(doer *User, repo *Repository, issue *Issue, commitSHA, content, treePath string, line int64) (*Comment, error) {
func CreateCodeComment(doer *User, repo *Repository, issue *Issue, commitSHA, content, treePath string, line, reviewID int64) (*Comment, error) {
return CreateComment(&CreateCommentOptions{
Type: CommentTypeCode,
Doer: doer,
@ -629,6 +631,7 @@ func CreateCodeComment(doer *User, repo *Repository, issue *Issue, commitSHA, co
LineNum: line,
TreePath: treePath,
CommitSHA: commitSHA,
ReviewID: reviewID,
})
}

View File

@ -4,11 +4,17 @@
package models
import "code.gitea.io/gitea/modules/util"
import (
"code.gitea.io/gitea/modules/util"
"github.com/go-xorm/builder"
)
// ReviewType defines the sort of feedback a review gives
type ReviewType int
// ReviewTypeUnknown unknown review type
const ReviewTypeUnknown ReviewType = -1
const (
// ReviewTypeApprove approves changes
ReviewTypeApprove ReviewType = iota
@ -88,33 +94,65 @@ func GetReviewByID(id int64) (*Review, error) {
return getReviewByID(x, id)
}
func getPendingReviewByReviewerID(e Engine, reviewer *User, issue *Issue) (review *Review, err error) {
var exists bool
if exists, err = e.Table("review").Where("reviewer_id = ? and issue_id = ? and type = ?", reviewer.ID, issue.ID, ReviewTypePending).
Get(review); !exists && err == nil {
return nil, nil
}
return
// FindReviewOptions represent possible filters to find reviews
type FindReviewOptions struct {
Type ReviewType
IssueID int64
ReviewerID int64
}
// GetPendingReviewByReviewer returns the latest pending review of reviewer at PR issue
func GetPendingReviewByReviewer(reviewer *User, issue *Issue) (*Review, error) {
return getPendingReviewByReviewerID(x, reviewer, issue)
func (opts *FindReviewOptions) toCond() builder.Cond {
var cond = builder.NewCond()
if opts.IssueID > 0 {
cond = cond.And(builder.Eq{"issue_id": opts.IssueID})
}
if opts.ReviewerID > 0 {
cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID})
}
if opts.Type != ReviewTypeUnknown {
cond = cond.And(builder.Eq{"type": opts.Type})
}
return cond
}
func createPendingReview(e Engine, reviewer *User, issue *Issue) (*Review, error) {
func findReviews(e Engine, opts FindReviewOptions) ([]*Review, error) {
reviews := make([]*Review, 0, 10)
sess := e.Where(opts.toCond())
return reviews, sess.
Asc("created_unix").
Asc("id").
Find(&reviews)
}
// FindReviews returns reviews passing FindReviewOptions
func FindReviews(opts FindReviewOptions) ([]*Review, error) {
return findReviews(x, opts)
}
// CreateReviewOptions represent the options to create a review. Type, Issue and Reviewer are required.
type CreateReviewOptions struct {
Content string
Type ReviewType
Issue *Issue
Reviewer *User
}
func createReview(e Engine, opts CreateReviewOptions) (*Review, error) {
review := &Review{
Type: ReviewTypePending,
Issue: issue,
IssueID: issue.ID,
Reviewer: reviewer,
ReviewerID: reviewer.ID,
Type: opts.Type,
Issue: opts.Issue,
IssueID: opts.Issue.ID,
Reviewer: opts.Reviewer,
ReviewerID: opts.Reviewer.ID,
Content: opts.Content,
}
_, err := e.Insert(review)
return review, err
if _, err := e.Insert(review); err != nil {
return nil, err
}
return review, nil
}
// CreatePendingReview creates an empty pending review
func CreatePendingReview(reviewer *User, issue *Issue) (*Review, error) {
return createPendingReview(x, reviewer, issue)
// CreateReview creates a new review based on opts
func CreateReview(opts CreateReviewOptions) (*Review, error) {
return createReview(x, opts)
}

View File

@ -42,7 +42,35 @@ func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) {
if form.Side == "previous" {
signedLine *= -1
}
//FIXME check if line and treepath exist
review := new(models.Review)
if form.IsReview {
// Check if the user has already a pending review for this issue
reviews, err := models.FindReviews(models.FindReviewOptions{
ReviewerID: ctx.User.ID,
IssueID: issue.ID,
Type: models.ReviewTypePending,
})
if err != nil {
ctx.ServerError("CreateCodeComment", err)
return
}
if len(reviews) == 0 {
// Create a new pending review for this issue & user
if review, err = models.CreateReview(models.CreateReviewOptions{
Type: models.ReviewTypePending,
Reviewer: ctx.User,
Issue: issue,
}); err != nil {
ctx.ServerError("CreateCodeComment", err)
return
}
} else {
review = reviews[0]
}
}
//FIXME check if line, commit and treepath exist
var err error
comment, err = models.CreateCodeComment(
ctx.User,
@ -52,31 +80,14 @@ func CreateCodeComment(ctx *context.Context, form auth.CodeCommentForm) {
form.Content,
form.TreePath,
signedLine,
review.ID,
)
if err != nil {
ctx.ServerError("CreateCodeComment", err)
return
}
if form.IsReview {
review, err := models.GetPendingReviewByReviewer(ctx.User, issue)
if err != nil {
ctx.ServerError("CreateCodeComment", err)
return
}
if review == nil {
if review, err = models.CreatePendingReview(ctx.User, issue); err != nil {
ctx.ServerError("CreateCodeComment", err)
return
}
}
comment.Review = review
comment.ReviewID = review.ID
if err = models.UpdateComment(comment); err != nil {
ctx.ServerError("CreateCodeComment", err)
return
}
} else {
// Send no notification if comment is pending
if !form.IsReview {
notification.Service.NotifyIssue(issue, ctx.User.ID)
}