273 lines
11 KiB
Svelte
273 lines
11 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 WorkAdmin from '$lib/components/WorkAdmin.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 w = null;
|
|
let gradesP = null;
|
|
let mean = 0;
|
|
|
|
$: w = data.work;
|
|
$: refresh_submission(data.work);
|
|
$: refresh_grades(data.work);
|
|
|
|
function refresh_submission(w) {
|
|
my_submission = w.getSubmission();
|
|
}
|
|
|
|
function refresh_grades(w) {
|
|
gradesP = w.getGrades();
|
|
gradesP.then((grades) => {
|
|
if (grades.length <= 0) return;
|
|
|
|
let sum = 0;
|
|
for (const grade of grades) {
|
|
sum += grade.score;
|
|
}
|
|
mean = sum / grades.length;
|
|
});
|
|
}
|
|
</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}
|
|
<WorkAdmin work={w} on:saved={() => edit = false} />
|
|
|
|
{#if w.description}
|
|
<hr>
|
|
{@html w.description}
|
|
{/if}
|
|
|
|
<hr>
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h3 class="mt-3">Notes</h3>
|
|
<button
|
|
class="btn btn-light"
|
|
on:click={() => refresh_grades(w)}
|
|
>
|
|
<i class="bi bi-arrow-clockwise"></i>
|
|
</button>
|
|
</div>
|
|
<div class="card mt-3 mb-5">
|
|
{#await gradesP}
|
|
<div class="text-center mb-5">
|
|
<div class="spinner-border text-primary mx-3" role="status"></div>
|
|
<span>Chargement des notes …</span>
|
|
</div>
|
|
{:then grades}
|
|
<table class="table table-hover table-striped table-sm mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th>Login</th>
|
|
<th>
|
|
Note
|
|
{#if mean > 0}(moyenne : {Math.round(mean*100)/100}){/if}
|
|
</th>
|
|
<th>Commentaire</th>
|
|
<th>Date de la note</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{#if !grades}
|
|
<div class="text-center">
|
|
Aucune note n'a encore été envoyée pour ce travail.
|
|
</div>
|
|
{:else}
|
|
{#each grades as grade, gid (grade.id)}
|
|
<tr>
|
|
<td>
|
|
<a href="users/{grade.id_user}">{grade.login}</a>
|
|
</td>
|
|
<td>{grade.score}</td>
|
|
<td>{#if grade.comment}{grade.comment}{:else}-{/if}</td>
|
|
<td>{grade.date}</td>
|
|
<td>
|
|
<a
|
|
href="/api/users/{grade.id_user}/works/{w.id}/grades/{grade.id}/traces"
|
|
target="_blank"
|
|
class="btn btn-sm btn-outline-info mx-1"
|
|
title="Voir le détail de la notation"
|
|
>
|
|
<i class="bi bi-list-check"></i>
|
|
</a>
|
|
<button
|
|
class="btn btn-sm btn-danger mx-1"
|
|
title="Supprimer la note"
|
|
on:click={() => { grade.delete(); refresh_grades(w); }}
|
|
>
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{/each}
|
|
{/if}
|
|
</tbody>
|
|
</table>
|
|
{/await}
|
|
</div>
|
|
{: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}
|
|
<dl style="columns: 3">
|
|
<dt>Date de début</dt>
|
|
<dd><DateFormat date={new Date(w.start_availability)} dateStyle="medium" timeStyle="medium" /></dd>
|
|
<dt>Date de fin</dt>
|
|
<dd><DateFormat date={new Date(w.end_availability)} dateStyle="medium" timeStyle="medium" /></dd>
|
|
{#if w.submission_url != "-"}
|
|
<dt>Rendu ?</dt>
|
|
<dd>
|
|
{#if w.submission_url}
|
|
<SubmissionStatus work={w} user={$user} />
|
|
{:else}
|
|
{#await my_submission}
|
|
<div class="spinner-grow spinner-grow-sm mx-1" role="status"></div>
|
|
{:then submission}
|
|
<i
|
|
class="bi bi-check-circle text-success"
|
|
title="Oui !"
|
|
></i>
|
|
<DateFormat date={new Date(submission.date)} dateStyle="medium" timeStyle="medium" />
|
|
{:catch}
|
|
<i
|
|
class="bi bi-x-circle text-danger"
|
|
title="Pas de rendu trouvé"
|
|
></i>
|
|
Non
|
|
{/await}
|
|
{/if}
|
|
</dd>
|
|
{/if}
|
|
</dl>
|
|
{#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 != "-"}
|
|
<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} />
|
|
<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>{submission.commit} ({submission.tag})</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>
|
|
{: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>
|