From e94af7df645d10710060997c2a771811fdbb8a54 Mon Sep 17 00:00:00 2001 From: jacobmathew105 <136278107+jacobmathew105@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:02:20 +1200 Subject: [PATCH 01/10] fix: merge conflicts --- backend/src/routes/api/navigate/group.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index 71780d9b..9032eccb 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -2,7 +2,7 @@ import Scene from "../../../db/models/scene"; import User from "../../../db/models/user"; import Group from "../../../db/models/group"; import Scenario from "../../../db/models/scenario"; -import Note from "../../../db/models/note"; +import Note from "../../../db/models/note";import Resource from "../../../db/models/resource" import HttpError from "../../../error/HttpError"; import STATUS from "../../../error/status"; @@ -222,9 +222,24 @@ export const groupGetResources = async (req) => { const flags = group.currentFlags || []; let resources = []; - if (flags) { - // TODO: add logic to map certain flags to groups here - resources = []; + + if (flags.length > 0) { + // Find resources that require flags present in the group's current flags + allResources = await Resource.find({},{'requiredFlags':1}); + console.log(flags) + console.log(resources); + // Log the requiredFlags of each resource + allResources.forEach(resource => { + let condition = True + resource.requiredFlags.forEach(flag=>{ + if(!flags.includes(flag)){ + condition = False + } + }) + if (condition){ + resources.push(resource._id) + } + }); } return { status: STATUS.OK, json: resources }; }; From cf75a13dcc7677eae60fc045f4e0d75e2c4bbfe7 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 16:17:50 +1200 Subject: [PATCH 02/10] feat: added mapping from flags to resources feat: added prop drilling on frontend so resources modal displays resources fetched from mapping --- backend/src/routes/api/navigate/group.js | 8 ++-- frontend/src/components/ResourcesModal.jsx | 41 ++++++++----------- .../PlayScenarioPageMulti.jsx | 6 +-- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index 9032eccb..4ace0d54 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -225,19 +225,19 @@ export const groupGetResources = async (req) => { if (flags.length > 0) { // Find resources that require flags present in the group's current flags - allResources = await Resource.find({},{'requiredFlags':1}); + const allResources = await Resource.find({}); console.log(flags) console.log(resources); // Log the requiredFlags of each resource allResources.forEach(resource => { - let condition = True + let condition = true resource.requiredFlags.forEach(flag=>{ if(!flags.includes(flag)){ - condition = False + condition = false } }) if (condition){ - resources.push(resource._id) + resources.push(resource) } }); } diff --git a/frontend/src/components/ResourcesModal.jsx b/frontend/src/components/ResourcesModal.jsx index b6ef9420..f3f2112b 100644 --- a/frontend/src/components/ResourcesModal.jsx +++ b/frontend/src/components/ResourcesModal.jsx @@ -1,10 +1,9 @@ import { useEffect, useState } from "react"; -import resources from "./ResourceObjects"; import styles from "../styling/NotesDisplayCard.module.scss"; import resourceStyles from "../styling/ResourceModal.module.scss"; -function ResourcesModal({ handleClose }) { - const [currentResourceId, setCurrentResourceId] = useState(resources[0]?.id); +function ResourcesModal({ handleClose, resources }) { + const [currentResourceId, setCurrentResourceId] = useState(resources[0]?._id); const handleKeyPress = (e) => { if (e.key === "Escape") handleClose(); @@ -15,28 +14,22 @@ function ResourcesModal({ handleClose }) { return () => document.removeEventListener("keydown", handleKeyPress); }, []); - const currentResource = resources.find(({ id }) => id === currentResourceId); + const currentResource = resources.find(({ _id }) => _id === currentResourceId); const ResourceContent = ({ item }) => { - if (item.type === "text") { - return ( -

- {item.items.map((textItem) => ( -

{textItem}

- ))} -

- ); + if (item.textContent) { + return

{item.textContent}

; } - if (item.type === "image") { + if (item.imageContent) { return ( {item.alt} ); } - return null; + return

No Content Available

; }; return ( @@ -58,23 +51,25 @@ function ResourcesModal({ handleClose }) {

Resources

- {currentResource?.content.map((item) => ( - - )) ||

No Resource Selected

} + {currentResource ? ( + + ) : ( +

No Resource Selected

+ )}
diff --git a/frontend/src/containers/pages/PlayScenarioPage/PlayScenarioPageMulti.jsx b/frontend/src/containers/pages/PlayScenarioPage/PlayScenarioPageMulti.jsx index 3da2c7da..4ef70bfe 100644 --- a/frontend/src/containers/pages/PlayScenarioPage/PlayScenarioPageMulti.jsx +++ b/frontend/src/containers/pages/PlayScenarioPage/PlayScenarioPageMulti.jsx @@ -48,10 +48,8 @@ const getResources = async (user, groupId) => { Authorization: `Bearer ${token}`, }, }; - console.log(config); const res = await axios.request(config); - console.log(res); - return res.data.active; + return res.data; }; /** @@ -99,7 +97,6 @@ export default function PlayScenarioPageMulti({ group }) { ); const newResources = await getResources(user, group._id); setResources(newResources); - console.log(resources); if (!sceneId) history.replace(`/play/${scenarioId}/multiplayer/${newSceneId}`); } catch (e) { @@ -173,6 +170,7 @@ export default function PlayScenarioPageMulti({ group }) { )} {resourcesOpen && ( setResourcesOpen(false)} From 625534f6ce453bba969f3d6af85d571a3620b909 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 16:30:34 +1200 Subject: [PATCH 03/10] chore: ran linter and prettier --- backend/src/routes/api/navigate/group.js | 25 +++++++++++----------- frontend/src/components/ResourcesModal.jsx | 8 +++++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index 4ace0d54..54ff1dc0 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -2,7 +2,8 @@ import Scene from "../../../db/models/scene"; import User from "../../../db/models/user"; import Group from "../../../db/models/group"; import Scenario from "../../../db/models/scenario"; -import Note from "../../../db/models/note";import Resource from "../../../db/models/resource" +import Note from "../../../db/models/note"; +import Resource from "../../../db/models/resource"; import HttpError from "../../../error/HttpError"; import STATUS from "../../../error/status"; @@ -221,23 +222,21 @@ export const groupGetResources = async (req) => { } const flags = group.currentFlags || []; - let resources = []; + const resources = []; if (flags.length > 0) { // Find resources that require flags present in the group's current flags const allResources = await Resource.find({}); - console.log(flags) - console.log(resources); - // Log the requiredFlags of each resource - allResources.forEach(resource => { - let condition = true - resource.requiredFlags.forEach(flag=>{ - if(!flags.includes(flag)){ - condition = false + // Log the requiredFlags of each resource + allResources.forEach((resource) => { + let condition = true; + resource.requiredFlags.forEach((flag) => { + if (!flags.includes(flag)) { + condition = false; } - }) - if (condition){ - resources.push(resource) + }); + if (condition) { + resources.push(resource); } }); } diff --git a/frontend/src/components/ResourcesModal.jsx b/frontend/src/components/ResourcesModal.jsx index f3f2112b..2baba7c3 100644 --- a/frontend/src/components/ResourcesModal.jsx +++ b/frontend/src/components/ResourcesModal.jsx @@ -14,7 +14,9 @@ function ResourcesModal({ handleClose, resources }) { return () => document.removeEventListener("keydown", handleKeyPress); }, []); - const currentResource = resources.find(({ _id }) => _id === currentResourceId); + const currentResource = resources.find( + ({ _id }) => _id === currentResourceId + ); const ResourceContent = ({ item }) => { if (item.textContent) { @@ -56,7 +58,9 @@ function ResourcesModal({ handleClose, resources }) { type="button" onClick={() => setCurrentResourceId(resource._id)} className={ - currentResourceId === resource._id ? resourceStyles.active : "" + currentResourceId === resource._id + ? resourceStyles.active + : "" } > {resource.name} From 99fa2bac2f10a41933637a6af9a6ead6ab548069 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 17:05:51 +1200 Subject: [PATCH 04/10] feat: added all dummy data resources into database refactor: made the resource modal display correctly using data fetched from db --- backend/src/db/models/resource.js | 4 +-- backend/src/routes/api/resources.js | 6 ++-- frontend/src/components/ResourcesModal.jsx | 32 +++++++++++++--------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/backend/src/db/models/resource.js b/backend/src/db/models/resource.js index 07d0891d..9c552ab2 100644 --- a/backend/src/db/models/resource.js +++ b/backend/src/db/models/resource.js @@ -7,9 +7,7 @@ const resourceSchema = new Schema({ type: String, required: true, }, - textContent: { - type: String, - }, + textContent: [String], imageContent: { type: String, }, diff --git a/backend/src/routes/api/resources.js b/backend/src/routes/api/resources.js index 4b48895b..9bf1bf85 100644 --- a/backend/src/routes/api/resources.js +++ b/backend/src/routes/api/resources.js @@ -22,14 +22,14 @@ const HTTP_NOT_FOUND = 404; const HTTP_INTERNAL_SERVER_ERROR = 500; // Apply auth middleware to all routes below this point -router.use(auth); +// router.use(auth); /** * @route POST / * @desc Create a New Resource * @param {Object} req.body - The resource details. - * @param {string} req.body.type - The type of the resource. - * @param {string} req.body.content - The content of the resource. + * @param {string} req.body.type - The type of the resource as text or image + * @param {string} req.body.content - The content of the resource. as either a string or an image? * @param {string} req.body.name - The name of the resource. * @returns {Object} 201 - The newly created resource. */ diff --git a/frontend/src/components/ResourcesModal.jsx b/frontend/src/components/ResourcesModal.jsx index 2baba7c3..85c9e749 100644 --- a/frontend/src/components/ResourcesModal.jsx +++ b/frontend/src/components/ResourcesModal.jsx @@ -19,19 +19,25 @@ function ResourcesModal({ handleClose, resources }) { ); const ResourceContent = ({ item }) => { - if (item.textContent) { - return

{item.textContent}

; - } - if (item.imageContent) { - return ( - {item.name - ); - } - return

No Content Available

; + const hasTextContent = item.textContent?.length > 0 && item.textContent[0] !== ""; + const hasImageContent = item.imageContent && item.imageContent !== ""; + + return ( +
+ {hasTextContent && + item.textContent.map((textItem) => ( +

{textItem}

+ ))} + {hasImageContent && ( + {item.name + )} + {!hasTextContent && !hasImageContent &&

No Content Available

} +
+ ); }; return ( From 24c770bfc1e76784a8627ec039c7ca41c25f90d9 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 17:08:33 +1200 Subject: [PATCH 05/10] refactor: made backend group resource function more efficient --- backend/src/routes/api/navigate/group.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index 54ff1dc0..0166ef16 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -225,20 +225,16 @@ export const groupGetResources = async (req) => { const resources = []; if (flags.length > 0) { - // Find resources that require flags present in the group's current flags + // Fetch all resources from the database const allResources = await Resource.find({}); - // Log the requiredFlags of each resource - allResources.forEach((resource) => { - let condition = true; - resource.requiredFlags.forEach((flag) => { - if (!flags.includes(flag)) { - condition = false; - } - }); - if (condition) { - resources.push(resource); - } - }); + + // Filter resources where all requiredFlags are present in the group's current flags + const matchingResources = allResources.filter((resource) => + resource.requiredFlags.every((flag) => flags.includes(flag)) + ); + + // Push the filtered resources to the resources array + resources.push(...matchingResources); } return { status: STATUS.OK, json: resources }; }; From 44d61d1b9c3f19ac32619a9b9ebefb62c709cede Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 17:20:37 +1200 Subject: [PATCH 06/10] chore: added requiredFlags to API endpoints when adding or changing resources --- backend/src/db/daos/resourcesDao.js | 10 ++++++---- backend/src/routes/api/resources.js | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/backend/src/db/daos/resourcesDao.js b/backend/src/db/daos/resourcesDao.js index d29812e9..cd836bce 100644 --- a/backend/src/db/daos/resourcesDao.js +++ b/backend/src/db/daos/resourcesDao.js @@ -2,7 +2,7 @@ import Resource from "../models/resource"; import Group from "../models/group"; // Create a New Resource -const createResource = async (type, content, name) => { +const createResource = async (type, content, name, requiredFlags) => { let dbResource = null; switch (type) { @@ -11,7 +11,7 @@ const createResource = async (type, content, name) => { name, textContent: content, imageContent: "", - requiredFlags: [], + requiredFlags: requiredFlags, }); await dbResource.save(); break; @@ -20,7 +20,7 @@ const createResource = async (type, content, name) => { name, textContent: "", imageContent: content, - requiredFlags: [], + requiredFlags: requiredFlags, }); await dbResource.save(); break; @@ -76,16 +76,18 @@ const removeFlag = async (groupId, flag) => { return group.currentFlags; }; -const updateResourceById = async (resourceId, name, type, content) => { +const updateResourceById = async (resourceId, name, type, content, requiredFlags) => { const resource = await Resource.findById(resourceId); resource.name = name; switch (type) { case "text": resource.textContent = content; + resource.requiredFlags = requiredFlags; break; case "image": resource.imageContent = content; + resource.requiredFlags = requiredFlags; break; default: throw new Error(`Unsupported resource type: ${type}`); diff --git a/backend/src/routes/api/resources.js b/backend/src/routes/api/resources.js index 9bf1bf85..b86b34d5 100644 --- a/backend/src/routes/api/resources.js +++ b/backend/src/routes/api/resources.js @@ -36,8 +36,8 @@ const HTTP_INTERNAL_SERVER_ERROR = 500; router.post( "/", handle(async (req, res) => { - const { type, content, name } = req.body; - const newResource = await createResource(type, content, name); + const { type, content, name, requiredFlags } = req.body; + const newResource = await createResource(type, content, name, requiredFlags); return res.status(HTTP_CREATED).json(newResource).send(); }) ); @@ -146,7 +146,7 @@ router.delete("/group/:groupId/:flag", async (req, res) => { router.put("/:resourceId", async (req, res) => { const { resourceId } = req.params; - const { name, type, content } = req.body; + const { name, type, content, requiredFlags } = req.body; if (!content || !name || !type) { return res.status(HTTP_BAD_REQUEST).send("Bad Request"); @@ -157,7 +157,8 @@ router.put("/:resourceId", async (req, res) => { resourceId, name, type, - content + content, + requiredFlags ); if (!updatedResource) { From 7d1fc8f2c3058216e971df4b9fa5a295c83f3e46 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 17:32:12 +1200 Subject: [PATCH 07/10] chore: ran prettier and lint --- backend/src/db/daos/resourcesDao.js | 12 +++++++++--- backend/src/routes/api/navigate/group.js | 4 ++-- backend/src/routes/api/resources.js | 11 ++++++++--- frontend/src/components/ResourcesModal.jsx | 7 +++---- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/backend/src/db/daos/resourcesDao.js b/backend/src/db/daos/resourcesDao.js index cd836bce..1a010afb 100644 --- a/backend/src/db/daos/resourcesDao.js +++ b/backend/src/db/daos/resourcesDao.js @@ -11,7 +11,7 @@ const createResource = async (type, content, name, requiredFlags) => { name, textContent: content, imageContent: "", - requiredFlags: requiredFlags, + requiredFlags, }); await dbResource.save(); break; @@ -20,7 +20,7 @@ const createResource = async (type, content, name, requiredFlags) => { name, textContent: "", imageContent: content, - requiredFlags: requiredFlags, + requiredFlags, }); await dbResource.save(); break; @@ -76,7 +76,13 @@ const removeFlag = async (groupId, flag) => { return group.currentFlags; }; -const updateResourceById = async (resourceId, name, type, content, requiredFlags) => { +const updateResourceById = async ( + resourceId, + name, + type, + content, + requiredFlags +) => { const resource = await Resource.findById(resourceId); resource.name = name; diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index 0166ef16..903d4e02 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -227,12 +227,12 @@ export const groupGetResources = async (req) => { if (flags.length > 0) { // Fetch all resources from the database const allResources = await Resource.find({}); - + // Filter resources where all requiredFlags are present in the group's current flags const matchingResources = allResources.filter((resource) => resource.requiredFlags.every((flag) => flags.includes(flag)) ); - + // Push the filtered resources to the resources array resources.push(...matchingResources); } diff --git a/backend/src/routes/api/resources.js b/backend/src/routes/api/resources.js index b86b34d5..58fe45e8 100644 --- a/backend/src/routes/api/resources.js +++ b/backend/src/routes/api/resources.js @@ -22,7 +22,7 @@ const HTTP_NOT_FOUND = 404; const HTTP_INTERNAL_SERVER_ERROR = 500; // Apply auth middleware to all routes below this point -// router.use(auth); +router.use(auth); /** * @route POST / @@ -37,7 +37,12 @@ router.post( "/", handle(async (req, res) => { const { type, content, name, requiredFlags } = req.body; - const newResource = await createResource(type, content, name, requiredFlags); + const newResource = await createResource( + type, + content, + name, + requiredFlags + ); return res.status(HTTP_CREATED).json(newResource).send(); }) ); @@ -146,7 +151,7 @@ router.delete("/group/:groupId/:flag", async (req, res) => { router.put("/:resourceId", async (req, res) => { const { resourceId } = req.params; - const { name, type, content, requiredFlags } = req.body; + const { name, type, content, requiredFlags } = req.body; if (!content || !name || !type) { return res.status(HTTP_BAD_REQUEST).send("Bad Request"); diff --git a/frontend/src/components/ResourcesModal.jsx b/frontend/src/components/ResourcesModal.jsx index 85c9e749..3ad6236a 100644 --- a/frontend/src/components/ResourcesModal.jsx +++ b/frontend/src/components/ResourcesModal.jsx @@ -19,15 +19,14 @@ function ResourcesModal({ handleClose, resources }) { ); const ResourceContent = ({ item }) => { - const hasTextContent = item.textContent?.length > 0 && item.textContent[0] !== ""; + const hasTextContent = + item.textContent?.length > 0 && item.textContent[0] !== ""; const hasImageContent = item.imageContent && item.imageContent !== ""; return (
{hasTextContent && - item.textContent.map((textItem) => ( -

{textItem}

- ))} + item.textContent.map((textItem) =>

{textItem}

)} {hasImageContent && ( Date: Fri, 30 Aug 2024 17:32:32 +1200 Subject: [PATCH 08/10] fix: fix note rest bug --- backend/src/routes/api/navigate/group.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index 71780d9b..914fd986 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -39,6 +39,7 @@ const deleteAllNotes = async (groupData) => { if (res.nModified !== 1) { throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR); } + return true; }; export const getScenarioFirstScene = async (scenarioId) => { @@ -192,9 +193,8 @@ export const groupReset = async (req) => { const group = await getGroupByIdAndUser(req.params.groupId, uid); const { role } = group.users[0]; - if (!(await deleteAllNotes(group))) { + if (!(await deleteAllNotes(group))) throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR); - } if (group.path[0] !== currentScene) throw new HttpError("Scene mismatch has occured", STATUS.CONFLICT); From 060497de16f9e7b876faccf822855a908b44f582 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 17:38:06 +1200 Subject: [PATCH 09/10] chore: commented out no note deleted catch in note deletion API --- backend/src/routes/api/navigate/group.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index c5066bc2..de7215fc 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -37,9 +37,9 @@ const deleteAllNotes = async (groupData) => { { _id: groupId }, { $set: { notes: {} } } ).exec(); - if (res.nModified !== 1) { - throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR); - } + // if (res.nModified !== 1) { + // throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR); + // } return true; }; From 34ea51a5472aa0899afa135dac7068c38c0da4e2 Mon Sep 17 00:00:00 2001 From: codecreator127 Date: Fri, 30 Aug 2024 17:40:02 +1200 Subject: [PATCH 10/10] chore: ran linter --- backend/src/routes/api/navigate/group.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/src/routes/api/navigate/group.js b/backend/src/routes/api/navigate/group.js index de7215fc..f674d061 100644 --- a/backend/src/routes/api/navigate/group.js +++ b/backend/src/routes/api/navigate/group.js @@ -33,10 +33,7 @@ const deleteAllNotes = async (groupData) => { ); const noteId = noteList.map(({ id }) => id); await Note.deleteMany({ _id: { $in: noteId } }); - const res = await Group.updateOne( - { _id: groupId }, - { $set: { notes: {} } } - ).exec(); + await Group.updateOne({ _id: groupId }, { $set: { notes: {} } }).exec(); // if (res.nModified !== 1) { // throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR); // }