import React, { PureComponent } from 'react'; import { NavModel } from '@grafana/data'; import { DeleteButton, LinkButton, FilterInput, VerticalGroup, HorizontalGroup, Pagination } from '@grafana/ui'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import Page from 'app/core/components/Page/Page'; import { TeamRolePicker } from 'app/core/components/RolePicker/TeamRolePicker'; import { fetchRoleOptions } from 'app/core/components/RolePicker/api'; import { config } from 'app/core/config'; import { getNavModel } from 'app/core/selectors/navModel'; import { contextSrv, User } from 'app/core/services/context_srv'; import { AccessControlAction, Role, StoreState, Team } from 'app/types'; import { connectWithCleanUp } from '../../core/components/connectWithCleanUp'; import { deleteTeam, loadTeams } from './state/actions'; import { setSearchQuery, setTeamsSearchPage } from './state/reducers'; import { getSearchQuery, getTeams, getTeamsCount, getTeamsSearchPage, isPermissionTeamAdmin } from './state/selectors'; const pageLimit = 30; export interface Props { navModel: NavModel; teams: Team[]; searchQuery: string; searchPage: number; teamsCount: number; hasFetched: boolean; loadTeams: typeof loadTeams; deleteTeam: typeof deleteTeam; setSearchQuery: typeof setSearchQuery; setTeamsSearchPage: typeof setTeamsSearchPage; editorsCanAdmin: boolean; signedInUser: User; } export interface State { roleOptions: Role[]; } export class TeamList extends PureComponent { constructor(props: Props) { super(props); this.state = { roleOptions: [] }; } componentDidMount() { this.fetchTeams(); if (contextSrv.licensedAccessControlEnabled() && contextSrv.hasPermission(AccessControlAction.ActionRolesList)) { this.fetchRoleOptions(); } } async fetchTeams() { await this.props.loadTeams(); } async fetchRoleOptions() { const roleOptions = await fetchRoleOptions(); this.setState({ roleOptions }); } deleteTeam = (team: Team) => { this.props.deleteTeam(team.id); }; onSearchQueryChange = (value: string) => { this.props.setSearchQuery(value); }; renderTeam(team: Team) { const { editorsCanAdmin, signedInUser } = this.props; const permission = team.permission; const teamUrl = `org/teams/edit/${team.id}`; const isTeamAdmin = isPermissionTeamAdmin({ permission, editorsCanAdmin, signedInUser }); const canDelete = contextSrv.hasAccessInMetadata(AccessControlAction.ActionTeamsDelete, team, isTeamAdmin); const canReadTeam = contextSrv.hasAccessInMetadata(AccessControlAction.ActionTeamsRead, team, isTeamAdmin); const canSeeTeamRoles = contextSrv.hasAccessInMetadata(AccessControlAction.ActionTeamsRolesList, team, false); const canUpdateTeamRoles = contextSrv.hasAccess(AccessControlAction.ActionTeamsRolesAdd, false) || contextSrv.hasAccess(AccessControlAction.ActionTeamsRolesRemove, false); const displayRolePicker = contextSrv.licensedAccessControlEnabled() && contextSrv.hasPermission(AccessControlAction.ActionTeamsRolesList) && contextSrv.hasPermission(AccessControlAction.ActionRolesList); return ( {canReadTeam ? ( Team avatar ) : ( Team avatar )} {canReadTeam ? {team.name} :
{team.name}
} {canReadTeam ? ( 0 ? undefined : 'Empty email cell'}> {team.email} ) : (
0 ? undefined : 'Empty email cell'}> {team.email}
)} {canReadTeam ? ( {team.memberCount} ) : (
{team.memberCount}
)} {displayRolePicker && ( {canSeeTeamRoles && ( )} )} this.deleteTeam(team)} /> ); } renderEmptyList() { return ( ); } getPaginatedTeams = (teams: Team[]) => { const offset = (this.props.searchPage - 1) * pageLimit; return teams.slice(offset, offset + pageLimit); }; renderTeamList() { const { teams, searchQuery, editorsCanAdmin, searchPage, setTeamsSearchPage } = this.props; const teamAdmin = contextSrv.hasRole('Admin') || (editorsCanAdmin && contextSrv.hasRole('Editor')); const canCreate = contextSrv.hasAccess(AccessControlAction.ActionTeamsCreate, teamAdmin); const displayRolePicker = contextSrv.licensedAccessControlEnabled() && contextSrv.hasPermission(AccessControlAction.ActionTeamsRolesList) && contextSrv.hasPermission(AccessControlAction.ActionRolesList); const newTeamHref = canCreate ? 'org/teams/new' : '#'; const paginatedTeams = this.getPaginatedTeams(teams); const totalPages = Math.ceil(teams.length / pageLimit); return ( <>
New Team
{displayRolePicker && } {paginatedTeams.map((team) => this.renderTeam(team))}
Name Email MembersRoles
); } renderList() { const { teamsCount, hasFetched } = this.props; if (!hasFetched) { return null; } if (teamsCount > 0) { return this.renderTeamList(); } else { return this.renderEmptyList(); } } render() { const { hasFetched, navModel } = this.props; return ( {this.renderList()} ); } } function mapStateToProps(state: StoreState) { return { navModel: getNavModel(state.navIndex, 'teams'), teams: getTeams(state.teams), searchQuery: getSearchQuery(state.teams), searchPage: getTeamsSearchPage(state.teams), teamsCount: getTeamsCount(state.teams), hasFetched: state.teams.hasFetched, editorsCanAdmin: config.editorsCanAdmin, // this makes the feature toggle mockable/controllable from tests, signedInUser: contextSrv.user, // this makes the feature toggle mockable/controllable from tests, }; } const mapDispatchToProps = { loadTeams, deleteTeam, setSearchQuery, setTeamsSearchPage, }; export default connectWithCleanUp(mapStateToProps, mapDispatchToProps, (state) => state.teams)(TeamList);