Răsfoiți Sursa

Merge pull request #6145 from weseek/imprv/98161-swrize-apiv3-put-personal-settings-disassociateldap

Imprv/98161 swrize apiv3 put personal settings disassociateldap
cao 3 ani în urmă
părinte
comite
f1dc39effd

+ 2 - 5
packages/app/src/client/app.jsx

@@ -12,7 +12,6 @@ import ContextExtractor from '~/client/services/ContextExtractor';
 import EditorContainer from '~/client/services/EditorContainer';
 import PageContainer from '~/client/services/PageContainer';
 import PageHistoryContainer from '~/client/services/PageHistoryContainer';
-import PersonalContainer from '~/client/services/PersonalContainer';
 import RevisionComparerContainer from '~/client/services/RevisionComparerContainer';
 import IdenticalPathPage from '~/components/IdenticalPathPage';
 import PrivateLegacyPages from '~/components/PrivateLegacyPages';
@@ -65,10 +64,9 @@ const pageHistoryContainer = new PageHistoryContainer(appContainer, pageContaine
 const revisionComparerContainer = new RevisionComparerContainer(appContainer, pageContainer);
 const commentContainer = new CommentContainer(appContainer);
 const editorContainer = new EditorContainer(appContainer);
-const personalContainer = new PersonalContainer(appContainer);
 const injectableContainers = [
   appContainer, socketIoContainer, pageContainer, pageHistoryContainer, revisionComparerContainer,
-  commentContainer, editorContainer, personalContainer,
+  commentContainer, editorContainer,
 ];
 
 logger.info('unstated containers have been initialized');
@@ -106,8 +104,7 @@ Object.assign(componentMappings, {
 
   'page-timeline': <PageTimeline />,
 
-  'personal-setting': <PersonalSettings crowi={personalContainer} />,
-
+  'personal-setting': <PersonalSettings />,
   'my-drafts': <MyDraftList />,
 
   'grw-fab-container': <Fab />,

+ 0 - 56
packages/app/src/client/services/PersonalContainer.js

@@ -1,56 +0,0 @@
-import { Container } from 'unstated';
-
-import loggerFactory from '~/utils/logger';
-
-import { apiv3Put } from '../util/apiv3-client';
-
-// eslint-disable-next-line no-unused-vars
-const logger = loggerFactory('growi:services:PersonalContainer');
-
-/**
- * Service container for personal settings page (PersonalSettings.jsx)
- * @extends {Container} unstated Container
- */
-export default class PersonalContainer extends Container {
-
-  constructor(appContainer) {
-    super();
-
-    this.appContainer = appContainer;
-
-    this.state = {
-      retrieveError: null,
-      name: '',
-      email: '',
-      isEmailPublished: false,
-      lang: 'en_US',
-      isGravatarEnabled: false,
-      externalAccounts: [],
-      apiToken: '',
-      slackMemberId: '',
-    };
-
-  }
-
-  /**
-   * Workaround for the mangling in production build to break constructor.name
-   */
-  static getClassName() {
-    return 'PersonalContainer';
-  }
-
-  /**
-   * Disassociate LDAP account
-   */
-  async disassociateLdapAccount(account) {
-    try {
-      await apiv3Put('/personal-setting/disassociate-ldap', account);
-    }
-    catch (err) {
-      this.setState({ retrieveError: err });
-      logger.error(err);
-      throw new Error('Failed to disassociate ldap account');
-    }
-  }
-
-}

+ 0 - 98
packages/app/src/components/Me/DisassociateModal.jsx

@@ -1,98 +0,0 @@
-import React from 'react';
-
-import PropTypes from 'prop-types';
-import { useTranslation } from 'react-i18next';
-import {
-  Modal,
-  ModalHeader,
-  ModalBody,
-  ModalFooter,
-} from 'reactstrap';
-
-import AppContainer from '~/client/services/AppContainer';
-import PersonalContainer from '~/client/services/PersonalContainer';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
-import { useSWRxPersonalExternalAccounts } from '~/stores/personal-settings';
-
-import { withUnstatedContainers } from '../UnstatedUtils';
-
-
-class DisassociateModal extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.onClickDisassociateBtn = this.onClickDisassociateBtn.bind(this);
-  }
-
-  async onClickDisassociateBtn() {
-    const { t, personalContainer, onDisassociated } = this.props;
-    const { providerType, accountId } = this.props.accountForDisassociate;
-
-    try {
-      await personalContainer.disassociateLdapAccount({ providerType, accountId });
-      this.props.onClose();
-      toastSuccess(t('security_setting.updated_general_security_setting'));
-    }
-    catch (err) {
-      toastError(err);
-    }
-
-    if (onDisassociated != null) {
-      onDisassociated();
-    }
-  }
-
-  render() {
-    const { t, accountForDisassociate } = this.props;
-    const { providerType, accountId } = accountForDisassociate;
-
-    return (
-      <Modal isOpen={this.props.isOpen} toggle={this.props.onClose}>
-        <ModalHeader className="bg-info text-light" toggle={this.props.onClose}>
-          {t('personal_settings.disassociate_external_account')}
-        </ModalHeader>
-        <ModalBody>
-          {/* eslint-disable-next-line react/no-danger */}
-          <p dangerouslySetInnerHTML={{ __html: t('personal_settings.disassociate_external_account_desc', { providerType, accountId }) }} />
-        </ModalBody>
-        <ModalFooter>
-          <button type="button" className="btn btn-sm btn-outline-secondary" onClick={this.props.onClose}>
-            { t('Cancel') }
-          </button>
-          <button type="button" className="btn btn-sm btn-danger" onClick={this.onClickDisassociateBtn}>
-            <i className="ti-unlink"></i>
-            { t('Disassociate') }
-          </button>
-        </ModalFooter>
-      </Modal>
-    );
-  }
-
-}
-
-DisassociateModal.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-  personalContainer: PropTypes.instanceOf(PersonalContainer).isRequired,
-
-  isOpen: PropTypes.bool.isRequired,
-  onClose: PropTypes.func.isRequired,
-  accountForDisassociate: PropTypes.object.isRequired,
-  onDisassociated: PropTypes.func,
-
-};
-
-const DisassociateModalWrapperFC = (props) => {
-  const { t } = useTranslation();
-  const { mutate: mutatePersonalExternalAccounts } = useSWRxPersonalExternalAccounts();
-  return <DisassociateModal t={t} onDisassociated={mutatePersonalExternalAccounts} {...props} />;
-};
-
-/**
- * Wrapper component for using unstated
- */
-const DisassociateModalWrapper = withUnstatedContainers(DisassociateModalWrapperFC, [AppContainer, PersonalContainer]);
-
-
-export default DisassociateModalWrapper;

+ 69 - 0
packages/app/src/components/Me/DisassociateModal.tsx

@@ -0,0 +1,69 @@
+import React, { useCallback } from 'react';
+
+import { useTranslation } from 'react-i18next';
+import {
+  Modal,
+  ModalHeader,
+  ModalBody,
+  ModalFooter,
+} from 'reactstrap';
+
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
+import { IExternalAccount } from '~/interfaces/external-account';
+import { usePersonalSettings, useSWRxPersonalExternalAccounts } from '~/stores/personal-settings';
+
+type Props = {
+  isOpen: boolean,
+  onClose: () => void,
+  accountForDisassociate: IExternalAccount,
+}
+
+
+const DisassociateModal = (props: Props): JSX.Element => {
+
+  const { t } = useTranslation();
+  const { mutate: mutatePersonalExternalAccounts } = useSWRxPersonalExternalAccounts();
+  const { disassociateLdapAccount } = usePersonalSettings();
+
+  const { providerType, accountId } = props.accountForDisassociate;
+
+  const disassociateAccountHandler = useCallback(async() => {
+
+    try {
+      await disassociateLdapAccount({ providerType, accountId });
+      props.onClose();
+      toastSuccess(t('security_setting.updated_general_security_setting'));
+    }
+    catch (err) {
+      toastError(err);
+    }
+
+    if (mutatePersonalExternalAccounts != null) {
+      mutatePersonalExternalAccounts();
+    }
+  }, [accountId, disassociateLdapAccount, mutatePersonalExternalAccounts, props, providerType, t]);
+
+  return (
+    <Modal isOpen={props.isOpen} toggle={props.onClose}>
+      <ModalHeader className="bg-info text-light" toggle={props.onClose}>
+        {t('personal_settings.disassociate_external_account')}
+      </ModalHeader>
+      <ModalBody>
+        {/* eslint-disable-next-line react/no-danger */}
+        <p dangerouslySetInnerHTML={{ __html: t('personal_settings.disassociate_external_account_desc', { providerType, accountId }) }} />
+      </ModalBody>
+      <ModalFooter>
+        <button type="button" className="btn btn-sm btn-outline-secondary" onClick={props.onClose}>
+          { t('Cancel') }
+        </button>
+        <button type="button" className="btn btn-sm btn-danger" onClick={disassociateAccountHandler}>
+          <i className="ti-unlink"></i>
+          { t('Disassociate') }
+        </button>
+      </ModalFooter>
+    </Modal>
+  );
+};
+
+
+export default DisassociateModal;

+ 7 - 1
packages/app/src/stores/personal-settings.tsx

@@ -1,4 +1,4 @@
-import useSWR, { mutate, SWRResponse } from 'swr';
+import useSWR, { SWRResponse } from 'swr';
 
 import { IExternalAccount } from '~/interfaces/external-account';
 import { IUser } from '~/interfaces/user';
@@ -19,6 +19,7 @@ export type IPersonalSettingsInfoOption = {
   sync: () => void,
   updateBasicInfo: () => Promise<void>,
   associateLdapAccount: (account: { username: string, password: string }) => Promise<void>,
+  disassociateLdapAccount: (account: { providerType: string, accountId: string }) => Promise<void>,
 }
 
 export const usePersonalSettings = (): SWRResponse<IUser, Error> & IPersonalSettingsInfoOption => {
@@ -58,11 +59,16 @@ export const usePersonalSettings = (): SWRResponse<IUser, Error> & IPersonalSett
     await apiv3Put('/personal-setting/associate-ldap', account);
   };
 
+  const disassociateLdapAccount = async(account): Promise<void> => {
+    await apiv3Put('/personal-setting/disassociate-ldap', account);
+  };
+
   return {
     ...swrResult,
     sync,
     updateBasicInfo,
     associateLdapAccount,
+    disassociateLdapAccount,
   };
 };