Merge branch 'master' into dms

This commit is contained in:
Clayton Wilson 2019-12-03 13:21:30 -05:00 committed by GitHub
commit 09a3ccd12d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 184 additions and 87 deletions

View File

@ -333,6 +333,24 @@ exports.getUserDetails = (req, res) => {
});
};
exports.getAllHandles = (req, res) => {
var user_query = admin.firestore().collection("users");
user_query.get()
.then((allUsers) => {
let users = [];
allUsers.forEach((user) => {
users.push(user.data().handle);
});
return res.status(200).json(users);
})
.catch((err) => {
return res.status(500).json({
message:"Failed to retrieve posts from database.",
error: err
});
});
};
exports.getAuthenticatedUser = (req, res) => {
let credentials = {};
db.doc(`/users/${req.user.handle}`)

View File

@ -16,6 +16,7 @@ const {
createDirectMessage,
checkDirectMessagesEnabled,
toggleDirectMessages,
getAllHandles,
getUserDetails,
getProfileInfo,
login,
@ -61,6 +62,10 @@ app.get("/getUser", fbAuth, getUserDetails);
app.post("/getUserDetails", fbAuth, getUserDetails);
// Returns a list of all usernames
// Used for searching
app.get("/getAllHandles", fbAuth, getAllHandles);
// Returns all profile data of the currently logged in user
app.get("/getProfileInfo", fbAuth, getProfileInfo);

View File

@ -11,11 +11,13 @@
"clsx": "^1.0.4",
"create-react-app": "^3.1.2",
"dayjs": "^1.8.17",
"fuse.js": "^3.4.6",
"install": "^0.13.0",
"jwt-decode": "^2.2.0",
"node-pre-gyp": "^0.13.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-modal": "^3.11.1",
"react-redux": "^7.1.1",
"react-router-dom": "^5.1.0",
"react-scripts": "0.9.5",

View File

@ -40,15 +40,28 @@ class Writing_Microblogs extends Component {
};
axios
.post("/putPost", postData, headers)
.post("/putPost", postData, headers) // TODO: add topics
.then(res => {
alert("Post was shared successfully!");
// alert("Post was shared successfully!");
console.log(res.data);
})
.catch(err => {
alert("An error occured.");
console.error(err);
});
console.log(postData.microBlogTopics);
postData.microBlogTopics.forEach(topic => {
axios
.post("/putTopic", {
following: topic
})
.then(res => {
console.log(res.data);
})
.catch(err => {
console.error(err);
});
});
event.preventDefault();
this.setState({ value: "", title: "", characterCount: 250, topics: "" });
}

View File

@ -1,13 +1,13 @@
/* eslint-disable */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import axios from 'axios';
import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import axios from "axios";
// Material UI and React Router
import Grid from '@material-ui/core/Grid';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Grid from "@material-ui/core/Grid";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
// component
@ -31,7 +31,7 @@ class Home extends Component {
console.log(res.data);
this.setState({
posts: res.data
})
});
})
.catch(err => console.log(err));
}
@ -41,17 +41,22 @@ class Home extends Component {
let authenticated = this.props.user.authenticated;
let username = this.props.user.credentials.handle;
let postMarkup = this.state.posts ? (
this.state.posts.map(post =>
this.state.posts.map(post => (
<Card>
<CardContent>
<Typography>
{
this.state.imageUrl ? (<img src={this.state.imageUrl} height="250" width="250" />) :
(<img src={noImage} height="50" width="50"/>)
}
{this.state.imageUrl ? (
<img src={this.state.imageUrl} height="250" width="250" />
) : (
<img src={noImage} height="50" width="50" />
)}
</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="body2" color={"textSecondary"}>{post.createdAt}</Typography>
<br />
<Typography variant="body1"><b>{post.microBlogTitle}</b></Typography>
<Typography variant="body2">{post.quoteBody}</Typography>
@ -65,11 +70,12 @@ class Home extends Component {
<Quote microblog = {post.postId}></Quote>
</CardContent>
</Card>
)
) : (<p>My Posts</p>);
))
) : (
<p>Loading post...</p>
);
return (
authenticated ?
return authenticated ? (
<Grid container spacing={16}>
<Grid item sm={4} xs={8}>
<Writing_Microblogs />
@ -77,26 +83,32 @@ class Home extends Component {
<Grid item sm={4} xs={8}>
{postMarkup}
</Grid>
</Grid>
:
</Grid>
) : (
<div>
<div>
<img src={logo} className="app-logo" alt="logo" />
<br/><br/>
<b>Welcome to Twistter!</b>
<br/><br/>
<b>See the most interesting topics people are following right now.</b>
<br />
<br />
<b>Welcome to Twistter!</b>
<br />
<br />
<b>See the most interesting topics people are following right now.</b>
</div>
<br/><br/><br/><br/>
<br />
<br />
<br />
<br />
<div>
<b>Join today or sign in if you already have an account.</b>
<br/><br/>
<div>
<b>Join today or sign in if you already have an account.</b>
<br />
<br />
<form action="./signup">
<button className="authButtons signup">Sign up</button>
<button className="authButtons signup">Sign up</button>
</form>
<br/>
<br />
<form action="./login">
<button className="authButtons login">Sign in</button>
</form>
@ -106,7 +118,6 @@ class Home extends Component {
}
}
class Quote extends Component {
constructor(props) {
super(props);
@ -319,11 +330,11 @@ class Like extends Component {
const mapStateToProps = (state) => ({
user: state.user
})
});
Home.propTypes = {
user: PropTypes.object.isRequired
}
};
Like.propTypes = {
user: PropTypes.object.isRequired
@ -333,4 +344,4 @@ Quote.propTypes = {
user: PropTypes.object.isRequired
}
export default connect(mapStateToProps)(Home, Like, Quote);
export default connect(mapStateToProps)(Home, Like, Quote);

View File

@ -2,38 +2,75 @@ import React, { Component } from "react";
// import props
import { TextField, Button } from "@material-ui/core";
import Grid from "@material-ui/core/Grid";
import Axios from "axios";
import axios from "axios";
import Fuse from "fuse.js";
import { BrowserRouter as Router } from "react-router-dom";
import CircularProgress from "@material-ui/core/CircularProgress";
const fuseOptions = {
shouldSort: true,
threshold: 0.6,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: []
};
let fuse;
export class Search extends Component {
state = {
searchPhase: null,
searchResult: null
handles: [],
// searchPhrase: null,
searchResult: null,
loading: false
};
handleSearch = () => {
console.log(this.state.searchPhase);
Axios.post("/getUserHandles", {
userHandle: this.state.searchPhase
})
.then(res => {
console.log(res);
this.setState({
searchResult: res.data
});
componentDidMount() {
this.setState({loading: true});
axios.get("/getAllHandles")
.then((res) => {
this.setState({
handles: res.data,
loading: false
}, () => {
console.log(res.data);
fuse = new Fuse(this.state.handles, fuseOptions); // "list" is the item array
})
.catch(err => {
console.log(err);
});
};
})
}
handleInput(event) {
// handleSearch = () => {
// console.log(this.state.searchPhase);
// axios.post("/getUserHandles", {
// userHandle: this.state.searchPhase
// })
// .then(res => {
// console.log(res);
// this.setState({
// searchResult: res.data
// });
// })
// .catch(err => {
// console.log(err);
// });
// };
handleChange = (event) => {
let result = fuse.search(event.target.value);
let parsed = [];
result.forEach((res) => {
console.log(res)
parsed.push(this.state.handles[res])
})
this.setState({
searchPhase: event.target.value
});
console.log(this.state.searchPhase);
searchResult: parsed.length !== 0 ? parsed : "No Results"
})
}
handleRedirect() {
@ -41,38 +78,49 @@ export class Search extends Component {
}
render() {
let resultMarkup = this.state.searchResult ? (
<Router>
<div>
<a href={`/user/${this.state.searchResult}`}>
{this.state.searchResult}
</a>
</div>
</Router>
) : (
// console.log(this.state.searchResult)
<p> No result </p>
);
let resultMarkup = this.state.searchResult && this.state.searchResult !== "No Results" ? (
this.state.searchResult.map(res =>
<Router>
<div>
<a href={`/user/${res}`}>
{res}
</a>
</div>
</Router>
)
)
:
this.state.searchResult === "No Results" ?
(
<p> No results </p>
)
:
(
null
)
return (
<Grid>
this.state.loading
?
<CircularProgress size={60} style={{marginTop: "300px"}}></CircularProgress>
:
<Grid>
<TextField
id="standard-required"
label="Search"
defaultValue="username"
margin="normal"
value={this.state.searchPhase}
onChange={event => this.handleInput(event)}
/>
<Grid>
<TextField
id="standard-required"
label="Username"
margin="normal"
// value={this.state.searchPhrase}
onChange={this.handleChange}
/>
</Grid>
<Grid>
{/* <Button color="primary" onClick={this.handleSearch}>
Search
</Button> */}
</Grid>
<Grid>{resultMarkup}</Grid>
</Grid>
<Grid>
<Button color="primary" onClick={this.handleSearch}>
Search
</Button>
</Grid>
<Grid>{resultMarkup}</Grid>
</Grid>
);
}
}