222 lines
9.7 KiB
Svelte
222 lines
9.7 KiB
Svelte
<script lang="ts">
|
|
import { goto } from '$app/navigation';
|
|
|
|
import { user } from '$lib/stores/user';
|
|
import DateFormat from '$lib/components/DateFormat.svelte';
|
|
import SubmissionStatus from '$lib/components/SubmissionStatus.svelte';
|
|
import SurveyBadge from '$lib/components/SurveyBadge.svelte';
|
|
import TraceStatus from '$lib/components/TraceStatus.svelte';
|
|
import WorkAdmin from '$lib/components/WorkAdmin.svelte';
|
|
import WorkGrades from '$lib/components/WorkGrades.svelte';
|
|
import WorkGradesSteps from '$lib/components/WorkGradesSteps.svelte';
|
|
import WorkHeader from '$lib/components/WorkHeader.svelte';
|
|
import WorkRepository from '$lib/components/WorkRepository.svelte';
|
|
import { getScore } from '$lib/users';
|
|
|
|
export let data;
|
|
let edit = false;
|
|
let my_submission = null;
|
|
let warn_already_used = false;
|
|
let showSteps = false;
|
|
let w = null;
|
|
|
|
$: w = data.work;
|
|
$: refresh_submission(data.work);
|
|
|
|
function refresh_submission(w) {
|
|
my_submission = w.getSubmission();
|
|
}
|
|
</script>
|
|
|
|
{#if $user && $user.is_admin}
|
|
<button class="btn btn-primary ms-1 float-end" on:click={() => { edit = !edit; } } title="Éditer"><i class="bi bi-pencil"></i></button>
|
|
<a class="btn btn-success ms-1 float-end" href="works/{w.id}/rendus" title="Voir les rendus"><i class="bi bi-files"></i></a>
|
|
{/if}
|
|
<div class="d-flex align-items-center">
|
|
<h2>
|
|
<a href="works/" class="text-muted" style="text-decoration: none"><</a>
|
|
{w.title}
|
|
</h2>
|
|
<SurveyBadge class="ms-2" survey={w} />
|
|
</div>
|
|
|
|
{#if $user && $user.is_admin && (edit || w.endAvailability() < Date.now())}
|
|
{#if edit}
|
|
<WorkAdmin work={w} on:saved={() => edit = false} />
|
|
{/if}
|
|
|
|
{#if w.description}
|
|
<hr>
|
|
{@html w.description}
|
|
{/if}
|
|
|
|
<hr>
|
|
{#if showSteps}
|
|
<WorkGradesSteps
|
|
work={w}
|
|
on:switch_steps={() => showSteps = false}
|
|
/>
|
|
{:else}
|
|
<WorkGrades
|
|
work={w}
|
|
on:switch_steps={() => showSteps = true}
|
|
/>
|
|
{/if}
|
|
{:else if (!$user || !$user.is_admin) && new Date(w.start_availability) > new Date()}
|
|
<div class="alert alert-warning">
|
|
<i class="bi bi-stopwatch-fill"></i>
|
|
<strong>Ce travail n'est pas encore ouvert.</strong> Revenez plus tard !
|
|
</div>
|
|
{:else}
|
|
<WorkHeader work={w} {my_submission} />
|
|
{#if w.description}
|
|
<hr>
|
|
{@html w.description}
|
|
{/if}
|
|
|
|
<hr>
|
|
|
|
<h3 class="mt-3">Rendu</h3>
|
|
|
|
{#if !w.corrected && w.submission_url != "-"}
|
|
<p>
|
|
Pour rendre votre travail, vous devez préalablement créer un dépôt Git sur la <a href="https://gitlab.cri.epita.fr/" target="_blank" rel="noreferrer">forge de l'école</a>.<br>Ce dépôt DOIT :
|
|
</p>
|
|
<ul>
|
|
<li>être dans l'espace de nom de votre utilisateur (à la fin de la liste des <span class="fst-italic">namespaces</span>),</li>
|
|
<li>avoir la visibilité « Privé »,</li>
|
|
<li>avoir invité <a href="https://gitlab.cri.epita.fr/nemunaire" target="_blank" style="font-family: monospace" rel="noreferrer">nemunaire</a> avec le rôle <span class="fst-italic">Reporter</span> une fois le dépôt créé.</li>
|
|
</ul>
|
|
|
|
{#if w.tag}
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-lightbulb-fill text-info me-1"></i>
|
|
Vous pouvez utiliser un dépôt pour tous les travaux à effectuer, ou créer un dépôt par travail.
|
|
Son nom/slug n'a pas d'importance car c'est à vous de le sélectionner dans le formulaire ci-après.
|
|
</div>
|
|
{/if}
|
|
{/if}
|
|
|
|
{#if w.submission_url != "-"}
|
|
{#if !w.corrected}
|
|
<WorkRepository class="mb-3" readonly={w.corrected || new Date(w.end_availability) <= new Date()} work={w} on:update_submission={() => refresh_submission(w)} bind:already_used={warn_already_used} />
|
|
{/if}
|
|
<div class="card mb-3">
|
|
<div class="card-body d-flex justify-content-between">
|
|
<div>
|
|
{#if w.submission_url}
|
|
<strong>État du rendu :</strong> <SubmissionStatus work={w} user={$user} />
|
|
{:else}
|
|
Rendu :
|
|
{#await my_submission}
|
|
<div class="spinner-grow spinner-grow-sm mx-1" role="status"></div>
|
|
{:then submission}
|
|
<strong><a href="/api/works/{w.id}/forge/-/tree/{submission.commit}" target="_blank">{submission.commit}</a> (<a href="/api/works/{w.id}/forge/-/tree/{submission.tag}" target="_blank">{submission.tag}</a>)</strong> (taille : {submission.size} o, date : <DateFormat date={new Date(submission.date)} dateStyle="medium" timeStyle="medium" />)
|
|
{:catch}
|
|
<strong>-</strong>
|
|
{/await}
|
|
{/if}
|
|
</div>
|
|
<div class="d-flex flex-column justify-content-center">
|
|
{#await my_submission then submission}
|
|
<a
|
|
href="/api/works/{w.id}/download"
|
|
class="btn btn-sm btn-dark"
|
|
title="Voir la tarball de mon rendu"
|
|
>
|
|
<i class="bi bi-download"></i>
|
|
</a>
|
|
{:catch}
|
|
<i
|
|
class="bi bi-x-circle text-danger"
|
|
title="Pas de rendu trouvé"
|
|
></i>
|
|
{/await}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
|
|
{#if w.corrected}
|
|
{#await getScore(w)}
|
|
<div class="spinner-border spinner-border-sm" role="status"></div>
|
|
{:then grade}
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-clipboard2-check-fill text-info me-1"></i>
|
|
<strong>Note finale :</strong> <span title="Établie le {grade.date}">{grade.score}</span> {#if grade.comment}– {grade.comment}{/if}
|
|
</div>
|
|
{#await w.getMyTraces()}
|
|
<div class="spinner-border spinner-border-sm" role="status"></div>
|
|
{:then traces}
|
|
{#each traces as trace}
|
|
<div class="d-flex align-items-center gap-2">
|
|
<h4>{trace.title}</h4>
|
|
<TraceStatus status={trace.status} />
|
|
</div>
|
|
{#if trace.items}
|
|
<ul class="list-group mb-3">
|
|
{#each trace.items as item}
|
|
<li class="list-group-item">
|
|
<i
|
|
class="me-1 bi"
|
|
class:bi-check-lg={item.status == "success"}
|
|
class:bi-x-lg={item.status == "failure"}
|
|
class:bi-question-lg={item.status != "success" && item.status != "failure"}
|
|
></i>
|
|
<strong>
|
|
{item.title}
|
|
</strong>
|
|
{#if item.msg}
|
|
{item.msg}
|
|
{/if}
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
{/if}
|
|
{#if trace.logs}
|
|
<div class="bg-dark text-light px-2 pt-2">
|
|
<pre class="pb-2">{#each trace.logs as l (l.pos)}{l.out}{/each}</pre>
|
|
</div>
|
|
{/if}
|
|
{/each}
|
|
{:catch error}
|
|
<div class="alert alert-danger">
|
|
<i class="bi text-warning bi-exclamation-triangle-fill" title={error}></i>
|
|
<strong>{error.message}</strong>
|
|
</div>
|
|
{/await}
|
|
{:catch error}
|
|
<div class="alert alert-danger">
|
|
<i class="bi text-warning bi-exclamation-triangle-fill" title={error}></i>
|
|
<strong>{error.message}</strong>
|
|
</div>
|
|
{/await}
|
|
{:else if w.submission_url != "-"}
|
|
{#if warn_already_used}
|
|
<div class="alert alert-danger">
|
|
<strong>Vous avez déjà utilisé ce dépôt pour rendre un autre travail.</strong> Pour conserver ce que vous avez fait, tout en respectant l'arborescence de rendu attendue, vous devriez partir d'une nouvelle branche vide :
|
|
<pre class="mx-2 mt-1 mb-2">
|
|
42sh$ git checkout --orphan renduX
|
|
42sh$ git reset
|
|
42sh$ rm -r *
|
|
# Créez l'arborescence de rendu ensuite</pre>
|
|
|
|
Pour retrouver ensuite vos rendus des travaux précédents :
|
|
<pre class="mx-2 my-1">
|
|
42sh$ git checkout renduY
|
|
-- ou --
|
|
42sh$ git checkout master
|
|
</pre>
|
|
</div>
|
|
{/if}
|
|
<div class="alert alert-warning">
|
|
Pour être reconnu, vous devez pousser un tag <strong><a href="keys">signé</a></strong> sur votre dépôt. {#if w.tag}Le tag attendu doit commencer par : <code>{w.tag}</code>. Par exemple <code>{w.tag}v1.0</code>, <code>{w.tag}v1.1</code>, …{/if} Seul le dernier tag <strong>alphabétique</strong> que vous envoyez avant la date du rendu sera pris en compte. Vous pouvez donc faire autant de tag que vous le souhaitez d'ici la date du rendu.
|
|
</div>
|
|
{:else}
|
|
<div class="alert alert-primary">
|
|
Ce travail n'a pas de modalité de rendu.
|
|
</div>
|
|
{/if}
|
|
{/if}
|
|
<div class="mb-5"></div>
|