client
This commit is contained in:
1 parent
9aa87f57ae
commit
6f99249d62
4 files changed
+76
-20
No files matched your search
@@ -2,6 +2,6 @@ window.__ENV = {
|
||||
GLOBAL_REFRESH: "60000",
|
||||
APP_HOST: "http://localhost:5173",
|
||||
APP_API_BASE_URL: "http://localhost:52345/api/v1",
|
||||
// APP_DEPLOYMENT_MODE: "self_hosted",
|
||||
APP_DEPLOYMENT_MODE: "saas",
|
||||
APP_DEPLOYMENT_MODE: "self_hosted",
|
||||
// APP_DEPLOYMENT_MODE: "saas",
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useAppSelector } from "@/hooks/AppHooks";
|
||||
import { Navigate } from "react-router";
|
||||
import NotFound from "@/pages/errors/NotFound";
|
||||
|
||||
export const ProtectedRoute: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
@@ -20,3 +21,24 @@ export const ProtectedRoute: React.FC<React.PropsWithChildren> = ({
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export const MasterRoute: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const user = useAppSelector((state) => state.auth.user);
|
||||
|
||||
if (user?.teams.length === 0) {
|
||||
return <Navigate to="/no-team" replace />;
|
||||
}
|
||||
|
||||
const perms: string[] = (user?.org?.permissions || []).map((p: any) =>
|
||||
(p ?? "").toString().trim().toLowerCase()
|
||||
);
|
||||
const hasMaster = perms.includes("master");
|
||||
|
||||
if (!hasMaster) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
@@ -1,5 +1,11 @@
|
||||
import { Box, Typography, Paper, Stack, Divider } from "@mui/material";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import Box from "@mui/material/Box";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useGet } from "@/hooks/UseApi";
|
||||
import { StatBox } from "@/components/design-elements";
|
||||
import { config as clientConfig } from "@/config";
|
||||
|
||||
type EnvConfig = {
|
||||
NODE_ENV: string;
|
||||
@@ -18,26 +24,24 @@ type EnvConfig = {
|
||||
};
|
||||
|
||||
export default function DiagnosticsConfigTab() {
|
||||
const theme = useTheme();
|
||||
const { response, loading, error } = useGet<{
|
||||
message: string;
|
||||
data: EnvConfig;
|
||||
}>("/diagnostic/env");
|
||||
}>("/diagnostic/env", {}, { refreshInterval: clientConfig.GLOBAL_REFRESH });
|
||||
|
||||
const data = response?.data;
|
||||
const clientEntries = Object.entries(clientConfig as Record<string, any>);
|
||||
|
||||
if (!data && !loading && !error) return null;
|
||||
|
||||
const totalKeys = data ? Object.keys(data).length : 0;
|
||||
|
||||
return (
|
||||
<Box p={2}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Environment Configuration
|
||||
</Typography>
|
||||
{loading && <Typography variant="body2">Loading…</Typography>}
|
||||
{error && (
|
||||
<Typography color="error" variant="body2">
|
||||
{error}
|
||||
</Typography>
|
||||
)}
|
||||
<Stack spacing={theme.spacing(8)}>
|
||||
{data && (
|
||||
<Paper variant="outlined">
|
||||
<Stack spacing={theme.spacing(3)}>
|
||||
<Typography variant="h1">Server environment</Typography>
|
||||
<Stack divider={<Divider />}>
|
||||
{Object.entries(data).map(([key, value]) => (
|
||||
<Box key={key} px={2} py={1.5} display="flex" gap={2}>
|
||||
@@ -50,8 +54,24 @@ export default function DiagnosticsConfigTab() {
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Stack spacing={theme.spacing(3)}>
|
||||
<Typography variant="h1">Client runtime config</Typography>
|
||||
<Stack divider={<Divider />}>
|
||||
{clientEntries.map(([key, value]) => (
|
||||
<Box key={key} px={2} py={1.5} display="flex" gap={2}>
|
||||
<Typography sx={{ minWidth: 220 }} color="text.secondary">
|
||||
{key}
|
||||
</Typography>
|
||||
<Typography sx={{ wordBreak: "break-all" }}>
|
||||
{String(value)}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ import BillingPage from "@/pages/billing/Billing";
|
||||
import BillingSuccessPage from "@/pages/billing/Success";
|
||||
|
||||
import RootLayout from "@/components/layouts/RootLayout";
|
||||
import { ProtectedRoute } from "@/components/protected-route";
|
||||
import { ProtectedRoute, MasterRoute } from "@/components/protected-route";
|
||||
|
||||
const Router = () => {
|
||||
return (
|
||||
@@ -84,7 +84,14 @@ const Router = () => {
|
||||
<Route path="uptime/:id" element={<UptimeDetailsPage />} />
|
||||
<Route path="uptime" element={<UptimeMonitorsPage />} />
|
||||
<Route path="settings" element={<SettingsPage />} />
|
||||
<Route path="settings/admin" element={<AdminSettingsPage />} />
|
||||
<Route
|
||||
path="settings/admin"
|
||||
element={
|
||||
<MasterRoute>
|
||||
<AdminSettingsPage />
|
||||
</MasterRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="teams/create" element={<TeamsCreatePage />} />
|
||||
<Route
|
||||
path="teams/:id/member/:memberId/configure"
|
||||
@@ -143,7 +150,14 @@ const Router = () => {
|
||||
element={<StatusConfigPage />}
|
||||
/>
|
||||
|
||||
<Route path="diagnostics" element={<DiagnosticPage />} />
|
||||
<Route
|
||||
path="diagnostics"
|
||||
element={
|
||||
<MasterRoute>
|
||||
<DiagnosticPage />
|
||||
</MasterRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="profile" element={<ProfilePage />} />
|
||||
<Route path="export" element={<ExportPage />} />
|
||||
|
||||
Reference in new issue
Block a user