diff --git a/index.html b/index.html index 0057fce..36372a6 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,19 @@ - + - - - - - Grader - - -
- - + + + + + + + + Grader + + +
+ + diff --git a/package-lock.json b/package-lock.json index 6c7462d..cea2139 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", + "@reduxjs/toolkit": "^2.6.1", "@tanstack/react-table": "^8.11.6", "@udecode/plate-alignment": "^24.5.2", "@udecode/plate-autoformat": "^24.5.2", @@ -88,6 +89,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.47.0", "react-lite-youtube-embed": "^2.3.52", + "react-redux": "^9.2.0", "react-resizable-panels": "^1.0.7", "react-router-dom": "^6.15.0", "react-sortablejs": "^6.1.4", @@ -97,6 +99,7 @@ "styled-components": "^6.1.1", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", + "use-debounce": "^10.0.4", "zod": "^3.22.4" }, "devDependencies": { @@ -2078,6 +2081,46 @@ "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, + "node_modules/@reduxjs/toolkit": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.1.tgz", + "integrity": "sha512-SSlIqZNYhqm/oMkXbtofwZSt9lrncblzo6YcZ9zoX+zLngRBrCOjK4lNLdkNucJF58RHOWrD9txT3bT3piH7Zw==", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/@reduxjs/toolkit/node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/@remix-run/router": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.8.0.tgz", @@ -2370,13 +2413,12 @@ "devOptional": true }, "node_modules/@types/react": { - "version": "18.2.21", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", - "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", + "version": "18.3.20", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", + "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", "devOptional": true, "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, @@ -2389,12 +2431,6 @@ "@types/react": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", - "devOptional": true - }, "node_modules/@types/semver": { "version": "7.5.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", @@ -2416,6 +2452,11 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.9.tgz", "integrity": "sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==" }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz", @@ -4419,6 +4460,14 @@ "redux": "^4.2.0" } }, + "node_modules/dnd-core/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -6242,6 +6291,28 @@ "react-dom": "^16.8.0 || ^17 || ^18" } }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -6487,12 +6558,9 @@ } }, "node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", - "dependencies": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/regenerator-runtime": { "version": "0.14.0", @@ -6511,6 +6579,11 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" + }, "node_modules/resolve": { "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", @@ -7200,6 +7273,17 @@ } } }, + "node_modules/use-debounce": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.4.tgz", + "integrity": "sha512-6Cf7Yr7Wk7Kdv77nnJMf6de4HuDE4dTxKij+RqE9rufDsI6zsbjyAxcH5y2ueJCQAnfgKbzXbZHYlkFwmBlWkw==", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/use-deep-compare": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/use-deep-compare/-/use-deep-compare-1.1.0.tgz", @@ -7262,11 +7346,11 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/util-deprecate": { diff --git a/package.json b/package.json index 36f45e2..5a2b6f7 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", + "@reduxjs/toolkit": "^2.6.1", "@tanstack/react-table": "^8.11.6", "@udecode/plate-alignment": "^24.5.2", "@udecode/plate-autoformat": "^24.5.2", @@ -90,6 +91,7 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.47.0", "react-lite-youtube-embed": "^2.3.52", + "react-redux": "^9.2.0", "react-resizable-panels": "^1.0.7", "react-router-dom": "^6.15.0", "react-sortablejs": "^6.1.4", @@ -99,6 +101,7 @@ "styled-components": "^6.1.1", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", + "use-debounce": "^10.0.4", "zod": "^3.22.4" }, "devDependencies": { diff --git a/src/components/Cards/ProblemCards/MyProblemMiniCard2.tsx b/src/components/Cards/ProblemCards/MyProblemMiniCard2.tsx index ace444a..3bba6b4 100644 --- a/src/components/Cards/ProblemCards/MyProblemMiniCard2.tsx +++ b/src/components/Cards/ProblemCards/MyProblemMiniCard2.tsx @@ -1,8 +1,8 @@ -import { FileSpreadsheet } from "lucide-react"; +import { FileSpreadsheet, Pencil, X } from "lucide-react"; import { useState } from "react"; import { - ProblemModel, - ProblemPopulateTestcases + ProblemModel, + ProblemPopulateTestcases, } from "../../../types/models/Problem.model"; import { onMiddleClickOpenInNewTab } from "../../../utilities/OnMiddleClickOpenInNewTab"; import MyProblemContextMenu from "../../ContextMenus/MyProblemContextMenu"; @@ -13,11 +13,15 @@ const MyProblemMiniCard2 = ({ disabled = false, disabledHighlight = false, onClick = () => {}, + onClickPencilIcon, + onClickXIcon, }: { problem: ProblemPopulateTestcases | ProblemModel; disabled?: boolean; disabledHighlight?: boolean; onClick?: () => void; + onClickPencilIcon?: () => void; + onClickXIcon?: () => void; }) => { const [highlightTitle, setHighlightTitle] = useState(false); @@ -58,55 +62,34 @@ const MyProblemMiniCard2 = ({ // className={`pt-6 px-5 ${disabled ? "opacity-50" : }`}`} > -
+
- -

- {problem.title} -

-
- {/*
- -
{problem.testcases.length}
+ +

+ {problem.title} +

-
- - SC - - 0} - > - TC - - - NRE - + +
+ {onClickPencilIcon && ( + + )} + {onClickXIcon && ( + + )}
-
- {problem.allowed_languages - .split(",") - .map((lang, index) => { - if (index < 3) { - return ProgrammingLanguageOptions.find( - (option) => option.value === lang - )?.badge; - } else if (index === 3) { - return ...; - } - })} -
*/}
diff --git a/src/components/ContextMenus/MyProblemContextMenu.tsx b/src/components/ContextMenus/MyProblemContextMenu.tsx index 3769102..038e1ff 100644 --- a/src/components/ContextMenus/MyProblemContextMenu.tsx +++ b/src/components/ContextMenus/MyProblemContextMenu.tsx @@ -36,7 +36,7 @@ const MyProblemContextMenu = ({ problem.problem_id ); - let createRequest = transformProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel2CreateProblemRequestForm( + const createRequest = transformProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel2CreateProblemRequestForm( response.data ) diff --git a/src/components/Dialogs/ProblemSubmissionSourceCodeAndRuntimeResultDialog.tsx b/src/components/Dialogs/ProblemSubmissionSourceCodeAndRuntimeResultDialog.tsx index fd4d7d8..3a2ef95 100644 --- a/src/components/Dialogs/ProblemSubmissionSourceCodeAndRuntimeResultDialog.tsx +++ b/src/components/Dialogs/ProblemSubmissionSourceCodeAndRuntimeResultDialog.tsx @@ -10,11 +10,11 @@ import { Separator } from "../shadcn/Seperator"; const ProblemSubmissionSourceCodeAndRuntimeResultDialog = ({ submission, children, - problem + problem, }: { submission: SubmissionPopulateSubmissionTestcaseAndAccountModel; children?: React.ReactNode; - problem: ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel + problem: ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel; }) => { const [sourceCode, setSourceCode] = React.useState( submission.submission_code @@ -44,10 +44,13 @@ const ProblemSubmissionSourceCodeAndRuntimeResultDialog = ({
({ - ...output, - input: problem.testcases[index]?.input - }))} + problem={problem} + runtimeResults={submission.runtime_output.map( + (output, index) => ({ + ...output, + input: problem.testcases[index]?.input, + }) + )} />
diff --git a/src/components/Dropdowns/MyProblemDropdown.tsx b/src/components/Dropdowns/MyProblemDropdown.tsx index a019e40..2161f4c 100644 --- a/src/components/Dropdowns/MyProblemDropdown.tsx +++ b/src/components/Dropdowns/MyProblemDropdown.tsx @@ -3,21 +3,21 @@ import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import { ProblemService } from "../../services/Problem.service"; import { transformCreateProblemRequestForm2CreateProblemRequest } from "../../types/adapters/CreateProblemRequestForm.adapter"; +import { transformProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel2CreateProblemRequestForm } from "../../types/adapters/Problem.adapter"; import { - ProblemModel, - ProblemPopulateTestcases, - ProblemSecureModel, + ProblemModel, + ProblemPopulateTestcases, + ProblemSecureModel, } from "../../types/models/Problem.model"; import DeleteProblemConfirmationDialog from "../Dialogs/DeleteProblemConfirmationDialog"; import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, } from "../shadcn/DropdownMenu"; import { toast } from "../shadcn/UseToast"; -import { transformProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel2CreateProblemRequestForm } from "../../types/adapters/Problem.adapter"; const MyProblemDropdown = ({ children, @@ -36,11 +36,12 @@ const MyProblemDropdown = ({ problem.problem_id ); - let createRequest = transformProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel2CreateProblemRequestForm( - response.data - ) + const createRequest = + transformProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel2CreateProblemRequestForm( + response.data + ); - createRequest.title += " (Copy)" + createRequest.title += " (Copy)"; const { request, groups } = transformCreateProblemRequestForm2CreateProblemRequest( @@ -60,7 +61,10 @@ const MyProblemDropdown = ({ toast({ title: `Cloned ${response.data.title}`, }); - window.open(`/my/problems/${response.data.problem_id}`, "_blank"); + window.open( + `/my/problems/${response.data.problem_id}`, + "_blank" + ); }); }; @@ -88,9 +92,11 @@ const MyProblemDropdown = ({ - window.open(`/my/problems/${problem.problem_id}/edit`, "_blank") + window.open( + `/my/problems/${problem.problem_id}/edit`, + "_blank" + ) } - > Edit Problem diff --git a/src/components/Forms/CreateCollectionForm/ManageProblems.tsx b/src/components/Forms/CreateCollectionForm/ManageProblems.tsx index cb04e2a..edefda4 100644 --- a/src/components/Forms/CreateCollectionForm/ManageProblems.tsx +++ b/src/components/Forms/CreateCollectionForm/ManageProblems.tsx @@ -70,45 +70,55 @@ const ManageProblems = ({ }); }, [selectedProblemsSortable]); - const [filteredProblems, setFilteredProblems] = useState([]); + const [filteredProblems, setFilteredProblems] = useState< + ProblemItemInterface[] + >([]); const [searchValue, setSearchValue] = useState(""); useEffect(() => { setFilteredProblems( allProblemsSortable.filter( - (item) => searchValue === "" || item.problem.title.includes(searchValue) + (item) => + searchValue === "" || + item.problem.title.includes(searchValue) ) ); - },[searchValue, allProblemsSortable]) + }, [searchValue, allProblemsSortable]); useEffect(() => { - ProblemService.getAllAsCreator(accountId,{end:10}).then((response) => { - setAllProblems( - transformProblemModel2ProblemHashedTable(response.data.problems) - ); - setAllProblemsSortable( - response.data.problems.map((problem) => ({ - id: problem.problem_id, - name: problem.title, - problem: problem, - groupPermissions: [], - })) - ); - - return ProblemService.getAllAsCreator(accountId) - }).then((response) => { - setAllProblems( - transformProblemModel2ProblemHashedTable(response.data.problems) - ); - setAllProblemsSortable( - response.data.problems.map((problem) => ({ - id: problem.problem_id, - name: problem.title, - problem: problem, - groupPermissions: [], - })) - ); - }); + ProblemService.getAllAsCreator(accountId, { end: 10 }) + .then((response) => { + setAllProblems( + transformProblemModel2ProblemHashedTable( + response.data.problems + ) + ); + setAllProblemsSortable( + response.data.problems.map((problem) => ({ + id: problem.problem_id, + name: problem.title, + problem: problem, + groupPermissions: [], + })) + ); + + return ProblemService.getAllAsCreator(accountId); + }) + .then((response) => { + setAllProblems( + transformProblemModel2ProblemHashedTable( + response.data.problems + ) + ); + setAllProblemsSortable( + response.data.problems.map((problem) => ({ + id: problem.problem_id, + name: problem.title, + problem: problem, + groupPermissions: [], + })) + ); + }); }, [accountId]); useEffect(() => { @@ -124,8 +134,6 @@ const ManageProblems = ({ useEffect(() => { if (initial) { - console.log("AAA",createRequest) - // setSelectedProblemsSortable(createRequest.problemsInterface); setSelectedProblemsSortable( createRequest.problemsInterface?.map((cp) => ({ id: cp.problem.problem_id, @@ -162,11 +170,18 @@ const ManageProblems = ({ {selectedProblemsSortable?.map((item) => ( + onClickXIcon={() => handleRemoveSelectedProblem( item.id as string ) } + onClickPencilIcon={() => { + const win = window.open( + `/my/problems/${item.problem.problem_id}/edit`, + "_blank" + ); + if (win) win.focus(); + }} key={item.id} problem={item.problem} /> @@ -182,7 +197,11 @@ const ManageProblems = ({
- setSearchValue(e.target.value)} className="mt-2" /> + setSearchValue(e.target.value)} + className="mt-2" + /> { - console.log(createRequest) if (createRequest.language) { setSelectedLanguage(createRequest.language); } @@ -136,6 +135,10 @@ const Scoring = ({ {((displayResult && validationResult) || createRequest.validated_testcases) && ( void; + onPreviousClick?: () => void; + disabled?: boolean; +}) => { + const { start, end, total } = pagination; + + const isFirstPage = useMemo(() => start === 0, [start]); + const isLastPage = useMemo(() => end >= total, [end, total]); + const currentPage = useMemo(() => Math.floor(start / 10) + 1, [start]); + const pageSize = useMemo(() => end - start, [end, start]); + const totalPages = useMemo( + () => Math.ceil(total / pageSize), + [total, pageSize] + ); + + return ( +
+
+ +
+ +
+ + {currentPage} / {totalPages} + +
+ +
+ +
+
+ ); +}; + +export default CustomPagination; diff --git a/src/components/ProblemViewLayout.tsx b/src/components/ProblemViewLayout.tsx index c495479..b3d03ab 100644 --- a/src/components/ProblemViewLayout.tsx +++ b/src/components/ProblemViewLayout.tsx @@ -4,8 +4,14 @@ import React, { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import styled from "styled-components"; import { ProgrammingLanguageOptions } from "../constants/ProgrammingLanguage"; -import { ProblemPoplulateCreatorModel, ProblemPopulateCreatorSecureModel } from "../types/models/Problem.model"; -import { GetSubmissionByAccountProblemResponse, SubmissionPopulateSubmissionTestcasesSecureModel } from "../types/models/Submission.model"; +import { + ProblemPoplulateCreatorModel, + ProblemPopulateCreatorSecureModel, +} from "../types/models/Problem.model"; +import { + GetSubmissionByAccountProblemResponse, + SubmissionPopulateSubmissionTestcasesSecureModel, +} from "../types/models/Submission.model"; import { handleDeprecatedDescription } from "../utilities/HandleDeprecatedDescription"; import { readableDateFormat } from "../utilities/ReadableDateFormat"; import PreviousSubmissionsCombobox from "./PreviousSubmissionsCombobox"; @@ -13,43 +19,57 @@ import ReadOnlyPlate from "./ReadOnlyPlate"; import TestcasesGradingIndicator from "./TestcasesGradingIndicator"; import { Button } from "./shadcn/Button"; import { Combobox } from "./shadcn/Combobox"; -import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./shadcn/Resizable"; +import { + ResizableHandle, + ResizablePanel, + ResizablePanelGroup, +} from "./shadcn/Resizable"; import { Separator } from "./shadcn/Seperator"; export type OnSubmitProblemViewLayoutCallback = { - setGrading: React.Dispatch> - setLastedSubmission: React.Dispatch> - selectedLanguage: string - submitCodeValue: string -} + setGrading: React.Dispatch>; + setLastedSubmission: React.Dispatch< + React.SetStateAction< + SubmissionPopulateSubmissionTestcasesSecureModel | undefined + > + >; + selectedLanguage: string; + submitCodeValue: string; +}; const ProblemViewLayout = ({ - onSubmit, - problem, - previousSubmissions -}:{ - onSubmit: (callback: OnSubmitProblemViewLayoutCallback) => void - problem: ProblemPoplulateCreatorModel | ProblemPopulateCreatorSecureModel - previousSubmissions: GetSubmissionByAccountProblemResponse + onSubmit, + problem, + previousSubmissions, +}: { + onSubmit: (callback: OnSubmitProblemViewLayoutCallback) => void; + problem: ProblemPoplulateCreatorModel | ProblemPopulateCreatorSecureModel; + previousSubmissions: GetSubmissionByAccountProblemResponse; }) => { + const navigate = useNavigate(); - const navigate = useNavigate(); - - // const [problem, setProblem] = useState(); + // const [problem, setProblem] = useState(); const [selectedLanguage, setSelectedLanguage] = useState("python"); const [grading, setGrading] = useState(false); - const [submitCodeValue, setSubmitCodeValue] = useState(""); + const [submitCodeValue, setSubmitCodeValue] = useState( + "" + ); - // const [previousSubmissions, setPreviousSubmissions] = - useState(); + // const [previousSubmissions, setPreviousSubmissions] = + useState(); const [lastedSubmission, setLastedSubmission] = useState(); - const handleSubmit = () => { - onSubmit({setGrading, setLastedSubmission,selectedLanguage,submitCodeValue}) - } + const handleSubmit = () => { + onSubmit({ + setGrading, + setLastedSubmission, + selectedLanguage, + submitCodeValue: submitCodeValue || "", + }); + }; - const handleSelectPreviousSubmission = (submissionId: string) => { + const handleSelectPreviousSubmission = (submissionId: string) => { let submission = null; if ( submissionId === previousSubmissions?.best_submission?.submission_id @@ -73,10 +93,13 @@ const ProblemViewLayout = ({ useEffect(() => { if (problem && problem?.allowed_languages.length > 0) { - setSelectedLanguage(ProgrammingLanguageOptions.filter(lang => problem?.allowed_languages.includes(lang.value))[0].value) + setSelectedLanguage( + ProgrammingLanguageOptions.filter((lang) => + problem?.allowed_languages.includes(lang.value) + )[0].value + ); } - },[problem]) - + }, [problem]); // useEffect(() => { @@ -88,8 +111,14 @@ const ProblemViewLayout = ({ // },[problem]) return ( - - + +
{problem?.title}
- +
Author @@ -123,9 +152,9 @@ const ProblemViewLayout = ({
*/}
-
- -
+
+ +
{problem && (
*/} - +
problem?.allowed_languages.includes(lang.value))} + options={ProgrammingLanguageOptions.filter((lang) => + problem?.allowed_languages.includes(lang.value) + )} onSelect={(value) => setSelectedLanguage(value)} // initialValue={selectedLanguage} value={selectedLanguage} @@ -196,7 +227,13 @@ const ProblemViewLayout = ({ } />
@@ -33,30 +36,23 @@ const MyCoursesTable = ({ header: "Collections", cell: ({ row }) => (
- + {row.original.collections.length}
), }, - { - accessorKey: "updated_date", - header: "Updated Date", - cell: ({ row }) => ( -
- {readableDateFormat(row.original.updated_date)} -
- ), - }, { - accessorKey: "action", - header: () => ( -
- Action + accessorKey: "updated_date", + header: "Updated Date", + cell: ({ row }) => ( +
+ {readableDateFormat(row.original.updated_date)}
), + }, + { + accessorKey: "action", + header: () =>
Action
, cell: ({ row }) => (
diff --git a/src/components/Tables/MyGroupsTable.tsx b/src/components/Tables/MyGroupsTable.tsx index 7326898..9e6b02c 100644 --- a/src/components/Tables/MyGroupsTable.tsx +++ b/src/components/Tables/MyGroupsTable.tsx @@ -1,60 +1,64 @@ -import { ColumnDef } from '@tanstack/react-table' -import { User, Users } from 'lucide-react' -import { Link } from 'react-router-dom' -import { GroupPopulateGroupMemberPopulateAccountSecureModel } from '../../types/models/Group.model' -import { readableDateFormat } from '../../utilities/ReadableDateFormat' -import { DataTable } from './Prototype/DataTable' +import { ColumnDef } from "@tanstack/react-table"; +import { User, Users } from "lucide-react"; +import { Link } from "react-router-dom"; +import { GroupPopulateGroupMemberPopulateAccountSecureModel } from "../../types/models/Group.model"; +import { readableDateFormat } from "../../utilities/ReadableDateFormat"; +import { DataTable } from "./Prototype/DataTable"; const MyGroupsTable = ({ - groups=[] -}:{ - groups: GroupPopulateGroupMemberPopulateAccountSecureModel[] + groups = [], +}: { + groups: GroupPopulateGroupMemberPopulateAccountSecureModel[]; }) => { + const column: ColumnDef[] = + [ + { + accessorKey: "name", + header: "Title", + cell: ({ row }) => ( +
+ + + {row.original.name} + +
+ ), + }, + { + accessorKey: "members", + header: "Members", + cell: ({ row }) => ( +
+ + {row.original.members.length} +
+ ), + }, + { + accessorKey: "updated_date", + header: "Updated Date", + cell: ({ row }) => ( +
+ {readableDateFormat(row.original.updated_date)} +
+ ), + }, + ]; - const column:ColumnDef[] = [ - { - accessorKey: "name", - header: "Title", - cell: ({ row }) => ( -
- - - {row.original.name} - -
- ) - }, - { - accessorKey: "members", - header: "Members", - cell: ({ row }) => ( -
- - {row.original.members.length} -
- ) - }, - { - accessorKey: "updated_date", - header: "Updated Date", - cell: ({ row }) => ( -
- {readableDateFormat(row.original.updated_date)} -
- ), - }, - ] + return ( +
+ +
+ ); +}; - return ( -
- -
- ) -} - -export default MyGroupsTable \ No newline at end of file +export default MyGroupsTable; diff --git a/src/components/Tables/MyPreviousSubmissionsTable.tsx b/src/components/Tables/MyPreviousSubmissionsTable.tsx index 231f999..1e46e9e 100644 --- a/src/components/Tables/MyPreviousSubmissionsTable.tsx +++ b/src/components/Tables/MyPreviousSubmissionsTable.tsx @@ -20,6 +20,7 @@ const MyPreviousSubmissionsTable = ({ cell: ({ row }) => (
{row.original.topic ? (
- + {row.original.topic.name} @@ -69,10 +74,7 @@ const MyPreviousSubmissionsTable = ({ }, { accessorKey: "is_passed", - header: () =>
- - Is Passed -
, + header: () =>
Is Passed
, cell: ({ row }) => { return (
diff --git a/src/components/Tables/MyProblemSubmissionsTable.tsx b/src/components/Tables/MyProblemSubmissionsTable.tsx index 4a51e7d..1ec12b8 100644 --- a/src/components/Tables/MyProblemSubmissionsTable.tsx +++ b/src/components/Tables/MyProblemSubmissionsTable.tsx @@ -10,36 +10,37 @@ import TestcasesGradingIndicator from "../TestcasesGradingIndicator"; import { Button } from "../shadcn/Button"; import { Link } from "react-router-dom"; - - const MyProblemSubmissionsTable = ({ submissions = [], - problem + problem, }: { submissions?: SubmissionPopulateSubmissionTestcaseAndAccountModel[]; - problem: ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel + problem: ProblemPopulateAccountAndTestcasesAndProblemGroupPermissionsPopulateGroupModel; }) => { - - const columns: ColumnDef[] = - [ - { - accessorKey: "username", - header: "Username", - cell: ({ row }) => ( -
- {row.original.account.username} -
- ), - }, - { - accessorKey: "course", - header: "Course", - cell: ({ row }) => ( -
+ const columns: ColumnDef[] = + [ + { + accessorKey: "username", + header: "Username", + cell: ({ row }) => ( +
+ {row.original.account.username} +
+ ), + }, + { + accessorKey: "course", + header: "Course", + cell: ({ row }) => ( +
{row.original.topic ? (
- + {row.original.topic.name} @@ -51,78 +52,77 @@ const MyProblemSubmissionsTable = ({
)}
- ), - }, - { - accessorKey: "language", - header: () =>
Language
, - cell: ({ row }) => ( -
- { - ProgrammingLanguageOptions.find( - (language) => - language.value === row.original.language - )?.badge - } -
- ), - }, - { - accessorKey: "is_passed", - header: () =>
- - Is Passed -
, - cell: ({ row }) => { - return ( -
- {row.original.is_passed ? ( - - ) : ( - - )} + ), + }, + { + accessorKey: "language", + header: () =>
Language
, + cell: ({ row }) => ( +
+ { + ProgrammingLanguageOptions.find( + (language) => + language.value === row.original.language + )?.badge + } +
+ ), + }, + { + accessorKey: "is_passed", + header: () =>
Is Passed
, + cell: ({ row }) => { + return ( +
+ {row.original.is_passed ? ( + + ) : ( + + )} +
+ ); + }, + }, + { + accessorKey: "runtime_result", + header: "Runtime Result", + cell: ({ row }) => ( +
+ +
+ ), + }, + { + accessorKey: "date", + header: "Submitted Date", + cell: ({ row }) => ( +
+ {readableDateFormat(row.original.date)} +
+ ), + }, + { + accessorKey: "action", + header: "", + cell: ({ row }) => ( +
+ + +
- ); + ), }, - }, - { - accessorKey: "runtime_result", - header: "Runtime Result", - cell: ({ row }) => ( -
- -
- ), - }, - { - accessorKey: "date", - header: "Submitted Date", - cell: ({ row }) => ( -
{readableDateFormat(row.original.date)}
- ), - }, - { - accessorKey: "action", - header: "", - cell: ({ row }) => ( -
- - - -
- ), - }, - ]; + ]; return (
diff --git a/src/components/Tables/ProblemTables/MyProblemsTable.tsx b/src/components/Tables/ProblemTables/MyProblemsTable.tsx index c460852..384f580 100644 --- a/src/components/Tables/ProblemTables/MyProblemsTable.tsx +++ b/src/components/Tables/ProblemTables/MyProblemsTable.tsx @@ -16,7 +16,11 @@ import { readableDateFormat } from "../../../utilities/ReadableDateFormat"; import MyProblemDropdown from "../../Dropdowns/MyProblemDropdown"; import { DataTable } from "../Prototype/DataTable"; import DataTableSortableLayout from "../Prototype/DataTableSortableLayout"; -import { HoverCard, HoverCardContent, HoverCardTrigger } from "../../shadcn/HoverCard"; +import { + HoverCard, + HoverCardContent, + HoverCardTrigger, +} from "../../shadcn/HoverCard"; import { Badge } from "../../shadcn/Badge"; const columns: ColumnDef[] = [ @@ -35,7 +39,10 @@ const columns: ColumnDef[] = [ return (
- + {row.original.title}
@@ -120,7 +127,10 @@ const columns: ColumnDef[] = [ cell: ({ row }) => (
- {row.original.time_limit} + + {row.original.time_limit.toFixed(3)}{" "} + ms +
), }, diff --git a/src/components/Tables/ProblemTables/PublicProblemsTable.tsx b/src/components/Tables/ProblemTables/PublicProblemsTable.tsx index c05eb35..6fbe821 100644 --- a/src/components/Tables/ProblemTables/PublicProblemsTable.tsx +++ b/src/components/Tables/ProblemTables/PublicProblemsTable.tsx @@ -7,9 +7,9 @@ import TestcasesGradingIndicator from "../../TestcasesGradingIndicator"; import { Badge } from "../../shadcn/Badge"; import { Button } from "../../shadcn/Button"; import { - HoverCard, - HoverCardContent, - HoverCardTrigger, + HoverCard, + HoverCardContent, + HoverCardTrigger, } from "../../shadcn/HoverCard"; import { DataTable } from "../Prototype/DataTable"; @@ -34,7 +34,10 @@ const PublicProblemsTable = ({ className="mr-2 text-blue-400" size={20} /> - + {row.original.title}
@@ -132,7 +135,7 @@ const PublicProblemsTable = ({ ), }, - { + { accessorKey: "author", header: "Author", cell: ({ row }) => ( @@ -166,6 +169,7 @@ const PublicProblemsTable = ({ cell: ({ row }) => (
{ columns: ColumnDef[]; @@ -100,7 +99,7 @@ export function DataTable({
- + {/* */}
{/*