group-project-wednesday-3pm-1 created by GitHub Classroom Calum, Ryan, Mifta, Ahmed
Our project ReedMi is a user-focused discussion platform similar to Reddit that aims to create a network for 'geeky' users to talk and gain knowledge about tech-related topics. ReedMi will help create this network by offering a forum for tech enthusiasts to propose topics and publish content. All users can access these various postings and participate by leaving comments likes or dislikes. Users can search for topics using the side panel filter, which will lead them to thier favorite posts. Users can create new posts using the Navigation bar to add to the forum. Users can fetch news from a third party API through 'Tech News'. ReedMi uses MongoDB, as the datastore, more about this is found later in this document.
If the project were to advance, the next phase of development would focus on augmenting the interactivity and user control within the ReedMi platform. This would include implementing functionality for users to express their opinions more dynamically by introducing the ability to like or dislike comments made by other users. This feature would add a layer of engagement and allow for a more nuanced reflection of user sentiment within discussions. Moreover, we would empower users with the ability to manage their digital footprint on the platform by granting them the capability to delete their own posts and any comments they have made. This step is critical for ensuring that users feel a sense of ownership and responsibility over their content and can adapt their contributions as their perspectives evolve or to correct any errors post-publication. Finally we would've enabled the reply system where users can engage with other users under posts.
AppRoutes.js
index.js
, which is the entry point of the REACT application.Routes
that map specific paths to corresponding components, such as Home
, Register
, LoginPage
, SelectedPost
, TechNews
, and NewPost
.*
) to the login page, ensuring that users are guided to a defined route.
error
: Tracks any errors that occur during API calls or data fetching.username
: Stores the current user's username after successful authentication.posts
: An array of post data retrieved from the database.allTopics
: An array of topics fetched from the database, used for categorising posts.loading
: A boolean flag to indicate whether the application is in the process of fetching necessary data.
fetchTopics
, fetchCurrentUser
, and fetchPosts
functions.loading
state is set to false
after all data fetching is completed, indicating that the application is ready to be used.fetchPosts
: Retrieves a list of posts from the backend and updates the posts
state.fetchTopics
: Fetches available topics from the backend to categorise posts and updates the allTopics
state.fetchCurrentUser
: Attempts to fetch the currently authenticated user's details and set the username
. On failure, it sets an error message.AuthenticatedRoute.js
:This component acts as a protective wrapper around other components, ensuring that only authenticated users can access the wrapped content.
username
: A string representing the username of the logged-in user.error
: A string to store any error messages encountered while fetching user data.loading
: A boolean indicating whether the user data is still being fetched.fetchCurrentUser(setUsername, setError)
: An asynchronous function that sends a request to fetch the current user's data. Upon success, it updates setUsername
with the fetched username. If an error occurs, it updates setError
with an error message.useEffect()
: Calls the fetchCurrentUser()
function to fetch the user data and sets loading
to false
once the data is fetched or an error occurs.loading
is true
, a loading message is displayed.error
is not null
or username
is null
, it redirects the user to the login page using the <Navigate>
component.username
is not null
and there are no errors, it renders the children
prop, allowing access to the wrapped content.LoginPage.js
: Login PageThis component provides a login interface for users.
userData
: An object containing the user's inputted username
and password
.error
: A string to store any error messages.handleInputChange()
: Updates userData
based on user input.loginUser()
: Sends a login request to the backend and navigates to the home page upon success.handleSubmit()
: Prevents default form behavior and calls loginUser()
.Register.js
: Registration PageThis component provides a registration interface for new users.
userData
: An object containing the user's inputted email
, username
, password
, and confirmPassword
.error
: A string to store any error messages.handleInputChange()
: Updates userData
based on user input.registerUser()
: Sends a registration request to the backend, logs out any current user, and logs in the newly registered user.handleSubmit()
: Prevents default form behavior and calls registerUser()
.Navbar.js
: Navigation BarThis component provides navigation links across the application.
username
: A string representing the username of the logged-in user.isLoading
: A boolean indicating whether user data is still being fetched.useEffect()
: Fetches the current user's data and updates username
and isLoading
.username
. If data is still loading, a loading state is shown.Home.js
: Main Home ComponentThis component is the main page of the application. It displays a list of posts, along with a sidebar to filter the posts by topic.
selectedTopic
: A string representing the topic currently selected by the user. Initially set to "All", indicating that posts from all topics are displayed by default.posts
: An array of post objects to be displayed in the PostList
component.allTopics
: An array of all available topics that can be used to filter the posts.fetchTopics
: A function to fetch the list of available topics.setLoggingIn
: A function to update the logging in status.useEffect()
: On component mount, it sets the setLoggingIn
state to false
.<Navbar />
: Renders the navigation bar at the top of the page.<Sidebar />
: Renders the sidebar component, passing in the allTopics
, fetchTopics
, setSelectedTopic
, and selectedTopic
as props. The sidebar allows users to select a topic to filter the posts.<PostList />
: Renders the list of posts, passing in the posts
and filter
as props. The filter
prop is set to the currently selectedTopic
, so the PostList
will only display posts that match the selected topic.setSelectedTopic
updates the selectedTopic
state to the chosen topic, which in turn filters the posts displayed in the PostList
.PostList.js
: Displaying and Filtering PostsThis component renders a list of posts, allowing users to click on a post to navigate to its detailed view.
posts
: An array of post objects.filter
: A string representing the category or topic used to filter posts.filteredPosts
: An array representing the posts that match the selected filter.useEffect()
: When the posts
or filter
prop changes, this effect filters the posts based on the selected topic and updates the filteredPosts
state.filter
prop is "All", all posts are displayed. Otherwise, posts are filtered based on the selected topic.handlePostClick
function navigates the user to the detailed view of the selected post.filteredPosts
and renders each post with its author, title, content preview, and image. Each post is clickable and redirects to its detailed view.Sidebar.js
: Sidebar ComponentThis component displays a sidebar containing buttons for different topics and allows users to add new topics.
allTopics
: An array of all available topics.fetchTopics
: A function to fetch the list of available topics.selectedTopic
: The currently selected topic.setSelectedTopic
: A function to update the selected topic.showTopicForm
: A boolean indicating whether the form to create a new topic is displayed.setSelectedTopic
updates the selectedTopic
state to the chosen topic.showForm
function conditionally renders the NewTopic
component based on the showTopicForm
state. The hideForm
function sets showTopicForm
to false
.allTopics
, highlighting the button corresponding to the selectedTopic
.NewTopic
form component.NewTopic
component is conditionally rendered based on showTopicForm
.SelectedPost.js
: Selected Post ViewThis component is responsible for fetching and displaying a single post based on the postId
parameter from the URL. Users can interact with the post by liking, disliking, or commenting.
post
: An object containing the details of the selected post.commentInput
: A string representing the user's comment input.reacted
: A string indicating whether the user has liked or disliked the post.likes
and dislikes
: Integers tracking the number of likes and dislikes for the post.fetchPost()
: Fetches the post data from the backend and updates the post
, likes
, and dislikes
states.useEffect()
: Calls fetchPost()
whenever postId
changes and updates likes
, dislikes
, and reacted
when post
changes.handleLike()
and handleDislike()
: Manages the user's likes and dislikes, updating the UI and sending the reaction to the backend.addComment()
: Sends the user's comment to the backend and updates the post to display the new comment.handleSubmit()
: Prevents the default form submission behavior and calls addComment()
.NewTopic.js
:NewPost.js
: Creating a New Post Feature:addPostToBackEnd
function triggers, which prepares the form data to be sent to the express server. This function creates a FormData
object containing the user's inputs and the image file, if provided.FormData
to the server's /api/createNewPost
endpoint via a POST request.req.body
and the file information in req.file
.fetchPosts()
function.TechNews.js
& SingleArticle.js
: TechNews Feature & Data Flow DocumentationThe TechNews feature allows users to interact with a web application interface to request and display technology news articles. Here's the data flow detailed with state names and application behavior:
TechNews
component loads when the user visits the TechNews section of the application.news
is an empty array, and searchQuery
is an empty string.fetchNews
is defined to handle the retrieval of news articles.searchQuery
state with the current input value.fetchNews
function is called.apiClient
to make a GET request to the backend server, including searchQuery
as a query parameter./api/techNews
designed to receive GET requests from the Front-End Client.searchQuery
from the incoming request for processing.API Details:
URL: https://newsapi.org/v2/everything
Provides a list of news articles based on the supplied search parameters.
searchQuery
received from the frontend along with the necessary API key for authentication.searchQuery
to the express server.fetchNews
function.news
state with the array of articles contained in the response, which prompts a re-render of the TechNews
component to display the new data.TechNews
component takes the news
state (now filled with articles) and uses it to render a list of SingleArticle
components, each displaying the content of one news article.fetchNews
function.This part outlines how MongoDB is being used as the database for oue React application. It includes details on the initial setup, data ingestion, and all the schemas used in our database.
data.json
file. This ensures that the application has content to display upon initial load.postTitle
: String representing the title.postContent
: String for the body content.img
: String URL for related imagery.category
: String indicating the post's category.createdAt
: Date marking the creation time.author
: Holds an ObjectId that references a User document. This creates a relationship between the Post and the User who created it.comments
: An array holding ObjectIds, each referencing a Comment document. This links the Post to all associated comments.reactions
: An array of ObjectIds referencing Reaction documents to represent user reactions to the post.Holds user information:
username
: Unique string for the user's name.email
: String for the user's email, unique to each user.password
: Encrypted string for the user's password.Represents comments on posts:
content
: String for the comment text.author
: ObjectId referencing a User document to denote the commenter's identity.post
: ObjectId referencing the related Post document. This establishes a connection between the comment and the specific post it belongs to.createdAt
: Date of comment creation.Tracks reactions to posts:
postId
: ObjectId referencing a Post document to associate the reaction with a particular post.userId
: ObjectId referencing a User document to attribute the reaction to a specific user.reaction
: String indicating the type of reaction, with limited options (e.g., 'upvote', 'downvote').Categorises posts:
topicName
: String for the topic title.topicDescription
: String detailing the topic.ReedMi places an emphasis on user authentication and security. Here's how we've implemented these features:
Google Authentication:
OAuth 2.0: We use Google's OAuth 2.0 for user authentication. Passport.js: Passport.js, along with the GoogleStrategy, is used for authenticating users via Google. User Creation: On a user's first Google login, a new user profile is created using the email received from Google. A unique username is generated by appending a random four-digit number to the part of the email before '@'. Session Management: Passport.js serialises and deserialises user data to and from the session.
Local Authentication:
Username and Password: Users can also register and log in using a combination of username and email. Password Security: User passwords are hashed using bcrypt before being stored in the database. Passport.js: We use Passport.js with the LocalStrategy to authenticate users using a username and password. Authorisation Middleware:
ensureAuthenticated: This middleware function ensures that certain routes are protected and only accessible by authenticated users.
Logout:
Session Destruction: Upon logout, the user's session is destroyed and cookies are cleared, ensuring a secure logout. Cross-Origin Resource Sharing (CORS):
Security: Our application is configured to handle CORS, ensuring that only trusted domains have access to our APIs.
GET /google
GET /google/callback
/home
). On failure, redirects to the root URL (/
).GET /oauth2/redirect/google
/
) on both success and failure.POST /register
email
, username
, password
, and confirm
.POST /login
GET /logout
/login
).GET /current_user
ensureAuthenticated
checks if the user is authenticated.ensureAuthenticated
next()
if the user is authenticated, allowing the request to proceed.GET /api/posts
GET /api/posts/:id
:id
, along with its comments, reactions, and author details.POST /api/posts/:postId/comment
:postId
.ensureAuthenticated
checks if the user is authenticated.POST /api/posts/:postId/reaction
:postId
.ensureAuthenticated
checks if the user is authenticated.GET /api/posts/:postId/comments
:postId
.POST /api/createNewPost
ensureAuthenticated
checks if the user is authenticated, and multer
handles file uploads.GET /api/topics
POST /api/topics
GET /api/techNews
q
specifies the user query.Mifta
Ryan
Calum
Ahmed:
Everyone: