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} > ); 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;