Reaction: "rocket",
})
resp = session.MakeRequest(t, req, http.StatusCreated)
- var apiNewReaction api.ReactionResponse
+ var apiNewReaction api.Reaction
DecodeJSON(t, resp, &apiNewReaction)
//Add existing reaction
//Get end result of reaction list of issue #1
req = NewRequestf(t, "GET", urlStr)
resp = session.MakeRequest(t, req, http.StatusOK)
- var apiReactions []*api.ReactionResponse
+ var apiReactions []*api.Reaction
DecodeJSON(t, resp, &apiReactions)
- expectResponse := make(map[int]api.ReactionResponse)
- expectResponse[0] = api.ReactionResponse{
+ expectResponse := make(map[int]api.Reaction)
+ expectResponse[0] = api.Reaction{
User: user2.APIFormat(),
Reaction: "eyes",
Created: time.Unix(1573248003, 0),
Reaction: "+1",
})
resp = session.MakeRequest(t, req, http.StatusCreated)
- var apiNewReaction api.ReactionResponse
+ var apiNewReaction api.Reaction
DecodeJSON(t, resp, &apiNewReaction)
//Add existing reaction
//Get end result of reaction list of issue #1
req = NewRequestf(t, "GET", urlStr)
resp = session.MakeRequest(t, req, http.StatusOK)
- var apiReactions []*api.ReactionResponse
+ var apiReactions []*api.Reaction
DecodeJSON(t, resp, &apiReactions)
- expectResponse := make(map[int]api.ReactionResponse)
- expectResponse[0] = api.ReactionResponse{
+ expectResponse := make(map[int]api.Reaction)
+ expectResponse[0] = api.Reaction{
User: user2.APIFormat(),
Reaction: "laugh",
Created: time.Unix(1573248004, 0),
}
- expectResponse[1] = api.ReactionResponse{
+ expectResponse[1] = api.Reaction{
User: user1.APIFormat(),
Reaction: "laugh",
Created: time.Unix(1573248005, 0),
return fmt.Sprintf("'%s' is not an allowed reaction", err.Reaction)
}
+// 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)
+}
+
// __________ .__ .__ __________ __
// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
type FindReactionsOptions struct {
IssueID int64
CommentID int64
+ UserID int64
+ Reaction string
}
func (opts *FindReactionsOptions) toConds() builder.Cond {
} else if opts.CommentID == -1 {
cond = cond.And(builder.Eq{"reaction.comment_id": 0})
}
+ 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
}
UserID: opts.Doer.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 {
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 {
return nil, err
}
}
// CreateReaction creates reaction for issue or comment.
-func CreateReaction(opts *ReactionOptions) (reaction *Reaction, err error) {
+func CreateReaction(opts *ReactionOptions) (*Reaction, error) {
if !setting.UI.ReactionsMap[opts.Type] {
return nil, ErrForbiddenIssueReaction{opts.Type}
}
sess := x.NewSession()
defer sess.Close()
- if err = sess.Begin(); err != nil {
+ if err := sess.Begin(); err != nil {
return nil, err
}
- reaction, err = createReaction(sess, opts)
+ reaction, err := createReaction(sess, opts)
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 reaction, nil
Type: "heart",
})
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) {
user2 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
user3 := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User)
user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
- ghost := NewGhostUser()
issue1 := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
addReaction(t, user2, issue1, comment1, "heart")
addReaction(t, user3, issue1, comment1, "heart")
addReaction(t, user4, issue1, comment1, "+1")
- addReaction(t, ghost, issue1, comment1, "heart")
err := comment1.LoadReactions()
assert.NoError(t, err)
- assert.Len(t, comment1.Reactions, 5)
+ assert.Len(t, comment1.Reactions, 4)
reactions := comment1.Reactions.GroupByType()
- assert.Len(t, reactions["heart"], 4)
+ assert.Len(t, reactions["heart"], 3)
assert.Len(t, reactions["+1"], 1)
}
comment1 := AssertExistsAndLoadBean(t, &Comment{ID: 1}).(*Comment)
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})
}
Reaction string `json:"content"`
}
-// ReactionResponse contain one reaction
-type ReactionResponse struct {
+// Reaction contain one reaction
+type Reaction struct {
User *User `json:"user"`
Reaction string `json:"content"`
// swagger:strfmt date-time
// required: true
// responses:
// "200":
- // "$ref": "#/responses/ReactionResponseList"
+ // "$ref": "#/responses/ReactionList"
// "403":
// "$ref": "#/responses/forbidden"
return
}
- var result []api.ReactionResponse
+ var result []api.Reaction
for _, r := range reactions {
- result = append(result, api.ReactionResponse{
+ result = append(result, api.Reaction{
User: r.User.APIFormat(),
Reaction: r.Type,
Created: r.CreatedUnix.AsTime(),
// schema:
// "$ref": "#/definitions/EditReactionOption"
// responses:
+ // "200":
+ // "$ref": "#/responses/Reaction"
// "201":
- // "$ref": "#/responses/ReactionResponse"
+ // "$ref": "#/responses/Reaction"
// "403":
// "$ref": "#/responses/forbidden"
if err != nil {
if models.IsErrForbiddenIssueReaction(err) {
ctx.Error(http.StatusForbidden, err.Error(), err)
+ } else if models.IsErrReactionAlreadyExist(err) {
+ ctx.JSON(http.StatusOK, api.Reaction{
+ User: ctx.User.APIFormat(),
+ Reaction: reaction.Type,
+ Created: reaction.CreatedUnix.AsTime(),
+ })
} else {
ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err)
}
return
}
- _, err = reaction.LoadUser()
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "Reaction.LoadUser()", err)
- return
- }
- ctx.JSON(http.StatusCreated, api.ReactionResponse{
- User: reaction.User.APIFormat(),
+ ctx.JSON(http.StatusCreated, api.Reaction{
+ User: ctx.User.APIFormat(),
Reaction: reaction.Type,
Created: reaction.CreatedUnix.AsTime(),
})
// required: true
// responses:
// "200":
- // "$ref": "#/responses/ReactionResponseList"
+ // "$ref": "#/responses/ReactionList"
// "403":
// "$ref": "#/responses/forbidden"
return
}
- var result []api.ReactionResponse
+ var result []api.Reaction
for _, r := range reactions {
- result = append(result, api.ReactionResponse{
+ result = append(result, api.Reaction{
User: r.User.APIFormat(),
Reaction: r.Type,
Created: r.CreatedUnix.AsTime(),
// schema:
// "$ref": "#/definitions/EditReactionOption"
// responses:
+ // "200":
+ // "$ref": "#/responses/Reaction"
// "201":
- // "$ref": "#/responses/ReactionResponse"
+ // "$ref": "#/responses/Reaction"
// "403":
// "$ref": "#/responses/forbidden"
if err != nil {
if models.IsErrForbiddenIssueReaction(err) {
ctx.Error(http.StatusForbidden, err.Error(), err)
+ } else if models.IsErrReactionAlreadyExist(err) {
+ ctx.JSON(http.StatusOK, api.Reaction{
+ User: ctx.User.APIFormat(),
+ Reaction: reaction.Type,
+ Created: reaction.CreatedUnix.AsTime(),
+ })
} else {
ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err)
}
return
}
- _, err = reaction.LoadUser()
- if err != nil {
- ctx.Error(http.StatusInternalServerError, "Reaction.LoadUser()", err)
- return
- }
- ctx.JSON(http.StatusCreated, api.ReactionResponse{
- User: reaction.User.APIFormat(),
+ ctx.JSON(http.StatusCreated, api.Reaction{
+ User: ctx.User.APIFormat(),
Reaction: reaction.Type,
Created: reaction.CreatedUnix.AsTime(),
})
Body []api.StopWatch `json:"body"`
}
-// EditReactionOption
-// swagger:response EditReactionOption
-type swaggerEditReactionOption struct {
+// Reaction
+// swagger:response Reaction
+type swaggerReaction struct {
// in:body
- Body api.EditReactionOption `json:"body"`
+ Body api.Reaction `json:"body"`
}
-// ReactionResponse
-// swagger:response ReactionResponse
-type swaggerReactionResponse struct {
+// ReactionList
+// swagger:response ReactionList
+type swaggerReactionList struct {
// in:body
- Body api.ReactionResponse `json:"body"`
-}
-
-// ReactionResponseList
-// swagger:response ReactionResponseList
-type swaggerReactionResponseList struct {
- // in:body
- Body []api.ReactionResponse `json:"body"`
+ Body []api.Reaction `json:"body"`
}
// in:body
RepoTopicOptions api.RepoTopicOptions
+
+ // in:body
+ EditReactionOption api.EditReactionOption
}
],
"responses": {
"200": {
- "$ref": "#/responses/ReactionResponseList"
+ "$ref": "#/responses/ReactionList"
},
"403": {
"$ref": "#/responses/forbidden"
}
],
"responses": {
+ "200": {
+ "$ref": "#/responses/Reaction"
+ },
"201": {
- "$ref": "#/responses/ReactionResponse"
+ "$ref": "#/responses/Reaction"
},
"403": {
"$ref": "#/responses/forbidden"
],
"responses": {
"200": {
- "$ref": "#/responses/ReactionResponseList"
+ "$ref": "#/responses/ReactionList"
},
"403": {
"$ref": "#/responses/forbidden"
}
],
"responses": {
+ "200": {
+ "$ref": "#/responses/Reaction"
+ },
"201": {
- "$ref": "#/responses/ReactionResponse"
+ "$ref": "#/responses/Reaction"
},
"403": {
"$ref": "#/responses/forbidden"
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
- "ReactionResponse": {
- "description": "ReactionResponse contain one reaction",
+ "Reaction": {
+ "description": "Reaction contain one reaction",
"type": "object",
"properties": {
"content": {
}
}
},
- "EditReactionOption": {
- "description": "EditReactionOption",
- "schema": {
- "$ref": "#/definitions/EditReactionOption"
- }
- },
"EmailList": {
"description": "EmailList",
"schema": {
}
}
},
- "ReactionResponse": {
- "description": "ReactionResponse",
+ "Reaction": {
+ "description": "Reaction",
"schema": {
- "$ref": "#/definitions/ReactionResponse"
+ "$ref": "#/definitions/Reaction"
}
},
- "ReactionResponseList": {
- "description": "ReactionResponseList",
+ "ReactionList": {
+ "description": "ReactionList",
"schema": {
"type": "array",
"items": {
- "$ref": "#/definitions/ReactionResponse"
+ "$ref": "#/definitions/Reaction"
}
}
},
"parameterBodies": {
"description": "parameterBodies",
"schema": {
- "$ref": "#/definitions/RepoTopicOptions"
+ "$ref": "#/definitions/EditReactionOption"
}
},
"redirect": {