import React from 'react';
import styled from '@emotion/styled';
import startCase from 'lodash/startCase';
import {Button} from 'sentry/components/button';
import EmptyMessage from 'sentry/components/emptyMessage';
import {TeamBadge} from 'sentry/components/idBadge/teamBadge';
import Link from 'sentry/components/links/link';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {Panel, PanelBody, PanelHeader, PanelItem} from 'sentry/components/panels';
import TeamRoleSelect from 'sentry/components/teamRoleSelect';
import {IconSubtract} from 'sentry/icons';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import {Member, Organization, Team} from 'sentry/types';
import {getEffectiveOrgRole} from 'sentry/utils/orgRole';
import {useTeams} from 'sentry/utils/useTeams';
import {RoleOverwritePanelAlert} from 'sentry/views/settings/organizationTeams/roleOverwriteWarning';
import {getButtonHelpText} from 'sentry/views/settings/organizationTeams/utils';
import {DropdownAddTeam, TeamSelectProps} from './utils';
type Props = TeamSelectProps & {
/**
* Member that this component is acting upon
*/
member: Member;
/**
* Used when showing Teams for a Member
*/
onChangeTeamRole: (teamSlug: string, teamRole: string) => void;
/**
* Used when showing Teams for a Member
*/
selectedOrgRole: Member['orgRole'];
/**
* Used when showing Teams for a Member
*/
selectedTeamRoles: Member['teamRoles'];
};
function TeamSelect({
disabled,
loadingTeams,
member,
selectedOrgRole,
selectedTeamRoles,
organization,
onAddTeam,
onRemoveTeam,
onCreateTeam,
onChangeTeamRole,
}: Props) {
const {teams, onSearch, fetching: isLoadingTeams} = useTeams();
const {orgRoleList, teamRoleList} = organization;
const selectedTeamSlugs = new Set(selectedTeamRoles.map(tm => tm.teamSlug));
const selectedTeams = teams.filter(tm => selectedTeamSlugs.has(tm.slug));
// Determine if adding a team changes the minimum team-role
// Get org-roles from team membership, if any
const groupOrgRoles = selectedTeams
.filter(team => team.orgRole)
.map(team => team.orgRole as string);
if (selectedOrgRole) {
groupOrgRoles.push(selectedOrgRole);
}
// Sort them and to get the highest priority role
// Highest priority role may change minimum team role
const effectiveOrgRole = getEffectiveOrgRole(groupOrgRoles, orgRoleList);
const renderBody = () => {
if (selectedTeams.length === 0) {
return {t('No Teams assigned')};
}
return (
{organization.features.includes('team-roles') && effectiveOrgRole && (
)}
{selectedTeams.map(team => (
onRemoveTeam(slug)}
/>
))}
);
};
return (
{t('Team')}
tm.slug)}
teams={teams}
/>
{loadingTeams ? : renderBody()}
);
}
function TeamRow({
disabled,
organization,
team,
member,
onRemoveTeam,
onChangeTeamRole,
}: {
disabled: boolean;
member: Member;
onChangeTeamRole: Props['onChangeTeamRole'];
onRemoveTeam: Props['onRemoveTeam'];
organization: Organization;
team: Team;
}) {
const hasOrgAdmin = organization.access.includes('org:admin');
const isIdpProvisioned = team.flags['idp:provisioned'];
const isPermissionGroup = team.orgRole !== null && !hasOrgAdmin;
const isRemoveDisabled = disabled || isIdpProvisioned || isPermissionGroup;
const buttonHelpText = getButtonHelpText(isIdpProvisioned, isPermissionGroup);
const orgRoleFromTeam = team.orgRole ? `${startCase(team.orgRole)} Team` : null;
return (
{orgRoleFromTeam}
{organization.features.includes('team-roles') && (
onChangeTeamRole(team.slug, newRole)}
/>
)}
}
title={buttonHelpText}
disabled={isRemoveDisabled}
onClick={() => onRemoveTeam(team.slug)}
>
{t('Remove')}
);
}
const TeamPanelItem = styled(PanelItem)`
padding: ${space(2)};
align-items: center;
justify-content: space-between;
`;
const TeamPanelItemLeft = styled('div')`
flex-grow: 4;
`;
const TeamOrgRole = styled('div')`
min-width: 90px;
flex-grow: 1;
display: flex;
justify-content: center;
`;
const RoleSelectWrapper = styled('div')`
min-width: 200px;
margin-right: ${space(2)};
`;
export default TeamSelect;