- {content}
-
-
-
+ {content || ''}
+ {link ? (
+
+
+
+ ) : (
+
+ )}
diff --git a/client/src/components/sidebar/SidebarContent.tsx b/client/src/components/sidebar/SidebarContent.tsx
index b0c5a3b5..be3cd9d3 100644
--- a/client/src/components/sidebar/SidebarContent.tsx
+++ b/client/src/components/sidebar/SidebarContent.tsx
@@ -41,6 +41,9 @@ export default function SidebarContent(props: SidebarProps) {
+
+ Definitions
+
{definitions.map((definition) => (
{
const { answerID } = req.params;
+ const id = parseInt(answerID, 10);
return (
- getNextQuestionFromDB(answerID)
+ getNextQuestionFromDB(id)
.then((nextQuestion) => {
res.status(StatusCode.OK).send(nextQuestion);
- // console.log('Next question', nextQuestion);
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch((e) => {
+ console.log(e);
next(ApiError.internal('Unable to retrieve next question'));
})
);
@@ -31,14 +32,16 @@ const getQuestionWithID = async (
next: express.NextFunction,
) => {
const { questionID } = req.params;
+ const id = parseInt(questionID, 10);
return (
- getQuestionById(questionID)
+ getQuestionById(id)
.then((nextQuestion) => {
// console.log(nextQuestion);
res.status(StatusCode.OK).send(nextQuestion);
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch((e) => {
+ console.log(e);
next(ApiError.internal('Unable to retrieve next question'));
})
);
diff --git a/server/src/controllers/resource.controller.ts b/server/src/controllers/resource.controller.ts
deleted file mode 100644
index 50f72aba..00000000
--- a/server/src/controllers/resource.controller.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import express from 'express';
-import StatusCode from '../util/statusCode';
-import ApiError from '../util/apiError';
-import getResourceFromDB from '../services/resource.service';
-
-const getResource = async (
- req: express.Request,
- res: express.Response,
- next: express.NextFunction,
-) => {
- const { answerID } = req.params;
- return (
- getResourceFromDB(answerID)
- .then((resource) => {
- res.status(StatusCode.OK).send(resource);
- })
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- .catch((e) => {
- next(ApiError.internal('Unable to retrieve next question'));
- })
- );
-};
-
-export default getResource;
diff --git a/server/src/models/answer.model.ts b/server/src/models/answer.model.ts
index 979d7e37..a4324d25 100644
--- a/server/src/models/answer.model.ts
+++ b/server/src/models/answer.model.ts
@@ -9,25 +9,34 @@
import mongoose from 'mongoose';
const AnswerSchema = new mongoose.Schema({
+ _id: {
+ type: Number,
+ required: true,
+ },
text: {
type: String,
required: true,
},
resultantQuestionId: {
- type: String,
- required: true,
+ type: Number,
+ required: false,
},
resourceContent: {
type: String,
- required: true,
+ required: false,
+ },
+ resourceLink: {
+ type: String,
+ required: false,
},
});
interface IAnswer extends mongoose.Document {
- _id: string;
+ _id: number;
text: string;
resourceContent: string;
- resultantQuestionId: string;
+ resultantQuestionId: number;
+ resourceLink: string;
}
const Answer = mongoose.model('Answer', AnswerSchema);
diff --git a/server/src/models/definition.model.ts b/server/src/models/definition.model.ts
index 90399104..42fc36af 100644
--- a/server/src/models/definition.model.ts
+++ b/server/src/models/definition.model.ts
@@ -15,7 +15,7 @@ const DefinitionSchema = new mongoose.Schema({
required: true,
},
questionIds: {
- type: [String],
+ type: [Number],
required: true,
},
});
@@ -24,7 +24,7 @@ interface IDefinition extends mongoose.Document {
_id: string;
word: string;
definition: string;
- questionIds: string[];
+ questionIds: number[];
}
const Definition = mongoose.model('Definition', DefinitionSchema);
diff --git a/server/src/models/question.model.ts b/server/src/models/question.model.ts
index 93355b14..a905d373 100644
--- a/server/src/models/question.model.ts
+++ b/server/src/models/question.model.ts
@@ -3,13 +3,35 @@
* access the model in TypeScript.
*/
-import { IAnswer } from './answer.model';
+import mongoose from 'mongoose';
+import { Answer, IAnswer } from './answer.model';
+
+const QuestionSchema = new mongoose.Schema({
+ _id: {
+ type: Number,
+ required: true,
+ },
+ text: {
+ type: String,
+ required: true,
+ },
+ resultantAnswers: {
+ type: [Answer.schema],
+ required: true,
+ },
+ isQuestion: {
+ type: Boolean,
+ required: true,
+ },
+});
interface IQuestion {
- _id: string;
+ _id: number;
text: string;
resultantAnswers: [IAnswer];
isQuestion: boolean;
}
-export default IQuestion;
+const Question = mongoose.model('Question', QuestionSchema);
+
+export { IQuestion, Question };
diff --git a/server/src/models/resource.model.ts b/server/src/models/resource.model.ts
deleted file mode 100644
index d4934f1a..00000000
--- a/server/src/models/resource.model.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Defines the resource model for the database and also the interface to
- * access the model in TypeScript.
- */
-
-import mongoose from 'mongoose';
-
-const ResourceSchema = new mongoose.Schema({
- title: {
- type: String,
- required: true,
- },
- content: {
- type: String,
- required: true,
- },
-});
-
-interface IResource extends mongoose.Document {
- _id: string;
- title: string;
- content: string;
-}
-
-const Resource = mongoose.model('Resource', ResourceSchema);
-
-export { IResource, Resource };
diff --git a/server/src/models/temp-question.model.ts b/server/src/models/temp-question.model.ts
deleted file mode 100644
index b21ec6bd..00000000
--- a/server/src/models/temp-question.model.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Defines a temporary "intermediate" question model for the database and also the interface to
- * access the model in TypeScript.
- */
-
-import mongoose from 'mongoose';
-
-const TempQuestionSchema = new mongoose.Schema({
- text: {
- type: String,
- required: true,
- },
- resultantAnswerIds: {
- type: [String],
- required: true,
- },
- isQuestion: {
- type: Boolean,
- required: true,
- },
-});
-
-interface ITempQuestion extends mongoose.Document {
- _id: string;
- text: string;
- resultantAnswerIds: string[];
- isQuestion: boolean;
-}
-
-const TempQuestion = mongoose.model(
- 'Question',
- TempQuestionSchema,
-);
-
-export { ITempQuestion, TempQuestion };
diff --git a/server/src/routes/resource.route.ts b/server/src/routes/resource.route.ts
deleted file mode 100644
index 43f080e3..00000000
--- a/server/src/routes/resource.route.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import express from 'express';
-import getResource from '../controllers/resource.controller';
-import 'dotenv/config';
-
-const router = express.Router();
-
-router.get('/get-resource/:answerID', getResource);
-
-export default router;
diff --git a/server/src/routes/routers.ts b/server/src/routes/routers.ts
index 5a9e218e..43efb474 100644
--- a/server/src/routes/routers.ts
+++ b/server/src/routes/routers.ts
@@ -10,7 +10,6 @@ import { Router } from 'express';
import adminRouter from './admin.route';
import authRouter from './auth.route';
import questionRouter from './question.route';
-import resourceRouter from './resource.route';
import definitionRouter from './definition.route';
const prefixToRouterMap: { prefix: string; router: Router }[] = [
@@ -26,10 +25,6 @@ const prefixToRouterMap: { prefix: string; router: Router }[] = [
prefix: '/api/question',
router: questionRouter,
},
- {
- prefix: '/api/resource',
- router: resourceRouter,
- },
{
prefix: '/api/definition',
router: definitionRouter,
diff --git a/server/src/services/definition.service.ts b/server/src/services/definition.service.ts
index facf9660..c6b4192a 100644
--- a/server/src/services/definition.service.ts
+++ b/server/src/services/definition.service.ts
@@ -2,7 +2,11 @@ import { Definition } from '../models/definition.model';
const getDefinitionsForQuestionFromDB = async (questionID: string) => {
console.log(questionID);
- const definitions = await Definition.find({ questionIds: questionID }).exec();
+ const id = parseInt(questionID, 10);
+ const definitions = await Definition.find({ questionIds: id }).exec();
+ if (!definitions) {
+ return [];
+ }
console.log(definitions);
return definitions;
};
diff --git a/server/src/services/question.service.ts b/server/src/services/question.service.ts
index 3e907c45..509127ed 100644
--- a/server/src/services/question.service.ts
+++ b/server/src/services/question.service.ts
@@ -3,93 +3,40 @@
*/
// import { hash } from 'bcrypt';
import { Answer, IAnswer } from '../models/answer.model';
-import IQuestion from '../models/question.model';
-import { TempQuestion, ITempQuestion } from '../models/temp-question.model';
-
-async function getAnswerObj(ansId: string) {
- const resultantAnswer = await Answer.findById(ansId);
- const answerObj = {
- _id: resultantAnswer?._id,
- text: resultantAnswer?.text,
- resourceContent: resultantAnswer?.resourceContent,
- resultantQuestionId: resultantAnswer?.resultantQuestionId,
- } as IAnswer;
- return answerObj;
-}
-
-const convertTempToQuestion = async (tempQuestion: ITempQuestion) => {
- const answerArray: IAnswer[] = [];
- if (tempQuestion != null) {
- await Promise.all(
- tempQuestion?.resultantAnswerIds.map(async (id) =>
- getAnswerObj(id).then((newAnswer) => answerArray.push(newAnswer)),
- ),
- );
- }
-
- const question = {
- _id: tempQuestion?._id,
- text: tempQuestion?.text,
- resultantAnswers: answerArray,
- isQuestion: tempQuestion?.isQuestion,
- } as IQuestion;
-
- return question;
-};
-
-const convertQuestionToTemp = (question: IQuestion) => {
- const answerIdArray: string[] = [];
- question.resultantAnswers.forEach((answer) => {
- answerIdArray.push(answer._id);
- });
- const tempQuestion = {
- _id: question._id,
- text: question.text,
- resultantAnswerIds: answerIdArray,
- isQuestion: question.isQuestion,
- } as ITempQuestion;
-
- return tempQuestion;
-};
-
-const getNextQuestionFromDB = async (answerID: string) => {
- const answer = await Answer.findById(answerID).exec();
- const tempQuestion = await TempQuestion.findById(
- answer?.resultantQuestionId,
- ).exec();
-
- if (tempQuestion != null) {
- return convertTempToQuestion(tempQuestion!);
- }
- return null;
-};
+import { IQuestion, Question } from '../models/question.model';
+
+// async function getAnswerObj(ansId: string) {
+// const resultantAnswer = await Answer.findById(ansId);
+// const answerObj = {
+// _id: resultantAnswer?._id,
+// text: resultantAnswer?.text,
+// resourceContent: resultantAnswer?.resourceContent,
+// resultantQuestionId: resultantAnswer?.resultantQuestionId,
+// } as IAnswer;
+// return answerObj;
+// }
/**
- * Get's a question from it's ID
+ * Get's a question from its ID
* @param questID the id of the desired question
* @returns the question with the given ID or null
*/
-const getQuestionById = async (questID: string) => {
- const tempQuestion = await TempQuestion.findById(questID).exec();
- if (tempQuestion != null) {
- return convertTempToQuestion(tempQuestion!);
+const getQuestionById = async (questID: number) => {
+ const question = await Question.findById(questID).exec();
+ if (!question) {
+ throw new Error('Question not found');
}
- return null;
+ return question;
};
-// const passwordHashSaltRounds = 10;
-// const removeSensitiveDataQuery = [
-// '-password',
-// '-verificationToken',
-// '-resetPasswordToken',
-// '-resetPasswordTokenExpiryDate',
-// ];
-
-// const removeSensitiveDataQueryKeepPassword = [
-// '-verificationToken',
-// '-resetPasswordToken',
-// '-resetPasswordTokenExpiryDate',
-// ];
+const getNextQuestionFromDB = async (answerID: number) => {
+ const answer = await Answer.findById(answerID).exec();
+ if (!answer) {
+ throw new Error('Answer not found');
+ }
+ const question = await getQuestionById(answer.resultantQuestionId);
+ return question;
+};
/**
* Creates a new question in the database.
@@ -104,81 +51,32 @@ const createQuestion = async (
isQuestion: boolean,
) => {
const newQuestion = {
- _id,
+ _id: parseInt(_id, 10),
text,
resultantAnswers,
isQuestion,
} as IQuestion;
- const newTempQuestion = convertQuestionToTemp(newQuestion);
-
- const user = await newTempQuestion.save();
- return user;
+ const q = await Question.create(newQuestion);
+ if (!q) {
+ throw new Error('Question not created');
+ }
+ return q;
};
-/**
- * Gets a user from the database by their email but doesn't include the
- * password in the returned user.
- * @param email The email of the user to get
- * @returns The {@link User} or null if the user was not found.
- */
-// const getUserByEmail = async (email: string) => {
-// const user = await Question.findOne({ email })
-// .select(removeSensitiveDataQuery)
-// .exec();
-// return user;
-// };
-
-// /**
-// * Gets a user from the database by their email and includes the password in
-// * the returned user.
-// * @param email The email of the user to get
-// * @returns The {@link User} or null if the user was not found.
-// */
-// const getUserByEmailWithPassword = async (email: string) => {
-// const user = await User.findOne({ email })
-// .select(removeSensitiveDataQueryKeepPassword)
-// .exec();
-// return user;
-// };
-
-// /**
-// * Gets a user from the database by their verification token but doesn't include
-// * the password in the returned user.
-// * @param verificationToken The {@link string} representing the verification token
-// * @returns The {@link User} or null if the user was not found.
-// */
-// const getUserByVerificationToken = async (verificationToken: string) => {
-// const user = await User.findOne({ verificationToken })
-// .select(removeSensitiveDataQuery)
-// .exec();
-// return user;
-// };
-
/**
* @returns All the {@link IQuestion}s in the database.
*/
const getAllQuestionsFromDB = async () => {
- const tempQuestionList = await TempQuestion.find({}).exec(); // .select(removeSensitiveDataQuery).exec();
- const questionArray: IQuestion[] = [];
- if (tempQuestionList != null) {
- await Promise.all(
- tempQuestionList?.map(async (tempQuestion) =>
- convertTempToQuestion(tempQuestion).then((newQuestion) =>
- questionArray.push(newQuestion),
- ),
- ),
- );
- return questionArray;
+ const questionList = await Question.find({}).exec();
+ if (!questionList) {
+ throw new Error('Questions not found');
}
- return null;
+ return questionList;
};
-// /**
-// * A function that upgrades a certain user to an admin.
-// * @param id The id of the user to upgrade.
-// * @returns nothing?
-// */
-
+/**
+ * Edits the text of a question in the database. The new text is expected to be in the request body.
+ */
const editQuestion = async (
questionVals: { [key: string]: string },
// NOTE that we are using strings for IDs here rather than the Answer Interface.
@@ -187,10 +85,16 @@ const editQuestion = async (
const qID = Object.keys(questionVals)[0];
const qText = questionVals[qID];
- await TempQuestion.findByIdAndUpdate(qID, [{ $set: { text: qText } }]).exec();
-
+ const newq = await Question.findByIdAndUpdate(qID, [
+ { $set: { text: qText } },
+ ]).exec();
+ if (!newq) {
+ throw new Error('Question not found');
+ }
// do we need to check for isQuestion? if it's false answerVals will just be empty.
- // for (const key in answerVals) {
+ if (!newq.isQuestion) {
+ throw new Error('Invalid question');
+ }
Object.keys(answerVals).forEach(async (key) => {
await Answer.findByIdAndUpdate(key, [
{ $set: { text: answerVals[key] } },
@@ -198,26 +102,10 @@ const editQuestion = async (
});
};
-// /**
-// * A function that deletes a user from the database.
-// * @param id The id of the user to delete.
-// * @returns The deleted {@link User}
-// */
-// const deleteUserById = async (id: string) => {
-// const user = await User.findByIdAndDelete(id).exec();
-// return user;
-// };
-
export {
- // passwordHashSaltRounds,
createQuestion,
- // getUserByEmail,
- // getUserByVerificationToken,
getQuestionById,
- // getUserByEmailWithPassword,
- // getUserByResetPasswordToken,
getAllQuestionsFromDB,
editQuestion,
getNextQuestionFromDB,
- // deleteUserById,
};
diff --git a/server/src/services/resource.service.ts b/server/src/services/resource.service.ts
deleted file mode 100644
index 9dff3f5c..00000000
--- a/server/src/services/resource.service.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * All the functions for interacting with user data in the MongoDB database
- */
-// import { hash } from 'bcrypt';
-// import { Answer, IAnswer } from '../models/answer.model';
-// import { IQuestion, Question } from '../models/question.model';
-// import { TempQuestion } from '../models/temp-question.model';
-import { Resource } from '../models/resource.model';
-
-// async function getAnswerObj(ansId: string) {
-// const resultantAnswer = await Answer.findById(ansId);
-// const answerObj = {
-// _id: resultantAnswer?._id,
-// text: resultantAnswer?.text,
-// resultantQuestionId: resultantAnswer?.resultantQuestionId,
-// } as IAnswer;
-// return answerObj;
-// }
-
-const getResourceFromDB = async (answerID: string) => {
- const resource = await Resource.findById(answerID).exec();
-
- return resource;
-};
-
-export default getResourceFromDB;