diff options
author | Lauris BH <lauris@nix.lv> | 2018-08-06 07:43:22 +0300 |
---|---|---|
committer | Jonas Franz <info@jonasfranz.software> | 2018-08-06 06:43:21 +0200 |
commit | 6e64f9db8eb889f9cc7e8c9576b2f9c89750927e (patch) | |
tree | d76b927295a1d2f69ea73a78e83d9264ce1510f2 /models/review.go | |
parent | 9c354a539ab498ebfdebf7395cf17f95f8b24ac8 (diff) | |
download | gitea-6e64f9db8eb889f9cc7e8c9576b2f9c89750927e.tar.gz gitea-6e64f9db8eb889f9cc7e8c9576b2f9c89750927e.zip |
Pull request review/approval and comment on code (#3748)
* Initial ui components for pull request review
* Add Review
Add IssueComment types
Signed-off-by: Jonas Franz <info@jonasfranz.software>
(cherry picked from commit 2b4daab)
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Replace ReviewComment with Content
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add load functions
Add ReviewID to findComments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add create review comment implementation
Add migration for review
Other small changes
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Simplified create and find functions for review
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Moved "Pending" to first position
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add GetCurrentReview to simplify fetching current review
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Preview for listing comments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Move new comment form to its own file
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Implement Review form
Show Review comments on comment stream
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add support for single comments
Showing buttons in context
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add pending tag to pending review comments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add unit tests for Review
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fetch all review ids at once
Add unit tests
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* gofmt
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Improved comment rendering in "Files" view by adding Comments to DiffLine
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add support for invalidating comments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Switched back to code.gitea.io/git
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Moved review migration from v64 to v65
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Rebuild css
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* gofmt
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Improve translations
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fix unit tests by updating fixtures and updating outdated test
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Comments will be shown at the right place now
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add support for deleting CodeComments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fix problems caused by files in subdirectories
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add support for showing code comments of reviews in conversation
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add support for "Show/Hide outdated"
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Update code.gitea.io/git
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add support for new webhooks
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Update comparison
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Resolve conflicts
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Minor UI improvements
* update code.gitea.io/git
* Fix ui bug reported by @lunny causing wrong position of add button
Add functionality to "Cancel" button
Add scale effects to add button
Hide "Cancel" button for existing comments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Prepare solving conflicts
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Show add button only if no comments already exist for the line
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add missing vendor files
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Check if reviewer is nil
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Show forms only to users who are logged in
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Revert "Show forms only to users who are logged in"
This reverts commit c083682
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Save patch in comment
Render patch for code comments
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add link to comment in code
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add reply form to comment list
Show forms only to signed in users
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add 'Reply' as translatable
Add CODE_COMMENT_LINES setting
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* gofmt
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fix problems introduced by checking for singed in user
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add v70
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Update generated stylesheet
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fix preview
Beginn with new review comment patch system
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add new algo to generate diff for line range
Remove old algo used for cutting big diffs (it was very buggy)
* Add documentation and example for CutDiffAroundLine
* Fix example of CutDiffAroundLine
* Fix some comment UI rendering bugs
* Add code comment edit mode
* Send notifications / actions to users until review gets published
Fix diff generation bug
Fix wrong hashtag
* Fix vet errors
* Send notifications also for single comments
* Fix some notification bugs, fix link
* Fix: add comment icon is only shown on code lines
* Add lint comment
* Add unit tests for git diff
* Add more error messages
* Regenerated css
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* fmt
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Regenerated CSS with latest less version
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fix test by updating comment type to new ID
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Introducing CodeComments as type for map[string]map[int64][]*Comment
Other minor code improvements
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Fix data-tab issues
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Remove unnecessary change
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* refactored checkForInvalidation
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Append comments instead of setting
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Use HeadRepo instead of BaseRepo
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Update migration
Signed-off-by: Jonas Franz <info@jonasfranz.de>
* Regenerated CSS
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Add copyright
Signed-off-by: Jonas Franz <info@jonasfranz.software>
* Update index.css
Signed-off-by: Jonas Franz <info@jonasfranz.software>
Diffstat (limited to 'models/review.go')
-rw-r--r-- | models/review.go | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/models/review.go b/models/review.go new file mode 100644 index 0000000000..3326ea0549 --- /dev/null +++ b/models/review.go @@ -0,0 +1,256 @@ +// Copyright 2018 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "fmt" + + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" + "github.com/go-xorm/xorm" + + "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 ( + // ReviewTypePending is a review which is not published yet + ReviewTypePending ReviewType = iota + // ReviewTypeApprove approves changes + ReviewTypeApprove + // ReviewTypeComment gives general feedback + ReviewTypeComment + // ReviewTypeReject gives feedback blocking merge + ReviewTypeReject +) + +// Icon returns the corresponding icon for the review type +func (rt ReviewType) Icon() string { + switch rt { + case ReviewTypeApprove: + return "eye" + case ReviewTypeReject: + return "x" + default: + case ReviewTypeComment: + case ReviewTypeUnknown: + return "comment" + } + return "comment" +} + +// Review represents collection of code comments giving feedback for a PR +type Review struct { + ID int64 `xorm:"pk autoincr"` + Type ReviewType + Reviewer *User `xorm:"-"` + ReviewerID int64 `xorm:"index"` + Issue *Issue `xorm:"-"` + IssueID int64 `xorm:"index"` + Content string + + CreatedUnix util.TimeStamp `xorm:"INDEX created"` + UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` + + // CodeComments are the initial code comments of the review + CodeComments CodeComments `xorm:"-"` +} + +func (r *Review) loadCodeComments(e Engine) (err error) { + r.CodeComments, err = fetchCodeCommentsByReview(e, r.Issue, nil, r) + return +} + +// LoadCodeComments loads CodeComments +func (r *Review) LoadCodeComments() error { + return r.loadCodeComments(x) +} + +func (r *Review) loadIssue(e Engine) (err error) { + r.Issue, err = getIssueByID(e, r.IssueID) + return +} + +func (r *Review) loadReviewer(e Engine) (err error) { + if r.ReviewerID == 0 { + return nil + } + r.Reviewer, err = getUserByID(e, r.ReviewerID) + return +} + +func (r *Review) loadAttributes(e Engine) (err error) { + if err = r.loadReviewer(e); err != nil { + return + } + if err = r.loadIssue(e); err != nil { + return + } + return +} + +// LoadAttributes loads all attributes except CodeComments +func (r *Review) LoadAttributes() error { + return r.loadAttributes(x) +} + +// Publish will send notifications / actions to participants for all code comments; parts are concurrent +func (r *Review) Publish() error { + return r.publish(x) +} + +func (r *Review) publish(e *xorm.Engine) error { + if r.Type == ReviewTypePending || r.Type == ReviewTypeUnknown { + return fmt.Errorf("review cannot be published if type is pending or unknown") + } + if r.Issue == nil { + if err := r.loadIssue(e); err != nil { + return err + } + } + if err := r.Issue.loadRepo(e); err != nil { + return err + } + if len(r.CodeComments) == 0 { + if err := r.loadCodeComments(e); err != nil { + return err + } + } + for _, lines := range r.CodeComments { + for _, comments := range lines { + for _, comment := range comments { + go func(en *xorm.Engine, review *Review, comm *Comment) { + sess := en.NewSession() + defer sess.Close() + if err := sendCreateCommentAction(sess, &CreateCommentOptions{ + Doer: comm.Poster, + Issue: review.Issue, + Repo: review.Issue.Repo, + Type: comm.Type, + Content: comm.Content, + }, comm); err != nil { + log.Warn("sendCreateCommentAction: %v", err) + } + }(e, r, comment) + } + } + } + return nil +} + +func getReviewByID(e Engine, id int64) (*Review, error) { + review := new(Review) + if has, err := e.ID(id).Get(review); err != nil { + return nil, err + } else if !has { + return nil, ErrReviewNotExist{ID: id} + } else { + return review, nil + } +} + +// GetReviewByID returns the review by the given ID +func GetReviewByID(id int64) (*Review, error) { + return getReviewByID(x, id) +} + +// FindReviewOptions represent possible filters to find reviews +type FindReviewOptions struct { + Type ReviewType + IssueID int64 + ReviewerID int64 +} + +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 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: opts.Type, + Issue: opts.Issue, + IssueID: opts.Issue.ID, + Reviewer: opts.Reviewer, + ReviewerID: opts.Reviewer.ID, + Content: opts.Content, + } + if _, err := e.Insert(review); err != nil { + return nil, err + } + return review, nil +} + +// CreateReview creates a new review based on opts +func CreateReview(opts CreateReviewOptions) (*Review, error) { + return createReview(x, opts) +} + +func getCurrentReview(e Engine, reviewer *User, issue *Issue) (*Review, error) { + if reviewer == nil { + return nil, nil + } + reviews, err := findReviews(e, FindReviewOptions{ + Type: ReviewTypePending, + IssueID: issue.ID, + ReviewerID: reviewer.ID, + }) + if err != nil { + return nil, err + } + if len(reviews) == 0 { + return nil, ErrReviewNotExist{} + } + return reviews[0], nil +} + +// GetCurrentReview returns the current pending review of reviewer for given issue +func GetCurrentReview(reviewer *User, issue *Issue) (*Review, error) { + return getCurrentReview(x, reviewer, issue) +} + +// UpdateReview will update all cols of the given review in db +func UpdateReview(r *Review) error { + if _, err := x.ID(r.ID).AllCols().Update(r); err != nil { + return err + } + return nil +} |