From be860a0b8f9e2319f5a5eb8500f02666589b81c5 Mon Sep 17 00:00:00 2001 From: Kwon Seo Jin <97675977+B0XERCAT@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:52:39 +0900 Subject: [PATCH 01/10] fix(fe): fix score sum bug (#2231) --- .../app/admin/contest/_components/ContestProblemColumns.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/app/admin/contest/_components/ContestProblemColumns.tsx b/apps/frontend/app/admin/contest/_components/ContestProblemColumns.tsx index 60e7881628..b881e0d65d 100644 --- a/apps/frontend/app/admin/contest/_components/ContestProblemColumns.tsx +++ b/apps/frontend/app/admin/contest/_components/ContestProblemColumns.tsx @@ -92,7 +92,7 @@ export const createColumns = ( row.original) .reduce((total, problem) => total + problem.score, 0)} From 9e7bebb2a3dae33082e97eb4cada8db96336310b Mon Sep 17 00:00:00 2001 From: Woojin Jung <44637040+jwoojin9@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:14:29 +0900 Subject: [PATCH 02/10] feat(fe): refresh problems dropdown list after submit (#2212) * feat(fe): refresh problems dropdown list after submit * fix(fe): make dropdown component * chore(fe): fix code * feat(fe): add submission result store * fix(fe): use tanstack query * fix(fe): use tanstack query * fix(fe): move code * fix(fe): resolve infinite rendering problem * fix(fe): resolve review * chore(fe): apply code review --------- Co-authored-by: Kohminchae <72334086+Kohminchae@users.noreply.github.com> Co-authored-by: Kohminchae --- .../_components/ContestProblemDropdown.tsx | 69 +++++++++++++++++++ .../_components/EditorHeader/EditorHeader.tsx | 6 ++ .../_components/EditorLayout.tsx | 63 +++-------------- apps/frontend/stores/editor.ts | 1 + 4 files changed, 85 insertions(+), 54 deletions(-) create mode 100644 apps/frontend/app/(client)/(code-editor)/_components/ContestProblemDropdown.tsx diff --git a/apps/frontend/app/(client)/(code-editor)/_components/ContestProblemDropdown.tsx b/apps/frontend/app/(client)/(code-editor)/_components/ContestProblemDropdown.tsx new file mode 100644 index 0000000000..335dab63c2 --- /dev/null +++ b/apps/frontend/app/(client)/(code-editor)/_components/ContestProblemDropdown.tsx @@ -0,0 +1,69 @@ +'use client' + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger +} from '@/components/shadcn/dropdown-menu' +import { cn, convertToLetter, fetcherWithAuth } from '@/libs/utils' +import checkIcon from '@/public/icons/check-green.svg' +import type { ContestProblem, ProblemDetail } from '@/types/type' +import { useQuery } from '@tanstack/react-query' +import Image from 'next/image' +import Link from 'next/link' +import { FaSortDown } from 'react-icons/fa' + +interface ContestProblemsResponse { + data: ContestProblem[] + total: number +} + +interface ContestProblemDropdownProps { + problem: ProblemDetail + problemId: number + contestId: number +} + +export default function ContestProblemDropdown({ + problem, + problemId, + contestId +}: ContestProblemDropdownProps) { + const { data: contestProblems } = useQuery< + ContestProblemsResponse | undefined + >({ + queryKey: ['contest', contestId, 'problems'], + queryFn: () => + fetcherWithAuth.get(`contest/${contestId}/problem?take=20`).json() + }) + + return ( + + +

{`${convertToLetter(contestProblems?.data.find((item) => item.id === Number(problemId))?.order as number)}. ${problem.title}`}

+ +
+ + {contestProblems?.data.map((p) => ( + + + {`${convertToLetter(p.order)}. ${p.title}`} + {p.submissionTime && ( +
+ check +
+ )} +
+ + ))} +
+
+ ) +} diff --git a/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx b/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx index c16cafbf03..7b727fcd43 100644 --- a/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx +++ b/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx @@ -36,6 +36,7 @@ import type { Submission, Template } from '@/types/type' +import { useQueryClient } from '@tanstack/react-query' import JSConfetti from 'js-confetti' import { Save } from 'lucide-react' import type { Route } from 'next' @@ -83,6 +84,8 @@ export default function Editor({ const whereToPush = useRef('') const isModalConfrimed = useRef(false) + const queryClient = useQueryClient() + useInterval( async () => { const res = await fetcherWithAuth(`submission/${submissionId}`, { @@ -186,6 +189,9 @@ export default function Editor({ storeCodeToLocalStorage(code) const submission: Submission = await res.json() setSubmissionId(submission.id) + queryClient.refetchQueries({ + queryKey: ['contest', contestId, 'problems'] + }) } else { setIsSubmitting(false) if (res.status === 401) { diff --git a/apps/frontend/app/(client)/(code-editor)/_components/EditorLayout.tsx b/apps/frontend/app/(client)/(code-editor)/_components/EditorLayout.tsx index 6c81a48496..4e67da54ef 100644 --- a/apps/frontend/app/(client)/(code-editor)/_components/EditorLayout.tsx +++ b/apps/frontend/app/(client)/(code-editor)/_components/EditorLayout.tsx @@ -1,21 +1,14 @@ import ContestStatusTimeDiff from '@/components/ContestStatusTimeDiff' import HeaderAuthPanel from '@/components/auth/HeaderAuthPanel' -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger -} from '@/components/shadcn/dropdown-menu' import { auth } from '@/libs/auth' -import { cn, convertToLetter, fetcher, fetcherWithAuth } from '@/libs/utils' -import checkIcon from '@/public/icons/check-green.svg' +import { fetcher, fetcherWithAuth } from '@/libs/utils' import codedangLogo from '@/public/logos/codedang-editor.svg' -import type { Contest, ContestProblem, ProblemDetail } from '@/types/type' +import type { Contest, ProblemDetail } from '@/types/type' import type { Route } from 'next' import Image from 'next/image' import Link from 'next/link' import { redirect } from 'next/navigation' -import { FaSortDown } from 'react-icons/fa' +import ContestProblemDropdown from './ContestProblemDropdown' import EditorMainResizablePanel from './EditorResizablePanel' interface EditorLayoutProps { @@ -24,25 +17,16 @@ interface EditorLayoutProps { children: React.ReactNode } -interface ContestProblemProps { - data: ContestProblem[] - total: number -} - export default async function EditorLayout({ contestId, problemId, children }: EditorLayoutProps) { - let problems: ContestProblemProps | undefined let contest: Contest | undefined let problem: ProblemDetail if (contestId) { // for getting contest info and problems list - problems = await fetcherWithAuth - .get(`contest/${contestId}/problem?take=20`) - .json() const res = await fetcherWithAuth( `contest/${contestId}/problem/${problemId}` ) @@ -72,46 +56,17 @@ export default async function EditorLayout({
{contest ? <>Contest : Problem}

/

- {contest ? ( + {contest && contestId ? ( <> {contest.title}

/

- - -

{`${convertToLetter(problems?.data.find((item) => item.id === Number(problemId))?.order as number)}. ${problem.title}`}

- -
- - {problems?.data.map((p: ContestProblem) => ( - - - {`${convertToLetter(p.order)}. ${p.title}`} - {p.submissionTime && ( -
- check -
- )} -
- - ))} -
-
+ ) : (

{`#${problem.id}. ${problem.title}`}

diff --git a/apps/frontend/stores/editor.ts b/apps/frontend/stores/editor.ts index d80aedc3ac..699ebc0861 100644 --- a/apps/frontend/stores/editor.ts +++ b/apps/frontend/stores/editor.ts @@ -23,6 +23,7 @@ export const useLanguageStore = (problemId: number, contestId?: number) => { ) ) } + interface CodeState { code: string setCode: (code: string) => void From 6071189d067adbec3ccdf347fe9ff26975218d31 Mon Sep 17 00:00:00 2001 From: Kohminchae <72334086+Kohminchae@users.noreply.github.com> Date: Fri, 22 Nov 2024 20:47:08 +0900 Subject: [PATCH 03/10] fix(fe): add fetch policy to useSuspenseQuery (#2229) * fix(fe): add fetch policy * fix(fe): use refetch * fix(fe): resolve build failed --- .../edit/_components/ScoreCautionDialog.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx b/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx index 85a883ff8d..9550598aec 100644 --- a/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx +++ b/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx @@ -7,6 +7,7 @@ import { DialogHeader, DialogTitle } from '@/components/shadcn/dialog' +import { GET_BELONGED_CONTESTS } from '@/graphql/contest/queries' import { UPDATE_CONTEST_PROBLEMS_SCORES } from '@/graphql/problem/mutations' import { useMutation } from '@apollo/client' import { Suspense, useState } from 'react' @@ -29,7 +30,15 @@ export function ScoreCautionDialog({ problemId }: ScoreCautionDialogProps) { const [updateContestsProblemsScores] = useMutation( - UPDATE_CONTEST_PROBLEMS_SCORES + UPDATE_CONTEST_PROBLEMS_SCORES, + { + refetchQueries: [ + { + query: GET_BELONGED_CONTESTS, + variables: { problemId } + } + ] + } ) const [zeroSetContests, setZeroSetContests] = useState([]) From 74447757174290c08927ae7cb608917c52a2114c Mon Sep 17 00:00:00 2001 From: KIM HYOJUNG Date: Sat, 23 Nov 2024 10:40:23 +0900 Subject: [PATCH 04/10] fix(fe): enable scrolling in modal content (#2230) --- .../edit/_components/BelongedContestTableColumns.tsx | 10 ++++++---- .../edit/_components/ScoreCautionDialog.tsx | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTableColumns.tsx b/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTableColumns.tsx index 0577d56a50..b5d19dfe4b 100644 --- a/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTableColumns.tsx +++ b/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTableColumns.tsx @@ -44,7 +44,7 @@ export const columns: ColumnDef[] = [ ), cell: ({ row }) => ( -

+

{row.getValue('title')}

), @@ -57,7 +57,9 @@ export const columns: ColumnDef[] = [

State

), cell: ({ row }) => ( -

{row.getValue('state')}

+

+ {row.getValue('state')} +

) }, { @@ -68,7 +70,7 @@ export const columns: ColumnDef[] = [ cell: ({ row }) => (

@@ -84,7 +86,7 @@ export const columns: ColumnDef[] = [ cell: ({ row }) => (

diff --git a/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx b/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx index 9550598aec..c4664b8ce3 100644 --- a/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx +++ b/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx @@ -45,7 +45,7 @@ export function ScoreCautionDialog({ return (

- + Are you sure you want to edit this problem? From bf8a4a6607ba27be7066677c0739da713c9d0b05 Mon Sep 17 00:00:00 2001 From: KIM HYOJUNG Date: Sat, 23 Nov 2024 10:40:57 +0900 Subject: [PATCH 05/10] fix(fe): add submission detail modal on participant (#2228) --- .../_components/SubmissionTable.tsx | 2 +- .../contest/[contestId]/(overall)/layout.tsx | 6 +-- .../_components/ContestOverallTabs.tsx | 13 +++++-- .../_components/SubmissionDetailAdmin.tsx | 0 .../[userId]/_components/SubmissionTable.tsx | 38 ++++++++++++++----- 5 files changed, 42 insertions(+), 17 deletions(-) rename apps/frontend/app/admin/contest/[contestId]/{(overall)/@tabs/submission => }/_components/SubmissionDetailAdmin.tsx (100%) diff --git a/apps/frontend/app/admin/contest/[contestId]/(overall)/@tabs/submission/_components/SubmissionTable.tsx b/apps/frontend/app/admin/contest/[contestId]/(overall)/@tabs/submission/_components/SubmissionTable.tsx index a76aabfc6f..5187ff9a3b 100644 --- a/apps/frontend/app/admin/contest/[contestId]/(overall)/@tabs/submission/_components/SubmissionTable.tsx +++ b/apps/frontend/app/admin/contest/[contestId]/(overall)/@tabs/submission/_components/SubmissionTable.tsx @@ -6,12 +6,12 @@ import DataTablePagination from '@/app/admin/_components/table/DataTablePaginati import DataTableProblemFilter from '@/app/admin/_components/table/DataTableProblemFilter' import DataTableRoot from '@/app/admin/_components/table/DataTableRoot' import DataTableSearchBar from '@/app/admin/_components/table/DataTableSearchBar' +import SubmissionDetailAdmin from '@/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin' import { Dialog, DialogContent } from '@/components/shadcn/dialog' import { GET_CONTEST_SUBMISSIONS } from '@/graphql/submission/queries' import { useSuspenseQuery } from '@apollo/client' import { useState } from 'react' import { columns } from './Columns' -import SubmissionDetailAdmin from './SubmissionDetailAdmin' export function SubmissionTable({ contestId }: { contestId: number }) { const { data } = useSuspenseQuery(GET_CONTEST_SUBMISSIONS, { diff --git a/apps/frontend/app/admin/contest/[contestId]/(overall)/layout.tsx b/apps/frontend/app/admin/contest/[contestId]/(overall)/layout.tsx index 7d3e281a82..c6c425af70 100644 --- a/apps/frontend/app/admin/contest/[contestId]/(overall)/layout.tsx +++ b/apps/frontend/app/admin/contest/[contestId]/(overall)/layout.tsx @@ -13,12 +13,10 @@ import ContestOverallTabs from '../_components/ContestOverallTabs' export default function Layout({ params, - tabs, - userId + tabs }: { params: { contestId: string } tabs: React.ReactNode - userId: number }) { const { contestId } = params @@ -60,7 +58,7 @@ export default function Layout({ content={contestData?.description} classname="prose mb-4 w-full max-w-full border-y-2 border-y-gray-300 p-5 py-12" /> - + {tabs} ) diff --git a/apps/frontend/app/admin/contest/[contestId]/_components/ContestOverallTabs.tsx b/apps/frontend/app/admin/contest/[contestId]/_components/ContestOverallTabs.tsx index 484e697d19..b705044b44 100644 --- a/apps/frontend/app/admin/contest/[contestId]/_components/ContestOverallTabs.tsx +++ b/apps/frontend/app/admin/contest/[contestId]/_components/ContestOverallTabs.tsx @@ -30,15 +30,22 @@ interface SubmissionSummary { } export default function ContestOverallTabs({ - contestId, - userId + contestId }: { contestId: string - userId: number }) { const id = parseInt(contestId, 10) const pathname = usePathname() + const { data: userData } = useQuery<{ + getUserIdByContest: { userId: number } + }>(GET_CONTEST_SCORE_SUMMARIES, { + variables: { contestId: id }, + skip: !contestId + }) + + const userId = userData?.getUserIdByContest?.userId + const { data: scoreData } = useQuery<{ getContestScoreSummaries: ScoreSummary[] }>(GET_CONTEST_SCORE_SUMMARIES, { diff --git a/apps/frontend/app/admin/contest/[contestId]/(overall)/@tabs/submission/_components/SubmissionDetailAdmin.tsx b/apps/frontend/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin.tsx similarity index 100% rename from apps/frontend/app/admin/contest/[contestId]/(overall)/@tabs/submission/_components/SubmissionDetailAdmin.tsx rename to apps/frontend/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin.tsx diff --git a/apps/frontend/app/admin/contest/[contestId]/participant/[userId]/_components/SubmissionTable.tsx b/apps/frontend/app/admin/contest/[contestId]/participant/[userId]/_components/SubmissionTable.tsx index 8414716c6e..2f9aa00d82 100644 --- a/apps/frontend/app/admin/contest/[contestId]/participant/[userId]/_components/SubmissionTable.tsx +++ b/apps/frontend/app/admin/contest/[contestId]/participant/[userId]/_components/SubmissionTable.tsx @@ -5,8 +5,11 @@ import DataTableFallback from '@/app/admin/_components/table/DataTableFallback' import DataTablePagination from '@/app/admin/_components/table/DataTablePagination' import DataTableProblemFilter from '@/app/admin/_components/table/DataTableProblemFilter' import DataTableRoot from '@/app/admin/_components/table/DataTableRoot' +import SubmissionDetailAdmin from '@/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin' +import { Dialog, DialogContent } from '@/components/shadcn/dialog' import { GET_CONTEST_SUBMISSION_SUMMARIES_OF_USER } from '@/graphql/contest/queries' import { useSuspenseQuery } from '@apollo/client' +import { useState } from 'react' import { submissionColumns } from './SubmissionColumns' export function SubmissionTable({ @@ -22,20 +25,37 @@ export function SubmissionTable({ variables: { contestId, userId, take: 1000 } } ) + const [isSubmissionDialogOpen, setIsSubmissionDialogOpen] = useState(false) + const [submissionId, setSubmissionId] = useState(0) const submissionsData = submissions.data.getContestSubmissionSummaryByUserId.submissions return ( - - - - - + <> + + + { + setSubmissionId(row.original.id) + setIsSubmissionDialogOpen(true) + }} + /> + + + + + + + + ) } From b71e24a9520d116d574bac297dcde27205d5dafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=ED=98=95?= <80684730+juhyeong0505@users.noreply.github.com> Date: Sat, 23 Nov 2024 11:28:54 +0900 Subject: [PATCH 06/10] fix(fe): differentiate sample and user id (#2218) * fix(fe): differentiate sample and user id * chore(fe): fix-code-style-because-of-repetition-of-logic * fix(fe): modify variable name, fix TestResultDetail bug --------- Co-authored-by: b0xercat --- .../TestcasePanel/TestcasePanel.tsx | 26 +++++++++---------- .../TestcasePanel/useTestResults.ts | 11 ++++++-- apps/frontend/types/type.ts | 1 + 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/TestcasePanel.tsx b/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/TestcasePanel.tsx index b8d9d05b93..a1eae46c0a 100644 --- a/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/TestcasePanel.tsx +++ b/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/TestcasePanel.tsx @@ -20,15 +20,15 @@ export default function TestcasePanel() { .concat(result) .filter( (item, index, self) => - index === self.findIndex((t) => t.id === item.id) + index === self.findIndex((t) => t.originalId === item.originalId) ) ) - setCurrentTab(result.id) + setCurrentTab(result.originalId) } const removeTab = (testcaseId: number) => { setTestcaseTabList((state) => - state.filter((item) => item.id !== testcaseId) + state.filter((item) => item.originalId !== testcaseId) ) if (currentTab === testcaseId) { setCurrentTab(0) @@ -56,7 +56,7 @@ export default function TestcasePanel() { setCurrentTab(0)} - nextTab={testcaseTabList[0]?.id} + nextTab={testcaseTabList[0]?.originalId} className="flex-shrink-0" > {testcaseTabList.length < 7 ? 'Testcase Result' : 'TC Res'} @@ -72,12 +72,12 @@ export default function TestcasePanel() { {testcaseTabList.map((testcase, index) => ( setCurrentTab(testcase.id)} - onClickCloseButton={() => removeTab(testcase.id)} - testcaseId={testcase.id} - key={testcase.id} + prevTab={testcaseTabList[index - 1]?.originalId} + nextTab={testcaseTabList[index + 1]?.originalId} + onClickTab={() => setCurrentTab(testcase.originalId)} + onClickCloseButton={() => removeTab(testcase.originalId)} + testcaseId={testcase.originalId} + key={testcase.originalId} > { (testcaseTabList.length < 7 @@ -117,7 +117,7 @@ export default function TestcasePanel() {
) : ( item.id === currentTab)} + data={processedData.find((item) => item.originalId === currentTab)} /> )} @@ -200,9 +200,9 @@ function TestSummary({ const total = data.length const notAcceptedTestcases = data - .map((testcase, index) => + .map((testcase) => testcase.result !== 'Accepted' - ? `${testcase.isUserTestcase ? 'User' : 'Sample'} #${index + 1}` + ? `${testcase.isUserTestcase ? 'User' : 'Sample'} #${testcase.id}` : -1 ) .filter((index) => index !== -1) diff --git a/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/useTestResults.ts b/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/useTestResults.ts index bf3cac0be9..1d18395b27 100644 --- a/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/useTestResults.ts +++ b/apps/frontend/app/(client)/(code-editor)/_components/TestcasePanel/useTestResults.ts @@ -85,13 +85,20 @@ export const useTestResults = () => { }) const testcases = useTestcaseStore((state) => state.getTestcases()) + let userTestcaseCount = 1 + let sampleTestcaseCount = 1 const testResults = data.length > 0 ? testcases.map((testcase, index) => { const testResult = data.find((item) => item.id === testcase.id) + if (testcase.isUserTestcase) { + testcase.id = userTestcaseCount++ + } else { + testcase.id = sampleTestcaseCount++ + } return { - id: index + 1, - originalId: testcase.id, + id: testcase.id, + originalId: index + 1, input: testcase.input, expectedOutput: testcase.output, output: testResult?.output ?? '', diff --git a/apps/frontend/types/type.ts b/apps/frontend/types/type.ts index 63a5aec25c..47147ea6de 100644 --- a/apps/frontend/types/type.ts +++ b/apps/frontend/types/type.ts @@ -184,6 +184,7 @@ export interface TestResultDetail extends TestResult { input: string expectedOutput: string isUserTestcase: boolean + originalId: number } export interface SettingsFormat { From 4ed9e3efd02c0044d37d252b7c48bd63c25ba122 Mon Sep 17 00:00:00 2001 From: Kohminchae <72334086+Kohminchae@users.noreply.github.com> Date: Sat, 23 Nov 2024 11:54:32 +0900 Subject: [PATCH 07/10] fix(fe): comment out popstate (#2233) * fix(fe): clearly stated the pushState url * fix(fe): fix url * fix(fe): remove popstate * chore(fe): add TODO --- .../_components/EditorHeader/EditorHeader.tsx | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx b/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx index 7b727fcd43..917ecbfdf1 100644 --- a/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx +++ b/apps/frontend/app/(client)/(code-editor)/_components/EditorHeader/EditorHeader.tsx @@ -80,7 +80,7 @@ export default function Editor({ ) const { currentModal, showSignIn } = useAuthModalStore((state) => state) const [showModal, setShowModal] = useState(false) - const pushed = useRef(false) + //const pushed = useRef(false) const whereToPush = useRef('') const isModalConfrimed = useRef(false) @@ -102,7 +102,7 @@ export default function Editor({ ? `/contest/${contestId}/problem/${problem.id}/submission/${submissionId}` : `/problem/${problem.id}/submission/${submissionId}` router.replace(href as Route) - window.history.pushState(null, '', '') + //window.history.pushState(null, '', window.location.href) if (submission.result === 'Accepted') { confetti?.addConfetti() } @@ -249,22 +249,26 @@ export default function Editor({ contestId ) - const handlePopState = () => { - if (!checkSaved()) { - whereToPush.current = contestId ? `/contest/${contestId}` : '/problem' - setShowModal(true) - } else window.history.back() - } - if (!pushed.current) { - window.history.pushState(null, '', '') - pushed.current = true - } + // TODO: 배포 후 뒤로 가기 로직 재구현 + + // const handlePopState = () => { + // if (!checkSaved()) { + // whereToPush.current = contestId + // ? `/contest/${contestId}/problem` + // : '/problem' + // setShowModal(true) + // } else window.history.back() + // } + // if (!pushed.current) { + // window.history.pushState(null, '', window.location.href) + // pushed.current = true + // } window.addEventListener('beforeunload', handleBeforeUnload) - window.addEventListener('popstate', handlePopState) + //window.addEventListener('popstate', handlePopState) return () => { window.removeEventListener('beforeunload', handleBeforeUnload) - window.removeEventListener('popstate', handlePopState) + //window.removeEventListener('popstate', handlePopState) } }, []) From 7027bab69e16f9d1bbe7b70533192d725bff26fa Mon Sep 17 00:00:00 2001 From: Jimin Ha Date: Sat, 23 Nov 2024 22:40:18 +0900 Subject: [PATCH 08/10] feat(fe): add testcase judge results not available alert when testcase is outdated (#2235) feat(fe): add Testcase Judge Results Not Available Alert when testcase is outdated --- .../_components/SubmissionDetailAdmin.tsx | 33 +++++++---- apps/frontend/components/shadcn/alert.tsx | 58 +++++++++++++++++++ 2 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 apps/frontend/components/shadcn/alert.tsx diff --git a/apps/frontend/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin.tsx b/apps/frontend/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin.tsx index 23fc081669..63dee729f7 100644 --- a/apps/frontend/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin.tsx +++ b/apps/frontend/app/admin/contest/[contestId]/_components/SubmissionDetailAdmin.tsx @@ -1,6 +1,7 @@ 'use client' import CodeEditor from '@/components/CodeEditor' +import { Alert, AlertDescription, AlertTitle } from '@/components/shadcn/alert' import { ScrollArea, ScrollBar } from '@/components/shadcn/scroll-area' import { Table, @@ -15,6 +16,7 @@ import { GET_SUBMISSION } from '@/graphql/submission/queries' import { dateFormatter, getResultColor } from '@/libs/utils' import type { Language } from '@/types/type' import { useLazyQuery, useQuery } from '@apollo/client' +import { IoWarning } from 'react-icons/io5' export default function SubmissionDetailAdmin({ submissionId @@ -125,9 +127,10 @@ export default function SubmissionDetailAdmin({ - {submission?.testcaseResult.length !== 0 && ( -
-

Testcase

+ +

Testcase

+ {submission?.testcaseResult.length !== 0 ? ( +
@@ -201,16 +204,22 @@ export default function SubmissionDetailAdmin({
+ ) : ( + + + Testcase Judge Results Not Available + + The testcases have been recently updated and are now outdated. + + )} -
-

Source Code

- -
+

Source Code

+
)} diff --git a/apps/frontend/components/shadcn/alert.tsx b/apps/frontend/components/shadcn/alert.tsx new file mode 100644 index 0000000000..808f3865f1 --- /dev/null +++ b/apps/frontend/components/shadcn/alert.tsx @@ -0,0 +1,58 @@ +import { cn } from '@/libs/utils' +import { cva, type VariantProps } from 'class-variance-authority' +import * as React from 'react' + +const alertVariants = cva( + 'relative w-full rounded-lg border border-gray-200 px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-gray-950 [&>svg~*]:pl-7 dark:border-gray-800 dark:[&>svg]:text-gray-50', + { + variants: { + variant: { + default: 'bg-white text-gray-950 dark:bg-gray-950 dark:text-gray-50', + destructive: + 'border-red-500/50 text-red-500 dark:border-red-500 [&>svg]:text-red-500 dark:border-red-900/50 dark:text-red-900 dark:dark:border-red-900 dark:[&>svg]:text-red-900' + } + }, + defaultVariants: { + variant: 'default' + } + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = 'Alert' + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = 'AlertTitle' + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = 'AlertDescription' + +export { Alert, AlertTitle, AlertDescription } From 3f41ce0f29c461733e84cff43b28ed8438614667 Mon Sep 17 00:00:00 2001 From: Kohminchae <72334086+Kohminchae@users.noreply.github.com> Date: Sat, 23 Nov 2024 23:50:53 +0900 Subject: [PATCH 09/10] fix(fe): add fetch policy to useSuspenseQuery (#2236) fix(fe): add fetch policy --- .../edit/_components/BelongedContestTable.tsx | 4 +++- .../edit/_components/ScoreCautionDialog.tsx | 11 +---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTable.tsx b/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTable.tsx index 524e29ec24..83490305c7 100644 --- a/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTable.tsx +++ b/apps/frontend/app/admin/problem/[problemId]/edit/_components/BelongedContestTable.tsx @@ -24,7 +24,9 @@ export function BelongedContestTable({ const { data } = useSuspenseQuery(GET_BELONGED_CONTESTS, { variables: { problemId - } + }, + // TODO: 필요시 refetch 하도록 수정 + fetchPolicy: 'network-only' }) useEffect(() => { diff --git a/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx b/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx index c4664b8ce3..85c6bed62a 100644 --- a/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx +++ b/apps/frontend/app/admin/problem/[problemId]/edit/_components/ScoreCautionDialog.tsx @@ -7,7 +7,6 @@ import { DialogHeader, DialogTitle } from '@/components/shadcn/dialog' -import { GET_BELONGED_CONTESTS } from '@/graphql/contest/queries' import { UPDATE_CONTEST_PROBLEMS_SCORES } from '@/graphql/problem/mutations' import { useMutation } from '@apollo/client' import { Suspense, useState } from 'react' @@ -30,15 +29,7 @@ export function ScoreCautionDialog({ problemId }: ScoreCautionDialogProps) { const [updateContestsProblemsScores] = useMutation( - UPDATE_CONTEST_PROBLEMS_SCORES, - { - refetchQueries: [ - { - query: GET_BELONGED_CONTESTS, - variables: { problemId } - } - ] - } + UPDATE_CONTEST_PROBLEMS_SCORES ) const [zeroSetContests, setZeroSetContests] = useState([]) From 6ab60c70edb2dc2b180da75da61ae83fefc72d54 Mon Sep 17 00:00:00 2001 From: HUNI <110475840+donghun1214@users.noreply.github.com> Date: Sun, 24 Nov 2024 00:40:31 +0900 Subject: [PATCH 10/10] fix(infra): update MQ engine version for compatibility (#2237) --- apps/infra/production/codedang/message_queue_aws.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/infra/production/codedang/message_queue_aws.tf b/apps/infra/production/codedang/message_queue_aws.tf index b4d7c940d9..6a0473c891 100644 --- a/apps/infra/production/codedang/message_queue_aws.tf +++ b/apps/infra/production/codedang/message_queue_aws.tf @@ -23,7 +23,7 @@ resource "aws_mq_broker" "judge_queue" { broker_name = "Codedang-JudgeQueue" engine_type = "RabbitMQ" - engine_version = "3.10.20" + engine_version = "3.11.28" host_instance_type = "mq.t3.micro" subnet_ids = [aws_subnet.private_mq.id] publicly_accessible = true