PersonalContainer.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import { Container } from 'unstated';
  2. import loggerFactory from '~/utils/logger';
  3. // eslint-disable-next-line no-unused-vars
  4. const logger = loggerFactory('growi:services:PersonalContainer');
  5. const DEFAULT_IMAGE = '/images/icons/user.svg';
  6. /**
  7. * Service container for personal settings page (PersonalSettings.jsx)
  8. * @extends {Container} unstated Container
  9. */
  10. export default class PersonalContainer extends Container {
  11. constructor(appContainer) {
  12. super();
  13. this.appContainer = appContainer;
  14. this.state = {
  15. retrieveError: null,
  16. name: '',
  17. email: '',
  18. registrationWhiteList: this.appContainer.getConfig().registrationWhiteList,
  19. isEmailPublished: false,
  20. lang: 'en_US',
  21. isGravatarEnabled: false,
  22. isUploadedPicture: false,
  23. uploadedPictureSrc: this.getUploadedPictureSrc(this.appContainer.currentUser),
  24. externalAccounts: [],
  25. apiToken: '',
  26. slackMemberId: '',
  27. };
  28. }
  29. /**
  30. * Workaround for the mangling in production build to break constructor.name
  31. */
  32. static getClassName() {
  33. return 'PersonalContainer';
  34. }
  35. /**
  36. * retrieve personal data
  37. */
  38. async retrievePersonalData() {
  39. try {
  40. const response = await this.appContainer.apiv3.get('/personal-setting/');
  41. const { currentUser } = response.data;
  42. this.setState({
  43. name: currentUser.name,
  44. email: currentUser.email,
  45. isEmailPublished: currentUser.isEmailPublished,
  46. lang: currentUser.lang,
  47. isGravatarEnabled: currentUser.isGravatarEnabled,
  48. apiToken: currentUser.apiToken,
  49. slackMemberId: currentUser.slackMemberId,
  50. });
  51. }
  52. catch (err) {
  53. this.setState({ retrieveError: err });
  54. logger.error(err);
  55. throw new Error('Failed to fetch personal data');
  56. }
  57. }
  58. /**
  59. * define a function for uploaded picture
  60. */
  61. getUploadedPictureSrc(user) {
  62. if (user == null) {
  63. return DEFAULT_IMAGE;
  64. }
  65. if (user.image) {
  66. this.setState({ isUploadedPicture: true });
  67. return user.image;
  68. }
  69. if (user.imageAttachment != null) {
  70. this.setState({ isUploadedPicture: true });
  71. return user.imageAttachment.filePathProxied;
  72. }
  73. return DEFAULT_IMAGE;
  74. }
  75. /**
  76. * retrieve external accounts that linked me
  77. */
  78. async retrieveExternalAccounts() {
  79. try {
  80. const response = await this.appContainer.apiv3.get('/personal-setting/external-accounts');
  81. const { externalAccounts } = response.data;
  82. this.setState({ externalAccounts });
  83. }
  84. catch (err) {
  85. this.setState({ retrieveError: err });
  86. logger.error(err);
  87. throw new Error('Failed to fetch external accounts');
  88. }
  89. }
  90. /**
  91. * Change name
  92. */
  93. changeName(inputValue) {
  94. this.setState({ name: inputValue });
  95. }
  96. /**
  97. * Change email
  98. */
  99. changeEmail(inputValue) {
  100. this.setState({ email: inputValue });
  101. }
  102. /**
  103. * Change Slack Member ID
  104. */
  105. changeSlackMemberId(inputValue) {
  106. this.setState({ slackMemberId: inputValue });
  107. }
  108. /**
  109. * Change isEmailPublished
  110. */
  111. changeIsEmailPublished(boolean) {
  112. this.setState({ isEmailPublished: boolean });
  113. }
  114. /**
  115. * Change lang
  116. */
  117. changeLang(lang) {
  118. this.setState({ lang });
  119. }
  120. /**
  121. * Change isGravatarEnabled
  122. */
  123. changeIsGravatarEnabled(boolean) {
  124. this.setState({ isGravatarEnabled: boolean });
  125. }
  126. /**
  127. * Update basic info
  128. * @memberOf PersonalContainer
  129. * @return {Array} basic info
  130. */
  131. async updateBasicInfo() {
  132. try {
  133. const response = await this.appContainer.apiv3.put('/personal-setting/', {
  134. name: this.state.name,
  135. email: this.state.email,
  136. isEmailPublished: this.state.isEmailPublished,
  137. lang: this.state.lang,
  138. slackMemberId: this.state.slackMemberId,
  139. });
  140. const { updatedUser } = response.data;
  141. this.setState({
  142. name: updatedUser.name,
  143. email: updatedUser.email,
  144. isEmailPublished: updatedUser.isEmailPublished,
  145. lang: updatedUser.lang,
  146. slackMemberId: updatedUser.slackMemberId,
  147. });
  148. }
  149. catch (err) {
  150. this.setState({ retrieveError: err });
  151. logger.error(err);
  152. throw new Error('Failed to update personal data');
  153. }
  154. }
  155. /**
  156. * Update profile image
  157. * @memberOf PersonalContainer
  158. */
  159. async updateProfileImage() {
  160. try {
  161. const response = await this.appContainer.apiv3.put('/personal-setting/image-type', {
  162. isGravatarEnabled: this.state.isGravatarEnabled,
  163. });
  164. const { userData } = response.data;
  165. this.setState({
  166. isGravatarEnabled: userData.isGravatarEnabled,
  167. });
  168. }
  169. catch (err) {
  170. this.setState({ retrieveError: err });
  171. logger.error(err);
  172. throw new Error('Failed to update profile image');
  173. }
  174. }
  175. /**
  176. * Upload image
  177. */
  178. async uploadAttachment(file) {
  179. try {
  180. const formData = new FormData();
  181. formData.append('file', file);
  182. formData.append('_csrf', this.appContainer.csrfToken);
  183. const response = await this.appContainer.apiPost('/attachments.uploadProfileImage', formData);
  184. this.setState({ isUploadedPicture: true, uploadedPictureSrc: response.attachment.filePathProxied });
  185. }
  186. catch (err) {
  187. this.setState({ retrieveError: err });
  188. logger.error(err);
  189. throw new Error('Failed to upload profile image');
  190. }
  191. }
  192. /**
  193. * Delete image
  194. */
  195. async deleteProfileImage() {
  196. try {
  197. await this.appContainer.apiPost('/attachments.removeProfileImage', { _csrf: this.appContainer.csrfToken });
  198. this.setState({ isUploadedPicture: false, uploadedPictureSrc: DEFAULT_IMAGE });
  199. }
  200. catch (err) {
  201. this.setState({ retrieveError: err });
  202. logger.error(err);
  203. throw new Error('Failed to delete profile image');
  204. }
  205. }
  206. /**
  207. * Associate LDAP account
  208. */
  209. async associateLdapAccount(account) {
  210. try {
  211. await this.appContainer.apiv3.put('/personal-setting/associate-ldap', account);
  212. }
  213. catch (err) {
  214. this.setState({ retrieveError: err });
  215. logger.error(err);
  216. throw new Error('Failed to associate ldap account');
  217. }
  218. }
  219. /**
  220. * Disassociate LDAP account
  221. */
  222. async disassociateLdapAccount(account) {
  223. try {
  224. await this.appContainer.apiv3.put('/personal-setting/disassociate-ldap', account);
  225. }
  226. catch (err) {
  227. this.setState({ retrieveError: err });
  228. logger.error(err);
  229. throw new Error('Failed to disassociate ldap account');
  230. }
  231. }
  232. }