WikiLerni/controllers/questionnaire.js

742 lines
30 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { Op, QueryTypes } = require("sequelize");
const pug = require("pug");
const striptags = require("striptags");
const config = require("../config/main.js");
const configQuestionnaires = require("../config/questionnaires.js");
const configTags = require("../config/tags.js");
const configLinks = require("../config/links.js");
const configIllustrations = require("../config/illustrations.js");
const configTpl = require("../views/"+config.theme+"/config/"+config.availableLangs[0]+".js");
const tool = require("../tools/main");
const toolError = require("../tools/error");
const toolFile = require("../tools/file");
const toolMail = require("../tools/mail");
const questionCtrl = require("./question");
const illustrationCtrl = require("./illustration");
const tagCtrl = require("./tag");
const userCtrl = require("./user");
const txtGeneral = require("../lang/"+config.adminLang+"/general");
const txtQuestionnaire = require("../lang/"+config.adminLang+"/questionnaire");
const txtQuestionnaireAccess = require("../lang/"+config.adminLang+"/questionnaireaccess");
const txtIllustration = require("../lang/"+config.adminLang+"/illustration");
exports.create = async (req, res, next) =>
{
try
{
const db = require("../models/index");
req.body.CreatorId=req.connectedUser.User.id;
const questionnaire=await db["Questionnaire"].create({ ...req.body }, { fields: ["title", "slug", "introduction", "keywords", "publishingAt", "language", "estimatedTime", "CreatorId"] });
creaStatsQuestionnairesJson();
//utile au middleware suivant (classement tags) qui s'occupe aussi de retourner une réponse si ok :
req.body.QuestionnaireId=questionnaire.id;
next();
}
catch(e)
{
const returnAPI=toolError.returnSequelize(e);
if(returnAPI.messages)
{
res.status(returnAPI.status).json({ errors : returnAPI.messages });
next();
}
else
next(e);
}
}
exports.modify = async (req, res, next) =>
{
try
{
const db = require("../models/index");
const questionnaire=await searchQuestionnaireById(req.params.id);
if(!questionnaire)
{
const Err=new Error;
error.status=404;
error.message=txtQuestionnaire.notFound+" ("+req.params.id+")";
throw Err;
}
else if(req.connectedUser.User.status==="creator" && req.connectedUser.User.id!==questionnaire.CreatorId)
res.status(401).json({ errors: txtGeneral.notAllowed });
else
{
await db["Questionnaire"].update({ ...req.body }, { where: { id : req.params.id } , fields: ["title", "slug", "introduction", "keywords", "publishingAt", "language", "estimatedTime"], limit:1 }); // voir si admin aura le droit de changer le créateur ? et ajouter une gestion des redirection si slug change ?
creaStatsQuestionnairesJson();// le nombre de quizs publiés peut avoir changé
}
//utile au middleware suivant (classement tags) qui s'occupe aussi de retourner une réponse si ok :
req.body.QuestionnaireId=req.params.id;
next();
}
catch(e)
{
const returnAPI=toolError.returnSequelize(e);
if(returnAPI.messages)
{
res.status(returnAPI.status).json({ errors : returnAPI.messages });
next();
}
else
next(e);
}
}
exports.delete = async (req, res, next) =>
{
try
{
const db = require("../models/index");
const questionnaire=await searchQuestionnaireById(req.params.id);
if(!questionnaire)
{
const Err=new Error;
error.status=404;
error.message=txtQuestionnaire.notFound+" ("+req.params.id+")";
throw Err;
}
else if(req.connectedUser.User.status==="creator" && req.connectedUser.User.id!==questionnaire.CreatorId)
res.status(401).json({ errors: txtGeneral.notAllowed });
else
{
// Permet de supprimer les fichiers associés en plus du sql. Inutile pour link qui n'a pas de fichier.
// À faire avant la suppression SQL du questionnaire entraînant la suppression en cascade du reste.
for(i in questionnaire.Questions)
await questionCtrl.deleteQuestionById(questionnaire.Questions[i].id);
for(i in questionnaire.Illustrations)
await illustrationCtrl.deleteIllustrationById(questionnaire.Illustrations[i].id);
const nb=await db["Questionnaire"].destroy( { where: { id : req.params.id }, limit:1 });
if(nb===1)
{
await toolFile.deleteJSON(config.dirCacheQuestionnaires, req.params.id);
res.status(200).json({ message: txtGeneral.deleteOkMessage });
// actualisation de liste des questionnaires pour les tags concernés.
// Ici au contraire, les enregistrements doivent être supprimés avant.
for(let i in questionnaire.Tags)
tagCtrl.creaQuestionnairesTagJson(questionnaire.Tags[i].TagId);
// La suppression peut éventuellement concerner un des derniers questionnaires, donc :
creaNewQuestionnairesJson();
creaStatsQuestionnairesJson();
// Éventuellement regénérer les caches listant les réponses/quizs des users ayant accès à ce questionnaire ?
// ++ HTML
}
else
{
const Err=new Error;
error.status=404;
error.message=txtQuestionnaire.notFound+" ("+req.params.id+")";
throw Err;
}
}
next();
}
catch(e)
{
next(e);
}
}
exports.getOneQuestionnaireById = async (req, res, next) =>
{
try
{
const datas=await searchQuestionnaireById(req.params.id, true);
if(datas)
res.status(200).json(datas);
else
res.status(404).json({ errors:txtQuestionnaire.notFound });
next();
}
catch(e)
{
next(e);
}
}
exports.showOneQuestionnaireById = async (req, res, next) =>
{
try
{
// Seuls certains utilisateurs peuvent avoir accès à cette page
const connectedUser=await userCtrl.checkTokenUser(req.params.token);
if(connectedUser===false)
res.status(403).json({ errors:txtGeneral.failAuthToken });
else
{
if(["admin", "manager", "creator"].indexOf(connectedUser.User.status) === -1)
res.status(403).json({ errors:txtGeneral.notAllowed });
else
{
const HTML=await creaQuestionnaireHTML(req.params.id, true);
if(HTML)
{
res.setHeader("Content-Type", "text/html");
res.send(HTML);
}
else
res.status(404).json({ errors:txtQuestionnaire.notFound });
}
}
next();
}
catch(e)
{
next(e);
}
}
// Recherche par mots-clés parmis tous les questionnaires publiés en filtrant parmi ceux auxquels l'abonné a déjà répondu ou pas
// Seul un certain nombre de résultats est renvoyé (pagination)
exports.searchQuestionnaires = async (req, res, next) =>
{
try
{
let search=tool.trimIfNotNull(req.body.searchQuestionnaires);
if(search === null || search === "" || search.length < config.minSearchQuestionnaires)
res.status(400).json(txtQuestionnaireAccess.searchIsNotLongEnough);
else
{
const db = require("../models/index");
let getQuestionnaires;
if(!tool.isEmpty(req.body.onlyAnswers) && !tool.isEmpty(req.connectedUser.User.id))
getQuestionnaires=await db.sequelize.query("SELECT DISTINCT `Questionnaires`.`id` FROM `Questionnaires` INNER JOIN `Answers` WHERE `Answers`.`QuestionnaireId`=`Questionnaires`.`id` AND `Answers`.`UserId`=:id AND (`title` LIKE :search OR `keywords` LIKE :search) AND `isPublished` = 1", { replacements: { id:req.connectedUser.User.id, search: "%"+search+"%" }, type: QueryTypes.SELECT });
else
getQuestionnaires=await db.sequelize.query("SELECT `id` FROM `Questionnaires` WHERE (`title` LIKE :search OR `keywords` LIKE :search) AND `isPublished` = 1", { replacements: { search: "%"+search+"%" }, type: QueryTypes.SELECT });
let begin=0, end, output="";
if(!tool.isEmpty(req.body.begin))
begin=parseInt(req.body.begin, 10);
end=begin+configTpl.nbQuestionnairesUserHomePage-1;// tableau commence à 0 !
if(req.body.output!==undefined)
output=req.body.output;
datas=await getListingsQuestionnairesOuput(getQuestionnaires, begin, end, output);
res.status(200).json(datas);
}
next();
}
catch(e)
{
next(e);
}
}
// Recherche aléatoire parmi tous les questionnaires publiés
// De nouveau on peut filtrer ou non ceux auxquels l'utilisateur a répondu
// Par contre, ici pas de pagination car on maîtrise le nombre de résultats envoyés
exports.getRandomQuestionnaires = async (req, res, next) =>
{
try
{
const db = require("../models/index");
let getQuestionnaires;
if(!tool.isEmpty(req.body.onlyAnswers) && !tool.isEmpty(req.connectedUser.User.id))
getQuestionnaires=await db.sequelize.query("SELECT DISTINCT `Questionnaires`.`id` FROM `Questionnaires` INNER JOIN `Answers` WHERE `Answers`.`QuestionnaireId`=`Questionnaires`.`id` AND `Answers`.`UserId`=:id AND `isPublished` = 1 ORDER BY RAND() LIMIT "+configQuestionnaires.nbRandomResults, { replacements: { id:req.connectedUser.User.id }, type: QueryTypes.SELECT });
else
getQuestionnaires=await db.sequelize.query("SELECT `id` FROM `Questionnaires` WHERE `isPublished` = 1 ORDER BY RAND() LIMIT "+configQuestionnaires.nbRandomResults, { type: QueryTypes.SELECT });
let begin=0, end;
end=begin+configTpl.nbQuestionnairesUserHomePage-1;
datas=await getListingsQuestionnairesOuput(getQuestionnaires, begin, end, "html");
res.status(200).json(datas);
next();
}
catch(e)
{
next(e);
}
}
// Recherche par mots-clés parmis tous les questionnaires, y compris ceux non publiés
exports.searchAdminQuestionnaires = async (req, res, next) =>
{
try
{
let search=tool.trimIfNotNull(req.body.searchQuestionnaires);
if(search === null || search === "" || search.length < config.minSearchQuestionnaires)
res.status(400).json(txtQuestionnaireAccess.searchIsNotLongEnough);
else
{
const db = require("../models/index");
const getQuestionnaires=await db.sequelize.query("SELECT `id`,`title` FROM `Questionnaires` WHERE (`title` LIKE :search OR `introduction` LIKE :search OR `keywords` LIKE :search) ORDER BY `title` ASC", { replacements: { search: "%"+search+"%" }, type: QueryTypes.SELECT });
res.status(200).json(getQuestionnaires);
}
next();
}
catch(e)
{
next(e);
}
}
// Retourne les statistiques concernant les questionnaires
exports.getStats = async(req, res, next) =>
{
try
{
const stats=await getStatsQuestionnaires();
res.status(200).json(stats);
}
catch(e)
{
next(e);
}
}
// Liste des prochains questionnaires devant être publiés.
// On vérifie à chaque fois si ils ont ce qu'il faut pour être publiables
// On en profite pour chercher la prochaine date sans questionnaire programmé
exports.getListNextQuestionnaires = async(req, res, next) =>
{
try
{
let questionnaires=await getNextQuestionnaires();
const dayWithoutPublication=[0,6];// à déclarer dans config + gérer cas où aucun jour n'est obligatoire
let dateNeeded="", questionnairesDatas, dateQuestionnaireTS, previousDayNeededTS, previousDayTS;
for(let i in questionnaires)
{
questionnairesDatas=await searchQuestionnaireById(questionnaires[i].id);
questionnaires[i].isPublishable=checkQuestionnaireIsPublishable(questionnairesDatas, false); // le questionnaire est-il complet ?
dateQuestionnaireTS=new Date(questionnaires[i].datePublishing).getTime();
if(dateNeeded==="")
{
// je commence par chercher le jour précédent pour lequel je dois avoir publié quelque chose :
previousDayTS=new Date(new Date(dateQuestionnaireTS-3600*1000*24));
previousDayNeededTS=0;
while (previousDayNeededTS===0)
{
if(dayWithoutPublication.indexOf(previousDayTS.getDay())===-1)
previousDayNeededTS=previousDayTS;
else
previousDayTS=new Date(previousDayTS.getTime()-3600*1000*24);
}
// si il n'y a pas de quiz précédent, cette date est celle que je cherche
if(!questionnaires[i-1])
{
if(previousDayNeededTS >= Date.now())
dateNeeded=previousDayNeededTS;
}
else
{ // sinon je compare la date du précédent quiz à celle pour laquelle j'ai besoin d'un quiz
if(new Date(questionnaires[i-1].datePublishing).getTime() < previousDayNeededTS)
dateNeeded=previousDayNeededTS;
}
}
}
if(questionnaires.length > 0 && dateNeeded==="")
dateNeeded=new Date(dateQuestionnaireTS+3600*1000*24);// le jour suivant celui du dernier questionnaire
else
dateNeeded=new Date(Date.now()+3600*1000*24);// mais il est possible que rien n'ai été publié ce jour, le quiz du jour étant absent de la liste traitée
res.status(200).json({questionnaires: questionnaires, dateNeeded: dateNeeded });
next();
}
catch(e)
{
next(e);
}
}
// test si des questionnaires doivent être publiés
// puis (re)génère tous les fichiers HTML des questionnaires + les pages accueil + news
// la requête est ensuite passé aux tags qui font la même chose
exports.HTMLRegenerate= async (req, res, next) =>
{
try
{
await checkQuestionnairesNeedToBePublished();
const nb=await checkQuestionnairesPublishedHaveHTML(true);
creaNewQuestionnairesJson();// provoque mise à jour du HTLM, RSS, etc.
res.messageToNext=txtQuestionnaire.haveBeenRegenerated.replace("#NB1", nb);
next();
}
catch(e)
{
next(e);
}
}
// CRONS
// Supprime fichiers json de questionnaires n'existant plus.
exports.deleteJsonFiles= async (req, res, next) =>
{
try
{
const db = require("../models/index");
const questionnaires=await db["Questionnaire"].findAll({ attributes: ["id"] });
let saveFiles=["last.json","stats.json"];// dans le même répertoir et à garder.
for(let i in questionnaires)
saveFiles.push(questionnaires[i].id+".json");
const deleteFiles = await toolFile.deleteFilesInDirectory(configQuestionnaires.dirCacheQuestionnaires, saveFiles);
res.status(200).json(deleteFiles);
next();
}
catch(e)
{
next(e);
}
}
// test si des questionnaires doivent être publiés
// + si des questionnaires publiés n'ont pas fichier html
// si fichier html créé il faut aussi actualiser la page d'accueil & co
exports.checkQuestionnairesNeedToBePublished= async (req, res, next) =>
{
try
{
await checkQuestionnairesNeedToBePublished();
const nb=await checkQuestionnairesPublishedHaveHTML();
if(nb > 0)
creaNewQuestionnairesJson();// provoque mise à jour du HTLM, RSS, etc.
res.status(200).json(txtQuestionnaire.haveBeenPublished.replace(":NB", nb));
next();
}
catch(e)
{
next(e);
}
}
// FONCTIONS UTILITAIRES
const creaQuestionnaireJson = async (id) =>
{
const db = require("../models/index");
const Questionnaire=await db["Questionnaire"].findByPk(id);
if(Questionnaire)
{
let datas={ Questionnaire };
const Tags=await db["QuestionnaireClassification"].findAll({ where: { QuestionnaireId: Questionnaire.id }, attributes: ["TagId"] });
if(Tags)
datas.Tags=Tags;
const Illustrations=await db["Illustration"].findAll({ where: { QuestionnaireId: Questionnaire.id } });
if(Illustrations)
datas.Illustrations=Illustrations;
const Links=await db["Link"].findAll({ where: { QuestionnaireId: Questionnaire.id } });
if(Links)
datas.Links=Links;
const Questions=await db["Question"].findAll({ where: { QuestionnaireId: Questionnaire.id }, order: [["rank", "ASC"], ["createdAt", "ASC"]], attributes: ["id"] });
if(Questions)
datas.Questions=Questions;
const wasPublished=datas.Questionnaire.isPublished;
datas.Questionnaire.isPublished=checkQuestionnaireIsPublishable(datas);
// important d'écrire le fichier ici, car il est nécessaire aux autres fonctions appelées ci-dessous
await toolFile.createJSON(config.dirCacheQuestionnaires, id, datas);
if(datas.Questionnaire.isPublished!==wasPublished)
{
await db["Questionnaire"].update({ isPublished:datas.Questionnaire.isPublished }, { where: { id : id } , fields: ["isPublished"], limit:1 });
// + liste des tags utilisés :
tagCtrl.creaUsedTagsJson();
// si le quiz était publié jusqu'ici, il me faut supprimer son fichier HTML (revenir pour réactiver)
if(wasPublished)
toolFile.deleteFile(config.dirHTMLQuestionnaire, Questionnaire.slug+".html");
}
// peut impacter la liste des derniers si des informations affichées ont changé
creaNewQuestionnairesJson();// peut avoir été impacté
// + les listes de quizs / tags :
for(let i in Tags)
tagCtrl.creaQuestionnairesTagJson(Tags[i].TagId) // ! Json + HTML, donc potentiellement long.
if(datas.Questionnaire.isPublished)
await creaQuestionnaireHTML(id);
return datas;
}
else
return false;
}
exports.creaQuestionnaireJson = creaQuestionnaireJson;
const checkQuestionnaireIsPublishable = (datas, checkDate=true) =>
{
if(checkDate)
{
if(datas.Questionnaire.publishingAt===null)
return false;
else
{
const today=new Date();
today.setHours(0,0,0,0);// !! attention au décalage horaire du fait de l'enregistrement en UTC dans mysql
const publishingAt=new Date(datas.Questionnaire.publishingAt);
if (publishingAt.getTime() > today.getTime())
return false;
}
}
if(datas.Questions==undefined || datas.Questions.length < config.nbQuestionsMin)
return false;// le nombre de réponses mini étant contrôlé au moment de l'enregistrement de la question
if(datas.Tags==undefined || datas.Tags.length < config.nbTagsMin)
return false;
if(datas.Links==undefined || datas.Links.length < config.nbLinksMin)
return false;
if(datas.Illustrations==undefined || datas.Illustrations.length < config.nbIllustrationsMin)
return false;
return true;
}
const creaQuestionnaireHTML = async (id, preview=false) =>
{
// besoin de toutes les infos concernant le questionnaire pour les transmettre à la vue
// à terme : séparer la création de la partie body pouvant être retournée pour recharger page, de la génération complète pour créer le fichier html
const questionnaire=await searchQuestionnaireById(id, true);
if(!questionnaire)
return false;
if(questionnaire.Questionnaire.isPublished===false && preview===false)
return false;
const compiledFunction = pug.compileFile("./views/"+config.theme+"/quiz.pug");
const configTpl = require("../views/"+config.theme+"/config/"+config.availableLangs[0]+".js");
const pageDatas=
{
config: config,
configTpl: configTpl,
tool: tool,
txtGeneral : txtGeneral,
txtQuestionnaire: txtQuestionnaire,
txtIllustration: txtIllustration,
pageLang: questionnaire.Questionnaire.language,
metaDescription: tool.shortenIfLongerThan(config.siteName+" : "+striptags(questionnaire.Questionnaire.introduction.replace("<br>", " ").replace("</p>", " ")), 200),
author: questionnaire.Questionnaire.CreatorName,
pageTitle: questionnaire.Questionnaire.title+" ("+txtQuestionnaire.questionnairesName+")",
contentTitle: questionnaire.Questionnaire.title,
questionnaire: questionnaire,
linkCanonical: config.siteUrl+"/"+config.dirWebQuestionnaire+"/"+questionnaire.Questionnaire.slug+".html"
}
const html=await compiledFunction(pageDatas);
if(preview===false)
{
await toolFile.createHTML(config.dirHTMLQuestionnaire, questionnaire.Questionnaire.slug, html);
return true;
}
else
return html;
}
const searchQuestionnaireById = async (id, reassemble=false) =>
{
let questionnaire=await toolFile.readJSON(config.dirCacheQuestionnaires, id);
if(!questionnaire)
questionnaire=await creaQuestionnaireJson(id);
if(!questionnaire)
return false;
if(reassemble)
{
let question; Questions=[];
const author=await userCtrl.searchUserById(questionnaire.Questionnaire.CreatorId);
if(author)
questionnaire.Questionnaire.CreatorName=author.User.name;
for(i in questionnaire.Questions)
{
question=await questionCtrl.searchQuestionById(questionnaire.Questions[i].id);
if(question)
Questions.push(question);
}
questionnaire.Questions=Questions;
const tags=await tagCtrl.getTagsQuestionnaire(id);
if(tags)
questionnaire.Tags=tags;
}
return questionnaire;
}
exports.searchQuestionnaireById = searchQuestionnaireById;
// Cherche si il y a des questionnaires dont la date de publication est passée mais qui ne sont pas notés comme publiés
// Vérifie si ils sont publiables et si oui change leur statut et réactualise le cache json
const checkQuestionnairesNeedToBePublished = async () =>
{
const db = require("../models/index");
const questionnaires= await db.sequelize.query("SELECT `id` FROM `Questionnaires` WHERE `publishingAt` < NOW() AND `isPublished` = false", { type: QueryTypes.SELECT });
let questionnaireDatas;
for(let i in questionnaires)
{
questionnaireDatas=await searchQuestionnaireById(questionnaires[i].id, true);
if(checkQuestionnaireIsPublishable(questionnaireDatas))
{
await db["Questionnaire"].update({ isPublished:true }, { where: { id : questionnaires[i].id } , fields: ["isPublished"], limit:1 });
creaQuestionnaireJson(questionnaires[i].id);// provoque normalement la création du HTML
}
}
}
// Contrôle si tous les fichiers devant être publiés ont bien leur fichier HTML, sinon le génère
// Si regenerate true, tous les fichiers sont générés, même si ils existent déjà (évolution template...)
// Retourne le nombre de fichiers ayant été régénérés
const checkQuestionnairesPublishedHaveHTML = async (regenerate=false) =>
{
const db = require("../models/index");
const questionnaires= await db.sequelize.query("SELECT `id`,`slug` FROM `Questionnaires` WHERE `isPublished` = true", { type: QueryTypes.SELECT });
let nb=0;
for(let i in questionnaires)
{
if(regenerate)
{
await creaQuestionnaireHTML(questionnaires[i].id);
nb++;
}
else if(await toolFile.checkIfFileExist(config.dirHTMLQuestionnaire, questionnaires[i].slug+".html")===false)
{
await creaQuestionnaireHTML(questionnaires[i].id);
nb++;
}
}
return nb;
}
// Liste des derniers questionnaires publiés (utile pour page d'accueil, flux rss, etc.)
const creaNewQuestionnairesJson = async () =>
{
const db = require("../models/index");
const Questionnaires=await db["Questionnaire"].findAll({ where: { isPublished : true }, order: [[config.fieldNewQuestionnaires, "DESC"], ["id", "DESC"]], attributes: ["id"], limit: config.nbNewQuestionnaires });
if(Questionnaires)
{
await toolFile.createJSON(config.dirCacheQuestionnaires, "last", Questionnaires);
creaNewQuestionnairesHTML(Questionnaires);
return Questionnaires;
}
else
return false;
}
exports.creaNewQuestionnairesJson = creaNewQuestionnairesJson;
// Se limite à compter le nombre total de questionnaires et à le stocker pour éviter de lancer une requête sql à chaque fois
const creaStatsQuestionnairesJson = async () =>
{
const db = require("../models/index");
const Questionnaires=await db["Questionnaire"].findAll({ attributes: ["id"] });
const QuestionnairesPublished=await db["Questionnaire"].findAll({ where: { isPublished : true }, attributes: ["id"] });
if(Questionnaires && QuestionnairesPublished)
{
const stats =
{
nbTot : Questionnaires.length,
nbPublished : QuestionnairesPublished.length
}
await toolFile.createJSON(config.dirCacheQuestionnaires, "stats", stats);
return stats;
}
else
return false;
}
exports.creaStatsQuestionnairesJson = creaStatsQuestionnairesJson;
// Retourne les données créées par la fonction précédente
const getStatsQuestionnaires = async () =>
{
let stats=await toolFile.readJSON(config.dirCacheQuestionnaires, "stats");
if(!stats)
stats=await creaStatsQuestionnairesJson();
if(!stats)
return false;
else
return stats;
}
exports.getStatsQuestionnaires = getStatsQuestionnaires;
// Quelle est la prochaine date pour laquelle aucun questionnaire n'a été publié ?
const getDateNewQuestionnaireNeeded = async (maxDays) =>
{
const db = require("../models/index");
let dateNeed="", checkDate, addMin=0, addMax=1;
while(dateNeed==="")
{
checkDate = await db.sequelize.query("SELECT ADDDATE(CURDATE(), :addMin) as `dateNeeded` FROM `Questionnaires` WHERE `isPublished`=1 AND `publishingAt` > ADDDATE(CURDATE(), :addMin) AND `publishingAt`< ADDDATE(CURDATE(), :addMax) ORDER BY `publishingAt` LIMIT 1", { replacements: { addMin: addMin, addMax: addMax }, type: QueryTypes.SELECT });
if(checkDate && getSubscriptions24H.length>0)
dateNeed=checkDate.dateNeeded;
else
{
addMin++;
addMax++;
}
if(addMin>maxDays)
return false;
}
return dateNeed;
}
exports.getDateNewQuestionnaireNeeded = getDateNewQuestionnaireNeeded;
// Les prochains questionnaires devant être publiés (permet aux gestionnaires de voir les dates vides)
const getNextQuestionnaires = async () =>
{
const db = require("../models/index");
const questionnaires= await db.sequelize.query("SELECT `id`,`title`, `publishingAt` as `datePublishing` FROM `Questionnaires` WHERE `publishingAt` > NOW() order by `publishingAt`", { type: QueryTypes.SELECT });
return questionnaires;
}
exports.getNextQuestionnaires = getNextQuestionnaires;
const creaNewQuestionnairesHTML = async (Questionnaires) =>
{
// On regénère la page d'accueil avec le(s) dernier(s) questionnaire(s) mis en avant :
let compiledFunction = pug.compileFile("./views/"+config.theme+"/home.pug");
const configTpl = require("../views/"+config.theme+"/config/"+config.availableLangs[0]+".js");
let questionnaires=[];
for(let i in Questionnaires)
questionnaires.push(await searchQuestionnaireById(Questionnaires[i].id));
let pageDatas=
{
config: config,
configTpl: configTpl,
tool: tool,
striptags: striptags,
txtGeneral : txtGeneral,
txtQuestionnaire: txtQuestionnaire,
txtIllustration: txtIllustration,
pageLang: config.adminLang,
metaDescription: txtGeneral.siteMetaDescription,
pageTitle: txtGeneral.siteHTMLTitle,
contentTitle: config.siteName,
questionnaires: questionnaires,
linkCanonical: config.siteUrl
}
let html=await compiledFunction(pageDatas);
await toolFile.createHTML(config.dirHTML, "index", html);
// + la page listant les X derniers quizs + liste des tags
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();
html=await compiledFunction(pageDatas);
await toolFile.createHTML(configQuestionnaires.dirHTMLTags, "index", html);
return true;
}
// À partir d'une liste d'id questionnaires fournis, retourne la liste complète ou partielle (pagination) avec les infos de chaque questionnaire
// Retour en html ou json suivant les cas
const getListingsQuestionnairesOuput = async (Questionnaires, begin=0, end=null, output="") =>
{
const datas= { nbTot: Questionnaires.length, questionnaires: [], html: "" };
if(datas.nbTot!==0)
{
if(end===null)
end=datas.nbTot;
for (let i = begin; i <= end; i++)
{
if(Questionnaires[i]===undefined)
break;
else
datas.questionnaires.push(await searchQuestionnaireById(Questionnaires[i].id));
}
// Utiles pour savoir où j'en suis rendu dans le front :
datas.begin=begin;
datas.end=end;
if(output==="html")
{
const compiledFunction = pug.compileFile("./views/"+config.theme+"/includes/listing-questionnaires.pug");
const pageDatas=
{
tool: tool,
striptags: striptags,
txtGeneral: txtGeneral,
txtIllustration: txtIllustration,
questionnaires: datas.questionnaires,
nbQuestionnairesList:configTpl.nbQuestionnairesUserHomePage
}
datas.html=await compiledFunction(pageDatas);
datas.questionnaires=null;// allège un peu le contenu retourné...
}
}
return datas;
}
exports.getListingsQuestionnairesOuput = getListingsQuestionnairesOuput;