mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Teams page replace mobx (#13219)
* creating types, actions, reducer * load teams and store in redux * delete team * set search query action and tests * Teampages page * team members, bug in fetching team * flattened team state, tests for TeamMembers * test for team member selector * team settings * actions for group sync * tests for team groups * removed comment * remove old stores * fix: formating of datasource.go * fix: minor changes to imports * adding debounce and fixing issue in teamlist * refactoring: moving types to their own files
This commit is contained in:
committed by
Torkel Ödegaard
parent
1ce9001141
commit
9f73f13091
164
public/app/features/teams/TeamGroupSync.tsx
Normal file
164
public/app/features/teams/TeamGroupSync.tsx
Normal file
@@ -0,0 +1,164 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import SlideDown from 'app/core/components/Animations/SlideDown';
|
||||
import Tooltip from 'app/core/components/Tooltip/Tooltip';
|
||||
import { TeamGroup } from '../../types';
|
||||
import { addTeamGroup, loadTeamGroups, removeTeamGroup } from './state/actions';
|
||||
import { getTeamGroups } from './state/selectors';
|
||||
|
||||
export interface Props {
|
||||
groups: TeamGroup[];
|
||||
loadTeamGroups: typeof loadTeamGroups;
|
||||
addTeamGroup: typeof addTeamGroup;
|
||||
removeTeamGroup: typeof removeTeamGroup;
|
||||
}
|
||||
|
||||
interface State {
|
||||
isAdding: boolean;
|
||||
newGroupId?: string;
|
||||
}
|
||||
|
||||
const headerTooltip = `Sync LDAP or OAuth groups with your Grafana teams.`;
|
||||
|
||||
export class TeamGroupSync extends PureComponent<Props, State> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { isAdding: false, newGroupId: '' };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTeamGroups();
|
||||
}
|
||||
|
||||
async fetchTeamGroups() {
|
||||
await this.props.loadTeamGroups();
|
||||
}
|
||||
|
||||
onToggleAdding = () => {
|
||||
this.setState({ isAdding: !this.state.isAdding });
|
||||
};
|
||||
|
||||
onNewGroupIdChanged = event => {
|
||||
this.setState({ newGroupId: event.target.value });
|
||||
};
|
||||
|
||||
onAddGroup = event => {
|
||||
event.preventDefault();
|
||||
this.props.addTeamGroup(this.state.newGroupId);
|
||||
this.setState({ isAdding: false, newGroupId: '' });
|
||||
};
|
||||
|
||||
onRemoveGroup = (group: TeamGroup) => {
|
||||
this.props.removeTeamGroup(group.groupId);
|
||||
};
|
||||
|
||||
isNewGroupValid() {
|
||||
return this.state.newGroupId.length > 1;
|
||||
}
|
||||
|
||||
renderGroup(group: TeamGroup) {
|
||||
return (
|
||||
<tr key={group.groupId}>
|
||||
<td>{group.groupId}</td>
|
||||
<td style={{ width: '1%' }}>
|
||||
<a className="btn btn-danger btn-mini" onClick={() => this.onRemoveGroup(group)}>
|
||||
<i className="fa fa-remove" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isAdding, newGroupId } = this.state;
|
||||
const groups = this.props.groups;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="page-action-bar">
|
||||
<h3 className="page-sub-heading">External group sync</h3>
|
||||
<Tooltip className="page-sub-heading-icon" placement="auto" content={headerTooltip}>
|
||||
<i className="gicon gicon-question gicon--has-hover" />
|
||||
</Tooltip>
|
||||
<div className="page-action-bar__spacer" />
|
||||
{groups.length > 0 && (
|
||||
<button className="btn btn-success pull-right" onClick={this.onToggleAdding}>
|
||||
<i className="fa fa-plus" /> Add group
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<SlideDown in={isAdding}>
|
||||
<div className="cta-form">
|
||||
<button className="cta-form__close btn btn-transparent" onClick={this.onToggleAdding}>
|
||||
<i className="fa fa-close" />
|
||||
</button>
|
||||
<h5>Add External Group</h5>
|
||||
<form className="gf-form-inline" onSubmit={this.onAddGroup}>
|
||||
<div className="gf-form">
|
||||
<input
|
||||
type="text"
|
||||
className="gf-form-input width-30"
|
||||
value={newGroupId}
|
||||
onChange={this.onNewGroupIdChanged}
|
||||
placeholder="cn=ops,ou=groups,dc=grafana,dc=org"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="gf-form">
|
||||
<button className="btn btn-success gf-form-btn" type="submit" disabled={!this.isNewGroupValid()}>
|
||||
Add group
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</SlideDown>
|
||||
|
||||
{groups.length === 0 &&
|
||||
!isAdding && (
|
||||
<div className="empty-list-cta">
|
||||
<div className="empty-list-cta__title">There are no external groups to sync with</div>
|
||||
<button onClick={this.onToggleAdding} className="empty-list-cta__button btn btn-xlarge btn-success">
|
||||
<i className="gicon gicon-add-team" />
|
||||
Add Group
|
||||
</button>
|
||||
<div className="empty-list-cta__pro-tip">
|
||||
<i className="fa fa-rocket" /> {headerTooltip}
|
||||
<a className="text-link empty-list-cta__pro-tip-link" href="asd" target="_blank">
|
||||
Learn more
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{groups.length > 0 && (
|
||||
<div className="admin-list-table">
|
||||
<table className="filter-table filter-table--hover form-inline">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>External Group ID</th>
|
||||
<th style={{ width: '1%' }} />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{groups.map(group => this.renderGroup(group))}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
groups: getTeamGroups(state.team),
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
loadTeamGroups,
|
||||
addTeamGroup,
|
||||
removeTeamGroup,
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TeamGroupSync);
|
||||
Reference in New Issue
Block a user