diff --git a/docs/docs.go b/docs/docs.go index 2b2e1d70..897fcd66 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -3685,6 +3685,49 @@ const docTemplate = `{ } } }, + "/answer/api/v1/plugin/status": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get all plugins status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Plugin" + ], + "summary": "get all plugins status", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.GetPluginListResp" + } + } + } + } + ] + } + } + } + } + }, "/answer/api/v1/post/render": { "post": { "security": [ @@ -7278,6 +7321,10 @@ const docTemplate = `{ "description": "username", "type": "string" }, + "visit_token": { + "description": "visit token", + "type": "string" + }, "website": { "description": "website", "type": "string" @@ -7679,27 +7726,21 @@ const docTemplate = `{ "type": "object", "properties": { "created_at": { - "description": "created time", "type": "integer" }, "description": { - "description": "description text", "type": "string" }, "display_name": { - "description": "display name", "type": "string" }, "excerpt": { - "description": "excerpt", "type": "string" }, "follow_count": { - "description": "follower amount", "type": "integer" }, "is_follower": { - "description": "is follower", "type": "boolean" }, "main_tag_slug_name": { @@ -7707,22 +7748,18 @@ const docTemplate = `{ "type": "string" }, "member_actions": { - "description": "MemberActions", "type": "array", "items": { "$ref": "#/definitions/schema.PermissionMemberAction" } }, "original_text": { - "description": "original text", "type": "string" }, "parsed_text": { - "description": "parsed text", "type": "string" }, "question_count": { - "description": "question amount", "type": "integer" }, "recommend": { @@ -7732,15 +7769,15 @@ const docTemplate = `{ "type": "boolean" }, "slug_name": { - "description": "slug name", + "type": "string" + }, + "status": { "type": "string" }, "tag_id": { - "description": "tag id", "type": "string" }, "updated_at": { - "description": "updated time", "type": "integer" } } @@ -8491,6 +8528,9 @@ const docTemplate = `{ "title": { "type": "string" }, + "url_title": { + "type": "string" + }, "user_info": { "description": "user info", "allOf": [ @@ -9640,6 +9680,10 @@ const docTemplate = `{ "description": "username", "type": "string" }, + "visit_token": { + "description": "visit token", + "type": "string" + }, "website": { "description": "website", "type": "string" diff --git a/docs/swagger.json b/docs/swagger.json index c4426944..48b6283e 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -3654,6 +3654,49 @@ } } }, + "/answer/api/v1/plugin/status": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get all plugins status", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Plugin" + ], + "summary": "get all plugins status", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.GetPluginListResp" + } + } + } + } + ] + } + } + } + } + }, "/answer/api/v1/post/render": { "post": { "security": [ @@ -7247,6 +7290,10 @@ "description": "username", "type": "string" }, + "visit_token": { + "description": "visit token", + "type": "string" + }, "website": { "description": "website", "type": "string" @@ -7648,27 +7695,21 @@ "type": "object", "properties": { "created_at": { - "description": "created time", "type": "integer" }, "description": { - "description": "description text", "type": "string" }, "display_name": { - "description": "display name", "type": "string" }, "excerpt": { - "description": "excerpt", "type": "string" }, "follow_count": { - "description": "follower amount", "type": "integer" }, "is_follower": { - "description": "is follower", "type": "boolean" }, "main_tag_slug_name": { @@ -7676,22 +7717,18 @@ "type": "string" }, "member_actions": { - "description": "MemberActions", "type": "array", "items": { "$ref": "#/definitions/schema.PermissionMemberAction" } }, "original_text": { - "description": "original text", "type": "string" }, "parsed_text": { - "description": "parsed text", "type": "string" }, "question_count": { - "description": "question amount", "type": "integer" }, "recommend": { @@ -7701,15 +7738,15 @@ "type": "boolean" }, "slug_name": { - "description": "slug name", + "type": "string" + }, + "status": { "type": "string" }, "tag_id": { - "description": "tag id", "type": "string" }, "updated_at": { - "description": "updated time", "type": "integer" } } @@ -8460,6 +8497,9 @@ "title": { "type": "string" }, + "url_title": { + "type": "string" + }, "user_info": { "description": "user info", "allOf": [ @@ -9609,6 +9649,10 @@ "description": "username", "type": "string" }, + "visit_token": { + "description": "visit token", + "type": "string" + }, "website": { "description": "website", "type": "string" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 7e413cf7..851e8a86 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -658,6 +658,9 @@ definitions: username: description: username type: string + visit_token: + description: visit token + type: string website: description: website type: string @@ -941,53 +944,42 @@ definitions: schema.GetTagResp: properties: created_at: - description: created time type: integer description: - description: description text type: string display_name: - description: display name type: string excerpt: - description: excerpt type: string follow_count: - description: follower amount type: integer is_follower: - description: is follower type: boolean main_tag_slug_name: description: if main tag slug name is not empty, this tag is synonymous with the main tag type: string member_actions: - description: MemberActions items: $ref: '#/definitions/schema.PermissionMemberAction' type: array original_text: - description: original text type: string parsed_text: - description: parsed text type: string question_count: - description: question amount type: integer recommend: type: boolean reserved: type: boolean slug_name: - description: slug name + type: string + status: type: string tag_id: - description: tag id type: string updated_at: - description: updated time type: integer type: object schema.GetTagSynonymsResp: @@ -1508,6 +1500,8 @@ definitions: type: array title: type: string + url_title: + type: string user_info: allOf: - $ref: '#/definitions/schema.SearchObjectUser' @@ -2302,6 +2296,9 @@ definitions: username: description: username type: string + visit_token: + description: visit token + type: string website: description: website type: string @@ -4659,6 +4656,30 @@ paths: summary: get user personal votes tags: - Activity + /answer/api/v1/plugin/status: + get: + consumes: + - application/json + description: get all plugins status + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + items: + $ref: '#/definitions/schema.GetPluginListResp' + type: array + type: object + security: + - ApiKeyAuth: [] + summary: get all plugins status + tags: + - Plugin /answer/api/v1/post/render: post: consumes: diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go index 4c6cddd8..1f96790f 100644 --- a/internal/controller/question_controller.go +++ b/internal/controller/question_controller.go @@ -656,10 +656,15 @@ func (qc *QuestionController) UpdateQuestion(ctx *gin.Context) { handler.HandleResponse(ctx, err, resp) return } + respInfo, ok := resp.(*schema.QuestionInfo) + if !ok { + handler.HandleResponse(ctx, err, resp) + return + } if !isAdmin || !linkUrlLimitUser { qc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionEdit, req.UserID) } - handler.HandleResponse(ctx, nil, &schema.UpdateQuestionResp{WaitForReview: !req.NoNeedReview}) + handler.HandleResponse(ctx, nil, &schema.UpdateQuestionResp{UrlTitle: respInfo.UrlTitle, WaitForReview: !req.NoNeedReview}) } // QuestionRecover recover deleted question diff --git a/internal/repo/search_common/search_repo.go b/internal/repo/search_common/search_repo.go index 67996164..de3c03eb 100644 --- a/internal/repo/search_common/search_repo.go +++ b/internal/repo/search_common/search_repo.go @@ -31,6 +31,7 @@ import ( "github.com/apache/incubator-answer/pkg/htmltext" "github.com/apache/incubator-answer/internal/base/data" + "github.com/apache/incubator-answer/internal/base/handler" "github.com/apache/incubator-answer/internal/base/reason" "github.com/apache/incubator-answer/internal/entity" "github.com/apache/incubator-answer/internal/schema" @@ -39,6 +40,7 @@ import ( usercommon "github.com/apache/incubator-answer/internal/service/user_common" "github.com/apache/incubator-answer/pkg/converter" "github.com/apache/incubator-answer/pkg/obj" + "github.com/apache/incubator-answer/pkg/uid" "github.com/segmentfault/pacman/errors" "xorm.io/builder" ) @@ -483,10 +485,19 @@ func (sr *searchRepo) parseResult(ctx context.Context, res []map[string][]byte) questionIDs = append(questionIDs, string(r["question_id"])) userIDs = append(userIDs, string(r["user_id"])) tp, _ := time.ParseInLocation("2006-01-02 15:04:05", string(r["created_at"]), time.Local) + + var ID = string(r["id"]) + var QuestionID = string(r["question_id"]) + if handler.GetEnableShortID(ctx) { + ID = uid.EnShortID(ID) + QuestionID = uid.EnShortID(QuestionID) + } + object := &schema.SearchObject{ - ID: string(r["id"]), - QuestionID: string(r["question_id"]), + ID: ID, + QuestionID: QuestionID, Title: string(r["title"]), + UrlTitle: htmltext.UrlTitle(string(r["title"])), Excerpt: htmltext.FetchExcerpt(string(r["parsed_text"]), "...", 240), CreatedAtParsed: tp.Unix(), UserInfo: &schema.SearchObjectUser{ diff --git a/internal/schema/answer_schema.go b/internal/schema/answer_schema.go index dde1cb1d..2cd45947 100644 --- a/internal/schema/answer_schema.go +++ b/internal/schema/answer_schema.go @@ -98,12 +98,12 @@ type AnswerListReq struct { } type AnswerInfo struct { - ID string `json:"id" xorm:"id"` - QuestionID string `json:"question_id" xorm:"question_id"` - Content string `json:"content" xorm:"content"` - HTML string `json:"html" xorm:"html"` - CreateTime int64 `json:"create_time" xorm:"created"` - UpdateTime int64 `json:"update_time" xorm:"updated"` + ID string `json:"id"` + QuestionID string `json:"question_id"` + Content string `json:"content"` + HTML string `json:"html"` + CreateTime int64 `json:"create_time"` + UpdateTime int64 `json:"update_time"` Accepted int `json:"accepted"` UserID string `json:"-"` UpdateUserID string `json:"-"` diff --git a/internal/schema/question_schema.go b/internal/schema/question_schema.go index 3d064023..bb409e6d 100644 --- a/internal/schema/question_schema.go +++ b/internal/schema/question_schema.go @@ -204,42 +204,43 @@ func (req *QuestionUpdate) Check() (errFields []*validator.FormErrorField, err e type QuestionBaseInfo struct { ID string `json:"id" ` - Title string `json:"title" xorm:"title"` // title - ViewCount int `json:"view_count" xorm:"view_count"` // view count - AnswerCount int `json:"answer_count" xorm:"answer_count"` // answer count - CollectionCount int `json:"collection_count" xorm:"collection_count"` // collection count - FollowCount int `json:"follow_count" xorm:"follow_count"` // follow count + Title string `json:"title"` + UrlTitle string `json:"url_title"` + ViewCount int `json:"view_count"` + AnswerCount int `json:"answer_count"` + CollectionCount int `json:"collection_count"` + FollowCount int `json:"follow_count"` Status string `json:"status"` AcceptedAnswer bool `json:"accepted_answer"` } type QuestionInfo struct { ID string `json:"id" ` - Title string `json:"title" xorm:"title"` // title - UrlTitle string `json:"url_title" xorm:"url_title"` // title - Content string `json:"content" xorm:"content"` // content - HTML string `json:"html" xorm:"html"` // html - Description string `json:"description"` //description - Tags []*TagResp `json:"tags" ` // tags - ViewCount int `json:"view_count" xorm:"view_count"` // view_count - UniqueViewCount int `json:"unique_view_count" xorm:"unique_view_count"` // unique_view_count - VoteCount int `json:"vote_count" xorm:"vote_count"` // vote_count - AnswerCount int `json:"answer_count" xorm:"answer_count"` // answer count - CollectionCount int `json:"collection_count" xorm:"collection_count"` // collection count - FollowCount int `json:"follow_count" xorm:"follow_count"` // follow count - AcceptedAnswerID string `json:"accepted_answer_id" ` // accepted_answer_id - LastAnswerID string `json:"last_answer_id" ` // last_answer_id - CreateTime int64 `json:"create_time" ` // create_time - UpdateTime int64 `json:"-"` // update_time + Title string `json:"title"` + UrlTitle string `json:"url_title"` + Content string `json:"content"` + HTML string `json:"html"` + Description string `json:"description"` + Tags []*TagResp `json:"tags"` + ViewCount int `json:"view_count"` + UniqueViewCount int `json:"unique_view_count"` + VoteCount int `json:"vote_count"` + AnswerCount int `json:"answer_count"` + CollectionCount int `json:"collection_count"` + FollowCount int `json:"follow_count"` + AcceptedAnswerID string `json:"accepted_answer_id"` + LastAnswerID string `json:"last_answer_id"` + CreateTime int64 `json:"create_time"` + UpdateTime int64 `json:"-"` PostUpdateTime int64 `json:"update_time"` QuestionUpdateTime int64 `json:"edit_time"` - Pin int `json:"pin"` // 1: unpin, 2: pin - Show int `json:"show"` // 0: show, 1: hide + Pin int `json:"pin"` + Show int `json:"show"` Status int `json:"status"` Operation *Operation `json:"operation,omitempty"` - UserID string `json:"-" ` - LastEditUserID string `json:"-" ` - LastAnsweredUserID string `json:"-" ` + UserID string `json:"-"` + LastEditUserID string `json:"-"` + LastAnsweredUserID string `json:"-"` UserInfo *UserBasicInfo `json:"user_info"` UpdateUserInfo *UserBasicInfo `json:"update_user_info,omitempty"` LastAnsweredUserInfo *UserBasicInfo `json:"last_answered_user_info,omitempty"` @@ -255,6 +256,7 @@ type QuestionInfo struct { // UpdateQuestionResp update question resp type UpdateQuestionResp struct { + UrlTitle string `json:"url_title"` WaitForReview bool `json:"wait_for_review"` } diff --git a/internal/schema/search_schema.go b/internal/schema/search_schema.go index 398fad1e..e1533953 100644 --- a/internal/schema/search_schema.go +++ b/internal/schema/search_schema.go @@ -115,6 +115,7 @@ type SearchObject struct { ID string `json:"id"` QuestionID string `json:"question_id"` Title string `json:"title"` + UrlTitle string `json:"url_title"` Excerpt string `json:"excerpt"` CreatedAtParsed int64 `json:"created_at"` VoteCount int `json:"vote_count"` diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go index b12a9dec..9a172c2e 100644 --- a/internal/service/question_common/question.go +++ b/internal/service/question_common/question.go @@ -593,6 +593,9 @@ func (qs *QuestionCommon) ShowListFormat(ctx context.Context, data *entity.Quest func (qs *QuestionCommon) ShowFormat(ctx context.Context, data *entity.Question) *schema.QuestionInfo { info := schema.QuestionInfo{} info.ID = data.ID + if handler.GetEnableShortID(ctx) { + info.ID = uid.EnShortID(data.ID) + } info.Title = data.Title info.UrlTitle = htmltext.UrlTitle(data.Title) info.Content = data.OriginalText diff --git a/internal/service/question_service.go b/internal/service/question_service.go index b550a1f9..f9159304 100644 --- a/internal/service/question_service.go +++ b/internal/service/question_service.go @@ -754,7 +754,6 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest _, existUnreviewed, err := qs.revisionService.ExistUnreviewedByObjectID(ctx, req.ID) if err != nil { return - } if existUnreviewed { err = errors.BadRequest(reason.QuestionCannotUpdate) @@ -1196,6 +1195,7 @@ func (qs *QuestionService) GetQuestionsByTitle(ctx context.Context, title string item := &schema.QuestionBaseInfo{} item.ID = question.ID item.Title = question.Title + item.UrlTitle = htmltext.UrlTitle(question.Title) item.ViewCount = question.ViewCount item.AnswerCount = question.AnswerCount item.CollectionCount = question.CollectionCount diff --git a/ui/src/pages/Questions/Ask/index.tsx b/ui/src/pages/Questions/Ask/index.tsx index f24385fc..3a465a63 100644 --- a/ui/src/pages/Questions/Ask/index.tsx +++ b/ui/src/pages/Questions/Ask/index.tsx @@ -288,7 +288,7 @@ const Ask = () => { modifyQuestion(ep) .then(async (res) => { await editCaptcha.close(); - navigate(pathFactory.questionLanding(qid, params.url_title), { + navigate(pathFactory.questionLanding(qid, res?.url_title), { state: { isReview: res?.wait_for_review }, }); }) @@ -340,7 +340,7 @@ const Ask = () => { if (checked) { navigate(pathFactory.questionLanding(id, res?.question?.url_title)); } else { - navigate(pathFactory.questionLanding(id)); + navigate(pathFactory.questionLanding(id, res?.url_title)); } } removeDraft();