Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions client/dist/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8" />
Expand All @@ -8,6 +9,18 @@
</head>

<body>
<script src="https://www.gstatic.com/firebasejs/5.6.0/firebase-app.js-auth "></script>
<script>
const firebaseConfig = {
apiKey: "AIzaSyA0LLhGRO00T9Cfm1DA15aq2edmTmB6H1Q",
authDomain: "mit-mixer.firebaseapp.com",
projectId: "mit-mixer",
storageBucket: "mit-mixer.appspot.com",
messagingSenderId: "673875830760",
appId: "1:673875830760:web:1db1205d5ee54af68ae65d",
measurementId: "G-4SGZQBDGBN"
};
</script>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
Expand Down
8 changes: 8 additions & 0 deletions client/src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { Router } from "@reach/router";
import NotFound from "./pages/NotFound.js";
import Skeleton from "./pages/Skeleton.js";
import SignUp from "./pages/SignUp.js";
import LoginPage from "./pages/LoginPage.js";
import HomePage_Signed_In from "./pages/HomePage_Signed_In.js";
import Chatbook from "./pages/Chatbook.js";
import Profile from "./pages/profile.js";


import "../utilities.css";
Expand Down Expand Up @@ -45,6 +49,10 @@ const App = () => {
<Router>
<Skeleton path="/" handleLogin={handleLogin} handleLogout={handleLogout} userId={userId} />
<SignUp path="/signup"/>
<LoginPage path="/loginpage" />
<HomePage_Signed_In path="/HomePage_Signed_In"/>
<Chatbook path="/chatbook" />
<Profile path="/profile" />
<NotFound default />
</Router>
</>
Expand Down
19 changes: 19 additions & 0 deletions client/src/components/auth_email_link_actioncode_settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

const actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for this
// URL must be in the authorized domains list in the Firebase Console.
url: 'http://localhost:5000',
// This must be true.
handleCodeInApp: true,
iOS: {
bundleId: 'com.example.ios'
},
android: {
packageName: 'com.example.android',
installApp: true,
minimumVersion: '12'
},
dynamicLinkDomain: 'mixermit.page.link'
};

export default actionCodeSettings;
36 changes: 36 additions & 0 deletions client/src/components/auth_email_link_send.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getAuth, sendSignInLinkToEmail } from "firebase/auth";

const auth = getAuth();
const email = "";
const actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for this
// URL must be in the authorized domains list in the Firebase Console.
url: 'https://www.youtube.com/',
// This must be true.
handleCodeInApp: true,
iOS: {
bundleId: 'com.example.ios'
},
android: {
packageName: 'com.example.android',
installApp: true,
minimumVersion: '12'
},
dynamicLinkDomain: 'mixermit.page.link'
};

sendSignInLinkToEmail(auth, email, actionCodeSettings)
.then(() => {
// The link was successfully sent. Inform the user.
// Save the email locally so you don't need to ask the user for it again
// if they open the link on the same device.
window.localStorage.setItem('emailForSignIn', email);
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ...
});

export default sendSignInLinkToEmail;
13 changes: 13 additions & 0 deletions client/src/components/authenticateUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { auth } from "./firebase";

async function authenticateUser(email, password, isLogin) {
try {
const user = isLogin
? await auth.signInWithEmailAndPassword(email, password)
: await auth.createUserWithEmailAndPassword(email, password);
console.log(user);
} catch (err) {
console.log(err);
}
}
export default authenticateUser;
32 changes: 32 additions & 0 deletions client/src/components/email_link_complete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth";

// Confirm the link is a sign-in with email link.
const auth = getAuth();
if (isSignInWithEmailLink(auth, window.location.href)) {
// Additional state parameters can also be passed via URL.
// This can be used to continue the user's intended action before triggering
// the sign-in operation.
// Get the email if available. This should be available if the user completes
// the flow on the same device where they started it.
let email = window.localStorage.getItem('emailForSignIn');
if (!email) {
// User opened the link on a different device. To prevent session fixation
// attacks, ask the user to provide the associated email again. For example:
email = window.prompt('Please provide your email for confirmation');
}
// The client SDK will parse the code from the link for you.
signInWithEmailLink(auth, email, window.location.href)
.then((result) => {
// Clear email from storage.
window.localStorage.removeItem('emailForSignIn');
// You can access the new user via result.user
// Additional user info profile not available via:
// result.additionalUserInfo.profile == null
// You can check if the user is new or existing:
// result.additionalUserInfo.isNewUser
})
.catch((error) => {
// Some error occurred, you can inspect the code: error.code
// Common errors could be invalid email and invalid or expired OTPs.
});
}
17 changes: 17 additions & 0 deletions client/src/components/firebase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import firebase from 'firebase/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

const app = firebase.initializeApp ({
apiKey: "AIzaSyA0LLhGRO00T9Cfm1DA15aq2edmTmB6H1Q",
authDomain: "mit-mixer.firebaseapp.com",
projectId: "mit-mixer",
storageBucket: "mit-mixer.appspot.com",
messagingSenderId: "673875830760",
appId: "1:673875830760:web:1db1205d5ee54af68ae65d",
measurementId: "G-4SGZQBDGBN"
});


export const auth = app.auth();
export default app;
45 changes: 45 additions & 0 deletions client/src/components/modules/Chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useState, useEffect } from "react";
import SingleMessage from "../modules/SingleMessage.js";
import { NewMessage } from "./NewPostInput.js";


/**
* @typedef UserObject
* @property {string} _id
* @property {string} name
*/
/**
* @typedef MessageObject
* @property {UserObject} sender
* @property {string} content
*/
/**
* @typedef ChatData
* @property {MessageObject[]} messages
* @property {UserObject} recipient
*/

/**
* Renders main chat window including previous messages,
* who is being chatted with, and the new message input.
*
* Proptypes
* @param {ChatData} data
*/
const Chat = (props) => {
return (
<div className="u-flexColumn Chat-container">
<h3>Chatting with {props.data.recipient.name}</h3>
<div className="Chat-historyContainer">
{props.data.messages.map((m, i) => (
<SingleMessage message={m} key={i} />
))}
</div>
<div className="Chat-newContainer">
<NewMessage recipient={props.data.recipient} />
</div>
</div>
);
}

export default Chat;
66 changes: 66 additions & 0 deletions client/src/components/modules/NewPostInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useState } from "react";

import { post } from "../../utilities";

/**
* New Post is a parent component for all input components
*
* Proptypes
* @param {string} defaultText is the placeholder text
* @param {string} storyId optional prop, used for comments
* @param {({storyId, value}) => void} onSubmit: (function) triggered when this post is submitted, takes {storyId, value} as parameters
*/
const NewPostInput = (props) => {
const [value, setValue] = useState("");

// called whenever the user types in the new post input box
const handleChange = (event) => {
setValue(event.target.value);
};

// called when the user hits "Submit" for a new post
const handleSubmit = (event) => {
event.preventDefault();
props.onSubmit && props.onSubmit(value);
setValue("");
};

return (
<div className="u-flex">
<input
type="text"
placeholder={props.defaultText}
value={value}
onChange={handleChange}
className="NewPostInput-input"
/>
<button
type="submit"
className="NewPostInput-button u-pointer"
value="Submit"
onClick={handleSubmit}
>
Submit
</button>
</div>
);
};



/**
* New Message is a New Message component for messages
*
* Proptypes
* @param {UserObject} recipient is the intended recipient
*/
const NewMessage = (props) => {
const sendMessage = (value) => {
const body = { recipient: props.recipient, content: value };
post("/api/message", body);
};

return <NewPostInput defaultText="New Message" onSubmit={sendMessage} />;
}

export { NewMessage };
19 changes: 19 additions & 0 deletions client/src/components/modules/SingleMessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useState, useEffect } from "react";


/**
* Renders a single chat message
*
* Proptypes
* @param {MessageObject} message
*/
const SingleMessage = (props) => {
return (
<div className={"u-flex u-flex-alignCenter SingleMessage-container"}>
<span className=" SingleMessage-sender u-bold">{props.message.sender.name + ":"}</span>
<span className="SingleMessage-content">{props.message.content}</span>
</div>
);
}

export default SingleMessage;
74 changes: 74 additions & 0 deletions client/src/components/pages/Chatbook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useEffect, useState } from "react";
import Chat from "../modules/Chat.js";
import { socket } from "../../client-socket.js";
import { get } from "../../utilities";

const ALL_CHAT = {
_id: "ALL_CHAT",
name: "ALL CHAT",
};

const Chatbook = (props) => {
/**
* @typedef UserObject
* @property {string} _id
* @property {string} name
*/
/**
* @typedef MessageObject
* @property {UserObject} sender
* @property {string} content
*/
/**
* @typedef ChatData
* @property {MessageObject[]} messages
* @property {UserObject} recipient
*/

const [activeChat, setActiveChat] = useState({
recipient: ALL_CHAT,
messages: [],
});

const loadMessageHistory = (recipient) => {

get("/api/chat", { recipient_id: recipient._id }).then((messages) => {
setActiveChat({
recipient: recipient,
messages: messages,
});
});
};

useEffect(() => {
document.title = "Chatbook";
}, []);

useEffect(() => {
loadMessageHistory(ALL_CHAT);
}, []);

useEffect(() => {
socket.on("message", addMessages);
return () => {
socket.off("message", addMessage);
};
// TODO (step 6.2): add socket.on for when received message
}, []);

if (!props.userId) {
return <div>Log in before using Chatbook</div>;
}

return (
<>
<div className="u-flex u-relative Chatbook-container">
<div className="Chatbook-chatContainer u-relative">
<Chat data={activeChat} />
</div>
</div>
</>
);
}

export default Chatbook;
Loading