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: [],

Reply via email to