Merge remote-tracking branch 'origin/main' into dev

This commit is contained in:
LinkinStars
2023-11-29 16:45:51 +08:00
11 changed files with 208 additions and 77 deletions
+57 -13
View File
@@ -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"
+57 -13
View File
@@ -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"
+34 -13
View File
@@ -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:
+6 -1
View File
@@ -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
+13 -2
View File
@@ -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{
+6 -6
View File
@@ -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:"-"`
+28 -26
View File
@@ -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"`
}
+1
View File
@@ -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"`
@@ -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
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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();