feat(notification): add upvote and down vote notification

This commit is contained in:
LinkinStars 2023-05-04 19:22:25 +08:00
parent 3952439d49
commit c56d54b0fe
5 changed files with 138 additions and 33 deletions

View File

@ -5,14 +5,24 @@ const (
UpdateQuestion = "notification.action.update_question"
// AnswerTheQuestion answer the question
AnswerTheQuestion = "notification.action.answer_the_question"
// UpVotedTheQuestion up voted the question
UpVotedTheQuestion = "notification.action.up_voted_question"
// DownVotedTheQuestion down voted the question
DownVotedTheQuestion = "notification.action.down_voted_question"
// UpdateAnswer update answer
UpdateAnswer = "notification.action.update_answer"
// AcceptAnswer accept answer
AcceptAnswer = "notification.action.accept_answer"
// UpVotedTheAnswer up voted the answer
UpVotedTheAnswer = "notification.action.up_voted_answer"
// DownVotedTheAnswer down voted the answer
DownVotedTheAnswer = "notification.action.down_voted_answer"
// CommentQuestion comment question
CommentQuestion = "notification.action.comment_question"
// CommentAnswer comment answer
CommentAnswer = "notification.action.comment_answer"
// UpVotedTheComment up voted the comment
UpVotedTheComment = "notification.action.up_voted_comment"
// ReplyToYou reply to you
ReplyToYou = "notification.action.reply_to_you"
// MentionYou mention you

View File

@ -5,6 +5,7 @@ import (
"strings"
"time"
"github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/pkg/converter"
"github.com/answerdev/answer/internal/base/pager"
@ -70,7 +71,9 @@ var LimitDownActions = map[string][]string{
func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUserID string, actions []string) (resp *schema.VoteResp, err error) {
resp = &schema.VoteResp{}
notificationUserIDs := make([]string, 0)
achievementNotificationUserIDs := make([]string, 0)
sendInboxNotification := false
upVote := false
_, err = vr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
result = nil
for _, action := range actions {
@ -127,7 +130,7 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
if isReachStandard {
insertActivity.Rank = 0
}
notificationUserIDs = append(notificationUserIDs, activityUserID)
achievementNotificationUserIDs = append(achievementNotificationUserIDs, activityUserID)
}
if has {
@ -142,13 +145,17 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
if err != nil {
return nil, err
}
sendInboxNotification = true
}
// update votes
if action == "vote_down" || action == "vote_up" {
if action == constant.ActVoteDown || action == constant.ActVoteUp {
votes := 1
if action == "vote_down" {
if action == constant.ActVoteDown {
upVote = false
votes = -1
} else {
upVote = true
}
err = vr.updateVotes(ctx, session, objectID, votes)
if err != nil {
@ -165,9 +172,12 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
resp, err = vr.GetVoteResultByObjectId(ctx, objectID)
resp.VoteStatus = vr.voteCommon.GetVoteStatus(ctx, objectID, userID)
for _, activityUserID := range notificationUserIDs {
for _, activityUserID := range achievementNotificationUserIDs {
vr.sendNotification(ctx, activityUserID, objectUserID, objectID)
}
if sendInboxNotification {
vr.sendVoteInboxNotification(userID, objectUserID, objectID, upVote)
}
return
}
@ -441,3 +451,40 @@ func (vr *VoteRepo) sendNotification(ctx context.Context, activityUserID, object
}
notice_queue.AddNotification(msg)
}
func (vr *VoteRepo) sendVoteInboxNotification(triggerUserID, receiverUserID, objectID string, upvote bool) {
if triggerUserID == receiverUserID {
return
}
objectType, _ := obj.GetObjectTypeStrByObjectID(objectID)
msg := &schema.NotificationMsg{
TriggerUserID: triggerUserID,
ReceiverUserID: receiverUserID,
Type: schema.NotificationTypeInbox,
ObjectID: objectID,
ObjectType: objectType,
}
if objectType == constant.QuestionObjectType {
if upvote {
msg.NotificationAction = constant.UpVotedTheQuestion
} else {
msg.NotificationAction = constant.DownVotedTheQuestion
}
}
if objectType == constant.AnswerObjectType {
if upvote {
msg.NotificationAction = constant.UpVotedTheAnswer
} else {
msg.NotificationAction = constant.DownVotedTheAnswer
}
}
if objectType == constant.CommentObjectType {
if upvote {
msg.NotificationAction = constant.UpVotedTheComment
}
}
if len(msg.NotificationAction) > 0 {
notice_queue.AddNotification(msg)
}
}

View File

@ -63,9 +63,23 @@ func (g *GetPluginConfigResp) SetConfigFields(ctx *gin.Context, fields []plugin.
configField.UIOptions.Label = field.UIOptions.Label.Translate(ctx)
configField.UIOptions.Text = field.UIOptions.Text.Translate(ctx)
if field.UIOptions.Action != nil {
configField.UIOptions.Action = &ConfigFieldUIOptionAction{
Url: field.UIOptions.Action.Url,
uiOptionAction := &UIOptionAction{
Url: field.UIOptions.Action.Url,
Method: field.UIOptions.Action.Method,
}
if field.UIOptions.Action.Loading != nil {
uiOptionAction.Loading = &LoadingAction{
Text: field.UIOptions.Action.Loading.Text.Translate(ctx),
State: string(field.UIOptions.Action.Loading.State),
}
}
if field.UIOptions.Action.OnComplete != nil {
uiOptionAction.OnCompleteAction = &OnCompleteAction{
ToastReturnMessage: field.UIOptions.Action.OnComplete.ToastReturnMessage,
RefreshFormConfig: field.UIOptions.Action.OnComplete.RefreshFormConfig,
}
}
configField.UIOptions.Action = uiOptionAction
}
for _, option := range field.Options {
@ -90,13 +104,13 @@ type ConfigField struct {
}
type ConfigFieldUIOptions struct {
Placeholder string `json:"placeholder,omitempty"`
Rows string `json:"rows,omitempty"`
InputType string `json:"input_type,omitempty"`
Label string `json:"label,omitempty"`
Action *ConfigFieldUIOptionAction `json:"action,omitempty"`
Variant string `json:"variant,omitempty"`
Text string `json:"text,omitempty"`
Placeholder string `json:"placeholder,omitempty"`
Rows string `json:"rows,omitempty"`
InputType string `json:"input_type,omitempty"`
Label string `json:"label,omitempty"`
Action *UIOptionAction `json:"action,omitempty"`
Variant string `json:"variant,omitempty"`
Text string `json:"text,omitempty"`
}
type ConfigFieldOption struct {
@ -104,8 +118,21 @@ type ConfigFieldOption struct {
Value string `json:"value"`
}
type ConfigFieldUIOptionAction struct {
Url string `json:"url"`
type UIOptionAction struct {
Url string `json:"url"`
Method string `json:"method,omitempty"`
Loading *LoadingAction `json:"loading,omitempty"`
OnCompleteAction *OnCompleteAction `json:"on_complete,omitempty"`
}
type LoadingAction struct {
Text string `json:"text"`
State string `json:"state"`
}
type OnCompleteAction struct {
ToastReturnMessage bool `json:"toast_return_message"`
RefreshFormConfig bool `json:"refresh_form_config"`
}
type UpdatePluginConfigReq struct {

View File

@ -63,12 +63,12 @@ func NewVoteService(
}
// VoteUp vote up
func (as *VoteService) VoteUp(ctx context.Context, dto *schema.VoteDTO) (voteResp *schema.VoteResp, err error) {
func (vs *VoteService) VoteUp(ctx context.Context, dto *schema.VoteDTO) (voteResp *schema.VoteResp, err error) {
voteResp = &schema.VoteResp{}
var objectUserID string
objectUserID, err = as.GetObjectUserID(ctx, dto.ObjectID)
objectUserID, err = vs.GetObjectUserID(ctx, dto.ObjectID)
if err != nil {
return
}
@ -80,19 +80,19 @@ func (as *VoteService) VoteUp(ctx context.Context, dto *schema.VoteDTO) (voteRes
}
if dto.IsCancel {
return as.voteRepo.VoteUpCancel(ctx, dto.ObjectID, dto.UserID, objectUserID)
return vs.voteRepo.VoteUpCancel(ctx, dto.ObjectID, dto.UserID, objectUserID)
} else {
return as.voteRepo.VoteUp(ctx, dto.ObjectID, dto.UserID, objectUserID)
return vs.voteRepo.VoteUp(ctx, dto.ObjectID, dto.UserID, objectUserID)
}
}
// VoteDown vote down
func (as *VoteService) VoteDown(ctx context.Context, dto *schema.VoteDTO) (voteResp *schema.VoteResp, err error) {
func (vs *VoteService) VoteDown(ctx context.Context, dto *schema.VoteDTO) (voteResp *schema.VoteResp, err error) {
voteResp = &schema.VoteResp{}
var objectUserID string
objectUserID, err = as.GetObjectUserID(ctx, dto.ObjectID)
objectUserID, err = vs.GetObjectUserID(ctx, dto.ObjectID)
if err != nil {
return
}
@ -104,9 +104,9 @@ func (as *VoteService) VoteDown(ctx context.Context, dto *schema.VoteDTO) (voteR
}
if dto.IsCancel {
return as.voteRepo.VoteDownCancel(ctx, dto.ObjectID, dto.UserID, objectUserID)
return vs.voteRepo.VoteDownCancel(ctx, dto.ObjectID, dto.UserID, objectUserID)
} else {
return as.voteRepo.VoteDown(ctx, dto.ObjectID, dto.UserID, objectUserID)
return vs.voteRepo.VoteDown(ctx, dto.ObjectID, dto.UserID, objectUserID)
}
}

View File

@ -44,13 +44,13 @@ type ConfigField struct {
}
type ConfigFieldUIOptions struct {
Placeholder Translator `json:"placeholder,omitempty"`
Rows string `json:"rows,omitempty"`
InputType InputType `json:"input_type,omitempty"`
Label Translator `json:"label,omitempty"`
Action *ConfigFieldUIOptionAction `json:"action,omitempty"`
Variant string `json:"variant,omitempty"`
Text Translator `json:"text,omitempty"`
Placeholder Translator `json:"placeholder,omitempty"`
Rows string `json:"rows,omitempty"`
InputType InputType `json:"input_type,omitempty"`
Label Translator `json:"label,omitempty"`
Action *UIOptionAction `json:"action,omitempty"`
Variant string `json:"variant,omitempty"`
Text Translator `json:"text,omitempty"`
}
type ConfigFieldOption struct {
@ -58,8 +58,29 @@ type ConfigFieldOption struct {
Value string `json:"value"`
}
type ConfigFieldUIOptionAction struct {
Url string `json:"url"`
type UIOptionAction struct {
Url string `json:"url"`
Method string `json:"method,omitempty"`
Loading *LoadingAction `json:"loading,omitempty"`
OnComplete *OnCompleteAction `json:"on_complete,omitempty"`
}
const (
LoadingActionStateNone LoadingActionType = "none"
LoadingActionStatePending LoadingActionType = "pending"
LoadingActionStateComplete LoadingActionType = "completed"
)
type LoadingActionType string
type LoadingAction struct {
Text Translator `json:"text"`
State LoadingActionType `json:"state"`
}
type OnCompleteAction struct {
ToastReturnMessage bool `json:"toast_return_message"`
RefreshFormConfig bool `json:"refresh_form_config"`
}
type Config interface {