TeamMemberRow.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import React, { PureComponent } from 'react';
  2. import { connect, ConnectedProps } from 'react-redux';
  3. import { SelectableValue } from '@grafana/data';
  4. import { LegacyForms, DeleteButton } from '@grafana/ui';
  5. import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
  6. import { WithFeatureToggle } from 'app/core/components/WithFeatureToggle';
  7. import { TeamMember, teamsPermissionLevels, TeamPermissionLevel } from 'app/types';
  8. import { updateTeamMember, removeTeamMember } from './state/actions';
  9. const { Select } = LegacyForms;
  10. const mapDispatchToProps = {
  11. removeTeamMember,
  12. updateTeamMember,
  13. };
  14. const connector = connect(null, mapDispatchToProps);
  15. interface OwnProps {
  16. member: TeamMember;
  17. syncEnabled: boolean;
  18. editorsCanAdmin: boolean;
  19. signedInUserIsTeamAdmin: boolean;
  20. }
  21. export type Props = ConnectedProps<typeof connector> & OwnProps;
  22. export class TeamMemberRow extends PureComponent<Props> {
  23. constructor(props: Props) {
  24. super(props);
  25. this.renderLabels = this.renderLabels.bind(this);
  26. this.renderPermissions = this.renderPermissions.bind(this);
  27. }
  28. onRemoveMember(member: TeamMember) {
  29. this.props.removeTeamMember(member.userId);
  30. }
  31. onPermissionChange = (item: SelectableValue<TeamPermissionLevel>, member: TeamMember) => {
  32. const permission = item.value;
  33. const updatedTeamMember: TeamMember = {
  34. ...member,
  35. permission: permission as number,
  36. };
  37. this.props.updateTeamMember(updatedTeamMember);
  38. };
  39. renderPermissions(member: TeamMember) {
  40. const { editorsCanAdmin, signedInUserIsTeamAdmin } = this.props;
  41. const value = teamsPermissionLevels.find((dp) => dp.value === member.permission)!;
  42. return (
  43. <WithFeatureToggle featureToggle={editorsCanAdmin}>
  44. <td className="width-5 team-permissions">
  45. <div className="gf-form">
  46. {signedInUserIsTeamAdmin && (
  47. <Select
  48. isSearchable={false}
  49. options={teamsPermissionLevels}
  50. onChange={(item) => this.onPermissionChange(item, member)}
  51. className="gf-form-select-box__control--menu-right"
  52. value={value}
  53. />
  54. )}
  55. {!signedInUserIsTeamAdmin && <span>{value.label}</span>}
  56. </div>
  57. </td>
  58. </WithFeatureToggle>
  59. );
  60. }
  61. renderLabels(labels: string[]) {
  62. if (!labels) {
  63. return <td />;
  64. }
  65. return (
  66. <td>
  67. {labels.map((label) => (
  68. <TagBadge key={label} label={label} removeIcon={false} count={0} onClick={() => {}} />
  69. ))}
  70. </td>
  71. );
  72. }
  73. render() {
  74. const { member, syncEnabled, signedInUserIsTeamAdmin } = this.props;
  75. return (
  76. <tr key={member.userId}>
  77. <td className="width-4 text-center">
  78. <img
  79. aria-label={`Avatar for team member "${member.name}"`}
  80. className="filter-table__avatar"
  81. src={member.avatarUrl}
  82. />
  83. </td>
  84. <td>{member.login}</td>
  85. <td>{member.email}</td>
  86. <td>{member.name}</td>
  87. {this.renderPermissions(member)}
  88. {syncEnabled && this.renderLabels(member.labels)}
  89. <td className="text-right">
  90. <DeleteButton
  91. aria-label="Remove team member"
  92. size="sm"
  93. disabled={!signedInUserIsTeamAdmin}
  94. onConfirm={() => this.onRemoveMember(member)}
  95. />
  96. </td>
  97. </tr>
  98. );
  99. }
  100. }
  101. export default connector(TeamMemberRow);