Skip to content

Commit

Permalink
instructions updated
Browse files Browse the repository at this point in the history
  • Loading branch information
g-pooja-03 committed Dec 1, 2024
2 parents bafee9e + 861421c commit 0081519
Show file tree
Hide file tree
Showing 27 changed files with 416 additions and 149 deletions.
43 changes: 35 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
The individual and team project for this class are designed to mirror the experiences of a software engineer joining a new development team: you will be “onboarded” to our codebase, make several individual contributions, and then form a team to propose, develop and implement new features. The codebase that we’ll be developing on is a Fake Stack Overflow project (let’s call it HuskyFlow). You will get an opportunity to work with the starter code which provides basic skeleton for the app and then additional features will be proposed and implemented by you! All implementation will take place in the TypeScript programming language, using React for the user interface.

Refer to the [Project Overview](https://neu-se.github.io/CS4530-Fall-2024/assignments/project-overview) for more instructions on the project deliverables and expectations.

{ : .note } Refer to [IP1](https://neu-se.github.io/CS4530-Fall-2024/assignments/ip1) and [IP2](https://neu-se.github.io/CS4530-Fall-2024/assignments/ip2) for instructions related to setting up MongoDB, setting environment variables, and running the client and server.

{ : .note } The fields of the Schemas were changed. As a result, features such as view counts will not work on database entries that were made in IP1 and IP2. If you want to test features, delete old database entries and make new questions either through manually making it in the client or run populate_db.ts.
Group 206
Elizabeth Jones, Pooja Gidwani, Kristen Liu, Isha Srivastava

The individual and team project for this class are designed to mirror the experiences of a software
engineer joining a new development team: you will be “onboarded” to our codebase, make several
individual contributions, and then form a team to propose, develop and implement new features.
The codebase that we’ll be developing on is a Fake Stack Overflow project (let’s call it HuskyFlow).
You will get an opportunity to work with the starter code which provides basic skeleton for the app
and then additional features will be proposed and implemented by you! All implementation will take
place in the TypeScript programming language, using React for the user interface.

Refer to the [Project Overview]
(https://neu-se.github.io/CS4530-Fall-2024/assignments/project-overview)
for more instructions on the project deliverables and expectations.

{ : .note } Refer to [IP1](https://neu-se.github.io/CS4530-Fall-2024/assignments/ip1) and
[IP2](https://neu-se.github.io/CS4530-Fall-2024/assignments/ip2) for instructions related to setting
up MongoDB, setting environment variables, and running the client and server.

{ : .note } The fields of the Schemas were changed. As a result, features such as view counts will
not work on database entries that were made in IP1 and IP2. If you want to test features, delete old
database entries and make new questions either through manually making it in the client or
run populate_db.ts.

## Database Architecture

Expand All @@ -14,7 +30,18 @@ A class diagram for the schema definition is shown below:
![Class Diagram](class-diagram.png)

### Final Project
Our program, CodeQuest, is a software question site. The baseline functionality including asking and answering questions, in addition to support for adding comments. We expanded on this, first with a login process for the application. Here, user data is stored and authenticated with Firebase. Moreover, when thinking about users on software question site, they will often have specific languages or systems they want to learn about. Thus, we support a feature for a user to choose tags that interest them (which they can also update later). We take this information and then suggest a community for the user to join, which they can accept, choose their own, or omit. Using this information, we have a homepage which displays different questions that might be relevant to the user, based on their community if specified. In addition, users will have a status based on a threshold of reliability that will define them as either a member or moderator. Moderators can edit or delete posts in their community. We implemented a chat feature so we can talk to other users in real time, as well as a chat feature built into the communities.
Our program, CodeQuest, is a software question site. The baseline functionality including asking
and answering questions, in addition to support for adding comments. We expanded on this, first with
a login process for the application. Here, user data is stored and authenticated with Firebase.
Moreover, when thinking about users on software question site, they will often have specific
languages or systems they want to learn about. Thus, we support a feature for a user to choose tags
that interest them (which they can also update later). We take this information and then suggest a
community for the user to join, which they can accept, choose their own, or omit. Using this
information, we have a homepage which displays different questions that might be relevant to the
user, based on their community if specified. In addition, users will have a status based on a
threshold of reliability that will define them as either a member or moderator. Moderators can edit
or delete posts in their community. We implemented a chat feature so we can talk to other users in
real time, as well as a chat feature built into the communities.

To run a working version of CodeQuest, first ensure you have all the required dependencies. You can view the downloadable code workspace in Visual Studio, which can be downloaded online. You can also download MongoDB for data storage purposes in the program. Once it is open, run curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh in the root directory. Also run nvm install 20. In the server directory, run npm install. Populate the database by running npx ts-node populate_db.ts mongodb://127.0.0.1:27017/fake_so here. In the client directory, run npm install. Also run npm install firebase. If not present, add a .env file in the client directory with this line REACT_APP_SERVER_URL=http://localhost:8000. In the server directory, add a .env file with these lines MONGODB_URI=mongodb://127.0.0.1:27017, CLIENT_URL=http://localhost:3000, PORT=8000.

Expand Down
2 changes: 1 addition & 1 deletion client/src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SideBarNav from '../main/sideBarNav';
import Header from '../header';

/**
* Main component represents the layout of the main page, including a sidebar and the main content area.
* Main component represents the layout of the main page, including a sidebar and main content area.
*/
const Layout = () => (
<>
Expand Down
5 changes: 4 additions & 1 deletion client/src/components/main/answerPage/questionBody/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@

.save-button {
background-color: #BABDE2;
position: relative;
color: white;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
margin-left: 10px;
top: -8px;
transition: background-color 0.3s ease, transform 0.3s ease;
}

Expand Down Expand Up @@ -77,4 +79,5 @@ textarea:focus {
display: flex;
flex-direction: column;
margin-left: 5%;
align-items: flex-start;
}
3 changes: 2 additions & 1 deletion client/src/components/main/commentSection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import useUserContext from '../../../hooks/useUserContext';
* Interface representing the props for the Comment Section component.
*
* - comments - list of the comment components
* - handleAddComment - a function that handles adding a new comment, taking a Comment object as an argument
* - handleAddComment - a function that handles adding a new comment, taking a Comment object
* as an argument
*/
interface CommentSectionProps {
comments: Comment[];
Expand Down
22 changes: 22 additions & 0 deletions client/src/components/main/profile/accountInfo/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,25 @@
.go-back-button:active {
background-color: #466694;
}

.moderator-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 10px 20px;
font-size: 13px;
font-weight: bold;
color: white;
background-color: #4A7DAA;
border: none;
border-radius: 8px;
cursor: pointer;
text-transform: uppercase;
letter-spacing: 1px;
margin: 20px 0;
transition: background-color 0.3s ease;
}

.moderator-button:hover {
background-color: #3A5F85;
}
4 changes: 3 additions & 1 deletion client/src/components/main/profile/accountInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ const AccountInfo = () => {
<p className='username-info'>{userData.status}</p>
</div>
{qualifyModerator && userData.status !== 'moderator' && (
<button onClick={updateUserStatus}>become a moderator</button>
<button className='moderator-button' onClick={updateUserStatus}>
become a moderator
</button>
)}
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions client/src/components/main/profile/community/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@

.community-pills-container {
display: flex;
flex-wrap: wrap; /* Ensures pills wrap if they overflow */
gap: 10px; /* Adds space between pills */
justify-content: center; /* Centers the pills in the container */
align-items: center; /* Aligns pills vertically */
margin: 20px 0; /* Adds spacing around the container */
flex-wrap: wrap;
gap: 10px;
justify-content: center;
align-items: center;
margin: 20px 0;
}

.community-pill {
Expand Down
1 change: 0 additions & 1 deletion client/src/components/main/profile/header/index.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* Assuming you have a specific CSS file for ProfileHeader */
.profile-header {
display: flex;
justify-content: center;
Expand Down
1 change: 0 additions & 1 deletion client/src/components/main/profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const ProfilePage = () => {
<div className='home-container'>
<SideBarHome />
<div className='profile-content'>
{/* <ProfileHeader className='title-text' titleText={titleText} /> */}
<Outlet />
</div>
</div>
Expand Down
1 change: 0 additions & 1 deletion client/src/components/main/profile/tags/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
width: 100%;
align-items: center;
justify-content: center;
/* background-color: #f5f5f5; */
box-sizing: border-box;
margin-top: -50px;
height: auto;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ interface OrderButtonProps {
* It will update the order of questions based on the input message.
*
* @param orderType - The label for the button and the value passed to setQuestionOrder function.
* @param setQuestionOrder - Callback function to set the order of questions based on the input message.
* @param setQuestionOrder - Callback function to set the order of questions based on the input
* message.
*/
const OrderButton = ({ orderType, setQuestionOrder }: OrderButtonProps) => (
<button
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/main/questionPage/question/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ interface QuestionProps {
}

/**
* Question component renders the details of a question including its title, tags, author, answers, and views.
* Clicking on the component triggers the handleAnswer function,
* Question component renders the details of a question including its title, tags, author,
* answers, and views. Clicking on the component triggers the handleAnswer function,
* and clicking on a tag triggers the clickTag function.
*
* @param q - The question object containing question details.
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/main/sideBarNav/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}

.menu_selected {
color: #895159; /* Ensure text color remains black */
color: #895159;
text-decoration: underline 895159 2px;
}

Expand Down
7 changes: 3 additions & 4 deletions client/src/hooks/useAnswerPage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
import { useNavigate, useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { Comment, Answer, Question, VoteData, NewQuestionData } from '../types';
Expand All @@ -10,7 +11,8 @@ import { getQuestionById } from '../services/questionService';
*
* @returns questionID - The current question ID retrieved from the URL parameters.
* @returns question - The current question object with its answers, comments, and votes.
* @returns handleNewComment - Function to handle the submission of a new comment to a question or answer.
* @returns handleNewComment - Function to handle the submission of a new comment to a question
* or answer.
* @returns handleNewAnswer - Function to navigate to the "New Answer" page
*/
const useAnswerPage = () => {
Expand Down Expand Up @@ -56,7 +58,6 @@ const useAnswerPage = () => {

await addComment(targetId, targetType, comment);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error adding comment:', error);
}
};
Expand All @@ -70,12 +71,10 @@ const useAnswerPage = () => {
const res = await getQuestionById(questionID, user.username);
setQuestion(res || null);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error fetching question:', error);
}
};

// eslint-disable-next-line no-console
fetchData().catch(e => console.log(e));
}, [questionID, user.username]);

Expand Down
4 changes: 2 additions & 2 deletions client/src/hooks/useCommunityNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const useCommunityNames = () => {
try {
const res = await getCommunityNames();
if (Array.isArray(res)) {
setCommunityNames(res.map(community => community.name)); // Assuming `name` is a property of the community object.
setCommunityNames(res.map(community => community.name));
} else {
setCommunityNames([]);
}
Expand All @@ -35,7 +35,7 @@ const useCommunityNames = () => {
};

fetchCommunityNames();
}, []); // Run the fetch only once on mount
}, []);

return { communityNames, loading, error };
};
Expand Down
3 changes: 2 additions & 1 deletion client/src/hooks/useRelevantCommunities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { getRelevantCommunities } from '../services/communityService';
* @param tags - The list of tags to fetch relevant communities for.
*
* @returns relevantCommunities - The current list of relevant communities.
* @returns setRelevantCommunities - Setter to manually update the relevant communities state if needed.
* @returns setRelevantCommunities - Setter to manually update the relevant communities state if
* needed.
* @returns loading - The current loading state.
* @returns error - The current error message.
*/
Expand Down
3 changes: 2 additions & 1 deletion client/src/hooks/useTagPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { TagData } from '../types';
* Custom hook for managing the tag page's state and navigation.
*
* @returns tlist - An array of tag data retrieved from the server
* @returns clickTag - Function to navigate to the home page with the selected tag as a URL parameter.
* @returns clickTag - Function to navigate to the home page with the selected tag as a URL
* parameter.
*/
const useTagPage = () => {
const navigate = useNavigate();
Expand Down
3 changes: 2 additions & 1 deletion client/src/hooks/useVoteStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const useVoteStatus = ({ question }: { question: Question }) => {
/**
* Function to get the current vote value for the user.
*
* @returns The current vote value for the user in the question, 1 for upvote, -1 for downvote, 0 for no vote.
* @returns The current vote value for the user in the question, 1 for upvote, -1 for downvote,
* 0 for no vote.
*/
const getVoteValue = () => {
if (user.username && question?.upVotes?.includes(user.username)) {
Expand Down
3 changes: 2 additions & 1 deletion client/src/services/commentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Comment } from '../types';
const COMMENT_API_URL = `${process.env.REACT_APP_SERVER_URL}/comment`;

/**
* Interface extending the request body when adding a comment to a question or an answer, which contains:
* Interface extending the request body when adding a comment to a question or an answer, which
* contains:
* - id - The unique identifier of the question or answer being commented on.
* - type - The type of the comment, either 'question' or 'answer'.
* - comment - The comment being added.
Expand Down
1 change: 0 additions & 1 deletion server/controller/community.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ const communityController = (socket: FakeSOSocket) => {
};

router.get('/getCommunityNames', getCommunityNames);
// router.get('/getCommunityByName/:name', getCommunityByName);
router.get('/getCommunityQuestions/:community', getCommunityQuestions);
router.get('/getCommunityMembers/:community', getCommunityMembers);
router.get('/getRelevantCommunities', getRelevantCommunities);
Expand Down
16 changes: 0 additions & 16 deletions server/populate_db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,22 +255,6 @@ async function communityCreate(name: string, tags: string[], users: string[], qu
return await CommunityModel.create(community);
}

/**
* FIX THIS COMMENT
*/
// async function userCreate(username: string, firstName: string, lastName: string, tags: Tag[], community: Community, status: string): Promise<User> {
// if (firstName === '' || lastName === '' || tags.length === 0 || status === '') throw new Error('Invalid Community Format');
// const user: User = {
// username: username,
// firstName: firstName,
// lastName: lastName,
// tags: tags,
// community: community,
// status: status,
// };
// return await UserModel.create(user);
// }

/**
* Populates the database with predefined data.
* Logs the status of the operation to the console.
Expand Down
Loading

0 comments on commit 0081519

Please sign in to comment.