Skip to content

Commit

Permalink
feat(toolbar): Add a badge showing the number of active alerts (getse…
Browse files Browse the repository at this point in the history
…ntry#74791)

The badge is looking like this:


![SCR-20240723-nkva](https://github.com/user-attachments/assets/78df774e-122e-4778-8157-58d19f765bf9)

also, i'm pretty happy about getting the types in shape to be able to
use `select` from useQuery. This makes things easier going forward.

Fixes getsentry#74568
  • Loading branch information
ryan953 authored Jul 23, 2024
1 parent 73390a2 commit 8d54097
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import CountBadge from '../countBadge';

import useAlertsCount from './useAlertsCount';

export default function AlertCountBadge() {
const {data: count} = useAlertsCount();

if (count === undefined) {
return null;
}
return <CountBadge value={count} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {useMemo} from 'react';

import type {Incident} from 'sentry/views/alerts/types';

import useConfiguration from '../../hooks/useConfiguration';
import useFetchApiData from '../../hooks/useFetchApiData';
import type {ApiEndpointQueryKey} from '../../types';

export default function useAlertsCount() {
const {organizationSlug, projectId} = useConfiguration();

return useFetchApiData<Incident[], number>({
queryKey: useMemo(
(): ApiEndpointQueryKey => [
'io.sentry.toolbar',
`/organizations/${organizationSlug}/incidents/`,
{
query: {
limit: 1,
queryReferrer: 'devtoolbar',
project: [projectId],
statusPeriod: '14d',
status: 'open',
},
},
],
[organizationSlug, projectId]
),
select: (data): number => data.json.length,
});
}
20 changes: 20 additions & 0 deletions static/app/components/devtoolbar/components/countBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {css} from '@emotion/react';

import {smallCss} from '../styles/typography';

export default function CountBadge({value}: {value: number}) {
return <div css={[smallCss, counterCss]}>{value}</div>;
}

const counterCss = css`
background: red;
background: var(--red400);
border-radius: 50%;
color: var(--gray100);
height: 1rem;
line-height: 1rem;
position: absolute;
right: -6px;
top: -6px;
width: 1rem;
`;
17 changes: 13 additions & 4 deletions static/app/components/devtoolbar/components/navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type {ReactNode} from 'react';
import {css} from '@emotion/react';

import useConfiguration from 'sentry/components/devtoolbar/hooks/useConfiguration';
import InteractionStateLayer from 'sentry/components/interactionStateLayer';
import {IconClose, IconFlag, IconIssues, IconMegaphone, IconSiren} from 'sentry/icons';

import useConfiguration from '../hooks/useConfiguration';
import usePlacementCss from '../hooks/usePlacementCss';
import useToolbarRoute from '../hooks/useToolbarRoute';
import {navigationButtonCss, navigationCss} from '../styles/navigation';
import {resetButtonCss, resetDialogCss} from '../styles/reset';
import {buttonCss} from '../styles/typography';

import AlertCountBadge from './alerts/alertCountBadge';

export default function Navigation({
setIsDisabled,
Expand All @@ -28,7 +32,9 @@ export default function Navigation({
>
<NavButton panelName="issues" label="Issues" icon={<IconIssues />} />
<NavButton panelName="feedback" label="User Feedback" icon={<IconMegaphone />} />
<NavButton panelName="alerts" label="Active Alerts" icon={<IconSiren />} />
<NavButton panelName="alerts" label="Active Alerts" icon={<IconSiren />}>
<AlertCountBadge />
</NavButton>
<NavButton panelName="featureFlags" label="Feature Flags" icon={<IconFlag />} />
<HideButton
onClick={() => {
Expand All @@ -44,13 +50,15 @@ export default function Navigation({
}

function NavButton({
children,
icon,
label,
panelName,
}: {
icon: React.ReactNode;
icon: ReactNode;
label: string;
panelName: ReturnType<typeof useToolbarRoute>['state']['activePanel'];
children?: ReactNode;
}) {
const {trackAnalytics} = useConfiguration();
const {state, setActivePanel} = useToolbarRoute();
Expand All @@ -73,6 +81,7 @@ function NavButton({
>
<InteractionStateLayer />
{icon}
{children}
</button>
);
}
Expand All @@ -98,7 +107,7 @@ function HideButton({onClick}: {onClick: () => void}) {
return (
<button
aria-label="Hide for this session"
css={[resetButtonCss, hideButtonCss]}
css={[resetButtonCss, buttonCss, hideButtonCss]}
onClick={onClick}
title="Hide for this session"
>
Expand Down
11 changes: 7 additions & 4 deletions static/app/components/devtoolbar/hooks/useFetchApiData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import type {ApiEndpointQueryKey, ApiResult} from '../types';

import useApiEndpoint from './useApiEndpoint';

export default function useFetchApiData<Data extends Array<unknown>>(
props: UseQueryOptions<ApiEndpointQueryKey, Error, Data, ApiEndpointQueryKey>
export default function useFetchApiData<
QueryFnData,
SelectFnData = ApiResult<QueryFnData>,
>(
props: UseQueryOptions<ApiResult<QueryFnData>, Error, SelectFnData, ApiEndpointQueryKey>
) {
const {fetchFn} = useApiEndpoint();

const infiniteQueryResult = useQuery<ApiEndpointQueryKey, Error, ApiResult<Data>, any>({
queryFn: fetchFn<Data>,
const infiniteQueryResult = useQuery<ApiEndpointQueryKey, Error, SelectFnData, any>({
queryFn: fetchFn<QueryFnData>,
...props,
});

Expand Down
20 changes: 20 additions & 0 deletions static/app/components/devtoolbar/styles/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ export const globalCss = css`
--blue200: rgba(60, 116, 221, 0.5);
--blue100: rgba(60, 116, 221, 0.09);
--green400: #207964;
--green300: #2ba185;
--green200: rgba(43, 161, 133, 0.55);
--green100: rgba(43, 161, 133, 0.11);
--yellow400: #856c00;
--yellow300: #ebc000;
--yellow200: rgba(235, 192, 0, 0.7);
--yellow100: rgba(235, 192, 0, 0.14);
--red400: #cf2126;
--red300: #f55459;
--red200: rgba(245, 84, 89, 0.5);
--red100: rgba(245, 84, 89, 0.1);
--pink400: #d1056b;
--pink300: #f14499;
--pink200: rgba(249, 26, 138, 0.5);
--pink100: rgba(249, 26, 138, 0.09);
--z-index: 100000;
color: var(--gray400);
Expand Down

0 comments on commit 8d54097

Please sign in to comment.