From b9a919ddcd4f5ceb5a6eb24eb6a975504b574e83 Mon Sep 17 00:00:00 2001 From: CJ Quines Date: Wed, 19 Mar 2025 10:58:47 -0400 Subject: [PATCH 1/2] chore: run prettier --- package.json | 2 +- .../forgot-password/forgot-password-page.tsx | 23 ++- src/app/(auth)/forgot-password/page.tsx | 2 +- src/app/(auth)/login/login_page.tsx | 10 +- src/app/(auth)/login/page.tsx | 2 +- src/app/(auth)/logout/logout_redirect.tsx | 1 - src/app/(auth)/logout/page.tsx | 1 - src/app/(auth)/password-reset/page.tsx | 2 +- .../password-reset/password-reset-page.tsx | 27 ++- src/app/(auth)/register/page.tsx | 2 +- src/app/(auth)/register/register_page.tsx | 7 +- src/app/admin/contests/page.tsx | 32 +++- .../admin/files/[hash]/[filename]/route.ts | 7 +- src/app/admin/page.tsx | 4 +- src/app/admin/sets/page.tsx | 43 +++-- src/app/admin/tasks/page.tsx | 32 +++- src/app/api/v1/auth/forgot-password/route.ts | 25 +-- src/app/api/v1/auth/login/route.ts | 16 +- src/app/api/v1/auth/register/route.ts | 25 +-- src/app/api/v1/auth/reset-password/route.ts | 17 +- src/app/api/v1/contests/route.tsx | 24 +-- src/app/api/v1/sets/[id]/route.ts | 1 - src/app/api/v1/sets/route.ts | 24 +-- .../api/v1/submissions/rejudge/[id]/route.ts | 6 +- src/app/api/v1/submissions/route.ts | 51 +++-- src/app/api/v1/tasks/[id]/kg/route.ts | 30 +-- .../api/v1/tasks/[id]/score_overall/route.ts | 13 +- src/app/api/v1/tasks/[id]/utils.ts | 2 - src/app/api/v1/tasks/files/route.ts | 4 +- src/app/api/v1/tasks/route.ts | 1 - src/app/api/v1/tasks/simple/route.ts | 24 +-- src/app/contests/[slug]/edit/page.tsx | 7 +- src/app/contests/[slug]/page.tsx | 11 +- src/app/contests/page.tsx | 2 +- src/app/layout.tsx | 4 +- src/app/page.tsx | 13 +- src/app/sets/[slug]/edit/page.tsx | 6 +- src/app/sets/[slug]/page.tsx | 12 +- src/app/sets/page.tsx | 2 +- src/app/submissions/[hid]/page.tsx | 4 +- src/app/tasks/[slug]/edit/page.tsx | 6 +- src/app/tasks/[slug]/page.tsx | 17 +- src/app/tasks/page.tsx | 12 +- .../components/admin_table/admin_table.tsx | 33 +--- src/client/components/auth/auth.tsx | 82 ++++---- src/client/components/box_icon.tsx | 2 +- src/client/components/cards/common_card.tsx | 67 ++++--- .../common_editor/common_editor.module.css | 30 +-- .../common_editor_attachments.tsx | 15 +- .../common_editor/common_editor_parts.tsx | 84 ++++----- .../common_editor/common_editor_statement.tsx | 16 +- .../common_editor/common_editor_tabs.tsx | 20 +- .../common_editor/common_editor_utils.tsx | 4 +- src/client/components/common_editor/index.ts | 12 +- src/client/components/common_editor/types.ts | 1 - .../contest_creator/contest_creator.tsx | 62 +++--- .../contest_editor/contest_coercion.ts | 2 +- .../contest_editor_advanced.tsx | 8 +- .../contest_editor/contest_editor_details.tsx | 4 +- src/client/components/contest_editor/index.ts | 2 +- .../contest_viewer/contest_viewer.tsx | 4 +- .../empty_notice/empty_notice.module.css | 1 - .../components/empty_notice/empty_notice.tsx | 36 ++-- src/client/components/footer/index.tsx | 39 +++- src/client/components/form/form.tsx | 28 ++- src/client/components/form/index.tsx | 2 +- .../components/homepage/homepage.module.css | 7 +- src/client/components/homepage/homepage.tsx | 84 ++++----- .../components/homepage/homepage_faq.tsx | 43 +++-- src/client/components/latex_display/index.ts | 2 +- .../latex_display/latex_display.tsx | 14 +- src/client/components/modal/index.tsx | 2 +- src/client/components/modal/modal.tsx | 47 +++-- src/client/components/navbar/index.tsx | 35 ++-- .../components/problem_set_creator/index.ts | 2 +- .../problem_set_creator.tsx | 62 +++--- .../components/problem_set_editor/index.tsx | 2 +- .../problem_set_coercion.ts | 2 +- .../problem_set_editor.module.css | 1 - .../problem_set_editor/problem_set_editor.tsx | 62 +++--- .../problem_set_viewer/problem_set_viewer.tsx | 4 +- .../components/sample_io_display/index.ts | 2 +- .../sample_io_display/sample_io_display.tsx | 43 +++-- src/client/components/scrollable/index.tsx | 2 +- .../submission_viewer/submission_viewer.tsx | 46 ++--- .../components/submissions_table/index.ts | 2 +- .../submissions_table/submissions_table.tsx | 12 +- src/client/components/submit_panel/index.ts | 2 +- .../components/submit_panel/submit_code.tsx | 13 +- .../components/submit_panel/submit_output.tsx | 2 +- .../submit_panel/submit_panel.module.css | 14 +- .../components/submit_panel/submit_utils.ts | 40 ++-- src/client/components/task_creator/index.ts | 2 +- .../components/task_creator/task_creator.tsx | 65 ++++--- src/client/components/task_editor/coercion.ts | 37 ++-- .../components/task_editor/task_editor.tsx | 22 +-- .../task_editor/task_editor_advanced.tsx | 15 +- .../task_editor/task_editor_details.tsx | 6 +- .../task_editor/task_editor_judging.tsx | 102 ++++++---- .../task_editor/task_editor_sample_io.tsx | 43 +++-- .../task_editor/task_editor_saving.tsx | 34 ++-- .../task_editor/task_editor_script.tsx | 90 +++++---- .../task_editor/task_editor_submissions.tsx | 5 +- .../task_editor/task_editor_subtasks.tsx | 6 +- .../task_editor/task_editor_utils.tsx | 2 +- src/client/components/task_editor/types.ts | 20 +- .../task_viewer/task_viewer.module.css | 2 +- .../components/task_viewer/task_viewer.tsx | 12 +- .../task_viewer/task_viewer_statement.tsx | 7 +- .../task_viewer/task_viewer_submissions.tsx | 28 +-- .../task_viewer/task_viewer_utils.tsx | 66 +++---- src/client/http.ts | 1 - src/client/submissions.ts | 3 +- src/common/latex/index.ts | 2 +- src/common/latex/latex_images.tsx | 26 +-- src/common/latex/latex_list.tsx | 74 +++++--- src/common/latex/latex_macros.tsx | 9 +- src/common/latex/latex_postprocess.ts | 6 +- src/common/latex/latex_render.tsx | 71 ++++--- src/common/latex/latex_strings.ts | 26 +-- src/common/latex/latex_syntax_highlight.tsx | 48 ++--- src/common/latex/latex_types.ts | 4 +- src/common/latex/latex_utils.tsx | 33 +++- src/common/responses.ts | 26 ++- src/common/types/constants.ts | 4 +- src/common/types/contests.ts | 9 +- src/common/types/index.ts | 7 +- src/common/types/judge.ts | 9 +- src/common/types/tasks.ts | 6 +- src/common/types/verdicts.ts | 3 +- src/common/utils/arrays.ts | 14 +- src/common/utils/hashing.ts | 4 +- src/common/utils/sleep.ts | 2 +- src/common/validation/common_validation.ts | 1 - src/common/validation/constant_validation.ts | 5 +- src/common/validation/contest_validation.ts | 1 - .../validation/problem_set_validation.ts | 8 +- .../validation/submission_validation.ts | 4 +- src/common/validation/task_validation.ts | 7 +- src/common/validation/user_validation.ts | 59 +++--- src/db/index.ts | 1 - .../20240320074757_initial_migration.ts | 24 ++- .../20250225225800_add_on_delete_cascades.ts | 82 ++++---- src/db/scripts/devtools/crud.ts | 4 +- src/db/scripts/devtools/database.ts | 1 - src/db/scripts/devtools/index.ts | 22 ++- src/db/scripts/seed.ts | 17 +- src/server/authorization.ts | 11 +- src/server/email/abstract.ts | 1 - src/server/email/console.ts | 6 +- src/server/email/index.ts | 6 +- src/server/email/ses.ts | 3 +- src/server/errors/forbidden.tsx | 6 +- src/server/evaluation/index.ts | 10 +- src/server/evaluation/judge_batch.ts | 15 +- src/server/evaluation/judge_checker.ts | 33 ++-- src/server/evaluation/judge_communication.ts | 37 +++- src/server/evaluation/judge_compile.ts | 15 +- src/server/evaluation/judge_constants.ts | 4 +- src/server/evaluation/judge_utils.ts | 12 +- src/server/files/abstract.ts | 2 +- src/server/files/azure.ts | 55 +++--- src/server/files/cache.ts | 178 ++++++++++-------- src/server/files/index.ts | 5 +- src/server/files/s3.ts | 65 ++++--- src/server/logic/judgements/judge_runner.ts | 41 ++-- .../problem_sets/get_editor_problem_set.ts | 15 +- .../logic/problem_sets/update_problem_set.ts | 13 +- .../logic/submissions/create_submission.ts | 41 ++-- .../logic/submissions/judge_submission.ts | 6 +- src/server/logic/tasks/editor_utils.ts | 28 +-- src/server/logic/tasks/get_editor_task.ts | 21 ++- src/server/logic/tasks/update_editor_task.ts | 33 ++-- src/server/logic/users.ts | 18 +- src/server/secrets.ts | 9 +- src/server/slugs.ts | 7 +- src/types/nextjs.ts | 1 - src/worker/types.ts | 7 +- src/worker/worker.ts | 25 ++- 179 files changed, 1921 insertions(+), 1652 deletions(-) diff --git a/package.json b/package.json index 4cd629b0..d351ccfe 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "db:recreate": "node --conditions=react-server -r ts-node/register src/db/scripts/devtools db:recreate", "db:migrate": "node --conditions=react-server -r ts-node/register src/db/scripts/devtools db:migrate", "db:seed": "node --conditions=react-server -r ts-node/register src/db/scripts/devtools db:seed", - "lint": "next lint", + "lint": "next lint && prettier src --check", "lint:fix": "next lint --fix && prettier src --write", "format": "prettier src --write" }, diff --git a/src/app/(auth)/forgot-password/forgot-password-page.tsx b/src/app/(auth)/forgot-password/forgot-password-page.tsx index 6aa8b910..1779561f 100644 --- a/src/app/(auth)/forgot-password/forgot-password-page.tsx +++ b/src/app/(auth)/forgot-password/forgot-password-page.tsx @@ -22,7 +22,10 @@ import { import { zUserForgotPassword } from "common/validation/user_validation"; import { applyValidationErrors, ResponseKind } from "common/responses"; import { UnreachableCheck } from "common/errors"; -import type { ForgotPasswordError, ForgotPasswordSuccess } from "@root/api/v1/auth/forgot-password/route"; +import type { + ForgotPasswordError, + ForgotPasswordSuccess, +} from "@root/api/v1/auth/forgot-password/route"; type ForgotPasswordForm = { username: string; @@ -38,7 +41,6 @@ export function ForgotPasswordPage() { resolver: zodResolver(zUserForgotPassword), }); - const onSubmit = async (data: ForgotPasswordForm) => { try { const url = getAPIPath({ kind: APIPath.ForgotPassword }); @@ -50,16 +52,16 @@ export function ForgotPasswordPage() { if (e instanceof AxiosError && e.response) { const response: AxiosResponse = e.response; const data = response.data; - switch(data.kind) { + switch (data.kind) { case ResponseKind.ValidationError: applyValidationErrors(setError, data.errors); break; default: UnreachableCheck(data.kind); - toast.error('An unexpected error occurred'); + toast.error("An unexpected error occurred"); } } else { - toast.error('An network error occurred. Please try again.'); + toast.error("An network error occurred. Please try again."); throw e; } } @@ -72,8 +74,8 @@ export function ForgotPasswordPage() { Username: - - + + @@ -81,11 +83,8 @@ export function ForgotPasswordPage() { - - Go back to login - + Go back to login ); -}; - +} diff --git a/src/app/(auth)/forgot-password/page.tsx b/src/app/(auth)/forgot-password/page.tsx index 8fbbc0e4..024a63d5 100644 --- a/src/app/(auth)/forgot-password/page.tsx +++ b/src/app/(auth)/forgot-password/page.tsx @@ -19,6 +19,6 @@ async function Page() { ); -}; +} export default Page; diff --git a/src/app/(auth)/login/login_page.tsx b/src/app/(auth)/login/login_page.tsx index 493d7d9d..f661c7bf 100644 --- a/src/app/(auth)/login/login_page.tsx +++ b/src/app/(auth)/login/login_page.tsx @@ -26,7 +26,6 @@ import { zUserLogin } from "common/validation/user_validation"; import { applyValidationErrors, ResponseKind } from "common/responses"; import type { UserLoginError, UserLoginSuccess } from "@root/api/v1/auth/login/route"; - type LoginForm = { username: string; password: string; @@ -45,11 +44,10 @@ export function LoginPage() { resolver: zodResolver(zUserLogin), }); - const onSubmit = async (data: LoginForm) => { try { const url = getAPIPath({ kind: APIPath.Login }); - const response: AxiosResponse = await http.post(url, { + const response: AxiosResponse = await http.post(url, { username: data.username, password: data.password, }); @@ -100,12 +98,10 @@ export function LoginPage() { Forgot your password - - Register an account - + Register an account ); -}; +} export default LoginPage; diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index f618963b..dad9e920 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -9,7 +9,7 @@ export const metadata: Metadata = { title: "Login", }; -const Page: FunctionComponent = async() => { +const Page: FunctionComponent = async () => { const session = await getSession(); if (session != null) { redirect("/"); diff --git a/src/app/(auth)/logout/logout_redirect.tsx b/src/app/(auth)/logout/logout_redirect.tsx index 7451d18b..6eb3d00f 100644 --- a/src/app/(auth)/logout/logout_redirect.tsx +++ b/src/app/(auth)/logout/logout_redirect.tsx @@ -6,7 +6,6 @@ import http from "client/http"; import { getPath, Path } from "client/paths"; import { useSessionWithUpdate } from "client/sessions"; - export const LogoutRedirect: FunctionComponent = () => { const { setSession } = useSessionWithUpdate(); const router = useRouter(); diff --git a/src/app/(auth)/logout/page.tsx b/src/app/(auth)/logout/page.tsx index 9d59353c..9e49250e 100644 --- a/src/app/(auth)/logout/page.tsx +++ b/src/app/(auth)/logout/page.tsx @@ -6,7 +6,6 @@ import http from "client/http"; import { getPath, Path } from "client/paths"; import { useSessionWithUpdate } from "client/sessions"; - const Page: FunctionComponent = () => { const router = useRouter(); const { setSession } = useSessionWithUpdate(); diff --git a/src/app/(auth)/password-reset/page.tsx b/src/app/(auth)/password-reset/page.tsx index eb37693c..0e4b2288 100644 --- a/src/app/(auth)/password-reset/page.tsx +++ b/src/app/(auth)/password-reset/page.tsx @@ -19,6 +19,6 @@ async function Page() { ); -}; +} export default Page; diff --git a/src/app/(auth)/password-reset/password-reset-page.tsx b/src/app/(auth)/password-reset/password-reset-page.tsx index b4942c82..e073bbdb 100644 --- a/src/app/(auth)/password-reset/password-reset-page.tsx +++ b/src/app/(auth)/password-reset/password-reset-page.tsx @@ -31,16 +31,16 @@ type PasswordResetForm = { }; export function PasswordResetPage() { - const [token, setToken] = useState(''); + const [token, setToken] = useState(""); const [tokenBad, setTokenBad] = useState(true); const router = useRouter(); // Get the token from the URL and check if it's "valid" (not empty) useEffect(() => { - const t = new URLSearchParams(window.location.search).get('token') ?? ''; + const t = new URLSearchParams(window.location.search).get("token") ?? ""; const bad = t.length == 0; if (bad) { - toast.error('Invalid token'); + toast.error("Invalid token"); } else { setToken(t); setTokenBad(bad); @@ -63,26 +63,26 @@ export function PasswordResetPage() { token: token, password: data.password, }); - toast.success('Successfully reset password!'); + toast.success("Successfully reset password!"); router.push(getPath({ kind: Path.AccountLogin })); } catch (e) { if (e instanceof AxiosError && e.response) { const response: AxiosResponse = e.response; const data = response.data; - switch(data.kind) { + switch (data.kind) { case ResponseKind.ValidationError: applyValidationErrors(setError, data.errors); if (data.errors.token != null && data.errors.token.length > 0) { - toast.error('The password reset token is invalid'); + toast.error("The password reset token is invalid"); setTokenBad(true); } break; default: UnreachableCheck(data.kind); - toast.error('An unexpected error occurred'); + toast.error("An unexpected error occurred"); } } else { - toast.error('An network error occurred. Please try again.'); + toast.error("An network error occurred. Please try again."); throw e; } } @@ -95,13 +95,13 @@ export function PasswordResetPage() { Password: - - + + Confirm Password: - - + + @@ -110,5 +110,4 @@ export function PasswordResetPage() { ); -}; - +} diff --git a/src/app/(auth)/register/page.tsx b/src/app/(auth)/register/page.tsx index cd001468..b45fe50e 100644 --- a/src/app/(auth)/register/page.tsx +++ b/src/app/(auth)/register/page.tsx @@ -19,4 +19,4 @@ export default async function Page() { ); -}; +} diff --git a/src/app/(auth)/register/register_page.tsx b/src/app/(auth)/register/register_page.tsx index e0dfa1fb..9f0e231d 100644 --- a/src/app/(auth)/register/register_page.tsx +++ b/src/app/(auth)/register/register_page.tsx @@ -26,7 +26,6 @@ import { zUserRegister } from "common/validation/user_validation"; import { applyValidationErrors, ResponseKind } from "common/responses"; import { UserRegisterError, UserRegisterSuccess } from "@root/api/v1/auth/register/route"; - type RegisterForm = { email: string; username: string; @@ -50,7 +49,7 @@ export function RegisterPage() { const onSubmit = async (data: RegisterForm) => { try { const url = getAPIPath({ kind: APIPath.Register }); - const response: AxiosResponse = await http.post(url, { + const response: AxiosResponse = await http.post(url, { email: data.email, username: data.username, password: data.password, @@ -110,9 +109,7 @@ export function RegisterPage() { - - Already have an account - + Already have an account ); diff --git a/src/app/admin/contests/page.tsx b/src/app/admin/contests/page.tsx index e6dc8a24..a5a706eb 100644 --- a/src/app/admin/contests/page.tsx +++ b/src/app/admin/contests/page.tsx @@ -2,7 +2,14 @@ import { Metadata } from "next"; import Link from "next/link"; import { ReactNode } from "react"; import { db } from "db"; -import { AdminTable, AdminTbody, AdminTD, AdminTH, AdminThead, AdminTR } from "client/components/admin_table/admin_table"; +import { + AdminTable, + AdminTbody, + AdminTD, + AdminTH, + AdminThead, + AdminTR, +} from "client/components/admin_table/admin_table"; import { DefaultLayout } from "client/components/layouts/default_layout"; import { ContestCreator } from "client/components/contest_creator"; import { EmptyNotice } from "client/components/empty_notice"; @@ -27,7 +34,7 @@ type ContestSummaryAdminDTO = { // eslint-disable-next-line @typescript-eslint/no-unused-vars -- pre-existing error before eslint inclusion async function getContestsData(session: SessionData): Promise { - const contests = await db + const contests = (await db .selectFrom("contests") .innerJoin("users", "users.id", "contests.owner_id") .select([ @@ -39,24 +46,23 @@ async function getContestsData(session: SessionData): Promise; + return ; } const contests = await getContestsData(session); let content: ReactNode = null; if (contests.length == 0) { - content = ; + content = ; } else { content = ( @@ -75,7 +81,10 @@ async function Page() { {uuidToHuradoID(contest.id)} - + {contest.slug} @@ -83,7 +92,10 @@ async function Page() { {contest.owner} {contest.created_at.toLocaleDateString()} - + Edit @@ -98,11 +110,11 @@ async function Page() {

Contests

- +
{content}
); -}; +} export default Page; diff --git a/src/app/admin/files/[hash]/[filename]/route.ts b/src/app/admin/files/[hash]/[filename]/route.ts index dae1a012..9459cd1e 100644 --- a/src/app/admin/files/[hash]/[filename]/route.ts +++ b/src/app/admin/files/[hash]/[filename]/route.ts @@ -18,11 +18,8 @@ export async function GET(request: NextRequest, context: NextContext { +const Page: FunctionComponent = async () => { const session = await getSession(); const tasks = canManageTasks(session); const sets = canManageProblemSets(session); const contests = canManageContests(session); if (!tasks && !sets && !contests) { - return ; + return ; } return ( diff --git a/src/app/admin/sets/page.tsx b/src/app/admin/sets/page.tsx index 30b0e346..5eb7bbef 100644 --- a/src/app/admin/sets/page.tsx +++ b/src/app/admin/sets/page.tsx @@ -2,7 +2,14 @@ import { Metadata } from "next"; import Link from "next/link"; import { ReactNode } from "react"; import { db } from "db"; -import { AdminTable, AdminTbody, AdminTD, AdminTH, AdminThead, AdminTR } from "client/components/admin_table/admin_table"; +import { + AdminTable, + AdminTbody, + AdminTD, + AdminTH, + AdminThead, + AdminTR, +} from "client/components/admin_table/admin_table"; import { DefaultLayout } from "client/components/layouts/default_layout"; import { EmptyNotice } from "client/components/empty_notice"; import { ProblemSetCreator } from "client/components/problem_set_creator"; @@ -17,7 +24,6 @@ export const metadata: Metadata = { title: "Admin | Problem Sets", }; - type ProblemSetSummaryAdminDTO = { id: string; title: string; @@ -28,34 +34,27 @@ type ProblemSetSummaryAdminDTO = { // eslint-disable-next-line @typescript-eslint/no-unused-vars -- pre-existing error before eslint inclusion async function getProblemSetsData(session: SessionData): Promise { - const sets = await db + const sets = (await db .selectFrom("problem_sets") - .select([ - "id", - "title", - "slug", - "is_public", - "order", - ]) + .select(["id", "title", "slug", "is_public", "order"]) .orderBy("order", "asc") .limit(1000) - .execute() satisfies ProblemSetSummaryAdminDTO[]; + .execute()) satisfies ProblemSetSummaryAdminDTO[]; return sets; } - async function Page() { const session = await getSession(); if (session == null || !canManageProblemSets(session)) { - return ; + return ; } const sets = await getProblemSetsData(session); let content: ReactNode = null; if (sets.length == 0) { - content = ; + content = ; } else { content = ( @@ -74,15 +73,21 @@ async function Page() { {uuidToHuradoID(task.id)} - + {task.slug} {task.title} - {task.is_public ? "Yes" : "No" } + {task.is_public ? "Yes" : "No"} {task.order} - + Edit @@ -97,11 +102,11 @@ async function Page() {

Problem Sets

- +
{content}
); -}; +} export default Page; diff --git a/src/app/admin/tasks/page.tsx b/src/app/admin/tasks/page.tsx index 03f3ee8d..ea2b5f46 100644 --- a/src/app/admin/tasks/page.tsx +++ b/src/app/admin/tasks/page.tsx @@ -2,7 +2,14 @@ import { Metadata } from "next"; import Link from "next/link"; import { ReactNode } from "react"; import { db } from "db"; -import { AdminTable, AdminTbody, AdminTD, AdminTH, AdminThead, AdminTR } from "client/components/admin_table/admin_table"; +import { + AdminTable, + AdminTbody, + AdminTD, + AdminTH, + AdminThead, + AdminTR, +} from "client/components/admin_table/admin_table"; import { DefaultLayout } from "client/components/layouts/default_layout"; import { EmptyNotice } from "client/components/empty_notice"; import { TaskCreator } from "client/components/task_creator"; @@ -27,7 +34,7 @@ type TaskSummaryAdminDTO = { // eslint-disable-next-line @typescript-eslint/no-unused-vars -- pre-existing error before eslint inclusion async function getTasksData(session: SessionData): Promise { - const tasks = await db + const tasks = (await db .selectFrom("tasks") .innerJoin("users", "users.id", "tasks.owner_id") .select([ @@ -39,24 +46,23 @@ async function getTasksData(session: SessionData): Promise; + return ; } const tasks = await getTasksData(session); let content: ReactNode = null; if (tasks.length == 0) { - content = ; + content = ; } else { content = ( @@ -75,7 +81,10 @@ async function Page() { {uuidToHuradoID(task.id)} - + {task.slug} @@ -83,7 +92,10 @@ async function Page() { {task.owner} {task.created_at.toLocaleDateString()} - + Edit @@ -98,11 +110,11 @@ async function Page() {

Tasks

- +
{content}
); -}; +} export default Page; diff --git a/src/app/api/v1/auth/forgot-password/route.ts b/src/app/api/v1/auth/forgot-password/route.ts index 54345955..1c16ce1e 100644 --- a/src/app/api/v1/auth/forgot-password/route.ts +++ b/src/app/api/v1/auth/forgot-password/route.ts @@ -13,12 +13,9 @@ import { enqueuePasswordReset } from "worker/queue"; export type ForgotPasswordError = APIValidationErrorType; -export type ForgotPasswordSuccess = APISuccessResponse<{ email: string }> - -export type ForgotPasswordResponse = - | ForgotPasswordError - | ForgotPasswordSuccess; +export type ForgotPasswordSuccess = APISuccessResponse<{ email: string }>; +export type ForgotPasswordResponse = ForgotPasswordError | ForgotPasswordSuccess; export async function POST(request: NextRequest) { const { username } = await request.json(); @@ -38,22 +35,26 @@ export async function POST(request: NextRequest) { .executeTakeFirst(); if (user == null) { - return NextResponse.json(customValidationError({ - username: ["User not found"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + username: ["User not found"], + }), + { status: 400 } + ); } await enqueuePasswordReset({ username: parsed.data.username, }); - return NextResponse.json(makeSuccessResponse({ - email: censorEmail(user.email), - })); + return NextResponse.json( + makeSuccessResponse({ + email: censorEmail(user.email), + }) + ); }); } - function censorEmail(email: string): string { const [username, domain] = email.split("@"); // Show only the first two characters of the username diff --git a/src/app/api/v1/auth/login/route.ts b/src/app/api/v1/auth/login/route.ts index 6cdac3c9..0dfce384 100644 --- a/src/app/api/v1/auth/login/route.ts +++ b/src/app/api/v1/auth/login/route.ts @@ -16,12 +16,9 @@ import { zUserLogin } from "common/validation/user_validation"; export type UserLoginError = APIValidationErrorType; -export type UserLoginSuccess = APISuccessResponse - -export type UserLoginResponse = - | UserLoginError - | UserLoginSuccess; +export type UserLoginSuccess = APISuccessResponse; +export type UserLoginResponse = UserLoginError | UserLoginSuccess; export async function POST(request: NextRequest): Promise> { const { username, password } = await request.json(); @@ -43,9 +40,12 @@ export async function POST(request: NextRequest): Promise; -export type UserRegisterSuccess = APISuccessResponse - -export type UserRegisterResponse = - | UserRegisterError - | UserRegisterSuccess; +export type UserRegisterSuccess = APISuccessResponse; +export type UserRegisterResponse = UserRegisterError | UserRegisterSuccess; type CustomValidationErrors = { email?: string[]; @@ -43,10 +45,9 @@ export async function POST(request: NextRequest): Promise eb.or([ - eb("email", "=", parsed.data.email), - eb("username", "=", parsed.data.username), - ])) + .where((eb) => + eb.or([eb("email", "=", parsed.data.email), eb("username", "=", parsed.data.username)]) + ) .select(["id", "email", "username"]) .execute(); @@ -68,7 +69,7 @@ export async function POST(request: NextRequest): Promise; -export type ResetPasswordSuccess = APISuccessResponse - -export type ResetPasswordResponse = - | ResetPasswordError - | ResetPasswordSuccess; +export type ResetPasswordSuccess = APISuccessResponse; +export type ResetPasswordResponse = ResetPasswordError | ResetPasswordSuccess; export async function POST(request: NextRequest) { const { token, password } = await request.json(); @@ -42,9 +39,12 @@ export async function POST(request: NextRequest) { .executeTakeFirst(); if (user == null) { - return NextResponse.json(customValidationError({ - token: ["Invalid token"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + token: ["Invalid token"], + }), + { status: 400 } + ); } await trx @@ -61,7 +61,6 @@ export async function POST(request: NextRequest) { }); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars -- pre-existing error before eslint inclusion function censorEmail(email: string): string { const [username, domain] = email.split("@"); diff --git a/src/app/api/v1/contests/route.tsx b/src/app/api/v1/contests/route.tsx index e9af56ec..2cdf83a6 100644 --- a/src/app/api/v1/contests/route.tsx +++ b/src/app/api/v1/contests/route.tsx @@ -17,12 +17,9 @@ export type ContestCreateError = | APIForbiddenErrorType | APIValidationErrorType; -export type ContestCreateSuccess = APISuccessResponse<{ id: string }> - -export type ContestCreateResponse = - | ContestCreateError - | ContestCreateSuccess; +export type ContestCreateSuccess = APISuccessResponse<{ id: string }>; +export type ContestCreateResponse = ContestCreateError | ContestCreateSuccess; export async function POST(request: NextRequest): Promise> { const session = await getSession(request); @@ -46,9 +43,12 @@ export async function POST(request: NextRequest): Promise 0) { - return NextResponse.json(customValidationError({ - slug: ["Slug already exists"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + slug: ["Slug already exists"], + }), + { status: 400 } + ); } const dbContest = await trx @@ -66,8 +66,10 @@ export async function POST(request: NextRequest): Promise; -export type ProblemSetCreateSuccess = APISuccessResponse<{ id: string }> - -export type ProblemSetCreateResponse = - | ProblemSetCreateError - | ProblemSetCreateSuccess; +export type ProblemSetCreateSuccess = APISuccessResponse<{ id: string }>; +export type ProblemSetCreateResponse = ProblemSetCreateError | ProblemSetCreateSuccess; export async function POST(request: NextRequest): Promise> { const session = await getSession(request); @@ -46,9 +43,12 @@ export async function POST(request: NextRequest): Promise 0) { - return NextResponse.json(customValidationError({ - slug: ["Slug already exists"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + slug: ["Slug already exists"], + }), + { status: 400 } + ); } const dbProblemSet = await trx @@ -65,8 +65,10 @@ export async function POST(request: NextRequest): Promise; export type CreateSubmissionError = APIValidationErrorCustomType; @@ -41,9 +41,12 @@ export async function POST(request: NextRequest) { const formData = await request.formData(); const formRequest = formData.get("request") as File; if (!(formRequest instanceof File)) { - return NextResponse.json(customValidationError({ - request: ["Missing File: Request"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + request: ["Missing File: Request"], + }), + { status: 400 } + ); } const jsonRequest = JSON.parse(await formRequest.text()); @@ -62,22 +65,28 @@ export async function POST(request: NextRequest) { .executeTakeFirst(); if (task == null) { - return NextResponse.json(customValidationError({ - task_id: ["Invalid task"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + task_id: ["Invalid task"], + }), + { status: 400 } + ); } else if (!task.is_public && !canManageTasks(session)) { return NextResponse.json(APIForbiddenError, { status: 401 }); } if (!isAllowedLanguage(task.type, task.allowed_languages, submissionReq.language)) { - return NextResponse.json(customValidationError({ - language: ["Invalid language"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + language: ["Invalid language"], + }), + { status: 400 } + ); } let sources: SubmissionFileCreate[]; - if (task.type === TaskType.OutputOnly) { + if (task.type === TaskType.OutputOnly) { const allowedFileNameList = await loadAllowedFilenames(submissionReq.task_id); const allowedFileNames = new Set(allowedFileNameList); @@ -105,9 +114,12 @@ export async function POST(request: NextRequest) { } else { const formSource = formData.get("source"); if (!(formSource instanceof File)) { - return NextResponse.json(customValidationError({ - request: ["Missing File: Source"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + request: ["Missing File: Source"], + }), + { status: 400 } + ); } sources = [ { @@ -118,9 +130,12 @@ export async function POST(request: NextRequest) { } if (!areAllowedFileSizes(sources, task.submission_size_limit_byte)) { - return NextResponse.json(customValidationError({ - file_size: ["Submission files are too big"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + file_size: ["Submission files are too big"], + }), + { status: 400 } + ); } const submission = await createSubmission(sources, submissionReq, session.user); diff --git a/src/app/api/v1/tasks/[id]/kg/route.ts b/src/app/api/v1/tasks/[id]/kg/route.ts index 0b95246d..4f416b9c 100644 --- a/src/app/api/v1/tasks/[id]/kg/route.ts +++ b/src/app/api/v1/tasks/[id]/kg/route.ts @@ -2,7 +2,11 @@ import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { TaskType } from "common/types/constants"; import { REGEX_SLUG } from "common/validation/common_validation"; -import { zTaskSubtaskBatch, zTaskSubtaskCommunication, zTaskSubtaskOutput } from "common/validation/task_validation"; +import { + zTaskSubtaskBatch, + zTaskSubtaskCommunication, + zTaskSubtaskOutput, +} from "common/validation/task_validation"; import { db } from "db"; import { canManageTasks } from "server/authorization"; import { upsertTaskData, upsertTaskSubtasks } from "server/logic/tasks/update_editor_task"; @@ -54,10 +58,16 @@ const zKgUpdateTaskTypeOutput = z.object({ subtasks: z.array(zTaskSubtaskOutput), }); -const zKgUpdateTaskSchema = z - .discriminatedUnion("type", [zKgUpdateTaskTypeBatch, zKgUpdateTaskTypeOutput, zKgUpdateTaskTypeCommunication]); +const zKgUpdateTaskSchema = z.discriminatedUnion("type", [ + zKgUpdateTaskTypeBatch, + zKgUpdateTaskTypeOutput, + zKgUpdateTaskTypeCommunication, +]); -type KgTaskDTO = z.infer | z.infer | z.infer; +type KgTaskDTO = + | z.infer + | z.infer + | z.infer; async function updateKgTask(task: KgTaskDTO) { return db.transaction().execute(async (trx) => { @@ -72,15 +82,7 @@ async function updateKgTask(task: KgTaskDTO) { time_limit_ms: "time_limit_ms" in task ? task.time_limit_ms : null, }) .where("id", "=", task.id) - .returning([ - "id", - "type", - "slug", - "title", - "is_public", - "score_max", - "time_limit_ms", - ]) + .returning(["id", "type", "slug", "title", "is_public", "score_max", "time_limit_ms"]) .executeTakeFirstOrThrow(); // eslint-disable-next-line @typescript-eslint/no-unused-vars -- pre-existing error before eslint inclusion @@ -96,6 +98,6 @@ async function updateKgTask(task: KgTaskDTO) { id: dbTask.id, slug: dbTask.slug, title: dbTask.title, - } + }; }); } diff --git a/src/app/api/v1/tasks/[id]/score_overall/route.ts b/src/app/api/v1/tasks/[id]/score_overall/route.ts index 48df095e..08eaf5fe 100644 --- a/src/app/api/v1/tasks/[id]/score_overall/route.ts +++ b/src/app/api/v1/tasks/[id]/score_overall/route.ts @@ -26,11 +26,14 @@ export async function GET(request: NextRequest, context: NextContext { if (a.id === uuid) { diff --git a/src/app/api/v1/tasks/files/route.ts b/src/app/api/v1/tasks/files/route.ts index 46f829db..ac358a21 100644 --- a/src/app/api/v1/tasks/files/route.ts +++ b/src/app/api/v1/tasks/files/route.ts @@ -8,7 +8,7 @@ import { getSession } from "server/sessions"; function isFile(obj: FormDataEntryValue): obj is File { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- pre-existing error before eslint inclusion - return typeof (obj as any)['arrayBuffer'] === 'function'; + return typeof (obj as any)["arrayBuffer"] === "function"; } export async function POST(request: NextRequest) { @@ -21,7 +21,7 @@ export async function POST(request: NextRequest) { } const formData = await request.formData(); - const file = formData.get('file'); + const file = formData.get("file"); if (file == null || !isFile(file)) { return NextResponse.json({ error: "File not attached" }, { status: 400 }); } diff --git a/src/app/api/v1/tasks/route.ts b/src/app/api/v1/tasks/route.ts index d3e751ba..429c049b 100644 --- a/src/app/api/v1/tasks/route.ts +++ b/src/app/api/v1/tasks/route.ts @@ -35,7 +35,6 @@ export async function POST(request: NextRequest) { task.id = dbTasks[0].id; // overwrite the dummy value await updateEditorTask(task); return NextResponse.json(task); - } else { return NextResponse.json({ error: parsed.error.format() }, { status: 400 }); } diff --git a/src/app/api/v1/tasks/simple/route.ts b/src/app/api/v1/tasks/simple/route.ts index 50bdf4b3..a06dbbf4 100644 --- a/src/app/api/v1/tasks/simple/route.ts +++ b/src/app/api/v1/tasks/simple/route.ts @@ -22,10 +22,7 @@ export type TaskCreateSimpleError = export type TaskCreateSimpleSuccess = APISuccessResponse<{ id: string }>; -export type TaskCreateSimpleResponse = - | TaskCreateSimpleError - | TaskCreateSimpleSuccess; - +export type TaskCreateSimpleResponse = TaskCreateSimpleError | TaskCreateSimpleSuccess; export async function POST(request: NextRequest): Promise> { const session = await getSession(request); @@ -49,9 +46,12 @@ export async function POST(request: NextRequest): Promise 0) { - return NextResponse.json(customValidationError({ - slug: ["Slug already exists"], - }), { status: 400 }); + return NextResponse.json( + customValidationError({ + slug: ["Slug already exists"], + }), + { status: 400 } + ); } const dbTask = await trx @@ -60,7 +60,7 @@ export async function POST(request: NextRequest): Promise; + return ; } const lookup = await findFromSlugOrHID(props.params.slug); diff --git a/src/app/contests/[slug]/page.tsx b/src/app/contests/[slug]/page.tsx index 66093796..9ea36d72 100644 --- a/src/app/contests/[slug]/page.tsx +++ b/src/app/contests/[slug]/page.tsx @@ -9,7 +9,10 @@ import { getSession } from "server/sessions"; import { ContestViewerDTO, TaskScoredSummaryDTO, TaskSummaryDTO } from "common/types"; import { ContestViewer } from "client/components/contest_viewer/contest_viewer"; -async function getContestData(slug: string, userId: string | null): Promise { +async function getContestData( + slug: string, + userId: string | null +): Promise { return db.transaction().execute(async (trx) => { const contest = await trx .selectFrom("contests") @@ -26,7 +29,7 @@ async function getContestData(slug: string, userId: string | null): Promise + .leftJoin("overall_verdicts", (join) => join .onRef("overall_verdicts.task_id", "=", "tasks.id") .on("overall_verdicts.user_id", "=", userId) @@ -81,9 +84,9 @@ export async function generateMetadata(props: ContestPageProps): Promise - ) + ); } return ( diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3012b179..bfa20ba3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -9,7 +9,7 @@ import { ToastContainer, Zoom } from "react-toastify"; import classNames from "classnames"; import { SessionProvider } from "client/sessions"; import { getSession } from "server/sessions"; -import HuradoPNG from "assets/images/hurado.png" +import HuradoPNG from "assets/images/hurado.png"; const fontMontserrat = Montserrat({ subsets: ["latin"], @@ -63,7 +63,7 @@ const RootLayout: FunctionComponent = async ({ children }) => { closeButton={false} /> {children} -