diff --git a/front/public/src/myQuizs.js b/front/public/src/myQuizs.js
index 013eb4e..01da499 100644
--- a/front/public/src/myQuizs.js
+++ b/front/public/src/myQuizs.js
@@ -9,7 +9,7 @@ import { availableLangs } from "../../../config/instance.js";
const lang=availableLangs[0];
// Textes :
-const { localDBNotReady }=require("../../../lang/"+lang+"/answer");
+const { localDBNotReady, localFileFail, localFileImportOK, wantToSaveResultsDatas }=require("../../../lang/"+lang+"/answer");
const { serverError }=require("../../../lang/"+lang+"/general");
// Fonctions :
@@ -22,11 +22,9 @@ import { loadMatomo } from "./tools/matomo.js";
import { userQuizsResults} from "./tools/userQuizsResults";
// Éléments du DOM manipulés :
-//const btnSave=document.getElementById("want2Save");
-//const btnSubmit=document.getElementById("checkResponses");
-//const propose2Save=document.getElementById("propose2Save");
-//const responseTxt=document.getElementById("response");
+const datas2Restore=document.getElementById("datas2Restore");
const quizsList=document.getElementById("quizsList");
+const responseTxt=document.getElementById("response");
let userDB, allPreviousAnswers=[], myResults;
const initialise = async () =>
@@ -34,10 +32,14 @@ const initialise = async () =>
try
{
// Instanciation de la classe s'occupant du stockage des résultats aux quizs :
- myResults=await userQuizsResults.initialise("myResults", 1);
+ myResults=await userQuizsResults.initialise("myResults", 2);
// Si la base de données est fonctionnel et que des résultats sont déjà enregistrés, on affiche la liste des quizs ayant une réponse connue :
if(myResults.dbIsReady !== false)
- await myResults.showMyQuizs();
+ {
+ myResults.showMyQuizs();
+ if(myResults.allResults.length !== 0)
+ myResults.saveMyQuizs("quizsSave", wantToSaveResultsDatas, ["button"]);
+ }
else
addElement(quizsList, "p", localDBNotReady);
// Statistiques :
@@ -50,143 +52,44 @@ const initialise = async () =>
}
initialise();
helloDev();
-/*
-// Fonction affichant le quiz, quand il est caché par défaut+ déclenchant 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");
-}
-let chronoBegin;
-if(btnShow)
-{
- btnShow.addEventListener("click", function(e)
- {
- try
- {
- e.preventDefault();
- showQuestionnaire();
- }
- catch(e)
- {
- addElement(responseTxt, "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)
+datas2Restore.addEventListener("change", function(e)
{
try
{
- e.preventDefault();
- btnSubmit.style.display="none"; // seulement une réponse à la fois, SVP :)
- responseTxt.innerHTML=""; // supprime les éventuels messages déjà affichés
- answer=userQuizsResults.checkUserAnswers(myForm);
- answer.duration=Math.round((Date.now()-chronoBegin)/1000);
- answer.QuestionnaireId=quizInfos.QuestionnaireId;
- answer.GroupId=quizInfos.GroupId;
-
- // Enregistrement et affichage du résultat, suivant les cas :
- let getOuput=userQuizsResults.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(myResults.allResults.length !== 0)
+ responseTxt.innerHTML="";
+ const selectedFiles=datas2Restore.files;
+ if(selectedFiles !== null && selectedFiles.length === 1)
{
- const saveResponses=await myResults.addResult(answer);
- if(saveResponses)
- await myResults.showPreviousResultsForId(quizInfos.QuestionnaireId, quizInfos.GroupId);
- getOuput+="
"+wantToSeaPreviousResults.replace("URL","#explanations");
- // Nouveau quiz pour cette personne ?
- await myResults.saveNewQuiz(quizInfos);
- }
- else
- {
- // S'il n'a pas encore de données, on stocke temporairement le résultat et propose de l'enregistrer :
- if(myResults.saveResultTemp(answer) && myResults.dbIsReady)
+ // selectedFiles[0].type ne fonctionne pas avec certains navigateurs (Fennec), donc... :
+ const extension=selectedFiles[0].name.substring(selectedFiles[0].name.lastIndexOf(".")+1);
+ if(extension !== "json")
+ addElement(responseTxt, "p", localFileFail, "", ["error"]);
+ else
{
- getOuput+="
"+wantToSaveResponses;
- propose2Save.style.display="block";
- }
- }
- addElement(responseTxt, "p", getOuput, "", ["info"]);
- // On redirige vers le résultat :
- const here=window.location;
- 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(responseTxt, "p", serverError, "", ["error"]);
- console.error(e);
- }
-});
-
-// L'utilisateur demande à sauvegarder son résultat :
-btnSave.addEventListener("click", async function(e)
-{
- try
- {
- e.preventDefault();
- if(!isEmpty(myResults.dbIsReady) && !isEmpty(answer)) // On ne devrait pas m'avoir proposé d'enregistrer dans ce cas, mais...
- {
- const saveResponses=await myResults.addResult(answer);
- if(saveResponses)
- {
- // Nouvel enregistrement = actualisation nécessaire de la liste des résultats pour ce quiz :
- await myResults.showPreviousResultsForId(quizInfos.QuestionnaireId, quizInfos.GroupId);
- // Nouveau quiz (ce qui doit être le cas, mais...) :
- await myResults.saveNewQuiz(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 !== "")
+ // Lecture du contenu du fichier qui est passé au parseur :
+ const reader=new FileReader();
+ reader.onload=async function(e)
{
- window.location.hash="";// ! le "#" reste
- window.location.assign(here+"explanations");
- }
- else
- window.location.assign(here+"#explanations");
+ const datas=JSON.parse(reader.result);
+ if(myResults.dbIsReady !== false)
+ {
+ if((datas.quizs.length !==0) &&(datas.results.length !==0))
+ {
+ await myResults.saveAllResults(datas.results);
+ await myResults.saveAllQuizs(datas.quizs);
+ // Puis actualise l'affichage :
+ myResults.showMyQuizs();
+ addElement(responseTxt, "p", localFileImportOK, "", ["success"]);
+ }
+ }
+ };
+ reader.readAsText(selectedFiles[0]);
}
- propose2Save.style.display="none";
}
}
catch(e)
{
- addElement(responseTxt, "p", serverError, "", ["error"]);
console.error(e);
}
-});*/
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/front/public/src/quiz.js b/front/public/src/quiz.js
index 7277170..76a72de 100644
--- a/front/public/src/quiz.js
+++ b/front/public/src/quiz.js
@@ -29,7 +29,8 @@ const quizInfos=
url: window.location.pathname,
GroupId: document.getElementById("groupId").value,
QuestionnaireId: document.getElementById("questionnaireId").value,
- title: myForm.dataset.title
+ title: myForm.dataset.title,
+ keywords: myForm.dataset.keywords
};
// Éléments du DOM manipulés :
@@ -50,7 +51,7 @@ const initialise = async () =>
btnShow.style.display="inline"; // Le bouton est caché si le JS est inactif, car le JS est nécessaire pour la suite...
}
// Instanciation de la classe s'occupant du stockage des résultats aux quizs :
- myResults=await userQuizsResults.initialise("myResults", 1);
+ myResults=await userQuizsResults.initialise("myResults", 2);
// Si la base de données est fonctionnel et que des résultats sont déjà enregistrés, on affiche ceux pour le quiz en cours :
if(myResults.allResults.length !== 0)
await myResults.showPreviousResultsForId(quizInfos.QuestionnaireId, quizInfos.GroupId);
diff --git a/front/public/src/tools/userQuizsResults.js b/front/public/src/tools/userQuizsResults.js
index e736104..484c149 100644
--- a/front/public/src/tools/userQuizsResults.js
+++ b/front/public/src/tools/userQuizsResults.js
@@ -182,7 +182,12 @@ export class userQuizsResults
store.createIndex("nbCorrectAnswers", "nbCorrectAnswers", { unique: false });
store.createIndex("nbQuestions", "nbQuestions", { unique: false });
store.createIndex("date", "date", { unique: false }); // bien que doublons peu probables...
- }
+ }
+ if (e.oldVersion < 2)
+ {
+ const quizsStore=req.transaction.objectStore("userQuizs");
+ quizsStore.createIndex("keywords", "keywords", { unique: false });
+ }
};
req.onsuccess= (e) =>
{
@@ -350,6 +355,38 @@ export class userQuizsResults
})
}
+ // Importation en masse des résultats :
+ async saveAllResults(results)
+ {
+ await this.getOpenDb();
+ return new Promise( (resolve, reject) =>
+ {
+ const resultsStore=getStore(this.db, "userResults", "readwrite");
+ // Au commence par vider l'existant :
+ resultsStore.clear();
+ // Puis on enregistre les données fournies :
+ for(const result of results)
+ {
+ if(this.checkIfResultIsComplete(result))
+ {
+ let req;
+ req=resultsStore.add(result);
+ req.onerror= (e) =>
+ {
+ this.db.close();
+ reject(e);
+ };
+ }
+ }
+ this.db.close();
+ // On injecte les donnés qui ont été acceptées dans l'instance :
+ this.getAllResults().then( () =>
+ {
+ resolve(true);
+ });
+ })
+ }
+
// Enregistre le quiz, s'il n'existe pas déjà :
async saveNewQuiz(quizInfos)
{
@@ -397,6 +434,38 @@ export class userQuizsResults
}
})
}
+
+ // Importation en masse des quizs :
+ async saveAllQuizs(quizs)
+ {
+ await this.getOpenDb();
+ return new Promise( (resolve, reject) =>
+ {
+ const quizsStore=getStore(this.db, "userQuizs", "readwrite");
+ // Au commence par vider l'existant :
+ quizsStore.clear();
+ // Puis on enregistre les données fournies :
+ for(const quiz of quizs)
+ {
+ if(!isEmpty(quiz.url) && !isEmpty(quiz.title) && (!isEmpty(quiz.QuestionnaireId) || !isEmpty(quiz.GroupId)))
+ {
+ let req;
+ req=quizsStore.add(quiz);
+ req.onerror= (e) =>
+ {
+ this.db.close();
+ reject(e);
+ };
+ }
+ }
+ this.db.close();
+ // On injecte les donnés qui ont été acceptées dans l'instance :
+ this.getAllQuizs().then( () =>
+ {
+ resolve(true);
+ });
+ })
+ }
// Fonction affichant les précédents résultats connus pour le quiz encours :
async showPreviousResultsForId(QuestionnaireId, GroupId, txtContentId="explanationsContent", txtTitleId="explanationsTitle")
@@ -443,9 +512,7 @@ export class userQuizsResults
addElement(explanationsContent, "ul", previousResultsContent);
}
else
- addElement(explanationsContent, "ul", noPreviousResults);
- /// Revoir : ajouter un lien vers la page listant les quizs auxquels l'utilisateur a répondu
- /// addElement(explanationsContent, "p", ""+configTemplate.userHomePageTxt+"", "", ["btn"], "", false);
+ addElement(explanationsContent, "ul", noPreviousResults);
}
}
@@ -454,13 +521,24 @@ export class userQuizsResults
{
const listElt=document.getElementById(listId);
// On affiche d'abord les quizs les plus récents :
- const myQuizs=this.allQuizs.reverse();
+ const myQuizs=Object.values(this.allQuizs);
+ myQuizs.reverse();
let html="";
for(const quiz of myQuizs)
html+=`
À chaque fois que vous répondez à un quiz sur WikiLerni, votre résultat peut être enregistré, si vous l'acceptez.
-Vous n'avez pas besoin de créer un compte, car ces données sont enregistrées dans votre navigateur internet, c'est-à-dire sur votre ordinateur. Ceci peut ne pas fonctionner, si vous utilisez une navigation privée ou d'autres configurations interdisant ce type d'enregistrement.
-Par ailleurs, ces données ne sont accessibles qu'à partir du navigateur vous ayant permi des les enregistrer.
Aussi, pour éviter de les perdre, ou encore vous permettre de les récupérer sur un autre navigateur, un outil de sauvegarde vous est proposé.
Tout d’abord, cette fonctionnalité est encore expérimentale. Donc si vous rencontrez une erreur, n’hésitez pas à m’en informer.
+À chaque fois que vous répondez à un quiz sur WikiLerni, votre résultat peut être enregistré. Ceci vous est proposé lors du premier enregistrement et est ensuite automatique.
+Vous pouvez ainsi retrouver facilement les quizs auxquels vous avez déjà répondu, ainsi que vos précédents résultats.
+Vous n’avez pas besoin de créer un compte, car ces données sont enregistrées dans votre navigateur internet, c’est-à-dire sur votre ordinateur.
+Ceci peut ne pas fonctionner, si vous utilisez une navigation privée ou d’autres configurations interdisant ce type d’enregistrement.
+Par ailleurs, ces données ne sont accessibles qu’à partir du navigateur vous ayant permis de les enregistrer.
Aussi, pour éviter de perdre vos données, ou encore, vous permettre de les récupérer sur un autre navigateur, une solution de sauvegarde vous est proposée. N’hésitez pas à la tester.