Skip to content

Commit fe1a92e

Browse files
authored
Merge pull request #3 from opsway-io/stripe
stripe
2 parents 031867b + 591c229 commit fe1a92e

File tree

9 files changed

+238
-3
lines changed

9 files changed

+238
-3
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import client from "../../client";
2+
3+
/*
4+
Shared
5+
*/
6+
7+
export interface Incident {
8+
id: string;
9+
teamId: number;
10+
monitorId: number;
11+
title: string;
12+
description: string;
13+
createdAt: string;
14+
}
15+
16+
/*
17+
Get Team Incidents
18+
*/
19+
20+
export interface GetIncidentsResponse {
21+
incidents: Incident[];
22+
}
23+
24+
export async function getIncidents(
25+
teamId: number,
26+
offset?: number,
27+
limit?: number,
28+
): Promise<GetIncidentsResponse> {
29+
const response = await client.get(`/v1/teams/${teamId}/incidents`,
30+
{
31+
params: {
32+
offset,
33+
limit,
34+
},
35+
},
36+
);
37+
38+
return response?.data;
39+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./incidents";

apps/dashboard/src/api/endpoints/monitors/checks.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,37 @@ export async function getMonitorChecks(
5656
return response?.data;
5757
}
5858

59+
export interface GetMonitorsIncidentsResponse {
60+
monitors: MonitorsWithIncidents[];
61+
}
62+
63+
export interface MonitorsWithIncidents {
64+
id: number;
65+
teamId: number;
66+
state: string;
67+
name: string;
68+
createdAt: string;
69+
updatedAt: string;
70+
incidents: Incident[];
71+
}
72+
export interface Incident {
73+
id: number;
74+
createdAt: string;
75+
updatedAt: string;
76+
MonitorAssertionID: number;
77+
}
78+
79+
80+
export async function getMonitorsIncidents(
81+
teamId: number,
82+
): Promise<GetMonitorsIncidentsResponse> {
83+
const response = await client.get(
84+
`/v1/teams/${teamId}/monitors/incidents`,
85+
);
86+
87+
return response?.data;
88+
}
89+
5990
/*
6091
Get Monitor Check
6192
*/
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useMutation, useQuery } from "@tanstack/react-query";
2+
import * as IncidentsAPI from "../api/endpoints/incidents";
3+
import useAuthenticationStore from "./authentication.store";
4+
import { getQueryClient } from "./client.query";
5+
6+
const queryClient = getQueryClient();
7+
8+
9+
export const useIncidents = (offset = 0, limit = 5) => {
10+
const teamId = useAuthenticationStore((state) => state.currentTeamId);
11+
12+
return useQuery(["team", teamId, "checks",
13+
{
14+
offset,
15+
limit,
16+
},
17+
], () => {
18+
if (!teamId) {
19+
return Promise.resolve(null);
20+
}
21+
22+
return IncidentsAPI.getIncidents(teamId, offset, limit);
23+
});
24+
};
25+

apps/dashboard/src/hooks/monitors.query.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,19 @@ export const useMonitorChecks = (monitorId?: number, offset = 0, limit = 5) => {
121121
);
122122
};
123123

124+
export const useMonitorsIncidents = () => {
125+
const teamId = useAuthenticationStore((state) => state.currentTeamId);
126+
127+
return useQuery(["teams", teamId, "monitors", "incidents"], () => {
128+
if (!teamId) {
129+
return Promise.resolve(null);
130+
}
131+
132+
return MonitorsAPI.getMonitorsIncidents(teamId);
133+
});
134+
}
135+
136+
124137
export const useLatestMonitorCheck = (monitorId?: number) => {
125138
const teamId = useAuthenticationStore((state) => state.currentTeamId);
126139

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import {
2+
Box,
3+
Button,
4+
Card,
5+
Chip,
6+
Grid,
7+
Stack,
8+
Tooltip,
9+
Typography,
10+
} from "@mui/material";
11+
import { FunctionComponent } from "react";
12+
import { IoOpenOutline, IoStatsChart } from "react-icons/io5";
13+
import { useNavigate } from "react-router-dom";
14+
import { MonitorsWithIncidents } from "../../../../../src/api/endpoints/monitors";
15+
16+
interface MonitorIncidentPageOverviewListProps {
17+
monitors?: MonitorsWithIncidents[];
18+
}
19+
20+
const IncidentPageOverviewList: FunctionComponent<
21+
MonitorIncidentPageOverviewListProps
22+
> = ({
23+
monitors
24+
}) => {
25+
return (
26+
<Stack spacing={2}>
27+
{monitors?.map((monitor) => (
28+
<OverviewListItem monitor={monitor} />
29+
))}
30+
</Stack>
31+
);
32+
};
33+
34+
interface OverviewListItemProps {
35+
monitor: MonitorsWithIncidents;
36+
}
37+
38+
const OverviewListItem: FunctionComponent<OverviewListItemProps> = (
39+
{
40+
monitor,
41+
}
42+
) => {
43+
const navigate = useNavigate();
44+
45+
return (
46+
<Stack direction="row" spacing={0.5}>
47+
<Card
48+
component={Button}
49+
sx={{
50+
display: "block",
51+
textAlign: "left",
52+
padding: 0,
53+
flex: 1,
54+
}}
55+
>
56+
<Stack direction="row">
57+
<Grid
58+
container
59+
alignItems="center"
60+
p={2}
61+
columns={{ xs: 1, md: 2 }}
62+
justifyContent="space-between"
63+
gap={{ xs: 2, md: 4 }}
64+
onClick={() => navigate("/status-pages/1")}
65+
>
66+
<Grid item>
67+
<Stack spacing={1}>
68+
<Typography variant="body2">{monitor.name}</Typography>
69+
70+
<Stack direction="row" spacing={1}>
71+
<Chip size="small" label="api" color="info" />
72+
<Chip size="small" label="login" color="info" />
73+
<Chip size="small" label="monitors" color="info" />
74+
<Chip size="small" label="foo" color="info" />
75+
<Chip size="small" label="bar" color="info" />
76+
</Stack>
77+
</Stack>
78+
</Grid>
79+
80+
<Grid
81+
item
82+
direction="row"
83+
display="flex"
84+
justifyContent="flex-end"
85+
alignItems="center"
86+
gap={2}
87+
>
88+
<Stack textAlign={{ xs: "left", md: "right" }}>
89+
<Typography variant="body2" color="text.secondary">
90+
{monitor.incidents.length} active incidents
91+
</Typography>
92+
</Stack>
93+
94+
<Box sx={{ display: { xs: "none", md: "block" } }}>
95+
<IoStatsChart size={38} />
96+
</Box>
97+
</Grid>
98+
</Grid>
99+
</Stack>
100+
</Card>
101+
102+
<Tooltip title="Open in a new tab">
103+
<Card component={Button} color="primary">
104+
<IoOpenOutline size={18} />
105+
</Card>
106+
</Tooltip>
107+
</Stack>
108+
);
109+
};
110+
111+
export default IncidentPageOverviewList;

apps/dashboard/src/pages/Dashboard/Incidents/index.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,20 @@ import { FunctionComponent } from "react";
22
import { Helmet } from "react-helmet";
33
import Container from "../../../components/Container";
44
import Placeholder from "../../../components/Placeholder";
5+
import IncidentOverviewList from "./components/OverviewList";
6+
// import { useIncidents } from "../../../hooks/incidents.query";
7+
import { useMonitorsIncidents } from "../../../hooks/monitors.query";
8+
9+
510

611
const IncidentsView: FunctionComponent = () => {
12+
13+
// Get incidents
14+
const {
15+
data: monitorsIncidents,
16+
error: incidentsError,
17+
isLoading: incidentsAreLoading,
18+
} = useMonitorsIncidents();
719
return (
820
<>
921
<Helmet>
@@ -14,7 +26,10 @@ const IncidentsView: FunctionComponent = () => {
1426
header="Incidents"
1527
description="An overview active and resolved incidents across your infrastructure."
1628
>
17-
<Placeholder />
29+
{incidentsAreLoading ? (<Placeholder />) :
30+
( <IncidentOverviewList monitors={monitorsIncidents?.monitors} />)
31+
}
32+
1833
</Container>
1934
</>
2035
);

apps/dashboard/src/pages/Dashboard/Monitors/Detail/components/AverageResponseTimeCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const AverageResponseTimeCard: FunctionComponent<
2424
return (
2525
<Card sx={{ flex: 1 }}>
2626
<CardContent>
27-
<Typography sx={{ opacity: 0.5 }}>Average response time</Typography>
27+
<Typography sx={{ opacity: 0.5 }}>Average response time (24-hour)</Typography>
2828

2929
<Conditional value={isLoading}>
3030
<Skeleton variant="text" width={100} height={28} />

apps/dashboard/src/pages/Dashboard/Monitors/Detail/components/UptimeCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const UptimeCard: FunctionComponent<UptimeCardProps> = ({ monitorId }) => {
2222
return (
2323
<Card sx={{ flex: 1 }}>
2424
<CardContent>
25-
<Typography sx={{ opacity: 0.5 }}>Uptime</Typography>
25+
<Typography sx={{ opacity: 0.5 }}>Uptime (24-hour)</Typography>
2626
<Conditional value={isLoading}>
2727
<Skeleton variant="text" width={100} height={28} />
2828
</Conditional>

0 commit comments

Comments
 (0)