Compare commits
No commits in common. "894358df20ad083d9830d5940d9d642a60794089" and "0e5961c406f0fab726a456cb6e15fe995a7666cf" have entirely different histories.
894358df20
...
0e5961c406
@ -3,7 +3,6 @@
|
|||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
import { getQuestions } from '../lib/questions';
|
import { getQuestions } from '../lib/questions';
|
||||||
import { ToastsStore } from '../stores/toasts';
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
export let survey = null;
|
export let survey = null;
|
||||||
@ -12,9 +11,7 @@
|
|||||||
survey.save().then((response) => {
|
survey.save().then((response) => {
|
||||||
dispatch('saved');
|
dispatch('saved');
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
ToastsStore.addErrorToast({
|
console.log(error)
|
||||||
msg: error.errmsg,
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,9 +19,7 @@
|
|||||||
survey.delete().then((response) => {
|
survey.delete().then((response) => {
|
||||||
goto(`surveys`);
|
goto(`surveys`);
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
ToastsStore.addErrorToast({
|
console.log(error)
|
||||||
msg: error.errmsg,
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,9 +27,7 @@
|
|||||||
survey.duplicate().then((response) => {
|
survey.duplicate().then((response) => {
|
||||||
goto(`surveys/${response.id}`);
|
goto(`surveys/${response.id}`);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
ToastsStore.addErrorToast({
|
console.log(error)
|
||||||
msg: error.errmsg,
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
export { className as class };
|
export { className as class };
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if survey.direct != null}<span class="badge bg-danger {className}">Direct</span>
|
{#if survey.direct}<span class="badge bg-danger {className}">Direct</span>
|
||||||
{:else if survey.startAvailability() > Date.now()}<span class="badge bg-info {className}">Prévu</span>
|
{:else if survey.startAvailability() > Date.now()}<span class="badge bg-info {className}">Prévu</span>
|
||||||
{:else if survey.endAvailability() > Date.now()}<span class="badge bg-warning {className}">En cours</span>
|
{:else if survey.endAvailability() > Date.now()}<span class="badge bg-warning {className}">En cours</span>
|
||||||
{:else if !survey.corrected}<span class="badge bg-primary text-light {className}">Terminé</span>
|
{:else if !survey.corrected}<span class="badge bg-primary text-light {className}">Terminé</span>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
req_surveys.then((surveys) => {
|
req_surveys.then((surveys) => {
|
||||||
for (const survey of surveys) {
|
for (const survey of surveys) {
|
||||||
if (survey.direct != null) {
|
if (survey.direct) {
|
||||||
direct = survey;
|
direct = survey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@
|
|||||||
{:then surveys}
|
{:then surveys}
|
||||||
<tbody style="cursor: pointer;">
|
<tbody style="cursor: pointer;">
|
||||||
{#each surveys as survey, sid (survey.id)}
|
{#each surveys as survey, sid (survey.id)}
|
||||||
{#if (survey.shown || survey.direct != null) && (!$user || (!$user.was_admin || $user.promo == survey.promo) || $user.is_admin)}
|
{#if survey.shown && (!$user || (!$user.was_admin || $user.promo == survey.promo) || $user.is_admin)}
|
||||||
{#if $user && $user.is_admin && (sid == 0 || surveys[sid-1].promo != survey.promo)}
|
{#if $user && $user.is_admin && (sid == 0 || surveys[sid-1].promo != survey.promo)}
|
||||||
<tr class="bg-info text-light">
|
<tr class="bg-info text-light">
|
||||||
<th colspan="5" class="fw-bold">
|
<th colspan="5" class="fw-bold">
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
<tr on:click={e => goto(survey.direct != null ?`surveys/${survey.id}/live`:$user.is_admin?`surveys/${survey.id}/responses`:`surveys/${survey.id}`)}>
|
<tr on:click={e => goto(survey.direct?`surveys/${survey.id}/live`:$user.is_admin?`surveys/${survey.id}/responses`:`surveys/${survey.id}`)}>
|
||||||
<td>
|
<td>
|
||||||
{survey.title}
|
{survey.title}
|
||||||
<SurveyBadge {survey} class="float-end" />
|
<SurveyBadge {survey} class="float-end" />
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { user } from '../stores/user';
|
import { user } from '../stores/user';
|
||||||
import { ToastsStore } from '../stores/toasts';
|
|
||||||
import QuestionForm from '../components/QuestionForm.svelte';
|
import QuestionForm from '../components/QuestionForm.svelte';
|
||||||
import { Question } from '../lib/questions';
|
import { Question } from '../lib/questions';
|
||||||
|
|
||||||
@ -20,16 +19,10 @@
|
|||||||
|
|
||||||
survey.submitAnswers(res, id_user).then((response) => {
|
survey.submitAnswers(res, id_user).then((response) => {
|
||||||
submitInProgress = false;
|
submitInProgress = false;
|
||||||
ToastsStore.addToast({
|
console.log("Vos réponses ont bien étés sauvegardées.");
|
||||||
msg: "Vos réponses ont bien étés sauvegardées.",
|
|
||||||
color: "success",
|
|
||||||
title: "Questionnaire",
|
|
||||||
});
|
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
submitInProgress = false;
|
submitInProgress = false;
|
||||||
ToastsStore.addErrorToast({
|
console.log("Une erreur s'est produite durant l'envoi de vos réponses : " + error + "<br>Veuillez réessayer dans quelques instants.");
|
||||||
msg: "Une erreur s'est produite durant l'envoi de vos réponses : " + error + "\nVeuillez réessayer dans quelques instants.",
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { ToastsStore } from '../stores/toasts';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="toast-container position-absolute top-0 end-0 p-3">
|
|
||||||
{#each $ToastsStore.toasts as toast}
|
|
||||||
<div class="toast show" role="alert">
|
|
||||||
<div class="toast-header">
|
|
||||||
<div class="bg-{toast.color} rounded me-2"> </div>
|
|
||||||
<strong>{#if toast.title}{toast.title}{:else}Questionnaire{/if}</strong>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="toast-body">
|
|
||||||
{toast.msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
@ -74,18 +74,6 @@ export class Question {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMyResponse() {
|
|
||||||
const res = await fetch(`api/questions/${this.id}/response`, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {'Accept': 'application/json'},
|
|
||||||
});
|
|
||||||
if (res.status == 200) {
|
|
||||||
return new Response(await res.json());
|
|
||||||
} else {
|
|
||||||
throw new Error((await res.json()).errmsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getResponses() {
|
async getResponses() {
|
||||||
const res = await fetch(`api/surveys/${this.id_survey}/questions/${this.id}/responses`, {
|
const res = await fetch(`api/surveys/${this.id_survey}/questions/${this.id}/responses`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
@ -42,8 +42,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Toaster from '../components/Toaster.svelte';
|
|
||||||
|
|
||||||
export let rroute = '';
|
export let rroute = '';
|
||||||
|
|
||||||
function switchAdminMode() {
|
function switchAdminMode() {
|
||||||
@ -142,5 +140,3 @@
|
|||||||
<div class="container mt-3">
|
<div class="container mt-3">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Toaster />
|
|
||||||
|
@ -181,7 +181,7 @@
|
|||||||
disabled={!current_question || !ws_up}
|
disabled={!current_question || !ws_up}
|
||||||
on:click={() => { ws.send('{"action":"pause"}')} }
|
on:click={() => { ws.send('{"action":"pause"}')} }
|
||||||
>
|
>
|
||||||
<i class="bi bi-pause-fill"></i>
|
Pause
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -213,7 +213,7 @@
|
|||||||
disabled={question.id === current_question || !ws_up}
|
disabled={question.id === current_question || !ws_up}
|
||||||
on:click={() => { ws.send('{"action":"new_question", "question":' + question.id + '}')} }
|
on:click={() => { ws.send('{"action":"new_question", "question":' + question.id + '}')} }
|
||||||
>
|
>
|
||||||
<i class="bi bi-play-fill"></i>
|
Lancer cette question
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { user } from '../../../stores/user';
|
import { user } from '../../../stores/user';
|
||||||
import { ToastsStore } from '../../../stores/toasts';
|
|
||||||
import SurveyBadge from '../../../components/SurveyBadge.svelte';
|
import SurveyBadge from '../../../components/SurveyBadge.svelte';
|
||||||
import QuestionForm from '../../../components/QuestionForm.svelte';
|
import QuestionForm from '../../../components/QuestionForm.svelte';
|
||||||
import { getQuestion } from '../../../lib/questions';
|
import { getQuestion } from '../../../lib/questions';
|
||||||
@ -26,26 +25,6 @@
|
|||||||
let show_question = null;
|
let show_question = null;
|
||||||
let value;
|
let value;
|
||||||
|
|
||||||
let req_question;
|
|
||||||
let nosend = false;
|
|
||||||
|
|
||||||
function afterQUpdate(q) {
|
|
||||||
value = undefined;
|
|
||||||
if (q) {
|
|
||||||
q.getMyResponse().then((response) => {
|
|
||||||
if (response && response.value)
|
|
||||||
value = response.value;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$: {
|
|
||||||
if (show_question) {
|
|
||||||
req_question = getQuestion(show_question);
|
|
||||||
req_question.then(afterQUpdate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function wsconnect() {
|
function wsconnect() {
|
||||||
const ws = new WebSocket((window.location.protocol == 'https'?'wss://':'ws://') + window.location.host + `/api/surveys/${sid}/ws`);
|
const ws = new WebSocket((window.location.protocol == 'https'?'wss://':'ws://') + window.location.host + `/api/surveys/${sid}/ws`);
|
||||||
|
|
||||||
@ -80,14 +59,12 @@
|
|||||||
wsconnect();
|
wsconnect();
|
||||||
|
|
||||||
function sendValue() {
|
function sendValue() {
|
||||||
if (show_question && value && !nosend) {
|
if (show_question && value) {
|
||||||
survey.submitAnswers([{"id_question": show_question, "value": value}], $user.id_user).then((response) => {
|
survey.submitAnswers([{"id_question": show_question, "value": value}], $user.id_user).then((response) => {
|
||||||
console.log("Vos réponses ont bien étés sauvegardées.");
|
console.log("Vos réponses ont bien étés sauvegardées.");
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
value = null;
|
value = null;
|
||||||
ToastsStore.addErrorToast({
|
console.log("Une erreur s'est produite durant l'envoi de vos réponses : " + error + "<br>Veuillez réessayer dans quelques instants.");
|
||||||
msg: "Une erreur s'est produite durant l'envoi de vos réponses : " + error + "\nVeuillez réessayer dans quelques instants.",
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,11 +91,8 @@
|
|||||||
|
|
||||||
<form on:submit|preventDefault={sendValue}>
|
<form on:submit|preventDefault={sendValue}>
|
||||||
{#if show_question}
|
{#if show_question}
|
||||||
{#await req_question}
|
{#await getQuestion(show_question)}
|
||||||
<div class="text-center">
|
Please wait
|
||||||
<div class="spinner-border text-primary mx-3" role="status"></div>
|
|
||||||
<span>Chargement d'une nouvelle question …</span>
|
|
||||||
</div>
|
|
||||||
{:then question}
|
{:then question}
|
||||||
<QuestionForm
|
<QuestionForm
|
||||||
qid={show_question}
|
qid={show_question}
|
||||||
@ -130,13 +104,6 @@
|
|||||||
<div class="progress-bar" role="progressbar" style="width: 25%"></div>
|
<div class="progress-bar" role="progressbar" style="width: 25%"></div>
|
||||||
</div-->
|
</div-->
|
||||||
</QuestionForm>
|
</QuestionForm>
|
||||||
{#if question.kind != 'mcq' && question.kind != 'ucq'}
|
|
||||||
<button
|
|
||||||
class="btn btn-primary"
|
|
||||||
>
|
|
||||||
Soumettre la réponse
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{/await}
|
{/await}
|
||||||
{:else if ws_up}
|
{:else if ws_up}
|
||||||
<h2 class="text-center">
|
<h2 class="text-center">
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import { writable } from 'svelte/store';
|
|
||||||
|
|
||||||
function createToastsStore() {
|
|
||||||
const { subscribe, set, update } = writable({toasts: []});
|
|
||||||
|
|
||||||
const addToast = (o) => {
|
|
||||||
o.timestamp = new Date();
|
|
||||||
|
|
||||||
o.close = () => {
|
|
||||||
update((i) => {
|
|
||||||
i.toasts = i.toasts.filter((j) => {
|
|
||||||
return !(j.title === o.title && j.msg === o.msg && j.timestamp === o.timestamp)
|
|
||||||
});
|
|
||||||
return i;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
update((i) => {
|
|
||||||
i.toasts.unshift(o);
|
|
||||||
return i;
|
|
||||||
});
|
|
||||||
|
|
||||||
o.cancel = setTimeout(o.close, o.dismiss?o.dismiss:5000);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addErrorToast = (o) => {
|
|
||||||
if (!o.title) o.title = 'Une erreur est survenue !';
|
|
||||||
if (!o.color) o.color = 'danger';
|
|
||||||
|
|
||||||
return addToast(o);
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
addToast,
|
|
||||||
addErrorToast,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ToastsStore = createToastsStore();
|
|
13
responses.go
13
responses.go
@ -64,10 +64,6 @@ func init() {
|
|||||||
func(s Survey, u *User, _ []byte) HTTPResponse {
|
func(s Survey, u *User, _ []byte) HTTPResponse {
|
||||||
return formatApiResponse(s.GetMyResponses(u, s.Corrected))
|
return formatApiResponse(s.GetMyResponses(u, s.Corrected))
|
||||||
}), loggedUser))
|
}), loggedUser))
|
||||||
router.GET("/api/questions/:qid/response", apiAuthHandler(questionAuthHandler(
|
|
||||||
func(q Question, u *User, _ []byte) HTTPResponse {
|
|
||||||
return formatApiResponse(q.GetMyResponse(u, false))
|
|
||||||
}), loggedUser))
|
|
||||||
router.GET("/api/users/:uid/surveys/:sid/responses", apiAuthHandler(func(u *User, ps httprouter.Params, body []byte) HTTPResponse {
|
router.GET("/api/users/:uid/surveys/:sid/responses", apiAuthHandler(func(u *User, ps httprouter.Params, body []byte) HTTPResponse {
|
||||||
return surveyAuthHandler(func(s Survey, u *User, _ []byte) HTTPResponse {
|
return surveyAuthHandler(func(s Survey, u *User, _ []byte) HTTPResponse {
|
||||||
return userHandler(func(u User, _ []byte) HTTPResponse {
|
return userHandler(func(u User, _ []byte) HTTPResponse {
|
||||||
@ -211,15 +207,6 @@ func (s *Survey) GetMyResponses(u *User, showScore bool) (responses []Response,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Question) GetMyResponse(u *User, showScore bool) (r Response, err error) {
|
|
||||||
err = DBQueryRow("SELECT R.id_response, R.id_question, R.id_user, R.answer, R.time_submit, R.score, R.score_explanation, R.id_corrector, R.time_scored FROM survey_responses R WHERE R.id_question=? AND R.id_user=? ORDER BY time_submit DESC LIMIT 1", q.Id, u.Id).Scan(&r.Id, &r.IdQuestion, &r.IdUser, &r.Answer, &r.TimeSubmit, &r.Score, &r.ScoreExplaination, &r.IdCorrector, &r.TimeScored)
|
|
||||||
if !showScore {
|
|
||||||
r.Score = nil
|
|
||||||
r.ScoreExplaination = nil
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Question) GetResponses() (responses []Response, err error) {
|
func (q *Question) GetResponses() (responses []Response, err error) {
|
||||||
if rows, errr := DBQuery("SELECT id_response, id_question, S.id_user, answer, S.time_submit, score, score_explanation, id_corrector, time_scored FROM (SELECT id_user, MAX(time_submit) AS time_submit FROM survey_responses WHERE id_question=? GROUP BY id_user) R INNER JOIN survey_responses S ON S.id_user = R.id_user AND S.time_submit = R.time_submit AND S.id_question=?", q.Id, q.Id); errr != nil {
|
if rows, errr := DBQuery("SELECT id_response, id_question, S.id_user, answer, S.time_submit, score, score_explanation, id_corrector, time_scored FROM (SELECT id_user, MAX(time_submit) AS time_submit FROM survey_responses WHERE id_question=? GROUP BY id_user) R INNER JOIN survey_responses S ON S.id_user = R.id_user AND S.time_submit = R.time_submit AND S.id_question=?", q.Id, q.Id); errr != nil {
|
||||||
return nil, errr
|
return nil, errr
|
||||||
|
Reference in New Issue
Block a user