add fav and repost function

This commit is contained in:
Tan, Kian-ting 2022-11-27 01:34:44 +08:00
parent c5a762a646
commit 715a0a1a07
10 changed files with 229 additions and 46 deletions

1
.gitignore vendored
View file

@ -133,3 +133,4 @@ tmp/restart.txt
# Django
migrations/
media/img/
db.sqlite3.sqbpro

View file

@ -63,6 +63,8 @@ class Following(models.Model):
)
class Post(models.Model):
text = models.TextField()
poster = models.ForeignKey(User, on_delete=models.CASCADE)
@ -81,3 +83,24 @@ class Post(models.Model):
)
class Repost(models.Model):
reposter = models.ForeignKey(User, on_delete=models.CASCADE, related_name="reposter")
reposted_post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="reposted_post")
repost_time = models.DateTimeField(default=timezone.now())
is_read = models.BooleanField(default=False)
class Reply(models.Model):
replyer_post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="replyer_post")
replyee_post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="replyee_post")
is_read = models.BooleanField(default=False)
class Fav(models.Model):
favouriter = models.ForeignKey(User, on_delete=models.CASCADE, related_name="favouriter")
favourited_post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="favourited_post")
favourited_time = models.DateTimeField(default=timezone.now())
is_read = models.BooleanField(default=False)

View file

@ -32,7 +32,10 @@ urlpatterns = [
path('api/get_latest_posts', views.api_get_latest_posts),
path('api/get_previous_posts', views.api_get_previous_posts),
path('user/<username>', views.user_timeline),
path('api/follow_request/<request_value>/<dest_username>', views.follow_request)
path('api/follow_request/<request_value>/<dest_username>', views.api_follow_request),
path('api/repost_request/<post_id>', views.api_repost_request),
path('api/fav_request/<post_id>', views.api_fav_request),
]
if settings.DEBUG:

View file

@ -1,7 +1,7 @@
import json
from django.http import HttpResponse, HttpResponseNotAllowed
from django.template import loader
from .models import User, Post, Following
from .models import User, Post, Following, Fav, Repost
from django.utils import timezone
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import redirect
@ -37,12 +37,21 @@ def api_get_previous_posts(request):
older_posts = Post.objects.filter(post_time__lt=oldest_datetime_object).filter(poster=poster).order_by('-id')[:20]
else:
pass
older_posts_list = [{"id" : o.pk,
"post_time" : datetime.strftime(o.post_time, "%Y-%m-%d %H:%M:%S.%f%z"),
"poster_username" : o.poster.username,
"poster_shown_name":o.poster.shown_name ,
"text": o.text}
for o in older_posts]
is_faved = [Fav.objects.filter(favourited_post=p).filter(favouriter=request.user).__len__() for p in older_posts]
is_reposted = [Repost.objects.filter(reposted_post=p).filter(reposter=request.user).__len__() for p in older_posts]
older_posts_info = zip(older_posts, is_faved, is_reposted)
older_posts_list = [{"id" : o[0].pk,
"post_time" : datetime.strftime(o[0].post_time, "%Y-%m-%d %H:%M:%S.%f%z"),
"poster_avatar" : o[0].poster.avatar.url,
"poster_username" : o[0].poster.username,
"poster_shown_name":o[0].poster.shown_name ,
"text": o[0].text,
"is_faved" : o[1],
"is_reposted" : o[2],
}
for o in older_posts_info]
if len(list(older_posts)) > 0:
oldest_time = datetime.strftime(list(older_posts)[-1].post_time, "%Y-%m-%d %H:%M:%S.%f%z")
else:
@ -72,12 +81,20 @@ def api_get_latest_posts(request):
poster = User.objects.get(username=username)
newer_posts = Post.objects.filter(post_time__gt=latest_datetime_object).filter(poster=poster).order_by('-id')[:20]
newer_posts_list = [{"id" : o.pk,
"post_time" : datetime.strftime(o.post_time, "%Y-%m-%d %H:%M:%S.%f%z"),
"poster_username" : o.poster.username,
"poster_shown_name":o.poster.shown_name ,
"text": o.text}
for o in newer_posts]
is_faved = [Fav.objects.filter(favourited_post=p).filter(favouriter=request.user).__len__() for p in newer_posts]
is_reposted = [Repost.objects.filter(reposted_post=p).filter(reposter=request.user).__len__() for p in newer_posts]
newer_posts_infp = zip(newer_posts, is_faved, is_reposted)
newer_posts_list = [{"id" : o[0].pk,
"post_time" : datetime.strftime(o[0].post_time, "%Y-%m-%d %H:%M:%S.%f%z"),
"poster_avatar" : o[0].poster.avatar.url,
"poster_username" : o[0].poster.username,
"poster_shown_name":o[0].poster.shown_name ,
"text": o[0].text,
"is_faved" : o[1],
"is_reposted" : o[2],
}
for o in newer_posts_infp]
return JsonResponse({'newer_posts':newer_posts_list})
else:
return HttpResponseNotAllowed('POST')
@ -273,7 +290,39 @@ def user_config(request):
def is_custom_avatar_path(old_image_path):
return os.path.exists(old_image_path) and (old_image_path != os.path.abspath("./media/static/default_avatar.png"))
def follow_request(request, request_value, dest_username):
def api_fav_request(request, post_id):
if request.method != "POST":
return HttpResponseNotAllowed('POST')
current_user = User.objects.get(id=request.user.id)
post = Post.objects.get(id=post_id)
if Fav.objects.filter(favouriter = current_user, favourited_post=post).__len__() > 0:
existed_fav = Fav.objects.filter(favouriter = current_user, favourited_post=post)[0]
existed_fav.delete()
return JsonResponse({'status': "deleted"})
else:
added_fav = Fav(favouriter = current_user, favourited_post=post)
added_fav.save()
return JsonResponse({'status': "faved"})
def api_repost_request(request, post_id):
if request.method != "POST":
return HttpResponseNotAllowed('POST')
current_user = User.objects.get(id=request.user.id)
post = Post.objects.get(id=post_id)
if Repost.objects.filter(reposter = current_user, reposted_post=post).__len__() > 0:
existed_repost = Repost.objects.filter(reposter = current_user, reposted_post=post)[0]
existed_repost.delete()
return JsonResponse({'status': "deleted"})
else:
added_repost = Repost(reposter = current_user, reposted_post=post)
added_repost.save()
return JsonResponse({'status': "reposted"})
def api_follow_request(request, request_value, dest_username):
if request.method != "POST":
return HttpResponseNotAllowed('POST')
else:
@ -318,6 +367,10 @@ def user_timeline(request, username):
else:
viewed_timeline_list = Post.objects.filter(poster = viewed_user.id).filter(privilage = 'public').order_by('-id')[:20]
is_faved = [Fav.objects.filter(favourited_post=p).filter(favouriter=request.user).__len__() for p in viewed_timeline_list]
is_reposted = [Repost.objects.filter(reposted_post=p).filter(reposter=request.user).__len__() for p in viewed_timeline_list]
viewed_timeline_info = zip(viewed_timeline_list, is_faved, is_reposted)
latest_received_time = timezone.now()
if len(viewed_timeline_list) > 0:
oldest_received_time = list(viewed_timeline_list)[-1].post_time
@ -334,7 +387,7 @@ def user_timeline(request, username):
'user_follower_number': user_follower_number,
'latest_received_time' : latest_received_time,
'oldest_received_time' : oldest_received_time,
'viewed_timeline_list': viewed_timeline_list,
'viewed_timeline_info': viewed_timeline_info,
}
return HttpResponse(template.render(context, request))
@ -346,6 +399,10 @@ def home(request):
all_i_follow = Following.objects.filter(follower=request.user.id).filter(isapproved="yes")
all_i_follow_and_me = User.objects.filter(Q(id__in = all_i_follow) | Q(id=request.user.id))
public_timeline_list = Post.objects.filter(poster__in = all_i_follow_and_me).order_by('-id')[:20]
is_faved = [Fav.objects.filter(favourited_post=p).filter(favouriter=request.user).__len__() for p in public_timeline_list]
is_reposted = [Repost.objects.filter(reposted_post=p).filter(reposter=request.user).__len__() for p in public_timeline_list]
public_timeline_info = zip(public_timeline_list, is_faved, is_reposted)
latest_received_time = timezone.now()
@ -359,6 +416,6 @@ def home(request):
context = {
'latest_received_time' : latest_received_time,
'oldest_received_time' : oldest_received_time,
'public_timeline_list': public_timeline_list,
'public_timeline_info': public_timeline_info,
}
return HttpResponse(template.render(context, request))

View file

@ -1,9 +1,40 @@
div.avatar-preview{
.post{
display:flex;
}
.post-content{
flex-direction: row;
}
.timeline-avatar-img{
flex-direction: row;
width:70px;
height:70px;
}
#avatar-img{
width: 200px;
height: 200px;
width: 150px;
height: 150px;
object-fit: cover;
}
.reply{
filter: grayscale(1);
}
.reply:hover{
filter: grayscale(0);
}
.unchecked{
filter: grayscale(1);
}
.repost:hover{
filter: grayscale(0);
}
.fav:hover{
filter: grayscale(0);
}

View file

@ -137,7 +137,9 @@ body: JSON.stringify({
return item['older_posts'];})
.then(posts => {if (posts.length == 0)
{$('previous_post_loader').style.display = 'none';}
else{posts.forEach(post => appendPostToTheEnd(post));
else{posts.forEach(post =>
appendPostToTheEnd(post));
updateClickedIconEvent();
$('oldest_time').innerHTML = new_oldest_time;}})
}
@ -185,6 +187,7 @@ body: JSON.stringify({
$('new_post_notifier').style.display = "none";
var nowTime = new Date();
var nowTimeString = nowTime.toISOString();
updateClickedIconEvent();
$("latest_time").innerHTML = nowTimeString.substring(0,10) + " " + nowTimeString.substring(11,23) + "000+0000"; });
}
@ -194,12 +197,16 @@ var new_div = document.createElement("div");
new_div.id = `post-${post.id}`;
new_div.className = "post";
post_text_replaced = post.text.replace(/(\r\n|\n\r|\r|\n)/g, "<br>" );
new_div.innerHTML = `<a href="/user/${post.poster_username}">${post.poster_shown_name}</a>
new_div.innerHTML = `
<img class="timeline-avatar-img" width="100" src="${post.poster_avatar}">
<div class="post-content">
<a href="/user/${post.poster_username}">${post.poster_shown_name}</a>
at <a href="/post/${post.id}" class="post-time">${post.post_time}</a><br>
${post_text_replaced}<br>
<span id="reply-${post.id}" value="${post.id}" class="reply"></span>
- <span id="repost-${post.id}" value="${post.id}" class="repost">🔁</span>
- <span id="fav-${post.id}" value="${post.id}" class="fav"></span>`;
<span id="reply-${post.id}" data-value="${post.id}" class="reply"></span>
- <span id="repost-${post.id}" data-value="${post.id}" class="${(post.is_reposted == "0" ? "unchecked" : "")} repost">🔁</span>
- <span id="fav-${post.id}" data-value="${post.id}" class="${(post.is_faved == "0" ? "unchecked" : "")} fav"></span>
</div>`;
new_div_timestamp = new_div.getElementsByClassName('post-time')[0];
@ -220,11 +227,66 @@ public_tl.insertBefore(new_div, $('latest_time').nextSibling);
$("new_post_notifier").addEventListener('click', getLatestPosts);
$("previous_post_loader").addEventListener('click', getPreviousPosts);
async function makeRepostRequest(event){
var postId = event.target.getAttribute('data-value');
await fetch(`/api/repost_request/${postId}`, {
method: 'POST',
headers: {
"X-CSRFToken": csrf_token,
'Content-Type': 'application/json',
},
body : ""
}).then(response => response.json())
.then(item => item['status'])
.then(status =>{
if (status == "reposted"){
event.target.classList.remove("unchecked");
}else if (status == "deleted"){
event.target.classList.add("unchecked");
}
});
}
async function makeFavRequest(event){
var postId = event.target.getAttribute('data-value');
await fetch(`/api/fav_request/${postId}`, {
method: 'POST',
headers: {
"X-CSRFToken": csrf_token,
'Content-Type': 'application/json',
},
body : ""
}).then(response => response.json())
.then(item => item['status'])
.then(status =>{
if (status == "faved"){
event.target.classList.remove("unchecked");
}else if (status == "deleted"){
event.target.classList.add("unchecked");
}
});
}
function updateClickedIconEvent(){
var reposted_items = document.getElementsByClassName('repost');
for (var i = 0; i < reposted_items.length; i++) {
reposted_items[i].addEventListener('click', makeRepostRequest);
}
var reposted_items = document.getElementsByClassName('fav');
for (var i = 0; i < reposted_items.length; i++) {
reposted_items[i].addEventListener('click', makeFavRequest);
}
}
updateClickedIconEvent()
if (requestNote["type"] == "home"){
$("submit_post").addEventListener('click', make_req);
adjust_post_text();
}
if (requestNote["type"] == "user"){
if ($("follow-user-button")){
$("follow-user-button").addEventListener('click', make_follow_req);
}
}

View file

@ -6,7 +6,7 @@
{% endblock %}
<meta charset="utf-8">
{% block title %}<title>Khaikang</title>
<link type="text/css" rel="stylesheet" href="{% static 'generic.css' %}"></style>
<link type="text/css" rel="stylesheet" href="{% static 'generic.css' %}?{% now 'U' %}"></style>
{% endblock %}
</head>
<body>

View file

@ -36,14 +36,18 @@
<div id="new_post_notifier" value=""></div>
<div id="latest_time" style="display: block;">{{latest_received_time|date:"Y-m-d H:i:s.u"}}+0000</div>
{% for public_post in public_timeline_list %}
{% for public_post in public_timeline_info %}
<div id="post-{{public_post.id}}" class="post"><a href="/user/{{public_post.poster}}">{{public_post.poster.shown_name}}</a>
at <a href="/post/{{public_post.id}}" class="post-time">{{public_post.post_time|date:"Y-m-d H:i:s.u"}}+0000</a><br/>
{{public_post.text|linebreaksbr}}<br/>
<span id="reply-{{public_post.id}}" value="{{public_post.id}}" class="reply">↩️</span>
- <span id="repost-{{public_post.id}}" value="{{public_post.id}}" class="repost">🔁</span>
- <span id="fav-{{public_post.id}}" value="{{public_post.id}}" class="fav"></span>
<div id="post-{{public_post.0.id}}" class="post">
<img class="timeline-avatar-img" src="{{public_post.0.poster.avatar.url}}">
<div class="post-content">
<a href="/user/{{public_post.0.poster}}">{{public_post.0.poster.shown_name}}</a>
at <a href="/post/{{public_post.0.id}}" class="post-time">{{public_post.0.post_time|date:"Y-m-d H:i:s.u"}}+0000</a><br/>
{{public_post.0.text|linebreaksbr}}<br/>
<span id="reply-{{public_post.0.id}}" data-value="{{public_post.0.id}}" class="reply">↩️</span>
- <span id="repost-{{public_post.0.id}}" data-value="{{public_post.0.id}}" class=" {%if public_post.1 == 0 %} unchecked{% endif %} repost">🔁</span>
- <span id="fav-{{public_post.0.id}}" data-value="{{public_post.0.id}}" class=" {%if public_post.2 == 0 %} unchecked{% endif %} fav"></span>
</div>
</div>
{% endfor %}
<div id="previous_post_loader">More posts</div>
@ -52,7 +56,7 @@
</div>
<script type="text/javascript" src="{% static 'timeline.js' %}">
<script type="text/javascript" src="{% static 'timeline.js' %}?{% now 'U' %}">

View file

@ -14,6 +14,6 @@
</form>
<script type="text/javascript" src="{% static 'user_config.js'%}">
<script type="text/javascript" src="{% static 'user_config.js'%}?{% now 'U' %}">
</script>
{% endblock %}

View file

@ -27,14 +27,16 @@ Following: <span class="fo-number">{{user_following_number}}</span> Follower: <s
<div id="new_post_notifier" value=""></div>
<div id="latest_time" style="display: block;">{{latest_received_time|date:"Y-m-d H:i:s.u"}}+0000</div>
{% for post in viewed_timeline_list %}
{% for post in viewed_timeline_info %}
<div id="post-{{post.id}}" class="post"><a href="/user/{{post.poster}}">{{post.poster.shown_name}}</a>
at <a href="/post/{{post.id}}" class="post-time">{{post.post_time|date:"Y-m-d H:i:s.u"}}+0000</a><br/>
{{post.text|linebreaksbr}}<br/>
<span id="reply-{{post.id}}" value="{{post.id}}" class="reply">↩️</span>
- <span id="repost-{{post.id}}" value="{{post.id}}" class="repost">🔁</span>
- <span id="fav-{{post.id}}" value="{{post.id}}" class="fav"></span>
<div id="post-{{post.0.id}}" class="post">
<img class="timeline-avatar-img"src="{{post.0.poster.avatar.url}}">
<div class="post-content"><a href="/user/{{post.0.poster}}">{{post.0.poster.shown_name}}</a>
at <a href="/post/{{post.0.id}}" class="post-time">{{post.0.post_time|date:"Y-m-d H:i:s.u"}}+0000</a><br/>
{{post.0.text|linebreaksbr}}<br/>
<span id="reply-{{post.0.id}}" data-value="{{post.0.id}}" class="reply">↩️</span>
- <span id="repost-{{post.0.id}}" data-value="{{post.0.id}}" class=" {%if post.1 == 0 %} unchecked{% endif %} repost">🔁</span>
- <span id="fav-{{post.0.id}}" data-value="{{post.0.id}}"class=" {%if post.2 == 0 %}unchecked{% endif %} fav"></span></div>
</div>
{% endfor %}
<div id="previous_post_loader">More posts</div>
@ -43,7 +45,7 @@ Following: <span class="fo-number">{{user_following_number}}</span> Follower: <s
</div>
<script type="text/javascript" src="{% static 'timeline.js' %}">
<script type="text/javascript" src="{% static 'timeline.js' %}?{% now 'U' %}">