From 2b122f6ab2fc46a010372692842c1956ca55bcd0 Mon Sep 17 00:00:00 2001 From: finn Date: Sat, 3 Aug 2024 04:59:05 -0700 Subject: [PATCH] mgt c6 checkpoint 2.2 --- backend/README.md | 7 +++ backend/app/forms.py | 9 +++- backend/app/models.py | 4 +- backend/app/routes.py | 30 +++++++++++-- backend/app/templates/edit_profile.html | 24 ++++++++++ backend/app/templates/user.html | 9 +++- .../39466ff4e782fc398fed2c3b21d53ba2.png | Bin 384 -> 0 bytes .../686fed96bd36dc9ba0c0434036031942.png | Bin 397 -> 0 bytes .../7a651a7bab949a73092e21ad0bd2f4a8.png | Bin 378 -> 0 bytes ...fee021_posts_table.py => 1a0e4f823e90_.py} | 30 ++++++++++--- .../versions/e42cf202d424_users_table.py | 42 ------------------ 11 files changed, 100 insertions(+), 55 deletions(-) create mode 100644 backend/app/templates/edit_profile.html delete mode 100644 backend/app/usercontent/identicon/39466ff4e782fc398fed2c3b21d53ba2.png delete mode 100644 backend/app/usercontent/identicon/686fed96bd36dc9ba0c0434036031942.png delete mode 100644 backend/app/usercontent/identicon/7a651a7bab949a73092e21ad0bd2f4a8.png rename backend/migrations/versions/{938ae2fee021_posts_table.py => 1a0e4f823e90_.py} (53%) delete mode 100644 backend/migrations/versions/e42cf202d424_users_table.py diff --git a/backend/README.md b/backend/README.md index 07ea60b..f4b48ea 100644 --- a/backend/README.md +++ b/backend/README.md @@ -28,6 +28,13 @@ flask db upgrade flask db downgrade [base] flask db upgrade + +full reset? +rm app.db +rm -r migrations +flask db init +flask db migrate +flask db upgrade ``` ## build notes: diff --git a/backend/app/forms.py b/backend/app/forms.py index fe31c0e..bcd5720 100644 --- a/backend/app/forms.py +++ b/backend/app/forms.py @@ -1,6 +1,6 @@ from flask_wtf import FlaskForm -from wtforms import StringField, PasswordField, BooleanField, SubmitField -from wtforms.validators import DataRequired, ValidationError, Email, EqualTo +from wtforms import StringField, PasswordField, BooleanField, SubmitField, TextAreaField +from wtforms.validators import DataRequired, ValidationError, Email, EqualTo, Length import sqlalchemy as sa from app import db from app.models import User @@ -27,3 +27,8 @@ class RegistrationForm(FlaskForm): user = db.session.scalar(sa.select(User).where(User.email == email.data)) if user is not None: raise ValidationError('Please use a different email address.') + +class EditProfileForm(FlaskForm): + username = StringField('Username', validators=[DataRequired()]) + about_me = TextAreaField('About me', validators=[Length(min=0, max=140)]) + submit = SubmitField('Update') diff --git a/backend/app/models.py b/backend/app/models.py index 36c70a5..dc5a1a3 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -15,6 +15,8 @@ class User(UserMixin, db.Model): email: so.Mapped[str] = so.mapped_column(sa.String(120), index=True, unique=True) password_hash: so.Mapped[Optional[str]] = so.mapped_column(sa.String(256)) posts: so.WriteOnlyMapped['Post'] = so.relationship(back_populates='author') + about_me: so.Mapped[Optional[str]] = so.mapped_column(sa.String(140)) + last_seen: so.Mapped[Optional[datetime]] = so.mapped_column(default=lambda: datetime.now(timezone.utc)) def set_password(self, password): self.password_hash = generate_password_hash(password) @@ -41,7 +43,7 @@ class User(UserMixin, db.Model): pngfile.close() else: return str(base64.b64encode(pngicon))[2:-1] - def avatar(self): + def avatar_path(self): digest = hashlib.md5(self.email.lower().encode('utf-8')).hexdigest() basedir = os.path.abspath(os.path.dirname(__file__)) pngloc = os.path.join(basedir, 'usercontent', 'identicon', digest + '.png') diff --git a/backend/app/routes.py b/backend/app/routes.py index e301aaf..b11bcde 100644 --- a/backend/app/routes.py +++ b/backend/app/routes.py @@ -1,9 +1,11 @@ from flask import render_template, flash, redirect, url_for, request from urllib.parse import urlsplit +from datetime import datetime, timezone + from app import app, db -from app.forms import LoginForm, RegistrationForm -from flask_login import current_user, login_user, logout_user, login_required +from app.forms import LoginForm, RegistrationForm, EditProfileForm import sqlalchemy as sa +from flask_login import current_user, login_user, logout_user, login_required from app.models import User @app.route('/') @@ -25,6 +27,12 @@ def index(): #return posts; return render_template('index.html', title='Home', posts=posts) +@app.before_request +def before_request(): + if current_user.is_authenticated: + current_user.last_seen = datetime.now(timezone.utc) + db.session.commit() + @app.route('/login', methods=['GET', 'POST']) def login(): if current_user.is_authenticated: @@ -57,7 +65,7 @@ def register(): user.set_password(form.password.data) db.session.add(user) db.session.commit() - user.gen_avatar() + #user.gen_avatar() flash('User has been created.') return redirect(url_for('login')) return render_template('register.html', title='Register', form=form) @@ -71,3 +79,19 @@ def user(username): {'author': user, 'body': 'Test2?'} ] return render_template('user.html', user=user, posts=posts) + +@app.route('/edit_profile', methods=['GET', 'POST']) +@login_required +def edit_profile(): + form = EditProfileForm() + if form.validate_on_submit(): + current_user.username = form.username.data + current_user.about_me = form.about_me.data + db.session.commit() + flash('Profile changes have been saved.') + return redirect(url_for('edit_profile')) + elif request.method == 'GET': + form.username.data = current_user.username + form.about_me.data = current_user.about_me() + return render_template('edit_profile.html', title='Edit Profile', form=form) + diff --git a/backend/app/templates/edit_profile.html b/backend/app/templates/edit_profile.html new file mode 100644 index 0000000..e347134 --- /dev/null +++ b/backend/app/templates/edit_profile.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block content %} +

Edit Profile

+
+ {{ form.hidden_tag() }} +

+ {{ form.username.label }} + {{ form.username(size=32) }} + {% for error in form.username.errors %} + [{{ error }}] + {% endfor %} +

+

+ {{ form.about_me.label }} + {{ form.about_me(cols=50, rows=4) }} + {% for error in form.about_me.errors %} + [{{ error }}] + {% endfor %} +

+

{{ form.submit }}

+
+ +{% endblock %} diff --git a/backend/app/templates/user.html b/backend/app/templates/user.html index 508579a..beac920 100644 --- a/backend/app/templates/user.html +++ b/backend/app/templates/user.html @@ -4,9 +4,16 @@ - +

User: {{ user.username }}

+

User: {{ user.username }}

+ {% if user.about_me %}

{{ user.about_me }}

{% endif %} + {% if user.last_seen %}

Last activity:{{ user.last_seen }}

{% endif %} +
+ {% if user == current_user() %} +

Edit Profile

+ {% endif %}
{% for post in posts %} {% include '_post.html' %} diff --git a/backend/app/usercontent/identicon/39466ff4e782fc398fed2c3b21d53ba2.png b/backend/app/usercontent/identicon/39466ff4e782fc398fed2c3b21d53ba2.png deleted file mode 100644 index 0e771b051fbeddbf1dcb239e5d92f644de153806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^Js`}%1|-)VaI|A!V08C%aSW-r_4e*T&ISVk*Mlx= z6eH%hM$W&{Ql_BAQdh8y>EiKcTb6CRc8-bPH;%E%(SU>Ppn`+|50Ld_X0Tk!{aNb^ zlOy?s+1!Pi7=bb@%?UtBEG)3TpexJk7f99SulOE!KK@=mXR|UVM2`c+T%c}D7W31i zahG0Hz2{weCq3m5*a}QV2#w4zN3vjHfgO(U0!!CU{gvNq-4=WA>_6E8^&B>R2r&)E nYR?%U*EWDW3ev)I*j?PnQ7pQoqGly9WEnhN{an^LB{Ts5e}ZwQ diff --git a/backend/app/usercontent/identicon/686fed96bd36dc9ba0c0434036031942.png b/backend/app/usercontent/identicon/686fed96bd36dc9ba0c0434036031942.png deleted file mode 100644 index 88c2f586d2c7f0899eff624bcf733920f3d98936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmeAS@N?(olHy`uVBq!ia0vp^Js`}%1|-)VaI|A!U<~neaSW-r_4e*T&Q=2fhl4I_ z6mxIPD9`?ommIc4)v5+U_0250Awl7H$2TB zx$Nxz!o<7j!ffF}O^gQ>Bv_h3a#&bEZ3+^bR_u*m@axyTfG=_9l?A1qsjt%uNp$3hyhFnqF(q=*9p9p00i_>zopr0A(YCf&c&j diff --git a/backend/app/usercontent/identicon/7a651a7bab949a73092e21ad0bd2f4a8.png b/backend/app/usercontent/identicon/7a651a7bab949a73092e21ad0bd2f4a8.png deleted file mode 100644 index 20f3c735219733f4aea39ce0da4441423ab69c17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 378 zcmeAS@N?(olHy`uVBq!ia0vp^Js`}%1|-)VaI|A!V083!aSW-r_4e*Y&ISVkhd^b` zIS&r}G@AZ-r_-(*77b1<9`~dj{C>^}_2}x@cEEYHe?x)*Pm`ko2OCQ>koEZFVxCR1 z&zGNHpK89J7bF6dQ;-15H8CE<#=3C)ak1w)-kJB?4(fA4R5$>Q!^L9Wp83w(h*-0I zyE>j3Cme>_3o})K2ODe8g!Iab>)#u%O5L7_*9Bnj0^OJPaGy#Js^5O>=6