BasicInfoSettings.jsx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import React, { useEffect } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { useTranslation } from 'react-i18next';
  4. import AppContainer from '~/client/services/AppContainer';
  5. import PersonalContainer from '~/client/services/PersonalContainer';
  6. import { toastSuccess, toastError } from '~/client/util/apiNotification';
  7. import { localeMetadatas } from '~/client/util/i18n';
  8. import { usePersonalSettingsInfo } from '~/stores/personal-settings';
  9. import { withUnstatedContainers } from '../UnstatedUtils';
  10. class BasicInfoSettings extends React.Component {
  11. constructor() {
  12. super();
  13. this.onClickSubmit = this.onClickSubmit.bind(this);
  14. }
  15. async onClickSubmit() {
  16. const { t, personalContainer } = this.props;
  17. try {
  18. await personalContainer.updateBasicInfo();
  19. toastSuccess(t('toaster.update_successed', { target: t('Basic Info') }));
  20. }
  21. catch (err) {
  22. toastError(err);
  23. }
  24. }
  25. render() {
  26. const {
  27. t, appContainer, personalSettingsInfo, mutatePersonalSettingsInfo, error,
  28. } = this.props;
  29. const { registrationWhiteList } = appContainer.getConfig();
  30. return (
  31. <>
  32. <div className="form-group row">
  33. <label htmlFor="userForm[name]" className="text-left text-md-right col-md-3 col-form-label">{t('Name')}</label>
  34. <div className="col-md-6">
  35. <input
  36. className="form-control"
  37. type="text"
  38. name="userForm[name]"
  39. defaultValue={personalSettingsInfo.name}
  40. onChange={(e) => { mutatePersonalSettingsInfo({ ...personalSettingsInfo, name: e.target.value }) }}
  41. />
  42. </div>
  43. </div>
  44. <div className="form-group row">
  45. <label htmlFor="userForm[email]" className="text-left text-md-right col-md-3 col-form-label">{t('Email')}</label>
  46. <div className="col-md-6">
  47. <input
  48. className="form-control"
  49. type="text"
  50. name="userForm[email]"
  51. defaultValue={personalSettingsInfo.email}
  52. onChange={(e) => { mutatePersonalSettingsInfo({ ...personalSettingsInfo, email: e.target.value }) }}
  53. />
  54. {registrationWhiteList.length !== 0 && (
  55. <div className="form-text text-muted">
  56. {t('page_register.form_help.email')}
  57. <ul>
  58. {registrationWhiteList.map(data => <li key={data}><code>{data}</code></li>)}
  59. </ul>
  60. </div>
  61. )}
  62. </div>
  63. </div>
  64. <div className="form-group row">
  65. <label className="text-left text-md-right col-md-3 col-form-label">{t('Disclose E-mail')}</label>
  66. <div className="col-md-6">
  67. <div className="custom-control custom-radio custom-control-inline">
  68. <input
  69. type="radio"
  70. id="radioEmailShow"
  71. className="custom-control-input"
  72. name="userForm[isEmailPublished]"
  73. checked={personalSettingsInfo.isEmailPublished}
  74. onChange={() => mutatePersonalSettingsInfo({ ...personalSettingsInfo, isEmailPublished: true })}
  75. />
  76. <label className="custom-control-label" htmlFor="radioEmailShow">{t('Show')}</label>
  77. </div>
  78. <div className="custom-control custom-radio custom-control-inline">
  79. <input
  80. type="radio"
  81. id="radioEmailHide"
  82. className="custom-control-input"
  83. name="userForm[isEmailPublished]"
  84. checked={!personalSettingsInfo.isEmailPublished}
  85. onChange={() => mutatePersonalSettingsInfo({ ...personalSettingsInfo, isEmailPublished: false })}
  86. />
  87. <label className="custom-control-label" htmlFor="radioEmailHide">{t('Hide')}</label>
  88. </div>
  89. </div>
  90. </div>
  91. <div className="form-group row">
  92. <label className="text-left text-md-right col-md-3 col-form-label">{t('Language')}</label>
  93. <div className="col-md-6">
  94. {
  95. localeMetadatas.map(meta => (
  96. <div key={meta.id} className="custom-control custom-radio custom-control-inline">
  97. <input
  98. type="radio"
  99. id={`radioLang${meta.id}`}
  100. className="custom-control-input"
  101. name="userForm[lang]"
  102. checked={personalSettingsInfo.lang === meta.id}
  103. onChange={() => { mutatePersonalSettingsInfo({ ...personalSettingsInfo, lang: meta.id }) }}
  104. />
  105. <label className="custom-control-label" htmlFor={`radioLang${meta.id}`}>{meta.displayName}</label>
  106. </div>
  107. ))
  108. }
  109. </div>
  110. </div>
  111. <div className="form-group row">
  112. <label htmlFor="userForm[slackMemberId]" className="text-left text-md-right col-md-3 col-form-label">{t('Slack Member ID')}</label>
  113. <div className="col-md-6">
  114. <input
  115. className="form-control"
  116. type="text"
  117. key={personalSettingsInfo.slackMemberId}
  118. name="userForm[slackMemberId]"
  119. defaultValue={personalSettingsInfo.slackMemberId}
  120. onChange={(e) => { mutatePersonalSettingsInfo({ ...personalSettingsInfo, slackMemberId: e.target.value }) }}
  121. />
  122. </div>
  123. </div>
  124. <div className="row my-3">
  125. <div className="offset-4 col-5">
  126. <button
  127. data-testid="grw-besic-info-settings-update-button"
  128. type="button"
  129. className="btn btn-primary"
  130. onClick={this.onClickSubmit}
  131. disabled={error != null}
  132. >
  133. {t('Update')}
  134. </button>
  135. </div>
  136. </div>
  137. </>
  138. );
  139. }
  140. }
  141. BasicInfoSettings.propTypes = {
  142. t: PropTypes.func.isRequired, // i18next
  143. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  144. personalContainer: PropTypes.instanceOf(PersonalContainer).isRequired,
  145. personalSettingsInfo: PropTypes.object,
  146. mutatePersonalSettingsInfo: PropTypes.func,
  147. error: PropTypes.object,
  148. };
  149. const BasicInfoSettingsWrapperFC = (props) => {
  150. const { t } = useTranslation();
  151. const usePersonalSettingsInfoResult = usePersonalSettingsInfo();
  152. useEffect(() => {
  153. // Sync only when getting personal settings data from DB
  154. usePersonalSettingsInfoResult.sync();
  155. // eslint-disable-next-line react-hooks/exhaustive-deps
  156. }, [usePersonalSettingsInfoResult.personalSettingsDataFromDB]);
  157. return (
  158. <BasicInfoSettings
  159. t={t}
  160. personalSettingsInfo={usePersonalSettingsInfoResult.data || {}}
  161. mutatePersonalSettingsInfo={usePersonalSettingsInfoResult.mutate}
  162. error={usePersonalSettingsInfoResult.error}
  163. {...props}
  164. />
  165. );
  166. };
  167. /**
  168. * Wrapper component for using unstated
  169. */
  170. const BasicInfoSettingsWrapper = withUnstatedContainers(BasicInfoSettingsWrapperFC, [AppContainer, PersonalContainer]);
  171. export default BasicInfoSettingsWrapper;