2022-03-01 17:40:41 +01:00
// -- GESTION DU FORMULAIRE PERMETTANT D'AFFICHER ET RÉPONDRE À UN QUIZ
/// Il n'est pas nécessaire d'avoir une base de données locale active pour répondre à un quiz.
/// Mais si ce n'est pas déjà le cas et que cela semble techniquement possible, on propose au répondant de sauvegarder son résultat.
/// Dans ce but son résultat est stocké temporairement.
/// Si la base de donnée locale existe déjà, l'enregistrement de son résultat se fait automatiquement dans IndexedDB et ses éventuels précédents résultats sont affichés.
// Configurations générales provenant du backend :
2022-03-14 18:17:54 +01:00
import { availableLangs , theme } from "../../../config/instance.js" ;
2022-03-01 17:40:41 +01:00
const lang = availableLangs [ 0 ] ;
// Fonctions :
import { checkAllPreviousResults , checkUserAnswers , getResultOutput , resultsOpenDb , saveNewQuiz , saveResult , saveResultTemp , showPreviousResults } from "./tools/answers.js" ;
import { saveIsReady } from "./tools/clientstorage.js" ;
import { addElement } from "./tools/dom.js" ;
import { helloDev } from "./tools/everywhere.js" ;
2022-03-14 18:17:54 +01:00
import { isEmpty } from "../../../tools/main" ;
2022-03-01 17:40:41 +01:00
import { loadMatomo } from "./tools/matomo.js" ;
// Textes :
2022-03-14 18:17:54 +01:00
const { wantToSaveResponses , wantToSeaPreviousResults } = require ( "../../../lang/" + lang + "/answer" ) ;
const { localDBConnexionFail , serverError } = require ( "../../../lang/" + lang + "/general" ) ;
2022-03-01 17:40:41 +01:00
// Informations du quiz, utile pour enregistrement dans base de donnée locale :
const myForm = document . getElementById ( "quiz" ) ; // quiz
const quizInfos =
{
url : window . location . pathname ,
GroupId : document . getElementById ( "groupId" ) . value ,
QuestionnaireId : document . getElementById ( "questionnaireId" ) . value ,
title : myForm . dataset . title
} ;
// Autres éléments du DOM manipulés :
const propose2Save = document . getElementById ( "propose2Save" ) ;
const btnSave = document . getElementById ( "want2Save" ) ;
const btnSubmit = document . getElementById ( "checkResponses" ) ;
const divResponse = document . getElementById ( "response" ) ;
// L'url permet de savoir si nous sommes sur un quiz unique ou groupé :
let btnShow ;
if ( quizInfos . url . indexOf ( "/gp/" ) == - 1 )
btnShow = document . getElementById ( "showQuestionnaire" ) ; // le quiz est affiché directement pour les groupes
let userDB , allPreviousAnswers = [ ] ;
const initialise = async ( ) =>
{
try
{
if ( btnShow )
btnShow . style . display = "inline" ; // Le bouton est caché si le JS inactif, car le JS est nécessaire pour la suite...
// On vérifie si la navigateur accepte l'utilisation d'IndexedDB :
const saveIsPossible = saveIsReady ( ) ;
if ( saveIsPossible )
{
// On essaye ensuite de se connecter à la base de données (ce qui va la créer si inexistante) :
userDB = await resultsOpenDb ( "myAnswers" , 1 ) ;
if ( userDB === undefined )
console . error ( localDBConnexionFail ) ;
else
{
// Vérifie si l'utilisateur a déjà sauvegardé au moins un résultat (et donc est ok pour les sauvegardes) :
allPreviousAnswers = await checkAllPreviousResults ( userDB ) ;
if ( allPreviousAnswers . length !== 0 )
await showPreviousResults ( userDB , quizInfos . QuestionnaireId , quizInfos . GroupId ) ;
}
}
loadMatomo ( ) ;
}
catch ( e )
{
console . error ( e ) ;
}
}
initialise ( ) ;
helloDev ( ) ;
// Affichage du quiz, quand il est caché par défaut (= l'internaute doit d'abord lire un article Wikipédia).
// Déclenche en même temps le chronomètre mesurant la durée de réponse aux questions.
const showQuestionnaire = ( ) =>
{
chronoBegin = Date . now ( ) ;
myForm . style . display = "block" ;
btnShow . style . display = "none" ;
const here = window . location ; // window.location à ajouter pour ne pas quitter la page en mode "preview".
if ( window . location . hash !== "" )
{
window . location . hash = "" ; // ! le "#" reste
window . location . assign ( here + "questionnaire" ) ;
}
else
window . location . assign ( here + "#questionnaire" ) ;
}
// L'utilisateur demande à voir le quiz :
let chronoBegin = 0 ;
if ( btnShow )
{
btnShow . addEventListener ( "click" , function ( e )
{
try
{
e . preventDefault ( ) ;
showQuestionnaire ( ) ;
}
catch ( e )
{
addElement ( divResponse , "p" , serverError , "" , [ "error" ] ) ;
console . error ( e ) ;
}
} ) ;
// Un lien peut être passé pour voir directement le quiz :
if ( location . hash !== "" && location . hash === "#questionnaire" )
showQuestionnaire ( ) ;
}
// Dans le cas d'un quiz groupé, le chrono est lancé dès l'affichage :
if ( quizInfos . GroupId != "0" )
{
chronoBegin = Date . now ( ) ;
btnSubmit . style . display = "block" ;
}
// Traitement de l'envoi de la réponse de l'utilisateur :
let answer ;
myForm . addEventListener ( "submit" , async function ( e )
{
try
{
e . preventDefault ( ) ;
btnSubmit . style . display = "none" ; // seulement une réponse à la fois, SVP :)
divResponse . innerHTML = "" ; // supprime les éventuels messages déjà affichés
answer = checkUserAnswers ( myForm ) ;
answer . duration = Math . round ( ( Date . now ( ) - chronoBegin ) / 1000 ) ;
answer . QuestionnaireId = quizInfos . QuestionnaireId ;
answer . GroupId = quizInfos . GroupId ;
// Affichage du résultat, suivant les cas :
let getOuput = getResultOutput ( answer ) ;
// S'il y a déjà une réponse dans la bd, c'est que l'utilisateur est ok pour les enregister.
if ( allPreviousAnswers . length !== 0 )
{
const saveResponses = await saveResult ( userDB , answer ) ;
if ( saveResponses )
await showPreviousResults ( userDB , quizInfos . QuestionnaireId , quizInfos . GroupId ) ;
getOuput += "<br><br>" + wantToSeaPreviousResults . replace ( "URL" , "#explanations" ) ;
// Nouveau quiz pour cette personne ?
await saveNewQuiz ( userDB , quizInfos ) ;
}
else
{
// S'il n'a pas encore de données, on stocke temporairement le résultat et propose de l'enregistrer :
if ( saveResultTemp ( answer ) && ! isEmpty ( userDB ) )
{
getOuput += "<br><br>" + wantToSaveResponses ;
propose2Save . style . display = "block" ;
}
}
addElement ( divResponse , "p" , getOuput , "" , [ "info" ] ) ;
// On redirige vers le résultat :
const here = window . location ; // window.location à ajouter pour ne pas quitter la page en mode "preview".
if ( window . location . hash !== "" )
{
window . location . hash = "" ; // ! le "#" reste
window . location . assign ( here + "response" ) ;
}
else
window . location . assign ( here + "#response" ) ;
// + Affichage des textes d'explication pour chaque question
const explanations = document . querySelectorAll ( ".help" ) ;
for ( let i in explanations )
{
if ( explanations [ i ] . style != undefined ) // sinon, la console affiche une erreur "TypeError: explanations[i].style is undefined", bien que tout fonctionne (?)
explanations [ i ] . style . display = "block" ;
}
}
catch ( e )
{
addElement ( divResponse , "p" , serverError , "" , [ "error" ] ) ;
console . error ( e ) ;
}
} )
// L'utilisateur demande à sauvegarder son résultat :
btnSave . addEventListener ( "click" , async function ( e )
{
try
{
e . preventDefault ( ) ;
if ( ! isEmpty ( userDB ) && ! isEmpty ( answer ) ) // On ne devrait pas me proposer d'enregistrer dans ce cas, mais...
{
const saveResponses = await saveResult ( userDB , answer ) ;
if ( saveResponses )
{
// Nouvel enregistrement = actualisation nécessaire de la liste des résultats pour ce quiz :
await showPreviousResults ( userDB , quizInfos . QuestionnaireId , quizInfos . GroupId ) ;
// Nouveau quiz
await saveNewQuiz ( userDB , quizInfos ) ;
// Redirection vers la liste des résultats :
const here = window . location ; // window.location à ajouter pour ne pas quitter la page en mode "preview".
if ( window . location . hash !== "" )
{
window . location . hash = "" ; // ! le "#" reste
window . location . assign ( here + "explanations" ) ;
}
else
window . location . assign ( here + "#explanations" ) ;
}
propose2Save . style . display = "none" ;
}
}
catch ( e )
{
addElement ( divResponse , "p" , serverError , "" , [ "error" ] ) ;
console . error ( e ) ;
}
} ) ;