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

Merge pull request #6040 from weseek/imprv/97303-replace-withTranslation-to-useTranslation

Imprv/97303 replace with translation to use translation
Yuki Takei пре 3 година
родитељ
комит
59c1230fb3

+ 8 - 5
packages/app/src/components/Admin/Common/AdminNavigation.jsx

@@ -1,18 +1,22 @@
 /* eslint-disable no-multi-spaces */
 /* eslint-disable react/jsx-props-no-multi-spaces */
 
+
 import React from 'react';
+
+import { pathUtils } from '@growi/core';
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 import urljoin from 'url-join';
 
-import { pathUtils } from '@growi/core';
 
 import AppContainer from '~/client/services/AppContainer';
+
 import { withUnstatedContainers } from '../../UnstatedUtils';
 
 const AdminNavigation = (props) => {
-  const { t, appContainer } = props;
+  const { t } = useTranslation();
+  const { appContainer } = props;
   const pathname = window.location.pathname;
 
   const growiCloudUri = appContainer.config.env.GROWI_CLOUD_URI;
@@ -141,8 +145,7 @@ const AdminNavigation = (props) => {
 const AdminNavigationWrapper = withUnstatedContainers(AdminNavigation, [AppContainer]);
 
 AdminNavigation.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
   appContainer: PropTypes.instanceOf(AppContainer).isRequired,
 };
 
-export default withTranslation()(AdminNavigationWrapper);
+export default AdminNavigationWrapper;

+ 0 - 23
packages/app/src/components/Admin/Common/AdminUpdateButtonRow.jsx

@@ -1,23 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-
-const AdminUpdateButtonRow = (props) => {
-  const { t } = props;
-
-  return (
-    <div className="row my-3">
-      <div className="mx-auto">
-        <button type="button" className="btn btn-primary" onClick={props.onClick} disabled={props.disabled}>{ t('Update') }</button>
-      </div>
-    </div>
-  );
-};
-
-AdminUpdateButtonRow.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  onClick: PropTypes.func.isRequired,
-  disabled: PropTypes.bool.isRequired,
-};
-
-export default withTranslation()(AdminUpdateButtonRow);

+ 23 - 0
packages/app/src/components/Admin/Common/AdminUpdateButtonRow.tsx

@@ -0,0 +1,23 @@
+import React from 'react';
+
+import { useTranslation } from 'react-i18next';
+
+type Props = {
+  onClick: () => void,
+  disabled: boolean,
+
+}
+
+const AdminUpdateButtonRow = (props: Props): JSX.Element => {
+  const { t } = useTranslation();
+
+  return (
+    <div className="row my-3">
+      <div className="mx-auto">
+        <button type="button" className="btn btn-primary" onClick={props.onClick} disabled={props.disabled}>{ t('Update') }</button>
+      </div>
+    </div>
+  );
+};
+
+export default AdminUpdateButtonRow;

+ 9 - 12
packages/app/src/components/Admin/Common/LabeledProgressBar.jsx → packages/app/src/components/Admin/Common/LabeledProgressBar.tsx

@@ -1,11 +1,16 @@
 import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
 
 import { Progress } from 'reactstrap';
 
-const LabeledProgressBar = (props) => {
+type Props = {
+  header: string,
+  currentCount: number,
+  totalCount: number,
+  errorsCount?: number,
+  isInProgress?: boolean,
+}
 
+const LabeledProgressBar = (props: Props): JSX.Element => {
   const {
     header, currentCount, totalCount, errorsCount, isInProgress,
   } = props;
@@ -27,12 +32,4 @@ const LabeledProgressBar = (props) => {
 
 };
 
-LabeledProgressBar.propTypes = {
-  header: PropTypes.string.isRequired,
-  currentCount: PropTypes.number.isRequired,
-  totalCount: PropTypes.number.isRequired,
-  errorsCount: PropTypes.number,
-  isInProgress: PropTypes.bool,
-};
-
-export default withTranslation()(LabeledProgressBar);
+export default LabeledProgressBar;

+ 0 - 47
packages/app/src/components/Admin/ElasticsearchManagement/NormalizeIndicesControls.jsx

@@ -1,47 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-
-import { withUnstatedContainers } from '../../UnstatedUtils';
-
-class NormalizeIndicesControls extends React.PureComponent {
-
-  render() {
-    const { t, isNormalized, isRebuildingProcessing } = this.props;
-
-    const isEnabled = (isNormalized != null) && !isNormalized && !isRebuildingProcessing;
-
-    return (
-      <>
-        <button
-          type="submit"
-          className={`btn ${isEnabled ? 'btn-outline-info' : 'btn-outline-secondary'}`}
-          onClick={() => { this.props.onNormalizingRequested() }}
-          disabled={!isEnabled}
-        >
-          { t('full_text_search_management.normalize_button') }
-        </button>
-
-        <p className="form-text text-muted">
-          { t('full_text_search_management.normalize_description') }<br />
-        </p>
-      </>
-    );
-  }
-
-}
-
-/**
- * Wrapper component for using unstated
- */
-const NormalizeIndicesControlsWrapper = withUnstatedContainers(NormalizeIndicesControls, []);
-
-NormalizeIndicesControls.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-
-  isRebuildingProcessing: PropTypes.bool.isRequired,
-  onNormalizingRequested: PropTypes.func.isRequired,
-  isNormalized: PropTypes.bool,
-};
-
-export default withTranslation()(NormalizeIndicesControlsWrapper);

+ 35 - 0
packages/app/src/components/Admin/ElasticsearchManagement/NormalizeIndicesControls.tsx

@@ -0,0 +1,35 @@
+import React from 'react';
+
+import { useTranslation } from 'react-i18next';
+
+type Props = {
+  isRebuildingProcessing: boolean,
+  onNormalizingRequested: () => void,
+  isNormalized?: boolean,
+}
+
+const NormalizeIndicesControls = (props: Props): JSX.Element => {
+  const { t } = useTranslation();
+  const { isNormalized, isRebuildingProcessing } = props;
+
+  const isEnabled = (isNormalized != null) && !isNormalized && !isRebuildingProcessing;
+
+  return (
+    <>
+      <button
+        type="submit"
+        className={`btn ${isEnabled ? 'btn-outline-info' : 'btn-outline-secondary'}`}
+        onClick={() => { props.onNormalizingRequested() }}
+        disabled={!isEnabled}
+      >
+        { t('full_text_search_management.normalize_button') }
+      </button>
+
+      <p className="form-text text-muted">
+        { t('full_text_search_management.normalize_description') }<br />
+      </p>
+    </>
+  );
+};
+
+export default NormalizeIndicesControls;

+ 10 - 6
packages/app/src/components/Admin/ElasticsearchManagement/RebuildIndexControls.jsx

@@ -1,11 +1,11 @@
 import React from 'react';
+
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 
-import { withUnstatedContainers } from '../../UnstatedUtils';
-import AppContainer from '~/client/services/AppContainer';
 import AdminSocketIoContainer from '~/client/services/AdminSocketIoContainer';
 
+import { withUnstatedContainers } from '../../UnstatedUtils';
 import LabeledProgressBar from '../Common/LabeledProgressBar';
 
 class RebuildIndexControls extends React.Component {
@@ -107,15 +107,19 @@ class RebuildIndexControls extends React.Component {
 
 }
 
+const RebuildIndexControlsFC = (props) => {
+  const { t } = useTranslation();
+  return <RebuildIndexControls t={t} {...props} />;
+};
+
 
 /**
  * Wrapper component for using unstated
  */
-const RebuildIndexControlsWrapper = withUnstatedContainers(RebuildIndexControls, [AppContainer, AdminSocketIoContainer]);
+const RebuildIndexControlsWrapper = withUnstatedContainers(RebuildIndexControlsFC, [AdminSocketIoContainer]);
 
 RebuildIndexControls.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminSocketIoContainer: PropTypes.instanceOf(AdminSocketIoContainer).isRequired,
 
   isRebuildingProcessing: PropTypes.bool.isRequired,
@@ -125,4 +129,4 @@ RebuildIndexControls.propTypes = {
   onRebuildingRequested: PropTypes.func.isRequired,
 };
 
-export default withTranslation()(RebuildIndexControlsWrapper);
+export default RebuildIndexControlsWrapper;

+ 0 - 46
packages/app/src/components/Admin/ElasticsearchManagement/ReconnectControls.jsx

@@ -1,46 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-
-import { withUnstatedContainers } from '../../UnstatedUtils';
-
-class ReconnectControls extends React.PureComponent {
-
-  render() {
-    const { t, isEnabled, isProcessing } = this.props;
-
-    return (
-      <>
-        <button
-          type="submit"
-          className={`btn ${isEnabled ? 'btn-outline-success' : 'btn-outline-secondary'}`}
-          onClick={() => { this.props.onReconnectingRequested() }}
-          disabled={!isEnabled}
-        >
-          { isProcessing && <i className="fa fa-spinner fa-pulse mr-2"></i> }
-          { t('full_text_search_management.reconnect_button') }
-        </button>
-
-        <p className="form-text text-muted">
-          { t('full_text_search_management.reconnect_description') }<br />
-        </p>
-      </>
-    );
-  }
-
-}
-
-/**
- * Wrapper component for using unstated
- */
-const ReconnectControlsWrapper = withUnstatedContainers(ReconnectControls, []);
-
-ReconnectControls.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-
-  isEnabled: PropTypes.bool,
-  isProcessing: PropTypes.bool,
-  onReconnectingRequested: PropTypes.func.isRequired,
-};
-
-export default withTranslation()(ReconnectControlsWrapper);

+ 36 - 0
packages/app/src/components/Admin/ElasticsearchManagement/ReconnectControls.tsx

@@ -0,0 +1,36 @@
+import React from 'react';
+
+import { useTranslation } from 'react-i18next';
+
+type Props = {
+  isEnabled?: boolean,
+  isProcessing?: boolean,
+  onReconnectingRequested: () => void,
+}
+
+const ReconnectControls = (props: Props): JSX.Element => {
+  const { t } = useTranslation();
+
+  const { isEnabled, isProcessing } = props;
+
+  return (
+    <>
+      <button
+        type="submit"
+        className={`btn ${isEnabled ? 'btn-outline-success' : 'btn-outline-secondary'}`}
+        onClick={() => { props.onReconnectingRequested() }}
+        disabled={!isEnabled}
+      >
+        { isProcessing && <i className="fa fa-spinner fa-pulse mr-2"></i> }
+        { t('full_text_search_management.reconnect_button') }
+      </button>
+
+      <p className="form-text text-muted">
+        { t('full_text_search_management.reconnect_description') }<br />
+      </p>
+    </>
+  );
+
+};
+
+export default ReconnectControls;

+ 17 - 18
packages/app/src/components/Admin/MarkdownSetting/IndentForm.jsx → packages/app/src/components/Admin/MarkdownSetting/IndentForm.tsx

@@ -1,25 +1,29 @@
 /* eslint-disable react/no-danger */
-import React from 'react';
+import React, { useCallback } from 'react';
 
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 import {
   UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem,
 } from 'reactstrap';
-import loggerFactory from '~/utils/logger';
 
-import { withUnstatedContainers } from '../../UnstatedUtils';
+import AdminMarkDownContainer from '~/client/services/AdminMarkDownContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
+import loggerFactory from '~/utils/logger';
 
-import AdminMarkDownContainer from '~/client/services/AdminMarkDownContainer';
+import { withUnstatedContainers } from '../../UnstatedUtils';
 import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:importer');
 
-const IndentForm = (props) => {
-  const onClickSubmit = async(props) => {
-    const { t } = props;
 
+type Props = {
+  adminMarkDownContainer: AdminMarkDownContainer;
+}
+
+const IndentForm = (props: Props) => {
+  const { t } = useTranslation();
+
+  const onClickSubmit = useCallback(async(props) => {
     try {
       await props.adminMarkDownContainer.updateIndentSetting();
       toastSuccess(t('toaster.update_successed', { target: t('admin:markdown_setting.indent_header') }));
@@ -28,10 +32,10 @@ const IndentForm = (props) => {
       toastError(err);
       logger.error(err);
     }
-  };
+  }, [t]);
 
   const renderIndentSizeOption = (props) => {
-    const { t, adminMarkDownContainer } = props;
+    const { adminMarkDownContainer } = props;
     const { adminPreferredIndentSize } = adminMarkDownContainer.state;
 
     return (
@@ -63,7 +67,7 @@ const IndentForm = (props) => {
   };
 
   const renderIndentForceOption = (props) => {
-    const { t, adminMarkDownContainer } = props;
+    const { adminMarkDownContainer } = props;
     const { isIndentSizeForced } = adminMarkDownContainer.state;
 
     const helpIndentInComment = { __html: t('admin:markdown_setting.indent_options.disallow_indent_change_desc') };
@@ -107,9 +111,4 @@ const IndentForm = (props) => {
  */
 const IndentFormWrapper = withUnstatedContainers(IndentForm, [AdminMarkDownContainer]);
 
-IndentForm.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  adminMarkDownContainer: PropTypes.instanceOf(AdminMarkDownContainer).isRequired,
-};
-
-export default withTranslation()(IndentFormWrapper);
+export default IndentFormWrapper;

+ 12 - 10
packages/app/src/components/Admin/MarkdownSetting/LineBreakForm.jsx

@@ -2,15 +2,13 @@
 import React from 'react';
 
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-import loggerFactory from '~/utils/logger';
+import { useTranslation } from 'react-i18next';
 
-import { withUnstatedContainers } from '../../UnstatedUtils';
+import AdminMarkDownContainer from '~/client/services/AdminMarkDownContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
+import loggerFactory from '~/utils/logger';
 
-
-import AppContainer from '~/client/services/AppContainer';
-import AdminMarkDownContainer from '~/client/services/AdminMarkDownContainer';
+import { withUnstatedContainers } from '../../UnstatedUtils';
 import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
 
 const logger = loggerFactory('growi:importer');
@@ -103,15 +101,19 @@ class LineBreakForm extends React.Component {
 
 }
 
+const LineBreakFormFC = (props) => {
+  const { t } = useTranslation();
+  return <LineBreakForm t={t} {...props} />;
+};
+
 /**
  * Wrapper component for using unstated
  */
-const LineBreakFormWrapper = withUnstatedContainers(LineBreakForm, [AppContainer, AdminMarkDownContainer]);
+const LineBreakFormWrapper = withUnstatedContainers(LineBreakFormFC, [AdminMarkDownContainer]);
 
 LineBreakForm.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+  t: PropTypes.func.isRequired,
   adminMarkDownContainer: PropTypes.instanceOf(AdminMarkDownContainer).isRequired,
 };
 
-export default withTranslation()(LineBreakFormWrapper);
+export default LineBreakFormWrapper;

+ 18 - 9
packages/app/src/components/Admin/Security/GitHubSecuritySettingContents.jsx

@@ -1,13 +1,15 @@
 /* eslint-disable react/no-danger */
 import React from 'react';
+
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 
-import { withUnstatedContainers } from '../../UnstatedUtils';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
 import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';
 import AdminGitHubSecurityContainer from '~/client/services/AdminGitHubSecurityContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
+
+import { withUnstatedContainers } from '../../UnstatedUtils';
 
 class GitHubSecurityManagementContents extends React.Component {
 
@@ -183,6 +185,18 @@ class GitHubSecurityManagementContents extends React.Component {
 
 }
 
+const GitHubSecurityManagementContentsFC = (props) => {
+  const { t } = useTranslation();
+  return <GitHubSecurityManagementContents t={t} {...props} />;
+};
+
+/**
+ * Wrapper component for using unstated
+ */
+const GitHubSecurityManagementContentsWrapper = withUnstatedContainers(GitHubSecurityManagementContentsFC, [
+  AdminGeneralSecurityContainer,
+  AdminGitHubSecurityContainer,
+]);
 
 GitHubSecurityManagementContents.propTypes = {
   t: PropTypes.func.isRequired, // i18next
@@ -190,9 +204,4 @@ GitHubSecurityManagementContents.propTypes = {
   adminGitHubSecurityContainer: PropTypes.instanceOf(AdminGitHubSecurityContainer).isRequired,
 };
 
-const GitHubSecurityManagementContentsWrapper = withUnstatedContainers(GitHubSecurityManagementContents, [
-  AdminGeneralSecurityContainer,
-  AdminGitHubSecurityContainer,
-]);
-
-export default withTranslation()(GitHubSecurityManagementContentsWrapper);
+export default GitHubSecurityManagementContentsWrapper;

+ 8 - 6
packages/app/src/components/Admin/Security/GoogleSecuritySettingContents.jsx

@@ -2,12 +2,11 @@
 import React from 'react';
 
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 
 
 import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';
 import AdminGoogleSecurityContainer from '~/client/services/AdminGoogleSecurityContainer';
-import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
 import { withUnstatedContainers } from '../../UnstatedUtils';
@@ -193,18 +192,21 @@ class GoogleSecurityManagementContents extends React.Component {
 
 }
 
+const GoogleSecurityManagementContentsFc = (props) => {
+  const { t } = useTranslation();
+  return <GoogleSecurityManagementContents t={t} {...props} />;
+};
+
 
 GoogleSecurityManagementContents.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminGeneralSecurityContainer: PropTypes.instanceOf(AdminGeneralSecurityContainer).isRequired,
   adminGoogleSecurityContainer: PropTypes.instanceOf(AdminGoogleSecurityContainer).isRequired,
 };
 
-const GoogleSecurityManagementContentsWrapper = withUnstatedContainers(GoogleSecurityManagementContents, [
-  AppContainer,
+const GoogleSecurityManagementContentsWrapper = withUnstatedContainers(GoogleSecurityManagementContentsFc, [
   AdminGeneralSecurityContainer,
   AdminGoogleSecurityContainer,
 ]);
 
-export default withTranslation()(GoogleSecurityManagementContentsWrapper);
+export default GoogleSecurityManagementContentsWrapper;

+ 8 - 5
packages/app/src/components/Admin/Security/LdapAuthTest.jsx

@@ -1,10 +1,9 @@
 import React from 'react';
 
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 
 import AdminLdapSecurityContainer from '~/client/services/AdminLdapSecurityContainer';
-import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { apiPost } from '~/client/util/apiv1-client';
 import loggerFactory from '~/utils/logger';
@@ -129,10 +128,14 @@ class LdapAuthTest extends React.Component {
 
 }
 
+const LdapAuthTestFc = (props) => {
+  const { t } = useTranslation();
+  return <LdapAuthTest t={t} {...props} />;
+};
+
 
 LdapAuthTest.propTypes = {
   t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
   adminLdapSecurityContainer: PropTypes.instanceOf(AdminLdapSecurityContainer).isRequired,
 
   username: PropTypes.string.isRequired,
@@ -141,6 +144,6 @@ LdapAuthTest.propTypes = {
   onChangePassword: PropTypes.func.isRequired,
 };
 
-const LdapAuthTestWrapper = withUnstatedContainers(LdapAuthTest, [AppContainer, AdminLdapSecurityContainer]);
+const LdapAuthTestWrapper = withUnstatedContainers(LdapAuthTestFc, [AdminLdapSecurityContainer]);
 
-export default withTranslation()(LdapAuthTestWrapper);
+export default LdapAuthTestWrapper;

+ 11 - 3
packages/app/src/components/PageEditor/GridEditModal.jsx

@@ -1,12 +1,15 @@
 import React from 'react';
+
 import PropTypes from 'prop-types';
+import { useTranslation } from 'react-i18next';
 import {
   Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
-import { withTranslation } from 'react-i18next';
-import geu from './GridEditorUtil';
+
 import BootstrapGrid from '~/client/models/BootstrapGrid';
 
+import geu from './GridEditorUtil';
+
 const resSizes = BootstrapGrid.ResponsiveSize;
 const resSizeObj = {
   [resSizes.XS_SIZE]: { displayText: 'grid_edit.smart_no' },
@@ -246,8 +249,13 @@ class GridEditModal extends React.Component {
 
 }
 
+const GridEditModalFc = React.forwardRef((props, ref) => {
+  const { t } = useTranslation();
+  return <GridEditModal t={t} ref={ref} {...props} />;
+});
+
 GridEditModal.propTypes = {
   onSave: PropTypes.func,
   t: PropTypes.func.isRequired,
 };
-export default withTranslation('translation', { withRef: true })(GridEditModal);
+export default GridEditModalFc;

+ 8 - 3
packages/app/src/components/PageEditor/LinkEditModal.jsx

@@ -3,7 +3,7 @@ import React from 'react';
 import path from 'path';
 
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
+import { useTranslation } from 'react-i18next';
 import {
   Modal,
   ModalHeader,
@@ -458,6 +458,11 @@ class LinkEditModal extends React.PureComponent {
 
 }
 
+const LinkEditModalFc = React.forwardRef((props, ref) => {
+  const { t } = useTranslation();
+  return <LinkEditModal t={t} ref={ref} {...props} />;
+});
+
 LinkEditModal.propTypes = {
   t: PropTypes.func.isRequired,
   pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
@@ -467,6 +472,6 @@ LinkEditModal.propTypes = {
 /**
  * Wrapper component for using unstated
  */
-const LinkEditModalWrapper = withUnstatedContainers(LinkEditModal, [PageContainer]);
+const LinkEditModalWrapper = withUnstatedContainers(LinkEditModalFc, [PageContainer]);
 
-export default withTranslation('translation', { withRef: true })(LinkEditModalWrapper);
+export default LinkEditModalWrapper;