Clone based off https://www.stackoverflow.com/.
Account holders are able to ask their questions on this site to get others to answer them. Bystanders may search questions and their answers, make comments, up or down votes etc.
Whether or not they have an account, people are allowed to search for topics and question, answers around their interest based on database or API data.
People ask questions, others vote on the answers, and the top is answer is featured and reputations established.
Puzzled users looking for the right question and answers may search and find threads leading to their questions. Answers which have been voted high are pulled ahead for others to view. Users with higher points will have better reputation so their next answers will be pulled ahead as well.
These are used to guage interactions between the users and the question and author. Ratings are tied to the answers but are created by the users.
Note: Comments are not private, so the comments should be honest and provide valid criticsm.
Users who find a questions they concerned by key words, search algorithms to look for these questions semantically is important. User can also bookmark the questions for future reference.
Features such as moderators or experts who has many followers are possible in this App
Extensive taggings are possible in this App so that questions along with all thier answwers, comments, ratings, etc. can be catagoried and searched.
While the backend Flask API is a fairly standard RESTful API, it requires authentication with a Cookie. Cross origin communication is protected by CSRF token that is facilitated also by React hooks API. The Flask server grabs the redux token for CSRF everytime it fetches to the Flask backend, which is used in all requests to the "any questions" server. Redux also stores and sets information about the active posts, whichever that has been selected by the user. By managing this state in Redux, it provides easy access to the information across components without prop threading. This was particularly important because there were so many components in the application and could further increase in the future. If too many components were re-rendering constantly because of state change it would cause significant performance issues or crash the application completely. Redux provided a relatively simple way to manage this point of complexity.
Redux also allows for a lot of extendibility if new features are to be implemented (additional feature wish-list discussed in conclusion).
Code for "any questions" auth flow:
function App() {
let location = useLocation();
let dispatch = useDispatch();
const [fetchWithCSRF, setFetchWithCSRF] = useState(() => fetch);
useEffect(() => {
async function restoreCSRF() {
const response = await fetch('/api/csrf/restore', {
method: 'GET',
credentials: 'include'
});
if (response.ok) {
const authData = await response.json();
setFetchWithCSRF(() => {
return (resource, init) => {
if (init.headers) {
init.headers['X-CSRFToken'] = authData.csrf_token;
} else {
init.headers = {
'X-CSRFToken': authData.csrf_token
}
}
return fetch(resource, init);
}
});
}
}
restoreCSRF();
}, []);
useEffect(() => {
dispatch(setCsrfFunc(fetchWithCSRF));
}, [fetchWithCSRF, dispatch]);
}
#Redux store:
export const login = (email, password) => {
return async (dispatch, getState) => {
const fetchWithCSRF = getState().authentication.csrf;
const res = await fetchWithCSRF('/api/session/login', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
credentials: 'include',
body: JSON.stringify({ email, password })
})
if (res.ok) {
const { user } = await res.json();
dispatch(setUser(user));
}
}
}
This is the backend for the Flask React project using SqlAlchemy and Psycopg-2.
-
Clone this repository
-
Install dependencies
pipenv install --dev -r dev-requirements.txt --python=python3 && pipenv install -r requirements.txt
-
Create a .env file based on the example with proper settings for your development environment
-
Setup your PostgreSQL user, password and database and make sure it matches your .env file
-
Get into your pipenv, seed your database, and run your flask app
pipenv shell
python -m database && flask run
-
To run the React App in development, checkout the README inside the client directory.
IMPORTANT! If you add any python dependencies to your pipfiles, you'll need to regenerate your requirements.txt before deployment. You can do this by running:
pipenv lock -r > requirements.txt
ALSO IMPORTANT! psycopg2-binary MUST remain a dev dependency because you can't install it on apline-linux. There is a layer in the Dockerfile that will install psycopg2 (not binary) for us.
Approach A. Deploy via Dockerfile and heroku Docker container
-
Create a new project on Heroku
-
Under Resources click "Find more add-ons" and add the add on called "Heroku Postgres"
-
Install the Heroku CLI
-
Run
heroku login
-
Login to the heroku container registry
heroku container:login
-
Update the
REACT_APP_BASE_URL
variable in the Dockerfile. This should be the full URL of your Heroku app: i.e. "https://flask-react-aa.herokuapp.com" -
Push your docker container to heroku from the root directory of your project. This will build the dockerfile and push the image to your heroku container registry
heroku container:push web -a {NAME_OF_HEROKU_APP}
-
Release your docker container to heroku
heroku container:release web -a {NAME_OF_HEROKU_APP}
-
set up your database:
heroku run -a {NAME_OF_HEROKU_APP} python -m database
-
Under Settings find "Config Vars" and add any additional/secret .env variables.
-
profit
-
Create a new project on Heroku
-
Under Resources click "Find more add-ons" and add the add on called "Heroku Postgres"
-
Install the Heroku CLI
-
Run
heroku login
-
Create in root directory Procfile and have this line in it:(since we are not using Dockerfile anymore) web: gunicorn starter_app:app
-
Add a package.json at the root level of the app with the following:
{ "name": "starter", "version": "0.0.0", "private": true, "scripts": { "heroku-prebuild": "npm install --prefix client && npm run build --prefix client" } }
-
heroku buildpacks:add --index 1 heroku/nodejs
-
update init.py in app_starter with the following: app = Flask(name, static_folder='../client/build', static_url_path='/')
-
delete Pipfile and Pipfile.lock in root directory
-
Add the above two files in your root directory .gitignore file
-
Add psycopg2-binary==2.8.6 from dev-requirements.txt into requirements.txt file
-
Connect to remote heroku
heroku git:remote -a flask-react-any-questions
-
Push to heroku
git push heroku
-
Setup database in remote herokuy and run app
heroku run -a flask-react-any-questions python -m database