Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b36379e
Create proposal.md
tjcoppola234 Sep 28, 2022
7659905
Update proposal.md
tjcoppola234 Sep 28, 2022
88707c8
initial react-snowpack build
tjcoppola234 Oct 6, 2022
10df746
initial react and snowpack build
tjcoppola234 Oct 6, 2022
48d0df2
set up server
tjcoppola234 Oct 6, 2022
6d9e640
made connection to db
tjcoppola234 Oct 6, 2022
7e2587e
server works, css attached, mongo untested
tjcoppola234 Oct 10, 2022
2938c06
Merge pull request #1 from tjcoppola234/init_server
tjcoppola234 Oct 10, 2022
ebec3d0
login and switch between pages setup
tjcoppola234 Oct 11, 2022
b830d1d
setup for register
tjcoppola234 Oct 11, 2022
9275c4e
Merge pull request #2 from tjcoppola234/login_page
tjcoppola234 Oct 11, 2022
81cb925
button to make a post
tjcoppola234 Oct 11, 2022
67e1492
log in and registering
Oct 11, 2022
37f2175
show posts and responses
tjcoppola234 Oct 12, 2022
571e479
Merge branch 'main' into app-layout
tjcoppola234 Oct 12, 2022
645c79a
Merge pull request #3 from tjcoppola234/app-layout
tjcoppola234 Oct 12, 2022
c876fcf
add list of responses to a user
Oct 12, 2022
345400c
shows responses and makes responses
tjcoppola234 Oct 12, 2022
a953d2f
Merge branch 'main' into show-resp
tjcoppola234 Oct 13, 2022
efccbdc
Merge pull request #4 from tjcoppola234/show-resp
tjcoppola234 Oct 13, 2022
978229d
refresh btn and display user's total responses
tjcoppola234 Oct 13, 2022
d7f2230
readme template
tjcoppola234 Oct 13, 2022
472923a
adding css
Oct 13, 2022
2941c39
merged
Oct 13, 2022
8496c0b
Update README.md
gabi246 Oct 13, 2022
a65036b
Theo's Contribution
tjcoppola234 Oct 14, 2022
a6f092c
Merge pull request #5 from tjcoppola234/readme
tjcoppola234 Oct 14, 2022
67c0177
Update README.md
GriffinAtchue Oct 14, 2022
7360e4e
css
Oct 14, 2022
d3a0ecb
Merge pull request #6 from tjcoppola234/css
tjcoppola234 Oct 14, 2022
16fb9d8
changed start call and added spaces
tjcoppola234 Oct 14, 2022
b58136b
css
Oct 14, 2022
781a2c2
Merge branch 'main' into optimize
tjcoppola234 Oct 14, 2022
a2a944d
Merge pull request #7 from tjcoppola234/optimize
tjcoppola234 Oct 14, 2022
340fc72
small change
tjcoppola234 Oct 14, 2022
fcab881
added node_modules
tjcoppola234 Oct 14, 2022
74c6067
Add Spotify Integration
Oct 14, 2022
9f578b1
Update README.md
Oct 14, 2022
f61fd88
Update embed instructions
Oct 14, 2022
f64cf81
Update README.md
Oct 14, 2022
9845126
Update README.md
Oct 14, 2022
65cdd06
Update README.md
tjcoppola234 Oct 14, 2022
453bfa1
Merge pull request #8 from tjcoppola234/spotify-integration
tjcoppola234 Oct 14, 2022
6bf7f59
Add files via upload
tjcoppola234 Oct 14, 2022
264e6c4
Update README.md
tjcoppola234 Oct 14, 2022
cdc9e60
Update README.md
tjcoppola234 Oct 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
USER='cs4241Final'
PASS='mk88jR728ghCAc4P'
HOST='cluster0.clagd6g.mongodb.net'
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

.cache/
coverage/
dist/*
!dist/index.html
# node_modules/
*.log

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
65 changes: 26 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,36 @@
# Final Project
*Due before the start of class, October 13th (final day of the term)*
# Song Finder
https://song-finder.glitch.me

For your final project, you'll implement a web application that exhibits understanding of the course materials.
This project should provide an opportunity to both be creative and to pursue individual research and learning goals.
This is a social music-based app where people can post about the kind of music they want to hear and others can respond with song suggestions.

## General description
Your project should consist of a complete Web application, exhibiting facets of the three main sections of the course material:
Users can:
- See the total number of song suggestions they have made
- View other users' responses to a post
- Create posts telling users what kind of music they are looking for
- Respond to posts with song suggestions, raising their total number of responses.

- Static web page content and design. You should have a project that is accessible, easily navigable, and features significant content.
- Dynamic behavior implemented with JavaScript (TypeScript is also allowed if your group wants to explore it).
- Server-side programming *using Node.js*. Typically this will take the form of some sort of persistent data (database), authentication, and possibly server-side computation.
- A video (less than five minutes) where each group member explains some aspect of the project. An easy way to produce this video is for you all the groups members to join a Zoom call that is recorded; each member can share their screen when they discuss the project or one member can "drive" the interface while other members narrate (this second option will probably work better.) The video should be posted on YouTube or some other accessible video hosting service. Make sure your video is less than five minutes, but long enough to successfully explain your project and show it in action. There is no minimum video length.
To use the app you must enter a username and password, and either log in with an existing account (press log in), or register for a new account (press register).

## Project ideation
Excellent projects typically serve someone/some group; for this assignment you need to define your users and stakeholders. I encourage you to identify projects that will have impact, either artistically, politically, or in terms of productivity.
After responding to a post, click the "Refresh Everything" button to see your total response number go up and your response appear under the post.

### Deliverables
## Technologies
- React.js: This was used to dynamically update content on the main page as it changed. It was also used for switching between the login and main page.
- MongoDB: This was used for storing all data related to account info, request posts, and song suggestions.
- Express.js: This was used to serve files from our source folder and simplify the data sending and retrieval process

#### Form Team (due 9/25)
Students are will work in teams of 3-5 students for the project; teams of two can be approved with the permission of the instructor. Working in teams should help enable you to build a good project in a limited amount of time. Use the `#project-logistics` channel in Discord to pitch ideas for final projects and/or find fellow team members as needed.
## Challenges
React has quite a steep learning curve and figuring out how to do tasks that would have been easier to do with basic javascript took a lot of time. But, after understanding the concepts and development flow of react, it became very useful and ultimately simplified complex and costly tasks.

Teams must be in place by end of day on Sunday, September 25th. If you have not identified a team at this point, you will be assigned a team. You will be given some class time on Monday to work on your proposal, but please plan on reserving additional time outside of class as needed.
Handling data on the main page was difficult because updating state variables would cause re-rendering loops and lead to endless fetch requests. Also, when setting state variables, their values would not immediately be updated, which made workarounds necessary.

#### Proposal (due 9/27)
Provide an outline of your project direction and the names of associated team members.
The outline should have enough detail so that staff can determine if it meets the minimum expectations, or if it goes too far to be reasonable by the deadline. Please include a general description of a project, and list of key technologies/libraries you plan on using (e.g. React, Three.js, Svelte, TypeScript etc.). Two to four paragraps should provide enough level of detail. Name the file proposal.md and submit a pull request by Tuesday, September 27th at 11:59 PM (end of day). Only one pull request is required per team.
Correctly switching between pages was comlicated and routing in React required lots of debugging until it worked correctly.

There are no other scheduled checkpoints for your project.
## Contributions
What each group member was responsible for designing / developing.
- Theo Coppola: Set up the structure of the application (login page + main page) and routing between pages. Created the server and implemented fetch/get requests and the database strucure with Marie. Created the readme. Implemented all jsx files and created methods, state variables, and event handlers.
- Marie Tessier: Worked mainly on the server side of the code and mongoDB with Theo. I helped implement the database structure and the fetch/get requests and posts. I also helped on the front end css, finding and implementing a template by Creative Tim (https://www.creative-tim.com). Note: Griffin sent me some that he had coded css because he was having trouble with his computer so the Git commits do not fully represent his contribution.
- Griffin Atchue: Worked on front end designing html pages that were eventually left out and implemented formatting through css with assistance due to technical issues.
- Jack McEvoy: Worked on front end designing html pages and overall layout that were eventually left out and implemented spotify integration.

#### Turning in Your Project
Submit a second PR on the final project repo to turn in your app and code. Again, only one pull request per team.

Deploy your app, in the form of a webpage, to Glitch/Heroku/Digital Ocean or some other service; it is critical that the application functions correctly wherever you post it.

The README for your second pull request doesn’t need to be a formal report, but it should contain:

1. A brief description of what you created, and a link to the project itself (two paragraphs of text)
2. Any additional instructions that might be needed to fully use your project (login information etc.)
3. An outline of the technologies you used and how you used them.
4. What challenges you faced in completing the project.
5. What each group member was responsible for designing / developing.
6. A link to your project video.

Think of 1,3, and 4 in particular in a similar vein to the design / tech achievements for A1—A4… make a case for why what you did was challenging and why your implementation deserves a grade of 100%.

## FAQs

- **Can I use XYZ framework?** You can use any web-based frameworks or tools available, but for your server programming you need to use Node.js. Your client-side scripting language should be either JavaScript or TypeScript.
## Walkthrough
[Tutorial Video](https://github.com/tjcoppola234/Final_Project/blob/main/video3389648567.mp4)
213 changes: 213 additions & 0 deletions build/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import React from "./_snowpack/pkg/react.js";
import "./blk-design-system-react.css.proxy.js";
import {Navigate} from "./_snowpack/pkg/react-router-dom.js";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
loggedin: true,
currUser: "",
userRespNum: -1,
posts: [],
displayMakePost: false,
displayMakeResponse: [],
displayViewResponses: [],
tempRespData: []
};
this.loginStatus();
this.load();
}
load() {
fetch("/collDocs", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({name: "posts"})
}).then((response) => response.json()).then((json) => {
console.log(json);
this.setState({posts: json});
});
}
numResponses(username) {
fetch("/userInfo", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({user: username})
}).then((response) => response.json()).then((json) => {
if (json[0] !== void 0) {
this.setState({userRespNum: json[0].responses.length});
}
});
}
loginStatus() {
fetch("/loginStatus", {
method: "get",
"no-cors": true,
headers: {"Content-Type": "application/json"}
}).then((response) => response.json()).then((json) => {
this.setState({loggedin: json.login, currUser: json.user});
this.numResponses(json.user);
});
}
makePost(e) {
e.preventDefault();
fetch("/addPost", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({user: this.state.currUser, comment: document.getElementById("makePostComment").value, responses: []})
});
this.setState({displayMakePost: false});
this.load();
}
showMakePost() {
if (this.state.displayMakePost) {
return /* @__PURE__ */ React.createElement("form", {
id: "makePost"
}, /* @__PURE__ */ React.createElement("label", {
for: "makePostComment"
}, "What would you like to hear?"), /* @__PURE__ */ React.createElement("input", {
id: "makePostComment",
type: "text"
}), /* @__PURE__ */ React.createElement("button", {
type: "submit",
onClick: (e) => this.makePost(e)
}, "Submit"), /* @__PURE__ */ React.createElement("button", {
type: "button",
onClick: () => this.setState({displayMakePost: false})
}, "Cancel"));
}
}
displayPost(post, i) {
return /* @__PURE__ */ React.createElement("li", null, "Comment: ", post.comment, /* @__PURE__ */ React.createElement("button", {
type: "button",
onClick: () => {
let arr = this.state.displayMakeResponse;
arr[i] = true;
this.setState({displayMakeResponse: arr});
}
}, "Respond"), /* @__PURE__ */ React.createElement("input", {
id: "viewrespbtn",
type: "button",
value: this.state.displayViewResponses[i] === true ? "Hide Responses" : "View Responses",
onClick: (e) => {
this.load();
let arr = this.state.displayViewResponses;
if (arr[i] === true) {
arr[i] = false;
this.setState({displayViewResponses: arr});
} else {
arr[i] = true;
this.setState({displayViewResponses: arr});
}
if (this.state.posts[i].responses !== void 0) {
let repdataArr = this.state.tempRespData;
repdataArr[i] = [];
this.setState({tempRespData: repdataArr});
for (let j = 0; j < this.state.posts[i].responses.length; j++) {
fetch("/collDoc", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({collName: "responses", _id: this.state.posts[i].responses[j]})
}).then((result) => result.json()).then((json) => {
let dataArr = this.state.tempRespData;
dataArr[i].push(json[0]);
this.setState({tempRespData: dataArr});
});
}
}
}
}), this.showViewResponses(i), this.showMakeResponse(i));
}
makeResponse(e, i) {
e.preventDefault();
fetch("/addResp", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
user: this.state.currUser,
song: document.getElementById("makeResponseSong").value,
artist: document.getElementById("makeResponseArtist").value,
comment: document.getElementById("makeResponseComment").value
})
}).then((response) => response.json()).then((json) => {
fetch("/updatePostNewResponse", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({_id: this.state.posts[i]._id, responseid: json.insertedId})
});
});
let arr = this.state.displayMakeResponse;
arr[i] = false;
this.setState({displayMakeResponse: arr});
}
showMakeResponse(i) {
if (this.state.displayMakeResponse[i]) {
return /* @__PURE__ */ React.createElement("form", {
id: "makeResponse"
}, /* @__PURE__ */ React.createElement("label", {
for: "makeResponseSong"
}, "Song: "), /* @__PURE__ */ React.createElement("input", {
id: "makeResponseSong",
type: "text"
}), /* @__PURE__ */ React.createElement("label", {
for: "makeResponseArtist"
}, "Artist: "), /* @__PURE__ */ React.createElement("input", {
id: "makeResponseArtist",
type: "text"
}), /* @__PURE__ */ React.createElement("label", {
for: "makeResponseComment"
}, "Comment: "), /* @__PURE__ */ React.createElement("input", {
id: "makeResponseComment",
type: "text"
}), /* @__PURE__ */ React.createElement("button", {
type: "submit",
onClick: (e) => this.makeResponse(e, i)
}, "Submit"), /* @__PURE__ */ React.createElement("button", {
type: "button",
onClick: () => {
let arr = this.state.displayMakeResponse;
arr[i] = false;
this.setState({displayMakeResponse: arr});
}
}, "Cancel"));
}
}
showViewResponses(i) {
if (this.state.displayViewResponses[i] && this.state.tempRespData[i] !== void 0 && this.state.tempRespData[i].length > 0) {
const jsx = /* @__PURE__ */ React.createElement("ul", null, this.state.tempRespData[i].map((entry, j) => {
if (entry !== null && Object.keys(entry).length !== 0) {
console.log(this.state.tempRespData);
return this.showResponseData(i, j);
}
}));
return jsx;
}
}
showResponseData(i, j) {
return /* @__PURE__ */ React.createElement("li", null, "Song: ", this.state.tempRespData[i][j].song, " Artist: ", this.state.tempRespData[i][j].artist, " Comment: ", this.state.tempRespData[i][j].comment);
}
render() {
if (this.state.loggedin == false) {
return /* @__PURE__ */ React.createElement(Navigate, {
replace: true,
to: "/login"
});
} else {
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h1", null, "Hello ", this.state.currUser, "  Responses Made: ", this.state.userRespNum), /* @__PURE__ */ React.createElement("button", {
type: "button",
onClick: () => window.location.reload()
}, "Refresh Everything"), /* @__PURE__ */ React.createElement("div", {
id: "displayPosts"
}, /* @__PURE__ */ React.createElement("button", {
type: "button",
onClick: () => this.setState({displayMakePost: true})
}, "Make Post"), this.showMakePost(), /* @__PURE__ */ React.createElement("ul", null, this.state.posts.map((post, i) => this.displayPost(post, i)))));
}
}
}
export default App;
72 changes: 72 additions & 0 deletions build/Login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, {useState} from "./_snowpack/pkg/react.js";
import {useNavigate} from "./_snowpack/pkg/react-router-dom.js";
function Login(props) {
const [user, setUser] = useState("");
const [pass, setPass] = useState("");
const [loginStatus, setLoginStatus] = useState("");
const navigate = useNavigate();
function logIn(e) {
e.preventDefault();
fetch("/loggingIn", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({user, pass})
}).then((response) => response.json()).then((json) => {
if (!json.login) {
setLoginStatus("Failed to log in");
document.getElementById("pass").value = "";
} else {
navigate("/");
}
});
}
function register(e) {
e.preventDefault();
fetch("/register", {
method: "post",
"no-cors": true,
headers: {"Content-Type": "application/json"},
body: JSON.stringify({user, pass, responses: []})
}).then((response) => response.json()).then((json) => {
console.log(json.result);
if (json.result !== "") {
setLoginStatus(json.result);
} else {
navigate("/");
}
});
}
return /* @__PURE__ */ React.createElement("form", {
id: "loginForm"
}, /* @__PURE__ */ React.createElement("h2", {
class: "loginText"
}, "Log in"), /* @__PURE__ */ React.createElement("label", {
id: "loginFields",
for: "user"
}, "Username:"), /* @__PURE__ */ React.createElement("input", {
type: "text",
id: "user",
name: "user",
onChange: (e) => setUser(e.target.value)
}), /* @__PURE__ */ React.createElement("label", {
id: "loginFields2",
for: "pass"
}, "Password: "), /* @__PURE__ */ React.createElement("input", {
type: "password",
id: "pass",
name: "pass",
onChange: (e) => setPass(e.target.value)
}), /* @__PURE__ */ React.createElement("input", {
id: "loginButtons",
type: "submit",
value: "log in",
onClick: (e) => logIn(e)
}), /* @__PURE__ */ React.createElement("input", {
id: "loginButtons2",
type: "submit",
value: "register",
onClick: (e) => register(e)
}), /* @__PURE__ */ React.createElement("p", null, loginStatus));
}
export default Login;
Loading