From dbd026e0f038fccdcff98f19f3a4b8a349307661 Mon Sep 17 00:00:00 2001 From: KanadeSiina Date: Mon, 19 Feb 2024 03:37:52 +0000 Subject: [PATCH 1/6] Prepare for submission detail --- src/api/submission.ts | 9 ++++ src/components/SubmissionDetail.tsx | 18 +++++++ src/hooks/submission.ts | 19 ++++++++ src/mocks/handlers.ts | 3 +- src/mocks/rest/submission.ts | 74 +++++++++++++++++------------ src/pages/Submission.tsx | 19 ++++++++ src/routes/Router.tsx | 2 + 7 files changed, 113 insertions(+), 31 deletions(-) create mode 100644 src/components/SubmissionDetail.tsx create mode 100644 src/pages/Submission.tsx diff --git a/src/api/submission.ts b/src/api/submission.ts index d66c336fc..783094cae 100644 --- a/src/api/submission.ts +++ b/src/api/submission.ts @@ -12,4 +12,13 @@ export namespace SubmissionService { } return res.data; } + export async function getSubmission(uid: string) { + let res = await client.get<{ + data: SubmissionServiceModel.SubmissionInfo + }>(`/api/v1/submission/${uid}`); + if (res.status !== 200) { + throw Error("failed to get submission detail"); + } + return res.data; + } } diff --git a/src/components/SubmissionDetail.tsx b/src/components/SubmissionDetail.tsx new file mode 100644 index 000000000..ccb696187 --- /dev/null +++ b/src/components/SubmissionDetail.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { SubmissionServiceModel } from "../typings/submission"; + +export interface SubmissionDetailProps { + data?: SubmissionServiceModel.SubmissionInfo; + className?: string; +} + +const SubmissionDetail: React.FC = (props) => { + + return ( +
+ {props.data?props.data.uid:""} +
+ ); +}; + +export default SubmissionDetail; diff --git a/src/hooks/submission.ts b/src/hooks/submission.ts index 80b0d1e52..dd2cc9d55 100644 --- a/src/hooks/submission.ts +++ b/src/hooks/submission.ts @@ -23,3 +23,22 @@ export const useSubmissionList = () => { return { getSubmissionList }; }; + +export const useSubmission = (uid: string) => { + const [submission, setSubmission] = useState(); + useEffect(() => { + SubmissionService.getSubmission(uid) + .then((res) => { + setSubmission(res.data) + }) + .catch((err) => { + console.log(err); + }); + }, [uid]); + + function getSubmission() { + return submission; + } + + return { getSubmission }; +} diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 5b0c1492c..988718f58 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -7,7 +7,7 @@ import { deleteProblem, putProblemPackage, } from "./rest/problem"; -import { getSubmissionInfoList } from "./rest/submission"; +import { getSubmissionInfoList, getSubmissionInfo } from "./rest/submission"; import { getCurrentUser, postLogin } from "./rest/user"; export const restHandlers = [ @@ -17,6 +17,7 @@ export const restHandlers = [ getProblemInfo, getProblemInfoList, getSubmissionInfoList, + getSubmissionInfo, checkProblemSlug, putProblemPackage, deleteProblem, diff --git a/src/mocks/rest/submission.ts b/src/mocks/rest/submission.ts index 94561bf3e..38b8b76bc 100644 --- a/src/mocks/rest/submission.ts +++ b/src/mocks/rest/submission.ts @@ -1,42 +1,56 @@ import { http } from "msw"; import { SubmissionServiceModel } from "../../typings/submission"; +const submissions:SubmissionServiceModel.SubmissionInfo[] = [ + { + uid: "1", + user: { + account: "user-1", + name: "User 1", + }, + problem: { + slug: "hello-world", + title: "Hello World", + tags: ["Primer"], + }, + language: "C++", + status: "finished", + }, + { + uid: "2", + user: { + account: "user-2", + name: "User 2", + }, + problem: { + slug: "a-plus-b-problem", + title: "A + B Problem", + tags: ["Primer"], + }, + language: "C++", + status: "wrong answer", + }, +]; + export const getSubmissionInfoList = http.get("/api/v1/submission", (info) => { const response: { total: number; list: SubmissionServiceModel.SubmissionInfo[]; } = { total: 2, - list: [ - { - uid: "1", - user: { - account: "user-1", - name: "User 1", - }, - problem: { - slug: "hello-world", - title: "Hello World", - tags: ["Primer"], - }, - language: "C++", - status: "finished", - }, - { - uid: "2", - user: { - account: "user-2", - name: "User 2", - }, - problem: { - slug: "a-plus-b-problem", - title: "A + B Problem", - tags: ["Primer"], - }, - language: "C++", - status: "wrong answer", - }, - ], + list: submissions, + }; + return new Response(JSON.stringify(response), { + status: 200, + }); +}); + +export const getSubmissionInfo = http.get("/api/v1/submission/:uid", ( { params }) => { + const { uid } = params; + const response: { + data: SubmissionServiceModel.SubmissionInfo; + } = { + data: submissions[+uid-1] }; return new Response(JSON.stringify(response), { status: 200, diff --git a/src/pages/Submission.tsx b/src/pages/Submission.tsx new file mode 100644 index 000000000..78bbcb97b --- /dev/null +++ b/src/pages/Submission.tsx @@ -0,0 +1,19 @@ +import { useSubmission } from "../hooks/submission"; +import UserLayout from "../layouts/userLayout/UserLayout"; +import { useParams } from "react-router-dom"; +import SubmissionDetail from "../components/SubmissionDetail"; + +const Submission: React.FC = () => { + const uid = useParams().uid as string; + const { getSubmission } = useSubmission(uid); + + return ( + + + + ); +}; + +export default Submission; diff --git a/src/routes/Router.tsx b/src/routes/Router.tsx index 411c0014e..5a2c8e380 100644 --- a/src/routes/Router.tsx +++ b/src/routes/Router.tsx @@ -6,6 +6,7 @@ import { default as AdminCreateProblem } from "../pages/admin-dashboard/CreatePr import AdminLayout from "../layouts/adminLayout/AdminLayout"; import ProblemList from "../pages/ProblemList"; import SubmissionList from "../pages/SubmissionList"; +import Submission from "../pages/Submission"; const PageRouter: React.FC = () => { return ( @@ -22,6 +23,7 @@ const PageRouter: React.FC = () => { user} /> } /> + } /> From 2c37721a7af2b37a426e60806ce4766bdc479cdc Mon Sep 17 00:00:00 2001 From: KanadeSiina Date: Mon, 19 Feb 2024 17:42:30 +0000 Subject: [PATCH 2/6] Unpack submission detail --- src/api/submission.ts | 4 +--- src/hooks/submission.ts | 2 +- src/mocks/rest/submission.ts | 6 +----- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/api/submission.ts b/src/api/submission.ts index 783094cae..1a6966e1b 100644 --- a/src/api/submission.ts +++ b/src/api/submission.ts @@ -13,9 +13,7 @@ export namespace SubmissionService { return res.data; } export async function getSubmission(uid: string) { - let res = await client.get<{ - data: SubmissionServiceModel.SubmissionInfo - }>(`/api/v1/submission/${uid}`); + let res = await client.get(`/api/v1/submission/${uid}`); if (res.status !== 200) { throw Error("failed to get submission detail"); } diff --git a/src/hooks/submission.ts b/src/hooks/submission.ts index dd2cc9d55..0dcde865c 100644 --- a/src/hooks/submission.ts +++ b/src/hooks/submission.ts @@ -29,7 +29,7 @@ export const useSubmission = (uid: string) => { useEffect(() => { SubmissionService.getSubmission(uid) .then((res) => { - setSubmission(res.data) + setSubmission(res) }) .catch((err) => { console.log(err); diff --git a/src/mocks/rest/submission.ts b/src/mocks/rest/submission.ts index 38b8b76bc..16369b1c4 100644 --- a/src/mocks/rest/submission.ts +++ b/src/mocks/rest/submission.ts @@ -47,11 +47,7 @@ export const getSubmissionInfoList = http.get("/api/v1/submission", (info) => { export const getSubmissionInfo = http.get("/api/v1/submission/:uid", ( { params }) => { const { uid } = params; - const response: { - data: SubmissionServiceModel.SubmissionInfo; - } = { - data: submissions[+uid-1] - }; + const response: SubmissionServiceModel.SubmissionInfo = submissions[+uid-1]; return new Response(JSON.stringify(response), { status: 200, }); From 618b31d3fe21f61bd49ad831d9263b40a6feae2c Mon Sep 17 00:00:00 2001 From: KanadeSiina Date: Mon, 19 Feb 2024 17:44:36 +0000 Subject: [PATCH 3/6] Prettier code --- src/api/submission.ts | 4 +++- src/components/SubmissionDetail.tsx | 5 +---- src/hooks/submission.ts | 11 ++++++----- src/mocks/rest/submission.ts | 20 ++++++++++++-------- src/pages/Submission.tsx | 4 +--- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/api/submission.ts b/src/api/submission.ts index 1a6966e1b..dcfb40a04 100644 --- a/src/api/submission.ts +++ b/src/api/submission.ts @@ -13,7 +13,9 @@ export namespace SubmissionService { return res.data; } export async function getSubmission(uid: string) { - let res = await client.get(`/api/v1/submission/${uid}`); + let res = await client.get( + `/api/v1/submission/${uid}`, + ); if (res.status !== 200) { throw Error("failed to get submission detail"); } diff --git a/src/components/SubmissionDetail.tsx b/src/components/SubmissionDetail.tsx index ccb696187..607ad44bc 100644 --- a/src/components/SubmissionDetail.tsx +++ b/src/components/SubmissionDetail.tsx @@ -7,11 +7,8 @@ export interface SubmissionDetailProps { } const SubmissionDetail: React.FC = (props) => { - return ( -
- {props.data?props.data.uid:""} -
+
{props.data ? props.data.uid : ""}
); }; diff --git a/src/hooks/submission.ts b/src/hooks/submission.ts index 0dcde865c..ade404438 100644 --- a/src/hooks/submission.ts +++ b/src/hooks/submission.ts @@ -25,20 +25,21 @@ export const useSubmissionList = () => { }; export const useSubmission = (uid: string) => { - const [submission, setSubmission] = useState(); + const [submission, setSubmission] = + useState(); useEffect(() => { SubmissionService.getSubmission(uid) .then((res) => { - setSubmission(res) + setSubmission(res); }) .catch((err) => { console.log(err); }); }, [uid]); - + function getSubmission() { return submission; } - + return { getSubmission }; -} +}; diff --git a/src/mocks/rest/submission.ts b/src/mocks/rest/submission.ts index 16369b1c4..787c1ae3d 100644 --- a/src/mocks/rest/submission.ts +++ b/src/mocks/rest/submission.ts @@ -1,7 +1,7 @@ import { http } from "msw"; import { SubmissionServiceModel } from "../../typings/submission"; -const submissions:SubmissionServiceModel.SubmissionInfo[] = [ +const submissions: SubmissionServiceModel.SubmissionInfo[] = [ { uid: "1", user: { @@ -45,10 +45,14 @@ export const getSubmissionInfoList = http.get("/api/v1/submission", (info) => { }); }); -export const getSubmissionInfo = http.get("/api/v1/submission/:uid", ( { params }) => { - const { uid } = params; - const response: SubmissionServiceModel.SubmissionInfo = submissions[+uid-1]; - return new Response(JSON.stringify(response), { - status: 200, - }); -}); +export const getSubmissionInfo = http.get( + "/api/v1/submission/:uid", + ({ params }) => { + const { uid } = params; + const response: SubmissionServiceModel.SubmissionInfo = + submissions[+uid - 1]; + return new Response(JSON.stringify(response), { + status: 200, + }); + }, +); diff --git a/src/pages/Submission.tsx b/src/pages/Submission.tsx index 78bbcb97b..485b9f393 100644 --- a/src/pages/Submission.tsx +++ b/src/pages/Submission.tsx @@ -9,9 +9,7 @@ const Submission: React.FC = () => { return ( - + ); }; From 9a4cb73cf83abd6dd2487bee15b91763472e8c10 Mon Sep 17 00:00:00 2001 From: KanadeSiina Date: Tue, 20 Feb 2024 17:00:48 +0000 Subject: [PATCH 4/6] Add code for submission detail --- package-lock.json | 244 ++++++++++++++++++++++++++++ package.json | 2 + src/components/SubmissionDetail.tsx | 42 ++++- src/mocks/rest/submission.ts | 6 +- src/typings/submission.ts | 1 + 5 files changed, 291 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 230472a9c..358861b53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "react-markdown": "^8.0.7", "react-redux": "^8.0.4", "react-router-dom": "^6.4.2", + "react-syntax-highlighter": "^15.5.0", "redux": "^4.2.0", "redux-logger": "^3.0.6", "redux-saga": "^1.2.1", @@ -43,6 +44,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.10", + "@types/react-syntax-highlighter": "^15.5.11", "@types/redux-logger": "^3.0.9", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.15", @@ -4041,6 +4043,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-syntax-highlighter": { + "version": "15.5.11", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.11.tgz", + "integrity": "sha512-ZqIJl+Pg8kD+47kxUjvrlElrraSUrYa4h0dauY/U/FTUuprSCqvUj+9PNQNQzVc6AJgIWUUxn87/gqsMHNbRjw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", @@ -5148,6 +5159,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -6532,6 +6561,18 @@ "reusify": "^1.0.4" } }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -6690,6 +6731,14 @@ "node": ">= 6" } }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -7154,6 +7203,14 @@ "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.2.tgz", "integrity": "sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw==" }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -7373,6 +7430,28 @@ "node": ">= 0.4" } }, + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -7518,6 +7597,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -7572,6 +7660,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -8146,6 +8243,19 @@ "loose-envify": "cli.js" } }, + "node_modules/lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -9225,6 +9335,32 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9651,6 +9787,14 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9874,6 +10018,21 @@ "react-dom": ">=16.8" } }, + "node_modules/react-syntax-highlighter": { + "version": "15.5.0", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz", + "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==", + "dependencies": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.4.1", + "lowlight": "^1.17.0", + "prismjs": "^1.27.0", + "refractor": "^3.6.0" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -9988,6 +10147,83 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/refractor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.27.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/refractor/node_modules/prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/refractor/node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -11803,6 +12039,14 @@ "node": ">=0.1" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 7115b64ba..1ec57b368 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "react-markdown": "^8.0.7", "react-redux": "^8.0.4", "react-router-dom": "^6.4.2", + "react-syntax-highlighter": "^15.5.0", "redux": "^4.2.0", "redux-logger": "^3.0.6", "redux-saga": "^1.2.1", @@ -68,6 +69,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.10", + "@types/react-syntax-highlighter": "^15.5.11", "@types/redux-logger": "^3.0.9", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.15", diff --git a/src/components/SubmissionDetail.tsx b/src/components/SubmissionDetail.tsx index 607ad44bc..45e1231fb 100644 --- a/src/components/SubmissionDetail.tsx +++ b/src/components/SubmissionDetail.tsx @@ -1,4 +1,6 @@ import React from "react"; +import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; +import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { SubmissionServiceModel } from "../typings/submission"; export interface SubmissionDetailProps { @@ -7,8 +9,44 @@ export interface SubmissionDetailProps { } const SubmissionDetail: React.FC = (props) => { - return ( -
{props.data ? props.data.uid : ""}
+ if (props && props.data) + console.log("lang", props.data.language.toLowerCase()); + return props.data ? ( +
+
+ + {/* head */} + + + + + + + + + + + + + + + + +
uidsluglanguagestatus
{props.data.uid}{props.data.problem.slug}{props.data.language}{props.data.status}
+
+ + {props.data.code} + +
+ ) : ( +
); }; diff --git a/src/mocks/rest/submission.ts b/src/mocks/rest/submission.ts index 787c1ae3d..22f527279 100644 --- a/src/mocks/rest/submission.ts +++ b/src/mocks/rest/submission.ts @@ -13,7 +13,8 @@ const submissions: SubmissionServiceModel.SubmissionInfo[] = [ title: "Hello World", tags: ["Primer"], }, - language: "C++", + language: "Cpp", + code: "#include\nusing namespace std;\nint main()\n{}\n", status: "finished", }, { @@ -27,7 +28,8 @@ const submissions: SubmissionServiceModel.SubmissionInfo[] = [ title: "A + B Problem", tags: ["Primer"], }, - language: "C++", + language: "Cpp", + code: "#include\nusing namespace std;\nint main()\n{}\n", status: "wrong answer", }, ]; diff --git a/src/typings/submission.ts b/src/typings/submission.ts index 2f1b40d0d..835ee4697 100644 --- a/src/typings/submission.ts +++ b/src/typings/submission.ts @@ -7,6 +7,7 @@ export namespace SubmissionServiceModel { user: UserServiceModel.UserInfo; problem: ProblemServiceModel.ProblemInfo; language: string; + code: string; status: string; } } From a4733aa9daf126c8ec8bda899187ef34ce1196f5 Mon Sep 17 00:00:00 2001 From: KanadeSiina Date: Thu, 22 Feb 2024 09:29:13 +0000 Subject: [PATCH 5/6] Add copy button --- package-lock.json | 36 ++++++++++++++++++++++ package.json | 2 ++ src/components/SubmissionDetail.tsx | 46 +++++++++++++++++++++-------- 3 files changed, 72 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 358861b53..b6072cc6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "monaco-editor": "^0.39.0", "msw": "^2.1.7", "react": "^18.2.0", + "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", "react-i18next": "^13.2.2", "react-markdown": "^8.0.7", @@ -44,6 +45,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.10", + "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-syntax-highlighter": "^15.5.11", "@types/redux-logger": "^3.0.9", "@vitejs/plugin-react": "^4.2.1", @@ -4035,6 +4037,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-copy-to-clipboard": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", + "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.2.18", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", @@ -5366,6 +5377,14 @@ "node": ">= 0.6" } }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js-compat": { "version": "3.35.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.1.tgz", @@ -9873,6 +9892,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -11196,6 +11227,11 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, "node_modules/tough-cookie": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", diff --git a/package.json b/package.json index 1ec57b368..2715bc686 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "monaco-editor": "^0.39.0", "msw": "^2.1.7", "react": "^18.2.0", + "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.2.0", "react-i18next": "^13.2.2", "react-markdown": "^8.0.7", @@ -69,6 +70,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.10", + "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-syntax-highlighter": "^15.5.11", "@types/redux-logger": "^3.0.9", "@vitejs/plugin-react": "^4.2.1", diff --git a/src/components/SubmissionDetail.tsx b/src/components/SubmissionDetail.tsx index 45e1231fb..d0a324aaf 100644 --- a/src/components/SubmissionDetail.tsx +++ b/src/components/SubmissionDetail.tsx @@ -2,6 +2,8 @@ import React from "react"; import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { SubmissionServiceModel } from "../typings/submission"; +import { CopyToClipboard } from "react-copy-to-clipboard"; +import DocumentDuplicateIcon from "@heroicons/react/24/outline/DocumentDuplicateIcon"; export interface SubmissionDetailProps { data?: SubmissionServiceModel.SubmissionInfo; @@ -9,8 +11,7 @@ export interface SubmissionDetailProps { } const SubmissionDetail: React.FC = (props) => { - if (props && props.data) - console.log("lang", props.data.language.toLowerCase()); + const [copyTip, setCopyTip] = React.useState("Copy code"); return props.data ? (
@@ -34,16 +35,37 @@ const SubmissionDetail: React.FC = (props) => {
- - {props.data.code} - +
+ + + {props.data.code} + +
) : (
From 99ab4d44092faa531ca30a7820f39fcafce18145 Mon Sep 17 00:00:00 2001 From: slhmy <1484836413@qq.com> Date: Thu, 22 Feb 2024 13:39:52 +0000 Subject: [PATCH 6/6] Perf Submission styles --- src/components/SubmissionDetail.tsx | 29 ++++++++++++++++++++--------- src/components/SubmissionTable.tsx | 14 +------------- src/utils/color.ts | 12 ++++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 src/utils/color.ts diff --git a/src/components/SubmissionDetail.tsx b/src/components/SubmissionDetail.tsx index d0a324aaf..ee188664e 100644 --- a/src/components/SubmissionDetail.tsx +++ b/src/components/SubmissionDetail.tsx @@ -4,6 +4,8 @@ import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { SubmissionServiceModel } from "../typings/submission"; import { CopyToClipboard } from "react-copy-to-clipboard"; import DocumentDuplicateIcon from "@heroicons/react/24/outline/DocumentDuplicateIcon"; +import { joinClasses } from "@/utils/common"; +import { getBadgeColorClasses } from "@/utils/color"; export interface SubmissionDetailProps { data?: SubmissionServiceModel.SubmissionInfo; @@ -14,23 +16,32 @@ const SubmissionDetail: React.FC = (props) => { const [copyTip, setCopyTip] = React.useState("Copy code"); return props.data ? (
-
+
{/* head */} - - - - + + + + - - - - + + + +
uidsluglanguagestatusUIDSLUGLANGUAGESTATUS
{props.data.uid}{props.data.problem.slug}{props.data.language}{props.data.status}{props.data.uid}{props.data.problem.slug}{props.data.language} +
+ {props.data.status} +
+
diff --git a/src/components/SubmissionTable.tsx b/src/components/SubmissionTable.tsx index f0967d721..77e86edb2 100644 --- a/src/components/SubmissionTable.tsx +++ b/src/components/SubmissionTable.tsx @@ -2,6 +2,7 @@ import React from "react"; import { useNavigate } from "react-router-dom"; import { joinClasses } from "../utils/common"; import { SubmissionServiceModel } from "../typings/submission"; +import { getBadgeColorClasses } from "@/utils/color"; const columns = [ { name: "PROBLEM", uid: "problem" }, @@ -17,19 +18,6 @@ export interface SubmissionTableProps { className?: string; } -function getBadgeColorClasses(status: string): string { - switch (status) { - case "finished": - return "badge-success"; - case "pending": - return "badge-warning"; - case "wrong answer": - return "badge-error"; - default: - return ""; - } -} - const SubmissionTable: React.FC = (props) => { const navigate = useNavigate(); diff --git a/src/utils/color.ts b/src/utils/color.ts new file mode 100644 index 000000000..613cd8818 --- /dev/null +++ b/src/utils/color.ts @@ -0,0 +1,12 @@ +export function getBadgeColorClasses(status: string): string { + switch (status) { + case "finished": + return "badge-success"; + case "pending": + return "badge-warning"; + case "wrong answer": + return "badge-error"; + default: + return ""; + } +}