From 23913f40bf956c1253b8c62428e56ed67feeeb5b Mon Sep 17 00:00:00 2001 From: Mallepally Lokeshwar Reddy Date: Mon, 12 Aug 2024 22:28:36 +0530 Subject: [PATCH 1/8] chore: Refactor variable names for consistency --- src/components/Topbar/Activity/ActivityList.jsx | 4 ++-- src/components/Topbar/Activity/index.jsx | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/Topbar/Activity/ActivityList.jsx b/src/components/Topbar/Activity/ActivityList.jsx index 742aefca..562126ad 100644 --- a/src/components/Topbar/Activity/ActivityList.jsx +++ b/src/components/Topbar/Activity/ActivityList.jsx @@ -28,7 +28,7 @@ const useStyles = makeStyles(theme => ({ } })); -function ActivityList({ value, toggle, acitvitylist, classname }) { +function ActivityList({ value, toggle, activityList, classname }) { const classes = useStyles(); return ( @@ -36,7 +36,7 @@ function ActivityList({ value, toggle, acitvitylist, classname }) { - {acitvitylist.map((item, index) => ( + {activityList.map((item, index) => ( + +
+ {tags.map((tag, index) => ( + handleDeleteTag(tag)} + className={classes.chip} + deleteIcon={} + /> + ))} +
+ diff --git a/src/store/actions/tutorialPageActions.js b/src/store/actions/tutorialPageActions.js index 221a2cc7..de918c76 100644 --- a/src/store/actions/tutorialPageActions.js +++ b/src/store/actions/tutorialPageActions.js @@ -101,6 +101,7 @@ export const getTutorialFeedData = created_by: tutorial?.created_by, createdAt: tutorial?.createdAt, featured_image: tutorial?.featured_image, + tut_tags: tutorial?.tut_tags, upVotes: tutorial?.upVotes || 0, downVotes: tutorial?.downVotes || 0, }; diff --git a/src/store/actions/tutorialsActions.js b/src/store/actions/tutorialsActions.js index 7d273c1d..1f0ef1cb 100644 --- a/src/store/actions/tutorialsActions.js +++ b/src/store/actions/tutorialsActions.js @@ -122,7 +122,7 @@ export const createTutorial = tutorialData => async (firebase, firestore, dispatch, history) => { try { dispatch({ type: actions.CREATE_TUTORIAL_START }); - const { title, summary, owner, created_by, is_org } = tutorialData; + const { title, summary, owner, created_by, is_org, tags } = tutorialData; const setData = async () => { const document = firestore.collection("tutorials").doc(); @@ -140,6 +140,7 @@ export const createTutorial = tutorial_id: documentID, featured_image: "", icon: "", + tut_tags: tags, url: "", background_color: "#ffffff", text_color: "#000000", From feaeb84b8b3a2d1d02ae079836a63794c084b109 Mon Sep 17 00:00:00 2001 From: Mallepally Lokeshwar Reddy Date: Tue, 13 Aug 2024 00:34:12 +0530 Subject: [PATCH 4/8] feat: Improve feed recommendations by integrating tag-based matching --- .../TutorialPage/components/PostDetails.jsx | 2 +- .../TutorialPage/components/Thumbnails.jsx | 20 ++++++--- .../TutorialPage/components/sideBar.jsx | 43 +++++++++++++++---- src/components/TutorialPage/index.jsx | 5 ++- src/store/actions/index.js | 3 ++ src/store/actions/tutorialPageActions.js | 34 +++++++++++++++ 6 files changed, 89 insertions(+), 18 deletions(-) diff --git a/src/components/TutorialPage/components/PostDetails.jsx b/src/components/TutorialPage/components/PostDetails.jsx index 1c46ac63..80644ac2 100644 --- a/src/components/TutorialPage/components/PostDetails.jsx +++ b/src/components/TutorialPage/components/PostDetails.jsx @@ -87,7 +87,7 @@ const PostDetails = ({ details }) => { {details?.title} - {details?.tag?.map(tag => ( + {details?.tags?.map(tag => ( ({ const Thumbnails = ({ tutorial }) => { const classes = useStyles(); + return ( <> - A + {tutorial?.created_by?.charAt(0) || "U"} - Abhishek From{" "} - Codelabz + + {tutorial?.created_by || "Unknown"} + {" "} + From{" "} + + {tutorial?.owner || "Unknown"} + - How to build a microservice design and architecture using - proper tools + {tutorial?.summary || "No summary available"} - + {/* - + */} diff --git a/src/components/TutorialPage/components/sideBar.jsx b/src/components/TutorialPage/components/sideBar.jsx index 8a56b8fc..be9297fd 100644 --- a/src/components/TutorialPage/components/sideBar.jsx +++ b/src/components/TutorialPage/components/sideBar.jsx @@ -1,6 +1,9 @@ +import React, { useState, useEffect } from "react"; import { Box, Grid, Typography, Button } from "@mui/material"; import Thumbnails from "./Thumbnails"; import { makeStyles } from "@mui/styles"; +import { getRecommendedTutorials } from "../../../store/actions"; +import { useFirebase, useFirestore } from "react-redux-firebase"; const useStyles = makeStyles(() => ({ container: { @@ -19,14 +22,37 @@ const useStyles = makeStyles(() => ({ "linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, #FFF 100%)" } })); -const SideBar = () => { +const SideBar = ({ currentTutorial }) => { const classes = useStyles(); + const [tutorials, setTutorials] = useState([]); + const firebase = useFirebase(); + const firestore = useFirestore(); + + useEffect(() => { + const fetchRecommendedTutorials = async () => { + try { + const recommendedTutorials = await getRecommendedTutorials( + currentTutorial?.tags + )(firebase, firestore); + setTutorials( + recommendedTutorials.filter( + tutorial => tutorial.tutorial_id !== currentTutorial?.id + ) + ); + } catch (error) { + console.error("Error fetching recommended tutorials:", error); + } + }; + + fetchRecommendedTutorials(); + }, [currentTutorial?.tags]); + return ( <> -
+ {/*
-
+
*/} { > More From Codelabz - - - + {tutorials.length > 0 && + tutorials.map((tutorial, index) => ( + + ))}
-
+ {/*
@@ -61,7 +88,7 @@ const SideBar = () => { - + */} ); diff --git a/src/components/TutorialPage/index.jsx b/src/components/TutorialPage/index.jsx index dd7895c2..4a0e4a98 100644 --- a/src/components/TutorialPage/index.jsx +++ b/src/components/TutorialPage/index.jsx @@ -51,13 +51,14 @@ function TutorialPage({ background = "white", textColor = "black" }) { ); const postDetails = { + id: tutorial?.tutorial_id, title: tutorial?.title, org: tutorial?.owner, user: tutorial?.created_by, upVote: tutorial?.upVotes, downVote: tutorial?.downVotes, published_on: tutorial?.createdAt, - tag: tutorial?.tut_tags + tags: tutorial?.tut_tags }; const steps = useSelector( @@ -121,7 +122,7 @@ function TutorialPage({ background = "white", textColor = "black" }) { xs={3} data-testId="tutorialpageSideBar" > - + diff --git a/src/store/actions/index.js b/src/store/actions/index.js index 76520c41..acede358 100644 --- a/src/store/actions/index.js +++ b/src/store/actions/index.js @@ -66,3 +66,6 @@ export { updateStepTitle, uploadTutorialImages } from "./tutorialsActions"; +export { + getRecommendedTutorials, +} from "./tutorialPageActions"; \ No newline at end of file diff --git a/src/store/actions/tutorialPageActions.js b/src/store/actions/tutorialPageActions.js index de918c76..0b900e73 100644 --- a/src/store/actions/tutorialPageActions.js +++ b/src/store/actions/tutorialPageActions.js @@ -221,3 +221,37 @@ export const addComment = comment => async (firebase, firestore, dispatch) => { dispatch({ type: actions.ADD_COMMENT_FAILED, payload: e.message }); } }; + +export const getRecommendedTutorials = currentTutorialTags => async (firebase, firestore) => { + try { + const tutorialsRef = firestore.collection("tutorials"); + + // Fetch tutorials with matching tags + const querySnapshot = await tutorialsRef + .where("tut_tags", "array-contains-any", currentTutorialTags) + .get(); + + // Calculate relevance score based on matching tags + const recommendedTutorials = querySnapshot.docs + .map(doc => { + const tutorial = doc.data(); + + // Skip unpublished tutorials + if (!tutorial.isPublished) return null; + + const matchingTags = tutorial.tut_tags.filter(tag => currentTutorialTags.includes(tag)); + return { + ...tutorial, + relevanceScore: matchingTags.length + }; + }) + .filter(tutorial => tutorial !== null); // Remove null values from the array + + recommendedTutorials.sort((a, b) => b.relevanceScore - a.relevanceScore); + + return recommendedTutorials; + } catch (error) { + console.error("Error fetching recommended tutorials:", error); + return []; + } +}; \ No newline at end of file From 5998cb1b9938cc67de81123845aefe37219adbfe Mon Sep 17 00:00:00 2001 From: Mallepally Lokeshwar Reddy Date: Tue, 13 Aug 2024 00:50:44 +0530 Subject: [PATCH 5/8] chore: Reset form fields and tags when closing tutorial modal --- .../Tutorials/NewTutorial/index.jsx | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/components/Tutorials/NewTutorial/index.jsx b/src/components/Tutorials/NewTutorial/index.jsx index d6e548a8..3e5754ee 100644 --- a/src/components/Tutorials/NewTutorial/index.jsx +++ b/src/components/Tutorials/NewTutorial/index.jsx @@ -138,6 +138,14 @@ const NewTutorial = ({ viewModal, onSidebarClick, viewCallback, active }) => { : null; useEffect(() => { + setTags([]); + setNewTag(""); + setformValue({ + title: "", + summary: "", + owner: "", + tags: [] + }); setVisible(viewModal); }, [viewModal]); @@ -180,6 +188,13 @@ const NewTutorial = ({ viewModal, onSidebarClick, viewCallback, active }) => { setTags(tags.filter(tag => tag !== tagToDelete)); }; + const handleKeyDown = e => { + if (e.key === "Enter") { + e.preventDefault(); + handleAddTag(); + } + }; + const classes = useStyles(); return ( { size="small" value={newTag} onChange={e => setNewTag(e.target.value)} + onKeyDown={handleKeyDown} />