Compare commits

...

2 Commits

Author SHA1 Message Date
6aad88920d feat: add Empty info on details page 2023-12-31 16:41:59 +08:00
68ea8f439d feat: configurable page title 2023-12-31 16:36:21 +08:00
3 changed files with 48 additions and 19 deletions

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { Card, Col, Row, Tabs, TabsProps, Tooltip } from "antd"; import { Card, Col, Empty, Row, Tabs, TabsProps, Tooltip, Typography } from "antd";
import { PrismAsync } from "react-syntax-highlighter"; import { PrismAsync } from "react-syntax-highlighter";
import { oneLight } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { oneLight } from "react-syntax-highlighter/dist/cjs/styles/prism";
@ -11,6 +11,8 @@ import { DetailsResp } from "../api/problem.ts";
import { ProblemLoader } from "../api/loader.ts"; import { ProblemLoader } from "../api/loader.ts";
import { StatusApi, StatusInfo, Verdict } from "../api/status.ts"; import { StatusApi, StatusInfo, Verdict } from "../api/status.ts";
const { Title, Paragraph } = Typography;
const VerdictMap: { const VerdictMap: {
[key in Verdict]: { color: string; label: string; name: string }; [key in Verdict]: { color: string; label: string; name: string };
} = { } = {
@ -70,21 +72,31 @@ export default function DetailsPage() {
}).then(setDetails); }).then(setDetails);
}, [status]); }, [status]);
const taskInfo = ( const taskInfo =
<Card style={{ padding: "1em" }}> status?.context === undefined ? (
{status?.context?.tasks?.map((task) => ( <Empty
<Card.Grid key={task.id} style={{ ...gridStyle, background: VerdictMap[task.verdict].color }}> description={
<Tooltip title={task.message} color="#2E3D89"> <Typography>
<div style={topLeftStyle}>{`#${task.id}`}</div> <Title level={4}>Waiting for Judge...</Title>
<div> <Paragraph>Please refresh the page after a few seconds.</Paragraph>
<div style={labelStyle}>{VerdictMap[task.verdict].label}</div> </Typography>
<div style={statusStyle}>{`${task.real_time}ms/${task.memory}KB`}</div> }
</div> />
</Tooltip> ) : (
</Card.Grid> <Card style={{ padding: "1em" }}>
))} {status?.context?.tasks?.map((task) => (
</Card> <Card.Grid key={task.id} style={{ ...gridStyle, background: VerdictMap[task.verdict].color }}>
); <Tooltip title={task.message} color="#2E3D89">
<div style={topLeftStyle}>{`#${task.id}`}</div>
<div>
<div style={labelStyle}>{VerdictMap[task.verdict].label}</div>
<div style={statusStyle}>{`${task.real_time}ms/${task.memory}KB`}</div>
</div>
</Tooltip>
</Card.Grid>
))}
</Card>
);
const sourceCode = ( const sourceCode = (
<PrismAsync <PrismAsync
@ -133,7 +145,12 @@ export default function DetailsPage() {
<> <>
<Row justify="center" align="top" gutter={[16, 16]}> <Row justify="center" align="top" gutter={[16, 16]}>
<Col flex={6}>{body}</Col> <Col flex={6}>{body}</Col>
<Col flex={1}>{details && <ProblemDetails details={details} />}</Col> {details && (
<Col flex={1}>
{" "}
<ProblemDetails details={details} />
</Col>
)}
</Row> </Row>
</> </>
); );

View File

@ -16,7 +16,7 @@ const LayoutProps: ProLayoutProps = {
layout: "top", layout: "top",
route: { route: {
path: "/", path: "/",
routes: NavConfigs.map((c) => { routes: NavConfigs.filter((c) => c.show).map((c) => {
return { return {
path: c.to, path: c.to,
name: c.label, name: c.label,
@ -64,6 +64,9 @@ export default function Root() {
const curTab = NavConfigs.filter((c) => c.regex.test(location.pathname)) const curTab = NavConfigs.filter((c) => c.regex.test(location.pathname))
.map((c) => c.to) .map((c) => c.to)
.concat("/home")[0]; .concat("/home")[0];
const title = NavConfigs.filter((c) => c.regex.test(location.pathname))
.map((c) => c.label)
.concat("Home")[0];
useEffect( useEffect(
() => { () => {
@ -115,7 +118,7 @@ export default function Root() {
return ( return (
<ProLayout {...LayoutProps} location={{ pathname: curTab }} avatarProps={avatarProps}> <ProLayout {...LayoutProps} location={{ pathname: curTab }} avatarProps={avatarProps}>
{msgContextHolder} {msgContextHolder}
<PageContainer> <PageContainer title={title}>
<React.Suspense fallback={<Skeleton />}> <React.Suspense fallback={<Skeleton />}>
<Outlet /> <Outlet />
</React.Suspense> </React.Suspense>

View File

@ -96,6 +96,7 @@ const NavConfigs = [
label: "Home", label: "Home",
icon: <HomeOutlined />, icon: <HomeOutlined />,
regex: /^\/$|^\/home$/i, regex: /^\/$|^\/home$/i,
show: true,
}, },
{ {
key: "problem", key: "problem",
@ -103,6 +104,7 @@ const NavConfigs = [
label: "Problem", label: "Problem",
icon: <QuestionCircleOutlined />, icon: <QuestionCircleOutlined />,
regex: /^\/+(problem|search)($|\/.*)/i, regex: /^\/+(problem|search)($|\/.*)/i,
show: true,
}, },
{ {
key: "profile", key: "profile",
@ -110,6 +112,13 @@ const NavConfigs = [
label: "Profile", label: "Profile",
icon: <ProfileOutlined />, icon: <ProfileOutlined />,
regex: /^\/profile($|\/.*)/i, regex: /^\/profile($|\/.*)/i,
show: true,
},
{
key: "details",
label: "Details",
regex: /^\/details\/\d+$/i,
show: false,
}, },
]; ];