Skip to content

Commit

Permalink
Merge pull request #226 from UoaWDCC/VPS-47/mapping-flags-to-resources
Browse files Browse the repository at this point in the history
VPS-47/mapping flags to resources
  • Loading branch information
codecreator127 authored Aug 30, 2024
2 parents e075b3c + 34ea51a commit 1778727
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 60 deletions.
16 changes: 12 additions & 4 deletions backend/src/db/daos/resourcesDao.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -11,7 +11,7 @@ const createResource = async (type, content, name) => {
name,
textContent: content,
imageContent: "",
requiredFlags: [],
requiredFlags,
});
await dbResource.save();
break;
Expand All @@ -20,7 +20,7 @@ const createResource = async (type, content, name) => {
name,
textContent: "",
imageContent: content,
requiredFlags: [],
requiredFlags,
});
await dbResource.save();
break;
Expand Down Expand Up @@ -76,16 +76,24 @@ 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}`);
Expand Down
4 changes: 1 addition & 3 deletions backend/src/db/models/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ const resourceSchema = new Schema({
type: String,
required: true,
},
textContent: {
type: String,
},
textContent: [String],
imageContent: {
type: String,
},
Expand Down
33 changes: 20 additions & 13 deletions backend/src/routes/api/navigate/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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 HttpError from "../../../error/HttpError";
import STATUS from "../../../error/status";

Expand Down Expand Up @@ -32,13 +33,11 @@ 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();
if (res.nModified !== 1) {
throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR);
}
await Group.updateOne({ _id: groupId }, { $set: { notes: {} } }).exec();
// if (res.nModified !== 1) {
// throw new HttpError("Failed to delete notes", STATUS.INTERNAL_SERVER_ERROR);
// }
return true;
};

export const getScenarioFirstScene = async (scenarioId) => {
Expand Down Expand Up @@ -192,9 +191,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);
Expand All @@ -221,10 +219,19 @@ export const groupGetResources = async (req) => {
}

const flags = group.currentFlags || [];
let resources = [];
if (flags) {
// TODO: add logic to map certain flags to groups here
resources = [];
const resources = [];

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);
}
return { status: STATUS.OK, json: resources };
};
18 changes: 12 additions & 6 deletions backend/src/routes/api/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,21 @@ 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.
*/
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();
})
);
Expand Down Expand Up @@ -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 } = req.body;
const { name, type, content, requiredFlags } = req.body;

if (!content || !name || !type) {
return res.status(HTTP_BAD_REQUEST).send("Bad Request");
Expand All @@ -157,7 +162,8 @@ router.put("/:resourceId", async (req, res) => {
resourceId,
name,
type,
content
content,
requiredFlags
);

if (!updatedResource) {
Expand Down
64 changes: 34 additions & 30 deletions frontend/src/components/ResourcesModal.jsx
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -15,28 +14,29 @@ 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 (
<p>
{item.items.map((textItem) => (
<p>{textItem}</p>
))}
</p>
);
}
if (item.type === "image") {
return (
<img
className={resourceStyles.resourceImage}
src={item.src}
alt={item.alt}
/>
);
}
return null;
const hasTextContent =
item.textContent?.length > 0 && item.textContent[0] !== "";
const hasImageContent = item.imageContent && item.imageContent !== "";

return (
<div>
{hasTextContent &&
item.textContent.map((textItem) => <p key={textItem}>{textItem}</p>)}
{hasImageContent && (
<img
className={resourceStyles.resourceImage}
src={item.imageContent}
alt={item.name || "Resource Image"}
/>
)}
{!hasTextContent && !hasImageContent && <p>No Content Available</p>}
</div>
);
};

return (
Expand All @@ -58,23 +58,27 @@ function ResourcesModal({ handleClose }) {
<h2 className={resourceStyles.modalHeading}>Resources</h2>
<nav className={resourceStyles.navBar}>
{resources.map((resource) => (
<p key={resource.id}>
<p key={resource._id}>
<button
type="button"
onClick={() => setCurrentResourceId(resource.id)}
onClick={() => setCurrentResourceId(resource._id)}
className={
currentResourceId === resource.id ? resourceStyles.active : ""
currentResourceId === resource._id
? resourceStyles.active
: ""
}
>
{resource.displayName}
{resource.name}
</button>
</p>
))}
</nav>
<div className={resourceStyles.r_content_card}>
{currentResource?.content.map((item) => (
<ResourceContent item={item} />
)) || <p>No Resource Selected</p>}
{currentResource ? (
<ResourceContent item={currentResource} />
) : (
<p>No Resource Selected</p>
)}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/**
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -173,6 +170,7 @@ export default function PlayScenarioPageMulti({ group }) {
)}
{resourcesOpen && (
<ResourcesModal
resources={resources}
group={group}
user={user}
handleClose={() => setResourcesOpen(false)}
Expand Down

0 comments on commit 1778727

Please sign in to comment.