From 102772d1a70f30f36c131e15abce4a807554e17b Mon Sep 17 00:00:00 2001 From: Inga Kirschnick Date: Tue, 29 Nov 2022 16:46:33 +0100 Subject: [PATCH 1/2] user settings page --- app/__init__.py | 3 + app/profile/__init__.py | 5 + app/profile/routes.py | 24 ++++ app/settings/forms.py | 44 +++++++ app/settings/routes.py | 13 ++- app/static/images/user_avatar.png | Bin 0 -> 2011 bytes app/templates/profile/profile_page.html.j2 | 42 +++++++ app/templates/settings/settings.html.j2 | 126 +++++++++++++-------- 8 files changed, 209 insertions(+), 48 deletions(-) create mode 100644 app/profile/__init__.py create mode 100644 app/profile/routes.py create mode 100644 app/static/images/user_avatar.png create mode 100644 app/templates/profile/profile_page.html.j2 diff --git a/app/__init__.py b/app/__init__.py index 78e208d1..960d4e90 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -77,6 +77,9 @@ def create_app(config: Config = Config) -> Flask: from .main import bp as main_blueprint app.register_blueprint(main_blueprint, url_prefix='/') + + from .profile import bp as profile_blueprint + app.register_blueprint(profile_blueprint, url_prefix='/profile') from .services import bp as services_blueprint app.register_blueprint(services_blueprint, url_prefix='/services') diff --git a/app/profile/__init__.py b/app/profile/__init__.py new file mode 100644 index 00000000..c8f843f4 --- /dev/null +++ b/app/profile/__init__.py @@ -0,0 +1,5 @@ +from flask import Blueprint + + +bp = Blueprint('profile', __name__) +from . import routes # noqa diff --git a/app/profile/routes.py b/app/profile/routes.py new file mode 100644 index 00000000..5487d417 --- /dev/null +++ b/app/profile/routes.py @@ -0,0 +1,24 @@ +from flask import render_template, url_for +from flask_login import current_user, login_required +from app import db +from app.models import User +from . import bp + + +@bp.route('') +@login_required +def profile(): + user_image = 'static/images/user_avatar.png' + user_name = current_user.username + last_seen = current_user.last_seen + member_since = current_user.member_since + email = current_user.email + role = current_user.role + return render_template('profile/profile_page.html.j2', + user_image=user_image, + user_name=user_name, + last_seen=last_seen, + member_since=member_since, + email=email, + role=role) + diff --git a/app/settings/forms.py b/app/settings/forms.py index 4e7eacf2..1403b501 100644 --- a/app/settings/forms.py +++ b/app/settings/forms.py @@ -1,10 +1,12 @@ from flask_wtf import FlaskForm from wtforms import ( BooleanField, + FileField, PasswordField, SelectField, StringField, SubmitField, + TextAreaField, ValidationError ) from wtforms.validators import ( @@ -47,6 +49,9 @@ class ChangePasswordForm(FlaskForm): class EditGeneralSettingsForm(FlaskForm): + user_avatar = FileField( + 'Image File' + ) email = StringField( 'E-Mail', validators=[InputRequired(), Length(max=254), Email()] @@ -65,8 +70,41 @@ class EditGeneralSettingsForm(FlaskForm): ) ] ) + full_name = StringField( + 'Full name', + validators=[Length(max=128)] + ) + bio = TextAreaField( + 'About me', + validators=[ + Length(max=254) + ] + ) + website = StringField( + 'Website', + validators=[ + Length(max=254) + ] + ) + organization = StringField( + 'Organization', + validators=[ + Length(max=128) + ] + ) + location = StringField( + 'Location', + validators=[ + Length(max=128) + ] + ) + submit = SubmitField() + def validate_image_file(self, field): + if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'): + raise ValidationError('only .jpg, .png and .jpeg!') + def __init__(self, user, *args, **kwargs): super().__init__(*args, **kwargs) self.user = user @@ -96,3 +134,9 @@ class EditNotificationSettingsForm(FlaskForm): (x.name, x.name.capitalize()) for x in UserSettingJobStatusMailNotificationLevel ] + +class EditPrivacySettingsForm(FlaskForm): + public_profile = BooleanField( + 'Public profile' + ) + submit = SubmitField() diff --git a/app/settings/routes.py b/app/settings/routes.py index 26b7fdda..42400136 100644 --- a/app/settings/routes.py +++ b/app/settings/routes.py @@ -6,7 +6,8 @@ from . import bp from .forms import ( ChangePasswordForm, EditGeneralSettingsForm, - EditNotificationSettingsForm + EditNotificationSettingsForm, + EditPrivacySettingsForm ) @@ -26,7 +27,10 @@ def settings(): data=current_user.to_json_serializeable(), prefix='edit-notification-settings-form' ) - + edit_privacy_settings_form = EditPrivacySettingsForm( + data=current_user.to_json_serializeable(), + prefix='edit-privacy-settings-form' + ) if change_password_form.submit.data and change_password_form.validate(): current_user.password = change_password_form.new_password.data db.session.commit() @@ -49,10 +53,13 @@ def settings(): db.session.commit() flash('Your changes have been saved') return redirect(url_for('.settings')) + user_image = 'static/images/user_avatar.png' return render_template( 'settings/settings.html.j2', change_password_form=change_password_form, edit_general_settings_form=edit_general_settings_form, edit_notification_settings_form=edit_notification_settings_form, - title='Settings' + edit_privacy_settings_form=edit_privacy_settings_form, + user_image=user_image, + title='Profile & Settings' ) diff --git a/app/static/images/user_avatar.png b/app/static/images/user_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..09892098aa943af5fe95e7dd434a07fe03e7ccd1 GIT binary patch literal 2011 zcmV<12PF83P)D!y%g4vZ*x1<2%*?Q`u)x5;+S=OH)zz}HvdGBD zw6wIs!oteR%FWHqrlzLJ$;r^r(7(UGt*x!9s;a}o!>FjJ#>U3Iy}i%R&$YF+x3{;h zuCCtR-nO>3udlDMv9Z$9(zv*|ySuyA*4EqG+ZlWNivR!y*-1n}RCr$O+*gj>NDPM2 zpNco<96RTn9rwSi8F&oCZFlz#Qq{xgJ4+x4LZrx&UjP6A00000000000000000000 z0000000000h)13Iv~gIg9X6)(&Ma2$kko6>k^LchuGJIe1?9VT%ih&$-<6da;(GtY zRygU`V`YKSGPJdX%aOK)>O)}bd#Gv~*uA$6-S28s*y-CA`a9YL;;WKvrF0c*ZKyul z)*h=`7wH^W2Elqsjqd}?Xz*Ptp%PkVVMQxo5?Bs`i9Upe<)onxU}?Eo>Ro7Cj@nv* ze0H1D=vvOYdIRQ`ySe^?YRPg}s_G9&F3o|+E;KJf72K|Qva4ddGB4O%8ki>o6?HI`i*6#+w#5|Y?<y|LwN+|wJ-DOs*c9lZ(lz;YDS^$r~880p|x z??Sy~IVsik0el`?F2Y>=KFtcZ1R zaGELyc&axa?H!NJ`jhg5v~%-y@6vvAx%c&^lgbGsy=v!Q)n20Y000000000000000 z0000001(G=0_9$3(l{U9f4Ydqf&CDSql-`X!}G?Z(<>_@q?M!EmqlnRgo`h=qe`mH zp^F!L#dKMP=0-j66q)X!m2_UKU< z?=gcl`PrjD-Z_UQ!Oo*l-Y$R@ac4on7M&O-j9L_~HG+QG8x@#l(9NwQst~Om6uTU# z#^D0B?jkA@-9e`x4^-yi2NWuOs^gbXXX{ZRZwp;qmr8Y=vc4+;?DuSiV=6Wdp+vB! zYWn~xgnKHt51~MOqTGjPD@PoaW3S(TV1qAdpLGPU;{}n+CNZ&z1&l zAk)yBhI<>K$Szko#25&!NK0f~qZEphQ8{ z3aIf)#a^Mvnrf|~$}^REhB95M)P*|TX3iCPq&kn#$aR|+5*6uFl|Ix;s7M0Ewp3#a z)kYpw@J3LsOsPOxLcOd<@p>5y2p=fiLkJUGpQ800tayqjR`dizEyTFw96Gb|` z!YX_?aV~Q~zz%VD}8+~-=U|TkA>Od+oZ}G}nbJRjS zi+DxREJj@nPrRDb5Owl07n$q)ia(q8)f$NXg*KhY?6EB-U9U5WqIxO65S z|C%@HT<{BxaK1b6FYI^o5WlAp7RhA6Kem`8MTkGt$mX+;7JpOgV>ZtqfL8IK*!Dm6 zzQ>>P{QXCNTMXj=+Nnb$0D%|)f;hy>mx(1hlm3f?BA8dZ4V=5bdfd6DDtbSk-BC3w tPksUb00000000000000000000fEW70#Mag`cL)Fg002ovPDHLkV1gNB=am2e literal 0 HcmV?d00001 diff --git a/app/templates/profile/profile_page.html.j2 b/app/templates/profile/profile_page.html.j2 new file mode 100644 index 00000000..cf724303 --- /dev/null +++ b/app/templates/profile/profile_page.html.j2 @@ -0,0 +1,42 @@ +{% extends "base.html.j2" %} +{% import "materialize/wtf.html.j2" as wtf %} + +{% block page_content %} +
+
+
+
+
+
+
+
+ user-image +
+
+
+

{{ user_name }}

+
Last seen: {{ last_seen }}
+

location_onBielefeld

+

+
+

Inga Kirschnick

+

Bio

+
+
+
+
+
+

{{ email }}

+

Webseite

+

Organization

+

Member since: {{ member_since }}

+

Role: {{ role }}

+
+
+
+
+
+
+
+ +{% endblock page_content %} diff --git a/app/templates/settings/settings.html.j2 b/app/templates/settings/settings.html.j2 index e229a382..a61e77ad 100644 --- a/app/templates/settings/settings.html.j2 +++ b/app/templates/settings/settings.html.j2 @@ -14,63 +14,99 @@ {{ edit_general_settings_form.hidden_tag() }}
- General settings - {{ wtf.render_field(edit_general_settings_form.username, material_icon='person') }} - {{ wtf.render_field(edit_general_settings_form.email, material_icon='email') }} + Your profile +
+
+
+ user-image + {{wtf.render_field(edit_general_settings_form.user_avatar, accept='image/*', class='file-path validate')}} +
+
+
+ {{ wtf.render_field(edit_general_settings_form.username, material_icon='person') }} + {{ wtf.render_field(edit_general_settings_form.email, material_icon='email') }} + {{ wtf.render_field(edit_general_settings_form.full_name, material_icon='badge') }} + {{ wtf.render_field(edit_general_settings_form.bio, material_icon='description') }} +
+
+
+
+ {{ wtf.render_field(edit_general_settings_form.website, material_icon='laptop') }} + {{ wtf.render_field(edit_general_settings_form.organization, material_icon='business') }} + {{ wtf.render_field(edit_general_settings_form.location, material_icon='location_on') }} +
+
{{ wtf.render_field(edit_general_settings_form.submit, material_icon='send') }}
- -
- + + -
- {{ edit_notification_settings_form.hidden_tag() }}
- Notification settings - {{ wtf.render_field(edit_notification_settings_form.job_status_mail_notification_level, material_icon='notifications') }} -
-
-
- {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} + Settings + + {{ edit_notification_settings_form.hidden_tag() }} +
+
+ Notification settings + {{ wtf.render_field(edit_notification_settings_form.job_status_mail_notification_level, material_icon='notifications') }} +
+
+
+ {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} +
+
+
+ + +
+
+ Privacy settings + {{ wtf.render_field(edit_privacy_settings_form.public_profile) }} +
+
+
+ {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} +
+
+
+ +
+ {{ change_password_form.hidden_tag() }} +
+
+ Change Password + {{ wtf.render_field(change_password_form.password, material_icon='vpn_key') }} + {{ wtf.render_field(change_password_form.new_password, material_icon='vpn_key') }} + {{ wtf.render_field(change_password_form.new_password_2, material_icon='vpn_key') }} +
+
+
+ {{ wtf.render_field(change_password_form.submit, material_icon='send') }} +
+
+
+
+ +
+
+ Delete account +

Deleting an account has the following effects:

+
    +
  • All data associated with your corpora and jobs will be permanently deleted.
  • +
  • All settings will be permanently deleted.
  • +
+
+
- - -
- {{ change_password_form.hidden_tag() }} -
-
- Change Password - {{ wtf.render_field(change_password_form.password, material_icon='vpn_key') }} - {{ wtf.render_field(change_password_form.new_password, material_icon='vpn_key') }} - {{ wtf.render_field(change_password_form.new_password_2, material_icon='vpn_key') }} -
-
-
- {{ wtf.render_field(change_password_form.submit, material_icon='send') }} -
-
-
-
- -
-
- Delete account -

Deleting an account has the following effects:

-
    -
  • All data associated with your corpora and jobs will be permanently deleted.
  • -
  • All settings will be permanently deleted.
  • -
-
-
From a009bbe1f941f9adfd178182ae255f804b574e2d Mon Sep 17 00:00:00 2001 From: Inga Kirschnick Date: Wed, 30 Nov 2022 14:36:42 +0100 Subject: [PATCH 2/2] Profile page --- app/admin/routes.py | 16 +-- app/models.py | 5 + app/profile/forms.py | 87 ++++++++++++++ app/profile/routes.py | 55 +++++++-- app/settings/forms.py | 12 +- app/settings/routes.py | 19 +--- app/templates/_sidenav.html.j2 | 12 +- app/templates/profile/edit_profile.html.j2 | 43 +++++++ app/templates/profile/profile_page.html.j2 | 61 ++++++++-- app/templates/settings/settings.html.j2 | 125 +++++++-------------- migrations/versions/4820fa2e3ee2_.py | 44 ++++++++ 11 files changed, 345 insertions(+), 134 deletions(-) create mode 100644 app/profile/forms.py create mode 100644 app/templates/profile/edit_profile.html.j2 create mode 100644 migrations/versions/4820fa2e3ee2_.py diff --git a/app/admin/routes.py b/app/admin/routes.py index c4480e18..90d9034d 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -5,7 +5,7 @@ from app import db, hashids from app.decorators import admin_required from app.models import Role, User, UserSettingJobStatusMailNotificationLevel from app.settings.forms import ( - EditGeneralSettingsForm, + EditProfileSettingsForm, EditNotificationSettingsForm ) from . import bp @@ -51,10 +51,10 @@ def edit_user(user_id): data={'confirmed': user.confirmed, 'role': user.role.hashid}, prefix='admin-edit-user-form' ) - edit_general_settings_form = EditGeneralSettingsForm( + edit_profile_settings_form = EditProfileSettingsForm( user, data=user.to_json_serializeable(), - prefix='edit-general-settings-form' + prefix='edit-profile-settings-form' ) edit_notification_settings_form = EditNotificationSettingsForm( data=user.to_json_serializeable(), @@ -68,10 +68,10 @@ def edit_user(user_id): db.session.commit() flash('Your changes have been saved') return redirect(url_for('.edit_user', user_id=user.id)) - if (edit_general_settings_form.submit.data - and edit_general_settings_form.validate()): - user.email = edit_general_settings_form.email.data - user.username = edit_general_settings_form.username.data + if (edit_profile_settings_form.submit.data + and edit_profile_settings_form.validate()): + user.email = edit_profile_settings_form.email.data + user.username = edit_profile_settings_form.username.data db.session.commit() flash('Your changes have been saved') return redirect(url_for('.edit_user', user_id=user.id)) @@ -87,7 +87,7 @@ def edit_user(user_id): return render_template( 'admin/edit_user.html.j2', admin_edit_user_form=admin_edit_user_form, - edit_general_settings_form=edit_general_settings_form, + edit_profile_settings_form=edit_profile_settings_form, edit_notification_settings_form=edit_notification_settings_form, title='Edit user', user=user diff --git a/app/models.py b/app/models.py index c607dc5f..62d0d99b 100644 --- a/app/models.py +++ b/app/models.py @@ -262,6 +262,11 @@ class User(HashidMixin, UserMixin, db.Model): default=UserSettingJobStatusMailNotificationLevel.END ) last_seen = db.Column(db.DateTime()) + full_name = db.Column(db.String(64)) + about_me = db.Column(db.String(256)) + location = db.Column(db.String(64)) + website = db.Column(db.String(128)) + organization = db.Column(db.String(128)) # Backrefs: role: Role # Relationships tesseract_ocr_pipeline_models = db.relationship( diff --git a/app/profile/forms.py b/app/profile/forms.py new file mode 100644 index 00000000..bcb9daf9 --- /dev/null +++ b/app/profile/forms.py @@ -0,0 +1,87 @@ +from flask_wtf import FlaskForm +from wtforms import ( + FileField, + StringField, + SubmitField, + TextAreaField, + ValidationError +) +from wtforms.validators import ( + InputRequired, + Email, + Length, + Regexp +) +from app.models import User +from app.auth import USERNAME_REGEX + +class EditProfileSettingsForm(FlaskForm): + user_avatar = FileField( + 'Image File' + ) + email = StringField( + 'E-Mail', + validators=[InputRequired(), Length(max=254), Email()] + ) + username = StringField( + 'Username', + validators=[ + InputRequired(), + Length(max=64), + Regexp( + USERNAME_REGEX, + message=( + 'Usernames must have only letters, numbers, dots or ' + 'underscores' + ) + ) + ] + ) + full_name = StringField( + 'Full name', + validators=[Length(max=128)] + ) + about_me = TextAreaField( + 'About me', + validators=[ + Length(max=254) + ] + ) + website = StringField( + 'Website', + validators=[ + Length(max=254) + ] + ) + organization = StringField( + 'Organization', + validators=[ + Length(max=128) + ] + ) + location = StringField( + 'Location', + validators=[ + Length(max=128) + ] + ) + + submit = SubmitField() + + def __init__(self, user, *args, **kwargs): + super().__init__(*args, **kwargs) + self.user = user + + def validate_email(self, field): + if (field.data != self.user.email + and User.query.filter_by(email=field.data).first()): + raise ValidationError('Email already registered') + + def validate_username(self, field): + if (field.data != self.user.username + and User.query.filter_by(username=field.data).first()): + raise ValidationError('Username already in use') + + def validate_image_file(self, field): + if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'): + raise ValidationError('only .jpg, .png and .jpeg!') diff --git a/app/profile/routes.py b/app/profile/routes.py index 5487d417..8001ddb4 100644 --- a/app/profile/routes.py +++ b/app/profile/routes.py @@ -1,24 +1,61 @@ -from flask import render_template, url_for +from flask import flash, redirect, render_template, url_for from flask_login import current_user, login_required from app import db from app.models import User from . import bp - +from .forms import ( + EditProfileSettingsForm +) @bp.route('') @login_required def profile(): user_image = 'static/images/user_avatar.png' user_name = current_user.username - last_seen = current_user.last_seen - member_since = current_user.member_since + last_seen = f'{current_user.last_seen.strftime("%Y-%m-%d %H:%M")}' + location = 'Bielefeld' + about_me = '''Lorem ipsum dolor sit amet, consetetur sadipscing elitr, + sed diam nonumy eirmod tempor invidunt ut labore et dolore + magna aliquyam erat, sed diam voluptua. At vero eos et accusam + et justo duo dolores et ea rebum. Stet clita kasd gubergren, + no sea takimat''' + full_name = 'Inga Kirschnick' email = current_user.email - role = current_user.role + website = 'https://nopaque.uni-bielefeld.de' + organization = 'Universität Bielefeld' + member_since = f'{current_user.member_since.strftime("%Y-%m-%d")}' return render_template('profile/profile_page.html.j2', user_image=user_image, user_name=user_name, - last_seen=last_seen, - member_since=member_since, - email=email, - role=role) + last_seen=last_seen, + location=location, + about_me=about_me, + full_name=full_name, + email=email, + website=website, + organization=organization, + member_since=member_since) +@bp.route('/edit') +@login_required +def edit_profile(): + edit_profile_settings_form = EditProfileSettingsForm( + current_user, + data=current_user.to_json_serializeable(), + prefix='edit-profile-settings-form' + ) + if (edit_profile_settings_form.submit.data + and edit_profile_settings_form.validate()): + current_user.email = edit_profile_settings_form.email.data + current_user.username = edit_profile_settings_form.username.data + current_user.about_me = edit_profile_settings_form.about_me.data + current_user.location = edit_profile_settings_form.location.data + current_user.organization = edit_profile_settings_form.organization.data + current_user.website = edit_profile_settings_form.website.data + current_user.full_name = edit_profile_settings_form.full_name.data + db.session.commit() + flash('Your changes have been saved') + return redirect(url_for('.profile.edit_profile')) + return render_template('profile/edit_profile.html.j2', + edit_profile_settings_form=edit_profile_settings_form, + title='Edit Profile') diff --git a/app/settings/forms.py b/app/settings/forms.py index 1403b501..25bb5f1f 100644 --- a/app/settings/forms.py +++ b/app/settings/forms.py @@ -48,7 +48,7 @@ class ChangePasswordForm(FlaskForm): raise ValidationError('Invalid password') -class EditGeneralSettingsForm(FlaskForm): +class EditProfileSettingsForm(FlaskForm): user_avatar = FileField( 'Image File' ) @@ -74,7 +74,7 @@ class EditGeneralSettingsForm(FlaskForm): 'Full name', validators=[Length(max=128)] ) - bio = TextAreaField( + about_me = TextAreaField( 'About me', validators=[ Length(max=254) @@ -101,10 +101,6 @@ class EditGeneralSettingsForm(FlaskForm): submit = SubmitField() - def validate_image_file(self, field): - if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'): - raise ValidationError('only .jpg, .png and .jpeg!') - def __init__(self, user, *args, **kwargs): super().__init__(*args, **kwargs) self.user = user @@ -118,6 +114,10 @@ class EditGeneralSettingsForm(FlaskForm): if (field.data != self.user.username and User.query.filter_by(username=field.data).first()): raise ValidationError('Username already in use') + + def validate_image_file(self, field): + if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'): + raise ValidationError('only .jpg, .png and .jpeg!') class EditNotificationSettingsForm(FlaskForm): diff --git a/app/settings/routes.py b/app/settings/routes.py index 42400136..d7e36218 100644 --- a/app/settings/routes.py +++ b/app/settings/routes.py @@ -5,7 +5,6 @@ from app.models import UserSettingJobStatusMailNotificationLevel from . import bp from .forms import ( ChangePasswordForm, - EditGeneralSettingsForm, EditNotificationSettingsForm, EditPrivacySettingsForm ) @@ -18,11 +17,6 @@ def settings(): current_user, prefix='change-password-form' ) - edit_general_settings_form = EditGeneralSettingsForm( - current_user, - data=current_user.to_json_serializeable(), - prefix='edit-general-settings-form' - ) edit_notification_settings_form = EditNotificationSettingsForm( data=current_user.to_json_serializeable(), prefix='edit-notification-settings-form' @@ -36,13 +30,7 @@ def settings(): db.session.commit() flash('Your changes have been saved') return redirect(url_for('.index')) - if (edit_general_settings_form.submit.data - and edit_general_settings_form.validate()): - current_user.email = edit_general_settings_form.email.data - current_user.username = edit_general_settings_form.username.data - db.session.commit() - flash('Your changes have been saved') - return redirect(url_for('.settings')) + if (edit_notification_settings_form.submit.data and edit_notification_settings_form.validate()): current_user.setting_job_status_mail_notification_level = ( @@ -53,13 +41,10 @@ def settings(): db.session.commit() flash('Your changes have been saved') return redirect(url_for('.settings')) - user_image = 'static/images/user_avatar.png' return render_template( 'settings/settings.html.j2', change_password_form=change_password_form, - edit_general_settings_form=edit_general_settings_form, edit_notification_settings_form=edit_notification_settings_form, edit_privacy_settings_form=edit_privacy_settings_form, - user_image=user_image, - title='Profile & Settings' + title='Settings' ) diff --git a/app/templates/_sidenav.html.j2 b/app/templates/_sidenav.html.j2 index b0ea6de8..f87f701e 100644 --- a/app/templates/_sidenav.html.j2 +++ b/app/templates/_sidenav.html.j2 @@ -2,8 +2,16 @@
  • - {{ current_user.username }} - +
    + + +
    + {{ current_user.username }} + +
    +
  • nopaque
  • diff --git a/app/templates/profile/edit_profile.html.j2 b/app/templates/profile/edit_profile.html.j2 new file mode 100644 index 00000000..3a5ce381 --- /dev/null +++ b/app/templates/profile/edit_profile.html.j2 @@ -0,0 +1,43 @@ +{% extends "base.html.j2" %} +{% import "materialize/wtf.html.j2" as wtf %} + +{% block page_content %} +
    +
    +
    +

    {{ title }}

    +
    +
    +
    + {{ edit_profile_settings_form.hidden_tag() }} +
    +
    +
    +
    +
    + user-image + {{wtf.render_field(edit_profile_settings_form.user_avatar, accept='image/*', class='file-path validate')}} +
    +
    +
    + {{ wtf.render_field(edit_profile_settings_form.username, material_icon='person') }} + {{ wtf.render_field(edit_profile_settings_form.email, material_icon='email') }} + {{ wtf.render_field(edit_profile_settings_form.full_name, material_icon='badge') }} + {{ wtf.render_field(edit_profile_settings_form.about_me, material_icon='description') }} + {{ wtf.render_field(edit_profile_settings_form.website, material_icon='laptop') }} + {{ wtf.render_field(edit_profile_settings_form.organization, material_icon='business') }} + {{ wtf.render_field(edit_profile_settings_form.location, material_icon='location_on') }} +
    +
    +
    +
    +
    + {{ wtf.render_field(edit_profile_settings_form.submit, material_icon='send') }} +
    +
    +
    +
    +
    +
    +
    +{% endblock page_content %} diff --git a/app/templates/profile/profile_page.html.j2 b/app/templates/profile/profile_page.html.j2 index cf724303..fd4648aa 100644 --- a/app/templates/profile/profile_page.html.j2 +++ b/app/templates/profile/profile_page.html.j2 @@ -10,33 +10,76 @@
    + {% if about_me %} + user-image + {% else %} user-image + {% endif %}

    {{ user_name }}

    Last seen: {{ last_seen }}
    -

    location_onBielefeld

    + {% if location %} +

    location_on{{ location }}

    + {% endif %}


    -

    Inga Kirschnick

    -

    Bio

    + {% if about_me%} +
    +
    + About me +

    {{ about_me }}

    +
    +
    + {% endif %}
    -

    {{ email }}

    -

    Webseite

    -

    Organization

    -

    Member since: {{ member_since }}

    -

    Role: {{ role }}

    + + {% if full_name %} + + + + + {% endif %} + {% if email %} + + + + + {% endif %} + {% if website %} + + + + + {% endif %} + {% if organization %} + + + + + {% endif %} +
    person{{ full_name }}
    email{{ email }}
    laptop{{ website }}
    business{{ organization }}
    +
    +

    Member since: {{ member_since }}

    +

    +
    + Edit profile
    - +
    +
    + +
    + +
    {% endblock page_content %} diff --git a/app/templates/settings/settings.html.j2 b/app/templates/settings/settings.html.j2 index a61e77ad..b33ab0a1 100644 --- a/app/templates/settings/settings.html.j2 +++ b/app/templates/settings/settings.html.j2 @@ -8,38 +8,46 @@

    {{ title }}

    -
    - {{ edit_general_settings_form.hidden_tag() }} + {{ edit_notification_settings_form.hidden_tag() }}
    - Your profile -
    -
    -
    - user-image - {{wtf.render_field(edit_general_settings_form.user_avatar, accept='image/*', class='file-path validate')}} -
    -
    -
    - {{ wtf.render_field(edit_general_settings_form.username, material_icon='person') }} - {{ wtf.render_field(edit_general_settings_form.email, material_icon='email') }} - {{ wtf.render_field(edit_general_settings_form.full_name, material_icon='badge') }} - {{ wtf.render_field(edit_general_settings_form.bio, material_icon='description') }} -
    -
    -
    -
    - {{ wtf.render_field(edit_general_settings_form.website, material_icon='laptop') }} - {{ wtf.render_field(edit_general_settings_form.organization, material_icon='business') }} - {{ wtf.render_field(edit_general_settings_form.location, material_icon='location_on') }} -
    -
    + Notification settings + {{ wtf.render_field(edit_notification_settings_form.job_status_mail_notification_level, material_icon='notifications') }}
    - {{ wtf.render_field(edit_general_settings_form.submit, material_icon='send') }} + {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} +
    +
    +
    +
    + +
    +
    + Privacy settings + {{ wtf.render_field(edit_privacy_settings_form.public_profile) }} +
    +
    +
    + {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} +
    +
    +
    + +
    + {{ change_password_form.hidden_tag() }} +
    +
    + Change Password + {{ wtf.render_field(change_password_form.password, material_icon='vpn_key') }} + {{ wtf.render_field(change_password_form.new_password, material_icon='vpn_key') }} + {{ wtf.render_field(change_password_form.new_password_2, material_icon='vpn_key') }} +
    +
    +
    + {{ wtf.render_field(change_password_form.submit, material_icon='send') }}
    @@ -47,64 +55,15 @@
    - Settings - - {{ edit_notification_settings_form.hidden_tag() }} -
    -
    - Notification settings - {{ wtf.render_field(edit_notification_settings_form.job_status_mail_notification_level, material_icon='notifications') }} -
    -
    -
    - {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} -
    -
    -
    - - -
    -
    - Privacy settings - {{ wtf.render_field(edit_privacy_settings_form.public_profile) }} -
    -
    -
    - {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} -
    -
    -
    - -
    - {{ change_password_form.hidden_tag() }} -
    -
    - Change Password - {{ wtf.render_field(change_password_form.password, material_icon='vpn_key') }} - {{ wtf.render_field(change_password_form.new_password, material_icon='vpn_key') }} - {{ wtf.render_field(change_password_form.new_password_2, material_icon='vpn_key') }} -
    -
    -
    - {{ wtf.render_field(change_password_form.submit, material_icon='send') }} -
    -
    -
    -
    - -
    -
    - Delete account -

    Deleting an account has the following effects:

    -
      -
    • All data associated with your corpora and jobs will be permanently deleted.
    • -
    • All settings will be permanently deleted.
    • -
    -
    - -
    + Delete account +

    Deleting an account has the following effects:

    +
      +
    • All data associated with your corpora and jobs will be permanently deleted.
    • +
    • All settings will be permanently deleted.
    • +
    +
    +
    diff --git a/migrations/versions/4820fa2e3ee2_.py b/migrations/versions/4820fa2e3ee2_.py new file mode 100644 index 00000000..4f821f66 --- /dev/null +++ b/migrations/versions/4820fa2e3ee2_.py @@ -0,0 +1,44 @@ +"""Add profile pages columns to users table + +Revision ID: 4820fa2e3ee2 +Revises: 31b9c0259e6b +Create Date: 2022-11-30 10:03:49.080576 + +""" +from alembic import op +import sqlalchemy as sa + +revision = '4820fa2e3ee2' +down_revision = '31b9c0259e6b' +branch_labels = None +depends_on = None + +def upgrade(): + + op.add_column( + 'users', + sa.Column('full_name', sa.String(length=64), nullable=True) + ) + op.add_column( + 'users', + sa.Column('about_me', sa.String(length=256), nullable=True) + ) + op.add_column( + 'users', + sa.Column('location', sa.String(length=64), nullable=True) + ) + op.add_column( + 'users', + sa.Column('website', sa.String(length=128), nullable=True) + ) + op.add_column( + 'users', + sa.Column('organization', sa.String(length=128), nullable=True) + ) + +def downgrade(): + op.drop_column('users', 'organization') + op.drop_column('users', 'website') + op.drop_column('users', 'location') + op.drop_column('users', 'about_me') + op.drop_column('users', 'full_name')