feat: add status basic page

This commit is contained in:
moonrailgun 2023-12-16 00:33:36 +08:00
parent 3c195b1245
commit 63145c1e4b
11 changed files with 106 additions and 8 deletions

View File

@ -18,6 +18,7 @@ import { useInjectWebsiteScript } from './hooks/useInjectWebsiteScript';
import { ConfigProvider, theme } from 'antd';
import clsx from 'clsx';
import { useSettingsStore } from './store/settings';
import { StatusPage } from './pages/Status';
export const AppRoutes: React.FC = React.memo(() => {
const { info } = useUserStore();
@ -42,6 +43,8 @@ export const AppRoutes: React.FC = React.memo(() => {
</Route>
)}
<Route path="/status/:slug" element={<StatusPage />} />
<Route
path="*"
element={

View File

@ -1,11 +1,15 @@
import React from 'react';
import { MonitorHealthBar } from '../../monitor/MonitorHealthBar';
import { useCurrentWorkspaceId } from '../../../store/user';
export const MonitorHealthBarItem: React.FC<{
monitorId: string;
}> = React.memo((props) => {
const workspaceId = useCurrentWorkspaceId();
return (
<MonitorHealthBar
workspaceId={workspaceId}
monitorId={props.monitorId}
count={40}
size="large"

View File

@ -8,6 +8,7 @@ import { useCurrentWorkspaceId } from '../../store/user';
import { useWatch } from '../../hooks/useWatch';
interface MonitorHealthBarProps {
workspaceId: string;
monitorId: string;
count?: number;
size?: HealthBarProps['size'];
@ -18,8 +19,13 @@ interface MonitorHealthBarProps {
}
export const MonitorHealthBar: React.FC<MonitorHealthBarProps> = React.memo(
(props) => {
const { monitorId, size, count = 20, showCurrentStatus = false } = props;
const workspaceId = useCurrentWorkspaceId();
const {
workspaceId,
monitorId,
size,
count = 20,
showCurrentStatus = false,
} = props;
const { data: recent = [] } = trpc.monitor.recentData.useQuery({
workspaceId,
monitorId,

View File

@ -166,6 +166,7 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
<Card>
<MonitorHealthBar
workspaceId={workspaceId}
monitorId={monitorId}
count={40}
size="large"

View File

@ -65,6 +65,7 @@ export const MonitorListItem: React.FC<{
}> = React.memo((props) => {
const { monitor, selectedMonitorId, setSelectedMonitorId } = props;
const navigate = useNavigate();
const workspaceId = useCurrentWorkspaceId();
const [beats, setBeats] = useState<
({
value: number;
@ -126,7 +127,11 @@ export const MonitorListItem: React.FC<{
</div>
<div className="flex items-center">
<MonitorHealthBar monitorId={monitor.id} onBeatsItemUpdate={setBeats} />
<MonitorHealthBar
workspaceId={workspaceId}
monitorId={monitor.id}
onBeatsItemUpdate={setBeats}
/>
</div>
</div>
);

View File

@ -91,7 +91,10 @@ export const WebsiteOverview: React.FC<{
className="cursor-pointer"
onClick={() => navigate(`/monitor/${website.monitorId}`)}
>
<MonitorHealthBar monitorId={website.monitorId} />
<MonitorHealthBar
workspaceId={website.workspaceId}
monitorId={website.monitorId}
/>
</div>
)}

View File

@ -4,4 +4,4 @@ import { Dashboard } from '../components/dashboard/Dashboard';
export const DashboardPage: React.FC = React.memo(() => {
return <Dashboard />;
});
Dashboard.displayName = 'Dashboard';
DashboardPage.displayName = 'DashboardPage';

View File

@ -0,0 +1,46 @@
import React from 'react';
import { useParams } from 'react-router';
import { trpc } from '../api/trpc';
import { Empty } from 'antd';
import { MonitorHealthBar } from '../components/monitor/MonitorHealthBar';
import { useUserStore } from '../store/user';
export const StatusPage: React.FC = React.memo(() => {
const { slug } = useParams<{ slug: string }>();
useUserStore();
const { data: info } = trpc.monitor.getPageInfo.useQuery({
slug: slug!,
});
const monitorList = info?.monitorList ?? [];
return (
<div className="w-4/5 mx-auto py-8">
<div className="text-2xl mb-4">{info?.title}</div>
<div className="text-lg mb-2">Services</div>
{info && (
<div className="shadow-2xl p-2.5">
{monitorList.length > 0 ? (
monitorList.map((item) => (
<div key={item.id} className="hover:bg-black hover:bg-opacity-20">
<MonitorHealthBar
workspaceId={info.workspaceId}
monitorId={item.id}
count={40}
size="large"
showCurrentStatus={true}
/>
</div>
))
) : (
<Empty description="No any monitor has been set" />
)}
</div>
)}
</div>
);
});
StatusPage.displayName = 'StatusPage';

View File

@ -15,7 +15,10 @@ export const useUserStore = create<UserState>(() => ({
export function setUserInfo(info: UserLoginInfo) {
if (!info.currentWorkspace && info.workspaces[0]) {
// Make sure currentWorkspace existed
info.currentWorkspace = info.workspaces[0].workspace;
info.currentWorkspace = {
...info.workspaces[0].workspace,
dashboardLayout: null,
};
}
useUserStore.setState({
@ -28,6 +31,10 @@ export function setUserInfo(info: UserLoginInfo) {
}
}
export function useUserInfo(): UserLoginInfo | null {
return useUserStore((state) => state.info);
}
export function useCurrentWorkspace() {
const currentWorkspace = useUserStore(
(state) => state.info?.currentWorkspace

View File

@ -28,8 +28,7 @@ export const userInfoSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
deletedAt: z.date().nullable(),
currentWorkspace: z.intersection(
workspaceSchema,
currentWorkspace: workspaceSchema.merge(
z.object({
dashboardLayout: workspaceDashboardLayoutSchema.nullable(),
})

View File

@ -1,5 +1,6 @@
import {
OpenApiMetaInfo,
publicProcedure,
router,
workspaceOwnerProcedure,
workspaceProcedure,
@ -435,6 +436,29 @@ export const monitorRouter = router({
},
});
}),
getPageInfo: publicProcedure
.meta({
openapi: {
tags: [OPENAPI_TAG.MONITOR],
method: 'GET',
path: '/monitor/getPageInfo',
},
})
.input(
z.object({
slug: z.string(),
})
)
.output(MonitorStatusPageModelSchema.nullable())
.query(({ input }) => {
const { slug } = input;
return prisma.monitorStatusPage.findUnique({
where: {
slug,
},
});
}),
createPage: workspaceOwnerProcedure
.meta(
buildMonitorOpenapi({