diff --git a/functions/handlers/users.js b/functions/handlers/users.js index 5350d19..3430fff 100644 --- a/functions/handlers/users.js +++ b/functions/handlers/users.js @@ -331,6 +331,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}`) diff --git a/functions/index.js b/functions/index.js index ee203eb..eab8aa9 100644 --- a/functions/index.js +++ b/functions/index.js @@ -11,6 +11,7 @@ app.use(cors()); *------------------------------------------------------------------*/ const { getAuthenticatedUser, + getAllHandles, getUserDetails, getProfileInfo, login, @@ -39,6 +40,10 @@ app.delete("/delete", fbAuth, deleteUser); 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); diff --git a/twistter-frontend/package.json b/twistter-frontend/package.json index a0cec16..52e50f3 100644 --- a/twistter-frontend/package.json +++ b/twistter-frontend/package.json @@ -10,11 +10,13 @@ "axios": "^0.19.0", "clsx": "^1.0.4", "create-react-app": "^3.1.2", + "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", diff --git a/twistter-frontend/src/Writing_Microblogs.js b/twistter-frontend/src/Writing_Microblogs.js index 040875a..2283e61 100644 --- a/twistter-frontend/src/Writing_Microblogs.js +++ b/twistter-frontend/src/Writing_Microblogs.js @@ -61,15 +61,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: "" }); } diff --git a/twistter-frontend/src/pages/Home.js b/twistter-frontend/src/pages/Home.js index 72c5c5a..c787276 100644 --- a/twistter-frontend/src/pages/Home.js +++ b/twistter-frontend/src/pages/Home.js @@ -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"; import withStyles from '@material-ui/styles/withStyles'; @@ -38,7 +38,7 @@ class Home extends Component { console.log(res.data); this.setState({ posts: res.data - }) + }); }) .catch(err => console.log(err)); } @@ -78,11 +78,12 @@ class Home extends Component { - ) - ) : (

My Posts

); + )) + ) : ( +

Loading post...

+ ); - return ( - authenticated ? + return authenticated ? ( @@ -90,26 +91,32 @@ class Home extends Component { {postMarkup} - - : + + ) : (
logo -

- Welcome to Twistter! -

- See the most interesting topics people are following right now. +
+
+ Welcome to Twistter! +
+
+ See the most interesting topics people are following right now.
-



+
+
+
+
-
- Join today or sign in if you already have an account. -

+
+ Join today or sign in if you already have an account. +
+
- +
-
+
@@ -119,7 +126,6 @@ class Home extends Component { } } - class Quote extends Component { constructor(props) { super(props); @@ -332,14 +338,13 @@ class Like extends Component { const mapStateToProps = (state) => ({ user: state.user -}) +}); Home.propTypes = { user: PropTypes.object.isRequired, clases: PropTypes.object.isRequired } - Like.propTypes = { user: PropTypes.object.isRequired } diff --git a/twistter-frontend/src/pages/Search.js b/twistter-frontend/src/pages/Search.js index 14cbc52..c8409f5 100644 --- a/twistter-frontend/src/pages/Search.js +++ b/twistter-frontend/src/pages/Search.js @@ -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 ? ( - -
- - {this.state.searchResult} - -
-
- ) : ( - // console.log(this.state.searchResult) -

No result

- ); + let resultMarkup = this.state.searchResult && this.state.searchResult !== "No Results" ? ( + this.state.searchResult.map(res => + +
+ + {res} + +
+
+ ) + ) + : + this.state.searchResult === "No Results" ? + ( +

No results

+ ) + : + ( + null + ) return ( - + this.state.loading + ? + + : - this.handleInput(event)} - /> + + + + + {/* */} + + {resultMarkup} - - - - {resultMarkup} - ); } }