From be91d0eb30911d158555b6c2be9b1c578f9c8fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20PENHO=C3=8BT?= Date: Thu, 29 Oct 2020 12:57:00 +0100 Subject: [PATCH] =?UTF-8?q?Modification=20vue=20derni=C3=A8res=20publicati?= =?UTF-8?q?on=20+=20cr=C3=A9ation=20nouvelle=20vue=20listant=20les=20tags.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + config/questionnaires.js | 6 ++- config/tags.js | 3 +- controllers/questionnaire.js | 7 ++- controllers/subscription.js | 4 ++ controllers/tag.js | 97 +++++++++++++++++++++++------------- views/wikilerni/config/fr.js | 6 ++- views/wikilerni/tagsList.pug | 18 +++++++ 8 files changed, 98 insertions(+), 44 deletions(-) create mode 100644 views/wikilerni/tagsList.pug diff --git a/.gitignore b/.gitignore index 767f6dc..b232392 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ nodemon.json /front/public/JS/*/ /front/public/quiz/ /front/public/quizs/ +/front/public/themes/ /front/public/index.html /front/public/CGV-CGU.html /front/public/mentions-legales.html diff --git a/config/questionnaires.js b/config/questionnaires.js index 999918e..d2560d7 100644 --- a/config/questionnaires.js +++ b/config/questionnaires.js @@ -58,11 +58,13 @@ module.exports = // Emplacement des fichiers HTML générés : dirHTMLGroups : "front/public/quiz/gp", dirHTMLQuestionnaires : "front/public/quiz", - dirHTMLTags : "front/public/quizs", + dirHTMLNews : "front/public/quizs", + dirHTMLTags : "front/public/themes", // Idem mais pour urls : dirWebGroups : "quiz/gp", dirWebQuestionnaires : "quiz", - dirWebTags : "quizs/", + dirWebNews : "quizs/", + dirWebTags : "themes/", // limite des résultat du moteur de recherche, quand demande de résultats au hasard : nbRandomResults : 3, /* Valeurs en fait définies dans instance.js donc à supprimer quand plus utilisées ailleurs : */ diff --git a/config/tags.js b/config/tags.js index 7a4b5ad..f81df0f 100644 --- a/config/tags.js +++ b/config/tags.js @@ -1,3 +1,4 @@ +/* // fichier à supprimer une fois tous les "require" ok const questionnaires = require("./questionnaires"); @@ -8,4 +9,4 @@ module.exports = dirWebTags : questionnaires.dirWebTags, nbTagsMin: questionnaires.nbTagsMin, nbTagsMax: questionnaires.nbTagsMax -}; \ No newline at end of file +};*/ \ No newline at end of file diff --git a/controllers/questionnaire.js b/controllers/questionnaire.js index 2cc219e..5ab0153 100644 --- a/controllers/questionnaire.js +++ b/controllers/questionnaire.js @@ -800,7 +800,7 @@ const creaNewQuestionnairesHTML = async (Questionnaires) => let questionnaires=[]; for(let i in Questionnaires) questionnaires.push(await searchQuestionnaireById(Questionnaires[i].id)); - let pageDatas= + let pageDatas = { config: config, configTpl: configTpl, @@ -822,10 +822,9 @@ const creaNewQuestionnairesHTML = async (Questionnaires) => compiledFunction=pug.compileFile("./views/"+config.theme+"/newQuestionnaires.pug"); pageDatas.metaDescription=configTpl.newQuestionnairesIntro; pageDatas.pageTitle=configTpl.newQuestionnairesTitle; - pageDatas.linkCanonical=config.siteUrl+"/"+configQuestionnaires.dirWebTags; - pageDatas.tags=await tagCtrl.getUsedTags(); + pageDatas.linkCanonical=config.siteUrl+"/"+configQuestionnaires.dirWebNews; html=await compiledFunction(pageDatas); - await toolFile.createHTML(configQuestionnaires.dirHTMLTags, "index", html); + await toolFile.createHTML(configQuestionnaires.dirHTMLNews, "index", html); return true; } diff --git a/controllers/subscription.js b/controllers/subscription.js index 6f731b4..5262f77 100644 --- a/controllers/subscription.js +++ b/controllers/subscription.js @@ -254,6 +254,7 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => // Il y a déjà eu au moins un envoi et le dernier envoi était un des éléments d'un quiz groupé : if(lastSended.length !==0 && lastSended[0].dateSended == subscriptionsOk[i].lastProcessingAt) { + console.log(subscriptionsOk[i].email+" a reçu un article hier.") const lastSendedGroup = await groupCtrl.searchGroupById(lastSended[0].GroupId); if(!tool.isEmpty(lastSendedGroup)) { @@ -261,6 +262,7 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => // Si le dernier élément envoyé était le dernier de son groupe, on envoie le lien du quiz reprenant toutes les questions du groupe : if(!tool.isEmpty(lastSendedGroupNbElements) && lastSendedGroup.Questionnaires[(lastSendedGroupNbElements-1)].id == lastSended[0].QuestionnaireId) { + console.log(subscriptionsOk[i].email+" va recevoir le quiz du groupe.") // Il faut que le quiz soi publié... Sinon on va envoyer un ancien quiz en attendant (cf + bas) if(lastSendedGroup.Group.isPublishable) elementToSend = lastSendedGroup.Group; @@ -268,6 +270,7 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => // Sinon l'élément suivant du groupe : else { + console.log(subscriptionsOk[i].email+" va recevoir le nouvel article du même groupe.") for(let j in lastSendedGroup.Questionnaires) if(lastSendedGroup.Questionnaires[j].id == lastSended[0].QuestionnaireId) elementToSend = await questionnaireCtrl.searchQuestionnaireById(lastSendedGroup.Questionnaires[(parseInt(j)+1)].id); @@ -276,6 +279,7 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => } else { + console.log(subscriptionsOk[i].email+" devrait recevoir le premier article du groupe suivant, si il existe.") // Soit il s'agit du premier envoi d'un abonnement, soit le dernier envoi était le quiz d'un groupe. // Dans ces deux cas, on va envoyer le premier élément non encore envoyé à cet abonné (le groupe peut ne pas être lui-même encore publié) : const getElementToSend = await db.sequelize.query("SELECT `Questionnaires`.`id` FROM `Questionnaires` INNER JOIN `Groups` ON `Questionnaires`.`GroupId`=`Groups`.`id` WHERE `Questionnaires`.`isPublished`=1 AND `Groups`.`language`='"+subscriptionsOk[i].language+"' AND `Questionnaires`.`id` NOT IN (SELECT `QuestionnaireId` FROM `QuestionnaireAccesses` where `UserId`="+subscriptionsOk[i].UserId+") ORDER BY `Groups`.`publishingAt`,`rankInGroup` ASC", { type: QueryTypes.SELECT }); diff --git a/controllers/tag.js b/controllers/tag.js index e419049..c2ecf45 100644 --- a/controllers/tag.js +++ b/controllers/tag.js @@ -1,21 +1,21 @@ const { Op, QueryTypes } = require("sequelize");// pour certaines requêtes sql const pug = require("pug"); -var striptags = require("striptags"); +const striptags = require("striptags"); const config = require("../config/main.js"); -const configTags = require("../config/tags.js"); +const configQuestionnaire = require("../config/questionnaires.js"); + +const ctrlQuestionnaire = require("./questionnaire"); const tool = require("../tools/main"); const toolError = require("../tools/error"); const toolFile = require("../tools/file"); -const questionnaireCtrl = require("./questionnaire"); - -const txt = require("../lang/"+config.adminLang+"/tag"); const txtGeneral = require("../lang/"+config.adminLang+"/general"); -const txtQuestionnaire = require("../lang/"+config.adminLang+"/questionnaire"); const txtIllustration = require("../lang/"+config.adminLang+"/illustration"); +const txtQuestionnaire = require("../lang/"+config.adminLang+"/questionnaire"); +const txtTag = require("../lang/"+config.adminLang+"/tag"); // Actualise le classement d'un questionnaire suivant les tags envoyés exports.checkTags = async (req, res, next) => @@ -23,10 +23,10 @@ exports.checkTags = async (req, res, next) => try { if(req.body.QuestionnaireId==undefined) - throw { message: txt.neededParams }; + throw { message: txtTag.neededParams }; const tagsCurrent=await getUsedTagsQuestionnaire(req.body.QuestionnaireId); if(tagsCurrent===false) - throw { message: txt.tagsForQuestionnaireNotFound }; + throw { message: txtTag.tagsForQuestionnaireNotFound }; const tagsReceived=req.body.classification.split(",");// ! peut être vide si pas/plus de classement souhaité for(i in tagsReceived) tagsReceived[i]=tagsReceived[i].trim().toLowerCase();// ! gestion de la casse différente pour JS, pas pour Mysql @@ -57,7 +57,7 @@ exports.checkTags = async (req, res, next) => } findTag=false; } - await questionnaireCtrl.creaQuestionnaireJson(req.body.QuestionnaireId);// attendre avant de répondre pour que cela pris en compte au réaffichage + await ctrlQuestionnaire.creaQuestionnaireJson(req.body.QuestionnaireId);// attendre avant de répondre pour que cela soit pris en compte au réaffichage. if(req.method=="PUT") res.status(200).json({ message: txtGeneral.updateOkMessage }); else if(req.method=="POST") @@ -82,13 +82,13 @@ exports.getTagsBeginningBy = async (req, res, next) => { try { - let tags=await getAllTags(), tagsOk=[], search=req.body.search.trim().toLowerCase(), item; + let tags=await getAllTags(), tagsOk=[], search=req.body.search.trim().toLowerCase(); if(search.length >= 2) { - for(i in tags) + for(let i in tags) { - item=tags[i].name.toLowerCase();// restera le problème des accents + let item=tags[i].name.toLowerCase();// il reste le problème des accents if(item.startsWith(search)) tagsOk.push(tags[i]); } @@ -129,14 +129,14 @@ const creaAllTagsJson = async () => { const db = require("../models/index"); const tags=await db["Tag"].findAll(); - await toolFile.createJSON(configTags.dirCacheTags, "all", tags); + await toolFile.createJSON(configQuestionnaire.dirCacheTags, "all", tags); return tags; } // Retourne la liste de tous les tags const getAllTags = async () => { - const tags=await toolFile.readJSON(configTags.dirCacheTags, "all"); + const tags=await toolFile.readJSON(configQuestionnaire.dirCacheTags, "all"); if(tags) return tags; else @@ -144,19 +144,45 @@ const getAllTags = async () => } // Créer la liste de tous tags utilisés pour classer au moins un quiz publié +/// Ajouter l'actualisation de la page "parcourir" du site const creaUsedTagsJson = async () => { const db = require("../models/index"); const tags = await db.sequelize.query("SELECT DISTINCT `Tags`.`id`,`Tags`.`name`,`Tags`.`slug` FROM `Tags` INNER JOIN `QuestionnaireClassifications` INNER JOIN `Questionnaires` WHERE `Tags`.`id`=`QuestionnaireClassifications`.`TagId` AND `QuestionnaireClassifications`.`QuestionnaireId`=`Questionnaires`.`id` AND `Questionnaires`.`isPublished`=true ORDER BY `name` ASC", { type: QueryTypes.SELECT , model: db["Tag"], mapToModel: true }); - await toolFile.createJSON(configTags.dirCacheTags, "used", tags); + await toolFile.createJSON(configQuestionnaire.dirCacheTags, "used", tags); + if(tags.length !== 0) + creaUsedTagsHTML(tags); return tags; } exports.creaUsedTagsJson = creaUsedTagsJson;// utile pour actualiser en cas de publication/dépublication d'un quiz +// Créer la page HTML listant tous les tags +const creaUsedTagsHTML = async (tags) => +{ + // + la page listant les X derniers quizs + liste des tags + const compiledFunction=pug.compileFile("./views/"+config.theme+"/tagsList.pug"); + const configTpl = require("../views/"+config.theme+"/config/"+config.availableLangs[0]+".js"); + let pageDatas = + { + config: config, + configTpl: configTpl, + tool: tool, + pageLang: config.adminLang, + metaDescription: configTpl.tagListMetaDesc, + pageTitle: configTpl.tagListTitle, + contentTitle: config.siteName, + tags: tags, + linkCanonical: config.siteUrl+"/"+configQuestionnaire.dirWebTags + } + html=await compiledFunction(pageDatas); + await toolFile.createHTML(configQuestionnaire.dirHTMLTags, "index", html); + return true; +} + // Retourne la liste des tags utilisés const getUsedTags = async () => { - const tags=await toolFile.readJSON(configTags.dirCacheTags, "used"); + const tags=await toolFile.readJSON(configQuestionnaire.dirCacheTags, "used"); if(tags) return tags; else @@ -168,20 +194,20 @@ exports.getUsedTags = getUsedTags; const getUsedTagsQuestionnaire = async (id) => { id=tool.trimIfNotNull(id); - if(id===null) + if(id === null) return false; - const questionnaire=await questionnaireCtrl.searchQuestionnaireById(id); + const questionnaire=await ctrlQuestionnaire.searchQuestionnaireById(id); if(!questionnaire) throw { message: txtQuestionnaire.notFound }; else { const allTags=await getAllTags(); let tagsQuestionnaire=[]; - for(i in questionnaire.Tags) + for(let i in questionnaire.Tags) { for(j in allTags) { - if(allTags[j].id===questionnaire.Tags[i].TagId) + if(allTags[j].id === questionnaire.Tags[i].TagId) { tagsQuestionnaire.push(allTags[j]); break; @@ -197,11 +223,11 @@ exports.getTagsQuestionnaire = getUsedTagsQuestionnaire; const creaQuestionnairesTagJson = async (id) => { id=tool.trimIfNotNull(id); - if(id===null) + if(id === null) return false; const db = require("../models/index"); const questionnaires = await db.sequelize.query("SELECT id FROM `Questionnaires` INNER JOIN `QuestionnaireClassifications` ON `Questionnaires`.`id`=`QuestionnaireClassifications`.`QuestionnaireId` AND `Questionnaires`.`isPublished`=1 AND `QuestionnaireClassifications`.`TagId`=:id ORDER BY "+config.fieldNewQuestionnaires+" DESC", { replacements: { id: id }, type: QueryTypes.SELECT , model: db["Questionnaire"], mapToModel: true }); - await toolFile.createJSON(configTags.dirCacheTags, "liste-"+id, questionnaires);// le supprimer si liste vide ? + await toolFile.createJSON(configQuestionnaire.dirCacheTags, "liste-"+id, questionnaires);// le supprimer si liste vide ? creaUsedTagsJson(); creaQuestionnairesTagHTML(id, questionnaires);// pas await, car potentiellement long ! return questionnaires; @@ -211,18 +237,18 @@ exports.creaQuestionnairesTagJson = creaQuestionnairesTagJson; const creaQuestionnairesTagHTML = async (id, Questionnaires) => { id=tool.trimIfNotNull(id); - if(id===null || Questionnaires===null) + if(id === null || Questionnaires === null) return false; const tag=await searchTagById(id); - if(Questionnaires.length===0) + if(Questionnaires.length === 0) { // plus aucun quiz classé ici. Il faudrait idéalement envoyer des erreurs 404/410, etc. // revoir aussi l'intérêt ou non de supprimer les pages suivantes, sachant qu'elles ne sont pas indexables ? ou les rendre dynamiques ? - await toolFile.deleteFile(configTags.dirHTMLTags, tag.slug+".html"); + await toolFile.deleteFile(configQuestionnaire.dirHTMLTags, tag.slug+".html"); return true; } const compiledFunction = pug.compileFile("./views/"+config.theme+"/tag.pug"); const configTpl = require("../views/"+config.theme+"/config/"+config.availableLangs[0]+".js"); - const pageDatas= + const pageDatas = { config: config, configTpl: configTpl, @@ -232,33 +258,32 @@ const creaQuestionnairesTagHTML = async (id, Questionnaires) => txtQuestionnaire: txtQuestionnaire, txtIllustration: txtIllustration, pageLang: config.adminLang, - metaDescription: config.siteName+" : "+txt.tagMetaDescription+tag.name, + metaDescription: config.siteName+" : "+txtTag.tagMetaDescription+tag.name, pageTitle: config.siteName+" - "+tag.name, contentTitle: config.siteName+" - "+tag.name, tagInfos: tag, - linkCanonical: config.siteUrl+"/"+configTags.dirWebTags+"/"+tag.slug+".html" + linkCanonical: config.siteUrl+"/"+configQuestionnaire.dirWebTags+"/"+tag.slug+".html" } const nbPages=Math.ceil(Questionnaires.length / configTpl.maxQuestionnairesByPage); pageDatas.nbPages=nbPages; - let debut=0, fin, questionnairesPage, questionnairesInfos=[], html, url; + let debut=0; for (let i = 1; i <= nbPages; i++) { - let questionnairesPage = Questionnaires.slice(debut, debut+configTpl.maxQuestionnairesByPage); + const questionnairesPage = Questionnaires.slice(debut, debut+configTpl.maxQuestionnairesByPage), questionnairesInfos=[]; for(let j in questionnairesPage) - questionnairesInfos.push(await questionnaireCtrl.searchQuestionnaireById(questionnairesPage[j].id)); + questionnairesInfos.push(await ctrlQuestionnaire.searchQuestionnaireById(questionnairesPage[j].id)); pageDatas.questionnaires=questionnairesInfos; pageDatas.page=i; - url=tag.slug; + let url=tag.slug; if(i!==1) { url=url+"-"+i; pageDatas.metaRobots="noindex,follow"; pageDatas.linkCanonical=null; } - html=await compiledFunction(pageDatas); - await toolFile.createHTML(configTags.dirHTMLTags, url, html); + const html=await compiledFunction(pageDatas); + await toolFile.createHTML(configQuestionnaire.dirHTMLTags, url, html); debut+=configTpl.maxQuestionnairesByPage; - questionnairesInfos=[]; } return true; } @@ -307,7 +332,7 @@ const linkTagQuestionnaire = async (tagName, questionnaireId) => const db = require("../models/index"); // ce tag est-il nouveau ? let tagLinked=await searchTagByName(tagName); - if(tagLinked===false) + if(tagLinked === false) { tagLinked=await db["Tag"].create({ name: tagName, slug: null }, { fields: ["name", "slug"] });// "slug : null" pour laisser le modèle le générer creaAllTagsJson(); diff --git a/views/wikilerni/config/fr.js b/views/wikilerni/config/fr.js index 1ff0051..5882b52 100644 --- a/views/wikilerni/config/fr.js +++ b/views/wikilerni/config/fr.js @@ -50,7 +50,11 @@ module.exports = /* Page dernières publications... */ newQuestionnairesTitle: "Culture générale - apprenez de nouvelles choses avec WikiLerni", newQuestionnairesIntro: "WikiLerni : testez vos connaissances et apprenez de nouvelles choses avec les quizs WikiLerni.", - newsListTitle: "

1 article Wikipédia + 1 quiz = 1 WikiLerni

WikiLerni, ce sont plusieurs quizs publiés chaque semaine, chacun associé à un article Wikipédia.
Sans publicité, ni commerce de vos données, vous apprenez de nouvelles choses en toute liberté.

Aristote : « L’homme a naturellement la passion de connaître… »
", + newsListTitle: "

Avec WikiLerni, vous apprenez chaque jour quelque chose de nouveau

Si dessous les dernières publications du site. Vous pouvez aussi parcourir le site par thèmes/mots-clés.

Aristote : « L’homme a naturellement la passion de connaître… »
", + /* Plan du site, liste des tags */ + tagListTitle: "Culture générale - des articles et quizs sur de nombreux thèmes !", + tagListMetaDesc: "WikiLerni : découvrir les différents thèmes abordés par WikiLerni. Inxex du site.", + tagListIntro: "

Avec WikiLerni, apprenez quelque chose de nouveau chaque jour

Aristote : « L’homme a naturellement la passion de connaître… »
", /* Page quizs */ quizElementLinksIntro: "Source(s)", quizElementSubcriptionFormTitle: "Recevez les prochains WikiLerni", diff --git a/views/wikilerni/tagsList.pug b/views/wikilerni/tagsList.pug new file mode 100644 index 0000000..4d04afc --- /dev/null +++ b/views/wikilerni/tagsList.pug @@ -0,0 +1,18 @@ +extends layout.pug + +block append scripts + script(src="/JS/polyfill.app.js" defer) + script(src="/JS/index.app.js" defer) + +block content + + div(id="prompt" class="cardboard") + p + img(id="logo" src="/themes/wikilerni/img/wikilerni-purple-2-512.png" alt="Logo WikiLerni") + h1(class="cardboard") #{configTpl.siteSlogan} + div#listsIntro !{configTpl.tagListIntro} + + nav(id="tagsList") + for tag in tags + div + a(href="/quizs/"+tag.slug+".html" class="button") #{tag.name} \ No newline at end of file