Skip to content
This repository has been archived by the owner on Sep 26, 2022. It is now read-only.

Add AJAX functions for following/unfollowing users #9

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
79 changes: 59 additions & 20 deletions app/core/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
from datetime import datetime
from flask import render_template, flash, redirect, \
url_for, request, current_app

from flask import (
make_response,
current_app,
flash,
redirect,
render_template,
request,
url_for
)
from flask_login import current_user, login_required
from app import db
from app.core import bp
Expand Down Expand Up @@ -83,30 +91,61 @@ def edit_profile():
return render_template('edit_profile.html', form=form, title="Edit Profile")


def ajax_flash(msg_type, message, message_list):
message_list.append({
'type': msg_type,
'message': message
})
return message_list


@bp.route('/follow/<username>')
def follow(username):
flash_messages = []

data = {
'redirect': ''
}

user = User.query.filter_by(username=username).first()

if not user:
flash("User not found")
return redirect(url_for("core.index"))
if user == current_user:
flash("You can't follow yourself")
return redirect(url_for('core.user', username=username))
current_user.follow(user)
db.session.commit()
flash(f"You are following {username}!")
return redirect(url_for("core.user", username=username))
flash_messages = ajax_flash('info', 'User not found', flash_messages)
data['redirect'] = url_for('core.index')
elif user == current_user:
flash_messages = ajax_flash('info', 'You can\'t follow yourself!', flash_messages)
else:
current_user.follow(user)
db.session.commit()
flash_messages = ajax_flash('success', f'You are following {username}', flash_messages)

data['flash_messages'] = flash_messages

r = make_response(data)
r.mimetype = 'application/json'
return r


@bp.route('/unfollow/<username>')
def unfollow(username):
flash_messages = [];

data = {
'redirect': ''
}
user = User.query.filter_by(username=username).first()
if not user:
flash("User not found")
return redirect(url_for("core.index"))
if user == current_user:
flash("You can unfollow yourself")
return redirect(url_for("core.user", username=username))
current_user.unfollow(user)
db.session.commit()
flash(f"You unfollowed {username}")
return redirect(url_for('core.user', username=username))
flash_messages = ajax_flash('info', 'User not found', flash_messages)
data['redirect'] = url_for('core.index')
elif user == current_user:
flash_messages = ajax_flash('info', 'You can\'t unfollow yourself', flash_messages)
else:
current_user.unfollow(user)
db.session.commit()
flash_messages = ajax_flash('success', f'You unfollowed {username}', flash_messages)

data['flash_messages'] = flash_messages

r = make_response(data)
r.mimetype = 'application/json'
return r
61 changes: 54 additions & 7 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
</div>
</nav>
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<div id="flash">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
{% block content %}{% endblock content %}
</div>
</body>
Expand All @@ -52,6 +54,9 @@
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>


{{ moment.include_moment() }}
<script>
$(function () {
Expand Down Expand Up @@ -95,6 +100,48 @@
}
)
})

const user = "{{user.username}}"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user object is only available in user.html, it is not available in base.html. It will work for /user/ endpoint, but it will not work for other endpoints, you may get jinja2.exceptions.UndefinedError, please check.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest moving follow, unfollow links to some reusable html template and use it everywhere, and move this javascript code to the new template created.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @SriNandan33 I made those follow/unfollow buttons snippets, and migrated the inline javascript used for following/unfollowing into a static directory

const Axios = window.axios;

function flashMessages(data){
html = '';

for (i = 0; i < data.length; i++) {
html += `
<div class="alert alert-${data[i]['type']}">
<a href="#" class="close" data-dismiss="alert">&times;</a>
${data[i].message}
</div>`;
}
return html;
};

function ajaxGetWithFlash(follow = true) {
const endpoint = follow ? `/follow/${user}` : `/unfollow/${user}`;
const link = follow ? '<p onclick="unFollowUser()">Unfollow</p>' : '<p onclick="followUser()">Follow</p>';

Axios.get(endpoint).then((response) => {
const messages = response.data.flash_messages;
const redirect = response.data.redirect;

if (redirect) {
window.location.href = redirect;
}
$('#flash').html(flashMessages(messages));
$('.follow-link').html(link)
}).catch((error) => {
console.error(`Error: ${error}, please contact the administrator`);
});
}

function unFollowUser() {
ajaxGetWithFlash(false)
}

function followUser() {
ajaxGetWithFlash(true)
}
</script>

</html>
14 changes: 11 additions & 3 deletions app/templates/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@ <h1>User: {{ user.username }}</h1>
{% if user.last_seen %}<p>Last seen on: {{ moment(user.last_seen).format('LLL') }}</p>{% endif %}
<p>{{ user.followers.count()}} followers, {{ user.followed.count()}} following.</p>
{% if user == current_user %}
<p><a href="{{ url_for('core.edit_profile')}}">Edit Profile</a></p>
<p>
<a href="{{ url_for('core.edit_profile')}}">
Edit Profile
</a>
</p>
{% elif current_user.is_following(user) %}
<p><a href="{{ url_for('core.unfollow', username=user.username)}}">Unfollow</a></p>
<div class="follow-link">
<p onclick="unFollowUser()">Unfollow</p>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use button here just to denote it is clickable and add some css to it. Don't forget to add cursor:pointer to css rule.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is also good to go 👍

</div>
{% else %}
<p><a href="{{ url_for('core.follow', username=user.username)}}">Follow</a></p>
<div class="follow-link">
<p onclick="followUser()">Follow</p>
</div>
{% endif %}
</td>
</tr>
Expand Down