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 @@
+ {% if location %} + Bielefeld
+ {% endif %} {{ location }}
Inga Kirschnick
-Bio
+ {% if about_me%} +{{ about_me }}
+{{ email }}
-Webseite
-Organization
-Member since: {{ member_since }}
-Role: {{ role }}
++ | {{ full_name }} | +
+ | {{ email }} | +
+ | {{ website }} | +
+ | {{ organization }} | +
Member since: {{ member_since }}
+ +