feedbackListPage.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import {Fragment} from 'react';
  2. import {RouteComponentProps} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import ErrorBoundary from 'sentry/components/errorBoundary';
  5. import FeedbackFilters from 'sentry/components/feedback/feedbackFilters';
  6. import FeedbackItemLoader from 'sentry/components/feedback/feedbackItem/feedbackItemLoader';
  7. import FeedbackSearch from 'sentry/components/feedback/feedbackSearch';
  8. import FeedbackSetupPanel from 'sentry/components/feedback/feedbackSetupPanel';
  9. import FeedbackList from 'sentry/components/feedback/list/feedbackList';
  10. import OldFeedbackButton from 'sentry/components/feedback/oldFeedbackButton';
  11. import useCurrentFeedbackId from 'sentry/components/feedback/useCurrentFeedbackId';
  12. import {FeedbackQueryKeys} from 'sentry/components/feedback/useFeedbackQueryKeys';
  13. import useHaveSelectedProjectsSetupFeedback from 'sentry/components/feedback/useHaveSelectedProjectsSetupFeedback';
  14. import FullViewport from 'sentry/components/layouts/fullViewport';
  15. import * as Layout from 'sentry/components/layouts/thirds';
  16. import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
  17. import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip';
  18. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  19. import {t} from 'sentry/locale';
  20. import {space} from 'sentry/styles/space';
  21. import useOrganization from 'sentry/utils/useOrganization';
  22. import FluidHeight from 'sentry/views/replays/detail/layout/fluidHeight';
  23. interface Props extends RouteComponentProps<{}, {}, {}> {}
  24. export default function FeedbackListPage({}: Props) {
  25. const organization = useOrganization();
  26. const {hasSetupOneFeedback} = useHaveSelectedProjectsSetupFeedback();
  27. const feedbackSlug = useCurrentFeedbackId();
  28. const hasSlug = Boolean(feedbackSlug);
  29. return (
  30. <SentryDocumentTitle title={t('User Feedback')} orgSlug={organization.slug}>
  31. <FullViewport>
  32. <FeedbackQueryKeys organization={organization}>
  33. <Layout.Header>
  34. <Layout.HeaderContent>
  35. <Layout.Title>
  36. {t('User Feedback')}
  37. <PageHeadingQuestionTooltip
  38. title={t(
  39. 'The User Feedback Widget allows users to submit feedback quickly and easily any time they encounter something that isn’t working as expected.'
  40. )}
  41. docsUrl="https://docs.sentry.io/product/user-feedback/"
  42. />
  43. </Layout.Title>
  44. </Layout.HeaderContent>
  45. <Layout.HeaderActions>
  46. <OldFeedbackButton />
  47. </Layout.HeaderActions>
  48. </Layout.Header>
  49. <PageFiltersContainer>
  50. <ErrorBoundary>
  51. <LayoutGrid>
  52. <FeedbackFilters style={{gridArea: 'filters'}} />
  53. {hasSetupOneFeedback || hasSlug ? (
  54. <Fragment>
  55. <Container style={{gridArea: 'list'}}>
  56. <FeedbackList />
  57. </Container>
  58. <FeedbackSearch style={{gridArea: 'search'}} />
  59. <Container style={{gridArea: 'details'}}>
  60. <FeedbackItemLoader />
  61. </Container>
  62. </Fragment>
  63. ) : (
  64. <SetupContainer>
  65. <FeedbackSetupPanel />
  66. </SetupContainer>
  67. )}
  68. </LayoutGrid>
  69. </ErrorBoundary>
  70. </PageFiltersContainer>
  71. </FeedbackQueryKeys>
  72. </FullViewport>
  73. </SentryDocumentTitle>
  74. );
  75. }
  76. const LayoutGrid = styled('div')`
  77. background: ${p => p.theme.background};
  78. overflow: hidden;
  79. flex-grow: 1;
  80. display: grid;
  81. gap: ${space(2)};
  82. place-items: stretch;
  83. grid-template-rows: max-content 1fr;
  84. grid-template-areas:
  85. 'filters search'
  86. 'list details';
  87. @media (max-width: ${p => p.theme.breakpoints.medium}) {
  88. padding: ${space(2)};
  89. grid-template-columns: 1fr;
  90. grid-template-areas:
  91. 'filters'
  92. 'search'
  93. 'list'
  94. 'details';
  95. }
  96. @media (min-width: ${p => p.theme.breakpoints.medium}) {
  97. padding: ${space(2)};
  98. grid-template-columns: minmax(1fr, 195px) 1fr;
  99. }
  100. @media (min-width: ${p => p.theme.breakpoints.large}) {
  101. padding: ${space(2)} ${space(4)} ${space(2)} ${space(4)};
  102. grid-template-columns: 390px 1fr;
  103. }
  104. @media (min-width: ${p => p.theme.breakpoints.large}) {
  105. grid-template-columns: minmax(390px, 1fr) 2fr;
  106. }
  107. `;
  108. const Container = styled(FluidHeight)`
  109. border: 1px solid ${p => p.theme.border};
  110. border-radius: ${p => p.theme.borderRadius};
  111. `;
  112. const SetupContainer = styled('div')`
  113. overflow: hidden;
  114. grid-column: 1 / -1;
  115. `;