This is an automated email from the ASF dual-hosted git repository.

shuai pushed a commit to branch feat/1.3.6/ui
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git


The following commit(s) were added to refs/heads/feat/1.3.6/ui by this push:
     new a4960f09 fix: optimize admin/write page content #815
a4960f09 is described below

commit a4960f09be22bf37aa93d6601b4c215b2a41fd30
Author: shuai <[email protected]>
AuthorDate: Fri Jul 12 11:13:12 2024 +0800

    fix: optimize admin/write page content #815
---
 i18n/en_US.yaml                         |  14 +-
 ui/src/common/interface.ts              |   6 +-
 ui/src/components/Editor/utils/index.ts |   3 +
 ui/src/components/TagSelector/index.tsx |  14 +-
 ui/src/pages/Admin/Write/index.tsx      | 234 ++++++++++++++++++++++----------
 ui/src/stores/writeSetting.ts           |   2 +-
 6 files changed, 187 insertions(+), 86 deletions(-)

diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml
index 9be207f7..ef1b0bc9 100644
--- a/i18n/en_US.yaml
+++ b/i18n/en_US.yaml
@@ -1747,19 +1747,21 @@ ui:
     write:
       page_title: Write
       restrict_answer:
-        title: Restrict answer
+        title: Answer write
         label: Each user can only write one answer for the same question
-        text: "Turn off to allow users to write multiple answers to the same 
question, which may cause answers to be unfocused."
+        text: "Turn off to allow users to write multiple answers to the same 
question, which may cause answers to be unfocused."
       recommend_tags:
         label: Recommend tags
-        text: "Please input tag slug above, one tag per line."
+        text: "Recommend tags will show in the dropdown list by default."
+        msg:
+          contain_reserved: "recommended tags cannot contain reserved tags"
       required_tag:
-        title: Required tag
-        label: Set recommend tag as required
+        title: Set required tags
+        label: Set “Recommend tags” as required tags
         text: "Every new question must have at least one recommend tag."
       reserved_tags:
         label: Reserved tags
-        text: "Reserved tags can only be added to a post by moderator."
+        text: "Reserved tags can only be used by moderator."
     seo:
       page_title: SEO
       permalink:
diff --git a/ui/src/common/interface.ts b/ui/src/common/interface.ts
index 0acd2f02..ff7c0902 100644
--- a/ui/src/common/interface.ts
+++ b/ui/src/common/interface.ts
@@ -425,9 +425,9 @@ export interface AdminSettingsLegal {
 
 export interface AdminSettingsWrite {
   restrict_answer?: boolean;
-  recommend_tags?: string[];
-  required_tag?: string;
-  reserved_tags?: string[];
+  recommend_tags?: Tag[];
+  required_tag?: boolean;
+  reserved_tags?: Tag[];
 }
 
 export interface AdminSettingsSeo {
diff --git a/ui/src/components/Editor/utils/index.ts 
b/ui/src/components/Editor/utils/index.ts
index 406acb8d..d49da78c 100644
--- a/ui/src/components/Editor/utils/index.ts
+++ b/ui/src/components/Editor/utils/index.ts
@@ -97,6 +97,9 @@ export const useEditor = ({
         wordWrap: 'break-word',
         wordBreak: 'break-all',
       },
+      '.ͼ7, .ͼ6': {
+        textDecoration: 'none',
+      },
     });
 
     const startState = EditorState.create({
diff --git a/ui/src/components/TagSelector/index.tsx 
b/ui/src/components/TagSelector/index.tsx
index 845ace24..1204a686 100644
--- a/ui/src/components/TagSelector/index.tsx
+++ b/ui/src/components/TagSelector/index.tsx
@@ -41,6 +41,8 @@ interface IProps {
   showRequiredTag?: boolean;
   autoFocus?: boolean;
   isInvalid?: boolean;
+  tagStyleMode?: 'default' | 'simple';
+  formText?: string;
   errMsg?: string;
 }
 
@@ -55,6 +57,8 @@ const TagSelector: FC<IProps> = ({
   showRequiredTag = false,
   autoFocus = false,
   isInvalid = false,
+  formText = '',
+  tagStyleMode = 'default',
   errMsg = '',
 }) => {
   const containerRef = useRef<HTMLDivElement>(null);
@@ -366,8 +370,12 @@ const TagSelector: FC<IProps> = ({
                   key={item.slug_name}
                   className={classNames(
                     'badge-tag rounded-1 m-1 flex-shrink-0',
-                    item.reserved && 'badge-tag-reserved',
-                    item.recommend && 'badge-tag-required',
+                    tagStyleMode === 'default' &&
+                      item.reserved &&
+                      'badge-tag-reserved',
+                    tagStyleMode === 'default' &&
+                      item.recommend &&
+                      'badge-tag-required',
                     index === repeatIndex && 'bg-fade-out',
                   )}>
                   {item.display_name}
@@ -435,7 +443,7 @@ const TagSelector: FC<IProps> = ({
           )}
         </Dropdown.Menu>
       </div>
-      {!hiddenDescription && <Form.Text>{t('hint')}</Form.Text>}
+      {!hiddenDescription && <Form.Text>{formText || t('hint')}</Form.Text>}
       <Form.Control.Feedback type="invalid">{errMsg}</Form.Control.Feedback>
     </div>
   );
diff --git a/ui/src/pages/Admin/Write/index.tsx 
b/ui/src/pages/Admin/Write/index.tsx
index 42806111..442c58f6 100644
--- a/ui/src/pages/Admin/Write/index.tsx
+++ b/ui/src/pages/Admin/Write/index.tsx
@@ -19,8 +19,9 @@
 
 import { FC, useEffect, useState } from 'react';
 import { useTranslation } from 'react-i18next';
+import { Form, Button } from 'react-bootstrap';
 
-import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
+import { TagSelector } from '@/components';
 import type * as Type from '@/common/interface';
 import { useToast } from '@/hooks';
 import {
@@ -30,80 +31,84 @@ import {
 import { handleFormError, scrollToElementTop } from '@/utils';
 import { writeSettingStore } from '@/stores';
 
+const initFormData = {
+  reserved_tags: {
+    value: [] as Type.Tag[], // Replace `Type.Tag` with the correct type for 
`reserved_tags.value`
+    errorMsg: '',
+    isInvalid: false,
+  },
+  recommend_tags: {
+    value: [] as Type.Tag[],
+    errorMsg: '',
+    isInvalid: false,
+  },
+  required_tag: {
+    value: false,
+    errorMsg: '',
+    isInvalid: false,
+  },
+  restrict_answer: {
+    value: false,
+    errorMsg: '',
+    isInvalid: false,
+  },
+};
+
 const Index: FC = () => {
   const { t } = useTranslation('translation', {
     keyPrefix: 'admin.write',
   });
   const Toast = useToast();
 
-  const schema: JSONSchema = {
-    title: t('page_title'),
-    properties: {
-      restrict_answer: {
-        type: 'boolean',
-        title: t('restrict_answer.title'),
-        description: t('restrict_answer.text'),
-        default: true,
-      },
-      recommend_tags: {
-        type: 'string',
-        title: t('recommend_tags.label'),
-        description: t('recommend_tags.text'),
-      },
-      required_tag: {
-        type: 'boolean',
-        title: t('required_tag.title'),
-        description: t('required_tag.text'),
-      },
-      reserved_tags: {
-        type: 'string',
-        title: t('reserved_tags.label'),
-        description: t('reserved_tags.text'),
-      },
-    },
+  const [formData, setFormData] = useState(initFormData);
+
+  const handleValueChange = (value) => {
+    setFormData({
+      ...formData,
+      ...value,
+    });
   };
-  const uiSchema: UISchema = {
-    restrict_answer: {
-      'ui:widget': 'switch',
-      'ui:options': {
-        label: t('restrict_answer.label'),
-      },
-    },
-    recommend_tags: {
-      'ui:widget': 'textarea',
-      'ui:options': {
-        rows: 10,
-      },
-    },
-    required_tag: {
-      'ui:widget': 'switch',
-      'ui:options': {
-        label: t('required_tag.label'),
-      },
-    },
-    reserved_tags: {
-      'ui:widget': 'textarea',
-      'ui:options': {
-        rows: 10,
-      },
-    },
+
+  const checkValidated = (): boolean => {
+    let bol = true;
+    const { recommend_tags, reserved_tags } = formData;
+    // 找出 recommend_tags 和 reserved_tags 中是否有重复的标签
+    // 通过标签中的 slug_name 来去重
+    const repeatTag = recommend_tags.value.filter((tag) =>
+      reserved_tags.value.some((rTag) => rTag?.slug_name === tag?.slug_name),
+    );
+    if (repeatTag.length > 0) {
+      handleValueChange({
+        recommend_tags: {
+          ...recommend_tags,
+          errorMsg: t('recommend_tags.msg.contain_reserved'),
+          isInvalid: true,
+        },
+      });
+      bol = false;
+      const ele = document.getElementById('recommend_tags');
+      scrollToElementTop(ele);
+    } else {
+      handleValueChange({
+        recommend_tags: {
+          ...recommend_tags,
+          errorMsg: '',
+          isInvalid: false,
+        },
+      });
+    }
+    return bol;
   };
-  const [formData, setFormData] = useState(initFormData(schema));
 
   const onSubmit = (evt) => {
     evt.preventDefault();
     evt.stopPropagation();
-    let recommend_tags = [];
-    if (formData.recommend_tags.value?.trim()) {
-      recommend_tags = formData.recommend_tags.value.trim().split('\n');
-    }
-    let reserved_tags = [];
-    if (formData.reserved_tags.value?.trim()) {
-      reserved_tags = formData.reserved_tags.value.trim().split('\n');
+    if (!checkValidated()) {
+      return;
     }
     const reqParams: Type.AdminSettingsWrite = {
-      recommend_tags,
-      reserved_tags,
+      recommend_tags: formData.recommend_tags.value,
+      reserved_tags: formData.reserved_tags.value,
       required_tag: formData.required_tag.value,
       restrict_answer: formData.restrict_answer.value,
     };
@@ -130,12 +135,12 @@ const Index: FC = () => {
   const initData = () => {
     getRequireAndReservedTag().then((res) => {
       if (Array.isArray(res.recommend_tags)) {
-        formData.recommend_tags.value = res.recommend_tags.join('\n');
+        formData.recommend_tags.value = res.recommend_tags;
       }
       formData.required_tag.value = res.required_tag;
       formData.restrict_answer.value = res.restrict_answer;
       if (Array.isArray(res.reserved_tags)) {
-        formData.reserved_tags.value = res.reserved_tags.join('\n');
+        formData.reserved_tags.value = res.reserved_tags;
       }
       setFormData({ ...formData });
     });
@@ -145,20 +150,103 @@ const Index: FC = () => {
     initData();
   }, []);
 
-  const handleOnChange = (data) => {
-    setFormData(data);
-  };
+  // const handleOnChange = (data) => {
+  //   setFormData(data);
+  // };
 
   return (
     <>
       <h3 className="mb-4">{t('page_title')}</h3>
-      <SchemaForm
-        schema={schema}
-        formData={formData}
-        onSubmit={onSubmit}
-        uiSchema={uiSchema}
-        onChange={handleOnChange}
-      />
+      <Form noValidate onSubmit={onSubmit}>
+        <Form.Group className="mb-3" controlId="reserved_tags">
+          <Form.Label>{t('reserved_tags.label')}</Form.Label>
+          <TagSelector
+            value={formData.reserved_tags.value}
+            onChange={(val) => {
+              handleValueChange({
+                reserved_tags: {
+                  value: val,
+                  errorMsg: '',
+                  isInvalid: false,
+                },
+              });
+            }}
+            showRequiredTag={false}
+            maxTagLength={0}
+            tagStyleMode="simple"
+            formText={t('reserved_tags.text')}
+            isInvalid={formData.reserved_tags.isInvalid}
+            errMsg={formData.reserved_tags.errorMsg}
+          />
+        </Form.Group>
+
+        <Form.Group className="mb-3" controlId="recommend_tags">
+          <Form.Label>{t('recommend_tags.label')}</Form.Label>
+          <TagSelector
+            value={formData.recommend_tags.value}
+            onChange={(val) => {
+              handleValueChange({
+                recommend_tags: {
+                  value: val,
+                  errorMsg: '',
+                  isInvalid: false,
+                },
+              });
+            }}
+            showRequiredTag={false}
+            tagStyleMode="simple"
+            formText={t('recommend_tags.text')}
+            isInvalid={formData.recommend_tags.isInvalid}
+            errMsg={formData.recommend_tags.errorMsg}
+          />
+        </Form.Group>
+
+        <Form.Group className="mb-3" controlId="required_tag">
+          <Form.Label>{t('required_tag.title')}</Form.Label>
+          <Form.Switch
+            label={t('required_tag.label')}
+            checked={formData.required_tag.value}
+            onChange={(evt) => {
+              handleValueChange({
+                required_tag: {
+                  value: evt.target.checked,
+                  errorMsg: '',
+                  isInvalid: false,
+                },
+              });
+            }}
+          />
+          <Form.Text>{t('required_tag.text')}</Form.Text>
+          <Form.Control.Feedback type="invalid">
+            {formData.required_tag.errorMsg}
+          </Form.Control.Feedback>
+        </Form.Group>
+
+        <Form.Group className="mb-3" controlId="restrict_answer">
+          <Form.Label>{t('restrict_answer.title')}</Form.Label>
+          <Form.Switch
+            label={t('restrict_answer.label')}
+            checked={formData.restrict_answer.value}
+            onChange={(evt) => {
+              handleValueChange({
+                restrict_answer: {
+                  value: evt.target.checked,
+                  errorMsg: '',
+                  isInvalid: false,
+                },
+              });
+            }}
+          />
+          <Form.Text>{t('restrict_answer.text')}</Form.Text>
+          <Form.Control.Feedback type="invalid">
+            {formData.restrict_answer.errorMsg}
+          </Form.Control.Feedback>
+        </Form.Group>
+
+        <Form.Group className="mb-3">
+          <Button type="submit">{t('save', { keyPrefix: 'btns' })}</Button>
+        </Form.Group>
+      </Form>
     </>
   );
 };
diff --git a/ui/src/stores/writeSetting.ts b/ui/src/stores/writeSetting.ts
index 0ea04962..8e7c1f52 100644
--- a/ui/src/stores/writeSetting.ts
+++ b/ui/src/stores/writeSetting.ts
@@ -30,7 +30,7 @@ const Index = create<IProps>((set) => ({
   write: {
     restrict_answer: true,
     recommend_tags: [],
-    required_tag: '',
+    required_tag: false,
     reserved_tags: [],
   },
   update: (params) =>

Reply via email to