* add ErrReactionAlreadyExist * extend FindReactionsOptions * createReaction check if exit before create
This commit is contained in:
parent
b4b8c9679f
commit
c63a80138a
3 changed files with 51 additions and 12 deletions
|
@ -1104,6 +1104,21 @@ func (err ErrNewIssueInsert) Error() string {
|
||||||
return err.OriginalError.Error()
|
return err.OriginalError.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrReactionAlreadyExist is used when a existing reaction was try to created
|
||||||
|
type ErrReactionAlreadyExist struct {
|
||||||
|
Reaction string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrReactionAlreadyExist checks if an error is a ErrReactionAlreadyExist.
|
||||||
|
func IsErrReactionAlreadyExist(err error) bool {
|
||||||
|
_, ok := err.(ErrReactionAlreadyExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrReactionAlreadyExist) Error() string {
|
||||||
|
return fmt.Sprintf("reaction '%s' already exists", err.Reaction)
|
||||||
|
}
|
||||||
|
|
||||||
// __________ .__ .__ __________ __
|
// __________ .__ .__ __________ __
|
||||||
// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_
|
// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_
|
||||||
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
|
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
|
||||||
|
|
|
@ -30,6 +30,8 @@ type Reaction struct {
|
||||||
type FindReactionsOptions struct {
|
type FindReactionsOptions struct {
|
||||||
IssueID int64
|
IssueID int64
|
||||||
CommentID int64
|
CommentID int64
|
||||||
|
UserID int64
|
||||||
|
Reaction string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts *FindReactionsOptions) toConds() builder.Cond {
|
func (opts *FindReactionsOptions) toConds() builder.Cond {
|
||||||
|
@ -40,6 +42,13 @@ func (opts *FindReactionsOptions) toConds() builder.Cond {
|
||||||
if opts.CommentID > 0 {
|
if opts.CommentID > 0 {
|
||||||
cond = cond.And(builder.Eq{"reaction.comment_id": opts.CommentID})
|
cond = cond.And(builder.Eq{"reaction.comment_id": opts.CommentID})
|
||||||
}
|
}
|
||||||
|
if opts.UserID > 0 {
|
||||||
|
cond = cond.And(builder.Eq{"reaction.user_id": opts.UserID})
|
||||||
|
}
|
||||||
|
if opts.Reaction != "" {
|
||||||
|
cond = cond.And(builder.Eq{"reaction.type": opts.Reaction})
|
||||||
|
}
|
||||||
|
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +66,25 @@ func createReaction(e *xorm.Session, opts *ReactionOptions) (*Reaction, error) {
|
||||||
UserID: opts.Doer.ID,
|
UserID: opts.Doer.ID,
|
||||||
IssueID: opts.Issue.ID,
|
IssueID: opts.Issue.ID,
|
||||||
}
|
}
|
||||||
|
findOpts := FindReactionsOptions{
|
||||||
|
IssueID: opts.Issue.ID,
|
||||||
|
CommentID: -1, // reaction to issue only
|
||||||
|
Reaction: opts.Type,
|
||||||
|
UserID: opts.Doer.ID,
|
||||||
|
}
|
||||||
if opts.Comment != nil {
|
if opts.Comment != nil {
|
||||||
reaction.CommentID = opts.Comment.ID
|
reaction.CommentID = opts.Comment.ID
|
||||||
|
findOpts.CommentID = opts.Comment.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
existingR, err := findReactions(e, findOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(existingR) > 0 {
|
||||||
|
return existingR[0], ErrReactionAlreadyExist{Reaction: opts.Type}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := e.Insert(reaction); err != nil {
|
if _, err := e.Insert(reaction); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -76,19 +101,19 @@ type ReactionOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateReaction creates reaction for issue or comment.
|
// CreateReaction creates reaction for issue or comment.
|
||||||
func CreateReaction(opts *ReactionOptions) (reaction *Reaction, err error) {
|
func CreateReaction(opts *ReactionOptions) (*Reaction, error) {
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err = sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
reaction, err = createReaction(sess, opts)
|
reaction, err := createReaction(sess, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return reaction, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
if err := sess.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return reaction, nil
|
return reaction, nil
|
||||||
|
|
|
@ -50,9 +50,10 @@ func TestIssueAddDuplicateReaction(t *testing.T) {
|
||||||
Type: "heart",
|
Type: "heart",
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, reaction)
|
assert.Equal(t, ErrReactionAlreadyExist{Reaction: "heart"}, err)
|
||||||
|
|
||||||
AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID})
|
existingR := AssertExistsAndLoadBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID}).(*Reaction)
|
||||||
|
assert.Equal(t, existingR.ID, reaction.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssueDeleteReaction(t *testing.T) {
|
func TestIssueDeleteReaction(t *testing.T) {
|
||||||
|
@ -129,7 +130,6 @@ func TestIssueCommentDeleteReaction(t *testing.T) {
|
||||||
user2 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
user2 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||||
user3 := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User)
|
user3 := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User)
|
||||||
user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
|
user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
|
||||||
ghost := NewGhostUser()
|
|
||||||
|
|
||||||
issue1 := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
|
issue1 := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
|
||||||
|
|
||||||
|
@ -139,14 +139,13 @@ func TestIssueCommentDeleteReaction(t *testing.T) {
|
||||||
addReaction(t, user2, issue1, comment1, "heart")
|
addReaction(t, user2, issue1, comment1, "heart")
|
||||||
addReaction(t, user3, issue1, comment1, "heart")
|
addReaction(t, user3, issue1, comment1, "heart")
|
||||||
addReaction(t, user4, issue1, comment1, "+1")
|
addReaction(t, user4, issue1, comment1, "+1")
|
||||||
addReaction(t, ghost, issue1, comment1, "heart")
|
|
||||||
|
|
||||||
err := comment1.LoadReactions()
|
err := comment1.LoadReactions()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, comment1.Reactions, 5)
|
assert.Len(t, comment1.Reactions, 4)
|
||||||
|
|
||||||
reactions := comment1.Reactions.GroupByType()
|
reactions := comment1.Reactions.GroupByType()
|
||||||
assert.Len(t, reactions["heart"], 4)
|
assert.Len(t, reactions["heart"], 3)
|
||||||
assert.Len(t, reactions["+1"], 1)
|
assert.Len(t, reactions["+1"], 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +159,7 @@ func TestIssueCommentReactionCount(t *testing.T) {
|
||||||
comment1 := AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)
|
comment1 := AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)
|
||||||
|
|
||||||
addReaction(t, user1, issue1, comment1, "heart")
|
addReaction(t, user1, issue1, comment1, "heart")
|
||||||
DeleteCommentReaction(user1, issue1, comment1, "heart")
|
assert.NoError(t, DeleteCommentReaction(user1, issue1, comment1, "heart"))
|
||||||
|
|
||||||
AssertNotExistsBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID, CommentID: comment1.ID})
|
AssertNotExistsBean(t, &Reaction{Type: "heart", UserID: user1.ID, IssueID: issue1.ID, CommentID: comment1.ID})
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue