Gradation: add route to add missing users
This commit is contained in:
parent
107b17c11f
commit
3397b9f123
@ -109,6 +109,18 @@ export class Work {
|
||||
}
|
||||
}
|
||||
|
||||
async addMissingGrades() {
|
||||
const res = await fetch(`api/works/${this.id}/grades`, {
|
||||
method: 'PATCH',
|
||||
headers: {'Accept': 'application/json'},
|
||||
});
|
||||
if (res.status == 200) {
|
||||
return (await res.json()).map((g) => new Grade(g));
|
||||
} else {
|
||||
throw new Error((await res.json()).errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
async getSubmission(uid) {
|
||||
const res = await fetch(uid?`api/users/${uid}/works/${this.id}/submission`:`api/works/${this.id}/submission`, {
|
||||
headers: {'Accept': 'application/json'}
|
||||
|
@ -40,6 +40,11 @@
|
||||
stats.mean = sum / grades.length;
|
||||
});
|
||||
}
|
||||
|
||||
async function addMissingStudents(w) {
|
||||
await w.addMissingGrades();
|
||||
refresh_grades(w);
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $user && $user.is_admin}
|
||||
@ -72,12 +77,22 @@
|
||||
{#if stats.mean > 0}(moyenne : {Math.round(stats.mean*100)/100}, min : {stats.min}, max : {stats.max}){/if}
|
||||
</small>
|
||||
</h3>
|
||||
<button
|
||||
class="btn btn-light"
|
||||
on:click={() => refresh_grades(w)}
|
||||
>
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-outline-info"
|
||||
title="Ajouter les étudiants manquant"
|
||||
on:click={() => addMissingStudents(w)}
|
||||
>
|
||||
<i class="bi bi-people"></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-light"
|
||||
title="Rafraîchir l'affichage des notes"
|
||||
on:click={() => refresh_grades(w)}
|
||||
>
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-3 mb-5">
|
||||
{#await gradesP}
|
||||
|
28
users.go
28
users.go
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -169,6 +170,33 @@ func getUsers() (users []User, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func getFilteredUsers(promo uint, group string) (users []User, err error) {
|
||||
// Avoid SQL injection: check group name doesn't contains harmful content
|
||||
var validGroup = regexp.MustCompile(`^[a-z0-9-]*$`)
|
||||
if !validGroup.MatchString(group) {
|
||||
return nil, fmt.Errorf("%q is not a valid group name", group)
|
||||
}
|
||||
|
||||
if rows, errr := DBQuery("SELECT id_user, login, email, firstname, lastname, time, promo, groups, is_admin FROM users WHERE promo = ? AND groups LIKE '%,"+group+",%' ORDER BY promo DESC, id_user DESC", promo); errr != nil {
|
||||
return nil, errr
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var u User
|
||||
if err = rows.Scan(&u.Id, &u.Login, &u.Email, &u.Firstname, &u.Lastname, &u.Time, &u.Promo, &u.Groups, &u.IsAdmin); err != nil {
|
||||
return
|
||||
}
|
||||
users = append(users, u)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func getPromos() (promos []uint, err error) {
|
||||
if rows, errr := DBQuery("SELECT DISTINCT promo FROM users ORDER BY promo DESC"); errr != nil {
|
||||
return nil, errr
|
||||
|
43
works.go
43
works.go
@ -179,6 +179,49 @@ func declareAPIAdminWorksRoutes(router *gin.RouterGroup) {
|
||||
|
||||
c.JSON(http.StatusOK, grades)
|
||||
})
|
||||
worksRoutes.PATCH("/grades", func(c *gin.Context) {
|
||||
w := c.MustGet("work").(*Work)
|
||||
|
||||
// Fetch existing grades
|
||||
grades, err := w.GetGrades("")
|
||||
if err != nil {
|
||||
log.Printf("Unable to GetGrades(wid=%d): %s", w.Id, err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during grades retrieval."})
|
||||
return
|
||||
}
|
||||
|
||||
// Create an index
|
||||
known_users := map[int64]bool{}
|
||||
for _, g := range grades {
|
||||
known_users[g.IdUser] = true
|
||||
}
|
||||
|
||||
// Fetch students list registered for this course
|
||||
users, err := getFilteredUsers(w.Promo, w.Group)
|
||||
if err != nil {
|
||||
log.Printf("Unable to getFilteredUsers(%d, %s): %s", w.Promo, w.Group, err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during users retrieval."})
|
||||
return
|
||||
}
|
||||
|
||||
var toAdd []WorkGrade
|
||||
for _, user := range users {
|
||||
if _, ok := known_users[user.Id]; !ok {
|
||||
toAdd = append(toAdd, WorkGrade{
|
||||
IdUser: user.Id,
|
||||
Login: user.Login,
|
||||
Grade: 0,
|
||||
Comment: "- Non rendu -",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(toAdd) > 0 {
|
||||
w.AddGrades(toAdd)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, toAdd)
|
||||
})
|
||||
worksRoutes.PUT("/grades", func(c *gin.Context) {
|
||||
w := c.MustGet("work").(*Work)
|
||||
|
||||
|
Reference in New Issue
Block a user