feat: add status basic page
This commit is contained in:
parent
3c195b1245
commit
63145c1e4b
@ -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={
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -166,6 +166,7 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
||||
|
||||
<Card>
|
||||
<MonitorHealthBar
|
||||
workspaceId={workspaceId}
|
||||
monitorId={monitorId}
|
||||
count={40}
|
||||
size="large"
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
)}
|
||||
|
||||
|
@ -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';
|
||||
|
46
src/client/pages/Status.tsx
Normal file
46
src/client/pages/Status.tsx
Normal 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';
|
@ -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
|
||||
|
@ -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(),
|
||||
})
|
||||
|
@ -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({
|
||||
|
Loading…
Reference in New Issue
Block a user