Browse Source

ref(feedback): Refactor feedback layout and some analytics (#61206)

There's a new tooltip on the Feedback title:
<img width="515" alt="SCR-20231205-oaxs"
src="https://github.com/getsentry/sentry/assets/187460/4d320350-7f45-449b-ad69-6d69ec332faa">
Ryan Albrecht 1 year ago
parent
commit
cd6a1d02d0

+ 18 - 18
static/app/components/feedback/feedbackSetupPanel.tsx

@@ -19,23 +19,8 @@ export default function FeedbackSetupPanel() {
     });
   }, [organization]);
 
-  const docsButton = (
-    <LinkButton
-      external
-      href="https://docs.sentry.io/product/user-feedback/setup/"
-      priority="primary"
-      onClick={() => {
-        trackAnalytics('feedback.index-setup-button-clicked', {
-          organization,
-        });
-      }}
-    >
-      {t('Set Up Now')}
-    </LinkButton>
-  );
-
   return (
-    <Panel>
+    <NoMarginPanel>
       <Container>
         <IlloBox>
           <img src={feedbackOnboardingImg} />
@@ -48,14 +33,29 @@ export default function FeedbackSetupPanel() {
                 'Allow your users to create bug reports so they can let you know about these sneaky issues right away. Every report will automatically include related replays, tags, and errors, making fixing the issue dead simple.'
               )}
             </p>
-            {docsButton}
+            <LinkButton
+              external
+              href="https://docs.sentry.io/product/user-feedback/setup/"
+              priority="primary"
+              analyticsEventName="Clicked Feedback Onboarding Setup Button"
+              analyticsEventKey="feedback.index-setup-button-clicked"
+              analyticsParams={{surface: 'setup-panel'}}
+            >
+              {t('Set Up Now')}
+            </LinkButton>
           </Fragment>
         </StyledBox>
       </Container>
-    </Panel>
+    </NoMarginPanel>
   );
 }
 
+const NoMarginPanel = styled(Panel)`
+  max-height: 100%;
+  overflow: scroll;
+  margin: 0;
+`;
+
 const Container = styled('div')`
   padding: ${space(3)};
   position: relative;

+ 29 - 0
static/app/components/feedback/oldFeedbackButton.tsx

@@ -0,0 +1,29 @@
+import {LinkButton} from 'sentry/components/button';
+import {t} from 'sentry/locale';
+import {useLocation} from 'sentry/utils/useLocation';
+import useOrganization from 'sentry/utils/useOrganization';
+import {normalizeUrl} from 'sentry/utils/withDomainRequired';
+
+export default function OldFeedbackButton() {
+  const location = useLocation();
+  const organization = useOrganization();
+
+  return (
+    <LinkButton
+      analyticsEventName="Clicked Go To Old User Feedback Button"
+      analyticsEventKey="feedback.index-old-ui-clicked"
+      size="sm"
+      priority="default"
+      to={{
+        pathname: normalizeUrl(`/organizations/${organization.slug}/user-feedback/`),
+        query: {
+          ...location.query,
+          query: undefined,
+          cursor: undefined,
+        },
+      }}
+    >
+      {t('Go to Old User Feedback')}
+    </LinkButton>
+  );
+}

+ 1 - 18
static/app/components/feedback/useFeedbackOnboarding.tsx → static/app/components/feedback/useHaveSelectedProjectsSetupFeedback.tsx

@@ -5,7 +5,6 @@ import {Project} from 'sentry/types';
 import {PageFilters} from 'sentry/types/core';
 import usePageFilters from 'sentry/utils/usePageFilters';
 import useProjects from 'sentry/utils/useProjects';
-import useUrlParams from 'sentry/utils/useUrlParams';
 
 function getSelectedProjectList(
   selectedProjects: PageFilters['projects'],
@@ -22,16 +21,7 @@ function getSelectedProjectList(
   return selectedProjects.map(id => projectsByProjectId[id]).filter(Boolean);
 }
 
-export function useHasOrganizationSetupFeedback() {
-  const {projects, fetching} = useProjects();
-  const hasOrgSetupFeedback = useMemo(
-    () => projects.some(p => p.hasFeedbacks),
-    [projects]
-  );
-  return {hasOrgSetupFeedback, fetching};
-}
-
-export function useHaveSelectedProjectsSetupFeedback() {
+export default function useHaveSelectedProjectsSetupFeedback() {
   const {projects, fetching} = useProjects();
   const {selection} = usePageFilters();
 
@@ -46,10 +36,3 @@ export function useHaveSelectedProjectsSetupFeedback() {
     fetching,
   };
 }
-
-export function useFeedbackHasSlug() {
-  const {getParamValue: getSlug} = useUrlParams('feedbackSlug', '');
-  const hasSlug = getSlug().length > 0;
-
-  return {hasSlug};
-}

+ 4 - 2
static/app/components/replays/pageBanner.tsx

@@ -14,22 +14,24 @@ interface Props {
   image: any;
   title: ReactNode;
   button?: ReactNode;
+  className?: string;
   onDismiss?: () => void;
   style?: CSSProperties;
 }
 
 export default function PageBanner({
   button,
+  className,
   description,
   heading,
   icon,
   image,
   onDismiss,
-  title,
   style,
+  title,
 }: Props) {
   return (
-    <Wrapper style={style}>
+    <Wrapper className={className} style={style}>
       {onDismiss && (
         <CloseButton
           onClick={onDismiss}

+ 0 - 4
static/app/utils/analytics/feedbackAnalyticsEvents.tsx

@@ -2,8 +2,6 @@ export type FeedbackEventParameters = {
   'feedback.details-integration-issue-clicked': {
     integration_key: string;
   };
-  'feedback.index-old-ui-clicked': {};
-  'feedback.index-setup-button-clicked': {};
   'feedback.index-setup-viewed': {};
   'feedback.list-item-selected': {};
 };
@@ -11,8 +9,6 @@ export type FeedbackEventParameters = {
 export type FeedbackEventKey = keyof FeedbackEventParameters;
 
 export const feedbackEventMap: Record<FeedbackEventKey, string | null> = {
-  'feedback.index-setup-button-clicked': 'Clicked Feedback Onboarding Setup Button',
-  'feedback.index-old-ui-clicked': 'Clicked Go To Old User Feedback Button',
   'feedback.index-setup-viewed': 'Viewed Feedback Onboarding Setup',
   'feedback.list-item-selected': 'Selected Item in Feedback List',
   'feedback.details-integration-issue-clicked':

+ 14 - 37
static/app/views/feedback/feedbackListPage.tsx

@@ -2,18 +2,16 @@ import {Fragment} from 'react';
 import {RouteComponentProps} from 'react-router';
 import styled from '@emotion/styled';
 
-import {Button} from 'sentry/components/button';
 import ErrorBoundary from 'sentry/components/errorBoundary';
 import FeedbackFilters from 'sentry/components/feedback/feedbackFilters';
 import FeedbackItemLoader from 'sentry/components/feedback/feedbackItem/feedbackItemLoader';
 import FeedbackSearch from 'sentry/components/feedback/feedbackSearch';
 import FeedbackSetupPanel from 'sentry/components/feedback/feedbackSetupPanel';
 import FeedbackList from 'sentry/components/feedback/list/feedbackList';
-import {
-  useFeedbackHasSlug,
-  useHaveSelectedProjectsSetupFeedback,
-} from 'sentry/components/feedback/useFeedbackOnboarding';
+import OldFeedbackButton from 'sentry/components/feedback/oldFeedbackButton';
+import useCurrentFeedbackId from 'sentry/components/feedback/useCurrentFeedbackId';
 import {FeedbackQueryKeys} from 'sentry/components/feedback/useFeedbackQueryKeys';
+import useHaveSelectedProjectsSetupFeedback from 'sentry/components/feedback/useHaveSelectedProjectsSetupFeedback';
 import FullViewport from 'sentry/components/layouts/fullViewport';
 import * as Layout from 'sentry/components/layouts/thirds';
 import ExternalLink from 'sentry/components/links/externalLink';
@@ -22,10 +20,7 @@ import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
 import {Tooltip} from 'sentry/components/tooltip';
 import {t, tct} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
-import {trackAnalytics} from 'sentry/utils/analytics';
-import {useLocation} from 'sentry/utils/useLocation';
 import useOrganization from 'sentry/utils/useOrganization';
-import {normalizeUrl} from 'sentry/utils/withDomainRequired';
 import FluidHeight from 'sentry/views/replays/detail/layout/fluidHeight';
 
 interface Props extends RouteComponentProps<{}, {}, {}> {}
@@ -33,8 +28,9 @@ interface Props extends RouteComponentProps<{}, {}, {}> {}
 export default function FeedbackListPage({}: Props) {
   const organization = useOrganization();
   const {hasSetupOneFeedback} = useHaveSelectedProjectsSetupFeedback();
-  const {hasSlug} = useFeedbackHasSlug();
-  const location = useLocation();
+
+  const feedbackSlug = useCurrentFeedbackId();
+  const hasSlug = Boolean(feedbackSlug);
 
   return (
     <SentryDocumentTitle title={t('User Feedback')} orgSlug={organization.slug}>
@@ -54,27 +50,7 @@ export default function FeedbackListPage({}: Props) {
                 position="left"
                 isHoverable
               >
-                <Button
-                  size="sm"
-                  priority="default"
-                  to={{
-                    pathname: normalizeUrl(
-                      `/organizations/${organization.slug}/user-feedback/`
-                    ),
-                    query: {
-                      ...location.query,
-                      query: undefined,
-                      cursor: undefined,
-                    },
-                  }}
-                  onClick={() => {
-                    trackAnalytics('feedback.index-old-ui-clicked', {
-                      organization,
-                    });
-                  }}
-                >
-                  {t('Go to Old User Feedback')}
-                </Button>
+                <OldFeedbackButton />
               </Tooltip>
             </Layout.HeaderActions>
           </Layout.Header>
@@ -108,20 +84,20 @@ export default function FeedbackListPage({}: Props) {
 
 const LayoutGrid = styled('div')`
   background: ${p => p.theme.background};
-
-  height: 100%;
-  width: 100%;
   padding: ${space(2)} ${space(4)} ${space(2)} ${space(4)};
   overflow: hidden;
 
+  flex-grow: 1;
+
   display: grid;
+  gap: ${space(2)};
+  place-items: stretch;
+
   grid-template-columns: minmax(390px, 1fr) 2fr;
   grid-template-rows: max-content 1fr;
   grid-template-areas:
     'filters search'
     'list details';
-  gap: ${space(2)};
-  place-items: stretch;
 `;
 
 const Container = styled(FluidHeight)`
@@ -130,5 +106,6 @@ const Container = styled(FluidHeight)`
 `;
 
 const SetupContainer = styled('div')`
-  grid-column: 1 / 3;
+  overflow: hidden;
+  grid-column: 1 / -1;
 `;