This commit is contained in:
Patrick Jentsch 2023-03-23 17:42:51 +01:00
parent 57813b4bc2
commit 5b6eae7645
7 changed files with 177 additions and 158 deletions

View File

@ -2,8 +2,8 @@ from flask import flash, redirect, render_template, request, url_for
from flask_breadcrumbs import register_breadcrumb from flask_breadcrumbs import register_breadcrumb
from app import db, hashids from app import db, hashids
from app.models import Corpus, Role, User, UserSettingJobStatusMailNotificationLevel from app.models import Corpus, Role, User, UserSettingJobStatusMailNotificationLevel
from app.settings.forms import EditNotificationSettingsForm from app.settings.forms import EditNotificationsForm
from app.settings.forms import EditProfileSettingsForm from app.settings.forms import EditAccountForm
from . import bp from . import bp
from .forms import AdminEditUserForm from .forms import AdminEditUserForm
from app.users.utils import ( from app.users.utils import (
@ -24,22 +24,22 @@ def admin():
@bp.route('/corpora') @bp.route('/corpora')
@register_breadcrumb(bp, '.corpora', 'Corpora') @register_breadcrumb(bp, '.corpora', 'Corpora')
def corpora(): def corpora():
corpora = [x.to_json_serializeable(backrefs=True) for x in Corpus.query.all()] corpora = Corpus.query.all()
return render_template( return render_template(
'admin/corpora.html.j2', 'admin/corpora.html.j2',
corpora=corpora, title='Corpora',
title='Corpora' corpora=corpora
) )
@bp.route('/users') @bp.route('/users')
@register_breadcrumb(bp, '.users', '<i class="material-icons left">group</i>Users') @register_breadcrumb(bp, '.users', '<i class="material-icons left">group</i>Users')
def users(): def users():
users = [x.to_json_serializeable(backrefs=True) for x in User.query.all()] users = User.query.all()
return render_template( return render_template(
'admin/users.html.j2', 'admin/users.html.j2',
users=users, title='Users',
title='Users' users=users
) )
@ -47,13 +47,11 @@ def users():
@register_breadcrumb(bp, '.users.entity', '', dynamic_list_constructor=user_dlc) @register_breadcrumb(bp, '.users.entity', '', dynamic_list_constructor=user_dlc)
def user(user_id): def user(user_id):
user = User.query.get_or_404(user_id) user = User.query.get_or_404(user_id)
return render_template('admin/user.html.j2', title=user.username, user=user) return render_template(
'admin/user.html.j2',
title=user.username,
@bp.route('/users/<hashid:user_id>/dashboard') user=user
@register_breadcrumb(bp, '.users.entity.dashboard', 'Dashboard', endpoint_arguments_constructor=user_eac) )
def user_dashboard(user_id):
return render_template('main/dashboard.html.j2', title='Dashboard')
@bp.route('/users/<hashid:user_id>/edit', methods=['GET', 'POST']) @bp.route('/users/<hashid:user_id>/edit', methods=['GET', 'POST'])
@ -64,12 +62,12 @@ def edit_user(user_id):
data={'confirmed': user.confirmed, 'role': user.role.hashid}, data={'confirmed': user.confirmed, 'role': user.role.hashid},
prefix='admin-edit-user-form' prefix='admin-edit-user-form'
) )
edit_profile_settings_form = EditProfileSettingsForm( edit_profile_settings_form = EditAccountForm(
user, user,
data=user.to_json_serializeable(), data=user.to_json_serializeable(),
prefix='edit-profile-settings-form' prefix='edit-profile-settings-form'
) )
edit_notification_settings_form = EditNotificationSettingsForm( edit_notification_settings_form = EditNotificationsForm(
data=user.to_json_serializeable(), data=user.to_json_serializeable(),
prefix='edit-notification-settings-form' prefix='edit-notification-settings-form'
) )

View File

@ -1,3 +1,4 @@
from flask_login import current_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import ( from wtforms import (
BooleanField, BooleanField,
@ -20,7 +21,8 @@ from app.models import User, UserSettingJobStatusMailNotificationLevel
from app.auth import USERNAME_REGEX from app.auth import USERNAME_REGEX
from app.wtf_validators import FileSizeLimit from app.wtf_validators import FileSizeLimit
class EditProfileSettingsForm(FlaskForm):
class EditAccountForm(FlaskForm):
email = StringField( email = StringField(
'E-Mail', 'E-Mail',
validators=[DataRequired(), Length(max=254), Email()] validators=[DataRequired(), Length(max=254), Email()]
@ -41,7 +43,12 @@ class EditProfileSettingsForm(FlaskForm):
) )
submit = SubmitField() submit = SubmitField()
def __init__(self, user, *args, **kwargs): def __init__(self, *args, **kwargs):
user = kwargs.get('user', current_user._get_current_object())
if 'data' not in kwargs:
kwargs['data'] = user.to_json_serializeable()
if 'prefix' not in kwargs:
kwargs['prefix'] = 'edit-profile-settings-form'
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.user = user self.user = user
@ -55,7 +62,11 @@ class EditProfileSettingsForm(FlaskForm):
and User.query.filter_by(username=field.data).first()): and User.query.filter_by(username=field.data).first()):
raise ValidationError('Username already in use') raise ValidationError('Username already in use')
class EditPublicProfileInformationForm(FlaskForm): def validate_on_submit(self):
return self.submit.data and self.validate()
class EditProfileForm(FlaskForm):
show_email = BooleanField('Email') show_email = BooleanField('Email')
show_last_seen = BooleanField('Last seen') show_last_seen = BooleanField('Last seen')
show_member_since = BooleanField('Member since') show_member_since = BooleanField('Member since')
@ -67,13 +78,11 @@ class EditPublicProfileInformationForm(FlaskForm):
'Full name', 'Full name',
validators=[Length(max=128)] validators=[Length(max=128)]
) )
style={'style': 'overflow: auto;'}
about_me = TextAreaField( about_me = TextAreaField(
'About me', 'About me',
validators=[ validators=[
Length(max=254) Length(max=254)
], ]
render_kw=style
) )
website = StringField( website = StringField(
'Website', 'Website',
@ -93,13 +102,24 @@ class EditPublicProfileInformationForm(FlaskForm):
Length(max=128) Length(max=128)
] ]
) )
submit = SubmitField() submit = SubmitField()
def __init__(self, *args, **kwargs):
if 'data' not in kwargs:
user = current_user._get_current_object()
kwargs['data'] = user.to_json_serializeable()
if 'prefix' not in kwargs:
kwargs['prefix'] = 'edit-public-profile-information-form'
super().__init__(*args, **kwargs)
def validate_image_file(self, field): def validate_image_file(self, field):
if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'): if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'):
raise ValidationError('only .jpg, .png and .jpeg!') raise ValidationError('only .jpg, .png and .jpeg!')
def validate_on_submit(self):
return self.submit.data and self.validate()
class ChangePasswordForm(FlaskForm): class ChangePasswordForm(FlaskForm):
password = PasswordField('Old password', validators=[DataRequired()]) password = PasswordField('Old password', validators=[DataRequired()])
new_password = PasswordField( new_password = PasswordField(
@ -118,7 +138,10 @@ class ChangePasswordForm(FlaskForm):
) )
submit = SubmitField() submit = SubmitField()
def __init__(self, user, *args, **kwargs): def __init__(self, *args, **kwargs):
user = kwargs.get('user', current_user._get_current_object())
if 'prefix' not in kwargs:
kwargs['prefix'] = 'change-password-form'
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.user = user self.user = user
@ -126,8 +149,11 @@ class ChangePasswordForm(FlaskForm):
if not self.user.verify_password(field.data): if not self.user.verify_password(field.data):
raise ValidationError('Invalid password') raise ValidationError('Invalid password')
def validate_on_submit(self):
return self.submit.data and self.validate()
class EditNotificationSettingsForm(FlaskForm):
class EditNotificationsForm(FlaskForm):
job_status_mail_notification_level = SelectField( job_status_mail_notification_level = SelectField(
'Job status mail notification level', 'Job status mail notification level',
choices=[ choices=[
@ -137,3 +163,14 @@ class EditNotificationSettingsForm(FlaskForm):
validators=[DataRequired()] validators=[DataRequired()]
) )
submit = SubmitField() submit = SubmitField()
def __init__(self, *args, **kwargs):
if 'data' not in kwargs:
user = current_user._get_current_object()
kwargs['data'] = user.to_json_serializeable()
if 'prefix' not in kwargs:
kwargs['prefix'] = 'edit-notification-settings-form'
super().__init__(*args, **kwargs)
def validate_on_submit(self):
return self.submit.data and self.validate()

View File

@ -1,20 +1,14 @@
from flask import ( from flask import abort, flash, redirect, render_template, url_for
abort,
flash,
redirect,
render_template,
url_for
)
from flask_breadcrumbs import register_breadcrumb from flask_breadcrumbs import register_breadcrumb
from flask_login import current_user, login_required from flask_login import current_user, login_required
from app import db from app import db
from app.models import Avatar, ProfilePrivacySettings from app.models import Avatar
from . import bp from . import bp
from .forms import ( from .forms import (
ChangePasswordForm, ChangePasswordForm,
EditNotificationSettingsForm, EditNotificationsForm,
EditProfileSettingsForm, EditAccountForm,
EditPublicProfileInformationForm EditProfileForm
) )
@ -22,81 +16,73 @@ from .forms import (
@register_breadcrumb(bp, '.', '<i class="material-icons left">settings</i>Settings') @register_breadcrumb(bp, '.', '<i class="material-icons left">settings</i>Settings')
@login_required @login_required
def settings(): def settings():
user = current_user._get_current_object()
# region forms # region forms
edit_profile_settings_form = EditProfileSettingsForm( edit_account_form = EditAccountForm()
current_user, edit_profile_form = EditProfileForm()
data=current_user.to_json_serializeable(), change_password_form = ChangePasswordForm()
prefix='edit-profile-settings-form' edit_notifications_form = EditNotificationsForm()
)
edit_public_profile_information_form = EditPublicProfileInformationForm(
data=current_user.to_json_serializeable(),
prefix='edit-public-profile-information-form'
)
change_password_form = ChangePasswordForm(
current_user,
prefix='change-password-form'
)
edit_notification_settings_form = EditNotificationSettingsForm(
data=current_user.to_json_serializeable(),
prefix='edit-notification-settings-form'
)
# endregion forms # endregion forms
# region handle edit profile settings form # region handle edit profile settings form
if edit_profile_settings_form.validate_on_submit(): if edit_account_form.validate_on_submit():
current_user.email = edit_profile_settings_form.email.data user.email = edit_account_form.email.data
current_user.username = edit_profile_settings_form.username.data user.username = edit_account_form.username.data
db.session.commit() db.session.commit()
flash('Profile settings updated') flash('Profile settings updated')
return redirect(url_for('.settings')) return redirect(url_for('.settings'))
# endregion handle edit profile settings forms # endregion handle edit profile settings forms
# region handle edit public profile information form # region handle edit public profile information form
if edit_public_profile_information_form.submit.data and edit_public_profile_information_form.validate(): if edit_profile_form.validate_on_submit():
print(edit_public_profile_information_form.show_email.data) if edit_profile_form.show_email.data:
if edit_public_profile_information_form.show_email.data: user.add_profile_privacy_setting('SHOW_EMAIL')
current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL)
else: else:
current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL) user.remove_profile_privacy_setting('SHOW_EMAIL')
if edit_public_profile_information_form.show_last_seen.data: if edit_profile_form.show_last_seen.data:
current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN) user.add_profile_privacy_setting('SHOW_LAST_SEEN')
else: else:
current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN) user.remove_profile_privacy_setting('SHOW_LAST_SEEN')
if edit_public_profile_information_form.show_member_since.data: if edit_profile_form.show_member_since.data:
current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE) user.add_profile_privacy_setting('SHOW_MEMBER_SINCE')
else: else:
current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE) user.remove_profile_privacy_setting('SHOW_MEMBER_SINCE')
if edit_public_profile_information_form.avatar.data: if edit_profile_form.avatar.data:
try: try:
Avatar.create(edit_public_profile_information_form.avatar.data, user=current_user) Avatar.create(
edit_profile_form.avatar.data,
user=user
)
except (AttributeError, OSError): except (AttributeError, OSError):
abort(500) abort(500)
current_user.about_me = edit_public_profile_information_form.about_me.data user.about_me = edit_profile_form.about_me.data
current_user.location = edit_public_profile_information_form.location.data user.location = edit_profile_form.location.data
current_user.organization = edit_public_profile_information_form.organization.data user.organization = edit_profile_form.organization.data
current_user.website = edit_public_profile_information_form.website.data user.website = edit_profile_form.website.data
current_user.full_name = edit_public_profile_information_form.full_name.data user.full_name = edit_profile_form.full_name.data
db.session.commit() db.session.commit()
flash('Your changes have been saved') flash('Your changes have been saved')
return redirect(url_for('.settings')) return redirect(url_for('.settings'))
# endregion handle edit public profile information form # endregion handle edit public profile information form
# region handle change_password_form POST # region handle change_password_form POST
if change_password_form.submit.data and change_password_form.validate(): if change_password_form.validate_on_submit():
current_user.password = change_password_form.new_password.data user.password = change_password_form.new_password.data
db.session.commit() db.session.commit()
flash('Your changes have been saved') flash('Your changes have been saved')
return redirect(url_for('.settings')) return redirect(url_for('.settings'))
# endregion handle change_password_form POST # endregion handle change_password_form POST
# region handle edit_notification_settings_form POST # region handle edit_notification_settings_form POST
if edit_notification_settings_form.submit and edit_notification_settings_form.validate(): if edit_notifications_form.validate_on_submit():
current_user.setting_job_status_mail_notification_level = edit_notification_settings_form.job_status_mail_notification_level.data user.setting_job_status_mail_notification_level = \
edit_notifications_form.job_status_mail_notification_level.data
db.session.commit() db.session.commit()
flash('Your changes have been saved') flash('Your changes have been saved')
return redirect(url_for('.settings')) return redirect(url_for('.settings'))
# endregion handle edit_notification_settings_form POST # endregion handle edit_notification_settings_form POST
return render_template( return render_template(
'settings/settings.html.j2', 'settings/settings.html.j2',
edit_profile_settings_form=edit_profile_settings_form, title='Settings',
edit_public_profile_information_form=edit_public_profile_information_form,
change_password_form=change_password_form, change_password_form=change_password_form,
edit_notification_settings_form=edit_notification_settings_form, edit_account_form=edit_account_form,
title='Settings' edit_notifications_form=edit_notifications_form,
edit_profile_form=edit_profile_form,
user=user
) )

View File

@ -18,6 +18,13 @@
<script> <script>
let corpusListElement = document.querySelector('#corpus-list'); let corpusListElement = document.querySelector('#corpus-list');
let corpusList = new CorpusList(corpusListElement); let corpusList = new CorpusList(corpusListElement);
corpusList.add({{ corpora|tojson }}); corpusList.add(
[
{% for corpus in corpora %}
{{ corpus.to_json_serializeable(backrefs=True)|tojson }}
{% if not loop.last %},{% endif %}
{% endfor %}
]
);
</script> </script>
{% endblock scripts %} {% endblock scripts %}

View File

@ -9,12 +9,18 @@
</div> </div>
<div class="col s12 l10"> <div class="col s12 l10">
<h1 id="title">{{ title }}</h1> <h1 id="title">{{ title }}</h1>
<span class="chip hoverable tooltipped no-autoinit" id="user-role-chip">{{ user.role.name }}</span> <p>
<span class="chip white-text" id="user-confirmed-chip" style="background-color: {{ '#4caf50' if user.confirmed else '#f44336' }};">{{ 'confirmed' if user.confirmed else 'unconfirmed' }}</span> <span class="chip hoverable tooltipped no-autoinit" id="user-role-chip">{{ user.role.name }}</span>
<p id="description">{{ user.about_me }}</p> {% if user.confirmed %}
<span class="chip white-text" id="user-confirmed-chip" style="background-color: #4caf50;">confirmed</span>
{% else %}
<span class="chip white-text" id="user-confirmed-chip" style="background-color: #f44336;">unconfirmed</span>
{% endif %}
</p>
<p>{{ user.about_me }}</p>
</div> </div>
<div class="col s12">&nbsp;</div> <div class="col s12 hide-on-med-and-down">&nbsp;</div>
<div class="col s12"> <div class="col s12">
<ul class="tabs tabs-fixed-width z-depth-1"> <ul class="tabs tabs-fixed-width z-depth-1">
@ -34,8 +40,8 @@
<li>Email: {{ user.email }}</li> <li>Email: {{ user.email }}</li>
<li>Id: {{ user.id }}</li> <li>Id: {{ user.id }}</li>
<li>Hashid: {{ user.hashid }}</li> <li>Hashid: {{ user.hashid }}</li>
<li>Member since: {{ user.member_since }}</li> <li>Member since: {{ user.member_since.strftime('%Y-%m-%d') }}</li>
<li>Last seen: {{ user.last_seen }}</li> <li>Last seen: {{ user.last_seen.strftime('%Y-%m-%d') }}</li>
</ul> </ul>
</div> </div>
<div class="card-action right-align"> <div class="card-action right-align">
@ -89,7 +95,7 @@
<p>Do you really want to delete the user {{ user.username }}? All associated data will be permanently deleted!</p> <p>Do you really want to delete the user {{ user.username }}? All associated data will be permanently deleted!</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#!" class="btn modal-close waves-effect waves-light">Cancel</a> <a class="btn modal-close waves-effect waves-light">Cancel</a>
<a href="{{ url_for('.delete_user', user_id=user.id) }}" class="btn red modal-close waves-effect waves-light"><i class="material-icons left">delete</i>Delete</a> <a href="{{ url_for('.delete_user', user_id=user.id) }}" class="btn red modal-close waves-effect waves-light"><i class="material-icons left">delete</i>Delete</a>
</div> </div>
</div> </div>

View File

@ -23,6 +23,13 @@
<script> <script>
let adminUserListElement = document.querySelector('#admin-user-list'); let adminUserListElement = document.querySelector('#admin-user-list');
let adminUserList = new AdminUserList(adminUserListElement); let adminUserList = new AdminUserList(adminUserListElement);
adminUserList.add({{ users|tojson }}); adminUserList.add(
[
{% for user in users %}
{{ user.to_json_serializeable(backrefs=True)|tojson }}
{% if not loop.last %},{% endif %}
{% endfor %}
]
);
</script> </script>
{% endblock scripts %} {% endblock scripts %}

View File

@ -18,7 +18,7 @@
</div> </div>
<div class="col s8"> <div class="col s8">
<br> <br>
<ul class="collapsible"> <ul class="collapsible no-autoinit settings-collapsible">
<li> <li>
<div class="collapsible-header" style="justify-content: space-between;"> <div class="collapsible-header" style="justify-content: space-between;">
<span>User Settings</span> <span>User Settings</span>
@ -28,48 +28,26 @@
<form method="POST" enctype="multipart/form-data"> <form method="POST" enctype="multipart/form-data">
<div class="row"> <div class="row">
<div class="col s6"> <div class="col s6">
{{ edit_profile_settings_form.hidden_tag() }} {{ edit_account_form.hidden_tag() }}
{{ wtf.render_field(edit_profile_settings_form.username, material_icon='person') }} {{ wtf.render_field(edit_account_form.username, material_icon='person') }}
{{ wtf.render_field(edit_profile_settings_form.email, material_icon='email') }} {{ wtf.render_field(edit_account_form.email, material_icon='email') }}
</div> </div>
</div> </div>
<div class="right-align"> <div class="right-align">
{{ wtf.render_field(edit_profile_settings_form.submit, material_icon='send') }} {{ wtf.render_field(edit_account_form.submit, material_icon='send') }}
</div> </div>
</form> </form>
</div> </div>
</li> </li>
{# <li>
<div class="collapsible-header" style="justify-content: space-between;"><span>Privacy Settings</span><i class="material-icons caret right">keyboard_arrow_right</i></div>
<div class="collapsible-body">
<form method="POST">
{{ edit_privacy_settings_form.hidden_tag() }}
<br>
{{ wtf.render_field(edit_privacy_settings_form.is_public, id='public-profile') }}
<br>
<hr>
<br>
{{ wtf.render_field(edit_privacy_settings_form.show_email, data_action='disable', disabled=true) }}
<br>
{{ wtf.render_field(edit_privacy_settings_form.show_last_seen, data_action='disable', disabled=true) }}
<br>
{{ wtf.render_field(edit_privacy_settings_form.show_member_since, data_action='disable', disabled=true) }}
<br>
<div class="right-align">
{{ wtf.render_field(edit_privacy_settings_form.submit, material_icon='send') }}
</div>
</form>
</div>
</li> #}
<li> <li>
<div class="collapsible-header" style="justify-content: space-between;"><span>Public Profile</span><i class="material-icons caret right">keyboard_arrow_right</i></div> <div class="collapsible-header" style="justify-content: space-between;"><span>Public Profile</span><i class="material-icons caret right">keyboard_arrow_right</i></div>
<div class="collapsible-body"> <div class="collapsible-body">
<form method="POST" enctype="multipart/form-data"> <form method="POST" enctype="multipart/form-data">
{{ edit_public_profile_information_form.hidden_tag() }} {{ edit_profile_form.hidden_tag() }}
<div class="switch"> <div class="switch">
<label> <label>
private private
<input {% if current_user.is_public %}checked{% endif %} id="profile-is-public-switch" type="checkbox"> <input {% if user.is_public %}checked{% endif %} id="profile-is-public-switch" type="checkbox">
<span class="lever"></span> <span class="lever"></span>
public public
</label> </label>
@ -82,42 +60,42 @@
<div class="col s3"> <div class="col s3">
<p> <p>
<label> <label>
{{ edit_public_profile_information_form.show_email() }} {{ edit_profile_form.show_email() }}
<span>{{ edit_public_profile_information_form.show_email.label.text }}</span> <span>{{ edit_profile_form.show_email.label.text }}</span>
</label> </label>
</p> </p>
</div> </div>
<div class="col s3"> <div class="col s3">
<p> <p>
<label> <label>
{{ edit_public_profile_information_form.show_last_seen() }} {{ edit_profile_form.show_last_seen() }}
<span>{{ edit_public_profile_information_form.show_last_seen.label.text }}</span> <span>{{ edit_profile_form.show_last_seen.label.text }}</span>
</label> </label>
</p> </p>
</div> </div>
<div class="col s4"> <div class="col s4">
<p> <p>
<label> <label>
{{ edit_public_profile_information_form.show_member_since() }} {{ edit_profile_form.show_member_since() }}
<span>{{ edit_public_profile_information_form.show_member_since.label.text }}</span> <span>{{ edit_profile_form.show_member_since.label.text }}</span>
</label> </label>
</p> </p>
</div> </div>
</div> </div>
<p></p> <p></p>
<br> <br>
{{ wtf.render_field(edit_public_profile_information_form.full_name, material_icon='badge') }} {{ wtf.render_field(edit_profile_form.full_name, material_icon='badge') }}
{{ wtf.render_field(edit_public_profile_information_form.about_me, material_icon='description', id='about-me-textfield') }} {{ wtf.render_field(edit_profile_form.about_me, material_icon='description', id='about-me-textfield') }}
{{ wtf.render_field(edit_public_profile_information_form.website, material_icon='laptop') }} {{ wtf.render_field(edit_profile_form.website, material_icon='laptop') }}
{{ wtf.render_field(edit_public_profile_information_form.organization, material_icon='business') }} {{ wtf.render_field(edit_profile_form.organization, material_icon='business') }}
{{ wtf.render_field(edit_public_profile_information_form.location, material_icon='location_on') }} {{ wtf.render_field(edit_profile_form.location, material_icon='location_on') }}
<p></p> <p></p>
<div class="row"> <div class="row">
<div class="col s12 m2"> <div class="col s12 m2">
<img src="{{ url_for('users.user_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img" id="avatar"> <img src="{{ url_for('users.user_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img" id="avatar">
</div> </div>
<div class="col s12 m6"> <div class="col s12 m6">
{{ wtf.render_field(edit_public_profile_information_form.avatar, accept='image/jpeg, image/png, image/gif', placeholder='Choose an image file', id='avatar-upload') }} {{ wtf.render_field(edit_profile_form.avatar, accept='image/jpeg, image/png, image/gif', placeholder='Choose an image file', id='avatar-upload') }}
</div> </div>
<div class="col s12 m1"> <div class="col s12 m1">
<a class="btn-floating red waves-effect waves-light modal-trigger" style="margin-top:15px;" href="#delete-avatar-modal"><i class="material-icons">delete</i></a> <a class="btn-floating red waves-effect waves-light modal-trigger" style="margin-top:15px;" href="#delete-avatar-modal"><i class="material-icons">delete</i></a>
@ -126,7 +104,7 @@
<br> <br>
<p></p> <p></p>
<div class="right-align"> <div class="right-align">
{{ wtf.render_field(edit_public_profile_information_form.submit, material_icon='send') }} {{ wtf.render_field(edit_profile_form.submit, material_icon='send') }}
</div> </div>
</form> </form>
</div> </div>
@ -144,7 +122,7 @@
</div> </div>
<div class="col s8"> <div class="col s8">
<br> <br>
<ul class="collapsible"> <ul class="collapsible no-autoinit settings-collapsible">
<li> <li>
<div class="collapsible-header" style="justify-content: space-between;"> <div class="collapsible-header" style="justify-content: space-between;">
<span>Notification Settings</span> <span>Notification Settings</span>
@ -152,10 +130,10 @@
</div> </div>
<div class="collapsible-body"> <div class="collapsible-body">
<form method="POST"> <form method="POST">
{{ edit_notification_settings_form.hidden_tag() }} {{ edit_notifications_form.hidden_tag() }}
{{ wtf.render_field(edit_notification_settings_form.job_status_mail_notification_level, material_icon='notifications') }} {{ wtf.render_field(edit_notifications_form.job_status_mail_notification_level, material_icon='notifications') }}
<div class="right-align"> <div class="right-align">
{{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }} {{ wtf.render_field(edit_notifications_form.submit, material_icon='send') }}
</div> </div>
</form> </form>
</div> </div>
@ -204,7 +182,7 @@
<div class="modal" id="delete-avatar-modal"> <div class="modal" id="delete-avatar-modal">
<div class="modal-content"> <div class="modal-content">
<h4>Confirm Avatar deletion</h4> <h4>Confirm Avatar deletion</h4>
<p>Do you really want to delete your Avatar?</p> <p>Do you really want to delete <b>{{ user.username }}</b>s avatar?</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a class="btn modal-close waves-effect waves-light">Cancel</a> <a class="btn modal-close waves-effect waves-light">Cancel</a>
@ -214,7 +192,7 @@
<div class="modal" id="delete-user"> <div class="modal" id="delete-user">
<div class="modal-content"> <div class="modal-content">
<h4>Confirm User deletion</h4> <h4>Confirm User deletion</h4>
<p>Do you really want to delete the User <b>{{ current_user.username }}</b>? All files will be permanently deleted!</p> <p>Do you really want to delete the User <b>{{ user.username }}</b>? All files will be permanently deleted!</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a class="btn modal-close waves-effect waves-light">Cancel</a> <a class="btn modal-close waves-effect waves-light">Cancel</a>
@ -226,20 +204,20 @@
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script> <script>
let deleteButton = document.querySelector('#delete-avatar'); let deleteButtonElement = document.querySelector('#delete-avatar');
let avatar = document.querySelector('#avatar'); let avatarElement = document.querySelector('#avatar');
let avatarUpload = document.querySelector('#avatar-upload'); let avatarUploadElement = document.querySelector('#avatar-upload');
avatarUpload.addEventListener('change', function() { avatarUploadElement.addEventListener('change', () => {
let file = this.files[0]; let file = avatarUploadElement.files[0];
avatar.src = URL.createObjectURL(file); avatarElement.src = URL.createObjectURL(file);
}); });
deleteButton.addEventListener('click', () => { deleteButtonElement.addEventListener('click', () => {
Requests.settings.entity.deleteAvatar(currentUserId) Requests.settings.entity.deleteAvatar(currentUserId)
.then( .then(
(response) => { (response) => {
avatar.src = "{{ url_for('static', filename='images/user_avatar.png') }}"; avatarElement.src = {{ url_for('static', filename='images/user_avatar.png')|tojson }};
} }
); );
}); });
@ -249,20 +227,21 @@ document.querySelector('#delete-user-button').addEventListener('click', (event)
.then((response) => {window.location.href = '/';}); .then((response) => {window.location.href = '/';});
}); });
document.querySelectorAll('.collapsible').forEach((collapsible) => { for (let collapsibleElement of document.querySelectorAll('.collapsible.no-autoinit.settings-collapsible')) {
M.Collapsible.init( M.Collapsible.init(
collapsible, collapsibleElement,
{ {
onOpenStart: (event) => { onOpenStart: (collapsibleItemElement) => {
let caret = event.querySelector('.caret'); let caret = collapsibleItemElement.querySelector('.caret');
caret.innerHTML = 'keyboard_arrow_down'; caret.innerHTML = 'keyboard_arrow_down';
}, },
onCloseStart: (event) => { onCloseStart: (collapsibleItemElement) => {
let caret = event.querySelector('.caret'); let caret = collapsibleItemElement.querySelector('.caret');
caret.innerHTML = 'keyboard_arrow_right'; caret.innerHTML = 'keyboard_arrow_right';
} }
}); }
}); );
}
// #region Public Switch // #region Public Switch
let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch'); let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch');
@ -274,6 +253,5 @@ profileIsPublicSwitchElement.addEventListener('change', (event) => {
}); });
}); });
// #endregion Public Switch // #endregion Public Switch
</script> </script>
{% endblock scripts %} {% endblock scripts %}