mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
Changer la structure de backend pour le fonctionnement des quiz
Fixes #247
This commit is contained in:
parent
2ee787d179
commit
821a485a29
13 changed files with 537 additions and 537 deletions
|
|
@ -53,7 +53,7 @@ const JoinRoom: React.FC = () => {
|
|||
setQuestions(questions);
|
||||
setQuestion(questions[0]);
|
||||
});
|
||||
socket.on('end-quiz', () => {
|
||||
socket.on('end-questionnaire', () => {
|
||||
disconnect();
|
||||
});
|
||||
socket.on('join-failure', (message) => {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class WebSocketService {
|
|||
|
||||
endQuiz(roomName: string) {
|
||||
if (this.socket) {
|
||||
this.socket.emit('end-quiz', { roomName });
|
||||
this.socket.emit('end-questionnaire', { roomName });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ const { Server } = require("socket.io");
|
|||
// instantiate the db
|
||||
const db = require('./config/db.js');
|
||||
// instantiate the models
|
||||
const quiz = require('./models/quiz.js');
|
||||
const quizModel = new quiz(db);
|
||||
const questionnaires = require('./models/questionnaires.js');
|
||||
const questionnaireModel = new questionnaires(db);
|
||||
const folders = require('./models/folders.js');
|
||||
const foldersModel = new folders(db, quizModel);
|
||||
const foldersModel = new folders(db, questionnaireModel);
|
||||
const users = require('./models/users.js');
|
||||
const userModel = new users(db, foldersModel);
|
||||
const images = require('./models/images.js');
|
||||
|
|
@ -24,21 +24,21 @@ const usersController = require('./controllers/users.js');
|
|||
const usersControllerInstance = new usersController(userModel);
|
||||
const foldersController = require('./controllers/folders.js');
|
||||
const foldersControllerInstance = new foldersController(foldersModel);
|
||||
const quizController = require('./controllers/quiz.js');
|
||||
const quizControllerInstance = new quizController(quizModel, foldersModel);
|
||||
const questionnaireController = require('./controllers/questionnaire.js');
|
||||
const questionnaireControllerInstance = new questionnaireController(questionnaireModel, foldersModel);
|
||||
const imagesController = require('./controllers/images.js');
|
||||
const imagesControllerInstance = new imagesController(imageModel);
|
||||
|
||||
// export the controllers
|
||||
module.exports.users = usersControllerInstance;
|
||||
module.exports.folders = foldersControllerInstance;
|
||||
module.exports.quizzes = quizControllerInstance;
|
||||
module.exports.questionnaires = questionnaireControllerInstance;
|
||||
module.exports.images = imagesControllerInstance;
|
||||
|
||||
//import routers (instantiate controllers as side effect)
|
||||
const userRouter = require('./routers/users.js');
|
||||
const folderRouter = require('./routers/folders.js');
|
||||
const quizRouter = require('./routers/quiz.js');
|
||||
const questionnaireRouter = require('./routers/questionnaires.js');
|
||||
const imagesRouter = require('./routers/images.js');
|
||||
|
||||
// Setup environment
|
||||
|
|
@ -82,7 +82,7 @@ app.use(bodyParser.json());
|
|||
// Create routes
|
||||
app.use('/api/user', userRouter);
|
||||
app.use('/api/folder', folderRouter);
|
||||
app.use('/api/quiz', quizRouter);
|
||||
app.use('/api/questionnaire', questionnaireRouter);
|
||||
app.use('/api/image', imagesRouter);
|
||||
|
||||
app.use(errorHandler);
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@ class Emailer {
|
|||
});
|
||||
}
|
||||
|
||||
quizShare(email, link) {
|
||||
questionnaireShare(email, link) {
|
||||
this.transporter.sendMail({
|
||||
from: this.senderEmail,
|
||||
to: email,
|
||||
subject: 'Un quiz vous a été transféré !',
|
||||
text: 'Veuillez suivre ce lien pour ajouter ce quiz à votre compte. '+ link
|
||||
subject: 'Un questionnaire vous a été transféré !',
|
||||
text: 'Veuillez suivre ce lien pour ajouter ce questionnaire à votre compte. '+ link
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,36 +38,36 @@ exports.IMAGE_NOT_FOUND = {
|
|||
code: 404
|
||||
}
|
||||
|
||||
exports.QUIZ_NOT_FOUND = {
|
||||
message: 'Aucun quiz portant cet identifiant n\'a été trouvé.',
|
||||
exports.QUESTIONNAIRE_NOT_FOUND = {
|
||||
message: 'Aucun questionnaire portant cet identifiant n\'a été trouvé.',
|
||||
code: 404
|
||||
}
|
||||
exports.QUIZ_ALREADY_EXISTS = {
|
||||
message: 'Le quiz existe déjà.',
|
||||
exports.QUESTIONNAIRE_ALREADY_EXISTS = {
|
||||
message: 'Le questionnaire existe déjà.',
|
||||
code: 400
|
||||
}
|
||||
exports.UPDATE_QUIZ_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la mise à jour du quiz.',
|
||||
exports.UPDATE_QUESTIONNAIRE_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la mise à jour du questionnaire.',
|
||||
code: 400
|
||||
}
|
||||
exports.DELETE_QUIZ_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la suppression du quiz.',
|
||||
exports.DELETE_QUESTIONNAIRE_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la suppression du questionnaire.',
|
||||
code: 400
|
||||
}
|
||||
exports.GETTING_QUIZ_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la récupération du quiz.',
|
||||
exports.GETTING_QUESTIONNAIRE_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la récupération du questionnaire.',
|
||||
code: 400
|
||||
}
|
||||
exports.MOVING_QUIZ_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors du déplacement du quiz.',
|
||||
exports.MOVING_QUESTIONNAIRE_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors du déplacement du questionnaire.',
|
||||
code: 400
|
||||
}
|
||||
exports.DUPLICATE_QUIZ_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la duplication du quiz.',
|
||||
exports.DUPLICATE_QUESTIONNAIRE_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la duplication du questionnaire.',
|
||||
code: 400
|
||||
}
|
||||
exports.COPY_QUIZ_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la copie du quiz.',
|
||||
exports.COPY_QUESTIONNAIRE_ERROR = {
|
||||
message: 'Une erreur s\'est produite lors de la copie du questionnaire.',
|
||||
code: 400
|
||||
}
|
||||
|
||||
|
|
|
|||
317
server/controllers/questionnaires.js
Normal file
317
server/controllers/questionnaires.js
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
const emailer = require('../config/email.js');
|
||||
|
||||
const AppError = require('../middleware/AppError.js');
|
||||
const { MISSING_REQUIRED_PARAMETER, NOT_IMPLEMENTED, QUESTIONNAIRE_NOT_FOUND, FOLDER_NOT_FOUND, QUESTIONNAIRE_ALREADY_EXISTS, GETTING_QUESTIONNAIRE_ERROR, DELETE_QUESTIONNAIRE_ERROR, UPDATE_QUESTIONNAIRE_ERROR, MOVING_QUESTIONNAIRE_ERROR } = require('../constants/errorCodes.js');
|
||||
|
||||
class QuestionnaireController {
|
||||
|
||||
constructor(questionnaireModel, foldersModel) {
|
||||
this.questionnaires = questionnaireModel;
|
||||
this.folders = foldersModel;
|
||||
}
|
||||
|
||||
create = async (req, res, next) => {
|
||||
try {
|
||||
const { title, content, folderId } = req.body;
|
||||
|
||||
if (!title || !content || !folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this folder mine
|
||||
const owner = await this.folders.getOwner(folderId);
|
||||
|
||||
if (owner != req.user.userId) {
|
||||
throw new AppError(FOLDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.questionnaires.create(title, content, folderId, req.user.userId);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(QUESTIONNAIRE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Questionnaire créé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
get = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId: questionnaireId } = req.params;
|
||||
|
||||
if (!questionnaireId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const content = await this.questionnaires.getContent(questionnaireId);
|
||||
|
||||
if (!content) {
|
||||
throw new AppError(GETTING_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
|
||||
// Is this questionnaire mine
|
||||
if (content.userId != req.user.userId) {
|
||||
throw new AppError(QUESTIONNAIRE_NOT_FOUND);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
data: content
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId: questionnaireId } = req.params;
|
||||
|
||||
if (!questionnaireId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this questionnaire mine
|
||||
const owner = await this.questionnaires.getOwner(questionnaireId);
|
||||
|
||||
if (owner != req.user.userId) {
|
||||
throw new AppError(QUESTIONNAIRE_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.questionnaires.delete(questionnaireId);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(DELETE_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Questionnaire supprimé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
update = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId: questionnaireId, newTitle, newContent } = req.body;
|
||||
|
||||
if (!newTitle || !newContent || !questionnaireId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this questionnaire mine
|
||||
const owner = await this.questionnaires.getOwner(questionnaireId);
|
||||
|
||||
if (owner != req.user.userId) {
|
||||
throw new AppError(QUESTIONNAIRE_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.questionnaires.update(questionnaireId, newTitle, newContent);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(UPDATE_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Questionnaire mis à jours avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
move = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId: questionnaireId, newFolderId } = req.body;
|
||||
|
||||
if (!questionnaireId || !newFolderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this questionnaire mine
|
||||
const questionnaireOwner = await this.questionnaires.getOwner(questionnaireId);
|
||||
|
||||
if (questionnaireOwner != req.user.userId) {
|
||||
throw new AppError(QUESTIONNAIRE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Is this folder mine
|
||||
const folderOwner = await this.folders.getOwner(newFolderId);
|
||||
|
||||
if (folderOwner != req.user.userId) {
|
||||
throw new AppError(FOLDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.questionnaires.move(questionnaireId, newFolderId);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(MOVING_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Utilisateur déplacé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
copy = async (req, _res, _next) => {
|
||||
const { questionnaireId, newTitle, folderId } = req.body;
|
||||
|
||||
if (!questionnaireId || !newTitle || !folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
throw new AppError(NOT_IMPLEMENTED);
|
||||
// const { questionnaireId } = req.params;
|
||||
// const { newUserId } = req.body;
|
||||
|
||||
// try {
|
||||
// //Trouver le questionnaire a dupliquer
|
||||
// const conn = db.getConnection();
|
||||
// const questionnaireToDuplicate = await conn.collection('questionnaire').findOne({ _id: ObjectId.createFromHexString(questionnaireId) });
|
||||
// if (!questionnaireToDuplicate) {
|
||||
// throw new Error("Questionnaire non trouvé");
|
||||
// }
|
||||
// console.log(questionnaireToDuplicate);
|
||||
// //Suppression du id du questionnaire pour ne pas le répliquer
|
||||
// delete questionnaireToDuplicate._id;
|
||||
// //Ajout du duplicata
|
||||
// await conn.collection('questionnaire').insertOne({ ...questionnaireToDuplicate, userId: ObjectId.createFromHexString(newUserId) });
|
||||
// res.json(Response.ok("Dossier dupliqué avec succès pour un autre utilisateur"));
|
||||
|
||||
// } catch (error) {
|
||||
// if (error.message.startsWith("Questionnaire non trouvé")) {
|
||||
// return res.status(404).json(Response.badRequest(error.message));
|
||||
// }
|
||||
// res.status(500).json(Response.serverError(error.message));
|
||||
// }
|
||||
};
|
||||
|
||||
removeQuestionnairesByFolderId = async (req, res, next) => {
|
||||
try {
|
||||
const { folderId } = req.body;
|
||||
|
||||
if (!folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Call the method from the Questionnaire model to delete questionnaires by folder ID
|
||||
await this.questionnaires.deleteQuestionnairesByFolderId(folderId);
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Questionnaires deleted successfully.'
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
duplicate = async (req, res, next) => {
|
||||
const { questionnaireId } = req.body;
|
||||
|
||||
try {
|
||||
const newQuestionnaireId = await this.questionnaires.duplicate(questionnaireId, req.user.userId);
|
||||
res.status(200).json({ success: true, newQuestionnaireId });
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
questionnaireExists = async (title, userId) => {
|
||||
try {
|
||||
const existingFile = await this.questionnaires.questionnaireExists(title, userId);
|
||||
return existingFile !== null;
|
||||
} catch (_error) {
|
||||
throw new AppError(GETTING_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
share = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId, email } = req.body;
|
||||
|
||||
if (!questionnaireId || !email) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const link = `${process.env.FRONTEND_URL}/teacher/Share/${questionnaireId}`;
|
||||
|
||||
emailer.questionnaireShare(email, link);
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Questionnaire partagé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getShare = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId } = req.params;
|
||||
|
||||
if (!questionnaireId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const content = await this.questionnaires.getContent(questionnaireId);
|
||||
|
||||
if (!content) {
|
||||
throw new AppError(GETTING_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
data: content.title
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
receiveShare = async (req, res, next) => {
|
||||
try {
|
||||
const { questionnaireId, folderId } = req.body;
|
||||
|
||||
if (!questionnaireId || !folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const folderOwner = await this.folders.getOwner(folderId);
|
||||
if (folderOwner != req.user.userId) {
|
||||
throw new AppError(FOLDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
const content = await this.questionnaires.getContent(questionnaireId);
|
||||
if (!content) {
|
||||
throw new AppError(GETTING_QUESTIONNAIRE_ERROR);
|
||||
}
|
||||
|
||||
const result = await this.questionnaires.create(content.title, content.content, folderId, req.user.userId);
|
||||
if (!result) {
|
||||
throw new AppError(QUESTIONNAIRE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Questionnaire partagé reçu.'
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
module.exports = QuestionnaireController;
|
||||
|
|
@ -1,317 +0,0 @@
|
|||
const emailer = require('../config/email.js');
|
||||
|
||||
const AppError = require('../middleware/AppError.js');
|
||||
const { MISSING_REQUIRED_PARAMETER, NOT_IMPLEMENTED, QUIZ_NOT_FOUND, FOLDER_NOT_FOUND, QUIZ_ALREADY_EXISTS, GETTING_QUIZ_ERROR, DELETE_QUIZ_ERROR, UPDATE_QUIZ_ERROR, MOVING_QUIZ_ERROR } = require('../constants/errorCodes');
|
||||
|
||||
class QuizController {
|
||||
|
||||
constructor(quizModel, foldersModel) {
|
||||
this.quizzes = quizModel;
|
||||
this.folders = foldersModel;
|
||||
}
|
||||
|
||||
create = async (req, res, next) => {
|
||||
try {
|
||||
const { title, content, folderId } = req.body;
|
||||
|
||||
if (!title || !content || !folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this folder mine
|
||||
const owner = await this.folders.getOwner(folderId);
|
||||
|
||||
if (owner != req.user.userId) {
|
||||
throw new AppError(FOLDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.quizzes.create(title, content, folderId, req.user.userId);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(QUIZ_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Quiz créé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
get = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId } = req.params;
|
||||
|
||||
if (!quizId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const content = await this.quizzes.getContent(quizId);
|
||||
|
||||
if (!content) {
|
||||
throw new AppError(GETTING_QUIZ_ERROR);
|
||||
}
|
||||
|
||||
// Is this quiz mine
|
||||
if (content.userId != req.user.userId) {
|
||||
throw new AppError(QUIZ_NOT_FOUND);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
data: content
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId } = req.params;
|
||||
|
||||
if (!quizId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this quiz mine
|
||||
const owner = await this.quizzes.getOwner(quizId);
|
||||
|
||||
if (owner != req.user.userId) {
|
||||
throw new AppError(QUIZ_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.quizzes.delete(quizId);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(DELETE_QUIZ_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Quiz supprimé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
update = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId, newTitle, newContent } = req.body;
|
||||
|
||||
if (!newTitle || !newContent || !quizId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this quiz mine
|
||||
const owner = await this.quizzes.getOwner(quizId);
|
||||
|
||||
if (owner != req.user.userId) {
|
||||
throw new AppError(QUIZ_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.quizzes.update(quizId, newTitle, newContent);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(UPDATE_QUIZ_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Quiz mis à jours avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
move = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId, newFolderId } = req.body;
|
||||
|
||||
if (!quizId || !newFolderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Is this quiz mine
|
||||
const quizOwner = await this.quizzes.getOwner(quizId);
|
||||
|
||||
if (quizOwner != req.user.userId) {
|
||||
throw new AppError(QUIZ_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Is this folder mine
|
||||
const folderOwner = await this.folders.getOwner(newFolderId);
|
||||
|
||||
if (folderOwner != req.user.userId) {
|
||||
throw new AppError(FOLDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
const result = await this.quizzes.move(quizId, newFolderId);
|
||||
|
||||
if (!result) {
|
||||
throw new AppError(MOVING_QUIZ_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Utilisateur déplacé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
copy = async (req, _res, _next) => {
|
||||
const { quizId, newTitle, folderId } = req.body;
|
||||
|
||||
if (!quizId || !newTitle || !folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
throw new AppError(NOT_IMPLEMENTED);
|
||||
// const { quizId } = req.params;
|
||||
// const { newUserId } = req.body;
|
||||
|
||||
// try {
|
||||
// //Trouver le quiz a dupliquer
|
||||
// const conn = db.getConnection();
|
||||
// const quiztoduplicate = await conn.collection('quiz').findOne({ _id: ObjectId.createFromHexString(quizId) });
|
||||
// if (!quiztoduplicate) {
|
||||
// throw new Error("Quiz non trouvé");
|
||||
// }
|
||||
// console.log(quiztoduplicate);
|
||||
// //Suppression du id du quiz pour ne pas le répliquer
|
||||
// delete quiztoduplicate._id;
|
||||
// //Ajout du duplicata
|
||||
// await conn.collection('quiz').insertOne({ ...quiztoduplicate, userId: ObjectId.createFromHexString(newUserId) });
|
||||
// res.json(Response.ok("Dossier dupliqué avec succès pour un autre utilisateur"));
|
||||
|
||||
// } catch (error) {
|
||||
// if (error.message.startsWith("Quiz non trouvé")) {
|
||||
// return res.status(404).json(Response.badRequest(error.message));
|
||||
// }
|
||||
// res.status(500).json(Response.serverError(error.message));
|
||||
// }
|
||||
};
|
||||
|
||||
deleteQuizzesByFolderId = async (req, res, next) => {
|
||||
try {
|
||||
const { folderId } = req.body;
|
||||
|
||||
if (!folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
// Call the method from the Quiz model to delete quizzes by folder ID
|
||||
await this.quizzes.deleteQuizzesByFolderId(folderId);
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Quizzes deleted successfully.'
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
duplicate = async (req, res, next) => {
|
||||
const { quizId } = req.body;
|
||||
|
||||
try {
|
||||
const newQuizId = await this.quizzes.duplicate(quizId, req.user.userId);
|
||||
res.status(200).json({ success: true, newQuizId });
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
quizExists = async (title, userId) => {
|
||||
try {
|
||||
const existingFile = await this.quizzes.quizExists(title, userId);
|
||||
return existingFile !== null;
|
||||
} catch (_error) {
|
||||
throw new AppError(GETTING_QUIZ_ERROR);
|
||||
}
|
||||
};
|
||||
|
||||
share = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId, email } = req.body;
|
||||
|
||||
if (!quizId || !email) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const link = `${process.env.FRONTEND_URL}/teacher/Share/${quizId}`;
|
||||
|
||||
emailer.quizShare(email, link);
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Quiz partagé avec succès.'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
getShare = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId } = req.params;
|
||||
|
||||
if (!quizId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const content = await this.quizzes.getContent(quizId);
|
||||
|
||||
if (!content) {
|
||||
throw new AppError(GETTING_QUIZ_ERROR);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
data: content.title
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
receiveShare = async (req, res, next) => {
|
||||
try {
|
||||
const { quizId, folderId } = req.body;
|
||||
|
||||
if (!quizId || !folderId) {
|
||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||
}
|
||||
|
||||
const folderOwner = await this.folders.getOwner(folderId);
|
||||
if (folderOwner != req.user.userId) {
|
||||
throw new AppError(FOLDER_NOT_FOUND);
|
||||
}
|
||||
|
||||
const content = await this.quizzes.getContent(quizId);
|
||||
if (!content) {
|
||||
throw new AppError(GETTING_QUIZ_ERROR);
|
||||
}
|
||||
|
||||
const result = await this.quizzes.create(content.title, content.content, folderId, req.user.userId);
|
||||
if (!result) {
|
||||
throw new AppError(QUIZ_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'Quiz partagé reçu.'
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
module.exports = QuizController;
|
||||
|
|
@ -3,9 +3,9 @@ const ObjectId = require('mongodb').ObjectId;
|
|||
const { generateUniqueTitle } = require('./utils');
|
||||
|
||||
class Folders {
|
||||
constructor(db, quizModel) {
|
||||
constructor(db, questionnaireModel) {
|
||||
this.db = db;
|
||||
this.quizModel = quizModel;
|
||||
this.questionnaireModel = questionnaireModel;
|
||||
}
|
||||
|
||||
async create(title, userId) {
|
||||
|
|
@ -58,7 +58,7 @@ class Folders {
|
|||
return folder.userId;
|
||||
}
|
||||
|
||||
// finds all quizzes in a folder
|
||||
// finds all questionnaires in a folder
|
||||
async getContent(folderId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
|
@ -79,7 +79,7 @@ class Folders {
|
|||
const folderResult = await foldersCollection.deleteOne({ _id: ObjectId.createFromHexString(folderId) });
|
||||
|
||||
if (folderResult.deletedCount != 1) return false;
|
||||
await this.quizModel.deleteQuizzesByFolderId(folderId);
|
||||
await this.questionnaireModel.deleteQuestionnairesByFolderId(folderId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -124,14 +124,14 @@ class Folders {
|
|||
throw new Error('Failed to create duplicate folder');
|
||||
}
|
||||
|
||||
// copy the quizzes from source folder to destination folder
|
||||
// copy the questionnaires from source folder to destination folder
|
||||
const content = await this.getContent(folderId);
|
||||
// console.log("folders.duplicate: found content", content);
|
||||
for (const quiz of content) {
|
||||
// console.log("folders.duplicate: creating quiz (copy)", quiz);
|
||||
const result = await this.quizModel.create(quiz.title, quiz.content, newFolderId.toString(), userId);
|
||||
for (const questionnaire of content) {
|
||||
// console.log("folders.duplicate: creating questionnaire (copy)", questionnaire);
|
||||
const result = await this.questionnaireModel.create(questionnaire.title, questionnaire.content, newFolderId.toString(), userId);
|
||||
if (!result) {
|
||||
throw new Error('Failed to create duplicate quiz');
|
||||
throw new Error('Failed to create duplicate questionnaire');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,8 +155,8 @@ class Folders {
|
|||
if (!newFolderId) {
|
||||
throw new Error('Failed to create a new folder.');
|
||||
}
|
||||
for (const quiz of sourceFolder.content) {
|
||||
await this.quizModel.create(quiz.title, quiz.content, newFolderId, userId);
|
||||
for (const questionnaire of sourceFolder.content) {
|
||||
await this.questionnaireModel.create(questionnaire.title, questionnaire.content, newFolderId, userId);
|
||||
}
|
||||
|
||||
return newFolderId;
|
||||
|
|
|
|||
155
server/models/questionnaires.js
Normal file
155
server/models/questionnaires.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
const { ObjectId } = require('mongodb');
|
||||
const { generateUniqueTitle } = require('./utils');
|
||||
|
||||
class Questionnaire {
|
||||
|
||||
constructor(db) {
|
||||
// console.log("Questionnaire constructor: db", db)
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
async create(title, content, folderId, userId) {
|
||||
// console.log(`questionnaires: create title: ${title}, folderId: ${folderId}, userId: ${userId}`);
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const existingQuestionnaire = await questionnaireCollection.findOne({ title: title, folderId: folderId, userId: userId })
|
||||
|
||||
if (existingQuestionnaire) {
|
||||
throw new Error(`Questionnaire already exists with title: ${title}, folderId: ${folderId}, userId: ${userId}`);
|
||||
}
|
||||
|
||||
const newQuestionnaire = {
|
||||
folderId: folderId,
|
||||
userId: userId,
|
||||
title: title,
|
||||
content: content,
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
}
|
||||
|
||||
const result = await questionnaireCollection.insertOne(newQuestionnaire);
|
||||
// console.log("questionnaires: create insertOne result", result);
|
||||
|
||||
return result.insertedId;
|
||||
}
|
||||
|
||||
async getOwner(questionnaireId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const questionnaire = await questionnaireCollection.findOne({ _id: ObjectId.createFromHexString(questionnaireId) });
|
||||
|
||||
return questionnaire.userId;
|
||||
}
|
||||
|
||||
async getContent(questionnaireId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const questionnaire = await questionnaireCollection.findOne({ _id: ObjectId.createFromHexString(questionnaireId) });
|
||||
|
||||
return questionnaire;
|
||||
}
|
||||
|
||||
async delete(questionnaireId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const result = await questionnaireCollection.deleteOne({ _id: ObjectId.createFromHexString(questionnaireId) });
|
||||
|
||||
if (result.deletedCount != 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
async deleteQuestionnairesByFolderId(folderId) {
|
||||
await this.db.connect();
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnairesCollection = conn.collection('files');
|
||||
|
||||
// Delete all questionnaires with the specified folderId
|
||||
const result = await questionnairesCollection.deleteMany({ folderId: folderId });
|
||||
return result.deletedCount > 0;
|
||||
}
|
||||
|
||||
async update(questionnaireId, newTitle, newContent) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const result = await questionnaireCollection.updateOne(
|
||||
{ _id: ObjectId.createFromHexString(questionnaireId) },
|
||||
{
|
||||
$set: {
|
||||
title: newTitle,
|
||||
content: newContent,
|
||||
updated_at: new Date()
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return result.modifiedCount === 1;
|
||||
}
|
||||
|
||||
async move(questionnaireId, newFolderId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const result = await questionnaireCollection.updateOne(
|
||||
{ _id: ObjectId.createFromHexString(questionnaireId) },
|
||||
{ $set: { folderId: newFolderId } }
|
||||
);
|
||||
|
||||
if (result.modifiedCount != 1) return false;
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async duplicate(questionnaireId, userId) {
|
||||
const conn = this.db.getConnection();
|
||||
const questionnaireCollection = conn.collection('files');
|
||||
|
||||
const sourceQuestionnaire = await questionnaireCollection.findOne({ _id: ObjectId.createFromHexString(questionnaireId), userId: userId });
|
||||
if (!sourceQuestionnaire) {
|
||||
throw new Error('Questionnaire not found for questionnaireId: ' + questionnaireId);
|
||||
}
|
||||
|
||||
// Use the utility function to generate a unique title
|
||||
const newQuestionnaireTitle = await generateUniqueTitle(sourceQuestionnaire.title, async (title) => {
|
||||
return await questionnaireCollection.findOne({ title: title, folderId: sourceQuestionnaire.folderId, userId: userId });
|
||||
});
|
||||
|
||||
const newQuestionnaireId = await this.create(newQuestionnaireTitle, sourceQuestionnaire.content, sourceQuestionnaire.folderId, userId);
|
||||
|
||||
if (!newQuestionnaireId) {
|
||||
throw new Error('Failed to create duplicate questionnaire');
|
||||
}
|
||||
|
||||
return newQuestionnaireId;
|
||||
}
|
||||
|
||||
async questionnaireExists(title, userId) {
|
||||
await this.db.connect();
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const filesCollection = conn.collection('files');
|
||||
const existingFolder = await filesCollection.findOne({ title: title, userId: userId });
|
||||
|
||||
return existingFolder !== null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Questionnaire;
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
const { ObjectId } = require('mongodb');
|
||||
const { generateUniqueTitle } = require('./utils');
|
||||
|
||||
class Quiz {
|
||||
|
||||
constructor(db) {
|
||||
// console.log("Quiz constructor: db", db)
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
async create(title, content, folderId, userId) {
|
||||
// console.log(`quizzes: create title: ${title}, folderId: ${folderId}, userId: ${userId}`);
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const existingQuiz = await quizCollection.findOne({ title: title, folderId: folderId, userId: userId })
|
||||
|
||||
if (existingQuiz) {
|
||||
throw new Error(`Quiz already exists with title: ${title}, folderId: ${folderId}, userId: ${userId}`);
|
||||
}
|
||||
|
||||
const newQuiz = {
|
||||
folderId: folderId,
|
||||
userId: userId,
|
||||
title: title,
|
||||
content: content,
|
||||
created_at: new Date(),
|
||||
updated_at: new Date()
|
||||
}
|
||||
|
||||
const result = await quizCollection.insertOne(newQuiz);
|
||||
// console.log("quizzes: create insertOne result", result);
|
||||
|
||||
return result.insertedId;
|
||||
}
|
||||
|
||||
async getOwner(quizId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const quiz = await quizCollection.findOne({ _id: ObjectId.createFromHexString(quizId) });
|
||||
|
||||
return quiz.userId;
|
||||
}
|
||||
|
||||
async getContent(quizId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const quiz = await quizCollection.findOne({ _id: ObjectId.createFromHexString(quizId) });
|
||||
|
||||
return quiz;
|
||||
}
|
||||
|
||||
async delete(quizId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const result = await quizCollection.deleteOne({ _id: ObjectId.createFromHexString(quizId) });
|
||||
|
||||
if (result.deletedCount != 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
async deleteQuizzesByFolderId(folderId) {
|
||||
await this.db.connect();
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizzesCollection = conn.collection('files');
|
||||
|
||||
// Delete all quizzes with the specified folderId
|
||||
const result = await quizzesCollection.deleteMany({ folderId: folderId });
|
||||
return result.deletedCount > 0;
|
||||
}
|
||||
|
||||
async update(quizId, newTitle, newContent) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const result = await quizCollection.updateOne(
|
||||
{ _id: ObjectId.createFromHexString(quizId) },
|
||||
{
|
||||
$set: {
|
||||
title: newTitle,
|
||||
content: newContent,
|
||||
updated_at: new Date()
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return result.modifiedCount === 1;
|
||||
}
|
||||
|
||||
async move(quizId, newFolderId) {
|
||||
await this.db.connect()
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const result = await quizCollection.updateOne(
|
||||
{ _id: ObjectId.createFromHexString(quizId) },
|
||||
{ $set: { folderId: newFolderId } }
|
||||
);
|
||||
|
||||
if (result.modifiedCount != 1) return false;
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async duplicate(quizId, userId) {
|
||||
const conn = this.db.getConnection();
|
||||
const quizCollection = conn.collection('files');
|
||||
|
||||
const sourceQuiz = await quizCollection.findOne({ _id: ObjectId.createFromHexString(quizId), userId: userId });
|
||||
if (!sourceQuiz) {
|
||||
throw new Error('Quiz not found for quizId: ' + quizId);
|
||||
}
|
||||
|
||||
// Use the utility function to generate a unique title
|
||||
const newQuizTitle = await generateUniqueTitle(sourceQuiz.title, async (title) => {
|
||||
return await quizCollection.findOne({ title: title, folderId: sourceQuiz.folderId, userId: userId });
|
||||
});
|
||||
|
||||
const newQuizId = await this.create(newQuizTitle, sourceQuiz.content, sourceQuiz.folderId, userId);
|
||||
|
||||
if (!newQuizId) {
|
||||
throw new Error('Failed to create duplicate quiz');
|
||||
}
|
||||
|
||||
return newQuizId;
|
||||
}
|
||||
|
||||
async quizExists(title, userId) {
|
||||
await this.db.connect();
|
||||
const conn = this.db.getConnection();
|
||||
|
||||
const filesCollection = conn.collection('files');
|
||||
const existingFolder = await filesCollection.findOne({ title: title, userId: userId });
|
||||
|
||||
return existingFolder !== null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Quiz;
|
||||
23
server/routers/questionnaires.js
Normal file
23
server/routers/questionnaires.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const questionnaires = require('../app.js').questionnaires;
|
||||
const jwt = require('../middleware/jwtToken.js');
|
||||
const asyncHandler = require('./routerUtils.js');
|
||||
|
||||
if (!questionnaires) {
|
||||
console.error("questionnaires is not defined");
|
||||
}
|
||||
|
||||
router.post("/create", jwt.authenticate, asyncHandler(questionnaires.create));
|
||||
router.get("/get/:questionnaireId", jwt.authenticate, asyncHandler(asyncHandler(questionnaires.get)));
|
||||
router.delete("/delete/:questionnaireId", jwt.authenticate, asyncHandler(questionnaires.delete));
|
||||
router.put("/update", jwt.authenticate, asyncHandler(questionnaires.update));
|
||||
router.put("/move", jwt.authenticate, asyncHandler(questionnaires.move));
|
||||
|
||||
router.post("/duplicate", jwt.authenticate, asyncHandler(questionnaires.duplicate));
|
||||
router.post("/copy/:questionnaireId", jwt.authenticate, asyncHandler(questionnaires.copy));
|
||||
router.put("/Share", jwt.authenticate, asyncHandler(questionnaires.share));
|
||||
router.get("/getShare/:questionnaireId", jwt.authenticate, asyncHandler(questionnaires.getShare));
|
||||
router.post("/receiveShare", jwt.authenticate, asyncHandler(questionnaires.receiveShare));
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const quizzes = require('../app.js').quizzes;
|
||||
const jwt = require('../middleware/jwtToken.js');
|
||||
const asyncHandler = require('./routerUtils.js');
|
||||
|
||||
if (!quizzes) {
|
||||
console.error("quizzes is not defined");
|
||||
}
|
||||
|
||||
router.post("/create", jwt.authenticate, asyncHandler(quizzes.create));
|
||||
router.get("/get/:quizId", jwt.authenticate, asyncHandler(asyncHandler(quizzes.get)));
|
||||
router.delete("/delete/:quizId", jwt.authenticate, asyncHandler(quizzes.delete));
|
||||
router.put("/update", jwt.authenticate, asyncHandler(quizzes.update));
|
||||
router.put("/move", jwt.authenticate, asyncHandler(quizzes.move));
|
||||
|
||||
router.post("/duplicate", jwt.authenticate, asyncHandler(quizzes.duplicate));
|
||||
router.post("/copy/:quizId", jwt.authenticate, asyncHandler(quizzes.copy));
|
||||
router.put("/Share", jwt.authenticate, asyncHandler(quizzes.share));
|
||||
router.get("/getShare/:quizId", jwt.authenticate, asyncHandler(quizzes.getShare));
|
||||
router.post("/receiveShare", jwt.authenticate, asyncHandler(quizzes.receiveShare));
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -76,8 +76,8 @@ const setupWebsocket = (io) => {
|
|||
socket.to(roomName).emit("launch-student-mode", questions);
|
||||
});
|
||||
|
||||
socket.on("end-quiz", ({ roomName }) => {
|
||||
socket.to(roomName).emit("end-quiz");
|
||||
socket.on("end-questionnaire", ({ roomName }) => {
|
||||
socket.to(roomName).emit("end-questionnaire");
|
||||
});
|
||||
|
||||
socket.on("message", (data) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue