123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- import {useEffect, useRef} from 'react';
- import styled from '@emotion/styled';
- import {
- deleteMonitorEnvironment,
- setEnvironmentIsMuted,
- } from 'sentry/actionCreators/monitors';
- import {
- GridLineLabels,
- GridLineOverlay,
- } from 'sentry/components/checkInTimeline/gridLines';
- import {useTimeWindowConfig} from 'sentry/components/checkInTimeline/hooks/useTimeWindowConfig';
- import Panel from 'sentry/components/panels/panel';
- import Text from 'sentry/components/text';
- import {t} from 'sentry/locale';
- import {space} from 'sentry/styles/space';
- import {setApiQueryData, useQueryClient} from 'sentry/utils/queryClient';
- import useApi from 'sentry/utils/useApi';
- import {useDimensions} from 'sentry/utils/useDimensions';
- import {useLocation} from 'sentry/utils/useLocation';
- import useOrganization from 'sentry/utils/useOrganization';
- import type {Monitor, MonitorBucket} from 'sentry/views/monitors/types';
- import {makeMonitorDetailsQueryKey} from 'sentry/views/monitors/utils';
- import {useMonitorStats} from './../utils/useMonitorStats';
- import {OverviewRow} from './overviewTimeline/overviewRow';
- import {CronServiceIncidents} from './serviceIncidents';
- interface Props {
- monitor: Monitor;
- /**
- * Called when monitor stats have been loaded for this timeline.
- */
- onStatsLoaded: (stats: MonitorBucket[]) => void;
- }
- export function DetailsTimeline({monitor, onStatsLoaded}: Props) {
- const organization = useOrganization();
- const location = useLocation();
- const api = useApi();
- const queryClient = useQueryClient();
- const elementRef = useRef<HTMLDivElement>(null);
- const {width: timelineWidth} = useDimensions<HTMLDivElement>({elementRef});
- const timeWindowConfig = useTimeWindowConfig({timelineWidth});
- const monitorDetailsQueryKey = makeMonitorDetailsQueryKey(
- organization,
- monitor.project.slug,
- monitor.slug,
- {...location.query}
- );
- const {data: monitorStats} = useMonitorStats({
- monitors: [monitor.id],
- timeWindowConfig,
- });
- useEffect(
- () => monitorStats?.[monitor.id] && onStatsLoaded?.(monitorStats[monitor.id]!),
- [onStatsLoaded, monitorStats, monitor.id]
- );
- const handleDeleteEnvironment = async (env: string) => {
- const success = await deleteMonitorEnvironment(api, organization.slug, monitor, env);
- if (!success) {
- return;
- }
- setApiQueryData(queryClient, monitorDetailsQueryKey, (oldMonitorDetails: Monitor) => {
- const newEnvList = oldMonitorDetails.environments.filter(e => e.name !== env);
- const newMonitorDetails = {
- ...oldMonitorDetails,
- environments: newEnvList,
- };
- return newMonitorDetails;
- });
- };
- const handleToggleMuteEnvironment = async (env: string, isMuted: boolean) => {
- const resp = await setEnvironmentIsMuted(
- api,
- organization.slug,
- monitor,
- env,
- isMuted
- );
- if (resp === null) {
- return;
- }
- setApiQueryData(queryClient, monitorDetailsQueryKey, (oldMonitorDetails: Monitor) => {
- const oldMonitorEnvIdx = oldMonitorDetails.environments.findIndex(
- monitorEnv => monitorEnv.name === env
- );
- if (oldMonitorEnvIdx < 0) {
- return oldMonitorDetails;
- }
- oldMonitorDetails.environments[oldMonitorEnvIdx] = {
- ...oldMonitorDetails.environments[oldMonitorEnvIdx]!,
- isMuted,
- };
- return oldMonitorDetails;
- });
- };
- return (
- <TimelineContainer>
- <TimelineWidthTracker ref={elementRef} />
- <Header>
- <TimelineTitle>{t('Check-Ins')}</TimelineTitle>
- <GridLineLabels timeWindowConfig={timeWindowConfig} />
- </Header>
- <AlignedGridLineOverlay
- allowZoom
- showCursor
- timeWindowConfig={timeWindowConfig}
- additionalUi={<CronServiceIncidents timeWindowConfig={timeWindowConfig} />}
- />
- <OverviewRow
- monitor={monitor}
- timeWindowConfig={timeWindowConfig}
- onDeleteEnvironment={handleDeleteEnvironment}
- onToggleMuteEnvironment={handleToggleMuteEnvironment}
- singleMonitorView
- />
- </TimelineContainer>
- );
- }
- const TimelineContainer = styled(Panel)`
- display: grid;
- grid-template-columns: 135px 1fr;
- `;
- const Header = styled('div')`
- grid-column: 1/-1;
- display: grid;
- grid-template-columns: subgrid;
- border-bottom: 1px solid ${p => p.theme.border};
- `;
- const TimelineWidthTracker = styled('div')`
- position: absolute;
- width: 100%;
- grid-row: 1;
- grid-column: 2;
- `;
- const AlignedGridLineOverlay = styled(GridLineOverlay)`
- grid-column: 2;
- `;
- const TimelineTitle = styled(Text)`
- padding: ${space(2)};
- grid-column: 1;
- line-height: 1.2;
- font-weight: bold;
- `;
|