Browse Source

Allow users to select the locale and timezone in their profile.

develop
Sam Black 4 years ago
parent
commit
49faaf7e8c
Signed by: samwwwblack GPG Key ID: 0FF0223994EA47D8
  1. 7
      cupola/forms/users.py
  2. 14
      cupola/forms/utils.py
  3. 2
      cupola/models/users.py
  4. 10
      cupola/static/js/cupola.js
  5. 3
      cupola/templates/layout/base.html
  6. 6
      cupola/templates/layout/macros.html
  7. 5
      cupola/templates/users/profile.html
  8. 3
      cupola/views/users.py
  9. 1
      requirements.txt

7
cupola/forms/users.py

@ -19,6 +19,7 @@
from flask_wtf import FlaskForm
from wtforms import BooleanField
from wtforms import PasswordField
from wtforms import SelectField
from wtforms import StringField
from wtforms import SubmitField
from wtforms import TextAreaField
@ -27,6 +28,8 @@ from wtforms import validators
from wtforms_sqlalchemy.fields import QuerySelectMultipleField
from cupola.forms.projects import ProjectUsersFormBase
from cupola.forms.utils import LANGUAGES_CHOICE
from cupola.forms.utils import TIMEZONE_CHOICE
from cupola.models.users import role_query_factory
@ -38,6 +41,10 @@ class ProfileForm(FlaskForm):
bio = TextAreaField("Biography")
notification_type = ProjectUsersFormBase.notification_type
notification_limit = ProjectUsersFormBase.notification_limit
locale = SelectField("Locale", choices=LANGUAGES_CHOICE)
timezone = SelectField("Timezone", choices=TIMEZONE_CHOICE)
submit = SubmitField("Save")

14
cupola/forms/utils.py

@ -1,7 +1,7 @@
# coding=utf8
#
# utils.py: Form utilities
# Copyright (C) 2016 Sam Black <samwwwblack@lapwing.org>
# Copyright (C) 2016-2017 Sam Black <samwwwblack@lapwing.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@ -16,7 +16,19 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from pytz import common_timezones
from sqlalchemy_utils.types.choice import Choice
from cupola.utils import LANGUAGES
LANGUAGES_CHOICE = tuple((short, description)
for short, description in LANGUAGES.items())
def _timezone_choice():
tzs = [("UTC", "UTC")]
tzs.extend([(tz, tz) for tz in common_timezones if tz != "UTC"])
return tuple(tzs)
TIMEZONE_CHOICE = _timezone_choice()
# This is from WTForms-Alchemy

2
cupola/models/users.py

@ -77,7 +77,7 @@ class User(db.Model, UserMixin):
notification_limit = db.Column(db.Integer(), default=20)
locale = db.Column(LocaleType())
timezone = db.Column(TimezoneType())
timezone = db.Column(TimezoneType(backend="pytz"))
@property
def username(self):

10
cupola/static/js/rotate.js → cupola/static/js/cupola.js

@ -1,5 +1,5 @@
/**
rotate.js: Rotate buttons when clicked.
cupola.js: Generic JS for all of Cupola.
Copyright (C) 2017 Sam Black <samwwwblack@lapwing.org>
This program is free software: you can redistribute it and/or modify
@ -15,6 +15,10 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
$(".rotatable").click(function(){
$(this).toggleClass("right");
$(document).ready(function() {
$('.combobox').combobox();
$(".rotatable").click(function(){
$(this).toggleClass("right");
});
});

3
cupola/templates/layout/base.html

@ -27,7 +27,8 @@
<script src="/static/js/patternfly/dataTables.colVis-1.1.2.js" type="text/javascript"></script>
<script src="/static/js/patternfly/dataTables.colReorder-1.4.1.js" type="text/javascript"></script>
<script src="/static/js/patternfly/patternfly-3.28.3.js" type="text/javascript"></script>
<script src="/static/js/rotate.js" type="text/javascript"></script>
<script src="/static/js/patternfly/bootstrap-combobox-1.1.8.js" type="text/javascript"></script>
<script src="/static/js/cupola.js" type="text/javascript"></script>
{% block body_js -%}{% endblock %}
</body>
</html>

6
cupola/templates/layout/macros.html

@ -1,5 +1,9 @@
{% macro _render_field_data(field, field_block_id, field_text,
field_block_status, static=False, add_hidden=False) %}
{% set class = ["is_invalid" if kwargs.get("error"),
field.render_kw.get("class", "") if field.render_kw,
kwargs.get("class_", ""),
"form-control"] %}
{% if static or field.flags.static %}
{% if add_hidden or field.flags.add_hidden %}
<input type="hidden" name="{{ field.name }}" id="{{ field_block_id }}" value="{{ field.data }}">
@ -8,7 +12,7 @@
{{ field.data or "No information" }}
</p>
{% else %}
{{ field(class="form-control", id=field_block_id, placeholder=field_text,
{{ field(class=class|join(" ")|trim, id=field_block_id, placeholder=field_text,
aria_describedby=field_block_status, readonly=field.flags.readonly, **kwargs) | safe }}
{% endif %}
{% endmacro %}

5
cupola/templates/users/profile.html

@ -28,6 +28,11 @@
{{ render_field(form.fullname) }}
{{ render_field(form.bio) }}
</div>
<div class="col-lg-12">
<h4 class="col-lg-offset-1">Localisation</h4>
{{ render_field(form.locale) }}
{{ render_field(form.timezone, class_="combobox") }}
</div>
<div class="col-lg-12">
<h4 class="col-lg-offset-1">Project Event Notifications</h4>
{{ render_field(form.notification_type) }}

3
cupola/views/users.py

@ -121,10 +121,11 @@ def profile(user_id):
:rtype: jinja2.Template
"""
user = User.query.get_or_404(user_id)
user_form = ProfileForm(request.form, obj=user)
user_form = ProfileForm(obj=user)
if user_form.validate_on_submit():
user_form.populate_obj(user)
db.session.commit()
flash(gettext("Profile updated successfully"), "success")
return redirect(url_for("users.profile", user_id=user.id))
return render_template("users/profile.html", user=user, form=user_form)

1
requirements.txt

@ -16,3 +16,4 @@ raven
arrow
sqlalchemy-utils
Flask-BabelEx
pytz

Loading…
Cancel
Save