Include Session in exam template

This commit is contained in:
Andrea Fazzi 2024-05-25 18:09:31 +02:00
parent 875775e1e4
commit 007236bd0f
11 changed files with 64 additions and 50 deletions

View file

@ -9,6 +9,6 @@ var (
filterTypeFormats = map[string]string{
"participants": "👫 Participants filter 👫",
"quizzes": "❓ Quizzes filter ❓",
"responses": "📝 Responsesfilter 📝",
"responses": "📝 Responses filter 📝",
}
)

View file

@ -67,8 +67,8 @@ func runServer(cmd *cobra.Command, args []string) {
mux.Handle("POST /login", serve.Recover(loginController))
mux.Handle("GET /sessions", serve.Recover(sessionsController))
mux.Handle("GET /sessions/{uuid}/exams/{token}", serve.Recover(examController))
mux.Handle("POST /sessions/{uuid}/exams/{token}", serve.Recover(examController))
mux.Handle("GET /sessions/{uuid}/exams/{participantID}", serve.Recover(examController))
mux.Handle("POST /sessions/{uuid}/exams/{participantID}", serve.Recover(examController))
mux.Handle("GET /public/", http.StripPrefix("/public", http.FileServer(http.Dir("public"))))

View file

@ -14,22 +14,22 @@ var ExamHandler = func(c *Controller, w http.ResponseWriter, r *http.Request) {
panic(err)
}
participantToken := r.PathValue("token")
participantID := r.PathValue("participantID")
session, err := c.sStore.Read(r.PathValue("uuid"))
if err != nil {
panic(err)
}
exam, ok := session.Exams[participantToken]
exam, ok := session.Exams[participantID]
if !ok {
panic(errors.New("Exam not found in the store!"))
}
examWithSession := struct {
*models.Exam
SessionID string
}{exam, session.ID}
Session *models.Session
}{exam, session}
switch r.Method {
@ -49,12 +49,14 @@ var ExamHandler = func(c *Controller, w http.ResponseWriter, r *http.Request) {
answers := make([]*models.ParticipantAnswer, 0)
participant := session.Participants[participantID]
for quizID, values := range r.Form {
correct := false
quiz := session.Quizzes[quizID]
for _, answerID := range values {
log.Info(answerID)
if quiz.Correct.ID == answerID {
correct = true
}
@ -64,8 +66,9 @@ var ExamHandler = func(c *Controller, w http.ResponseWriter, r *http.Request) {
response, err := c.rStore.Create(
&models.Response{
SessionID: session.ID,
Answers: answers,
SessionTitle: session.Title,
Participant: participant,
Answers: answers,
})
if err != nil {
panic(err)

View file

@ -15,7 +15,7 @@ var SessionsHandler = func(c *Controller, w http.ResponseWriter, r *http.Request
claims := token.Claims.(jwt.MapClaims)
var participantSessions []struct {
Token string
ParticipantID string
*models.Session
}
@ -23,9 +23,9 @@ var SessionsHandler = func(c *Controller, w http.ResponseWriter, r *http.Request
for _, exam := range session.Exams {
if exam.Participant.Token == claims["token"] {
s := struct {
Token string
ParticipantID string
*models.Session
}{exam.Participant.Token, session}
}{exam.Participant.ID, session}
participantSessions = append(participantSessions, s)
break
}

View file

@ -96,8 +96,9 @@ func New(path string, stdin string) *SessionModel {
viewport := viewport.New()
table := table.New(table.WithRelWidths(20, 30, 30, 20))
table := table.New(table.WithRelWidths(20, 10, 25, 25, 20))
table.Model.SetColumns([]btTable.Column{
{Title: "UUID", Width: 20},
{Title: "Token", Width: 20},
{Title: "Lastname", Width: 20},
{Title: "Firstname", Width: 20},
@ -285,9 +286,10 @@ func (m *SessionModel) showErrorOnStatusBar(err error) {
func (m *SessionModel) updateTableContent(session *models.Session) {
rows := make([]btTable.Row, 0)
for token, exam := range session.Exams {
for _, exam := range session.Exams {
rows = append(rows, btTable.Row{
token,
sanitize(exam.Participant.ID),
exam.Participant.Token,
exam.Participant.Lastname,
exam.Participant.Firstname,
exam.Participant.Attributes.Get("class"),
@ -303,8 +305,8 @@ func (m *SessionModel) updateViewportContent(session *models.Session) {
panic(errors.New("Session have not exams"))
}
currentToken := m.table.SelectedRow()[0]
currentExam := session.Exams[currentToken]
currentUUID := m.table.SelectedRow()[0]
currentExam := session.Exams[desanitize(currentUUID)]
if currentExam == nil {
panic("Current token is not associate to any exam!")
@ -466,3 +468,10 @@ func sanitize(text string) string {
// required to resolve this problem.
return strings.Replace(text, "-", "", -1)
}
func desanitize(text string) string {
// FIXME: The use of a standard '-' character causes rendering
// issues within the viewport. Further investigation is
// required to resolve this problem.
return strings.Replace(text, "", "-", -1)
}

View file

@ -8,34 +8,29 @@
</head>
<body>
<header class="d-flex flex-wrap align-items-center justify-content-between py-3 border-bottom p-3 text-bg-dark border-bottom sticky-top">
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
<span class="fs-4 mx-2">Probo_</span>
</a>
<nav class="navbar bg-body-tertiary">
<div class="container">
<a class="navbar-brand" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="24" fill="currentColor" class="bi bi-book d-inline-block align-text-top" viewBox="0 0 16 16">
<path d="M1 2.828c.885-.37 2.154-.769 3.388-.893 1.33-.134 2.458.063 3.112.752v9.746c-.935-.53-2.12-.603-3.213-.493-1.18.12-2.37.461-3.287.811zm7.5-.141c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783"/>
</svg>
Probo_
</a>
<span class="navbar-text">
{{.Session.Title}}
</span>
<div class="text-end">
<input type="submit" value="Salva" class="btn btn-primary me-2" form="submit-exam-form"/>
</div>
<div class="text-end">
<input type="submit" value="Salva" class="btn btn-primary me-2" form="submit-exam-form"/>
</div>
</header>
</nav>
<form action="/sessions/{{.SessionID}}/exams/{{.Participant.Token}}" method="POST" id="submit-exam-form"/>
<form action="/sessions/{{.Session.ID}}/exams/{{.Participant.Token}}" method="POST" id="submit-exam-form"/>
{{template "content" .}}
<footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<div class="col-md-4 d-flex align-items-center">
<a href="/" class="mb-3 me-2 mb-md-0 text-body-secondary text-decoration-none lh-1">
<svg class="bi" width="30" height="24"><use xlink:href="#bootstrap"></use></svg>
</a>
<span class="mb-3 mb-md-0 text-body-secondary">© 2024 Andrea Fazzi</span>
</div>
<ul class="nav col-md-4 justify-content-end list-unstyled d-flex">
<li class="ms-3"><a class="text-body-secondary" href="#"><svg class="bi" width="24" height="24"><use xlink:href="#twitter"></use></svg></a></li>
<li class="ms-3"><a class="text-body-secondary" href="#"><svg class="bi" width="24" height="24"><use xlink:href="#instagram"></use></svg></a></li>
<li class="ms-3"><a class="text-body-secondary" href="#"><svg class="bi" width="24" height="24"><use xlink:href="#facebook"></use></svg></a></li>
</ul>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>

View file

@ -8,7 +8,7 @@
<h5 class="card-title">{{$session.Title}}</h5>
<h6 class="card-subtitle mb-2 text-body-secondary">{{$session.CreatedAt}}</h6>
<p class="card-text">{{$session.Description}}</p>
<a href="/sessions/{{$session.ID}}/exams/{{$session.Token}}" class="btn btn-primary">Inizia!</a>
<a href="/sessions/{{$session.ID}}/exams/{{$session.ParticipantID}}" class="btn btn-primary">Inizia!</a>
</div>
</div>
</div>

View file

@ -14,8 +14,9 @@ type ParticipantAnswer struct {
type Response struct {
Meta
SessionID string `json:"session_id"`
Answers []*ParticipantAnswer `json:"answers"`
SessionTitle string `json:"session_title"`
Participant *Participant `json:"participant"`
Answers []*ParticipantAnswer `json:"answers"`
}
func (r *Response) String() string {

View file

@ -9,11 +9,13 @@ import (
type Session struct {
Meta
Title string `json:"title"`
Description string `json:"description"`
Quizzes map[string]*Quiz `json:"quizzes"`
Answers map[string]*Answer `json:"answers"`
Exams map[string]*Exam `json:"exams"`
Title string `json:"title"`
Description string `json:"description"`
Participants map[string]*Participant `json:"participants"`
Quizzes map[string]*Quiz `json:"quizzes"`
Answers map[string]*Answer `json:"answers"`
Exams map[string]*Exam `json:"exams"`
}
func (s *Session) String() string {

View file

@ -8,7 +8,7 @@ import (
type ResponseFileStore = FileStore[*models.Response, *store.Store[*models.Response]]
func NewResponseFileStore(config *FileStoreConfig[*models.Response, *store.ResponseStore]) (*ResponseFileStore, error) {
return NewFileStore[*models.Response](config, store.NewStore[*models.Response]())
return NewFileStore(config, store.NewStore[*models.Response]())
}
func NewDefaultResponseFileStore() (*ResponseFileStore, error) {

View file

@ -33,10 +33,14 @@ func (s *SessionStore) Create(session *models.Session) (*models.Session, error)
}
}
session.Participants = make(map[string]*models.Participant, 0)
session.Quizzes = make(map[string]*models.Quiz, 0)
session.Answers = make(map[string]*models.Answer, 0)
for _, exam := range session.Exams {
session.Participants[exam.Participant.ID] = exam.Participant
for _, quiz := range exam.Quizzes {
session.Quizzes[quiz.ID] = quiz