Skip to content

Commit

Permalink
Merge pull request #60 from MichaelZhao21/refactor/code-cleanup
Browse files Browse the repository at this point in the history
Code cleanup/QOL changes
  • Loading branch information
MichaelZhao21 authored Nov 18, 2023
2 parents 76cf3cc + 8783c69 commit d7e478a
Show file tree
Hide file tree
Showing 17 changed files with 248 additions and 86 deletions.
22 changes: 18 additions & 4 deletions client/src/components/judge/ProjectDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { twMerge } from 'tailwind-merge';
import Paragraph from '../Paragraph';
import { getRequest } from '../../api';
import { errorAlert } from '../../util';
import StarDisplay from './StarDisplay';

interface ProjectDisplayProps {
/* Project ID to display */
projectId: string;

/* Judge for the project */
judge: Judge;

/* Define the className */
className?: string;
}
Expand All @@ -18,7 +22,7 @@ const ProjectDisplay = (props: ProjectDisplayProps) => {
useEffect(() => {
async function fetchData() {
if (!props.projectId) return;

const projRes = await getRequest<Project>(`/project/${props.projectId}`, 'judge');
if (projRes.status !== 200) {
errorAlert(projRes);
Expand All @@ -38,9 +42,19 @@ const ProjectDisplay = (props: ProjectDisplayProps) => {

return (
<div className={twMerge('px-2', props.className)}>
<h1 className='text-3xl mb-1'>{project.name}</h1>
<h2 className='text-xl mb-1'>Table {project.location}</h2>
<Paragraph className='text-light' text={project.description} />
<h1 className="text-3xl mb-1">{project.name}</h1>
<h2 className="text-xl mb-1">Table {project.location}</h2>
<div className="flex mb-3">
<StarDisplay
id={project.id}
clickable={true}
stars={
props.judge.seen_projects.find((jp) => jp.project_id === project.id)
?.stars || 0
}
/>
</div>
<Paragraph className="text-light" text={project.description} />
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/judge/Star.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface StarProps {
}

const Star = (props: StarProps) => {
const handleClick: React.MouseEventHandler<HTMLDivElement> = async (e) => {
const handleClick: React.MouseEventHandler<HTMLDivElement> = async () => {
if (!props.clickable) return;

// Update star count based on the star # clicked
Expand Down
11 changes: 6 additions & 5 deletions client/src/pages/admin/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const AdminLogin = () => {
setLoginLock(false);
return;
}

// Wrong password
if (res.data?.ok !== 1) {
setError(true);
Expand All @@ -84,10 +84,11 @@ const AdminLogin = () => {
maxAge: 60 * 60 * 24,
});

// Redirect
navigate('/admin');

setLoginLock(false);
// Delay to allow cookie to be set; janky Firefox 119 fix
setTimeout(() => {
navigate('/admin');
setLoginLock(false);
}, 50);
};

return (
Expand Down
131 changes: 107 additions & 24 deletions client/src/pages/admin/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,21 @@ import Popup from '../../components/Popup';
import Checkbox from '../../components/Checkbox';
import Loading from '../../components/Loading';

// Text components
const Section = ({ children: c }: { children: React.ReactNode }) => (
<h2 className="text-4xl mt-8 mb-2 text-primary">{c}</h2>
);
const SubSection = ({ children: c }: { children: React.ReactNode }) => (
<h3 className="text-xl font-bold">{c}</h3>
);
const Description = ({ children: c }: { children: React.ReactNode }) => (
<p className="text-light">{c}</p>
);

const AdminSettings = () => {
const [reassignPopup, setReassignPopup] = useState(false);
const [clockResetPopup, setClockResetPopup] = useState(false);
const [dropPopup, setDropPopup] = useState(false);
const [groupChecked, setGroupChecked] = useState(false);
const [groups, setGroups] = useState('');
const [judgingTimer, setJudgingTimer] = useState('');
Expand Down Expand Up @@ -87,11 +100,33 @@ const AdminSettings = () => {
errorAlert(res);
return;
}

alert('Timer updated!');
getOptions();
};

const resetClock = async () => {
const res = await postRequest<OkResponse>('/admin/clock/reset', 'admin', null);
if (res.status !== 200 || res.data?.ok !== 1) {
errorAlert(res);
return;
}

alert('Clock reset!');
setClockResetPopup(false);
};

const dropDatabase = async () => {
const res = await postRequest<OkResponse>('/admin/reset', 'admin', null);
if (res.status !== 200 || res.data?.ok !== 1) {
errorAlert(res);
return;
}

alert('Database reset!');
setDropPopup(false);
};

const exportCsv = async (type: string) => {
const res = await fetch(`${process.env.REACT_APP_JURY_URL}/admin/export/${type}`, {
method: 'GET',
Expand All @@ -103,9 +138,9 @@ const AdminSettings = () => {
return;
}

saveToFile(await res.blob() as Blob, type, 'csv');
saveToFile((await res.blob()) as Blob, type, 'csv');
};

const exportByChallenge = async () => {
const res = await fetch(`${process.env.REACT_APP_JURY_URL}/admin/export/challenges`, {
method: 'GET',
Expand All @@ -117,9 +152,9 @@ const AdminSettings = () => {
return;
}

saveToFile(await res.blob() as Blob, 'challenge-projects', 'zip');
saveToFile((await res.blob()) as Blob, 'challenge-projects', 'zip');
};

const saveToFile = (blob: Blob, name: string, ext: string) => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
Expand All @@ -136,12 +171,24 @@ const AdminSettings = () => {
<div className="flex flex-col items-start justify-center w-full px-8 py-4 md:px-16 md:py-8">
<h1 className="text-4xl font-bold">Settings</h1>
{/* TODO: Add other settings */}
<h2 className="text-4xl mt-8 mb-2 text-primary">Judging Timer</h2>
<h3 className="text-xl font-bold">Set Judging Timer</h3>
<p className="text-light">
<Section>Set Main Clock</Section>
<SubSection>Reset Clock</SubSection>
<Description>Reset the clock back to 00:00:00</Description>
<Button
type="primary"
onClick={() => {
setClockResetPopup(true);
}}
className="mt-4 w-auto md:w-auto px-4 py-2"
>
Reset
</Button>
<Section>Judging Timer</Section>
<SubSection>Set Judging Timer</SubSection>
<Description>
Set how long judges have to view each project. This will reflect on the timer
that shows on the judging page.
</p>
</Description>
<input
className="w-full h-14 px-4 text-2xl border-lightest border-2 rounded-sm focus:border-primary focus:border-4 focus:outline-none"
type="string"
Expand All @@ -158,29 +205,29 @@ const AdminSettings = () => {
>
Update Timer
</Button>
<h2 className="text-4xl mt-8 mb-2 text-primary">Project Numbers</h2>
<h3 className="text-xl font-bold">Reassign Project Numbers</h3>
<p className="text-light">
Reassign all table numbers to the projects. This will keep the relative order
but reassign the table numbers starting from the first project.
</p>
<Section>Project Numbers</Section>
<SubSection>Reassign Project Numbers</SubSection>
<Description>
Reassign all project numbers to the projects. This will keep the relative order
but reassign the project numbers starting from the first project.
</Description>
<Button
type="primary"
onClick={() => {
setReassignPopup(true);
}}
className="mt-4 w-auto md:w-auto px-4 py-2 bg-gold text-black"
className="mt-4 mb-8 w-auto md:w-auto px-4 py-2 bg-gold text-black"
>
Reassign
</Button>
<h3 className="text-xl font-bold mt-4">Table Groupings</h3>
<p className="text-light">
<SubSection>Table Groupings</SubSection>
<Description>
Check this box to use table groupings. This will force judges to stay in a
grouping for 3 rounds before moving on. This ideally should decrease the
distance judges will have to walk, if groups are defined correctly. Note that
group sizes <span className="font-bold">must be greater than 3</span> otherwise
the groupings will be ignored.
</p>
</Description>
<Checkbox
checked={groupChecked}
onChange={(c) => {
Expand All @@ -189,11 +236,11 @@ const AdminSettings = () => {
>
Enable Table Groupings
</Checkbox>
<p className="text-light mt-4">
<Description>
{
'List table groupings below. It should be in the form <tableStartNum> <tableEndNum>. Each group should be on its own line. No table numbers should overlap. If groups are defined, table numbers will be assigned according to the ranges defined here (ie. groups of 1-10, 101-110 will skip table numbers 11-100). If there are more table numbers than groups defined, the default behavior is to append incrementally to the last group.'
}
</p>
</Description>
<textarea
className="w-full h-36 px-4 py-4 text-2xl border-lightest border-2 rounded-sm focus:border-primary focus:border-4 focus:outline-none"
placeholder="1 10"
Expand All @@ -209,9 +256,9 @@ const AdminSettings = () => {
>
Update Groupings
</Button>
<h2 className="text-4xl mt-8 mb-2 text-primary">Export Data</h2>
<h3 className="text-lg font-bold">Export Collections</h3>
<p className="text-light">Export each collection individually as a CSV download.</p>
<Section>Export Data</Section>
<SubSection>Export Collection</SubSection>
<Description>Export each collection individually as a CSV download.</Description>
<div className="flex">
<Button
type="primary"
Expand Down Expand Up @@ -239,6 +286,21 @@ const AdminSettings = () => {
Export by Challenges
</Button>
</div>
<Section>Reset Database</Section>
<SubSection>THIS WILL DELETE THE ENTIRE DATABASE</SubSection>
<Description>
Mostly used for testing purposes/before the event if you want to reset
everything bc something got messed up. Do NOT use this during judging (duh).
</Description>
<Button
type="error"
onClick={() => {
setDropPopup(true);
}}
className="mt-4 w-auto md:w-auto px-4 py-2"
>
Drop Database
</Button>
</div>
<Popup
enabled={reassignPopup}
Expand All @@ -251,6 +313,27 @@ const AdminSettings = () => {
Are you sure you want to reassign project numbers? This should NOT be done DURING
judging; only beforehand!!
</Popup>
<Popup
enabled={clockResetPopup}
setEnabled={setClockResetPopup}
onSubmit={resetClock}
submitText="Reset"
title="Heads Up!"
red
>
Are you sure you want to reset the main clock? This will reset the clock to 00:00:00
</Popup>
<Popup
enabled={dropPopup}
setEnabled={setDropPopup}
onSubmit={dropDatabase}
submitText="RESET DATA"
title="Heads Up!"
red
>
THIS WILL ACTUALLY DELETE ALL DATA!!!!! YOU NEED TO BE ABSOLUTELY SURE YOU WANT TO
DO THIS. THIS IS YOUR LAST WARNING!
</Popup>
<Loading disabled={!loading} />
</>
);
Expand Down
31 changes: 16 additions & 15 deletions client/src/pages/judge/live.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const JudgeLive = () => {
return;
}
if (startedRes.data?.ok !== 1) {
console.error(`Judging is paused!`);
setVerified(true);
setInfoPage('paused');
return;
}
Expand Down Expand Up @@ -128,7 +128,8 @@ const JudgeLive = () => {

useEffect(() => {
if (!verified) return;

if (infoPage === 'paused') return;

getJudgeData();
}, [verified]);

Expand Down Expand Up @@ -256,6 +257,17 @@ const JudgeLive = () => {
getJudgeData();
};

// Display an error page if an error condition holds
const infoIndex = infoPages.indexOf(infoPage);
if (infoIndex !== -1) {
return (
<JudgeInfoPage
title={infoData[infoIndex].title}
description={infoData[infoIndex].description}
/>
);
}

// Show loading screen if judge does not exist
if (!judge) {
return (
Expand Down Expand Up @@ -308,17 +320,6 @@ const JudgeLive = () => {
);
};

// Display an error page if an error condition holds
const infoIndex = infoPages.indexOf(infoPage);
if (infoIndex !== -1) {
return (
<JudgeInfoPage
title={infoData[infoIndex].title}
description={infoData[infoIndex].description}
/>
);
}

return (
<>
<JuryHeader withLogout />
Expand Down Expand Up @@ -386,12 +387,12 @@ const JudgeLive = () => {
</div>
</div>
<Back location="/judge" />
{judge.next && <ProjectDisplay projectId={judge.next} />}
{judge.next && <ProjectDisplay judge={judge} projectId={judge.next} />}
{judge.prev && (
<>
<div className="my-6 h-[0.5px] shrink-0 w-full bg-light"></div>
<h3 className="font-bold text-light px-2 mb-1">Previous Project</h3>
<ProjectDisplay projectId={judge.prev} />
<ProjectDisplay judge={judge} projectId={judge.prev} />
</>
)}
<VotePopup
Expand Down
Loading

0 comments on commit d7e478a

Please sign in to comment.