Compare commits

...

4 Commits

Author SHA1 Message Date
9c850a27bc feat: add GitHub Action 2023-12-31 14:12:57 +08:00
0c412f5bae feat: pagination on search page 2023-12-27 22:22:46 +08:00
e36c386805 feat: add tags support 2023-12-27 21:59:32 +08:00
e8a4ecaccb feat: ProTable scroll 2023-12-27 21:40:40 +08:00
5 changed files with 89 additions and 17 deletions

39
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,39 @@
name: Docker Image CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Docker Login
uses: docker/login-action@v3.0.0
with:
registry: git.0x7f.app
username: Paul
password: ${{ secrets.GITEA_DOCKER_TOKEN }}
- name: PNPM Build Cache
uses: actions/cache@v3
with:
path: pnpm-build-cache
key: ${{ runner.os }}-pnpm-build-cache-${{ hashFiles('pnpm-lock.yaml') }}
- name: inject go-build-cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2.1.3
with:
cache-source: pnpm-build-cache
- name: Build And Push
uses: docker/build-push-action@v5.1.0
with:
push: ${{ github.event_name != 'pull_request' }}
cache-from: type=gha
cache-to: type=gha,mode=max
tags: git.0x7f.app/woj/woj-ui:1.0.0
secrets: |
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}

View File

@ -1,4 +1,4 @@
import { Meta, send } from "./base.ts"; import { Meta, send, WithCount } from "./base.ts";
import { UserProfile } from "./user.ts"; import { UserProfile } from "./user.ts";
export interface TaskInfo { export interface TaskInfo {
@ -15,6 +15,7 @@ export interface ProblemInfo {
meta: Meta; meta: Meta;
title: string; title: string;
statement: string; statement: string;
tags: { Elements: string[] };
provider: UserProfile; provider: UserProfile;
is_enabled: boolean; is_enabled: boolean;
} }
@ -34,13 +35,17 @@ export interface DetailsResp {
} }
export interface SearchReq { export interface SearchReq {
search: string; keyword: string;
tag: string;
offset?: number;
limit: number;
} }
export interface UpdateReq { export interface UpdateReq {
pid: number; pid: number;
title: string; title: string;
statement: string; statement: string;
tags: string[];
is_enabled: boolean; is_enabled: boolean;
} }
@ -58,7 +63,7 @@ export class ProblemApi {
return send("/problem/details", data); return send("/problem/details", data);
} }
static async Search(data: SearchReq): Promise<ProblemInfo[]> { static async Search(data: SearchReq): Promise<WithCount<ProblemInfo>> {
return send("/problem/search", data); return send("/problem/search", data);
} }

View File

@ -27,6 +27,11 @@ export default function ProblemDetails(props: ProblemDetailsProps) {
))} ))}
</Space> </Space>
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="Tags">
{details.problem.tags.Elements.map((tag) => {
return <Tag key={tag}>{tag}</Tag>;
})}
</Descriptions.Item>
<Descriptions.Item label="Task Nums">{details.context.Tasks.length}</Descriptions.Item> <Descriptions.Item label="Task Nums">{details.context.Tasks.length}</Descriptions.Item>
</Descriptions> </Descriptions>
); );

View File

@ -121,10 +121,9 @@ export default function StatusTable(props: StatusTableProps) {
columns={columns} columns={columns}
request={request} request={request}
rowKey={(record) => record.id} rowKey={(record) => record.id}
pagination={{ pagination={{ pageSize: 10 }}
pageSize: 10,
}}
search={false} search={false}
scroll={{ x: "max-content" }}
dateFormatter="string" dateFormatter="string"
headerTitle={props.title || "Judge Status"} headerTitle={props.title || "Judge Status"}
/> />

View File

@ -1,13 +1,14 @@
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { ProColumns, ProTable } from "@ant-design/pro-components"; import { ProColumns, ProTable } from "@ant-design/pro-components";
import { Button, Space } from "antd"; import { Button, Space, Tag } from "antd";
import { ProblemApi } from "../api/problem.ts"; import { ProblemApi } from "../api/problem.ts";
interface ProblemList { interface ProblemList {
id: number; id: number;
title: string; title: string;
tags: string[];
provider: string; provider: string;
} }
@ -23,6 +24,20 @@ const columns: ProColumns<ProblemList>[] = [
dataIndex: "title", dataIndex: "title",
align: "left", align: "left",
}, },
{
title: "Tags",
dataIndex: "tags",
align: "left",
render: (_node, entity) => {
return (
<Space>
{entity.tags.map((tag) => {
return <Tag key={tag}>{tag}</Tag>;
})}
</Space>
);
},
},
{ {
title: "Provider", title: "Provider",
hideInSearch: true, hideInSearch: true,
@ -50,19 +65,32 @@ const columns: ProColumns<ProblemList>[] = [
]; ];
export default function SearchPage() { export default function SearchPage() {
const request = async (params: Record<string, string>) => { const request = async (
params: Record<string, string> & {
pageSize?: number;
current?: number;
keyword?: string | undefined;
},
) => {
try { try {
const cur = params.current || 1;
const size = params.pageSize || 10;
const info = await ProblemApi.Search({ const info = await ProblemApi.Search({
search: params.title || "", keyword: params.title || "",
tag: params.tags || "",
offset: (cur - 1) * (size || 10),
limit: size,
}); });
const data = info.map((i) => { const data = info.data.map((i) => {
return { return {
id: i.meta.ID, id: i.meta.ID,
title: i.title, title: i.title,
tags: i.tags.Elements,
provider: i.provider.nick_name, provider: i.provider.nick_name,
}; };
}); });
return { success: true, data: data, total: data.length }; return { success: true, data: data, total: info.count };
} catch (e) { } catch (e) {
console.log(e); console.log(e);
return { success: false, data: [], total: 0 }; return { success: false, data: [], total: 0 };
@ -75,12 +103,8 @@ export default function SearchPage() {
columns={columns} columns={columns}
request={request} request={request}
rowKey={(record) => record.id} rowKey={(record) => record.id}
pagination={{ pagination={{ pageSize: 10 }}
pageSize: 10, scroll={{ x: "max-content" }}
}}
search={{
labelWidth: "auto",
}}
dateFormatter="string" dateFormatter="string"
headerTitle="Problem Lists" headerTitle="Problem Lists"
/> />