TeamGroupSync.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import React, { PureComponent } from 'react';
  2. import { connect } from 'react-redux';
  3. import { SlideDown } from 'app/core/components/Animations/SlideDown';
  4. import { Input, Tooltip } from '@grafana/ui';
  5. import { TeamGroup } from '../../types';
  6. import { addTeamGroup, loadTeamGroups, removeTeamGroup } from './state/actions';
  7. import { getTeamGroups } from './state/selectors';
  8. import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
  9. export interface Props {
  10. groups: TeamGroup[];
  11. loadTeamGroups: typeof loadTeamGroups;
  12. addTeamGroup: typeof addTeamGroup;
  13. removeTeamGroup: typeof removeTeamGroup;
  14. }
  15. interface State {
  16. isAdding: boolean;
  17. newGroupId?: string;
  18. }
  19. const headerTooltip = `Sync LDAP or OAuth groups with your Grafana teams.`;
  20. export class TeamGroupSync extends PureComponent<Props, State> {
  21. constructor(props: Props) {
  22. super(props);
  23. this.state = { isAdding: false, newGroupId: '' };
  24. }
  25. componentDidMount() {
  26. this.fetchTeamGroups();
  27. }
  28. async fetchTeamGroups() {
  29. await this.props.loadTeamGroups();
  30. }
  31. onToggleAdding = () => {
  32. this.setState({ isAdding: !this.state.isAdding });
  33. };
  34. onNewGroupIdChanged = (event: any) => {
  35. this.setState({ newGroupId: event.target.value });
  36. };
  37. onAddGroup = (event: any) => {
  38. event.preventDefault();
  39. this.props.addTeamGroup(this.state.newGroupId);
  40. this.setState({ isAdding: false, newGroupId: '' });
  41. };
  42. onRemoveGroup = (group: TeamGroup) => {
  43. this.props.removeTeamGroup(group.groupId);
  44. };
  45. isNewGroupValid() {
  46. return this.state.newGroupId.length > 1;
  47. }
  48. renderGroup(group: TeamGroup) {
  49. return (
  50. <tr key={group.groupId}>
  51. <td>{group.groupId}</td>
  52. <td style={{ width: '1%' }}>
  53. <a className="btn btn-danger btn-small" onClick={() => this.onRemoveGroup(group)}>
  54. <i className="fa fa-remove" />
  55. </a>
  56. </td>
  57. </tr>
  58. );
  59. }
  60. render() {
  61. const { isAdding, newGroupId } = this.state;
  62. const groups = this.props.groups;
  63. return (
  64. <div>
  65. <div className="page-action-bar">
  66. <h3 className="page-sub-heading">External group sync</h3>
  67. <Tooltip placement="auto" content={headerTooltip}>
  68. <div className="page-sub-heading-icon">
  69. <i className="gicon gicon-question gicon--has-hover" />
  70. </div>
  71. </Tooltip>
  72. <div className="page-action-bar__spacer" />
  73. {groups.length > 0 && (
  74. <button className="btn btn-primary pull-right" onClick={this.onToggleAdding}>
  75. <i className="fa fa-plus" /> Add group
  76. </button>
  77. )}
  78. </div>
  79. <SlideDown in={isAdding}>
  80. <div className="cta-form">
  81. <button className="cta-form__close btn btn-transparent" onClick={this.onToggleAdding}>
  82. <i className="fa fa-close" />
  83. </button>
  84. <h5>Add External Group</h5>
  85. <form className="gf-form-inline" onSubmit={this.onAddGroup}>
  86. <div className="gf-form">
  87. <Input
  88. type="text"
  89. className="gf-form-input width-30"
  90. value={newGroupId}
  91. onChange={this.onNewGroupIdChanged}
  92. placeholder="cn=ops,ou=groups,dc=grafana,dc=org"
  93. />
  94. </div>
  95. <div className="gf-form">
  96. <button className="btn btn-primary gf-form-btn" type="submit" disabled={!this.isNewGroupValid()}>
  97. Add group
  98. </button>
  99. </div>
  100. </form>
  101. </div>
  102. </SlideDown>
  103. {groups.length === 0 && !isAdding && (
  104. <EmptyListCTA
  105. onClick={this.onToggleAdding}
  106. buttonIcon="gicon gicon-team"
  107. title="There are no external groups to sync with"
  108. buttonTitle="Add Group"
  109. proTip={headerTooltip}
  110. proTipLinkTitle="Learn more"
  111. proTipLink="http://docs.grafana.org/auth/enhanced_ldap/"
  112. proTipTarget="_blank"
  113. />
  114. )}
  115. {groups.length > 0 && (
  116. <div className="admin-list-table">
  117. <table className="filter-table filter-table--hover form-inline">
  118. <thead>
  119. <tr>
  120. <th>External Group ID</th>
  121. <th style={{ width: '1%' }} />
  122. </tr>
  123. </thead>
  124. <tbody>{groups.map(group => this.renderGroup(group))}</tbody>
  125. </table>
  126. </div>
  127. )}
  128. </div>
  129. );
  130. }
  131. }
  132. function mapStateToProps(state: any) {
  133. return {
  134. groups: getTeamGroups(state.team),
  135. };
  136. }
  137. const mapDispatchToProps = {
  138. loadTeamGroups,
  139. addTeamGroup,
  140. removeTeamGroup,
  141. };
  142. export default connect(
  143. mapStateToProps,
  144. mapDispatchToProps
  145. )(TeamGroupSync);