check details base
This commit is contained in:
1 parent
d139e0b643
commit
66c406151a
9 files changed
+112
-47
No files matched your search
+2
-1
@@ -4,4 +4,5 @@
|
||||
AGENTS.md
|
||||
*.sh
|
||||
notes
|
||||
docker-compose.yml
|
||||
docker-compose.yml
|
||||
mongo
|
||||
@@ -7,16 +7,42 @@ import type { StackProps } from "@mui/material/Stack";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
interface BasePageProps extends StackProps {
|
||||
loading?: boolean;
|
||||
error?: boolean;
|
||||
children: React.ReactNode;
|
||||
breadcrumbOverride?: string[];
|
||||
}
|
||||
|
||||
export const BasePage = ({
|
||||
loading,
|
||||
error,
|
||||
children,
|
||||
breadcrumbOverride,
|
||||
...props
|
||||
}: BasePageProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Stack
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
sx={{ height: "100%" }}
|
||||
>
|
||||
<CircularProgress color="primary" size={28} />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<ErrorFallback
|
||||
title="Something went wrong..."
|
||||
subtitle="Please try again later"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack spacing={theme.spacing(10)} {...props}>
|
||||
<Breadcrumb breadcrumbOverride={breadcrumbOverride} />
|
||||
@@ -49,27 +75,6 @@ export const BasePageWithStates = ({
|
||||
}: BasePageWithStatesProps) => {
|
||||
const showLoading = loading && (!items || items.length === 0);
|
||||
|
||||
if (showLoading) {
|
||||
return (
|
||||
<Stack
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
sx={{ height: "100%" }}
|
||||
>
|
||||
<CircularProgress color="primary" size={28} />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<ErrorFallback
|
||||
title="Something went wrong..."
|
||||
subtitle="Please try again later"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isEmpty(items)) {
|
||||
return (
|
||||
<EmptyFallback
|
||||
@@ -81,7 +86,11 @@ export const BasePageWithStates = ({
|
||||
);
|
||||
}
|
||||
|
||||
return <BasePage {...props}>{children}</BasePage>;
|
||||
return (
|
||||
<BasePage loading={showLoading} error={error} {...props}>
|
||||
{children}
|
||||
</BasePage>
|
||||
);
|
||||
};
|
||||
|
||||
interface MonitorBasePageWithStatesProps extends StackProps {
|
||||
@@ -114,27 +123,6 @@ export const MonitorBasePageWithStates = ({
|
||||
|
||||
const showLoading = loading && (!items || items.length === 0);
|
||||
|
||||
if (showLoading) {
|
||||
return (
|
||||
<Stack
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
sx={{ height: "100%" }}
|
||||
>
|
||||
<CircularProgress color="primary" size={28} />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<ErrorFallback
|
||||
title="Something went wrong..."
|
||||
subtitle="Please try again later"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isEmpty(items)) {
|
||||
return (
|
||||
<EmptyMonitorFallback
|
||||
@@ -148,5 +136,9 @@ export const MonitorBasePageWithStates = ({
|
||||
);
|
||||
}
|
||||
|
||||
return <BasePage {...props}>{children}</BasePage>;
|
||||
return (
|
||||
<BasePage loading={showLoading} error={error} {...props}>
|
||||
{children}
|
||||
</BasePage>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import { BasePage } from "@/components/design-elements";
|
||||
|
||||
import { useParams } from "react-router";
|
||||
import { useGet } from "@/hooks/UseApi";
|
||||
import type { ICheck } from "@/types/check";
|
||||
import type { ApiResponse } from "@/types/api";
|
||||
const CheckDetails = () => {
|
||||
const { id } = useParams();
|
||||
const { response, loading, error } = useGet<ApiResponse<ICheck>>(
|
||||
`/checks/${id}`
|
||||
);
|
||||
|
||||
const check = response?.data;
|
||||
return (
|
||||
<BasePage loading={loading} error={error}>
|
||||
{JSON.stringify(check)}
|
||||
</BasePage>
|
||||
);
|
||||
};
|
||||
|
||||
export default CheckDetails;
|
||||
@@ -6,6 +6,7 @@ import type { ICheck, IChecksWithCount } from "@/types/check";
|
||||
import type { ApiResponse } from "@/types/api";
|
||||
import type { MonitorStatus } from "@/types/monitor";
|
||||
|
||||
import { useNavigate } from "react-router";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGet } from "@/hooks/UseApi";
|
||||
@@ -51,6 +52,7 @@ const getHeaders = (t: Function, uiTimezone: string) => {
|
||||
};
|
||||
|
||||
export const CheckTable = ({ monitorId }: { monitorId: string }) => {
|
||||
const navigate = useNavigate();
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||
const { t } = useTranslation();
|
||||
@@ -87,7 +89,13 @@ export const CheckTable = ({ monitorId }: { monitorId: string }) => {
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Table headers={headers} data={checks} />
|
||||
<Table
|
||||
headers={headers}
|
||||
data={checks}
|
||||
onRowClick={(row) => {
|
||||
navigate(`/checks/${row._id}`);
|
||||
}}
|
||||
/>
|
||||
<Pagination
|
||||
component="div"
|
||||
count={count}
|
||||
|
||||
@@ -119,7 +119,7 @@ const UptimeMonitors = () => {
|
||||
|
||||
return (
|
||||
<MonitorBasePageWithStates
|
||||
loading={loading}
|
||||
loading={true}
|
||||
error={error}
|
||||
items={monitorItems}
|
||||
page="uptime"
|
||||
|
||||
@@ -21,6 +21,7 @@ import NotificationChannelsConfigPage from "@/pages/notification-channels/Notifi
|
||||
import IncidentsPage from "@/pages/incidents/IncidentsPage";
|
||||
import IncidentDetailsPage from "@/pages/incidents/IncidentDetails";
|
||||
import ChecksPage from "@/pages/checks/ChecksPage";
|
||||
import CheckDetails from "@/pages/checks/CheckDetails";
|
||||
import PageSpeedMonitorsPage from "@/pages/pagespeed/PageSpeedMonitors";
|
||||
import PageSpeedDetailsPage from "@/pages/pagespeed/PageSpeedDetails";
|
||||
import PageSpeedConfigurePage from "@/pages/pagespeed/PageSpeedConfig";
|
||||
@@ -121,6 +122,7 @@ const Router = () => {
|
||||
<Route path="incidents" element={<IncidentsPage />} />
|
||||
<Route path="incidents/:id" element={<IncidentDetailsPage />} />
|
||||
<Route path="checks" element={<ChecksPage />} />
|
||||
<Route path="checks/:id" element={<CheckDetails />} />
|
||||
<Route path="pagespeed/create" element={<PageSpeedCreatePage />} />
|
||||
<Route
|
||||
path="pagespeed/:id/configure"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { CheckService } from "@/services/index.js";
|
||||
|
||||
export interface IChecksController {
|
||||
getChecksByStatus: (req: Request, res: Response, next: NextFunction) => void;
|
||||
getCheckById: (req: Request, res: Response, next: NextFunction) => void;
|
||||
}
|
||||
|
||||
class ChecksController implements IChecksController {
|
||||
@@ -53,6 +54,30 @@ class ChecksController implements IChecksController {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getCheckById = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const userContext = req.user;
|
||||
if (!userContext) {
|
||||
return res.status(401).json({ message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const teamId = userContext.currentTeamId;
|
||||
if (!teamId) {
|
||||
throw new ApiError("No team ID", 400);
|
||||
}
|
||||
|
||||
const checkId = req.params.id;
|
||||
const check = await this.checkService.getCheckById(checkId, teamId);
|
||||
|
||||
return res.status(200).json({
|
||||
message: "Check retrieved successfully",
|
||||
data: check,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default ChecksController;
|
||||
@@ -26,6 +26,13 @@ class CheckRoutes {
|
||||
validateQuery(checksStatusIdQuerySchema),
|
||||
this.controller.getChecksByStatus
|
||||
);
|
||||
this.router.get(
|
||||
"/:id",
|
||||
verifyToken,
|
||||
addUserContext,
|
||||
verifyOrgPermission([PERMISSIONS.checks.read]),
|
||||
this.controller.getCheckById
|
||||
);
|
||||
};
|
||||
|
||||
getRouter() {
|
||||
|
||||
@@ -33,6 +33,8 @@ export interface ICheckService {
|
||||
range: string
|
||||
) => Promise<{ checks: ICheck[]; count: number }>;
|
||||
|
||||
getCheckById: (checkId: string, teamId: string) => Promise<ICheck | null>;
|
||||
|
||||
cleanupOrphanedChecks: () => Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -259,6 +261,13 @@ class CheckService implements ICheckService {
|
||||
]);
|
||||
return { checks, count };
|
||||
};
|
||||
|
||||
getCheckById = async (checkId: string, teamId: string) => {
|
||||
return await Check.findOne({
|
||||
_id: new mongoose.Types.ObjectId(checkId),
|
||||
"metadata.teamId": new mongoose.Types.ObjectId(teamId),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default CheckService;
|
||||
Reference in new issue
Block a user