[Web] Recreate repos for specific teams and during contest

This commit is contained in:
orosmatthew 2024-03-14 11:24:50 -04:00
parent c54643d8f9
commit 8344cbe2bc
5 changed files with 115 additions and 47 deletions

View File

@ -68,7 +68,7 @@ async function addProblemsCPP(opts: OptsAddProblems) {
}); });
} }
export async function createRepos(contestId: number) { export async function createRepos(contestId: number, teamIds: number[]) {
const vol = new memfs.Volume(); const vol = new memfs.Volume();
const fs = createFsFromVolume(vol); const fs = createFsFromVolume(vol);
@ -81,7 +81,9 @@ export async function createRepos(contestId: number) {
return; return;
} }
contest.teams.forEach(async (team) => { contest.teams
.filter((t) => teamIds.includes(t.id))
.forEach(async (team) => {
fs.mkdirSync(team.id.toString(), { recursive: true }); fs.mkdirSync(team.id.toString(), { recursive: true });
await git.init({ fs: fs, bare: false, defaultBranch: 'master', dir: team.id.toString() }); await git.init({ fs: fs, bare: false, defaultBranch: 'master', dir: team.id.toString() });
if (team.language === 'Java') { if (team.language === 'Java') {

View File

@ -96,7 +96,7 @@ export const actions = {
}); });
return { success: true }; return { success: true };
}, },
repo: async ({ params }) => { repo: async ({ params, request }) => {
if (!params.contestId) { if (!params.contestId) {
return { success: false }; return { success: false };
} }
@ -104,10 +104,20 @@ export const actions = {
if (isNaN(contestId)) { if (isNaN(contestId)) {
return { success: false }; return { success: false };
} }
if (fs.existsSync(join('repo', contestId.toString()))) { const form = await request.formData();
fs.removeSync(join('repo', contestId.toString())); const formEntries = Array.from(form.entries());
const resetTeamIds = formEntries
.filter((e) => e[0].startsWith('teamId'))
.map((e) => {
return parseInt(e[1].toString());
});
resetTeamIds.forEach((teamId) => {
const repoPath = join('repo', contestId.toString(), `${teamId.toString()}.git`);
if (fs.existsSync(repoPath) === true) {
fs.removeSync(repoPath);
} }
await createRepos(contestId); });
await createRepos(contestId, resetTeamIds);
return { success: true }; return { success: true };
}, },
'freeze-time': async ({ params, request }) => { 'freeze-time': async ({ params, request }) => {

View File

@ -11,10 +11,12 @@
$: if (form) { $: if (form) {
freezeModal.hide(); freezeModal.hide();
repoModal.hide();
} }
let confirmModal: ConfirmModal; let confirmModal: ConfirmModal;
let freezeModal: Modal; let freezeModal: Modal;
let repoModal: Modal;
function enhanceConfirm(form: HTMLFormElement, text: string) { function enhanceConfirm(form: HTMLFormElement, text: string) {
enhance(form, async ({ cancel }) => { enhance(form, async ({ cancel }) => {
@ -32,6 +34,18 @@
$: if (freezeTimeInputLocal !== undefined) { $: if (freezeTimeInputLocal !== undefined) {
freezeTimeInput = new Date(freezeTimeInputLocal).toISOString(); freezeTimeInput = new Date(freezeTimeInputLocal).toISOString();
} }
function repoSelectNone() {
document.querySelectorAll<HTMLInputElement>('.repoCheck').forEach((e) => {
e.checked = false;
});
}
function repoSelectAll() {
document.querySelectorAll<HTMLInputElement>('.repoCheck').forEach((e) => {
e.checked = true;
});
}
</script> </script>
<svelte:head> <svelte:head>
@ -65,6 +79,43 @@
</form> </form>
</Modal> </Modal>
<Modal title="Reset Repos" bind:this={repoModal}>
<form action="?/repo" method="POST" use:enhance>
<div class="modal-body">
<div class="d-flex flex-row gap-2 pb-2">
<button on:click={repoSelectNone} type="button" class="btn btn-sm btn-outline-secondary"
>Select None</button
>
<button on:click={repoSelectAll} type="button" class="btn btn-sm btn-outline-secondary"
>Select All</button
>
</div>
{#each data.teams as team}
<div class="form-check">
<input
name={`teamId${team.id}`}
class="form-check-input repoCheck"
type="checkbox"
value={team.id}
id={`repoCheck${team.id}`}
/>
<label class="form-check-label" for={`repoCheck${team.id}`}>{team.name}</label>
</div>
{/each}
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-outline-secondary"
on:click={() => {
repoModal.hide();
}}>Cancel</button
>
<button type="submit" class="btn btn-warning">Reset Selected</button>
</div>
</form>
</Modal>
<h1 style="text-align:center" class="mb-4"><i class="bi bi-flag"></i> Contest - {data.name}</h1> <h1 style="text-align:center" class="mb-4"><i class="bi bi-flag"></i> Contest - {data.name}</h1>
<FormAlert /> <FormAlert />
@ -85,6 +136,13 @@
freezeModal.show(); freezeModal.show();
}}>Set Freeze Time</button }}>Set Freeze Time</button
> >
<button
type="button"
class="btn btn-outline-warning"
on:click={() => {
repoModal.show();
}}>Reset Repos</button
>
{#if data.activeTeams === 0} {#if data.activeTeams === 0}
<form <form
method="POST" method="POST"
@ -94,19 +152,11 @@
> >
<button type="submit" class="btn btn-danger">Delete</button> <button type="submit" class="btn btn-danger">Delete</button>
</form> </form>
<form
method="POST"
action="?/repo"
class="d-inline"
use:enhanceConfirm={'Are you sure you want to recreate repos? This WILL DELETE ALL DATA on the repos currently.'}
>
<button type="submit" class="btn btn-warning">Recreate Repos</button>
</form>
<form <form
method="POST" method="POST"
action="?/start" action="?/start"
class="d-inline" class="d-inline"
use:enhanceConfirm={'Are you sure you want to start the contest?'} use:enhanceConfirm={'Are you sure you want to start the contest? (THIS WILL DELETE ALL DATA IF THE CONTEST HAS ALREADY BEEN RUN)'}
> >
<button type="submit" class="btn btn-success">Start</button> <button type="submit" class="btn btn-success">Start</button>
</form> </form>

View File

@ -45,7 +45,10 @@ export const actions = {
include: { teams: true, problems: true } include: { teams: true, problems: true }
}); });
await createRepos(createdContest.id); await createRepos(
createdContest.id,
teams.map((t) => t.id)
);
return { success: true }; return { success: true };
} }

View File

@ -153,7 +153,10 @@ export const actions = {
await db.activeTeam.create({ data: { teamId: team.id, contestId: contest.id } }); await db.activeTeam.create({ data: { teamId: team.id, contestId: contest.id } });
}); });
await createRepos(contest.id); await createRepos(
contest.id,
fullContest.teams.map((t) => t.id)
);
} }
} }
} catch (err) { } catch (err) {