Преглед изворни кода

Merge pull request #4231 from weseek/feat/7305-migrate-to-unified-rules

EditorSettings.tsxのリファクタ
Yuki Takei пре 4 година
родитељ
комит
130c0275ae
1 измењених фајлова са 114 додато и 144 уклоњено
  1. 114 144
      packages/app/src/components/Me/EditorSettings.tsx

+ 114 - 144
packages/app/src/components/Me/EditorSettings.tsx

@@ -1,19 +1,38 @@
 import React, {
-  FC, useEffect, useState,
+  Dispatch,
+  FC, SetStateAction, useEffect, useState,
 } from 'react';
 import { useTranslation } from 'react-i18next';
 import PropTypes from 'prop-types';
 import AppContainer from '~/client/services/AppContainer';
 
-import EditorContainer from '~/client/services/EditorContainer';
 import { withUnstatedContainers } from '../UnstatedUtils';
 
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
-type Props = {
-  appContainer: AppContainer,
+type EditorSettingsBodyProps = {
+  appContainer: AppContainer
 }
 
+type RuleListGroupProps = {
+  title: string;
+  ruleList: RulesMenuItem[]
+  textlintRules: LintRule[]
+  setTextlintRules: Dispatch<SetStateAction<LintRule[]>>
+}
+
+type LintRule = {
+  name: string
+  options?: unknown
+  isEnabled?: boolean
+}
+
+type RulesMenuItem = {
+  name: string
+  description: string
+}
+
+
 const commonRulesMenuItems = [
   {
     name: 'common-misspellings',
@@ -129,106 +148,30 @@ const japaneseRulesMenuItems = [
 
 ];
 
-type LintRules = {
-  name: string;
-  options?: unknown;
-  isEnabled?: boolean;
-}
-
 
-const EditorSettingsBody: FC<Props> = (props) => {
+const RuleListGroup: FC<RuleListGroupProps> = ({
+  title, ruleList, textlintRules, setTextlintRules,
+}) => {
   const { t } = useTranslation();
-  const { appContainer } = props;
-  const [commonTextlintRules, setCommonTextlintRules] = useState<LintRules[]>([]);
-  const [japaneseTextlintRules, setJapaneseTextlintRules] = useState<LintRules[]>([]);
-
-  const initializeEditorSettings = async() => {
-    const { data } = await appContainer.apiv3Get('/personal-setting/editor-settings');
-
-    if (data?.commonTextlintRules != null) {
-      setCommonTextlintRules(data?.commonTextlintRules);
-    }
-    if (data?.japaneseTextlintRules != null) {
-      setJapaneseTextlintRules(data?.japaneseTextlintRules);
-    }
 
-    // If database is empty, add default rules to state
-    if (data?.commonTextlintRules.length === 0 || data?.commonTextlintRules == null) {
-      const defaultCommonRules = commonRulesMenuItems.map(rule => (
-        {
-          name: rule.name,
-          isEnabled: true,
-        }
-      ));
-      setCommonTextlintRules(defaultCommonRules);
-    }
-    if (data?.japaneseTextlintRules.length === 0 || data?.japaneseTextlintRules == null) {
-      const defaultJapaneseRules = japaneseRulesMenuItems.map(rule => (
-        {
-          name: rule.name,
-          isEnabled: true,
-        }
-      ));
-      setJapaneseTextlintRules(defaultJapaneseRules);
-    }
-  };
-
-  useEffect(() => {
-    initializeEditorSettings();
-  }, []);
-
-  const commonRuleCheckboxHandler = (isChecked: boolean, ruleName: string) => {
-    setCommonTextlintRules(prevState => (
-      prevState.filter(rule => rule.name !== ruleName).concat({ name: ruleName, isEnabled: isChecked })
-    ));
-  };
-
-  const japaneseRuleCheckboxHandler = (isChecked: boolean, ruleName: string) => {
-    setJapaneseTextlintRules(prevState => (
-      prevState.filter(rule => rule.name !== ruleName).concat({ name: ruleName, isEnabled: isChecked })
-    ));
-  };
-
-  const updateCommonRuleHandler = async() => {
-    try {
-      const { data } = await appContainer.apiv3Put('/personal-setting/editor-settings', { commonTextlintRules });
-      setCommonTextlintRules(data?.commonTextlintRules);
-      toastSuccess(t('toaster.update_successed', { target: 'Updated Textlint Settings' }));
-    }
-    catch (err) {
-      toastError(err);
-    }
-  };
-
-  const updateJapaneseRuleHandler = async() => {
-    try {
-      const { data } = await appContainer.apiv3Put('/personal-setting/editor-settings', { japaneseTextlintRules });
-      setJapaneseTextlintRules(data?.japaneseTextlintRules);
-      toastSuccess(t('toaster.update_successed', { target: 'Updated Textlint Settings' }));
-    }
-    catch (err) {
-      toastError(err);
-    }
-  };
-
-  const isCheckedInCommonRules = (ruleName: string) => (
-    commonTextlintRules.filter(stateRule => (
+  const isCheckedRule = (ruleName: string) => (
+    textlintRules.filter(stateRule => (
       stateRule.name === ruleName
     ))[0]?.isEnabled
   );
 
-  const isCheckedInJapaneseRules = (ruleName: string) => (
-    japaneseTextlintRules.filter(stateRule => (
-      stateRule.name === ruleName
-    ))[0]?.isEnabled
-  );
+  const ruleCheckboxHandler = (isChecked: boolean, ruleName: string) => {
+    setTextlintRules(prevState => (
+      prevState.filter(rule => rule.name !== ruleName).concat({ name: ruleName, isEnabled: isChecked })
+    ));
+  };
 
   return (
     <>
-      <h2 className="border-bottom my-4">{t('editor_settings.common_settings.common_settings')}</h2>
+      <h2 className="border-bottom my-4">{t(title)}</h2>
       <div className="form-group row">
         <div className="offset-md-3 col-md-6 text-left">
-          {commonRulesMenuItems.map(rule => (
+          {ruleList.map(rule => (
             <div
               key={rule.name}
               className="custom-control custom-switch custom-checkbox-success"
@@ -237,8 +180,8 @@ const EditorSettingsBody: FC<Props> = (props) => {
                 type="checkbox"
                 className="custom-control-input"
                 id={rule.name}
-                checked={isCheckedInCommonRules(rule.name)}
-                onChange={e => commonRuleCheckboxHandler(e.target.checked, rule.name)}
+                checked={isCheckedRule(rule.name)}
+                onChange={e => ruleCheckboxHandler(e.target.checked, rule.name)}
               />
               <label className="custom-control-label" htmlFor={rule.name}>
                 <strong>{rule.name}</strong>
@@ -248,68 +191,95 @@ const EditorSettingsBody: FC<Props> = (props) => {
               </p>
             </div>
           ))}
-
-          <div className="row my-3">
-            <div className="offset-4 col-5">
-              <button
-                type="button"
-                className="btn btn-primary"
-                onClick={updateCommonRuleHandler}
-              >
-                {t('Update')}
-              </button>
-            </div>
-          </div>
-
         </div>
       </div>
+    </>
+  );
+};
 
 
-      <h2 className="border-bottom my-4">{t('editor_settings.japanese_settings.japanese_settings')}</h2>
+RuleListGroup.propTypes = {
+  title: PropTypes.string.isRequired,
+  ruleList: PropTypes.array.isRequired,
+  textlintRules: PropTypes.array.isRequired,
+  setTextlintRules: PropTypes.func.isRequired,
+};
 
-      <div className="form-group row">
-        <div className="offset-md-3 col-md-6 text-left">
-          {japaneseRulesMenuItems.map(rule => (
-            <div
-              key={rule.name}
-              className="custom-control custom-switch custom-checkbox-success"
-            >
-              <input
-                type="checkbox"
-                className="custom-control-input"
-                id={rule.name}
-                checked={isCheckedInJapaneseRules(rule.name)}
-                onChange={e => japaneseRuleCheckboxHandler(e.target.checked, rule.name)}
-              />
-              <label className="custom-control-label" htmlFor={rule.name}>
-                <strong>{rule.name}</strong>
-              </label>
-              <p className="form-text text-muted small">
-                {t(rule.description)}
-              </p>
-            </div>
-          ))}
-          <div className="row my-3">
-            <div className="offset-4 col-5">
-              <button
-                type="button"
-                className="btn btn-primary"
-                onClick={updateJapaneseRuleHandler}
-              >
-                {t('Update')}
-              </button>
-            </div>
-          </div>
 
-        </div>
-      </div>
+const EditorSettingsBody: FC<EditorSettingsBodyProps> = (props) => {
+  const { t } = useTranslation();
+  const { appContainer } = props;
+  const [textlintRules, setTextlintRules] = useState<LintRule[]>([]);
 
+  const initializeEditorSettings = async() => {
+    const { data } = await appContainer.apiv3Get('/personal-setting/editor-settings');
+
+    if (data?.textlintSettings?.textlintRules != null) {
+      setTextlintRules(data.textlintSettings.textlintRules);
+    }
+
+    // If database is empty, add default rules to state
+    if (data?.textlintSettings?.textlintRules == null) {
+
+      const createRulesFromDefaultList = (rule: { name: string }) => (
+        {
+          name: rule.name,
+          isEnabled: true,
+        }
+      );
+
+      const defaultCommonRules = commonRulesMenuItems.map(rule => createRulesFromDefaultList(rule));
+      const defaultJapaneseRules = japaneseRulesMenuItems.map(rule => createRulesFromDefaultList(rule));
+      setTextlintRules([...defaultCommonRules, ...defaultJapaneseRules]);
+    }
+  };
 
+  useEffect(() => {
+    initializeEditorSettings();
+  }, []);
+
+  const updateRulesHandler = async() => {
+    try {
+      const { data } = await appContainer.apiv3Put('/personal-setting/editor-settings', { textlintSettings: textlintRules });
+      setTextlintRules(data.textlintSettings.textlintRules);
+      toastSuccess(t('toaster.update_successed', { target: 'Updated Textlint Settings' }));
+    }
+    catch (err) {
+      toastError(err);
+    }
+  };
+
+  return (
+    <>
+      <RuleListGroup
+        title="editor_settings.common_settings.common_settings"
+        ruleList={commonRulesMenuItems}
+        textlintRules={textlintRules}
+        setTextlintRules={setTextlintRules}
+      />
+      <RuleListGroup
+        title="editor_settings.japanese_settings.japanese_settings"
+        ruleList={japaneseRulesMenuItems}
+        textlintRules={textlintRules}
+        setTextlintRules={setTextlintRules}
+      />
+
+      <div className="row my-3">
+        <div className="offset-4 col-5">
+          <button
+            type="button"
+            className="btn btn-primary"
+            onClick={updateRulesHandler}
+          >
+            {t('Update')}
+          </button>
+        </div>
+      </div>
     </>
   );
 };
 
-export const EditorSettings = withUnstatedContainers(EditorSettingsBody, [AppContainer, EditorContainer]);
+export const EditorSettings = withUnstatedContainers(EditorSettingsBody, [AppContainer]);
 
 EditorSettingsBody.propTypes = {
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,