import styled from '@emotion/styled';
import debounce from 'lodash/debounce';
import Button from 'sentry/components/button';
import Confirm from 'sentry/components/confirm';
import DropdownAutoComplete from 'sentry/components/dropdownAutoComplete';
import {Item} from 'sentry/components/dropdownAutoComplete/types';
import DropdownButton from 'sentry/components/dropdownButton';
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 {DEFAULT_DEBOUNCE_DURATION} from 'sentry/constants';
import {IconSubtract} from 'sentry/icons';
import {t} from 'sentry/locale';
import space from 'sentry/styles/space';
import {Organization, Team} from 'sentry/types';
import useTeams from 'sentry/utils/useTeams';
type Props = {
/**
* Should button be disabled
*/
disabled: boolean;
/**
* callback when teams are added
*/
onAddTeam: (team: Team) => void;
/**
* Callback when teams are removed
*/
onRemoveTeam: (teamSlug: string) => void;
organization: Organization;
/**
* Teams that are already selected.
*/
selectedTeams: Team[];
/**
* Message to display when the last team is removed
* if empty no confirm will be displayed.
*/
confirmLastTeamRemoveMessage?: string;
/**
* Used to determine whether we should show a loading state while waiting for teams
*/
loadingTeams?: boolean;
/**
* Optional menu header.
*/
menuHeader?: React.ReactElement;
};
function TeamSelect({
disabled,
selectedTeams,
menuHeader,
organization,
onAddTeam,
onRemoveTeam,
confirmLastTeamRemoveMessage,
loadingTeams,
}: Props) {
const {teams, onSearch, fetching} = useTeams();
const handleAddTeam = (option: Item) => {
const team = teams.find(tm => tm.slug === option.value);
if (team) {
onAddTeam(team);
}
};
const renderBody = () => {
if (selectedTeams.length === 0) {
return {t('No Teams assigned')};
}
const confirmMessage =
selectedTeams.length === 1 && confirmLastTeamRemoveMessage
? confirmLastTeamRemoveMessage
: null;
return selectedTeams.map(team => (
onRemoveTeam(slug)}
disabled={disabled}
confirmMessage={confirmMessage}
/>
));
};
// Only show options that aren't selected in the dropdown
const options = teams
.filter(team => !selectedTeams.some(selectedTeam => selectedTeam.slug === team.slug))
.map((team, index) => ({
index,
value: team.slug,
searchKey: team.slug,
label: ,
}));
return (
{t('Team')}
) => void>(
e => onSearch(e.target.value),
DEFAULT_DEBOUNCE_DURATION
)}
onSelect={handleAddTeam}
emptyMessage={t('No teams')}
menuHeader={menuHeader}
disabled={disabled}
alignMenu="right"
>
{({isOpen}) => (
{t('Add Team')}
)}
{loadingTeams ? : renderBody()}
);
}
type TeamRowProps = {
confirmMessage: string | null;
disabled: boolean;
onRemove: Props['onRemoveTeam'];
orgId: string;
team: Team;
};
const TeamRow = ({orgId, team, onRemove, disabled, confirmMessage}: TeamRowProps) => (
onRemove(team.slug)}
disabled={disabled}
>
} disabled={disabled}>
{t('Remove')}
);
const DropdownTeamBadge = styled(TeamBadge)`
font-weight: normal;
font-size: ${p => p.theme.fontSizeMedium};
text-transform: none;
`;
const TeamPanelItem = styled(PanelItem)`
padding: ${space(2)};
align-items: center;
`;
const StyledLink = styled(Link)`
flex: 1;
margin-right: ${space(1)};
`;
export default TeamSelect;