Skip to content

Commit

Permalink
Frontend submission fixes (#883)
Browse files Browse the repository at this point in the history
Co-authored-by: Lowell Torola <[email protected]>
  • Loading branch information
TheApplePieGod and lowtorola authored Jan 6, 2025
1 parent 2860965 commit a25b3f4
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 92 deletions.
25 changes: 15 additions & 10 deletions frontend/src/api/loaders/scrimmagingLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { buildKey, safeEnsureQueryData } from "../helpers";
import { myTeamFactory, searchTeamsFactory } from "../team/teamFactories";
import {
CompeteMatchScrimmagingRecordRetrieveScrimmageTypeEnum,
Status526Enum,
type Episode,
type TeamPrivate,
} from "api/_autogen";
Expand All @@ -30,17 +31,9 @@ export const scrimmagingLoader =
queryFn: async () => await episodeInfoFactory.queryFn({ id: episodeId }),
});

if ((await episodeData).game_release.getTime() > Date.now()) {
toast.error(
`Scrimmaging page not released yet for ${
(await episodeData).name_long
}.`,
);
return redirect(`/${episodeId}/home`);
}

let teamData: TeamPrivate | null = null;
try {
await queryClient.ensureQueryData<TeamPrivate>({
teamData = await queryClient.ensureQueryData<TeamPrivate>({
queryKey: buildKey(myTeamFactory.queryKey, { episodeId }),
queryFn: async () => await myTeamFactory.queryFn({ episodeId }),
});
Expand All @@ -49,6 +42,18 @@ export const scrimmagingLoader =
return redirect(`/${episodeId}/home`);
}

const isStaffTeam = teamData.status === Status526Enum.S;
if (
!isStaffTeam &&
(await episodeData).game_release.getTime() > Date.now()
) {
toast.error(
`Scrimmaging page not released yet for ${
(await episodeData).name_long
}.`,
);
return redirect(`/${episodeId}/home`);
}
// Outbox
safeEnsureQueryData({ episodeId }, scrimmageInboxListFactory, queryClient);

Expand Down
27 changes: 16 additions & 11 deletions frontend/src/api/loaders/submissionsLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
tournamentSubsListFactory,
} from "../compete/competeFactories";
import { buildKey, safeEnsureQueryData } from "../helpers";
import type { Episode, TeamPrivate } from "api/_autogen";
import { type Episode, Status526Enum, type TeamPrivate } from "api/_autogen";
import { episodeInfoFactory } from "api/episode/episodeFactories";
import { myTeamFactory } from "api/team/teamFactories";
import toast from "react-hot-toast";
Expand All @@ -26,17 +26,9 @@ export const submissionsLoader =
queryFn: async () => await episodeInfoFactory.queryFn({ id: episodeId }),
});

if ((await episodeData).game_release.getTime() > Date.now()) {
toast.error(
`Submissions page not released yet for ${
(await episodeData).name_long
}.`,
);
return redirect(`/${episodeId}/home`);
}

let teamData: TeamPrivate | null = null;
try {
await queryClient.ensureQueryData<TeamPrivate>({
teamData = await queryClient.ensureQueryData<TeamPrivate>({
queryKey: buildKey(myTeamFactory.queryKey, { episodeId }),
queryFn: async () => await myTeamFactory.queryFn({ episodeId }),
});
Expand All @@ -45,6 +37,19 @@ export const submissionsLoader =
return redirect(`/${episodeId}/home`);
}

const isStaffTeam = teamData.status === Status526Enum.S;
if (
!isStaffTeam &&
(await episodeData).game_release.getTime() > Date.now()
) {
toast.error(
`Submissions page not released yet for ${
(await episodeData).name_long
}.`,
);
return redirect(`/${episodeId}/home`);
}

// Submissions list
safeEnsureQueryData({ episodeId, page }, subsListFactory, queryClient);

Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type React from "react";
import SidebarSection from "./SidebarSection";
import type { IconName } from "../elements/Icon";
import type { Episode, TeamPrivate } from "api/_autogen";
import type { UseQueryResult } from "@tanstack/react-query";
import { type Episode, type TeamPrivate, Status526Enum } from "api/_autogen";
import { type AuthState, AuthStateEnum } from "contexts/CurrentUserContext";

interface SidebarProps {
Expand Down Expand Up @@ -132,10 +132,12 @@ export const renderableItems = (
const loggedIn = authState === AuthStateEnum.AUTHENTICATED;

const userHasTeam = userTeam.isSuccess;
const staffTeam = userTeam.data?.status === Status526Enum.S;

return items.filter((itemData) => {
// Ensure that we are allowed to render this item
if (itemData.requireGameReleased && !gameReleased) return false;
if (!staffTeam && itemData.requireGameReleased && !gameReleased)
return false;
if (itemData.userAuthLevel > UserAuthLevel.LOGGED_OUT && !loggedIn)
return false;
if (
Expand Down
218 changes: 149 additions & 69 deletions frontend/src/views/Submissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
import { useQueryClient } from "@tanstack/react-query";
import { useSearchParams } from "react-router-dom";
import { getParamEntries, parsePageParam } from "../utils/searchParamHelpers";
import { useUserTeam } from "api/team/useTeam";
import { Status526Enum, LanguageEnum } from "api/_autogen";

interface SubmissionFormInput {
file: FileList;
Expand Down Expand Up @@ -119,6 +121,7 @@ const Submissions: React.FC = () => {

const CodeSubmission: React.FC = () => {
const { episodeId } = useEpisodeId();
const teamData = useUserTeam({ episodeId });
const queryClient = useQueryClient();

const episode = useEpisodeInfo({ id: episodeId });
Expand Down Expand Up @@ -150,7 +153,8 @@ const CodeSubmission: React.FC = () => {

if (!episode.isSuccess) return null;

if (episode.data.frozen)
const isStaffTeam = teamData.data?.status === Status526Enum.S;
if (!isStaffTeam && episode.data.frozen)
return (
<p>
Submissions are currently frozen! This is most likely due to a
Expand All @@ -159,77 +163,153 @@ const CodeSubmission: React.FC = () => {
</p>
);

return (
<div>
<p>Submit your code using the button below.</p>
<p>
Create a{" "}
<span className="rounded-md bg-gray-200 px-1 py-0.5 font-mono">
zip
</span>{" "}
file of your robot player, and submit it below. The submission format
should be a zip file containing a single folder (which is your package
name), which should contain{" "}
<span className="rounded-md bg-gray-200 px-1 py-0.5 font-mono">
RobotPlayer.java
</span>{" "}
and any other code you have written, for example:
</p>
<span className="w-full">
<p className="rounded-md border border-gray-400 bg-gray-100 px-4 py-3 font-mono">
{
"submission.zip --> examplefuncsplayer --> RobotPlayer.java, FooBar.java"
}
if (episode.data.language === LanguageEnum.Py3) {
return (
<div>
<p>Submit your python code using the button below.</p>
<p>
Create a{" "}
<span className="rounded-md bg-gray-200 px-1 py-0.5 font-mono">
zip
</span>{" "}
file of your robot player, and submit it below. The submission format
should be a zip file containing a single folder (which is your package
name), which should contain{" "}
<span className="rounded-md bg-gray-200 px-1 py-0.5 font-mono">
bot.py
</span>{" "}
and any other code you have written, for example:
</p>
</span>
<form
onSubmit={(e) => {
void handleSubmit(onSubmit)(e);
}}
className="mt-4 flex flex-col gap-4"
>
<div>
<FormLabel required label="Choose Submission File" />
<input
type="file"
accept=".zip"
required
{...register("file", { required: FIELD_REQUIRED_ERROR_MSG })}
/>
</div>
<div className="flex w-full flex-row items-end gap-10">
<Input
className="w-1/3"
label="Package Name (i.e. where is RobotPlayer?)"
required
errorMessage={errors.packageName?.message}
{...register("packageName", {
required: FIELD_REQUIRED_ERROR_MSG,
})}
<span className="w-full">
<p className="rounded-md border border-gray-400 bg-gray-100 px-4 py-3 font-mono">
{"submission.zip --> examplefuncsplayer --> bot.py, utils.py"}
</p>
</span>
<form
onSubmit={(e) => {
void handleSubmit(onSubmit)(e);
}}
className="mt-4 flex flex-col gap-4"
>
<div>
<FormLabel required label="Choose Submission File" />
<input
type="file"
accept=".zip"
required
{...register("file", { required: FIELD_REQUIRED_ERROR_MSG })}
/>
</div>
<div className="flex w-full flex-col items-start gap-4 lg:flex-row lg:items-end">
<Input
className="w-full lg:w-1/3"
label="Package Name (i.e. examplefuncsplayer)"
required
errorMessage={errors.packageName?.message}
{...register("packageName", {
required: FIELD_REQUIRED_ERROR_MSG,
})}
/>
<Input
className="w-full lg:w-2/3"
label="Description (for your reference)"
required
errorMessage={errors.description?.message}
{...register("description", {
required: FIELD_REQUIRED_ERROR_MSG,
})}
/>
</div>
<Button
className={`max-w-sm ${
uploadSub.isPending || !isDirty
? "disabled cursor-not-allowed"
: ""
}`}
variant="dark"
label="Submit"
type="submit"
loading={uploadSub.isPending}
disabled={uploadSub.isPending || !isDirty}
/>
<Input
className="w-2/3"
label="Description (for your reference)"
required
errorMessage={errors.description?.message}
{...register("description", {
required: FIELD_REQUIRED_ERROR_MSG,
})}
</form>
</div>
);
} else {
return (
<div>
<p>Submit your java code using the button below.</p>
<p>
Create a{" "}
<span className="rounded-md bg-gray-200 px-1 py-0.5 font-mono">
zip
</span>{" "}
file of your robot player, and submit it below. The submission format
should be a zip file containing a single folder (which is your package
name), which should contain{" "}
<span className="rounded-md bg-gray-200 px-1 py-0.5 font-mono">
RobotPlayer.java
</span>{" "}
and any other code you have written, for example:
</p>
<span className="w-full">
<p className="rounded-md border border-gray-400 bg-gray-100 px-4 py-3 font-mono">
{
"submission.zip --> examplefuncsplayer --> RobotPlayer.java, FooBar.java"
}
</p>
</span>
<form
onSubmit={(e) => {
void handleSubmit(onSubmit)(e);
}}
className="mt-4 flex flex-col gap-4"
>
<div>
<FormLabel required label="Choose Submission File" />
<input
type="file"
accept=".zip"
required
{...register("file", { required: FIELD_REQUIRED_ERROR_MSG })}
/>
</div>
<div className="flex w-full flex-col items-start gap-4 lg:flex-row lg:items-end">
<Input
className="w-full lg:w-1/3"
label="Package Name (i.e. examplefuncsplayer)"
required
errorMessage={errors.packageName?.message}
{...register("packageName", {
required: FIELD_REQUIRED_ERROR_MSG,
})}
/>
<Input
className="w-full lg:w-2/3"
label="Description (for your reference)"
required
errorMessage={errors.description?.message}
{...register("description", {
required: FIELD_REQUIRED_ERROR_MSG,
})}
/>
</div>
<Button
className={`max-w-sm ${
uploadSub.isPending || !isDirty
? "disabled cursor-not-allowed"
: ""
}`}
variant="dark"
label="Submit"
type="submit"
loading={uploadSub.isPending}
disabled={uploadSub.isPending || !isDirty}
/>
</div>
<Button
className={`max-w-sm ${
uploadSub.isPending || !isDirty ? "disabled cursor-not-allowed" : ""
}`}
variant="dark"
label="Submit"
type="submit"
loading={uploadSub.isPending}
disabled={uploadSub.isPending || !isDirty}
/>
</form>
</div>
);
</form>
</div>
);
}
};

export default Submissions;

0 comments on commit a25b3f4

Please sign in to comment.