Improve live admin

This commit is contained in:
nemunaire 2022-09-02 12:00:13 +02:00
parent 0f8d77b05f
commit 4f13efbab1
2 changed files with 66 additions and 15 deletions

View File

@ -359,6 +359,7 @@ func SurveyWSAdmin(c *gin.Context) {
if survey, err := getSurvey(sid); err != nil { if survey, err := getSurvey(sid); err != nil {
log.Println("Unable to retrieve survey:", err) log.Println("Unable to retrieve survey:", err)
} else { } else {
survey.EndAvailability = time.Now()
survey.Direct = nil survey.Direct = nil
_, err = survey.Update() _, err = survey.Update()
if err != nil { if err != nil {

View File

@ -12,10 +12,11 @@
<script> <script>
import { user } from '../../../stores/user'; import { user } from '../../../stores/user';
import CorrectionPieChart from '../../../components/CorrectionPieChart.svelte'; import CorrectionPieChart from '../../../components/CorrectionPieChart.svelte';
import QuestionForm from '../../../components/QuestionForm.svelte';
import SurveyAdmin from '../../../components/SurveyAdmin.svelte'; import SurveyAdmin from '../../../components/SurveyAdmin.svelte';
import SurveyBadge from '../../../components/SurveyBadge.svelte'; import SurveyBadge from '../../../components/SurveyBadge.svelte';
import { getSurvey } from '../../../lib/surveys'; import { getSurvey } from '../../../lib/surveys';
import { getQuestions } from '../../../lib/questions'; import { getQuestion, getQuestions, Question } from '../../../lib/questions';
import { getUsers } from '../../../lib/users'; import { getUsers } from '../../../lib/users';
export let surveyP; export let surveyP;
@ -33,18 +34,32 @@
function updateSurvey() { function updateSurvey() {
surveyP = getSurvey(survey.id); surveyP = getSurvey(survey.id);
surveyP.then((s) => {
survey = s;
updateQuestions();
if (survey.direct !== null) {
wsconnect();
}
});
} }
function updateQuestions() { function updateQuestions() {
req_questions = getQuestions(survey.id); req_questions = getQuestions(survey.id);
} }
function deleteQuestion(question) {
edit_question = null;
question.delete();
}
let ws = null; let ws = null;
let ws_up = false; let ws_up = false;
let wsstats = null; let wsstats = null;
let current_question = null; let current_question = null;
let edit_question = null;
let responses = {}; let responses = {};
let corrected = false; let corrected = false;
let next_corrected = false;
let timer = 20; let timer = 20;
let timer_end = null; let timer_end = null;
let timer_remain = 0; let timer_remain = 0;
@ -85,7 +100,7 @@
responsesbyid = tmp; responsesbyid = tmp;
} }
let graph_data = {labels:[]}; let graph_data = {labels:[], datasets:[]};
async function reset_graph_data(questionid) { async function reset_graph_data(questionid) {
if (questionid) { if (questionid) {
const labels = []; const labels = [];
@ -147,23 +162,22 @@
ws.addEventListener("close", (e) => { ws.addEventListener("close", (e) => {
ws_up = false; ws_up = false;
console.log('Socket is closed. Reconnect will be attempted in 1 second.'); console.log('Socket is closed. Reconnect will be attempted in 1 second.');
ws = null;
updateSurvey();
setTimeout(function() { setTimeout(function() {
wsconnect(); ws = null;
updateSurvey();
}, 1500); }, 1500);
}); });
ws.addEventListener("error", (err) => { ws.addEventListener("error", (err) => {
ws_up = false; ws_up = false;
console.log('Socket closed due to error.', err); console.log('Socket closed due to error.', err);
ws = null;
}); });
ws.addEventListener("message", (message) => { ws.addEventListener("message", (message) => {
const data = JSON.parse(message.data); const data = JSON.parse(message.data);
if (data.action && data.action == "new_question") { if (data.action && data.action == "new_question") {
current_question = data.question; current_question = data.question;
corrected = data.corrected == true;
if (timer_cancel) { if (timer_cancel) {
clearInterval(timer_cancel); clearInterval(timer_cancel);
timer_cancel = null; timer_cancel = null;
@ -185,6 +199,9 @@
} else if (data.action && data.action == "new_ask") { } else if (data.action && data.action == "new_ask") {
asks.push({"id": data.question, "content": data.value, "userid": data.user}); asks.push({"id": data.question, "content": data.value, "userid": data.user});
asks = asks; asks = asks;
} else if (data.action && data.action == "end") {
ws.close();
updateSurvey();
} else { } else {
current_question = null; current_question = null;
timer_end = null; timer_end = null;
@ -209,6 +226,15 @@
> >
<i class="bi bi-align-end"></i> <i class="bi bi-align-end"></i>
</button> </button>
{:else}
<button
type="button"
class="btn btn-primary ms-1 float-end"
title="Commencer le direct"
on:click={() => {survey.shown = true; survey.direct = 0; survey.start_availability = new Date(); survey.end_availability = new Date(Date.now() + 43200000); survey.save().then(() => updateSurvey());}}
>
<i class="bi bi-align-start"></i>
</button>
{/if} {/if}
<a href="surveys/{survey.id}/responses" class="btn btn-success ms-1 float-end" title="Voir les réponses"><i class="bi bi-files"></i></a> <a href="surveys/{survey.id}/responses" class="btn btn-success ms-1 float-end" title="Voir les réponses"><i class="bi bi-files"></i></a>
{/if} {/if}
@ -306,13 +332,21 @@
<button <button
type="button" type="button"
class="btn btn-sm" class="btn btn-sm"
class:btn-outline-success={!corrected} class:btn-outline-success={!next_corrected}
class:btn-success={corrected} class:btn-success={next_corrected}
on:click={() => { corrected = !corrected } } on:click={() => { next_corrected = !next_corrected } }
title="La prochaine question est affichée corrigée" title="La prochaine question est affichée corrigée"
> >
<i class="bi bi-eye"></i> <i class="bi bi-eye"></i>
</button> </button>
<button
type="button"
class="btn btn-sm btn-info"
on:click={() => { edit_question = new Question({ id_survey: survey.id }) } }
title="Ajouter une question"
>
<i class="bi bi-plus"></i>
</button>
</th> </th>
</tr> </tr>
</thead> </thead>
@ -340,10 +374,10 @@
<button <button
type="button" type="button"
class="btn btn-sm" class="btn btn-sm"
class:btn-primary={!corrected} class:btn-primary={!next_corrected}
class:btn-success={corrected} class:btn-success={next_corrected}
disabled={question.id === current_question || !ws_up} disabled={(question.id === current_question && next_corrected == corrected) || !ws_up}
on:click={() => { ws.send('{"action":"new_question", "corrected": ' + corrected + ', "timer": 0, "question":' + question.id + '}')} } on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + ', "timer": 0, "question":' + question.id + '}')} }
> >
<i class="bi bi-play-fill"></i> <i class="bi bi-play-fill"></i>
</button> </button>
@ -351,7 +385,7 @@
type="button" type="button"
class="btn btn-sm btn-danger" class="btn btn-sm btn-danger"
disabled={question.id === current_question || !ws_up} disabled={question.id === current_question || !ws_up}
on:click={() => { ws.send('{"action":"new_question", "corrected": ' + corrected + ', "timer": ' + timer * 1000 + ',"question":' + question.id + '}')} } on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + ', "timer": ' + timer * 1000 + ',"question":' + question.id + '}')} }
> >
<i class="bi bi-stopwatch-fill"></i> <i class="bi bi-stopwatch-fill"></i>
</button> </button>
@ -363,6 +397,14 @@
> >
<i class="bi bi-files"></i> <i class="bi bi-files"></i>
</a> </a>
<button
type="button"
class="btn btn-sm btn-info"
disabled={question.id === current_question}
on:click={() => { getQuestion(question.id).then((q) => {edit_question = q})} }
>
<i class="bi bi-pencil"></i>
</button>
</td> </td>
</tr> </tr>
{/each} {/each}
@ -370,6 +412,14 @@
</table> </table>
</div> </div>
{/await} {/await}
{#if edit_question !== null}
<QuestionForm
{survey}
edit
question={edit_question}
on:delete={() => deleteQuestion(edit_question)}
/>
{/if}
<hr> <hr>
<button <button
@ -588,7 +638,7 @@
<small class="text-muted">{wsstats.nb_clients} utilisateurs</small> <small class="text-muted">{wsstats.nb_clients} utilisateurs</small>
{/if} {/if}
</h3> </h3>
{#if wsstats} {#if wsstats && wsstats.users}
<div class="row row-cols-5 py-3"> <div class="row row-cols-5 py-3">
{#each wsstats.users as login, lid (lid)} {#each wsstats.users as login, lid (lid)}
<div class="col"> <div class="col">