diff --git a/snikket_web/admin.py b/snikket_web/admin.py index 05768b3..6a8b855 100644 --- a/snikket_web/admin.py +++ b/snikket_web/admin.py @@ -19,12 +19,11 @@ from quart import ( abort, flash, ) -import flask_wtf from flask_babel import lazy_gettext as _l, _ from . import prosodyclient -from .infra import client, circle_name +from .infra import client, circle_name, BaseForm bp = Blueprint("admin", __name__, url_prefix="/admin") @@ -35,7 +34,7 @@ async def index() -> str: return await render_template("admin_home.html") -class PasswordResetLinkPost(flask_wtf.FlaskForm): # type: ignore +class PasswordResetLinkPost(BaseForm): action_create = wtforms.StringField() action_revoke = wtforms.StringField() @@ -55,7 +54,7 @@ async def users() -> str: ) -class DeleteUserForm(flask_wtf.FlaskForm): # type:ignore +class DeleteUserForm(BaseForm): action_delete = wtforms.SubmitField( _l("Delete user permanently") ) @@ -132,11 +131,11 @@ async def create_password_reset_link() -> typing.Union[str, quart.Response]: ) -class InvitesListForm(flask_wtf.FlaskForm): # type:ignore +class InvitesListForm(BaseForm): action_revoke = wtforms.StringField() -class InvitePost(flask_wtf.FlaskForm): # type:ignore +class InvitePost(BaseForm): circles = wtforms.SelectMultipleField( _l("Invite to circle"), # NOTE: This is for when/if we ever support multi-group invites. @@ -230,7 +229,7 @@ async def invitations() -> typing.Union[str, quart.Response]: ) -class InviteForm(flask_wtf.FlaskForm): # type:ignore +class InviteForm(BaseForm): action_revoke = wtforms.SubmitField( _l("Revoke") ) @@ -302,7 +301,7 @@ async def edit_invite(id_: str) -> typing.Union[str, quart.Response]: ) -class CirclePost(flask_wtf.FlaskForm): # type:ignore +class CirclePost(BaseForm): name = wtforms.StringField( _l("Name"), validators=[wtforms.validators.InputRequired()], @@ -350,7 +349,7 @@ async def create_circle() -> typing.Union[str, quart.Response]: ) -class EditCircleForm(flask_wtf.FlaskForm): # type:ignore +class EditCircleForm(BaseForm): name = wtforms.StringField( _l("Name"), validators=[wtforms.validators.InputRequired()], diff --git a/snikket_web/infra.py b/snikket_web/infra.py index 212ca14..195dc84 100644 --- a/snikket_web/infra.py +++ b/snikket_web/infra.py @@ -10,6 +10,7 @@ from quart import ( ) import flask_babel +import flask_wtf from flask_babel import _ from . import prosodyclient @@ -55,3 +56,14 @@ def generate_error_id() -> str: return base64.b32encode(secrets.token_bytes(8)).decode( "ascii" ).rstrip("=") + + +class BaseForm(flask_wtf.FlaskForm): # type:ignore + def __init__(self, *args: typing.Any, **kwargs: typing.Any): + meta = kwargs["meta"] = dict(kwargs.get("meta", {})) + if "locales" not in meta: + locale = flask_babel.get_locale() + if locale: + meta["locales"] = [str(locale)] + + super().__init__(*args, **kwargs) diff --git a/snikket_web/invite.py b/snikket_web/invite.py index 19a4314..8b35376 100644 --- a/snikket_web/invite.py +++ b/snikket_web/invite.py @@ -16,10 +16,9 @@ from quart import ( import wtforms -import flask_wtf from flask_babel import lazy_gettext as _l -from .infra import client, selected_locale +from .infra import client, selected_locale, BaseForm bp = Blueprint("invite", __name__) @@ -102,7 +101,7 @@ async def view(id_: str) -> typing.Union[quart.Response, ) -class RegisterForm(flask_wtf.FlaskForm): # type:ignore +class RegisterForm(BaseForm): localpart = wtforms.StringField( _l("Username"), ) @@ -173,7 +172,7 @@ async def register(id_: str) -> typing.Union[str, quart.Response]: ) -class ResetForm(flask_wtf.FlaskForm): # type:ignore +class ResetForm(BaseForm): password = wtforms.PasswordField( _l("Password"), ) diff --git a/snikket_web/main.py b/snikket_web/main.py index 6a8f8e0..09746a1 100644 --- a/snikket_web/main.py +++ b/snikket_web/main.py @@ -22,17 +22,16 @@ import babel import wtforms import flask_wtf - from flask_babel import lazy_gettext as _l, _ from . import xmpputil, _version -from .infra import client +from .infra import client, BaseForm bp = quart.Blueprint("main", __name__) -class LoginForm(flask_wtf.FlaskForm): # type:ignore +class LoginForm(BaseForm): address = wtforms.TextField( _l("Address"), validators=[wtforms.validators.InputRequired()], diff --git a/snikket_web/templates/login.html b/snikket_web/templates/login.html index 515d0c4..334b62a 100644 --- a/snikket_web/templates/login.html +++ b/snikket_web/templates/login.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% from "library.j2" import box, form_button %} +{% from "library.j2" import box, form_button, render_errors %} {% set body_id = "login" %} {% block head_lead %}
{{ _("Enter your Snikket address and password to manage your account.") }}