add unfo/foing request

This commit is contained in:
Tan, Kian-ting 2022-11-26 05:01:20 +08:00
parent 0b1b077feb
commit c5a762a646
7 changed files with 190 additions and 48 deletions

View file

@ -52,6 +52,15 @@ class User(AbstractUser):
class Following(models.Model): class Following(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name="follower") follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name="follower")
followee = models.ForeignKey(User, on_delete=models.CASCADE, related_name="followee") followee = models.ForeignKey(User, on_delete=models.CASCADE, related_name="followee")
IS_DECIDED = [
('undecided', 'undecided'),
('yes', 'yes'),
]
isapproved = models.CharField(
max_length=9,
choices=IS_DECIDED,
default='undecided',
)
class Post(models.Model): class Post(models.Model):

View file

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

View file

@ -1,5 +1,5 @@
import json import json
from django.http import HttpResponse from django.http import HttpResponse, HttpResponseNotAllowed
from django.template import loader from django.template import loader
from .models import User, Post, Following from .models import User, Post, Following
from django.utils import timezone from django.utils import timezone
@ -24,7 +24,19 @@ def api_get_previous_posts(request):
post_body_json = json.loads(post_body_orig) post_body_json = json.loads(post_body_orig)
oldest_time = post_body_json["oldest_time"] oldest_time = post_body_json["oldest_time"]
oldest_datetime_object = datetime.strptime(oldest_time, '%Y-%m-%d %H:%M:%S.%f%z') oldest_datetime_object = datetime.strptime(oldest_time, '%Y-%m-%d %H:%M:%S.%f%z')
older_posts = Post.objects.filter(post_time__lt=oldest_datetime_object).order_by('-id')[:20]
note = post_body_json["request_note"]
if note["type"] == "home":
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))
older_posts = Post.objects.filter(post_time__lt=oldest_datetime_object).filter(poster__in = all_i_follow_and_me).order_by('-id')[:20]
elif note["type"] == "user":
username = note["arg"]
poster = User.objects.get(username=username)
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, older_posts_list = [{"id" : o.pk,
"post_time" : datetime.strftime(o.post_time, "%Y-%m-%d %H:%M:%S.%f%z"), "post_time" : datetime.strftime(o.post_time, "%Y-%m-%d %H:%M:%S.%f%z"),
"poster_username" : o.poster.username, "poster_username" : o.poster.username,
@ -37,6 +49,8 @@ def api_get_previous_posts(request):
oldest_time = oldest_time oldest_time = oldest_time
return JsonResponse({'older_posts':older_posts_list, return JsonResponse({'older_posts':older_posts_list,
'oldest_time': oldest_time}) 'oldest_time': oldest_time})
else:
return HttpResponseNotAllowed('POST')
@ -46,7 +60,18 @@ def api_get_latest_posts(request):
post_body_json = json.loads(post_body_orig) post_body_json = json.loads(post_body_orig)
latest_time = post_body_json["latest_time"] latest_time = post_body_json["latest_time"]
latest_datetime_object = datetime.strptime(latest_time, '%Y-%m-%d %H:%M:%S.%f%z') latest_datetime_object = datetime.strptime(latest_time, '%Y-%m-%d %H:%M:%S.%f%z')
newer_posts = Post.objects.filter(post_time__gte=latest_datetime_object)
note = post_body_json["request_note"]
if note["type"] == "home":
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))
newer_posts = Post.objects.filter(post_time__gt=latest_datetime_object).filter(poster__in = all_i_follow_and_me).order_by('-id')[:20]
elif note["type"] == "user":
username = note["arg"]
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, newer_posts_list = [{"id" : o.pk,
"post_time" : datetime.strftime(o.post_time, "%Y-%m-%d %H:%M:%S.%f%z"), "post_time" : datetime.strftime(o.post_time, "%Y-%m-%d %H:%M:%S.%f%z"),
"poster_username" : o.poster.username, "poster_username" : o.poster.username,
@ -54,6 +79,8 @@ def api_get_latest_posts(request):
"text": o.text} "text": o.text}
for o in newer_posts] for o in newer_posts]
return JsonResponse({'newer_posts':newer_posts_list}) return JsonResponse({'newer_posts':newer_posts_list})
else:
return HttpResponseNotAllowed('POST')
def api_get_recent_posts_counter(request): def api_get_recent_posts_counter(request):
if request.method == 'POST': if request.method == 'POST':
@ -61,8 +88,28 @@ def api_get_recent_posts_counter(request):
post_body_json = json.loads(post_body_orig) post_body_json = json.loads(post_body_orig)
latest_time = post_body_json["latest_time"] latest_time = post_body_json["latest_time"]
latest_datetime_object = datetime.strptime(latest_time, '%Y-%m-%d %H:%M:%S.%f%z') latest_datetime_object = datetime.strptime(latest_time, '%Y-%m-%d %H:%M:%S.%f%z')
newer_posts_len = Post.objects.filter(post_time__gte=latest_datetime_object).exclude(Q(poster=request.user) & Q(post_time=latest_datetime_object)).__len__()
note = post_body_json["request_note"]
if note["type"] == "home":
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))
newer_posts_len = Post.objects.filter(post_time__gte=latest_datetime_object) \
.filter(poster__in = all_i_follow_and_me) \
.exclude(Q(poster=request.user) & Q(post_time=latest_datetime_object)) \
.__len__()
elif note["type"] == "user":
username = note["arg"]
poster = User.objects.get(username=username)
newer_posts_len = Post.objects.filter(post_time__gte=latest_datetime_object) \
.filter(poster=poster) \
.exclude(Q(post_time=latest_datetime_object)) \
.__len__()
return JsonResponse({'newer_posts_num':newer_posts_len}) return JsonResponse({'newer_posts_num':newer_posts_len})
else:
return HttpResponseNotAllowed('POST')
@ -82,6 +129,8 @@ def api_post(request):
post_time = timezone.now()) post_time = timezone.now())
a_post.save() a_post.save()
return HttpResponse(200, str(post_text)) return HttpResponse(200, str(post_text))
else:
return HttpResponseNotAllowed('POST')
def signup(request): def signup(request):
small_letters_a_to_z = string.ascii_letters small_letters_a_to_z = string.ascii_letters
@ -170,8 +219,9 @@ def user_config(request):
class Meta: class Meta:
model = User model = User
fields = ('shown_name', 'avatar', 'desc', 'email') fields = ('shown_name', 'desc', 'avatar', 'email')
avatar = forms.ImageField(required = False)
if request.user == AnonymousUser(): if request.user == AnonymousUser():
@ -186,9 +236,13 @@ def user_config(request):
if form.is_valid(): if form.is_valid():
print(old_image_path) image_path = os.path.abspath(f"./media/{current_user.avatar.name}")
try:
avatar_path_in_form = form.cleaned_data['avatar'].path
except AttributeError:
avatar_path_in_form = form.cleaned_data['avatar']
if os.path.exists(old_image_path) and (old_image_path != os.path.abspath("./media/static/default_avatar.png")): if avatar_path_in_form != old_image_path and is_custom_avatar_path(old_image_path):
a = os.remove(old_image_path) a = os.remove(old_image_path)
print(a) print(a)
@ -209,14 +263,54 @@ def user_config(request):
pass pass
current_user = User.objects.get(id=request.user.id) current_user = User.objects.get(id=request.user.id)
form = UserConfigForm(initial={'shown_name': request.user.shown_name, form = UserConfigForm(initial={'shown_name': current_user.shown_name,
'desc' : request.user.desc, 'desc' : current_user.desc,
'url' : request.user.url, 'url' : current_user.url,
'email' : request.user.email}) 'email' : current_user.email})
template = loader.get_template('user_config.html') template = loader.get_template('user_config.html')
return HttpResponse(template.render({'form': form, 'avatar': current_user.avatar}, request)) return HttpResponse(template.render({'form': form, 'avatar': current_user.avatar}, 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):
if request.method != "POST":
return HttpResponseNotAllowed('POST')
else:
current_user = User.objects.get(id=request.user.id)
dest_user = User.objects.get(username=dest_username)
if request_value == "send-following-request":
following_status = Following(follower=current_user, followee= dest_user, isapproved="undecided")
following_status.save()
return JsonResponse({'status': "request sent"})
elif request_value == "cancel-following-request":
following_status = Following.objects.get(follower=current_user.id, followee= dest_user.id)
following_status.delete()
return JsonResponse({'status': "request cancelled"})
elif request_value == "unfollow":
following_status = Following.objects.get(follower=current_user.id, followee= dest_user.id)
following_status.delete()
return JsonResponse({'status': "unfollowed"})
else:
return JsonResponse({'status': "other"})
def user_timeline(request, username): def user_timeline(request, username):
user_id = User.objects.get(username=username).id
user_following_number = Following.objects.filter(follower=user_id).filter(isapproved="yes").__len__()
user_follower_number = Following.objects.filter(followee=user_id).filter(isapproved="yes").__len__()
following_relationship = Following.objects.filter(follower=request.user.id).filter(followee=user_id)
following_status = ""
if following_relationship.__len__() == 0:
following_status = "unfollowed"
else:
following_status = following_relationship[0].isapproved
viewed_user = User.objects.get(username=username) viewed_user = User.objects.get(username=username)
if Following.objects.filter(follower = request.user.id).filter(followee=viewed_user.id) or request.user.id == viewed_user.id: if Following.objects.filter(follower = request.user.id).filter(followee=viewed_user.id) or request.user.id == viewed_user.id:
@ -235,6 +329,9 @@ def user_timeline(request, username):
context = { context = {
'username' : username, 'username' : username,
'user_shown_name' : viewed_user.shown_name, 'user_shown_name' : viewed_user.shown_name,
'following_status': following_status,
'user_following_number' : user_following_number,
'user_follower_number': user_follower_number,
'latest_received_time' : latest_received_time, 'latest_received_time' : latest_received_time,
'oldest_received_time' : oldest_received_time, 'oldest_received_time' : oldest_received_time,
'viewed_timeline_list': viewed_timeline_list, 'viewed_timeline_list': viewed_timeline_list,
@ -245,9 +342,11 @@ def home(request):
if request.user == AnonymousUser(): if request.user == AnonymousUser():
return redirect('/account/login') # redirect to main page return redirect('/account/login') # redirect to main page
public_timeline_list = Post.objects.filter(privilage = 'public').order_by('-id')[:20] 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]
latest_received_time = timezone.now() latest_received_time = timezone.now()
if len(public_timeline_list) > 0: if len(public_timeline_list) > 0:

View file

@ -15,6 +15,15 @@ x => timezoneChangingOne(x)
); );
} }
var requestNote = {"type" : "home", "arg" : ""};
var pathName = window.location.pathname;
var homePattern = /[/]home[/]/;
var userPagePattern = /[/]user[/]([^/]+)/;
var userIdName = "";
if (pathName.match(userPagePattern)){
userIdName = pathName.match(userPagePattern)[1];
requestNote = {"type" : "user", "arg" : userIdName};
}
@ -25,7 +34,8 @@ csrf_token = $("_token").content;
var httpRequest; var httpRequest;
$("submit_post").addEventListener('click', make_req);
async function make_req() { async function make_req() {
@ -44,7 +54,8 @@ headers: {
}, },
body: JSON.stringify({ body: JSON.stringify({
"privilage" : post_privilage, "privilage" : post_privilage,
"text": post_text, "text" : post_text,
"request_note" : requestNote,
}) })
}).then(response => {if (response.ok == true) }).then(response => {if (response.ok == true)
@ -83,10 +94,11 @@ headers: {
}, },
body: JSON.stringify({ body: JSON.stringify({
"latest_time" : latest_time_string, "latest_time" : latest_time_string,
"request_note" : requestNote,
}) })
}).then(response => response.json()) }).then(response => response.json())
.then(the_json => {console.log(the_json);let newer_posts_num = the_json['newer_posts_num']; .then(the_json => {let newer_posts_num = the_json['newer_posts_num'];
if (newer_posts_num == 1) if (newer_posts_num == 1)
{ $("new_post_notifier").style.display = "block"; { $("new_post_notifier").style.display = "block";
$("new_post_notifier").innerHTML = `1 new post`} $("new_post_notifier").innerHTML = `1 new post`}
@ -117,6 +129,8 @@ headers: {
}, },
body: JSON.stringify({ body: JSON.stringify({
"oldest_time" : oldest_time_string, "oldest_time" : oldest_time_string,
"request_note" : requestNote,
}) }).then(response => response.json()) }) }).then(response => response.json())
.then(item => {new_oldest_time_raw = item['oldest_time']; .then(item => {new_oldest_time_raw = item['oldest_time'];
new_oldest_time = new_oldest_time_raw.substring(0,10) + " " + new_oldest_time_raw.substring(11,26) + "+0000"; new_oldest_time = new_oldest_time_raw.substring(0,10) + " " + new_oldest_time_raw.substring(11,26) + "+0000";
@ -128,6 +142,31 @@ body: JSON.stringify({
} }
async function make_follow_req(){
requestValue = $("follow-user-button").value;
await fetch(`/api/follow_request/${requestValue}/${userIdName}`, {
method: 'POST',
headers: {
"X-CSRFToken": csrf_token,
'Content-Type': 'application/json',
},
body : ""
}).then(response => response.json())
.then(
item =>{
returnValue = item["status"];
if (returnValue == "request sent"){
$("follow-user-button").value = "cancel-following-request";
$("follow-user-button").innerHTML = "Cancel Following Request";
}
else if(returnValue == "request cancelled" || returnValue == "unfollowed"){
$("follow-user-button").value = "send-following-request";
$("follow-user-button").innerHTML = "Follow";
}
}
)
}
async function getLatestPosts(){ async function getLatestPosts(){
latest_time_string = $("latest_time").innerHTML; latest_time_string = $("latest_time").innerHTML;
await fetch('/api/get_latest_posts', { await fetch('/api/get_latest_posts', {
@ -138,7 +177,9 @@ headers: {
}, },
body: JSON.stringify({ body: JSON.stringify({
"latest_time" : latest_time_string, "latest_time" : latest_time_string,
}) }).then(response => response.json()) "request_note" : requestNote,
}) })
.then(response => response.json())
.then(item => item['newer_posts']) .then(item => item['newer_posts'])
.then(posts => {posts.forEach(post => addPostToTheBeginning(post)); .then(posts => {posts.forEach(post => addPostToTheBeginning(post));
$('new_post_notifier').style.display = "none"; $('new_post_notifier').style.display = "none";
@ -153,7 +194,6 @@ var new_div = document.createElement("div");
new_div.id = `post-${post.id}`; new_div.id = `post-${post.id}`;
new_div.className = "post"; new_div.className = "post";
post_text_replaced = post.text.replace(/(\r\n|\n\r|\r|\n)/g, "<br>" ); post_text_replaced = post.text.replace(/(\r\n|\n\r|\r|\n)/g, "<br>" );
console.log(post_text_replaced);
new_div.innerHTML = `<a href="/user/${post.poster_username}">${post.poster_shown_name}</a> new_div.innerHTML = `<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> at <a href="/post/${post.id}" class="post-time">${post.post_time}</a><br>
${post_text_replaced}<br> ${post_text_replaced}<br>
@ -181,5 +221,10 @@ $("new_post_notifier").addEventListener('click', getLatestPosts);
$("previous_post_loader").addEventListener('click', getPreviousPosts); $("previous_post_loader").addEventListener('click', getPreviousPosts);
if (requestNote["type"] == "home"){
adjust_post_text(); $("submit_post").addEventListener('click', make_req);
adjust_post_text();
}
if (requestNote["type"] == "user"){
$("follow-user-button").addEventListener('click', make_follow_req);
}

View file

@ -5,13 +5,13 @@
{% block meta%} {% block meta%}
{% endblock %} {% endblock %}
<meta charset="utf-8"> <meta charset="utf-8">
{% block title %}<title>Local Library</title> {% 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' %}"></style>
{% endblock %} {% endblock %}
</head> </head>
<body> <body>
<h1 id="title">{%block title}Kianting.social{%endblock title}</h1> <h1 id="title">{%block maintitle %}Kianting.social{% endblock %}</h1>
<div id="headbar">{% block headbar %}{% endblock headbar%}</div> <div id="headbar">{% block headbar %}{% endblock headbar%}</div>
<div id="sidebar">{% block sidebar %}<!-- insert default navigation text for every page -->{% endblock %}</div> <div id="sidebar">{% block sidebar %}<!-- insert default navigation text for every page -->{% endblock %}</div>
<div id="content">{% block content %}<!-- default content text (typically empty) -->{% endblock %}</div> <div id="content">{% block content %}<!-- default content text (typically empty) -->{% endblock %}</div>

View file

@ -14,7 +14,6 @@
<form method="POST" id="posting-form"> <form method="POST" id="posting-form">
{% csrf_token %} {% csrf_token %}
<div class="posting-form-group"> <div class="posting-form-group">
<label>Post</label>
<textarea id="post_text" name="post_text" placeholder="What do you want to post?" <textarea id="post_text" name="post_text" placeholder="What do you want to post?"
maxlength="500" style="resize: none;" oninput="auto_expand(this)"></textarea> maxlength="500" style="resize: none;" oninput="auto_expand(this)"></textarea>
@ -30,7 +29,7 @@
<option value="private">Private</option> <option value="private">Private</option>
</select> </select>
<button id="submit_post" type="button" class="btn">Post!</button> <button id="submit_post" type="button" class="btn">Kóng!</button>
</form> </form>
<div id="public_timeline"> <div id="public_timeline">

View file

@ -11,28 +11,18 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<form method="POST" id="posting-form"> <div id="intro"><div id="intro-shown-name">{{user_shown_name}}</div><div id="intro-id-name">{{username}}</div>
{% csrf_token %} {% if username == request.user.username %}
<div class="posting-form-group"> My account<br>
<label>Post</label> {% endif %}
{% if username != request.user.username %}
{% if following_status == "unfollowed" %}<button value="send-following-request" id="follow-user-button">Follow</button><br>{% endif %}
{% if following_status == "undecided" %}<button value="cancel-following-request" id="follow-user-button">Cancel Following Request</button><br>{% endif %}
{% if following_status == "yes" %}<button value="unfollow" id="follow-user-button">Unfollow</button><br>{% endif %}
<textarea id="post_text" name="post_text" placeholder="What do you want to post?" {% endif %}
maxlength="500" style="resize: none;" oninput="auto_expand(this)"></textarea> Following: <span class="fo-number">{{user_following_number}}</span> Follower: <span class="fo-number">{{user_follower_number}}</span></div>
</div>
{% csrf_token %}
<label for="privilege">Privileges:</label>
<select name="privilege" id="privil_choosing">
<option value="public" selected>Public Timeline</option>
<option value="unpublic">Not in Public Timeline</option>
<option value="private">Private</option>
</select>
<button id="submit_post" type="button" class="btn">Post!</button>
</form>
<div id="intro">{{user_shown_name}}<br>{{username}}</div>
<div id="public_timeline"> <div id="public_timeline">
<div id="new_post_notifier" value=""></div> <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> <div id="latest_time" style="display: block;">{{latest_received_time|date:"Y-m-d H:i:s.u"}}+0000</div>
@ -52,8 +42,7 @@
</div> </div>
<pre> % static 'timeline.js' 要修改
</pre>
<script type="text/javascript" src="{% static 'timeline.js' %}"> <script type="text/javascript" src="{% static 'timeline.js' %}">