This is an automated email from the ASF dual-hosted git repository. shuai pushed a commit to branch dev in repository https://gitbox.apache.org/repos/asf/answer.git
commit a63fe5b26c1ba32adf5c6ebc06b99c3c560090f7 Author: Dinesht04 <[email protected]> AuthorDate: Sat Oct 11 01:36:12 2025 +0530 feat(internal,ui): add minimum tags property --- internal/migrations/init.go | 1 + internal/schema/question_schema.go | 6 +++--- internal/schema/siteinfo_schema.go | 1 + internal/service/content/question_service.go | 12 ++++++++++-- internal/service/tag_common/tag_common.go | 9 +++++++++ ui/src/common/interface.ts | 1 + ui/src/pages/Admin/Write/index.tsx | 29 +++++++++++++++++++++++++++- ui/src/stores/writeSetting.ts | 1 + 8 files changed, 54 insertions(+), 6 deletions(-) diff --git a/internal/migrations/init.go b/internal/migrations/init.go index fde27cdd..a14a371d 100644 --- a/internal/migrations/init.go +++ b/internal/migrations/init.go @@ -290,6 +290,7 @@ func (m *Mentor) initSiteInfoPrivilegeRank() { func (m *Mentor) initSiteInfoWrite() { writeData := map[string]interface{}{ "restrict_answer": true, + "min_tags": 1, "required_tag": false, "recommend_tags": []string{}, "reserved_tags": []string{}, diff --git a/internal/schema/question_schema.go b/internal/schema/question_schema.go index b5e4baa3..5092ddf8 100644 --- a/internal/schema/question_schema.go +++ b/internal/schema/question_schema.go @@ -83,7 +83,7 @@ type QuestionAdd struct { // html HTML string `json:"-"` // tags - Tags []*TagItem `validate:"required,dive" json:"tags"` + Tags []*TagItem `validate:"dive" json:"tags"` // user id UserID string `json:"-"` QuestionPermission @@ -119,7 +119,7 @@ type QuestionAddByAnswer struct { AnswerContent string `validate:"required,notblank,gte=6,lte=65535" json:"answer_content"` AnswerHTML string `json:"-"` // tags - Tags []*TagItem `validate:"required,dive" json:"tags"` + Tags []*TagItem `validate:"dive" json:"tags"` // user id UserID string `json:"-"` MentionUsernameList []string `validate:"omitempty" json:"mention_username_list"` @@ -200,7 +200,7 @@ type QuestionUpdate struct { HTML string `json:"-"` InviteUser []string `validate:"omitempty" json:"invite_user"` // tags - Tags []*TagItem `validate:"required,dive" json:"tags"` + Tags []*TagItem `validate:"dive" json:"tags"` // edit summary EditSummary string `validate:"omitempty" json:"edit_summary"` // user id diff --git a/internal/schema/siteinfo_schema.go b/internal/schema/siteinfo_schema.go index 19f01ffd..1ecd9760 100644 --- a/internal/schema/siteinfo_schema.go +++ b/internal/schema/siteinfo_schema.go @@ -76,6 +76,7 @@ type SiteBrandingReq struct { // SiteWriteReq site write request type SiteWriteReq struct { RestrictAnswer bool `validate:"omitempty" json:"restrict_answer"` + MinimumTags int `validate:"omitempty" json:"min_tags"` RequiredTag bool `validate:"omitempty" json:"required_tag"` RecommendTags []*SiteWriteTag `validate:"omitempty,dive" json:"recommend_tags"` ReservedTags []*SiteWriteTag `validate:"omitempty,dive" json:"reserved_tags"` diff --git a/internal/service/content/question_service.go b/internal/service/content/question_service.go index 69f568c4..610cc10d 100644 --- a/internal/service/content/question_service.go +++ b/internal/service/content/question_service.go @@ -229,7 +229,11 @@ func (qs *QuestionService) AddQuestionCheckTags(ctx context.Context, Tags []*ent return []string{}, nil } func (qs *QuestionService) CheckAddQuestion(ctx context.Context, req *schema.QuestionAdd) (errorlist any, err error) { - if len(req.Tags) == 0 { + minimumTags, err := qs.tagCommon.GetMinimumTags(ctx, req.Tags) + if err != nil { + return + } + if len(req.Tags) < minimumTags { errorlist := make([]*validator.FormErrorField, 0) errorlist = append(errorlist, &validator.FormErrorField{ ErrorField: "tags", @@ -284,7 +288,11 @@ func (qs *QuestionService) HasNewTag(ctx context.Context, tags []*schema.TagItem // AddQuestion add question func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.QuestionAdd) (questionInfo any, err error) { - if len(req.Tags) == 0 { + minimumTags, err := qs.tagCommon.GetMinimumTags(ctx, req.Tags) + if err != nil { + return + } + if len(req.Tags) < minimumTags { errorlist := make([]*validator.FormErrorField, 0) errorlist = append(errorlist, &validator.FormErrorField{ ErrorField: "tags", diff --git a/internal/service/tag_common/tag_common.go b/internal/service/tag_common/tag_common.go index 318eac20..58f16214 100644 --- a/internal/service/tag_common/tag_common.go +++ b/internal/service/tag_common/tag_common.go @@ -292,6 +292,15 @@ func (ts *TagCommonService) ExistRecommend(ctx context.Context, tags []*schema.T return false, nil } +func (ts *TagCommonService) GetMinimumTags(ctx context.Context, tags []*schema.TagItem) (int, error) { + siteInfo, err := ts.siteInfoService.GetSiteWrite(ctx) + if err != nil { + return 1, err + } + minimumTags := siteInfo.MinimumTags + return minimumTags, nil +} + func (ts *TagCommonService) HasNewTag(ctx context.Context, tags []*schema.TagItem) (bool, error) { tagNames := make([]string, 0) tagMap := make(map[string]bool) diff --git a/ui/src/common/interface.ts b/ui/src/common/interface.ts index 114b0e4c..bade01ea 100644 --- a/ui/src/common/interface.ts +++ b/ui/src/common/interface.ts @@ -439,6 +439,7 @@ export interface AdminSettingsLegal { export interface AdminSettingsWrite { restrict_answer?: boolean; + min_tags?: number, recommend_tags?: Tag[]; required_tag?: boolean; reserved_tags?: Tag[]; diff --git a/ui/src/pages/Admin/Write/index.tsx b/ui/src/pages/Admin/Write/index.tsx index f7832e7f..15c0c2a6 100644 --- a/ui/src/pages/Admin/Write/index.tsx +++ b/ui/src/pages/Admin/Write/index.tsx @@ -37,6 +37,11 @@ const initFormData = { errorMsg: '', isInvalid: false, }, + min_tags: { + value: 0, + errorMsg: '', + isInvalid: false, + }, recommend_tags: { value: [] as Type.Tag[], errorMsg: '', @@ -133,6 +138,7 @@ const Index: FC = () => { } const reqParams: Type.AdminSettingsWrite = { recommend_tags: formData.recommend_tags.value, + min_tags: Number(formData.min_tags.value), reserved_tags: formData.reserved_tags.value, required_tag: formData.required_tag.value, restrict_answer: formData.restrict_answer.value, @@ -177,6 +183,7 @@ const Index: FC = () => { if (Array.isArray(res.recommend_tags)) { formData.recommend_tags.value = res.recommend_tags; } + formData.min_tags.value = res.min_tags; formData.required_tag.value = res.required_tag; formData.restrict_answer.value = res.restrict_answer; if (Array.isArray(res.reserved_tags)) { @@ -247,7 +254,27 @@ const Index: FC = () => { errMsg={formData.recommend_tags.errorMsg} /> </Form.Group> - + <Form.Group className="mb-3" controlId="min_tags"> + <Form.Label>{t('min_tags.label')}</Form.Label> + <Form.Control + type="number" + value={formData.min_tags.value} + isInvalid={formData.min_tags.isInvalid} + onChange={(evt) => { + handleValueChange({ + min_tags: { + value: evt.target.value, + errorMsg: '', + isInvalid: false, + }, + }); + }} + /> + <Form.Text>{t('min_tags.text')}</Form.Text> + <Form.Control.Feedback type="invalid"> + {formData.min_tags.errorMsg} + </Form.Control.Feedback> + </Form.Group> <Form.Group className="mb-3" controlId="required_tag"> <Form.Label>{t('required_tag.title')}</Form.Label> <Form.Switch diff --git a/ui/src/stores/writeSetting.ts b/ui/src/stores/writeSetting.ts index ec0ae1eb..9c44c964 100644 --- a/ui/src/stores/writeSetting.ts +++ b/ui/src/stores/writeSetting.ts @@ -29,6 +29,7 @@ interface IProps { const Index = create<IProps>((set) => ({ write: { restrict_answer: true, + min_tags: 1, recommend_tags: [], required_tag: false, reserved_tags: [],
