AdminUsersContainer.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. import { isServer } from '@growi/core/dist/utils';
  2. import { debounce } from 'throttle-debounce';
  3. import { Container } from 'unstated';
  4. import {
  5. apiv3Delete, apiv3Get, apiv3Post, apiv3Put,
  6. } from '../util/apiv3-client';
  7. /**
  8. * Service container for admin users page (Users.jsx)
  9. * @extends {Container} unstated Container
  10. */
  11. export default class AdminUsersContainer extends Container {
  12. constructor(appContainer) {
  13. super();
  14. if (isServer()) {
  15. return;
  16. }
  17. this.appContainer = appContainer;
  18. this.state = {
  19. users: [],
  20. sort: 'id',
  21. sortOrder: 'asc',
  22. isPasswordResetModalShown: false,
  23. isUserInviteModalShown: false,
  24. userForPasswordResetModal: null,
  25. totalUsers: 0,
  26. activePage: 1,
  27. pagingLimit: Infinity,
  28. selectedStatusList: new Set(['all']),
  29. searchText: '',
  30. };
  31. this.showPasswordResetModal = this.showPasswordResetModal.bind(this);
  32. this.hidePasswordResetModal = this.hidePasswordResetModal.bind(this);
  33. this.toggleUserInviteModal = this.toggleUserInviteModal.bind(this);
  34. this.handleChangeSearchTextDebouce = debounce(3000, () => this.retrieveUsersByPagingNum(1));
  35. }
  36. /**
  37. * Workaround for the mangling in production build to break constructor.name
  38. */
  39. static getClassName() {
  40. return 'AdminUsersContainer';
  41. }
  42. /**
  43. * Workaround for status list
  44. */
  45. isSelected(statusType) {
  46. return this.state.selectedStatusList.has(statusType);
  47. }
  48. handleClick(statusType) {
  49. const all = 'all';
  50. if (this.isSelected(statusType)) {
  51. this.deleteStatusFromList(statusType);
  52. }
  53. else {
  54. if (statusType === all) {
  55. this.clearStatusList();
  56. }
  57. else {
  58. this.deleteStatusFromList(all);
  59. }
  60. this.addStatusToList(statusType);
  61. }
  62. }
  63. async clearStatusList() {
  64. const { selectedStatusList } = this.state;
  65. selectedStatusList.clear();
  66. await this.setState({ selectedStatusList });
  67. }
  68. async addStatusToList(statusType) {
  69. const { selectedStatusList } = this.state;
  70. selectedStatusList.add(statusType);
  71. await this.setState({ selectedStatusList });
  72. this.retrieveUsersByPagingNum(1);
  73. }
  74. async deleteStatusFromList(statusType) {
  75. const { selectedStatusList } = this.state;
  76. selectedStatusList.delete(statusType);
  77. await this.setState({ selectedStatusList });
  78. this.retrieveUsersByPagingNum(1);
  79. }
  80. /**
  81. * Workaround for Increment Search Text Input
  82. */
  83. async handleChangeSearchText(searchText) {
  84. await this.setState({ searchText });
  85. this.handleChangeSearchTextDebouce();
  86. }
  87. async clearSearchText() {
  88. await this.setState({ searchText: '' });
  89. this.retrieveUsersByPagingNum(1);
  90. }
  91. /**
  92. * Workaround for Sorting
  93. */
  94. async sort(sort, isAsc) {
  95. const sortOrder = isAsc ? 'asc' : 'desc';
  96. await this.setState({ sort, sortOrder });
  97. this.retrieveUsersByPagingNum(1);
  98. }
  99. async resetAllChanges() {
  100. await this.setState({
  101. sort: 'id',
  102. sortOrder: 'asc',
  103. searchText: '',
  104. selectedStatusList: new Set(['all']),
  105. });
  106. this.retrieveUsersByPagingNum(1);
  107. }
  108. /**
  109. * syncUsers of selectedPage
  110. * @memberOf AdminUsersContainer
  111. * @param {number} selectedPage
  112. */
  113. async retrieveUsersByPagingNum(selectedPage) {
  114. const params = {
  115. page: selectedPage,
  116. sort: this.state.sort,
  117. sortOrder: this.state.sortOrder,
  118. selectedStatusList: Array.from(this.state.selectedStatusList),
  119. searchText: this.state.searchText,
  120. // Even if email is hidden, it will be displayed on admin page.
  121. forceIncludeAttributes: ['email'],
  122. };
  123. const { data } = await apiv3Get('/users', params);
  124. if (data.paginateResult == null) {
  125. throw new Error('data must conclude \'paginateResult\' property.');
  126. }
  127. const { docs: users, totalDocs: totalUsers, limit: pagingLimit } = data.paginateResult;
  128. this.setState({
  129. users,
  130. totalUsers,
  131. pagingLimit,
  132. activePage: selectedPage,
  133. });
  134. }
  135. /**
  136. * create user invited
  137. * @memberOf AdminUsersContainer
  138. * @param {object} shapedEmailList
  139. * @param {bool} sendEmail
  140. */
  141. async createUserInvited(shapedEmailList, sendEmail) {
  142. const response = await apiv3Post('/users/invite', {
  143. shapedEmailList,
  144. sendEmail,
  145. });
  146. await this.retrieveUsersByPagingNum(this.state.activePage);
  147. return response.data;
  148. }
  149. /**
  150. * open reset password modal, and props user
  151. * @memberOf AdminUsersContainer
  152. * @param {object} user
  153. */
  154. async showPasswordResetModal(user) {
  155. await this.setState({
  156. isPasswordResetModalShown: true,
  157. userForPasswordResetModal: user,
  158. });
  159. }
  160. /**
  161. * close reset password modal
  162. * @memberOf AdminUsersContainer
  163. */
  164. async hidePasswordResetModal() {
  165. await this.setState({
  166. isPasswordResetModalShown: false,
  167. userForPasswordResetModal: null,
  168. });
  169. }
  170. /**
  171. * toggle user invite modal
  172. * @memberOf AdminUsersContainer
  173. */
  174. async toggleUserInviteModal() {
  175. await this.setState({ isUserInviteModalShown: !this.state.isUserInviteModalShown });
  176. }
  177. /**
  178. * Grant user admin
  179. * @memberOf AdminUsersContainer
  180. * @param {string} userId
  181. * @return {string} username
  182. */
  183. async grantUserAdmin(userId) {
  184. const response = await apiv3Put(`/users/${userId}/grant-admin`);
  185. const { username } = response.data.userData;
  186. await this.retrieveUsersByPagingNum(this.state.activePage);
  187. return username;
  188. }
  189. /**
  190. * Revoke user admin
  191. * @memberOf AdminUsersContainer
  192. * @param {string} userId
  193. * @return {string} username
  194. */
  195. async revokeUserAdmin(userId) {
  196. const response = await apiv3Put(`/users/${userId}/revoke-admin`);
  197. const { username } = response.data.userData;
  198. await this.retrieveUsersByPagingNum(this.state.activePage);
  199. return username;
  200. }
  201. /**
  202. * Grant user read only access
  203. * @memberOf AdminUsersContainer
  204. * @param {string} userId
  205. * @return {string} username
  206. */
  207. async grantUserReadOnly(userId) {
  208. const response = await apiv3Put(`/users/${userId}/grant-read-only`);
  209. const { username } = response.data.userData;
  210. await this.retrieveUsersByPagingNum(this.state.activePage);
  211. return username;
  212. }
  213. /**
  214. * Revoke user read only access
  215. * @memberOf AdminUsersContainer
  216. * @param {string} userId
  217. * @return {string} username
  218. */
  219. async revokeUserReadOnly(userId) {
  220. const response = await apiv3Put(`/users/${userId}/revoke-read-only`);
  221. const { username } = response.data.userData;
  222. await this.retrieveUsersByPagingNum(this.state.activePage);
  223. return username;
  224. }
  225. /**
  226. * Activate user
  227. * @memberOf AdminUsersContainer
  228. * @param {string} userId
  229. * @return {string} username
  230. */
  231. async activateUser(userId) {
  232. const response = await apiv3Put(`/users/${userId}/activate`);
  233. const { username } = response.data.userData;
  234. await this.retrieveUsersByPagingNum(this.state.activePage);
  235. return username;
  236. }
  237. /**
  238. * Deactivate user
  239. * @memberOf AdminUsersContainer
  240. * @param {string} userId
  241. * @return {string} username
  242. */
  243. async deactivateUser(userId) {
  244. const response = await apiv3Put(`/users/${userId}/deactivate`);
  245. const { username } = response.data.userData;
  246. await this.retrieveUsersByPagingNum(this.state.activePage);
  247. return username;
  248. }
  249. /**
  250. * remove user
  251. * @memberOf AdminUsersContainer
  252. * @param {string} userId
  253. * @return {object} removedUserData
  254. */
  255. async removeUser(userId) {
  256. const response = await apiv3Delete(`/users/${userId}/remove`);
  257. const removedUserData = response.data.userData;
  258. await this.retrieveUsersByPagingNum(this.state.activePage);
  259. return removedUserData;
  260. }
  261. }