Add humanized "last seen X ago" and "registered X ago" text on profile

This commit is contained in:
Xevion
2022-03-27 03:13:48 -05:00
parent 3df856aa60
commit 677abe3d65
5 changed files with 50 additions and 3 deletions

View File

@@ -10,6 +10,7 @@ flask-login = "*"
flask-sqlalchemy = "*" flask-sqlalchemy = "*"
pytz = "*" pytz = "*"
faker = "*" faker = "*"
humanize = "*"
[dev-packages] [dev-packages]

10
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "274a5de62926ba1c658817a40cb4b731272e26e154ce7a4a3b2f2095805a5dde" "sha256": "d91ae74e8b4c1a9e9603e27dbdddd314ae6a462649cbff848d12c89ac84b0034"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@@ -125,6 +125,14 @@
"markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
"version": "==1.1.2" "version": "==1.1.2"
}, },
"humanize": {
"hashes": [
"sha256:8d86333b8557dacffd4dce1dbe09c81c189e2caf7bb17a970b2212f0f58f10f2",
"sha256:ee1f872fdfc7d2ef4a28d4f80ddde9f96d36955b5d6b0dac4bdeb99502bddb00"
],
"index": "pypi",
"version": "==4.0.0"
},
"itsdangerous": { "itsdangerous": {
"hashes": [ "hashes": [
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",

View File

@@ -1,7 +1,13 @@
import datetime
import json
from typing import List
import humanize
from flask_login import UserMixin from flask_login import UserMixin
from sqlalchemy import func from sqlalchemy import func
from .create_app import db from .create_app import db
MAXIMUM_ONLINE_DELTA = datetime.timedelta(minutes=5)
class User(UserMixin, db.Model): class User(UserMixin, db.Model):
@@ -14,6 +20,16 @@ class User(UserMixin, db.Model):
last_seen = db.Column(db.DateTime, nullable=False, server_default=func.now()) last_seen = db.Column(db.DateTime, nullable=False, server_default=func.now())
last_ip = db.Column(db.String(64), nullable=True) last_ip = db.Column(db.String(64), nullable=True)
def get_last_seen(self) -> str:
delta: datetime.timedelta = datetime.datetime.utcnow() - self.last_seen
if delta > MAXIMUM_ONLINE_DELTA:
return f'Last seen {humanize.naturaldelta(delta)} ago'
return 'Online now!'
def get_registration_delta(self) -> str:
delta: datetime.timedelta = datetime.datetime.utcnow() - self.time_registered
return humanize.naturaldelta(delta)
class Post(db.Model): class Post(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
@@ -22,3 +38,18 @@ class Post(db.Model):
date_posted = db.Column(db.DateTime, server_default=func.now()) date_posted = db.Column(db.DateTime, server_default=func.now())
date_updated = db.Column(db.DateTime, nullable=True) date_updated = db.Column(db.DateTime, nullable=True)
likes = db.Column(db.Text, default='[]') likes = db.Column(db.Text, default='[]')
def get_likes(self) -> List[int]:
"""Return the IDs of the Users who have liked this post."""
return json.loads(self.likes)
def set_likes(self, likes: List[int]) -> None:
"""Set the likes c"""
self.likes = list(dict.fromkeys(json.dumps(likes)))
self.save()
def add_like(self, user_id: int) -> None:
likes: List[int] = self.get_likes()
if user_id not in likes:
likes.append(user_id)
self.set_likes(likes)

View File

@@ -41,6 +41,7 @@ def user(username: str):
user = User.query.filter_by(username=username).first_or_404() user = User.query.filter_by(username=username).first_or_404()
return render_template('pages/user.html', user=user) return render_template('pages/user.html', user=user)
@blueprint.route('/user/<username>/edit') @blueprint.route('/user/<username>/edit')
@login_required @login_required
def profile(): def profile():

View File

@@ -4,13 +4,19 @@
<div class="content-inner"> <div class="content-inner">
<div class="profile-title"> <div class="profile-title">
<span class="profile-username">{{ user.username }}</span> <span class="profile-username">{{ user.username }}</span>
<span class="profile-timestamp online">Online Now!</span> {% with seen_text = user.get_last_seen() %}
{% if seen_text == 'Online now!' %}
<span class="profile-timestamp online">{{ seen_text }}</span>
{% else %}
<span class="profile-timestamp offline">{{ seen_text }}</span>
{% endif %}
{% endwith %}
</div> </div>
<div class="profile-lower"> <div class="profile-lower">
<div class="profile-left"> <div class="profile-left">
<img class="profile-picture" src="{{ url_for('static', filename='default_photo.png') }}" alt="{{ user.username }}'s Profile Picture"> <img class="profile-picture" src="{{ url_for('static', filename='default_photo.png') }}" alt="{{ user.username }}'s Profile Picture">
<div class="profile-details"> <div class="profile-details">
Registered 33 days ago<br> Registered {{ user.get_registration_delta() }} ago<br>
67 likes<br> 67 likes<br>
14 posts<br> 14 posts<br>
</div> </div>