screenshotsModal.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import {Fragment, useState} from 'react';
  2. import {css} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import type {ModalRenderProps} from 'sentry/actionCreators/modal';
  5. import ScreenshotPagination from 'sentry/components/events/eventTagsAndScreenshot/screenshot/screenshotPagination';
  6. import FeedbackScreenshot from 'sentry/components/feedback/feedbackItem/feedbackScreenshot';
  7. import PanelHeader from 'sentry/components/panels/panelHeader';
  8. import {tct} from 'sentry/locale';
  9. import type {EventAttachment, Organization, Project} from 'sentry/types';
  10. type Props = ModalRenderProps & {
  11. initialIndex: number;
  12. organization: Organization;
  13. projectSlug: Project['slug'];
  14. screenshots: EventAttachment[];
  15. };
  16. export default function ScreenshotsModal({
  17. Body,
  18. Header,
  19. initialIndex,
  20. organization,
  21. projectSlug,
  22. screenshots,
  23. }: Props) {
  24. // Selected index can be any integer, positive or negative
  25. const [selectedIndex, setSelectedIndex] = useState(initialIndex);
  26. // Current index maps the selectedIndex into the range for which we have screenshots
  27. const currentIndex = selectedIndex % screenshots.length;
  28. // Cannot be undefined because of the modulo above:
  29. const currentScreenshot = screenshots.at(currentIndex)!;
  30. return (
  31. <Fragment>
  32. <Header closeButton>
  33. {screenshots.length > 1 && (
  34. <PaginationWrapper lightText>
  35. <StyledScreenshotPagination
  36. nextDisabled={false}
  37. previousDisabled={false}
  38. onNext={() => {
  39. setSelectedIndex(prev => prev + 1);
  40. }}
  41. onPrevious={() => {
  42. setSelectedIndex(prev => prev - 1);
  43. }}
  44. headerText={tct('[currentScreenshotIndex] of [totalScreenshotCount]', {
  45. currentScreenshotIndex: currentIndex + 1,
  46. totalScreenshotCount: screenshots.length,
  47. })}
  48. />
  49. </PaginationWrapper>
  50. )}
  51. </Header>
  52. <Body>
  53. <FeedbackScreenshot
  54. organization={organization}
  55. screenshot={currentScreenshot}
  56. projectSlug={projectSlug}
  57. />
  58. </Body>
  59. </Fragment>
  60. );
  61. }
  62. const PaginationWrapper = styled(PanelHeader)`
  63. margin: 0;
  64. padding: 0;
  65. border: 0;
  66. display: flex;
  67. align-items: center;
  68. justify-content: space-between;
  69. text-transform: none;
  70. background: ${p => p.theme.background};
  71. `;
  72. const StyledScreenshotPagination = styled(ScreenshotPagination)`
  73. flex-grow: 1;
  74. `;
  75. export const modalCss = css`
  76. height: 100%;
  77. width: 100%;
  78. margin-top: 0 !important;
  79. `;