Browse Source

feat(team-stats): Add empty states to team stats tables (#30685)

* feat(team-releases): Add empty states to all tables

* fix team releases table

* add missing margins

* fix test string
Taylan Gocmen 3 years ago
parent
commit
6c9d35328e

+ 57 - 2
static/app/views/organizationStats/teamInsights/teamAlertsTriggered.tsx

@@ -1,6 +1,8 @@
+import {css} from '@emotion/react';
 import styled from '@emotion/styled';
 
 import AsyncComponent from 'sentry/components/asyncComponent';
+import Button from 'sentry/components/button';
 import BarChart from 'sentry/components/charts/barChart';
 import {DateTimeObject} from 'sentry/components/charts/utils';
 import LoadingIndicator from 'sentry/components/loadingIndicator';
@@ -9,6 +11,8 @@ import {t} from 'sentry/locale';
 import space from 'sentry/styles/space';
 import {Organization} from 'sentry/types';
 
+import PanelTable from '../../../components/panels/panelTable';
+
 import {
   barAxisLabel,
   convertDaySeriesToWeeks,
@@ -76,13 +80,36 @@ class TeamAlertsTriggered extends AsyncComponent<Props, State> {
   }
 
   renderBody() {
+    const {organization} = this.props;
     const {alertsTriggered} = this.state;
     const data = convertDayValueObjectToSeries(alertsTriggered ?? {});
     const seriesData = convertDaySeriesToWeeks(data);
 
     return (
       <ChartWrapper>
-        {alertsTriggered && (
+        <StyledPanelTable
+          isEmpty={!alertsTriggered || data.length === 0}
+          emptyMessage={t('No Alerts Owned By This Team')}
+          emptyAction={
+            <ButtonsContainer>
+              <Button
+                priority="primary"
+                size="small"
+                to={`/organizations/${organization.slug}/alerts/rules/`}
+              >
+                {t('Create Alert Rule')}
+              </Button>
+              <Button
+                size="small"
+                external
+                to="https://docs.sentry.io/product/alerts/create-alerts/"
+              >
+                {t('Learn more')}
+              </Button>
+            </ButtonsContainer>
+          }
+          headers={[]}
+        >
           <BarChart
             style={{height: 190}}
             isGroupedByDate
@@ -99,7 +126,7 @@ class TeamAlertsTriggered extends AsyncComponent<Props, State> {
               },
             ]}
           />
-        )}
+        </StyledPanelTable>
       </ChartWrapper>
     );
   }
@@ -110,3 +137,31 @@ export default TeamAlertsTriggered;
 const ChartWrapper = styled('div')`
   padding: ${space(2)} ${space(2)} 0 ${space(2)};
 `;
+
+const StyledPanelTable = styled(PanelTable)<{isEmpty: boolean}>`
+  grid-template-columns: 1fr;
+  font-size: ${p => p.theme.fontSizeMedium};
+  white-space: nowrap;
+  margin-bottom: 0;
+  border: 0;
+  box-shadow: unset;
+
+  & > div {
+    padding: ${space(1)} ${space(2)};
+  }
+
+  ${p =>
+    p.isEmpty &&
+    css`
+      & > div:last-child {
+        padding: 48px ${space(2)};
+      }
+    `}
+`;
+
+const ButtonsContainer = styled('div')`
+  & > a {
+    margin-right: ${space(0.5)};
+    margin-left: ${space(0.5)};
+  }
+`;

+ 10 - 0
static/app/views/organizationStats/teamInsights/teamIssuesAge.tsx

@@ -1,4 +1,5 @@
 import {Fragment} from 'react';
+import {css} from '@emotion/react';
 import styled from '@emotion/styled';
 import moment from 'moment';
 
@@ -136,6 +137,7 @@ class TeamIssuesAge extends AsyncComponent<Props, State> {
         </ChartWrapper>
         <StyledPanelTable
           isEmpty={!oldestIssues || oldestIssues.length === 0}
+          emptyMessage={t("No Unresolved Issues For This Team's Projects")}
           headers={[
             t('Oldest Issues'),
             <RightAligned key="events">{t('Events')}</RightAligned>,
@@ -204,6 +206,14 @@ const StyledPanelTable = styled(PanelTable)`
   > * {
     padding: ${space(1)} ${space(2)};
   }
+
+  ${p =>
+    p.isEmpty &&
+    css`
+      & > div:last-child {
+        padding: 48px ${space(2)};
+      }
+    `}
 `;
 
 const RightAligned = styled('span')`

+ 11 - 0
static/app/views/organizationStats/teamInsights/teamIssuesReviewed.tsx

@@ -1,4 +1,5 @@
 import {Fragment} from 'react';
+import {css} from '@emotion/react';
 import styled from '@emotion/styled';
 import isEqual from 'lodash/isEqual';
 
@@ -150,6 +151,8 @@ class TeamIssuesReviewed extends AsyncComponent<Props, State> {
           )}
         </IssuesChartWrapper>
         <StyledPanelTable
+          isEmpty={projects.length === 0}
+          emptyMessage={t('No Projects Assigned To This Team')}
           headers={[
             t('Project'),
             <AlignRight key="forReview">{t('For Review')}</AlignRight>,
@@ -200,6 +203,14 @@ const StyledPanelTable = styled(PanelTable)`
   & > div {
     padding: ${space(1)} ${space(2)};
   }
+
+  ${p =>
+    p.isEmpty &&
+    css`
+      & > div:last-child {
+        padding: 48px ${space(2)};
+      }
+    `}
 `;
 
 const ProjectBadgeContainer = styled('div')`

+ 21 - 2
static/app/views/organizationStats/teamInsights/teamReleases.tsx

@@ -1,11 +1,12 @@
 import {ComponentType, Fragment} from 'react';
-import {withTheme} from '@emotion/react';
+import {css, withTheme} from '@emotion/react';
 import styled from '@emotion/styled';
 import isEqual from 'lodash/isEqual';
 import round from 'lodash/round';
 import moment from 'moment';
 
 import AsyncComponent from 'sentry/components/asyncComponent';
+import Button from 'sentry/components/button';
 import BarChart from 'sentry/components/charts/barChart';
 import MarkLine from 'sentry/components/charts/components/markLine';
 import {DateTimeObject, getTooltipArrow} from 'sentry/components/charts/utils';
@@ -244,6 +245,16 @@ class TeamReleases extends AsyncComponent<Props, State> {
         </ChartWrapper>
         <StyledPanelTable
           isEmpty={projects.length === 0}
+          emptyMessage={t("No Releases Were Setup For This Team's Projects")}
+          emptyAction={
+            <Button
+              size="small"
+              external
+              href="https://docs.sentry.io/product/releases/setup/"
+            >
+              {t('Learn More')}
+            </Button>
+          }
           headers={[
             t('Releases Per Project'),
             <RightAligned key="last">
@@ -293,7 +304,7 @@ const ChartWrapper = styled('div')`
   border-bottom: 1px solid ${p => p.theme.border};
 `;
 
-const StyledPanelTable = styled(PanelTable)`
+const StyledPanelTable = styled(PanelTable)<{isEmpty: boolean}>`
   grid-template-columns: 1fr 0.2fr 0.2fr 0.2fr;
   white-space: nowrap;
   margin-bottom: 0;
@@ -304,6 +315,14 @@ const StyledPanelTable = styled(PanelTable)`
   & > div {
     padding: ${space(1)} ${space(2)};
   }
+
+  ${p =>
+    p.isEmpty &&
+    css`
+      & > div:last-child {
+        padding: 48px ${space(2)};
+      }
+    `}
 `;
 
 const RightAligned = styled('span')`

+ 21 - 1
static/app/views/organizationStats/teamInsights/teamStability.tsx

@@ -1,9 +1,11 @@
 import {Fragment} from 'react';
+import {css} from '@emotion/react';
 import styled from '@emotion/styled';
 import isEqual from 'lodash/isEqual';
 import round from 'lodash/round';
 
 import AsyncComponent from 'sentry/components/asyncComponent';
+import Button from 'sentry/components/button';
 import {DateTimeObject} from 'sentry/components/charts/utils';
 import IdBadge from 'sentry/components/idBadge';
 import {getParams} from 'sentry/components/organizations/globalSelectionHeader/getParams';
@@ -182,6 +184,16 @@ class TeamStability extends AsyncComponent<Props, State> {
     return (
       <StyledPanelTable
         isEmpty={projects.length === 0}
+        emptyMessage={t('No Projects With Release Health Enabled')}
+        emptyAction={
+          <Button
+            size="small"
+            external
+            href="https://docs.sentry.io/platforms/dotnet/guides/nlog/configuration/releases/#release-health"
+          >
+            {t('Learn More')}
+          </Button>
+        }
         headers={[
           t('Project'),
           <RightAligned key="last">{tct('Last [period]', {period})}</RightAligned>,
@@ -207,7 +219,7 @@ class TeamStability extends AsyncComponent<Props, State> {
 
 export default TeamStability;
 
-const StyledPanelTable = styled(PanelTable)`
+const StyledPanelTable = styled(PanelTable)<{isEmpty: boolean}>`
   grid-template-columns: 1fr 0.2fr 0.2fr 0.2fr;
   font-size: ${p => p.theme.fontSizeMedium};
   white-space: nowrap;
@@ -218,6 +230,14 @@ const StyledPanelTable = styled(PanelTable)`
   & > div {
     padding: ${space(1)} ${space(2)};
   }
+
+  ${p =>
+    p.isEmpty &&
+    css`
+      & > div:last-child {
+        padding: 48px ${space(2)};
+      }
+    `}
 `;
 
 const RightAligned = styled('span')`

+ 3 - 1
tests/js/spec/views/organizationStats/teamInsights/teamStability.spec.jsx

@@ -41,6 +41,8 @@ describe('TeamStability', () => {
       <TeamStability projects={[]} organization={TestStubs.Organization()} period="7d" />
     );
 
-    expect(screen.getByText('There are no items to display')).toBeInTheDocument();
+    expect(
+      screen.getByText('No Projects With Release Health Enabled')
+    ).toBeInTheDocument();
   });
 });