UserGroupTable.jsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import React, { Fragment } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import dateFnsFormat from 'date-fns/format';
  5. import { withUnstatedContainers } from '../../UnstatedUtils';
  6. import AppContainer from '~/client/services/AppContainer';
  7. class UserGroupTable extends React.Component {
  8. constructor(props) {
  9. super(props);
  10. this.xss = window.xss;
  11. this.state = {
  12. userGroups: this.props.userGroups,
  13. userGroupMap: {},
  14. };
  15. this.generateUserGroupMap = this.generateUserGroupMap.bind(this);
  16. this.onDelete = this.onDelete.bind(this);
  17. }
  18. componentWillMount() {
  19. const userGroupMap = this.generateUserGroupMap(this.props.userGroups, this.props.userGroupRelations);
  20. this.setState({ userGroupMap });
  21. }
  22. componentWillReceiveProps(nextProps) {
  23. const { userGroups, userGroupRelations } = nextProps;
  24. const userGroupMap = this.generateUserGroupMap(userGroups, userGroupRelations);
  25. this.setState({
  26. userGroups,
  27. userGroupMap,
  28. });
  29. }
  30. generateUserGroupMap(userGroups, userGroupRelations) {
  31. const userGroupMap = {};
  32. userGroupRelations.forEach((relation) => {
  33. const group = relation.relatedGroup;
  34. const users = userGroupMap[group] || [];
  35. users.push(relation.relatedUser);
  36. // register
  37. userGroupMap[group] = users;
  38. });
  39. return userGroupMap;
  40. }
  41. onDelete(e) {
  42. const { target } = e;
  43. const groupId = target.getAttribute('data-user-group-id');
  44. const group = this.state.userGroups.find((group) => {
  45. return group._id === groupId;
  46. });
  47. this.props.onDelete(group);
  48. }
  49. render() {
  50. const { t } = this.props;
  51. return (
  52. <Fragment>
  53. <h2>{t('admin:user_group_management.group_list')}</h2>
  54. <table className="table table-bordered table-user-list">
  55. <thead>
  56. <tr>
  57. <th>{t('Name')}</th>
  58. <th>{t('User')}</th>
  59. <th width="100px">{t('Created')}</th>
  60. <th width="70px"></th>
  61. </tr>
  62. </thead>
  63. <tbody>
  64. {this.state.userGroups.map((group) => {
  65. const users = this.state.userGroupMap[group._id];
  66. return (
  67. <tr key={group._id}>
  68. {this.props.isAclEnabled
  69. ? (
  70. <td><a href={`/admin/user-group-detail/${group._id}`}>{this.xss.process(group.name)}</a></td>
  71. )
  72. : (
  73. <td>{this.xss.process(group.name)}</td>
  74. )
  75. }
  76. <td>
  77. <ul className="list-inline">
  78. {users != null && users.map((user) => {
  79. return <li key={user._id} className="list-inline-item badge badge-pill badge-warning">{this.xss.process(user.username)}</li>;
  80. })}
  81. </ul>
  82. </td>
  83. <td>{dateFnsFormat(new Date(group.createdAt), 'yyyy-MM-dd')}</td>
  84. {this.props.isAclEnabled
  85. ? (
  86. <td>
  87. <div className="btn-group admin-group-menu">
  88. <button
  89. type="button"
  90. id={`admin-group-menu-button-${group._id}`}
  91. className="btn btn-outline-secondary btn-sm dropdown-toggle"
  92. data-toggle="dropdown"
  93. >
  94. <i className="icon-settings"></i>
  95. </button>
  96. <div className="dropdown-menu" role="menu" aria-labelledby={`admin-group-menu-button-${group._id}`}>
  97. <a className="dropdown-item" href={`/admin/user-group-detail/${group._id}`}>
  98. <i className="icon-fw icon-note"></i> {t('Edit')}
  99. </a>
  100. <button className="dropdown-item" type="button" role="button" onClick={this.onDelete} data-user-group-id={group._id}>
  101. <i className="icon-fw icon-fire text-danger"></i> {t('Delete')}
  102. </button>
  103. </div>
  104. </div>
  105. </td>
  106. )
  107. : (
  108. <td></td>
  109. )
  110. }
  111. </tr>
  112. );
  113. })}
  114. </tbody>
  115. </table>
  116. </Fragment>
  117. );
  118. }
  119. }
  120. /**
  121. * Wrapper component for using unstated
  122. */
  123. const UserGroupTableWrapper = withUnstatedContainers(UserGroupTable, [AppContainer]);
  124. UserGroupTable.propTypes = {
  125. t: PropTypes.func.isRequired, // i18next
  126. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  127. userGroups: PropTypes.arrayOf(PropTypes.object).isRequired,
  128. userGroupRelations: PropTypes.arrayOf(PropTypes.object).isRequired,
  129. isAclEnabled: PropTypes.bool.isRequired,
  130. onDelete: PropTypes.func.isRequired,
  131. };
  132. export default withTranslation()(UserGroupTableWrapper);