issueSearchWithSavedSearches.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import styled from '@emotion/styled';
  2. import {Button, ButtonLabel} from 'sentry/components/button';
  3. import {t} from 'sentry/locale';
  4. import {trackAnalytics} from 'sentry/utils/analytics';
  5. import useOrganization from 'sentry/utils/useOrganization';
  6. import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';
  7. import {SAVED_SEARCHES_SIDEBAR_OPEN_LOCALSTORAGE_KEY} from 'sentry/views/issueList/utils';
  8. import {useSelectedSavedSearch} from 'sentry/views/issueList/utils/useSelectedSavedSearch';
  9. import IssueListSearchBar from './searchBar';
  10. type IssueSearchWithSavedSearchesProps = {
  11. onSearch: (query: string) => void;
  12. query: string;
  13. };
  14. export function IssueSearchWithSavedSearches({
  15. query,
  16. onSearch,
  17. }: IssueSearchWithSavedSearchesProps) {
  18. const organization = useOrganization();
  19. const selectedSavedSearch = useSelectedSavedSearch();
  20. const [isSavedSearchesOpen, setIsSavedSearchesOpen] = useSyncedLocalStorageState(
  21. SAVED_SEARCHES_SIDEBAR_OPEN_LOCALSTORAGE_KEY,
  22. false
  23. );
  24. function onSavedSearchesToggleClicked() {
  25. const newOpenState = !isSavedSearchesOpen;
  26. trackAnalytics('search.saved_search_sidebar_toggle_clicked', {
  27. organization,
  28. open: newOpenState,
  29. });
  30. setIsSavedSearchesOpen(newOpenState);
  31. }
  32. return (
  33. <SearchBarWithButtonContainer>
  34. <StyledButton onClick={onSavedSearchesToggleClicked}>
  35. {selectedSavedSearch?.name ?? t('Custom Search')}
  36. </StyledButton>
  37. <StyledIssueListSearchBarWithButton
  38. searchSource="main_search"
  39. organization={organization}
  40. query={query || ''}
  41. onSearch={onSearch}
  42. excludedTags={['environment']}
  43. placeholder={t('Search for events, users, tags, and more')}
  44. />
  45. </SearchBarWithButtonContainer>
  46. );
  47. }
  48. const SearchBarWithButtonContainer = styled('div')`
  49. flex: 1;
  50. display: flex;
  51. align-items: stretch;
  52. width: 100%;
  53. @media (min-width: ${p => p.theme.breakpoints.small}) {
  54. flex-basis: 35rem;
  55. }
  56. `;
  57. const StyledButton = styled(Button)`
  58. /* Hide this button on small screens */
  59. display: none;
  60. @media (min-width: ${p => p.theme.breakpoints.small}) {
  61. display: flex;
  62. align-items: center;
  63. height: 100%;
  64. max-width: 180px;
  65. text-align: left;
  66. border-top-right-radius: 0;
  67. border-bottom-right-radius: 0;
  68. border-right: none;
  69. ${ButtonLabel} {
  70. height: auto;
  71. display: block;
  72. ${p => p.theme.overflowEllipsis};
  73. }
  74. }
  75. `;
  76. const StyledIssueListSearchBarWithButton = styled(IssueListSearchBar)`
  77. flex: 1;
  78. min-width: 0;
  79. @media (min-width: ${p => p.theme.breakpoints.small}) {
  80. border-top-left-radius: 0;
  81. border-bottom-left-radius: 0;
  82. }
  83. `;