filtersBar.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import type {Location} from 'history';
  4. import {Button} from 'sentry/components/button';
  5. import ButtonBar from 'sentry/components/buttonBar';
  6. import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
  7. import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter';
  8. import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
  9. import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
  10. import {t} from 'sentry/locale';
  11. import {space} from 'sentry/styles/space';
  12. import {defined} from 'sentry/utils';
  13. import {ToggleOnDemand} from 'sentry/utils/performance/contexts/onDemandControl';
  14. import {decodeList} from 'sentry/utils/queryString';
  15. import {ReleasesProvider} from 'sentry/utils/releases/releasesProvider';
  16. import useOrganization from 'sentry/utils/useOrganization';
  17. import usePageFilters from 'sentry/utils/usePageFilters';
  18. import ReleasesSelectControl from './releasesSelectControl';
  19. import type {DashboardFilters} from './types';
  20. import {DashboardFilterKeys} from './types';
  21. type FiltersBarProps = {
  22. filters: DashboardFilters;
  23. hasUnsavedChanges: boolean;
  24. isEditingDashboard: boolean;
  25. isPreview: boolean;
  26. location: Location;
  27. onDashboardFilterChange: (activeFilters: DashboardFilters) => void;
  28. onCancel?: () => void;
  29. onSave?: () => void;
  30. };
  31. export default function FiltersBar({
  32. filters,
  33. hasUnsavedChanges,
  34. isEditingDashboard,
  35. isPreview,
  36. location,
  37. onCancel,
  38. onDashboardFilterChange,
  39. onSave,
  40. }: FiltersBarProps) {
  41. const {selection} = usePageFilters();
  42. const organization = useOrganization();
  43. const selectedReleases =
  44. (defined(location.query?.[DashboardFilterKeys.RELEASE])
  45. ? decodeList(location.query[DashboardFilterKeys.RELEASE])
  46. : filters?.[DashboardFilterKeys.RELEASE]) ?? [];
  47. return (
  48. <Wrapper>
  49. <PageFilterBar condensed>
  50. <ProjectPageFilter disabled={isEditingDashboard} />
  51. <EnvironmentPageFilter disabled={isEditingDashboard} />
  52. <DatePageFilter disabled={isEditingDashboard} />
  53. </PageFilterBar>
  54. <Fragment>
  55. <FilterButtons>
  56. <ReleasesProvider organization={organization} selection={selection}>
  57. <ReleasesSelectControl
  58. handleChangeFilter={onDashboardFilterChange}
  59. selectedReleases={selectedReleases}
  60. isDisabled={isEditingDashboard}
  61. />
  62. </ReleasesProvider>
  63. </FilterButtons>
  64. {hasUnsavedChanges && !isEditingDashboard && !isPreview && (
  65. <FilterButtons>
  66. <Button priority="primary" onClick={onSave}>
  67. {t('Save')}
  68. </Button>
  69. <Button onClick={onCancel}>{t('Cancel')}</Button>
  70. </FilterButtons>
  71. )}
  72. </Fragment>
  73. <ToggleOnDemand />
  74. </Wrapper>
  75. );
  76. }
  77. const Wrapper = styled('div')`
  78. display: flex;
  79. flex-direction: row;
  80. gap: ${space(1.5)};
  81. margin-bottom: ${space(2)};
  82. @media (max-width: ${p => p.theme.breakpoints.small}) {
  83. display: grid;
  84. grid-auto-flow: row;
  85. }
  86. `;
  87. const FilterButtons = styled(ButtonBar)`
  88. display: grid;
  89. gap: ${space(1.5)};
  90. @media (min-width: ${p => p.theme.breakpoints.small}) {
  91. display: flex;
  92. align-items: flex-start;
  93. gap: ${space(1.5)};
  94. }
  95. `;