issueSearchWithSavedSearches.tsx 2.8 KB

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