issueSearchWithSavedSearches.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. {!organization.features.includes('issue-stream-custom-views') && (
  35. <StyledButton onClick={onSavedSearchesToggleClicked}>
  36. {selectedSavedSearch?.name ?? t('Custom Search')}
  37. </StyledButton>
  38. )}
  39. <StyledIssueListSearchBarWithButton
  40. searchSource="main_search"
  41. organization={organization}
  42. query={query || ''}
  43. onSearch={onSearch}
  44. excludedTags={['environment']}
  45. placeholder={t('Search for events, users, tags, and more')}
  46. roundCorners={organization.features.includes('issue-stream-custom-views')}
  47. />
  48. </SearchBarWithButtonContainer>
  49. );
  50. }
  51. const SearchBarWithButtonContainer = styled('div')`
  52. flex: 1;
  53. display: flex;
  54. align-items: stretch;
  55. width: 100%;
  56. @media (min-width: ${p => p.theme.breakpoints.small}) {
  57. flex-basis: 35rem;
  58. }
  59. `;
  60. const StyledButton = styled(Button)`
  61. /* Hide this button on small screens */
  62. display: none;
  63. @media (min-width: ${p => p.theme.breakpoints.small}) {
  64. display: flex;
  65. align-items: center;
  66. height: 100%;
  67. max-width: 180px;
  68. text-align: left;
  69. border-top-right-radius: 0;
  70. border-bottom-right-radius: 0;
  71. border-right: none;
  72. ${ButtonLabel} {
  73. height: auto;
  74. display: block;
  75. ${p => p.theme.overflowEllipsis};
  76. }
  77. }
  78. `;
  79. const StyledIssueListSearchBarWithButton = styled(IssueListSearchBar)<{
  80. roundCorners: boolean;
  81. }>`
  82. flex: 1;
  83. min-width: 0;
  84. ${p =>
  85. !p.roundCorners &&
  86. `
  87. @media (min-width: ${p.theme.breakpoints.small}) {
  88. border-top-left-radius: 0;
  89. border-bottom-left-radius: 0;
  90. }
  91. `}
  92. `;