Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve gui - WiP #3034

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion core/admin/assets/assets/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ function hibpCheck(pwd) {
// TODO: conditionally (or lazy) load select2 and dataTable
$('document').ready(function() {

// select content of autofocused field (if any)
$(document.activeElement).filter('input,textarea').first().select();

// intercept anchors with data-clicked attribute and open alternate location instead
$('[data-clicked]').click(function(e) {
e.preventDefault();
Expand All @@ -73,7 +76,7 @@ $('document').ready(function() {
var fieldset = $(this).parents('fieldset');
if (this.checked) {
fieldset.removeAttr('disabled');
fieldset.find('input,textarea').not(this).removeAttr('disabled');
fieldset.find('input,textarea').not(this).removeAttr('disabled').first().focus();
} else {
fieldset.attr('disabled', '');
fieldset.find('input,textarea').not(this).attr('disabled', '');
Expand Down
2 changes: 1 addition & 1 deletion core/admin/mailu/sso/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class LoginForm(flask_wtf.FlaskForm):
class Meta:
csrf = False
email = fields.StringField(_('E-mail'), [validators.Email(), validators.DataRequired()], render_kw={'autofocus': True})
email = fields.StringField(_('E-mail'), [validators.Email(), validators.DataRequired()], render_kw={'autofocus': True, 'type': 'email'})
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pwned = fields.HiddenField(label='', default=-1)
submitWebmail = fields.SubmitField(_('Sign in'))
Expand Down
54 changes: 29 additions & 25 deletions core/admin/mailu/ui/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

LOCALPART_REGEX = "^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*$"

AUTOFOCUS = {'autofocus': True}
NO_AUTOCOMPLETE = {'autocomplete': 'off', 'autocorrect': 'off', 'autocapitalize': 'off', 'spellcheck': 'false'}

class DestinationField(fields.SelectMultipleField):
""" Allow for multiple emails selection from current user choices and
additional email addresses.
Expand Down Expand Up @@ -56,18 +59,18 @@ class ConfirmationForm(flask_wtf.FlaskForm):
submit = fields.SubmitField(_('Confirm'))

class DomainForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Domain name'), [validators.DataRequired()])
name = fields.StringField(_('Domain name'), [validators.DataRequired()], render_kw=NO_AUTOCOMPLETE)
max_users = fields_.IntegerField(_('Maximum user count'), [validators.NumberRange(min=-1)], default=10)
max_aliases = fields_.IntegerField(_('Maximum alias count'), [validators.NumberRange(min=-1)], default=10)
max_quota_bytes = fields_.IntegerSliderField(_('Maximum user quota'), default=0)
signup_enabled = fields.BooleanField(_('Enable sign-up'), default=False)
comment = fields.StringField(_('Comment'))
comment = fields.StringField(_('Comment'), render_kw=AUTOFOCUS)
submit = fields.SubmitField(_('Save'))


class DomainSignupForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Domain name'), [validators.DataRequired()])
localpart = fields.StringField(_('Initial admin'), [validators.DataRequired()])
name = fields.StringField(_('Domain name'), [validators.DataRequired()], render_kw=AUTOFOCUS|NO_AUTOCOMPLETE)
localpart = fields.StringField(_('Initial admin'), [validators.DataRequired()], render_kw=NO_AUTOCOMPLETE)
pw = fields.PasswordField(_('Admin password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
pwned = fields.HiddenField(label='', default=-1)
Expand All @@ -76,35 +79,35 @@ class DomainSignupForm(flask_wtf.FlaskForm):


class AlternativeForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Alternative name'), [validators.DataRequired()])
name = fields.StringField(_('Alternative name'), [validators.DataRequired()], render_kw=AUTOFOCUS|NO_AUTOCOMPLETE)
submit = fields.SubmitField(_('Save'))


class RelayForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Relayed domain name'), [validators.DataRequired()])
smtp = fields.StringField(_('Remote host'))
comment = fields.StringField(_('Comment'))
name = fields.StringField(_('Relayed domain name'), [validators.DataRequired()], render_kw=AUTOFOCUS|NO_AUTOCOMPLETE)
smtp = fields.StringField(_('Remote host'), render_kw=NO_AUTOCOMPLETE)
comment = fields.StringField(_('Comment'), render_kw=AUTOFOCUS)
submit = fields.SubmitField(_('Save'))


class UserForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('E-mail'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
localpart = fields.StringField(_('E-mail'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)], render_kw=NO_AUTOCOMPLETE)
pw = fields.PasswordField(_('Password'))
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
pwned = fields.HiddenField(label='', default=-1)
quota_bytes = fields_.IntegerSliderField(_('Quota'), default=10**9)
enable_imap = fields.BooleanField(_('Allow IMAP access'), default=True)
enable_pop = fields.BooleanField(_('Allow POP3 access'), default=True)
allow_spoofing = fields.BooleanField(_('Allow the user to spoof the sender (send email as anyone)'), default=False)
displayed_name = fields.StringField(_('Displayed name'))
displayed_name = fields.StringField(_('Displayed name'), render_kw=AUTOFOCUS)
comment = fields.StringField(_('Comment'))
enabled = fields.BooleanField(_('Enabled'), default=True)
change_pw_next_login = fields.BooleanField(_('Force password change at next login'), default=True)
submit = fields.SubmitField(_('Save'))


class UserSignupForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('Email address'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
localpart = fields.StringField(_('Email address'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)], render_kw=AUTOFOCUS|NO_AUTOCOMPLETE)
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
pwned = fields.HiddenField(label='', default=-1)
Expand All @@ -114,32 +117,32 @@ class UserSignupFormCaptcha(UserSignupForm):
captcha = flask_wtf.RecaptchaField()

class UserSettingsForm(flask_wtf.FlaskForm):
displayed_name = fields.StringField(_('Displayed name'))
displayed_name = fields.StringField(_('Displayed name'), render_kw=AUTOFOCUS)
spam_enabled = fields.BooleanField(_('Enable spam filter'))
spam_mark_as_read = fields.BooleanField(_('Enable marking spam mails as read'))
spam_threshold = fields_.IntegerSliderField(_('Spam filter tolerance'))
forward_enabled = fields.BooleanField(_('Enable forwarding'))
forward_keep = fields.BooleanField(_('Keep a copy of the emails'))
forward_destination = fields.StringField(_('Destination'), [validators.Optional(), MultipleEmailAddressesVerify()])
forward_destination = fields.StringField(_('Destination'), [validators.Optional(), MultipleEmailAddressesVerify()], render_kw=NO_AUTOCOMPLETE)
submit = fields.SubmitField(_('Save settings'))


class UserPasswordForm(flask_wtf.FlaskForm):
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw = fields.PasswordField(_('Password'), [validators.DataRequired()], render_kw=AUTOFOCUS)
pw2 = fields.PasswordField(_('Password check'), [validators.DataRequired()])
pwned = fields.HiddenField(label='', default=-1)
submit = fields.SubmitField(_('Update password'))

class UserPasswordChangeForm(flask_wtf.FlaskForm):
current_pw = fields.PasswordField(_('Current password'), [validators.DataRequired()])
current_pw = fields.PasswordField(_('Current password'), [validators.DataRequired()], render_kw=AUTOFOCUS)
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Password check'), [validators.DataRequired()])
pwned = fields.HiddenField(label='', default=-1)
submit = fields.SubmitField(_('Update password'))

class UserReplyForm(flask_wtf.FlaskForm):
reply_enabled = fields.BooleanField(_('Enable automatic reply'))
reply_subject = fields.StringField(_('Reply subject'))
reply_subject = fields.StringField(_('Reply subject'), render_kw=AUTOFOCUS)
reply_body = fields.StringField(_('Reply body'),
widget=widgets.TextArea())
reply_startdate = fields.DateField(_('Start of vacation'))
Expand All @@ -152,9 +155,9 @@ class TokenForm(flask_wtf.FlaskForm):
_('Your token (write it down, as it will never be displayed again)')
)
raw_password = fields.HiddenField([validators.DataRequired()])
comment = fields.StringField(_('Comment'))
comment = fields.StringField(_('Comment'), render_kw=AUTOFOCUS)
ip = fields.StringField(
_('Authorized IP'), [validators.Optional()]
_('Authorized IP'), [validators.Optional()], render_kw=NO_AUTOCOMPLETE
)
submit = fields.SubmitField(_('Save'))

Expand All @@ -168,11 +171,11 @@ def validate_ip(form, field):
raise validators.ValidationError('Not a valid list of CIDRs')

class AliasForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('Alias'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
localpart = fields.StringField(_('Alias'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)], render_kw=NO_AUTOCOMPLETE)
wildcard = fields.BooleanField(
_('Use SQL LIKE Syntax (e.g. for catch-all aliases)'))
destination = DestinationField(_('Destination'))
comment = fields.StringField(_('Comment'))
comment = fields.StringField(_('Comment'), render_kw=AUTOFOCUS)
submit = fields.SubmitField(_('Save'))


Expand All @@ -190,20 +193,21 @@ class FetchForm(flask_wtf.FlaskForm):
protocol = fields.SelectField(_('Protocol'), choices=[
('imap', 'IMAP'), ('pop3', 'POP3')
])
host = fields.StringField(_('Hostname or IP'), [validators.DataRequired()])
host = fields.StringField(_('Hostname or IP'), [validators.DataRequired()], render_kw=NO_AUTOCOMPLETE)
port = fields.IntegerField(_('TCP port'), [validators.DataRequired(), validators.NumberRange(min=0, max=65535)], default=993)
tls = fields.BooleanField(_('Enable TLS'), default=True)
username = fields.StringField(_('Username'), [validators.DataRequired()])
password = fields.PasswordField(_('Password'))
username = fields.StringField(_('Username'), [validators.DataRequired()], render_kw=NO_AUTOCOMPLETE)
password = fields.PasswordField(_('Password'), render_kw=AUTOFOCUS)
keep = fields.BooleanField(_('Keep emails on the server'))
scan = fields.BooleanField(_('Rescan emails locally'))
folders = fields.StringField(_('Folders to fetch on the server'), [validators.Optional(), MultipleFoldersVerify()], default='INBOX,Junk')
folders = fields.StringField(_('Folders to fetch on the server'), [validators.Optional(), MultipleFoldersVerify()], default='INBOX,Junk', render_kw=NO_AUTOCOMPLETE)
submit = fields.SubmitField(_('Submit'))


class AnnouncementForm(flask_wtf.FlaskForm):
announcement_subject = fields.StringField(_('Announcement subject'),
[validators.DataRequired()])
[validators.DataRequired()], render_kw=AUTOFOCUS)
announcement_body = fields.StringField(_('Announcement body'),
[validators.DataRequired()], widget=widgets.TextArea())
submit = fields.SubmitField(_('Send'))

4 changes: 4 additions & 0 deletions core/admin/mailu/ui/templates/admin/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
{% trans %}Add a global administrator{% endtrans %}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.admin_list') }}">{% trans %}Back to{% endtrans %} {% trans %}Global administrators{% endtrans %}</a>
{%- endblock %}

{%- block content %}
{%- call macros.card() %}
<form class="form" method="post" role="form">
Expand Down
6 changes: 5 additions & 1 deletion core/admin/mailu/ui/templates/alias/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
{{ domain }}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.alias_list', domain_name=domain.name) }}">{% trans %}Back to{% endtrans %} {% trans %}Alias list{% endtrans %}</a>
{%- endblock %}

{%- block content %}
{%- call macros.card() %}
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>', autofocus=True, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{{ macros.form_field(form.wildcard) }}
{{ macros.form_field(form.destination, class_='mailselect') }}
{{ macros.form_field(form.comment) }}
Expand Down
4 changes: 4 additions & 0 deletions core/admin/mailu/ui/templates/alternative/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
{%- block subtitle %}
{{ domain }}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.alternative_list', domain_name=domain.name) }}">{% trans %}Back to{% endtrans %} {% trans %}Alternative domain list{% endtrans %}</a>
{%- endblock %}
6 changes: 5 additions & 1 deletion core/admin/mailu/ui/templates/domain/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
{% trans %}New domain{% endtrans %}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.domain_list') }}">{% trans %}Back to{% endtrans %} {% trans %}Domain list{% endtrans %}</a>
{%- endblock %}

{%- block content %}
{%- call macros.card() %}
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{{ macros.form_field(form.name) }}
{{ macros.form_field(form.name, autofocus=True, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{{ macros.form_fields((form.max_users, form.max_aliases)) }}
{{ macros.form_field(form.max_quota_bytes, step=50*10**6, max=50*10**9, data_infinity="true", data_unit=10**9,
prepend='<span class="input-group-text"><span id="max_quota_bytes_value"></span>&nbsp;GB</span>') }}
Expand Down
11 changes: 6 additions & 5 deletions core/admin/mailu/ui/templates/domain/signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
{%- endblock %}

{%- block content %}

<form class="form" method="post" role="form">
{{ form.hidden_tag() }}

Expand All @@ -24,12 +23,14 @@

{%- call macros.card() %}
{%- if form.localpart %}
{{ macros.form_fields((form.localpart, form.name), append='<span class="input-group-text">@</span>') }}
{{ macros.form_fields((form.pw, form.pw2)) }}
{{ macros.form_fields((form.localpart, form.name), append='<span class="input-group-text">@</span>', autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{{ macros.form_fields((form.pw, form.pw2)) }}
{%- else %}
{{ macros.form_field(form.name) }}
{{ macros.form_field(form.name) }}
{%- endif %}
{%- if form.captcha %}
{{ macros.form_field(form.captcha, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{%- endif %}
{{ macros.form_field(form.captcha) }}
{{ macros.form_field(form.submit) }}
{%- endcall %}
</form>
Expand Down
12 changes: 10 additions & 2 deletions core/admin/mailu/ui/templates/fetch/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,32 @@
{{ user }}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.fetch_list') }}">{% trans %}Back to{% endtrans %} {% trans %}Fetched accounts{% endtrans %}</a>
{%- endblock %}

{%- block content %}
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{%- call macros.card(title="Remote server") %}
{{ macros.form_field(form.protocol) }}
{%- if form.host.data %}
{{ macros.form_fields((form.host, form.port)) }}
{%- else %}
{{ macros.form_fields((form.host, form.port), autofocus=true, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{%- endif %}
{{ macros.form_field(form.tls) }}
{%- endcall %}

{%- call macros.card(title="Authentication") %}
{{ macros.form_field(form.username) }}
{{ macros.form_field(form.username, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{{ macros.form_field(form.password) }}
{%- endcall %}

{%- call macros.card(title="Settings") %}
{{ macros.form_field(form.keep) }}
{{ macros.form_field(form.scan) }}
{{ macros.form_field(form.folders) }}
{{ macros.form_field(form.folders, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{%- endcall %}

{{ macros.form_field(form.submit) }}
Expand Down
2 changes: 1 addition & 1 deletion core/admin/mailu/ui/templates/fetch/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
{%- endblock %}

{%- block subtitle %}
{{ user }}
{{ fetch }}
{%- endblock %}
4 changes: 4 additions & 0 deletions core/admin/mailu/ui/templates/manager/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
{{ domain }}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.manager_list', domain_name=domain.name) }}">{% trans %}Back to{% endtrans %} {% trans %}Manager list{% endtrans %}</a>
{%- endblock %}

{%- block content %}
{%- call macros.card() %}
<form class="form" method="post" role="form">
Expand Down
4 changes: 4 additions & 0 deletions core/admin/mailu/ui/templates/relay/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
{%- block title %}
{% trans %}New relay domain{% endtrans %}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.relay_list') }}">{% trans %}Back to{% endtrans %} {% trans %}Relayed domain list{% endtrans %}</a>
{%- endblock %}
4 changes: 4 additions & 0 deletions core/admin/mailu/ui/templates/token/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
{%- block subtitle %}
{{ user }}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.token_list') }}">{% trans %}Back to{% endtrans %} {% trans %}Authentication tokens{% endtrans %}</a>
{%- endblock %}
6 changes: 5 additions & 1 deletion core/admin/mailu/ui/templates/user/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
{{ domain.name }}
{%- endblock %}

{%- block main_action %}
<a class="btn btn-primary float-right" href="{{ url_for('.user_list', domain_name=domain.name) }}">{% trans %}Back to{% endtrans %} {% trans %}User list{% endtrans %}</a>
{%- endblock %}

{%- block content %}
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}

{%- call macros.card(_("General")) %}
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>', autofocus=true, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{{ macros.form_fields((form.pw, form.pw2)) }}
{{ macros.form_field(form.displayed_name) }}
{{ macros.form_field(form.comment) }}
Expand Down
2 changes: 1 addition & 1 deletion core/admin/mailu/ui/templates/user/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{{ form.hidden_tag() }}

{%- call macros.card(title=_("Displayed name")) %}
{{ macros.form_field(form.displayed_name) }}
{{ macros.form_field(form.displayed_name, autofocus=True) }}
{%- endcall %}

{%- call macros.card(title=_("Antispam")) %}
Expand Down
4 changes: 2 additions & 2 deletions core/admin/mailu/ui/templates/user/signup.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{%- call macros.card() %}
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>') }}
{{ macros.form_field(form.localpart, append='<span class="input-group-text">@'+domain.name+'</span>', autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{{ macros.form_fields((form.pw, form.pw2)) }}
{%- if form.captcha %}
{{ macros.form_field(form.captcha) }}
{{ macros.form_field(form.captcha, autocomplete="off", autocorrect="off", autocapitalize="off", spellcheck="false") }}
{%- endif %}
{{ macros.form_field(form.submit) }}
{%- endcall %}
Expand Down