mirror of https://gitee.com/answerdev/answer.git
Merge branch 'feat/0.5.0/timeline' into feat/0.6.0/user-role
# Conflicts: # internal/controller/tag_controller.go # internal/schema/activity.go # internal/service/activity/activity.go
This commit is contained in:
commit
74015c13eb
|
@ -35,12 +35,12 @@ var (
|
||||||
// @in header
|
// @in header
|
||||||
// @name Authorization
|
// @name Authorization
|
||||||
func main() {
|
func main() {
|
||||||
|
log.SetLogger(zap.NewLogger(
|
||||||
|
log.ParseLevel(logLevel), zap.WithName("answer"), zap.WithPath(logPath), zap.WithCallerFullPath()))
|
||||||
Execute()
|
Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
func runApp() {
|
func runApp() {
|
||||||
log.SetLogger(zap.NewLogger(
|
|
||||||
log.ParseLevel(logLevel), zap.WithName("answer"), zap.WithPath(logPath), zap.WithCallerFullPath()))
|
|
||||||
c, err := conf.ReadConfig(cli.GetConfigFilePath())
|
c, err := conf.ReadConfig(cli.GetConfigFilePath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -197,7 +197,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
||||||
activityCommon := activity_common2.NewActivityCommon(activityRepo)
|
activityCommon := activity_common2.NewActivityCommon(activityRepo)
|
||||||
activityActivityRepo := activity.NewActivityRepo(dataData)
|
activityActivityRepo := activity.NewActivityRepo(dataData)
|
||||||
commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo)
|
commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo)
|
||||||
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService)
|
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService)
|
||||||
activityController := controller.NewActivityController(activityCommon, activityService)
|
activityController := controller.NewActivityController(activityCommon, activityService)
|
||||||
roleController := controller_backyard.NewRoleController(roleService)
|
roleController := controller_backyard.NewRoleController(roleService)
|
||||||
answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_backyardReportController, userBackyardController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController, roleController)
|
answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_backyardReportController, userBackyardController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController, roleController)
|
||||||
|
|
|
@ -1,9 +1,21 @@
|
||||||
package constant
|
package constant
|
||||||
|
|
||||||
// question activity
|
|
||||||
|
|
||||||
type ActivityTypeKey string
|
type ActivityTypeKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ActEdited = "edited"
|
||||||
|
ActClosed = "closed"
|
||||||
|
ActVotedDown = "voted_down"
|
||||||
|
ActVotedUp = "voted_up"
|
||||||
|
ActVoteDown = "vote_down"
|
||||||
|
ActVoteUp = "vote_up"
|
||||||
|
ActUpVote = "upvote"
|
||||||
|
ActDownVote = "downvote"
|
||||||
|
ActFollow = "follow"
|
||||||
|
ActAccepted = "accepted"
|
||||||
|
ActAccept = "accept"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ActQuestionAsked ActivityTypeKey = "question.asked"
|
ActQuestionAsked ActivityTypeKey = "question.asked"
|
||||||
ActQuestionClosed ActivityTypeKey = "question.closed"
|
ActQuestionClosed ActivityTypeKey = "question.closed"
|
||||||
|
@ -12,29 +24,25 @@ const (
|
||||||
ActQuestionCommented ActivityTypeKey = "question.commented"
|
ActQuestionCommented ActivityTypeKey = "question.commented"
|
||||||
ActQuestionAccept ActivityTypeKey = "question.accept"
|
ActQuestionAccept ActivityTypeKey = "question.accept"
|
||||||
ActQuestionUpvote ActivityTypeKey = "question.upvote"
|
ActQuestionUpvote ActivityTypeKey = "question.upvote"
|
||||||
ActQuestionDownvote ActivityTypeKey = "question.downvote"
|
ActQuestionDownVote ActivityTypeKey = "question.downvote"
|
||||||
ActQuestionEdited ActivityTypeKey = "question.edited"
|
ActQuestionEdited ActivityTypeKey = "question.edited"
|
||||||
ActQuestionRollback ActivityTypeKey = "question.rollback"
|
ActQuestionRollback ActivityTypeKey = "question.rollback"
|
||||||
ActQuestionDeleted ActivityTypeKey = "question.deleted"
|
ActQuestionDeleted ActivityTypeKey = "question.deleted"
|
||||||
ActQuestionUndeleted ActivityTypeKey = "question.undeleted"
|
ActQuestionUndeleted ActivityTypeKey = "question.undeleted"
|
||||||
)
|
)
|
||||||
|
|
||||||
// answer activity
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ActAnswerAnswered ActivityTypeKey = "answer.answered"
|
ActAnswerAnswered ActivityTypeKey = "answer.answered"
|
||||||
ActAnswerCommented ActivityTypeKey = "answer.commented"
|
ActAnswerCommented ActivityTypeKey = "answer.commented"
|
||||||
ActAnswerAccept ActivityTypeKey = "answer.accept"
|
ActAnswerAccept ActivityTypeKey = "answer.accept"
|
||||||
ActAnswerUpvote ActivityTypeKey = "answer.upvote"
|
ActAnswerUpvote ActivityTypeKey = "answer.upvote"
|
||||||
ActAnswerDownvote ActivityTypeKey = "answer.downvote"
|
ActAnswerDownVote ActivityTypeKey = "answer.downvote"
|
||||||
ActAnswerEdited ActivityTypeKey = "answer.edited"
|
ActAnswerEdited ActivityTypeKey = "answer.edited"
|
||||||
ActAnswerRollback ActivityTypeKey = "answer.rollback"
|
ActAnswerRollback ActivityTypeKey = "answer.rollback"
|
||||||
ActAnswerDeleted ActivityTypeKey = "answer.deleted"
|
ActAnswerDeleted ActivityTypeKey = "answer.deleted"
|
||||||
ActAnswerUndeleted ActivityTypeKey = "answer.undeleted"
|
ActAnswerUndeleted ActivityTypeKey = "answer.undeleted"
|
||||||
)
|
)
|
||||||
|
|
||||||
// tag activity
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ActTagCreated ActivityTypeKey = "tag.created"
|
ActTagCreated ActivityTypeKey = "tag.created"
|
||||||
ActTagEdited ActivityTypeKey = "tag.edited"
|
ActTagEdited ActivityTypeKey = "tag.edited"
|
||||||
|
|
|
@ -39,6 +39,9 @@ func (ac *ActivityController) GetObjectTimeline(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
if userInfo := middleware.GetUserInfoFromContext(ctx); userInfo != nil {
|
||||||
|
req.IsAdmin = userInfo.IsAdmin
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := ac.activityService.GetObjectTimeline(ctx, req)
|
resp, err := ac.activityService.GetObjectTimeline(ctx, req)
|
||||||
handler.HandleResponse(ctx, err, resp)
|
handler.HandleResponse(ctx, err, resp)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"github.com/answerdev/answer/internal/base/handler"
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
"github.com/answerdev/answer/internal/base/middleware"
|
"github.com/answerdev/answer/internal/base/middleware"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
"github.com/answerdev/answer/internal/entity"
|
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
"github.com/answerdev/answer/internal/service"
|
"github.com/answerdev/answer/internal/service"
|
||||||
"github.com/answerdev/answer/internal/service/dashboard"
|
"github.com/answerdev/answer/internal/service/dashboard"
|
||||||
|
@ -268,10 +267,13 @@ func (ac *AnswerController) Adopted(ctx *gin.Context) {
|
||||||
// @Router /answer/admin/api/answer/status [put]
|
// @Router /answer/admin/api/answer/status [put]
|
||||||
// @Success 200 {object} handler.RespBody
|
// @Success 200 {object} handler.RespBody
|
||||||
func (ac *AnswerController) AdminSetAnswerStatus(ctx *gin.Context) {
|
func (ac *AnswerController) AdminSetAnswerStatus(ctx *gin.Context) {
|
||||||
req := &entity.AdminSetAnswerStatusRequest{}
|
req := &schema.AdminSetAnswerStatusRequest{}
|
||||||
if handler.BindAndCheck(ctx, req) {
|
if handler.BindAndCheck(ctx, req) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := ac.answerService.AdminSetAnswerStatus(ctx, req.AnswerID, req.StatusStr)
|
|
||||||
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
|
||||||
|
err := ac.answerService.AdminSetAnswerStatus(ctx, req)
|
||||||
handler.HandleResponse(ctx, err, gin.H{})
|
handler.HandleResponse(ctx, err, gin.H{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (tc *TagController) RemoveTag(ctx *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tc.tagService.RemoveTag(ctx, req.TagID)
|
err = tc.tagService.RemoveTag(ctx, req)
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,6 @@ type CmsAnswerSearch struct {
|
||||||
QuestionID string `validate:"omitempty,gt=0,lte=24" json:"question_id" form:"question_id" ` //Query string
|
QuestionID string `validate:"omitempty,gt=0,lte=24" json:"question_id" form:"question_id" ` //Query string
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdminSetAnswerStatusRequest struct {
|
|
||||||
StatusStr string `json:"status" form:"status"`
|
|
||||||
AnswerID string `json:"answer_id" form:"answer_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName answer table name
|
// TableName answer table name
|
||||||
func (Answer) TableName() string {
|
func (Answer) TableName() string {
|
||||||
return "answer"
|
return "answer"
|
||||||
|
|
|
@ -3,7 +3,7 @@ package entity
|
||||||
// Config config
|
// Config config
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ID int `xorm:"not null pk autoincr INT(11) id"`
|
ID int `xorm:"not null pk autoincr INT(11) id"`
|
||||||
Key string `xorm:"unique VARCHAR(32) key"`
|
Key string `xorm:"unique VARCHAR(128) key"`
|
||||||
Value string `xorm:"TEXT value"`
|
Value string `xorm:"TEXT value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,11 +63,12 @@ type QuestionWithTagsRevision struct {
|
||||||
|
|
||||||
// TagSimpleInfoForRevision tag simple info for revision
|
// TagSimpleInfoForRevision tag simple info for revision
|
||||||
type TagSimpleInfoForRevision struct {
|
type TagSimpleInfoForRevision struct {
|
||||||
ID string `xorm:"not null pk comment('tag_id') BIGINT(20) id"`
|
ID string `xorm:"not null pk comment('tag_id') BIGINT(20) id"`
|
||||||
MainTagID int64 `xorm:"not null default 0 BIGINT(20) main_tag_id"`
|
MainTagID int64 `xorm:"not null default 0 BIGINT(20) main_tag_id"`
|
||||||
SlugName string `xorm:"not null default '' unique VARCHAR(35) slug_name"`
|
MainTagSlugName string `xorm:"not null default '' VARCHAR(35) main_tag_slug_name"`
|
||||||
DisplayName string `xorm:"not null default '' VARCHAR(35) display_name"`
|
SlugName string `xorm:"not null default '' unique VARCHAR(35) slug_name"`
|
||||||
Recommend bool `xorm:"not null default false BOOL recommend"`
|
DisplayName string `xorm:"not null default '' VARCHAR(35) display_name"`
|
||||||
Reserved bool `xorm:"not null default false BOOL reserved"`
|
Recommend bool `xorm:"not null default false BOOL recommend"`
|
||||||
RevisionID string `xorm:"not null default 0 BIGINT(20) revision_id"`
|
Reserved bool `xorm:"not null default false BOOL reserved"`
|
||||||
|
RevisionID string `xorm:"not null default 0 BIGINT(20) revision_id"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,26 +195,26 @@ func initConfigTable(engine *xorm.Engine) error {
|
||||||
{ID: 32, Key: "question.follow", Value: `0`},
|
{ID: 32, Key: "question.follow", Value: `0`},
|
||||||
{ID: 33, Key: "email.config", Value: `{"from_name":"","from_email":"","smtp_host":"","smtp_port":465,"smtp_password":"","smtp_username":"","smtp_authentication":true,"encryption":"","register_title":"[{{.SiteName}}] Confirm your new account","register_body":"Welcome to {{.SiteName}}<br><br>\n\nClick the following link to confirm and activate your new account:<br>\n<a href='{{.RegisterUrl}}' target='_blank'>{{.RegisterUrl}}</a><br><br>\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n","pass_reset_title":"[{{.SiteName }}] Password reset","pass_reset_body":"Somebody asked to reset your password on [{{.SiteName}}].<br><br>\n\nIf it was not you, you can safely ignore this email.<br><br>\n\nClick the following link to choose a new password:<br>\n<a href='{{.PassResetUrl}}' target='_blank'>{{.PassResetUrl}}</a>\n","change_title":"[{{.SiteName}}] Confirm your new email address","change_body":"Confirm your new email address for {{.SiteName}} by clicking on the following link:<br><br>\n\n<a href='{{.ChangeEmailUrl}}' target='_blank'>{{.ChangeEmailUrl}}</a><br><br>\n\nIf you did not request this change, please ignore this email.\n","test_title":"[{{.SiteName}}] Test Email","test_body":"This is a test email."}`},
|
{ID: 33, Key: "email.config", Value: `{"from_name":"","from_email":"","smtp_host":"","smtp_port":465,"smtp_password":"","smtp_username":"","smtp_authentication":true,"encryption":"","register_title":"[{{.SiteName}}] Confirm your new account","register_body":"Welcome to {{.SiteName}}<br><br>\n\nClick the following link to confirm and activate your new account:<br>\n<a href='{{.RegisterUrl}}' target='_blank'>{{.RegisterUrl}}</a><br><br>\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n","pass_reset_title":"[{{.SiteName }}] Password reset","pass_reset_body":"Somebody asked to reset your password on [{{.SiteName}}].<br><br>\n\nIf it was not you, you can safely ignore this email.<br><br>\n\nClick the following link to choose a new password:<br>\n<a href='{{.PassResetUrl}}' target='_blank'>{{.PassResetUrl}}</a>\n","change_title":"[{{.SiteName}}] Confirm your new email address","change_body":"Confirm your new email address for {{.SiteName}} by clicking on the following link:<br><br>\n\n<a href='{{.ChangeEmailUrl}}' target='_blank'>{{.ChangeEmailUrl}}</a><br><br>\n\nIf you did not request this change, please ignore this email.\n","test_title":"[{{.SiteName}}] Test Email","test_body":"This is a test email."}`},
|
||||||
{ID: 35, Key: "tag.follow", Value: `0`},
|
{ID: 35, Key: "tag.follow", Value: `0`},
|
||||||
{ID: 36, Key: "rank.question.add", Value: `0`},
|
{ID: 36, Key: "rank.question.add", Value: `1`},
|
||||||
{ID: 37, Key: "rank.question.edit", Value: `0`},
|
{ID: 37, Key: "rank.question.edit", Value: `200`},
|
||||||
{ID: 38, Key: "rank.question.delete", Value: `0`},
|
{ID: 38, Key: "rank.question.delete", Value: `-1`},
|
||||||
{ID: 39, Key: "rank.question.vote_up", Value: `0`},
|
{ID: 39, Key: "rank.question.vote_up", Value: `15`},
|
||||||
{ID: 40, Key: "rank.question.vote_down", Value: `0`},
|
{ID: 40, Key: "rank.question.vote_down", Value: `125`},
|
||||||
{ID: 41, Key: "rank.answer.add", Value: `0`},
|
{ID: 41, Key: "rank.answer.add", Value: `1`},
|
||||||
{ID: 42, Key: "rank.answer.edit", Value: `0`},
|
{ID: 42, Key: "rank.answer.edit", Value: `200`},
|
||||||
{ID: 43, Key: "rank.answer.delete", Value: `0`},
|
{ID: 43, Key: "rank.answer.delete", Value: `-1`},
|
||||||
{ID: 44, Key: "rank.answer.accept", Value: `0`},
|
{ID: 44, Key: "rank.answer.accept", Value: `1`},
|
||||||
{ID: 45, Key: "rank.answer.vote_up", Value: `0`},
|
{ID: 45, Key: "rank.answer.vote_up", Value: `15`},
|
||||||
{ID: 46, Key: "rank.answer.vote_down", Value: `0`},
|
{ID: 46, Key: "rank.answer.vote_down", Value: `125`},
|
||||||
{ID: 47, Key: "rank.comment.add", Value: `0`},
|
{ID: 47, Key: "rank.comment.add", Value: `1`},
|
||||||
{ID: 48, Key: "rank.comment.edit", Value: `0`},
|
{ID: 48, Key: "rank.comment.edit", Value: `-1`},
|
||||||
{ID: 49, Key: "rank.comment.delete", Value: `0`},
|
{ID: 49, Key: "rank.comment.delete", Value: `-1`},
|
||||||
{ID: 50, Key: "rank.report.add", Value: `0`},
|
{ID: 50, Key: "rank.report.add", Value: `1`},
|
||||||
{ID: 51, Key: "rank.tag.add", Value: `0`},
|
{ID: 51, Key: "rank.tag.add", Value: `1`},
|
||||||
{ID: 52, Key: "rank.tag.edit", Value: `0`},
|
{ID: 52, Key: "rank.tag.edit", Value: `100`},
|
||||||
{ID: 53, Key: "rank.tag.delete", Value: `0`},
|
{ID: 53, Key: "rank.tag.delete", Value: `-1`},
|
||||||
{ID: 54, Key: "rank.tag.synonym", Value: `0`},
|
{ID: 54, Key: "rank.tag.synonym", Value: `20000`},
|
||||||
{ID: 55, Key: "rank.link.url_limit", Value: `0`},
|
{ID: 55, Key: "rank.link.url_limit", Value: `10`},
|
||||||
{ID: 56, Key: "rank.vote.detail", Value: `0`},
|
{ID: 56, Key: "rank.vote.detail", Value: `0`},
|
||||||
{ID: 57, Key: "reason.spam", Value: `{"name":"spam","description":"This post is an advertisement, or vandalism. It is not useful or relevant to the current topic."}`},
|
{ID: 57, Key: "reason.spam", Value: `{"name":"spam","description":"This post is an advertisement, or vandalism. It is not useful or relevant to the current topic."}`},
|
||||||
{ID: 58, Key: "reason.rude_or_abusive", Value: `{"name":"rude or abusive","description":"A reasonable person would find this content inappropriate for respectful discourse."}`},
|
{ID: 58, Key: "reason.rude_or_abusive", Value: `{"name":"rude or abusive","description":"A reasonable person would find this content inappropriate for respectful discourse."}`},
|
||||||
|
@ -266,6 +266,14 @@ func initConfigTable(engine *xorm.Engine) error {
|
||||||
{ID: 104, Key: "tag.rollback", Value: `0`},
|
{ID: 104, Key: "tag.rollback", Value: `0`},
|
||||||
{ID: 105, Key: "tag.deleted", Value: `0`},
|
{ID: 105, Key: "tag.deleted", Value: `0`},
|
||||||
{ID: 106, Key: "tag.undeleted", Value: `0`},
|
{ID: 106, Key: "tag.undeleted", Value: `0`},
|
||||||
|
{ID: 107, Key: "rank.comment.vote_up", Value: `1`},
|
||||||
|
{ID: 108, Key: "rank.comment.vote_down", Value: `1`},
|
||||||
|
{ID: 109, Key: "rank.question.edit_without_review", Value: `2000`},
|
||||||
|
{ID: 110, Key: "rank.answer.edit_without_review", Value: `2000`},
|
||||||
|
{ID: 111, Key: "rank.tag.edit_without_review", Value: `20000`},
|
||||||
|
{ID: 112, Key: "rank.answer.audit", Value: `2000`},
|
||||||
|
{ID: 113, Key: "rank.question.audit", Value: `2000`},
|
||||||
|
{ID: 114, Key: "rank.tag.audit", Value: `20000`},
|
||||||
}
|
}
|
||||||
_, err := engine.Insert(defaultConfigTable)
|
_, err := engine.Insert(defaultConfigTable)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -3,10 +3,90 @@ package migrations
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/answerdev/answer/internal/entity"
|
||||||
|
"github.com/segmentfault/pacman/log"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addActivityTimeline(x *xorm.Engine) error {
|
func addActivityTimeline(x *xorm.Engine) error {
|
||||||
|
// only increasing field length to 128
|
||||||
|
type Config struct {
|
||||||
|
Key string `xorm:"unique VARCHAR(128) key"`
|
||||||
|
}
|
||||||
|
if err := x.Sync(new(Config)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defaultConfigTable := []*entity.Config{
|
||||||
|
{ID: 36, Key: "rank.question.add", Value: `1`},
|
||||||
|
{ID: 37, Key: "rank.question.edit", Value: `200`},
|
||||||
|
{ID: 38, Key: "rank.question.delete", Value: `-1`},
|
||||||
|
{ID: 39, Key: "rank.question.vote_up", Value: `15`},
|
||||||
|
{ID: 40, Key: "rank.question.vote_down", Value: `125`},
|
||||||
|
{ID: 41, Key: "rank.answer.add", Value: `1`},
|
||||||
|
{ID: 42, Key: "rank.answer.edit", Value: `200`},
|
||||||
|
{ID: 43, Key: "rank.answer.delete", Value: `-1`},
|
||||||
|
{ID: 44, Key: "rank.answer.accept", Value: `1`},
|
||||||
|
{ID: 45, Key: "rank.answer.vote_up", Value: `15`},
|
||||||
|
{ID: 46, Key: "rank.answer.vote_down", Value: `125`},
|
||||||
|
{ID: 47, Key: "rank.comment.add", Value: `1`},
|
||||||
|
{ID: 48, Key: "rank.comment.edit", Value: `-1`},
|
||||||
|
{ID: 49, Key: "rank.comment.delete", Value: `-1`},
|
||||||
|
{ID: 50, Key: "rank.report.add", Value: `1`},
|
||||||
|
{ID: 51, Key: "rank.tag.add", Value: `1`},
|
||||||
|
{ID: 52, Key: "rank.tag.edit", Value: `100`},
|
||||||
|
{ID: 53, Key: "rank.tag.delete", Value: `-1`},
|
||||||
|
{ID: 54, Key: "rank.tag.synonym", Value: `20000`},
|
||||||
|
{ID: 55, Key: "rank.link.url_limit", Value: `10`},
|
||||||
|
{ID: 56, Key: "rank.vote.detail", Value: `0`},
|
||||||
|
|
||||||
|
{ID: 87, Key: "question.asked", Value: `0`},
|
||||||
|
{ID: 88, Key: "question.closed", Value: `0`},
|
||||||
|
{ID: 89, Key: "question.reopened", Value: `0`},
|
||||||
|
{ID: 90, Key: "question.answered", Value: `0`},
|
||||||
|
{ID: 91, Key: "question.commented", Value: `0`},
|
||||||
|
{ID: 92, Key: "question.accept", Value: `0`},
|
||||||
|
{ID: 93, Key: "question.edited", Value: `0`},
|
||||||
|
{ID: 94, Key: "question.rollback", Value: `0`},
|
||||||
|
{ID: 95, Key: "question.deleted", Value: `0`},
|
||||||
|
{ID: 96, Key: "question.undeleted", Value: `0`},
|
||||||
|
{ID: 97, Key: "answer.answered", Value: `0`},
|
||||||
|
{ID: 98, Key: "answer.commented", Value: `0`},
|
||||||
|
{ID: 99, Key: "answer.edited", Value: `0`},
|
||||||
|
{ID: 100, Key: "answer.rollback", Value: `0`},
|
||||||
|
{ID: 101, Key: "answer.undeleted", Value: `0`},
|
||||||
|
{ID: 102, Key: "tag.created", Value: `0`},
|
||||||
|
{ID: 103, Key: "tag.edited", Value: `0`},
|
||||||
|
{ID: 104, Key: "tag.rollback", Value: `0`},
|
||||||
|
{ID: 105, Key: "tag.deleted", Value: `0`},
|
||||||
|
{ID: 106, Key: "tag.undeleted", Value: `0`},
|
||||||
|
|
||||||
|
{ID: 107, Key: "rank.comment.vote_up", Value: `1`},
|
||||||
|
{ID: 108, Key: "rank.comment.vote_down", Value: `1`},
|
||||||
|
{ID: 109, Key: "rank.question.edit_without_review", Value: `2000`},
|
||||||
|
{ID: 110, Key: "rank.answer.edit_without_review", Value: `2000`},
|
||||||
|
{ID: 111, Key: "rank.tag.edit_without_review", Value: `20000`},
|
||||||
|
{ID: 112, Key: "rank.answer.audit", Value: `2000`},
|
||||||
|
{ID: 113, Key: "rank.question.audit", Value: `2000`},
|
||||||
|
{ID: 114, Key: "rank.tag.audit", Value: `20000`},
|
||||||
|
}
|
||||||
|
for _, c := range defaultConfigTable {
|
||||||
|
exist, err := x.Get(&entity.Config{ID: c.ID, Key: c.Key})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exist {
|
||||||
|
if _, err = x.Update(c, &entity.Config{ID: c.ID, Key: c.Key}); err != nil {
|
||||||
|
log.Errorf("update %+v config failed: %s", c, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err = x.Insert(&entity.Config{ID: c.ID, Key: c.Key, Value: c.Value}); err != nil {
|
||||||
|
log.Errorf("insert %+v config failed: %s", c, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Revision struct {
|
type Revision struct {
|
||||||
ReviewUserID int64 `xorm:"not null default 0 BIGINT(20) review_user_id"`
|
ReviewUserID int64 `xorm:"not null default 0 BIGINT(20) review_user_id"`
|
||||||
}
|
}
|
||||||
|
@ -15,5 +95,8 @@ func addActivityTimeline(x *xorm.Engine) error {
|
||||||
RevisionID int64 `xorm:"not null default 0 BIGINT(20) revision_id"`
|
RevisionID int64 `xorm:"not null default 0 BIGINT(20) revision_id"`
|
||||||
OriginalObjectID string `xorm:"not null default 0 BIGINT(20) original_object_id"`
|
OriginalObjectID string `xorm:"not null default 0 BIGINT(20) original_object_id"`
|
||||||
}
|
}
|
||||||
return x.Sync(new(Activity), new(Revision))
|
type Tag struct {
|
||||||
|
UserID string `xorm:"not null default 0 BIGINT(20) user_id"`
|
||||||
|
}
|
||||||
|
return x.Sync(new(Activity), new(Revision), new(Tag))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,13 @@ package activity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/answerdev/answer/internal/base/constant"
|
||||||
"github.com/answerdev/answer/internal/base/data"
|
"github.com/answerdev/answer/internal/base/data"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
"github.com/answerdev/answer/internal/entity"
|
"github.com/answerdev/answer/internal/entity"
|
||||||
|
"github.com/answerdev/answer/internal/repo/config"
|
||||||
"github.com/answerdev/answer/internal/service/activity"
|
"github.com/answerdev/answer/internal/service/activity"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +30,23 @@ func NewActivityRepo(
|
||||||
func (ar *activityRepo) GetObjectAllActivity(ctx context.Context, objectID string, showVote bool) (
|
func (ar *activityRepo) GetObjectAllActivity(ctx context.Context, objectID string, showVote bool) (
|
||||||
activityList []*entity.Activity, err error) {
|
activityList []*entity.Activity, err error) {
|
||||||
activityList = make([]*entity.Activity, 0)
|
activityList = make([]*entity.Activity, 0)
|
||||||
err = ar.data.DB.Find(&activityList, &entity.Activity{OriginalObjectID: objectID})
|
session := ar.data.DB.Desc("created_at")
|
||||||
|
|
||||||
|
if !showVote {
|
||||||
|
var activityTypeNotShown []int
|
||||||
|
for _, obj := range []string{constant.AnswerObjectType, constant.QuestionObjectType, constant.CommentObjectType} {
|
||||||
|
for _, act := range []string{
|
||||||
|
constant.ActVotedDown,
|
||||||
|
constant.ActVotedUp,
|
||||||
|
constant.ActVoteDown,
|
||||||
|
constant.ActVoteUp,
|
||||||
|
} {
|
||||||
|
activityTypeNotShown = append(activityTypeNotShown, config.Key2IDMapping[fmt.Sprintf("%s.%s", obj, act)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.NotIn("activity_type", activityTypeNotShown)
|
||||||
|
}
|
||||||
|
err = session.Find(&activityList, &entity.Activity{OriginalObjectID: objectID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,9 +144,11 @@ func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
|
||||||
if action == acceptAction {
|
if action == acceptAction {
|
||||||
addActivity.UserID = questionUserID
|
addActivity.UserID = questionUserID
|
||||||
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
|
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
|
||||||
|
addActivity.OriginalObjectID = questionObjID // if activity is 'accept' means this question is accept the answer.
|
||||||
} else {
|
} else {
|
||||||
addActivity.UserID = answerUserID
|
addActivity.UserID = answerUserID
|
||||||
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
|
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
|
||||||
|
addActivity.OriginalObjectID = answerObjID // if activity is 'accepted' means this answer was accepted.
|
||||||
}
|
}
|
||||||
if isSelf {
|
if isSelf {
|
||||||
addActivity.Rank = 0
|
addActivity.Rank = 0
|
||||||
|
@ -234,16 +236,17 @@ func (ar *AnswerActivityRepo) CancelAcceptAnswer(ctx context.Context,
|
||||||
return errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
return errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
|
||||||
}
|
}
|
||||||
addActivity := &entity.Activity{
|
addActivity := &entity.Activity{
|
||||||
ObjectID: answerObjID,
|
ObjectID: answerObjID,
|
||||||
OriginalObjectID: questionObjID,
|
ActivityType: activityType,
|
||||||
ActivityType: activityType,
|
Rank: -deltaRank,
|
||||||
Rank: -deltaRank,
|
HasRank: hasRank,
|
||||||
HasRank: hasRank,
|
|
||||||
}
|
}
|
||||||
if action == acceptAction {
|
if action == acceptAction {
|
||||||
addActivity.UserID = questionUserID
|
addActivity.UserID = questionUserID
|
||||||
|
addActivity.OriginalObjectID = questionObjID
|
||||||
} else {
|
} else {
|
||||||
addActivity.UserID = answerUserID
|
addActivity.UserID = answerUserID
|
||||||
|
addActivity.OriginalObjectID = answerObjID
|
||||||
}
|
}
|
||||||
addActivityList = append(addActivityList, addActivity)
|
addActivityList = append(addActivityList, addActivity)
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func Test_tagRepo_GetTagByID(t *testing.T) {
|
||||||
tagOnce.Do(addTagList)
|
tagOnce.Do(addTagList)
|
||||||
tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
|
tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
|
||||||
|
|
||||||
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID)
|
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, exist)
|
assert.True(t, exist)
|
||||||
assert.Equal(t, testTagList[0].SlugName, gotTag.SlugName)
|
assert.Equal(t, testTagList[0].SlugName, gotTag.SlugName)
|
||||||
|
@ -139,7 +139,7 @@ func Test_tagRepo_UpdateTag(t *testing.T) {
|
||||||
|
|
||||||
tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
|
tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
|
||||||
|
|
||||||
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID)
|
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, exist)
|
assert.True(t, exist)
|
||||||
assert.Equal(t, testTagList[0].DisplayName, gotTag.DisplayName)
|
assert.Equal(t, testTagList[0].DisplayName, gotTag.DisplayName)
|
||||||
|
@ -152,7 +152,7 @@ func Test_tagRepo_UpdateTagQuestionCount(t *testing.T) {
|
||||||
err := tagCommonRepo.UpdateTagQuestionCount(context.TODO(), testTagList[0].ID, 100)
|
err := tagCommonRepo.UpdateTagQuestionCount(context.TODO(), testTagList[0].ID, 100)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID)
|
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, exist)
|
assert.True(t, exist)
|
||||||
assert.Equal(t, 100, gotTag.QuestionCount)
|
assert.Equal(t, 100, gotTag.QuestionCount)
|
||||||
|
@ -172,7 +172,7 @@ func Test_tagRepo_UpdateTagSynonym(t *testing.T) {
|
||||||
|
|
||||||
tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
|
tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
|
||||||
|
|
||||||
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[2].ID)
|
gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[2].ID, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, exist)
|
assert.True(t, exist)
|
||||||
assert.Equal(t, testTagList[0].ID, fmt.Sprintf("%d", gotTag.MainTagID))
|
assert.Equal(t, testTagList[0].ID, fmt.Sprintf("%d", gotTag.MainTagID))
|
||||||
|
|
|
@ -122,12 +122,14 @@ func (tr *tagCommonRepo) GetTagListByNames(ctx context.Context, names []string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTagByID get tag one
|
// GetTagByID get tag one
|
||||||
func (tr *tagCommonRepo) GetTagByID(ctx context.Context, tagID string) (
|
func (tr *tagCommonRepo) GetTagByID(ctx context.Context, tagID string, includeDeleted bool) (
|
||||||
tag *entity.Tag, exist bool, err error,
|
tag *entity.Tag, exist bool, err error,
|
||||||
) {
|
) {
|
||||||
tag = &entity.Tag{}
|
tag = &entity.Tag{}
|
||||||
session := tr.data.DB.Where(builder.Eq{"id": tagID})
|
session := tr.data.DB.Where(builder.Eq{"id": tagID})
|
||||||
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
if !includeDeleted {
|
||||||
|
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
||||||
|
}
|
||||||
exist, err = session.Get(tag)
|
exist, err = session.Get(tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
return nil, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
|
||||||
|
|
|
@ -17,6 +17,7 @@ type GetObjectTimelineReq struct {
|
||||||
ObjectID string `validate:"omitempty,gt=0,lte=100" form:"object_id"`
|
ObjectID string `validate:"omitempty,gt=0,lte=100" form:"object_id"`
|
||||||
ShowVote bool `validate:"omitempty" form:"show_vote"`
|
ShowVote bool `validate:"omitempty" form:"show_vote"`
|
||||||
UserID string `json:"-"`
|
UserID string `json:"-"`
|
||||||
|
IsAdmin bool `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectTimelineResp get object timeline response
|
// GetObjectTimelineResp get object timeline response
|
||||||
|
@ -38,6 +39,7 @@ type ActObjectTimeline struct {
|
||||||
ObjectType string `json:"object_type"`
|
ObjectType string `json:"object_type"`
|
||||||
Cancelled bool `json:"cancelled"`
|
Cancelled bool `json:"cancelled"`
|
||||||
CancelledAt int64 `json:"cancelled_at"`
|
CancelledAt int64 `json:"cancelled_at"`
|
||||||
|
UserID string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActObjectInfo act object info
|
// ActObjectInfo act object info
|
||||||
|
@ -48,6 +50,7 @@ type ActObjectInfo struct {
|
||||||
AnswerID string `json:"answer_id"`
|
AnswerID string `json:"answer_id"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
|
MainTagSlugName string `json:"main_tag_slug_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectTimelineDetailReq get object timeline detail request
|
// GetObjectTimelineDetailReq get object timeline detail request
|
||||||
|
@ -65,7 +68,18 @@ type GetObjectTimelineDetailResp struct {
|
||||||
|
|
||||||
// ObjectTimelineDetail object timeline detail
|
// ObjectTimelineDetail object timeline detail
|
||||||
type ObjectTimelineDetail struct {
|
type ObjectTimelineDetail struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Tags []string `json:"tags"`
|
Tags []*ObjectTimelineTag `json:"tags"`
|
||||||
OriginalText string `json:"original_text"`
|
OriginalText string `json:"original_text"`
|
||||||
|
SlugName string `json:"slug_name"`
|
||||||
|
MainTagSlugName string `json:"main_tag_slug_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectTimelineTag object timeline tags
|
||||||
|
type ObjectTimelineTag struct {
|
||||||
|
SlugName string `json:"slug_name"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
MainTagSlugName string `json:"main_tag_slug_name"`
|
||||||
|
Recommend bool `json:"recommend"`
|
||||||
|
Reserved bool `json:"reserved"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,13 @@ type AdminAnswerInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnswerAdoptedReq struct {
|
type AnswerAdoptedReq struct {
|
||||||
QuestionID string `json:"question_id" ` // question_id
|
QuestionID string `json:"question_id"`
|
||||||
AnswerID string `json:"answer_id" `
|
AnswerID string `json:"answer_id"`
|
||||||
UserID string `json:"-" `
|
UserID string `json:"-" `
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AdminSetAnswerStatusRequest struct {
|
||||||
|
StatusStr string `json:"status"`
|
||||||
|
AnswerID string `json:"answer_id"`
|
||||||
|
UserID string `json:"-" `
|
||||||
|
}
|
||||||
|
|
|
@ -11,11 +11,13 @@ import (
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
"github.com/answerdev/answer/internal/service/activity_common"
|
"github.com/answerdev/answer/internal/service/activity_common"
|
||||||
"github.com/answerdev/answer/internal/service/comment_common"
|
"github.com/answerdev/answer/internal/service/comment_common"
|
||||||
|
"github.com/answerdev/answer/internal/service/meta"
|
||||||
"github.com/answerdev/answer/internal/service/object_info"
|
"github.com/answerdev/answer/internal/service/object_info"
|
||||||
"github.com/answerdev/answer/internal/service/revision_common"
|
"github.com/answerdev/answer/internal/service/revision_common"
|
||||||
"github.com/answerdev/answer/internal/service/tag_common"
|
"github.com/answerdev/answer/internal/service/tag_common"
|
||||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||||
"github.com/answerdev/answer/pkg/converter"
|
"github.com/answerdev/answer/pkg/converter"
|
||||||
|
"github.com/answerdev/answer/pkg/obj"
|
||||||
"github.com/segmentfault/pacman/log"
|
"github.com/segmentfault/pacman/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@ type ActivityService struct {
|
||||||
objectInfoService *object_info.ObjService
|
objectInfoService *object_info.ObjService
|
||||||
commentCommonService *comment_common.CommentCommonService
|
commentCommonService *comment_common.CommentCommonService
|
||||||
revisionService *revision_common.RevisionService
|
revisionService *revision_common.RevisionService
|
||||||
|
metaService *meta.MetaService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewActivityService new activity service
|
// NewActivityService new activity service
|
||||||
|
@ -44,6 +47,7 @@ func NewActivityService(
|
||||||
objectInfoService *object_info.ObjService,
|
objectInfoService *object_info.ObjService,
|
||||||
commentCommonService *comment_common.CommentCommonService,
|
commentCommonService *comment_common.CommentCommonService,
|
||||||
revisionService *revision_common.RevisionService,
|
revisionService *revision_common.RevisionService,
|
||||||
|
metaService *meta.MetaService,
|
||||||
) *ActivityService {
|
) *ActivityService {
|
||||||
return &ActivityService{
|
return &ActivityService{
|
||||||
objectInfoService: objectInfoService,
|
objectInfoService: objectInfoService,
|
||||||
|
@ -53,6 +57,7 @@ func NewActivityService(
|
||||||
tagCommonService: tagCommonService,
|
tagCommonService: tagCommonService,
|
||||||
commentCommonService: commentCommonService,
|
commentCommonService: commentCommonService,
|
||||||
revisionService: revisionService,
|
revisionService: revisionService,
|
||||||
|
metaService: metaService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,25 +69,10 @@ func (as *ActivityService) GetObjectTimeline(ctx context.Context, req *schema.Ge
|
||||||
Timeline: make([]*schema.ActObjectTimeline, 0),
|
Timeline: make([]*schema.ActObjectTimeline, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
objInfo, err := as.objectInfoService.GetInfo(ctx, req.ObjectID)
|
resp.ObjectInfo, err = as.getTimelineMainObjInfo(ctx, req.ObjectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp.ObjectInfo.Title = objInfo.Title
|
|
||||||
resp.ObjectInfo.ObjectType = objInfo.ObjectType
|
|
||||||
resp.ObjectInfo.QuestionID = objInfo.QuestionID
|
|
||||||
resp.ObjectInfo.AnswerID = objInfo.AnswerID
|
|
||||||
if len(objInfo.ObjectCreatorUserID) > 0 {
|
|
||||||
// get object creator user info
|
|
||||||
userBasicInfo, exist, err := as.userCommon.GetUserBasicInfoByID(ctx, objInfo.ObjectCreatorUserID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if exist {
|
|
||||||
resp.ObjectInfo.Username = userBasicInfo.Username
|
|
||||||
resp.ObjectInfo.DisplayName = userBasicInfo.DisplayName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
activityList, err := as.activityRepo.GetObjectAllActivity(ctx, req.ObjectID, req.ShowVote)
|
activityList, err := as.activityRepo.GetObjectAllActivity(ctx, req.ObjectID, req.ShowVote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,67 +86,155 @@ func (as *ActivityService) GetObjectTimeline(ctx context.Context, req *schema.Ge
|
||||||
Cancelled: act.Cancelled == entity.ActivityCancelled,
|
Cancelled: act.Cancelled == entity.ActivityCancelled,
|
||||||
ObjectID: act.ObjectID,
|
ObjectID: act.ObjectID,
|
||||||
}
|
}
|
||||||
|
item.ObjectType, _ = obj.GetObjectTypeStrByObjectID(act.ObjectID)
|
||||||
if item.Cancelled {
|
if item.Cancelled {
|
||||||
item.CancelledAt = act.CancelledAt.Unix()
|
item.CancelledAt = act.CancelledAt.Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
// database save activity type is number, change to activity type string is like "question.asked".
|
// database save activity type is number, change to activity type string is like "question.asked".
|
||||||
// so we need to cut the front part of '.'
|
// so we need to cut the front part of '.'
|
||||||
item.ObjectType, item.ActivityType, _ = strings.Cut(config.ID2KeyMapping[act.ActivityType], ".")
|
_, item.ActivityType, _ = strings.Cut(config.ID2KeyMapping[act.ActivityType], ".")
|
||||||
|
// format activity type string to show
|
||||||
isHidden, formattedActivityType := formatActivity(item.ActivityType)
|
if isHidden, formattedActivityType := formatActivity(item.ActivityType); isHidden {
|
||||||
if isHidden {
|
|
||||||
continue
|
continue
|
||||||
|
} else {
|
||||||
|
item.ActivityType = formattedActivityType
|
||||||
}
|
}
|
||||||
item.ActivityType = formattedActivityType
|
|
||||||
|
|
||||||
// get user info
|
// if activity is down vote, only admin can see who does it.
|
||||||
userBasicInfo, exist, err := as.userCommon.GetUserBasicInfoByID(ctx, act.UserID)
|
if item.ActivityType == constant.ActDownVote && !req.IsAdmin {
|
||||||
|
item.Username = "N/A"
|
||||||
|
item.UserDisplayName = "N/A"
|
||||||
|
} else {
|
||||||
|
item.UserID = act.UserID
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Comment = as.getTimelineActivityComment(ctx, item.ObjectID, item.ObjectType, item.ActivityType, item.RevisionID)
|
||||||
|
resp.Timeline = append(resp.Timeline, item)
|
||||||
|
}
|
||||||
|
as.formatTimelineUserInfo(ctx, resp.Timeline)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *ActivityService) getTimelineMainObjInfo(ctx context.Context, objectID string) (
|
||||||
|
resp *schema.ActObjectInfo, err error) {
|
||||||
|
resp = &schema.ActObjectInfo{}
|
||||||
|
objInfo, err := as.objectInfoService.GetInfo(ctx, objectID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.Title = objInfo.Title
|
||||||
|
if objInfo.ObjectType == constant.TagObjectType {
|
||||||
|
tag, exist, _ := as.tagCommonService.GetTagByID(ctx, objInfo.TagID)
|
||||||
|
if exist {
|
||||||
|
resp.Title = tag.SlugName
|
||||||
|
resp.MainTagSlugName = tag.MainTagSlugName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp.ObjectType = objInfo.ObjectType
|
||||||
|
resp.QuestionID = objInfo.QuestionID
|
||||||
|
resp.AnswerID = objInfo.AnswerID
|
||||||
|
if len(objInfo.ObjectCreatorUserID) > 0 {
|
||||||
|
// get object creator user info
|
||||||
|
userBasicInfo, exist, err := as.userCommon.GetUserBasicInfoByID(ctx, objInfo.ObjectCreatorUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
item.Username = userBasicInfo.Username
|
resp.Username = userBasicInfo.Username
|
||||||
item.UserDisplayName = userBasicInfo.DisplayName
|
resp.DisplayName = userBasicInfo.DisplayName
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
if item.ObjectType == constant.CommentObjectType {
|
func (as *ActivityService) getTimelineActivityComment(ctx context.Context, objectID, objectType,
|
||||||
comment, err := as.commentCommonService.GetComment(ctx, item.ObjectID)
|
activityType, revisionID string) (comment string) {
|
||||||
if err != nil {
|
if objectType == constant.CommentObjectType {
|
||||||
log.Error(err)
|
commentInfo, err := as.commentCommonService.GetComment(ctx, objectID)
|
||||||
} else {
|
if err != nil {
|
||||||
item.Comment = comment.ParsedText
|
log.Error(err)
|
||||||
|
} else {
|
||||||
|
return commentInfo.ParsedText
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if activityType == constant.ActEdited {
|
||||||
|
revision, err := as.revisionService.GetRevision(ctx, revisionID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
} else {
|
||||||
|
return revision.Log
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if activityType == constant.ActClosed {
|
||||||
|
// only question can be closed
|
||||||
|
metaInfo, err := as.metaService.GetMetaByObjectIdAndKey(ctx, objectID, entity.QuestionCloseReasonKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
} else {
|
||||||
|
closeMsg := &schema.CloseQuestionMeta{}
|
||||||
|
if err := json.Unmarshal([]byte(metaInfo.Value), closeMsg); err == nil {
|
||||||
|
return closeMsg.CloseMsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Timeline = append(resp.Timeline, item)
|
|
||||||
}
|
}
|
||||||
return
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (as *ActivityService) formatTimelineUserInfo(ctx context.Context, timeline []*schema.ActObjectTimeline) {
|
||||||
|
userExist := make(map[string]bool)
|
||||||
|
userIDs := make([]string, 0)
|
||||||
|
for _, info := range timeline {
|
||||||
|
if len(info.UserID) == 0 || userExist[info.UserID] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
userIDs = append(userIDs, info.UserID)
|
||||||
|
}
|
||||||
|
if len(userIDs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userInfoMapping, err := as.userCommon.BatchUserBasicInfoByID(ctx, userIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, info := range timeline {
|
||||||
|
if len(info.UserID) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if userInfo, ok := userInfoMapping[info.UserID]; ok {
|
||||||
|
info.Username = userInfo.Username
|
||||||
|
info.UserDisplayName = userInfo.DisplayName
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectTimelineDetail get object timeline
|
// GetObjectTimelineDetail get object timeline
|
||||||
func (as *ActivityService) GetObjectTimelineDetail(ctx context.Context, req *schema.GetObjectTimelineDetailReq) (
|
func (as *ActivityService) GetObjectTimelineDetail(ctx context.Context, req *schema.GetObjectTimelineDetailReq) (
|
||||||
resp *schema.GetObjectTimelineDetailResp, err error) {
|
resp *schema.GetObjectTimelineDetailResp, err error) {
|
||||||
resp = &schema.GetObjectTimelineDetailResp{}
|
resp = &schema.GetObjectTimelineDetailResp{}
|
||||||
resp.OldRevision, err = as.getOneObjectDetail(ctx, req.OldRevisionID)
|
resp.OldRevision, _ = as.getOneObjectDetail(ctx, req.OldRevisionID)
|
||||||
if err != nil {
|
resp.NewRevision, _ = as.getOneObjectDetail(ctx, req.NewRevisionID)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
resp.NewRevision, err = as.getOneObjectDetail(ctx, req.NewRevisionID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectTimelineDetail get object detail
|
// GetObjectTimelineDetail get object detail
|
||||||
func (as *ActivityService) getOneObjectDetail(ctx context.Context, revisionID string) (
|
func (as *ActivityService) getOneObjectDetail(ctx context.Context, revisionID string) (
|
||||||
resp *schema.ObjectTimelineDetail, err error) {
|
resp *schema.ObjectTimelineDetail, err error) {
|
||||||
resp = &schema.ObjectTimelineDetail{Tags: make([]string, 0)}
|
resp = &schema.ObjectTimelineDetail{Tags: make([]*schema.ObjectTimelineTag, 0)}
|
||||||
|
|
||||||
|
// if request revision is 0, return null object detail.
|
||||||
|
if revisionID == "0" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
revision, err := as.revisionService.GetRevision(ctx, revisionID)
|
revision, err := as.revisionService.GetRevision(ctx, revisionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
log.Warn(err)
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
objInfo, err := as.objectInfoService.GetInfo(ctx, revision.ObjectID)
|
objInfo, err := as.objectInfoService.GetInfo(ctx, revision.ObjectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -171,7 +249,13 @@ func (as *ActivityService) getOneObjectDetail(ctx context.Context, revisionID st
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
for _, tag := range data.Tags {
|
for _, tag := range data.Tags {
|
||||||
resp.Tags = append(resp.Tags, tag.SlugName)
|
resp.Tags = append(resp.Tags, &schema.ObjectTimelineTag{
|
||||||
|
SlugName: tag.SlugName,
|
||||||
|
DisplayName: tag.DisplayName,
|
||||||
|
MainTagSlugName: tag.MainTagSlugName,
|
||||||
|
Recommend: tag.Recommend,
|
||||||
|
Reserved: tag.Reserved,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
resp.Title = data.Title
|
resp.Title = data.Title
|
||||||
resp.OriginalText = data.OriginalText
|
resp.OriginalText = data.OriginalText
|
||||||
|
@ -189,8 +273,10 @@ func (as *ActivityService) getOneObjectDetail(ctx context.Context, revisionID st
|
||||||
log.Errorf("revision parsing error %s", err)
|
log.Errorf("revision parsing error %s", err)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
resp.Title = data.SlugName
|
resp.Title = data.DisplayName
|
||||||
resp.OriginalText = data.OriginalText
|
resp.OriginalText = data.OriginalText
|
||||||
|
resp.SlugName = data.SlugName
|
||||||
|
resp.MainTagSlugName = data.MainTagSlugName
|
||||||
default:
|
default:
|
||||||
log.Errorf("unknown object type %s", objInfo.ObjectType)
|
log.Errorf("unknown object type %s", objInfo.ObjectType)
|
||||||
}
|
}
|
||||||
|
@ -198,14 +284,19 @@ func (as *ActivityService) getOneObjectDetail(ctx context.Context, revisionID st
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatActivity(activityType string) (isHidden bool, formattedActivityType string) {
|
func formatActivity(activityType string) (isHidden bool, formattedActivityType string) {
|
||||||
if activityType == "voted_up" || activityType == "voted_down" || activityType == "accepted" {
|
if activityType == constant.ActVotedUp ||
|
||||||
|
activityType == constant.ActVotedDown ||
|
||||||
|
activityType == constant.ActFollow {
|
||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
if activityType == "vote_up" {
|
if activityType == constant.ActVoteUp {
|
||||||
return false, "upvote"
|
return false, constant.ActUpVote
|
||||||
}
|
}
|
||||||
if activityType == "vote_down" {
|
if activityType == constant.ActVoteDown {
|
||||||
return false, "downvote"
|
return false, constant.ActDownVote
|
||||||
|
}
|
||||||
|
if activityType == constant.ActAccepted {
|
||||||
|
return false, constant.ActAccept
|
||||||
}
|
}
|
||||||
return false, activityType
|
return false, activityType
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,19 +7,18 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/constant"
|
"github.com/answerdev/answer/internal/base/constant"
|
||||||
"github.com/answerdev/answer/internal/service/activity"
|
|
||||||
"github.com/answerdev/answer/internal/service/activity_common"
|
|
||||||
"github.com/answerdev/answer/internal/service/activity_queue"
|
|
||||||
"github.com/answerdev/answer/internal/service/notice_queue"
|
|
||||||
"github.com/answerdev/answer/internal/service/revision_common"
|
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
"github.com/answerdev/answer/internal/entity"
|
"github.com/answerdev/answer/internal/entity"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
|
"github.com/answerdev/answer/internal/service/activity"
|
||||||
|
"github.com/answerdev/answer/internal/service/activity_common"
|
||||||
|
"github.com/answerdev/answer/internal/service/activity_queue"
|
||||||
answercommon "github.com/answerdev/answer/internal/service/answer_common"
|
answercommon "github.com/answerdev/answer/internal/service/answer_common"
|
||||||
collectioncommon "github.com/answerdev/answer/internal/service/collection_common"
|
collectioncommon "github.com/answerdev/answer/internal/service/collection_common"
|
||||||
|
"github.com/answerdev/answer/internal/service/notice_queue"
|
||||||
"github.com/answerdev/answer/internal/service/permission"
|
"github.com/answerdev/answer/internal/service/permission"
|
||||||
questioncommon "github.com/answerdev/answer/internal/service/question_common"
|
questioncommon "github.com/answerdev/answer/internal/service/question_common"
|
||||||
|
"github.com/answerdev/answer/internal/service/revision_common"
|
||||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
"github.com/segmentfault/pacman/log"
|
"github.com/segmentfault/pacman/log"
|
||||||
|
@ -118,6 +117,12 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, req *schema.RemoveAns
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("delete answer activity change failed: %s", err.Error())
|
log.Errorf("delete answer activity change failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
activity_queue.AddActivity(&schema.ActivityMsg{
|
||||||
|
UserID: req.UserID,
|
||||||
|
ObjectID: answerInfo.ID,
|
||||||
|
OriginalObjectID: answerInfo.ID,
|
||||||
|
ActivityTypeKey: constant.ActAnswerDeleted,
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,12 +402,12 @@ func (as *AnswerService) Get(ctx context.Context, answerID, loginUserID string)
|
||||||
return info, questionInfo, has, nil
|
return info, questionInfo, has, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (as *AnswerService) AdminSetAnswerStatus(ctx context.Context, answerID string, setStatusStr string) error {
|
func (as *AnswerService) AdminSetAnswerStatus(ctx context.Context, req *schema.AdminSetAnswerStatusRequest) error {
|
||||||
setStatus, ok := entity.CmsAnswerSearchStatus[setStatusStr]
|
setStatus, ok := entity.CmsAnswerSearchStatus[req.StatusStr]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("question status does not exist")
|
return fmt.Errorf("question status does not exist")
|
||||||
}
|
}
|
||||||
answerInfo, exist, err := as.answerRepo.GetAnswer(ctx, answerID)
|
answerInfo, exist, err := as.answerRepo.GetAnswer(ctx, req.AnswerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -419,6 +424,13 @@ func (as *AnswerService) AdminSetAnswerStatus(ctx context.Context, answerID stri
|
||||||
err = as.answerActivityService.DeleteAnswer(ctx, answerInfo.ID, answerInfo.CreatedAt, answerInfo.VoteCount)
|
err = as.answerActivityService.DeleteAnswer(ctx, answerInfo.ID, answerInfo.CreatedAt, answerInfo.VoteCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("admin delete question then rank rollback error %s", err.Error())
|
log.Errorf("admin delete question then rank rollback error %s", err.Error())
|
||||||
|
} else {
|
||||||
|
activity_queue.AddActivity(&schema.ActivityMsg{
|
||||||
|
UserID: req.UserID,
|
||||||
|
ObjectID: answerInfo.ID,
|
||||||
|
OriginalObjectID: answerInfo.ID,
|
||||||
|
ActivityTypeKey: constant.ActAnswerDeleted,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,12 +150,19 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment
|
||||||
resp.UserStatus = userInfo.Status
|
resp.UserStatus = userInfo.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
activity_queue.AddActivity(&schema.ActivityMsg{
|
activityMsg := &schema.ActivityMsg{
|
||||||
UserID: comment.UserID,
|
UserID: comment.UserID,
|
||||||
ObjectID: comment.ID,
|
ObjectID: comment.ID,
|
||||||
OriginalObjectID: req.ObjectID,
|
OriginalObjectID: req.ObjectID,
|
||||||
ActivityTypeKey: constant.ActQuestionCommented,
|
ActivityTypeKey: constant.ActQuestionCommented,
|
||||||
})
|
}
|
||||||
|
switch objInfo.ObjectType {
|
||||||
|
case constant.QuestionObjectType:
|
||||||
|
activityMsg.ActivityTypeKey = constant.ActQuestionCommented
|
||||||
|
case constant.AnswerObjectType:
|
||||||
|
activityMsg.ActivityTypeKey = constant.ActAnswerCommented
|
||||||
|
}
|
||||||
|
activity_queue.AddActivity(activityMsg)
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ func (os *ObjService) GetUnreviewedRevisionInfo(ctx context.Context, objectID st
|
||||||
}
|
}
|
||||||
|
|
||||||
case constant.TagObjectType:
|
case constant.TagObjectType:
|
||||||
tagInfo, exist, err := os.tagRepo.GetTagByID(ctx, objectID)
|
tagInfo, exist, err := os.tagRepo.GetTagByID(ctx, objectID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ func (os *ObjService) GetInfo(ctx context.Context, objectID string) (objInfo *sc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case constant.TagObjectType:
|
case constant.TagObjectType:
|
||||||
tagInfo, exist, err := os.tagRepo.GetTagByID(ctx, objectID)
|
tagInfo, exist, err := os.tagRepo.GetTagByID(ctx, objectID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -740,13 +740,19 @@ func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, questionI
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("admin delete question then rank rollback error %s", err.Error())
|
log.Errorf("admin delete question then rank rollback error %s", err.Error())
|
||||||
}
|
}
|
||||||
|
activity_queue.AddActivity(&schema.ActivityMsg{
|
||||||
|
UserID: questionInfo.UserID,
|
||||||
|
ObjectID: questionInfo.ID,
|
||||||
|
OriginalObjectID: questionInfo.ID,
|
||||||
|
ActivityTypeKey: constant.ActQuestionDeleted,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if setStatus == entity.QuestionStatusAvailable && questionInfo.Status == entity.QuestionStatusClosed {
|
if setStatus == entity.QuestionStatusAvailable && questionInfo.Status == entity.QuestionStatusClosed {
|
||||||
activity_queue.AddActivity(&schema.ActivityMsg{
|
activity_queue.AddActivity(&schema.ActivityMsg{
|
||||||
UserID: questionInfo.UserID,
|
UserID: questionInfo.UserID,
|
||||||
ObjectID: questionInfo.ID,
|
ObjectID: questionInfo.ID,
|
||||||
OriginalObjectID: questionInfo.ID,
|
OriginalObjectID: questionInfo.ID,
|
||||||
ActivityTypeKey: constant.ActQuestionDeleted,
|
ActivityTypeKey: constant.ActQuestionReopened,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if setStatus == entity.QuestionStatusClosed && questionInfo.Status != entity.QuestionStatusClosed {
|
if setStatus == entity.QuestionStatusClosed && questionInfo.Status != entity.QuestionStatusClosed {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/answerdev/answer/internal/service/revision"
|
"github.com/answerdev/answer/internal/service/revision"
|
||||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
|
"github.com/segmentfault/pacman/log"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/entity"
|
"github.com/answerdev/answer/internal/entity"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
|
@ -55,6 +56,7 @@ func (rs *RevisionService) GetRevision(ctx context.Context, revisionID string) (
|
||||||
revision *entity.Revision, err error) {
|
revision *entity.Revision, err error) {
|
||||||
revisionInfo, exist, err := rs.revisionRepo.GetRevisionByID(ctx, revisionID)
|
revisionInfo, exist, err := rs.revisionRepo.GetRevisionByID(ctx, revisionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !exist {
|
if !exist {
|
||||||
|
|
|
@ -49,13 +49,17 @@ func NewTagService(
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTag delete tag
|
// RemoveTag delete tag
|
||||||
func (ts *TagService) RemoveTag(ctx context.Context, tagID string) (err error) {
|
func (ts *TagService) RemoveTag(ctx context.Context, req *schema.RemoveTagReq) (err error) {
|
||||||
// TODO permission
|
err = ts.tagRepo.RemoveTag(ctx, req.TagID)
|
||||||
|
|
||||||
err = ts.tagRepo.RemoveTag(ctx, tagID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
activity_queue.AddActivity(&schema.ActivityMsg{
|
||||||
|
UserID: req.UserID,
|
||||||
|
ObjectID: req.TagID,
|
||||||
|
OriginalObjectID: req.TagID,
|
||||||
|
ActivityTypeKey: constant.ActTagDeleted,
|
||||||
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ type TagCommonRepo interface {
|
||||||
GetTagBySlugName(ctx context.Context, slugName string) (tagInfo *entity.Tag, exist bool, err error)
|
GetTagBySlugName(ctx context.Context, slugName string) (tagInfo *entity.Tag, exist bool, err error)
|
||||||
GetTagListByName(ctx context.Context, name string, limit int, hasReserved bool) (tagList []*entity.Tag, err error)
|
GetTagListByName(ctx context.Context, name string, limit int, hasReserved bool) (tagList []*entity.Tag, err error)
|
||||||
GetTagListByNames(ctx context.Context, names []string) (tagList []*entity.Tag, err error)
|
GetTagListByNames(ctx context.Context, names []string) (tagList []*entity.Tag, err error)
|
||||||
GetTagByID(ctx context.Context, tagID string) (tag *entity.Tag, exist bool, err error)
|
GetTagByID(ctx context.Context, tagID string, includeDeleted bool) (tag *entity.Tag, exist bool, err error)
|
||||||
GetTagPage(ctx context.Context, page, pageSize int, tag *entity.Tag, queryCond string) (tagList []*entity.Tag, total int64, err error)
|
GetTagPage(ctx context.Context, page, pageSize int, tag *entity.Tag, queryCond string) (tagList []*entity.Tag, total int64, err error)
|
||||||
GetRecommendTagList(ctx context.Context) (tagList []*entity.Tag, err error)
|
GetRecommendTagList(ctx context.Context) (tagList []*entity.Tag, err error)
|
||||||
GetReservedTagList(ctx context.Context) (tagList []*entity.Tag, err error)
|
GetReservedTagList(ctx context.Context) (tagList []*entity.Tag, err error)
|
||||||
|
@ -222,7 +222,7 @@ func (ts *TagCommonService) AddTagList(ctx context.Context, tagList []*entity.Ta
|
||||||
|
|
||||||
// GetTagByID get object tag
|
// GetTagByID get object tag
|
||||||
func (ts *TagCommonService) GetTagByID(ctx context.Context, tagID string) (tag *entity.Tag, exist bool, err error) {
|
func (ts *TagCommonService) GetTagByID(ctx context.Context, tagID string) (tag *entity.Tag, exist bool, err error) {
|
||||||
tag, exist, err = ts.tagCommonRepo.GetTagByID(ctx, tagID)
|
tag, exist, err = ts.tagCommonRepo.GetTagByID(ctx, tagID, false)
|
||||||
if !exist {
|
if !exist {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue