import {Fragment, useCallback, useMemo} from 'react';
import styled from '@emotion/styled';
import Access from 'sentry/components/acl/access';
import Badge from 'sentry/components/badge';
import Button from 'sentry/components/button';
import Confirm from 'sentry/components/confirm';
import DropdownButton from 'sentry/components/dropdownButton';
import CompactSelect from 'sentry/components/forms/compactSelect';
import {ControlProps} from 'sentry/components/forms/selectControl';
import QueryCount from 'sentry/components/queryCount';
import {IconDelete} from 'sentry/icons';
import {t} from 'sentry/locale';
import space from 'sentry/styles/space';
import {Organization, SavedSearch} from 'sentry/types';
import {defined} from 'sentry/utils';
import {getSortLabel} from './utils';
type Props = {
onSavedSearchDelete: (savedSearch: SavedSearch) => void;
onSavedSearchSelect: (savedSearch: SavedSearch) => void;
organization: Organization;
savedSearchList: SavedSearch[];
sort: string;
isActive?: boolean;
query?: string;
queryCount?: number;
};
function SavedSearchTab({
isActive,
organization,
savedSearchList,
onSavedSearchSelect,
onSavedSearchDelete,
query,
queryCount,
sort,
}: Props) {
const savedSearch = savedSearchList.find(
search => search.query === query && search.sort === sort
);
const savedSearchValue = savedSearch
? savedSearch.isGlobal
? `global-search-${savedSearch.id}`
: `saved-search-${savedSearch.id}`
: '';
const options: ControlProps['options'] = useMemo(() => {
const savedSearches = savedSearchList.filter(search => !search.isGlobal);
const globalSearches = savedSearchList.filter(
search => search.isGlobal && !search.isPinned && search.query !== 'is:unresolved'
);
function getSearchOption(search, keyPrefix) {
return {
value: `${keyPrefix}-${search.id}`,
label: search.name,
details: (
{search.query}
{` \u2022 ${t('Sort:')} ${getSortLabel(search.sort)}`}
),
tooltip: (
{`${search.name} \u2022 `}
{search.query}
{` \u2022 `}
{t('Sort: ')}
{getSortLabel(search.sort)}
),
tooltipOptions: {delay: 1000},
...(!search.isPinned &&
!search.isGlobal && {
trailingItems: (
onSavedSearchDelete(search)}
message={t('Are you sure you want to delete this saved search?')}
stopPropagation
>
}
aria-label={t('delete')}
size="zero"
/>
),
}),
trailingItemsSpanFullHeight: true,
};
}
const searchOptions: ControlProps['options'] = [];
if (savedSearches.length > 0) {
searchOptions.push({
value: 'saved-searches',
label: t('Saved Searches'),
options: savedSearches.map(search => getSearchOption(search, 'saved-search')),
});
}
if (globalSearches.length > 0) {
searchOptions.push({
value: 'global-searches',
label: t('Recommended Searches'),
options: globalSearches.map(search => getSearchOption(search, 'global-search')),
});
}
return searchOptions;
}, []);
const trigger = ({props, ref}) => (
{isActive ? (
{savedSearch ? savedSearch.name : t('Custom Search')}
{defined(queryCount) && queryCount > 0 && (
)}
) : (
t('Saved Searches')
)}
);
const onChange = useCallback(
option => {
const searchObj = savedSearchList.find(s =>
s.isGlobal
? `global-search-${s.id}` === option.value
: `saved-search-${s.id}` === option.value
);
searchObj && onSavedSearchSelect(searchObj);
},
[savedSearchList, onSavedSearchSelect]
);
return (
);
}
export default SavedSearchTab;
const StyledCompactSelect = styled(CompactSelect)<{isActive?: boolean}>`
&& {
position: static;
}
border-bottom-width: 4px;
border-bottom-style: solid;
border-bottom-color: ${p => (p.isActive ? p.theme.active : 'transparent')};
`;
const StyledDropdownTrigger = styled(DropdownButton)<{isActive?: boolean}>`
display: flex;
height: calc(1.25rem - 2px);
align-items: center;
color: ${p => (p.isActive ? p.theme.textColor : p.theme.subText)};
box-sizing: content-box;
padding: ${space(1)} 0;
&:hover {
color: ${p => p.theme.textColor};
}
`;
const Details = styled('span')`
font-family: ${p => p.theme.text.familyMono};
font-size: ${p => p.theme.fontSizeExtraSmall};
max-width: 16rem;
${p => p.theme.overflowEllipsis}
`;
const TooltipSearchQuery = styled('span')`
color: ${p => p.theme.subText};
font-weight: normal;
font-family: ${p => p.theme.text.familyMono};
`;
const DeleteButton = styled(Button)`
color: ${p => p.theme.subText};
flex-shrink: 0;
padding: ${space(1)} 0;
:hover {
color: ${p => p.theme.error};
}
`;