Merge branch 'master' into engage_microblog

This commit is contained in:
asankaran35 2019-11-27 21:08:55 -05:00 committed by GitHub
commit 1a2af4e9bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 661 additions and 284 deletions

View File

@ -1,20 +1,28 @@
const { admin, db } = require("../util/admin"); const { admin, db } = require("../util/admin");
exports.putTopic = (req, res) => { exports.putTopic = (req, res) => {
const newTopic = { let new_following = [];
topic: req.body.topic let userRef = db.doc(`/users/${req.userData.handle}`);
}; userRef
.get()
admin
.firestore()
.collection("topics")
.add(newTopic)
.then(doc => { .then(doc => {
const resTopic = newTopic; new_following = doc.data().followedTopics;
return res.status(200).json(resTopic); new_following.push(req.body.following);
// add stuff
userRef
.set({ followedTopics: new_following }, { merge: true })
.then(doc => {
return res
.status(201)
.json({ message: `Following ${req.body.following}` });
}) })
.catch(err => { .catch(err => {
console.error(err); return res.status(500).json({ err });
return res.status(500).json({ error: "something is wrong" }); });
return res.status(200).json({ message: "OK" });
})
.catch(err => {
return res.status(500).json({ err });
}); });
}; };
@ -40,21 +48,46 @@ exports.getAllTopics = (req, res) => {
}; };
exports.deleteTopic = (req, res) => { exports.deleteTopic = (req, res) => {
const topic = db.doc(`/topics/${req.params.topicId}`); let new_following = [];
topic let userRef = db.doc(`/users/${req.userData.handle}`);
userRef
.get() .get()
.then(doc => { .then(doc => {
if (!doc.exists) { new_following = doc.data().followedTopics;
return res.status(404).json({ error: "Topic not found" }); // remove username from array
} else { new_following.forEach(function(follower, index) {
return topic.delete(); if (follower === `${req.body.unfollow}`) {
new_following.splice(index, 1);
} }
}) });
.then(() => {
return res.json({ message: "Topic successfully deleted!" }); // update database
userRef
.set({ followedTopics: new_following }, { merge: true })
.then(doc => {
return res
.status(202)
.json({ message: `Successfully unfollow ${req.body.unfollow}` });
}) })
.catch(err => { .catch(err => {
console.error(err); return res.status(500).json({ err });
return res.status(500).json({ error: "Failed to delete topic." }); });
return res.status(200).json({ message: "ok" });
})
.catch(err => {
return res.status(500).json({ err });
});
};
exports.getUserTopics = (req, res) => {
let data = [];
db.doc(`/users/${req.body.handle}`)
.get()
.then(doc => {
data = doc.data().followedTopics;
return res.status(200).json({ data });
})
.catch(err => {
return res.status(500).json({ err });
}); });
}; };

View File

@ -201,9 +201,9 @@ exports.deleteUser = (req, res) => {
// Get the profile image filename // Get the profile image filename
// `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media` // `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`
let imageFileName; let imageFileName;
req.userData.imageUrl ? req.userData.imageUrl
imageFileName = req.userData.imageUrl.split('/o/')[1].split('?alt=')[0] : ? (imageFileName = req.userData.imageUrl.split("/o/")[1].split("?alt=")[0])
imageFileName = 'no-img.png' : (imageFileName = "no-img.png");
const userId = req.userData.userId; const userId = req.userData.userId;
let errors = {}; let errors = {};
@ -221,56 +221,58 @@ exports.deleteUser = (req, res) => {
let auth = admin.auth().deleteUser(userId); let auth = admin.auth().deleteUser(userId);
// Deletes database data // Deletes database data
let data = db.collection("users").doc(`${req.user.handle}`).delete(); let data = db
.collection("users")
.doc(`${req.user.handle}`)
.delete();
// Deletes any custom profile image // Deletes any custom profile image
let image; let image;
if (imageFileName !== 'no-img.png') { if (imageFileName !== "no-img.png") {
image = admin.storage().bucket().file(imageFileName).delete() image = admin
.storage()
.bucket()
.file(imageFileName)
.delete();
} else { } else {
image = Promise.resolve(); image = Promise.resolve();
} }
// Deletes all users posts // Deletes all users posts
let posts = db.collection("posts") let posts = db
.collection("posts")
.where("userHandle", "==", req.user.handle) .where("userHandle", "==", req.user.handle)
.get() .get()
.then((query) => { .then(query => {
query.forEach((snap) => { query.forEach(snap => {
snap.ref.delete(); snap.ref.delete();
}); });
return; return;
}) });
let promises = [ let promises = [
auth auth.then(thenFunction("auth")).catch(err => catchFunction("auth", err)),
.then(thenFunction('auth')) data.then(thenFunction("data")).catch(err => catchFunction("data", err)),
.catch((err) => catchFunction('auth', err)), image.then(thenFunction("image")).catch(err => catchFunction("image", err)),
data posts.then(thenFunction("posts")).catch(err => catchFunction("image", err))
.then(thenFunction('data'))
.catch((err) => catchFunction('data', err)),
image
.then(thenFunction('image'))
.catch((err) => catchFunction('image', err)),
posts
.then(thenFunction('posts'))
.catch((err) => catchFunction('image', err))
]; ];
// Wait for all promises to resolve // Wait for all promises to resolve
let waitPromise = Promise.all(promises); let waitPromise = Promise.all(promises);
waitPromise.then(() => { waitPromise
.then(() => {
if (Object.keys(errors) > 0) { if (Object.keys(errors) > 0) {
return res.status(500).json(errors); return res.status(500).json(errors);
} else { } else {
return res.status(200).json({message: `All data for ${req.userData.handle} has been deleted.`}); return res.status(200).json({
message: `All data for ${req.userData.handle} has been deleted.`
});
} }
}) })
.catch((err) => { .catch(err => {
return res.status(500).json({ error: err }); return res.status(500).json({ error: err });
}) });
}; };
// Returns all data in the database for the user who is currently signed in // Returns all data in the database for the user who is currently signed in
@ -356,23 +358,29 @@ exports.verifyUser = (req, res) => {
db.doc(`/users/${req.body.user}`) db.doc(`/users/${req.body.user}`)
.get() .get()
.then((doc) => { .then(doc => {
if (doc.exists) { if (doc.exists) {
let verifiedUser = doc.data(); let verifiedUser = doc.data();
verifiedUser.verified = true; verifiedUser.verified = true;
return db.doc(`/users/${req.body.user}`).set(verifiedUser, {merge: true}); return db
.doc(`/users/${req.body.user}`)
.set(verifiedUser, { merge: true });
} else { } else {
return res.status(400).json({error: `User ${req.body.user} was not found`}); return res
.status(400)
.json({ error: `User ${req.body.user} was not found` });
} }
}) })
.then(() => { .then(() => {
return res.status(201).json({message: `${req.body.user} is now verified`}); return res
.status(201)
.json({ message: `${req.body.user} is now verified` });
}) })
.catch((err) => { .catch(err => {
console.error(err); console.error(err);
return res.status(500).json({ error: err.code }); return res.status(500).json({ error: err.code });
}); });
} };
// Unverifies the user sent to the request // Unverifies the user sent to the request
// Must be run by admin // Must be run by admin
@ -383,37 +391,104 @@ exports.unverifyUser = (req, res) => {
db.doc(`/users/${req.body.user}`) db.doc(`/users/${req.body.user}`)
.get() .get()
.then((doc) => { .then(doc => {
if (doc.exists) { if (doc.exists) {
let unverifiedUser = doc.data(); let unverifiedUser = doc.data();
unverifiedUser.verified = false; unverifiedUser.verified = false;
return db.doc(`/users/${req.body.user}`).set(unverifiedUser, {merge: true}); return db
.doc(`/users/${req.body.user}`)
.set(unverifiedUser, { merge: true });
} else { } else {
return res.status(400).json({error: `User ${req.body.user} was not found`}); return res
.status(400)
.json({ error: `User ${req.body.user} was not found` });
} }
}) })
.then(() => { .then(() => {
return res.status(201).json({message: `${req.body.user} is no longer verified`}); return res
.status(201)
.json({ message: `${req.body.user} is no longer verified` });
}) })
.catch((err) => { .catch(err => {
console.error(err); console.error(err);
return res.status(500).json({ error: err.code }); return res.status(500).json({ error: err.code });
}); });
} };
exports.getUserHandles = (req, res) => { exports.getUserHandles = (req, res) => {
admin db.doc(`/users/${req.body.userHandle}`)
.firestore()
.collection("users")
.get() .get()
.then(data => { .then(doc => {
let users = []; if (doc.exists) {
data.forEach(function(doc) { let userHandle = doc.data().handle;
users.push(doc.data().handle); return res.status(200).json(userHandle);
}); } else {
return res.status(200).json(users); return res.status(404).json({ error: "user not found" });
}
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
return res.status(500).json({ error: "Failed to get all user handles." }); return res.status(500).json({ error: "Failed to get all user handles." });
}); });
}; };
exports.addSubscription = (req, res) => {
let new_following = [];
let userRef = db.doc(`/users/${req.userData.handle}`);
userRef.get().then(doc => {
new_following = doc.data().following;
new_following.push(req.body.following);
// add stuff
userRef
.set({ following: new_following }, { merge: true })
.then(doc => {
return res
.status(201)
.json({ message: `Following ${req.body.following}` });
})
.catch(err => {
return res.status(500).json({ err });
});
return res.status(500).json({ error: "shouldn't execute" });
});
};
exports.getSubs = (req, res) => {
let data = [];
db.doc(`/users/${req.userData.handle}`)
.get()
.then(doc => {
data = doc.data().following;
return res.status(200).json({ data });
})
.catch(err => {
return res.status(500).json({ err });
});
};
exports.removeSub = (req, res) => {
let new_following = [];
let userRef = db.doc(`/users/${req.userData.handle}`);
userRef.get().then(doc => {
new_following = doc.data().following;
// remove username from array
new_following.forEach(function(follower, index) {
if (follower === `${req.body.unfollow}`) {
new_following.splice(index, 1);
}
});
// update database
userRef
.set({ following: new_following }, { merge: true })
.then(doc => {
return res
.status(202)
.json({ message: `Successfully unfollow ${req.body.unfollow}` });
})
.catch(err => {
return res.status(500).json({ err });
});
return res.status(500).json({ error: "shouldn't execute" });
});
};

View File

@ -19,7 +19,10 @@ const {
updateProfileInfo, updateProfileInfo,
verifyUser, verifyUser,
unverifyUser, unverifyUser,
getUserHandles getUserHandles,
addSubscription,
getSubs,
removeSub
} = require("./handlers/users"); } = require("./handlers/users");
// Adds a user to the database and registers them in firebase with // Adds a user to the database and registers them in firebase with
@ -34,7 +37,7 @@ app.post("/login", login);
//Deletes user account //Deletes user account
app.delete("/delete", fbAuth, deleteUser); app.delete("/delete", fbAuth, deleteUser);
app.get("/getUser", fbAuth, getUserDetails); app.post("/getUserDetails", fbAuth, getUserDetails);
// Returns all profile data of the currently logged in user // Returns all profile data of the currently logged in user
app.get("/getProfileInfo", fbAuth, getProfileInfo); app.get("/getProfileInfo", fbAuth, getProfileInfo);
@ -53,7 +56,16 @@ app.post("/verifyUser", fbAuth, verifyUser);
app.post("/unverifyUser", fbAuth, unverifyUser); app.post("/unverifyUser", fbAuth, unverifyUser);
// get user handles with search phase // get user handles with search phase
app.get("/getUserHandles", fbAuth, getUserHandles); app.post("/getUserHandles", fbAuth, getUserHandles);
// get user's subscription
app.get("/getSubs", fbAuth, getSubs);
// add user to another user's "following" data field
app.post("/addSubscription", fbAuth, addSubscription);
// remove one subscription
app.post("/removeSub", fbAuth, removeSub);
/*------------------------------------------------------------------* /*------------------------------------------------------------------*
* handlers/post.js * * handlers/post.js *
@ -78,7 +90,12 @@ app.post("/quoteWithoutPost/:postId", fbAuth, quoteWithoutPost);
/*------------------------------------------------------------------* /*------------------------------------------------------------------*
* handlers/topic.js * * handlers/topic.js *
*------------------------------------------------------------------*/ *------------------------------------------------------------------*/
const { putTopic, getAllTopics, deleteTopic } = require("./handlers/topic"); const {
putTopic,
getAllTopics,
deleteTopic,
getUserTopics
} = require("./handlers/topic");
// add topic to database // add topic to database
app.post("/putTopic", fbAuth, putTopic); app.post("/putTopic", fbAuth, putTopic);
@ -87,6 +104,9 @@ app.post("/putTopic", fbAuth, putTopic);
app.get("/getAllTopics", fbAuth, getAllTopics); app.get("/getAllTopics", fbAuth, getAllTopics);
// delete a specific topic // delete a specific topic
app.delete("/deleteTopic/:topicId", fbAuth, deleteTopic); app.post("/deleteTopic", fbAuth, deleteTopic);
// get topic for this user
app.post("/getUserTopics", fbAuth, getUserTopics);
exports.api = functions.https.onRequest(app); exports.api = functions.https.onRequest(app);

View File

@ -19,8 +19,6 @@ import { logoutUser, getUserData } from "./redux/actions/userActions";
// Components // Components
import AuthRoute from "./util/AuthRoute"; import AuthRoute from "./util/AuthRoute";
// axios.defaults.baseURL = 'http://localhost:5006/twistter-e4649/us-central1/api';
// Pages // Pages
import home from "./pages/Home"; import home from "./pages/Home";
import signup from "./pages/Signup"; import signup from "./pages/Signup";
@ -33,6 +31,7 @@ import editProfile from "./pages/editProfile";
import userLine from "./Userline.js"; import userLine from "./Userline.js";
import verify from "./pages/verify"; import verify from "./pages/verify";
import Search from "./pages/Search.js"; import Search from "./pages/Search.js";
import otherUser from "./pages/otherUser";
const theme = createMuiTheme(themeObject); const theme = createMuiTheme(themeObject);
@ -65,7 +64,6 @@ class App extends Component {
</div> </div>
<div className="app"> <div className="app">
<Switch> <Switch>
{/* AuthRoute checks if the user is logged in and if they are it redirects them to /home */} {/* AuthRoute checks if the user is logged in and if they are it redirects them to /home */}
<AuthRoute exact path="/signup" component={signup} /> <AuthRoute exact path="/signup" component={signup} />
<AuthRoute exact path="/login" component={login} /> <AuthRoute exact path="/login" component={login} />
@ -79,9 +77,9 @@ class App extends Component {
<Route exact path="/edit" component={editProfile} /> <Route exact path="/edit" component={editProfile} />
<Route exact path="/verify" component={verify} /> <Route exact path="/verify" component={verify} />
<Route exact path="/search" component={Search} /> <Route exact path="/search" component={Search} />
<Route exact path="/user/:userhandle" component={otherUser} />
<AuthRoute exact path="/" component={home} /> <AuthRoute exact path="/" component={home} />
</Switch> </Switch>
</div> </div>
</Router> </Router>

View File

@ -1,17 +1,17 @@
/* eslint-disable */ /* eslint-disable */
import React, { Component } from 'react'; import React, { Component } from "react";
import { Link } from 'react-router-dom'; import { Link } from "react-router-dom";
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
// Material UI stuff // Material UI stuff
import AppBar from '@material-ui/core/AppBar'; import AppBar from "@material-ui/core/AppBar";
import ToolBar from '@material-ui/core/Toolbar'; import ToolBar from "@material-ui/core/Toolbar";
import Button from '@material-ui/core/Button'; import Button from "@material-ui/core/Button";
import withStyles from "@material-ui/core/styles/withStyles"; import withStyles from "@material-ui/core/styles/withStyles";
// Redux stuff // Redux stuff
import { logoutUser } from '../../redux/actions/userActions'; import { logoutUser } from "../../redux/actions/userActions";
import { connect } from 'react-redux'; import { connect } from "react-redux";
const styles = { const styles = {
form: { form: {
@ -38,34 +38,47 @@ export class Navbar extends Component {
return ( return (
<AppBar> <AppBar>
<ToolBar> <ToolBar>
<Button component={ Link } to='/'> <Button component={Link} to="/">
Home Home
</Button> </Button>
{authenticated && <Button component={ Link } to='/user'> {authenticated && (
<Button component={Link} to="/user">
Profile Profile
</Button>} </Button>
{!authenticated && <Button component={ Link } to='/login'> )}
{!authenticated && (
<Button component={Link} to="/login">
Login Login
</Button>} </Button>
{!authenticated && <Button component={ Link } to='/signup'> )}
{!authenticated && (
<Button component={Link} to="/signup">
Sign Up Sign Up
</Button>} </Button>
{authenticated && <Button component={ Link } to='/logout'> )}
{authenticated && (
<Button component={Link} to="/search">
Search
</Button>
)}
{authenticated && (
<Button component={Link} to="/logout">
Logout Logout
</Button>} </Button>
)}
</ToolBar> </ToolBar>
</AppBar> </AppBar>
) );
} }
} }
const mapStateToProps = (state) => ({ const mapStateToProps = state => ({
user: state.user user: state.user
}) });
Navbar.propTypes = { Navbar.propTypes = {
user: PropTypes.object.isRequired, user: PropTypes.object.isRequired,
classes: PropTypes.object.isRequired classes: PropTypes.object.isRequired
} };
export default connect(mapStateToProps)(withStyles(styles)(Navbar)); export default connect(mapStateToProps)(withStyles(styles)(Navbar));

View File

@ -1,17 +1,10 @@
import React, { Component } from "react"; import React, { Component } from "react";
// import props // import props
import { TextField, Paper } from "@material-ui/core"; import { TextField, Button } from "@material-ui/core";
import Grid from "@material-ui/core/Grid"; import Grid from "@material-ui/core/Grid";
import Axios from "axios"; import Axios from "axios";
import user from "./user.js";
import { import { BrowserRouter as Router } from "react-router-dom";
BrowserRouter as Router,
Switch,
Route,
Link,
useRouteMatch
} from "react-router-dom";
export class Search extends Component { export class Search extends Component {
state = { state = {
@ -19,20 +12,28 @@ export class Search extends Component {
searchResult: null searchResult: null
}; };
handleSearch(event) { handleSearch = () => {
Axios.get("/getUserHandles").then(res => { console.log(this.state.searchPhase);
Axios.post("/getUserHandles", {
userHandle: this.state.searchPhase
})
.then(res => {
console.log(res);
this.setState({ this.setState({
searchResult: res.data searchResult: res.data
}); });
})
.catch(err => {
console.log(err);
}); });
console.log(this.state.searchPhase); };
}
handleInput(event) { handleInput(event) {
this.setState({ this.setState({
searchPhase: event.target.value searchPhase: event.target.value
}); });
this.handleSearch(); console.log(this.state.searchPhase);
} }
handleRedirect() { handleRedirect() {
@ -41,16 +42,16 @@ export class Search extends Component {
render() { render() {
let resultMarkup = this.state.searchResult ? ( let resultMarkup = this.state.searchResult ? (
this.state.searchResult.map(result => (
<Router> <Router>
<div> <div>
<Link to={`/user`}>{result}</Link> <a href={`/user/${this.state.searchResult}`}>
{this.state.searchResult}
</a>
</div> </div>
</Router> </Router>
))
) : ( ) : (
// console.log(this.state.searchResult) // console.log(this.state.searchResult)
<p> searching... </p> <p> No result </p>
); );
return ( return (
@ -65,6 +66,11 @@ export class Search extends Component {
onChange={event => this.handleInput(event)} onChange={event => this.handleInput(event)}
/> />
</Grid> </Grid>
<Grid>
<Button color="primary" onClick={this.handleSearch}>
Search
</Button>
</Grid>
<Grid>{resultMarkup}</Grid> <Grid>{resultMarkup}</Grid>
</Grid> </Grid>
); );

View File

@ -0,0 +1,158 @@
/* eslint-disable */
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import axios from "axios";
//import '../App.css';
// Material UI and React Router
import { makeStyles, styled } from "@material-ui/core/styles";
import { Link } from "react-router-dom";
import Card from "@material-ui/core/Card";
import CardMedia from "@material-ui/core/CardMedia";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import Grid from "@material-ui/core/Grid";
import Chip from "@material-ui/core/Chip";
import Typography from "@material-ui/core/Typography";
import AddCircle from "@material-ui/icons/AddCircle";
import TextField from "@material-ui/core/TextField";
import VerifiedIcon from "@material-ui/icons/CheckSharp";
// component
import "../App.css";
import noImage from "../images/no-img.png";
import Writing_Microblogs from "../Writing_Microblogs";
const MyChip = styled(Chip)({
margin: 2,
color: "primary"
});
class user extends Component {
state = {
profile: window.location.pathname.split("/").pop(),
imageUrl: null,
topics: null,
user: null,
following: null
};
handleSub = () => {
if (this.state.following === true) {
axios
.post("/removeSub", {
unfollow: this.state.profile
})
.then(res => {
console.log("removed sub");
this.setState({
following: false
});
})
.catch(function(err) {
console.log(err);
});
} else {
axios
.post("/addSubscription", {
following: this.state.profile
})
.then(res => {
console.log("adding sub");
this.setState({
following: true
});
})
.catch(function(err) {
console.log(err);
});
}
};
componentDidMount() {
axios
.post("/getUserDetails", {
handle: this.state.profile
})
.then(res => {
this.setState({
imageUrl: res.data.userData.imageUrl,
topics: res.data.userData.followedTopics
});
})
.catch(err => console.log(err));
axios
.get("/user")
.then(res => {
this.setState({
following: res.data.credentials.following.includes(this.state.profile)
});
})
.catch(err => console.log(err));
}
render() {
let profileMarkup = this.state.profile ? (
<div>
<Typography variant="h5">
@{this.state.profile}{" "}
{this.state.verified ? (
<VerifiedIcon style={{ fill: "#1397D5" }} />
) : null}
</Typography>
</div>
) : (
<p>loading username...</p>
);
let topicsMarkup = this.state.topics ? (
this.state.topics.map(
topic => <MyChip label={topic} key={{ topic }.topic.id} /> // console.log({ topic }.topic.id)
)
) : (
<p> loading topics...</p>
);
let imageMarkup = this.state.imageUrl ? (
<img src={this.state.imageUrl} height="150" width="150" />
) : (
<img src={noImage} height="150" width="150" />
);
let followMarkup = this.state.following ? (
<Button variant="contained" color="primary" onClick={this.handleSub}>
unfollow
</Button>
) : (
<Button variant="contained" color="primary" onClick={this.handleSub}>
follow
</Button>
);
console.log(this.state.following);
return (
<Grid container spacing={24}>
<Grid item sm={4} xs={8}>
{imageMarkup}
{profileMarkup}
{followMarkup}
{topicsMarkup}
<br />
</Grid>
</Grid>
);
}
}
const mapStateToProps = state => ({
user: state.user
});
user.propTypes = {
user: PropTypes.object.isRequired
};
export default connect(mapStateToProps)(user);

View File

@ -1,34 +1,74 @@
/* eslint-disable */ /* eslint-disable */
import React, { Component } from 'react'; import React, { Component } from "react";
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
import { connect } from 'react-redux'; import { connect } from "react-redux";
import axios from 'axios'; import axios from "axios";
//import '../App.css'; //import '../App.css';
// Material-UI
// Material UI and React Router import withStyles from "@material-ui/core/styles/withStyles";
import { makeStyles, styled } from "@material-ui/core/styles"; import { makeStyles, styled } from "@material-ui/core/styles";
import { Link } from 'react-router-dom'; import { Link } from "react-router-dom";
import Card from "@material-ui/core/Card"; import Card from "@material-ui/core/Card";
import CardMedia from '@material-ui/core/CardMedia'; import CardMedia from "@material-ui/core/CardMedia";
import CardContent from '@material-ui/core/CardContent'; import CardContent from "@material-ui/core/CardContent";
import Button from '@material-ui/core/Button'; import Button from "@material-ui/core/Button";
import Grid from "@material-ui/core/Grid"; import Grid from "@material-ui/core/Grid";
import Chip from "@material-ui/core/Chip"; import Chip from "@material-ui/core/Chip";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import AddCircle from '@material-ui/icons/AddCircle'; import AddCircle from "@material-ui/icons/AddCircle";
import TextField from '@material-ui/core/TextField'; import TextField from "@material-ui/core/TextField";
import VerifiedIcon from '@material-ui/icons/CheckSharp'; import VerifiedIcon from "@material-ui/icons/CheckSharp";
import Paper from "@material-ui/core/Paper";
import GridList from "@material-ui/core/GridList";
import GridListTile from "@material-ui/core/GridListTile";
import GridListTileBar from "@material-ui/core/GridListTileBar";
import Container from "@material-ui/core/Container";
// component // component
import '../App.css'; import "../App.css";
import noImage from '../images/no-img.png'; import noImage from "../images/no-img.png";
import Writing_Microblogs from '../Writing_Microblogs'; import Writing_Microblogs from "../Writing_Microblogs";
const MyChip = styled(Chip)({ const MyChip = styled(Chip)({
margin: 2, margin: 2,
color: "primary" color: "primary"
}); });
const styles = {
button: {
positon: "relative",
float: "left",
marginLeft: 30,
marginTop: 20
},
paper: {
// marginLeft: "10%",
// marginRight: "10%"
},
card: {
marginBottom: 10
},
profileImage: {
marginTop: 20
},
topicsContainer: {
border: "lightgray solid 1px",
marginTop: 20,
paddingTop: 10,
paddingBottom: 10,
height: 300
},
addCircle: {
width: 65,
height: 65,
marginTop: 10
},
username: {
marginBottom: 100
}
};
class user extends Component { class user extends Component {
state = { state = {
profile: null, profile: null,
@ -38,8 +78,11 @@ class user extends Component {
}; };
handleDelete = topic => { handleDelete = topic => {
console.log(topic);
axios axios
.delete(`/deleteTopic/${topic.id}`) .post(`/deleteTopic`, {
unfollow: topic
})
.then(function() { .then(function() {
location.reload(); location.reload();
}) })
@ -51,7 +94,7 @@ class user extends Component {
handleAddCircle = () => { handleAddCircle = () => {
axios axios
.post("/putTopic", { .post("/putTopic", {
topic: this.state.newTopic following: this.state.newTopic
}) })
.then(function() { .then(function() {
location.reload(); location.reload();
@ -74,16 +117,10 @@ class user extends Component {
this.setState({ this.setState({
profile: res.data.credentials.handle, profile: res.data.credentials.handle,
imageUrl: res.data.credentials.imageUrl, imageUrl: res.data.credentials.imageUrl,
verified: res.data.credentials.verified ? res.data.credentials.verified : false verified: res.data.credentials.verified
}); ? res.data.credentials.verified
}) : false,
.catch(err => console.log(err)); topics: res.data.credentials.followedTopics
axios
.get("/getAllTopics")
.then(res => {
this.setState({
topics: res.data
}); });
}) })
.catch(err => console.log(err)); .catch(err => console.log(err));
@ -91,7 +128,7 @@ class user extends Component {
axios axios
.get("/getallPostsforUser") .get("/getallPostsforUser")
.then(res => { .then(res => {
console.log(res.data); // console.log(res.data);
this.setState({ this.setState({
posts: res.data posts: res.data
}) })
@ -103,20 +140,28 @@ class user extends Component {
} }
render() { render() {
const { classes } = this.props;
let authenticated = this.props.user.authenticated; let authenticated = this.props.user.authenticated;
let classes = this.props;
let profileMarkup = this.state.profile ? ( let profileMarkup = this.state.profile ? (
<div> <div>
<Typography variant='h5'>@{this.state.profile} {this.state.verified ? (<VerifiedIcon style={{fill: "#1397D5"}}/>): (null)}</Typography> <Typography variant="h5" className={classes.username}>
</div>) : (<p>loading username...</p>); @{this.state.profile}{" "}
{this.state.verified ? (
<VerifiedIcon style={{ fill: "#1397D5" }} />
) : null}
</Typography>
</div>
) : (
<p className={classes.username}>loading username...</p>
);
let topicsMarkup = this.state.topics ? ( let topicsMarkup = this.state.topics ? (
this.state.topics.map( this.state.topics.map(
topic => ( topic => (
<MyChip <MyChip
label={{ topic }.topic.topic} label={topic}
key={{ topic }.topic.id} key={topic.id}
onDelete={key => this.handleDelete(topic)} onDelete={key => this.handleDelete(topic)}
/> />
) // console.log({ topic }.topic.id) ) // console.log({ topic }.topic.id)
@ -125,26 +170,47 @@ class user extends Component {
<p> loading topics...</p> <p> loading topics...</p>
); );
let imageMarkup = this.state.imageUrl ? (<img src={this.state.imageUrl} height="150" width="150" />) : let imageMarkup = this.state.imageUrl ? (
(<img src={noImage} height="150" width="150"/>); <img
className={classes.profileImage}
src={this.state.imageUrl}
height="250"
width="250"
/>
) : (
<img
className={classes.profileImage}
src={noImage}
height="250"
width="250"
/>
);
let postMarkup = this.state.posts ? ( let postMarkup = this.state.posts ? (
this.state.posts.map(post => this.state.posts.map(post => (
<Card> <Card className={classes.card}>
<CardContent> <CardContent>
<Typography> <Typography>
{ {this.state.imageUrl ? (
this.state.imageUrl ? (<img src={this.state.imageUrl} height="250" width="250" />) : <img src={this.state.imageUrl} height="50" width="50" />
(<img src={noImage} height="50" width="50"/>) ) : (
} <img src={noImage} height="50" width="50" />
)}
</Typography> </Typography>
<Typography variant="h7">
<b>{post.userHandle}</b>
</Typography>
<Typography variant="body2" color={"textSecondary"}>
{post.createdAt}
</Typography>
<Typography variant="h7"><b>{post.userHandle}</b></Typography> <Typography variant="h7"><b>{post.userHandle}</b></Typography>
<Typography variant="body2" color={"textSecondary"}>{post.createdAt.substring(0,10) + <Typography variant="body2" color={"textSecondary"}>{post.createdAt.substring(0,10) +
" " + post.createdAt.substring(11,19)}</Typography> " " + post.createdAt.substring(11,19)}</Typography>
<br /> <br />
<Typography variant="body1"><b>{post.microBlogTitle}</b></Typography> <Typography variant="body1">
<b>{post.microBlogTitle}</b>
</Typography>
<Typography variant="body2">{post.body}</Typography> <Typography variant="body2">{post.body}</Typography>
<br /> <br />
<Typography variant="body2"><b>Topics:</b> {post.microBlogTopics.join("," + " ")}</Typography> <Typography variant="body2"><b>Topics:</b> {post.microBlogTopics.join("," + " ")}</Typography>
@ -152,15 +218,48 @@ class user extends Component {
<Typography variant="body2" color={"textSecondary"}>Likes {post.likeCount}</Typography> <Typography variant="body2" color={"textSecondary"}>Likes {post.likeCount}</Typography>
</CardContent> </CardContent>
</Card> </Card>
) ))
) : (<p>My Posts</p>); ) : (
<p>My Posts</p>
);
// FIX: This needs to check if user's profile page being displayed
// is the same as the user who is logged in
// Can't check for that right now, because this page is always
// showing the logged in users profile, instead of retreiving the
// profile based on the URL entered
let editButtonMarkup = true ? (
<Link to="/edit">
<Button className={classes.button} variant="outlined" color="primary">
Edit Profile
</Button>
</Link>
) : null;
return ( return (
<Grid container spacing={24}> <div>
<Grid item sm={4} xs={8}> {/* <Paper className={classes.paper}> */}
<Grid container direction="column">
<Grid item>
<Grid container>
<Grid item sm>
{editButtonMarkup}
</Grid>
<Grid item sm>
{/* <Grid container direction="column"> */}
{/* <Grid item sm> */}
{imageMarkup} {imageMarkup}
{profileMarkup} {profileMarkup}
{/* </Grid> */}
{/* <Grid item sm> */}
{/* {postMarkup} */}
{/* </Grid> */}
{/* </Grid> */}
</Grid>
<Grid item sm>
<Container className={classes.topicsContainer} maxWidth="xs">
{topicsMarkup} {topicsMarkup}
</Container>
<TextField <TextField
id="newTopic" id="newTopic"
label="new topic" label="new topic"
@ -168,63 +267,38 @@ class user extends Component {
margin="normal" margin="normal"
variant="outlined" variant="outlined"
value={this.state.newTopic} value={this.state.newTopic}
onChange={(event) => this.handleChange(event)} onChange={event => this.handleChange(event)}
/> />
<AddCircle <AddCircle
className={classes.addCircle}
color="primary" color="primary"
// iconStyle={classes.addCircle}
clickable clickable
onClick={this.handleAddCircle} onClick={this.handleAddCircle}
cursor="pointer"
/> />
<br /> </Grid>
<Grid container direction="column"> </Grid>
<Grid item>
{
authenticated &&
<Button
style={{width:150, marginBottom: 10, marginTop: 5}}
component={ Link }
to='/edit'
variant="outlined"
color="primary"
>
Edit Profile
</Button>}
</Grid> </Grid>
<Grid item> <Grid item>
{ <Grid container>
authenticated && <Grid item sm />
this.state.profile === 'Admin' && <Grid item>{postMarkup}</Grid>
<Button <Grid item sm />
style={{width:150}}
component={ Link }
variant="outlined"
color="primary"
to='/verify'
>
Verify Users
</Button>}
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>
<Grid item sm={4} xs={8}> </div>
{postMarkup}
</Grid>
<Grid item sm={4} xs={8}>
<Writing_Microblogs />
</Grid>
      
</Grid>
); );
} }
} }
const mapStateToProps = (state) => ({ const mapStateToProps = state => ({
user: state.user user: state.user
}) });
user.propTypes = { user.propTypes = {
user: PropTypes.object.isRequired user: PropTypes.object.isRequired
} };
export default connect(mapStateToProps)(user); export default connect(mapStateToProps)(withStyles(styles)(user));