UsersTable.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import React, { FC, useEffect, useState } from 'react';
  2. import { OrgRole } from '@grafana/data';
  3. import { Button, ConfirmModal } from '@grafana/ui';
  4. import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker';
  5. import { fetchBuiltinRoles, fetchRoleOptions } from 'app/core/components/RolePicker/api';
  6. import { contextSrv } from 'app/core/core';
  7. import { AccessControlAction, OrgUser, Role } from 'app/types';
  8. import { OrgRolePicker } from '../admin/OrgRolePicker';
  9. export interface Props {
  10. users: OrgUser[];
  11. orgId?: number;
  12. onRoleChange: (role: OrgRole, user: OrgUser) => void;
  13. onRemoveUser: (user: OrgUser) => void;
  14. }
  15. const UsersTable: FC<Props> = (props) => {
  16. const { users, orgId, onRoleChange, onRemoveUser } = props;
  17. const [userToRemove, setUserToRemove] = useState<OrgUser | null>(null);
  18. const [roleOptions, setRoleOptions] = useState<Role[]>([]);
  19. const [builtinRoles, setBuiltinRoles] = useState<{ [key: string]: Role[] }>({});
  20. useEffect(() => {
  21. async function fetchOptions() {
  22. try {
  23. if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
  24. let options = await fetchRoleOptions(orgId);
  25. setRoleOptions(options);
  26. }
  27. if (
  28. contextSrv.accessControlBuiltInRoleAssignmentEnabled() &&
  29. contextSrv.hasPermission(AccessControlAction.ActionBuiltinRolesList)
  30. ) {
  31. const builtInRoles = await fetchBuiltinRoles(orgId);
  32. setBuiltinRoles(builtInRoles);
  33. }
  34. } catch (e) {
  35. console.error('Error loading options');
  36. }
  37. }
  38. if (contextSrv.licensedAccessControlEnabled()) {
  39. fetchOptions();
  40. }
  41. }, [orgId]);
  42. return (
  43. <>
  44. <table className="filter-table form-inline">
  45. <thead>
  46. <tr>
  47. <th />
  48. <th>Login</th>
  49. <th>Email</th>
  50. <th>Name</th>
  51. <th>Seen</th>
  52. <th>Role</th>
  53. <th style={{ width: '34px' }} />
  54. </tr>
  55. </thead>
  56. <tbody>
  57. {users.map((user, index) => {
  58. return (
  59. <tr key={`${user.userId}-${index}`}>
  60. <td className="width-2 text-center">
  61. <img className="filter-table__avatar" src={user.avatarUrl} alt="User avatar" />
  62. </td>
  63. <td className="max-width-6">
  64. <span className="ellipsis" title={user.login}>
  65. {user.login}
  66. </span>
  67. </td>
  68. <td className="max-width-5">
  69. <span className="ellipsis" title={user.email}>
  70. {user.email}
  71. </span>
  72. </td>
  73. <td className="max-width-5">
  74. <span className="ellipsis" title={user.name}>
  75. {user.name}
  76. </span>
  77. </td>
  78. <td className="width-1">{user.lastSeenAtAge}</td>
  79. <td className="width-8">
  80. {contextSrv.licensedAccessControlEnabled() ? (
  81. <UserRolePicker
  82. userId={user.userId}
  83. orgId={orgId}
  84. builtInRole={user.role}
  85. onBuiltinRoleChange={(newRole) => onRoleChange(newRole, user)}
  86. roleOptions={roleOptions}
  87. builtInRoles={builtinRoles}
  88. disabled={!contextSrv.hasPermissionInMetadata(AccessControlAction.OrgUsersWrite, user)}
  89. />
  90. ) : (
  91. <OrgRolePicker
  92. aria-label="Role"
  93. value={user.role}
  94. disabled={!contextSrv.hasPermissionInMetadata(AccessControlAction.OrgUsersWrite, user)}
  95. onChange={(newRole) => onRoleChange(newRole, user)}
  96. />
  97. )}
  98. </td>
  99. {contextSrv.hasPermissionInMetadata(AccessControlAction.OrgUsersRemove, user) && (
  100. <td>
  101. <Button
  102. size="sm"
  103. variant="destructive"
  104. onClick={() => {
  105. setUserToRemove(user);
  106. }}
  107. icon="times"
  108. aria-label="Delete user"
  109. />
  110. </td>
  111. )}
  112. </tr>
  113. );
  114. })}
  115. </tbody>
  116. </table>
  117. {Boolean(userToRemove) && (
  118. <ConfirmModal
  119. body={`Are you sure you want to delete user ${userToRemove?.login}?`}
  120. confirmText="Delete"
  121. title="Delete"
  122. onDismiss={() => {
  123. setUserToRemove(null);
  124. }}
  125. isOpen={true}
  126. onConfirm={() => {
  127. if (!userToRemove) {
  128. return;
  129. }
  130. onRemoveUser(userToRemove);
  131. setUserToRemove(null);
  132. }}
  133. />
  134. )}
  135. </>
  136. );
  137. };
  138. export default UsersTable;