Modification vue dernières publication + création nouvelle vue listant les tags.
This commit is contained in:
parent
8ce66d7981
commit
be91d0eb30
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
@ -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 : */
|
||||
|
@ -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
|
||||
};
|
||||
};*/
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 });
|
||||
|
@ -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();
|
||||
|
@ -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: "<h3>1 article Wikipédia + 1 quiz = 1 WikiLerni</h3><p>WikiLerni, ce sont plusieurs quizs publiés chaque semaine, chacun associé à un article Wikipédia.<br>Sans publicité, ni commerce de vos données, <b>vous apprenez de nouvelles choses en toute liberté</b>.</p><blockquote>Aristote : « L’homme a naturellement la passion de connaître… »</blockquote>",
|
||||
newsListTitle: "<h3>Avec WikiLerni, vous apprenez chaque jour quelque chose de nouveau</h3><p>Si dessous les dernières publications du site. Vous pouvez aussi <a href='/themes/'>parcourir le site par thèmes/mots-clés</a>.</p><blockquote>Aristote : « L’homme a naturellement la passion de connaître… »</blockquote>",
|
||||
/* 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: "<h3>Avec WikiLerni, apprenez quelque chose de nouveau chaque jour</h3><blockquote>Aristote : « L’homme a naturellement la passion de connaître… »</blockquote>",
|
||||
/* Page quizs */
|
||||
quizElementLinksIntro: "Source(s)",
|
||||
quizElementSubcriptionFormTitle: "Recevez les prochains WikiLerni",
|
||||
|
18
views/wikilerni/tagsList.pug
Normal file
18
views/wikilerni/tagsList.pug
Normal file
@ -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}
|
Loading…
Reference in New Issue
Block a user