feedbackListHeader.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import styled from '@emotion/styled';
  2. import Button from 'sentry/components/actions/button';
  3. import Checkbox from 'sentry/components/checkbox';
  4. import {DropdownMenu} from 'sentry/components/dropdownMenu';
  5. import ErrorBoundary from 'sentry/components/errorBoundary';
  6. import decodeMailbox from 'sentry/components/feedback/decodeMailbox';
  7. import MailboxPicker from 'sentry/components/feedback/list/mailboxPicker';
  8. import PanelItem from 'sentry/components/panels/panelItem';
  9. import {Flex} from 'sentry/components/profiling/flex';
  10. import {IconEllipsis} from 'sentry/icons/iconEllipsis';
  11. import {t, tct} from 'sentry/locale';
  12. import {space} from 'sentry/styles/space';
  13. import useLocationQuery from 'sentry/utils/url/useLocationQuery';
  14. import useUrlParams from 'sentry/utils/useUrlParams';
  15. interface Props {
  16. checked: string[];
  17. toggleChecked: (id: string) => void;
  18. }
  19. export default function FeedbackListHeader({checked, toggleChecked}: Props) {
  20. const {mailbox} = useLocationQuery({
  21. fields: {
  22. mailbox: decodeMailbox,
  23. },
  24. });
  25. const {setParamValue: setMailbox} = useUrlParams('mailbox');
  26. return (
  27. <HeaderPanelItem>
  28. <Checkbox
  29. checked={checked.length ? 'indeterminate' : false}
  30. onChange={() => {
  31. checked.length ? checked.forEach(c => toggleChecked(c)) : null;
  32. }}
  33. />
  34. {checked.length ? (
  35. <HasSelection checked={checked} mailbox={mailbox} />
  36. ) : (
  37. <MailboxPicker value={mailbox} onChange={setMailbox} />
  38. )}
  39. </HeaderPanelItem>
  40. );
  41. }
  42. function HasSelection({checked, mailbox}) {
  43. return (
  44. <Flex gap={space(1)} align="center" justify="space-between" style={{flexGrow: 1}}>
  45. <span>
  46. <strong>{tct('[count] Selected', {count: checked.length})}</strong>
  47. </span>
  48. <Flex gap={space(1)} justify="flex-end">
  49. <ErrorBoundary mini>
  50. <Button>{mailbox === 'resolved' ? t('Unresolve') : t('Resolve')}</Button>
  51. </ErrorBoundary>
  52. <ErrorBoundary mini>
  53. <DropdownMenu
  54. position="bottom-end"
  55. triggerProps={{
  56. 'aria-label': t('Read Menu'),
  57. icon: <IconEllipsis size="xs" />,
  58. showChevron: false,
  59. size: 'xs',
  60. }}
  61. items={[
  62. {
  63. key: 'mark read',
  64. label: t('Mark Read'),
  65. onAction: () => {},
  66. },
  67. {
  68. key: 'mark unread',
  69. label: t('Mark Unread'),
  70. onAction: () => {},
  71. },
  72. ]}
  73. />
  74. </ErrorBoundary>
  75. </Flex>
  76. </Flex>
  77. );
  78. }
  79. const HeaderPanelItem = styled(PanelItem)`
  80. display: flex;
  81. padding: ${space(1)} ${space(2)} ${space(1)} ${space(2)};
  82. gap: ${space(1)};
  83. align-items: center;
  84. `;