Skip to content
Snippets Groups Projects
Commit 99ddd2e3 authored by Patrick Jentsch's avatar Patrick Jentsch
Browse files

normalize forms

parent 54b5635e
Branches
Tags
No related merge requests found
Showing
with 80 additions and 147 deletions
...@@ -7,7 +7,7 @@ from wtforms import ( ...@@ -7,7 +7,7 @@ from wtforms import (
SubmitField, SubmitField,
ValidationError ValidationError
) )
from wtforms.validators import DataRequired, Email, EqualTo, Length, Regexp from wtforms.validators import DataRequired, InputRequired, Email, EqualTo, Length, Regexp
from . import USERNAME_REGEX from . import USERNAME_REGEX
...@@ -20,31 +20,18 @@ class LoginForm(FlaskForm): ...@@ -20,31 +20,18 @@ class LoginForm(FlaskForm):
class RegistrationForm(FlaskForm): class RegistrationForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()]) email = StringField('Email', validators=[DataRequired(), Email()])
username = StringField( username = StringField('Username',
'Username',
validators=[ validators=[
DataRequired(), InputRequired(),
Length(1, 64), Length(min=1, max=64),
Regexp( Regexp(
USERNAME_REGEX, USERNAME_REGEX,
message='Usernames must have only letters, numbers, dots or underscores' # noqa message='Usernames must have only letters, numbers, dots or underscores' # noqa
) )
] ]
) )
password = PasswordField( password = PasswordField('Password', validators=[DataRequired(), EqualTo('password_confirmation', message='Passwords must match')])
'Password', password_confirmation = PasswordField('Password confirmation', validators=[DataRequired(), EqualTo('password', message='Passwords must match')])
validators=[
DataRequired(),
EqualTo('password_confirmation', message='Passwords must match')
]
)
password_confirmation = PasswordField(
'Password confirmation',
validators=[
DataRequired(),
EqualTo('password', message='Passwords must match')
]
)
submit = SubmitField('Register') submit = SubmitField('Register')
def validate_email(self, field): def validate_email(self, field):
...@@ -57,20 +44,8 @@ class RegistrationForm(FlaskForm): ...@@ -57,20 +44,8 @@ class RegistrationForm(FlaskForm):
class ResetPasswordForm(FlaskForm): class ResetPasswordForm(FlaskForm):
password = PasswordField( password = PasswordField('New password', validators=[DataRequired(), EqualTo('password_confirmation', message='Passwords must match')])
'New password', password_confirmation = PasswordField('Password confirmation', validators=[DataRequired(), EqualTo('password', message='Passwords must match')])
validators=[
DataRequired(),
EqualTo('password_confirmation', message='Passwords must match')
]
)
password_confirmation = PasswordField(
'Password confirmation',
validators=[
DataRequired(),
EqualTo('password', message='Passwords must match')
]
)
submit = SubmitField('Reset Password') submit = SubmitField('Reset Password')
......
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from wtforms import ( from wtforms import (
FileField,
StringField, StringField,
SubmitField, SubmitField,
ValidationError, ValidationError,
IntegerField IntegerField
) )
from wtforms.validators import DataRequired, Length from wtforms.validators import DataRequired, InputRequired, Length
class AddCorpusFileForm(FlaskForm): class AddCorpusFileForm(FlaskForm):
...@@ -15,36 +15,25 @@ class AddCorpusFileForm(FlaskForm): ...@@ -15,36 +15,25 @@ class AddCorpusFileForm(FlaskForm):
Form to add a .vrt corpus file to the current corpus. Form to add a .vrt corpus file to the current corpus.
''' '''
# Required fields # Required fields
author = StringField('Author', validators=[DataRequired(), Length(1, 255)]) author = StringField('Author', validators=[InputRequired(), Length(min=1, max=255)])
file = FileField('File', validators=[DataRequired()]) publishing_year = IntegerField('Publishing year', validators=[InputRequired(), Length(min=1, max=255)])
publishing_year = IntegerField('Publishing year', title = StringField('Title', validators=[InputRequired(), Length(min=1, max=255)])
validators=[DataRequired()]) vrt = FileField('File', validators=[FileRequired()])
title = StringField('Title', validators=[DataRequired(), Length(1, 255)])
# Optional fields # Optional fields
address = StringField('Adress', validators=[Length(0, 255)]) address = StringField('Adress', validators=[Length(max=255)])
booktitle = StringField('Booktitle', validators=[Length(0, 255)]) booktitle = StringField('Booktitle', validators=[Length(max=255)])
chapter = StringField('Chapter', validators=[Length(0, 255)]) chapter = StringField('Chapter', validators=[Length(max=255)])
editor = StringField('Editor', validators=[Length(0, 255)]) editor = StringField('Editor', validators=[Length(max=255)])
institution = StringField('Institution', validators=[Length(0, 255)]) institution = StringField('Institution', validators=[Length(max=255)])
journal = StringField('Journal', validators=[Length(0, 255)]) journal = StringField('Journal', validators=[Length(max=255)])
pages = StringField('Pages', validators=[Length(0, 255)]) pages = StringField('Pages', validators=[Length(max=255)])
publisher = StringField('Publisher', validators=[Length(0, 255)]) publisher = StringField('Publisher', validators=[Length(max=255)])
school = StringField('School', validators=[Length(0, 255)]) school = StringField('School', validators=[Length(max=255)])
submit = SubmitField() submit = SubmitField()
def __init__(self, corpus, *args, **kwargs): def validate_vrt(self, field):
super().__init__(*args, **kwargs)
self.corpus = corpus
def validate_file(self, field):
if not field.data.filename.lower().endswith('.vrt'): if not field.data.filename.lower().endswith('.vrt'):
raise ValidationError('File does not have an approved extension: ' raise ValidationError('VRT files only!')
'.vrt')
field.data.filename = secure_filename(field.data.filename)
for corpus_file in self.corpus.files:
if field.data.filename == corpus_file.filename:
raise ValidationError('File already registered to corpus.')
class EditCorpusFileForm(FlaskForm): class EditCorpusFileForm(FlaskForm):
''' '''
...@@ -52,8 +41,7 @@ class EditCorpusFileForm(FlaskForm): ...@@ -52,8 +41,7 @@ class EditCorpusFileForm(FlaskForm):
''' '''
# Required fields # Required fields
author = StringField('Author', validators=[DataRequired(), Length(1, 255)]) author = StringField('Author', validators=[DataRequired(), Length(1, 255)])
publishing_year = IntegerField('Publishing year', publishing_year = IntegerField('Publishing year', validators=[DataRequired()])
validators=[DataRequired()])
title = StringField('Title', validators=[DataRequired(), Length(1, 255)]) title = StringField('Title', validators=[DataRequired(), Length(1, 255)])
# Optional fields # Optional fields
address = StringField('Adress', validators=[Length(0, 255)]) address = StringField('Adress', validators=[Length(0, 255)])
...@@ -72,27 +60,23 @@ class AddCorpusForm(FlaskForm): ...@@ -72,27 +60,23 @@ class AddCorpusForm(FlaskForm):
''' '''
Form to add a a new corpus. Form to add a a new corpus.
''' '''
description = StringField('Description', description = StringField('Description', validators=[DataRequired(), Length(1, 255)])
validators=[DataRequired(), Length(1, 255)])
submit = SubmitField()
title = StringField('Title', validators=[DataRequired(), Length(1, 32)]) title = StringField('Title', validators=[DataRequired(), Length(1, 32)])
submit = SubmitField()
class ImportCorpusForm(FlaskForm): class ImportCorpusForm(FlaskForm):
''' '''
Form to import a corpus. Form to import a corpus.
''' '''
description = StringField('Description', description = StringField('Description', validators=[DataRequired(), Length(1, 255)])
validators=[DataRequired(), Length(1, 255)]) archive = FileField('File', validators=[DataRequired()])
file = FileField('File', validators=[DataRequired()])
submit = SubmitField()
title = StringField('Title', validators=[DataRequired(), Length(1, 32)]) title = StringField('Title', validators=[DataRequired(), Length(1, 32)])
submit = SubmitField()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def validate_file(self, field): def validate_archive(self, field):
if not field.data.filename.lower().endswith('.zip'): if field.data.mimetype != 'application/zip':
raise ValidationError('File does not have an approved extension: ' raise ValidationError('ZIP files only!')
'.zip')
field.data.filename = secure_filename(field.data.filename)
...@@ -190,7 +190,7 @@ def add_corpus_file(corpus_id): ...@@ -190,7 +190,7 @@ def add_corpus_file(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id) corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.user == current_user or current_user.is_administrator()): if not (corpus.user == current_user or current_user.is_administrator()):
abort(403) abort(403)
form = AddCorpusFileForm(corpus, prefix='add-corpus-file-form') form = AddCorpusFileForm(prefix='add-corpus-file-form')
if form.is_submitted(): if form.is_submitted():
if not form.validate(): if not form.validate():
return make_response(form.errors, 400) return make_response(form.errors, 400)
...@@ -269,8 +269,9 @@ def download_corpus_file(corpus_id, corpus_file_id): ...@@ -269,8 +269,9 @@ def download_corpus_file(corpus_id, corpus_file_id):
abort(403) abort(403)
return send_from_directory( return send_from_directory(
as_attachment=True, as_attachment=True,
attachment_filename=corpus_file.filename,
directory=os.path.dirname(corpus_file.path), directory=os.path.dirname(corpus_file.path),
filename=corpus_file.filename filename=os.path.basename(corpus_file.path)
) )
......
from app.models import Job, TesseractOCRModel from app.models import TesseractOCRModel
from flask_login import current_user from flask_login import current_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed, FileRequired from flask_wtf.file import FileField, FileRequired
from wtforms import ( from wtforms import (
BooleanField, BooleanField,
MultipleFileField, MultipleFileField,
...@@ -15,24 +15,10 @@ from . import SERVICES ...@@ -15,24 +15,10 @@ from . import SERVICES
class AddJobForm(FlaskForm): class AddJobForm(FlaskForm):
description = StringField('Description', validators=[InputRequired()]) # noqa description = StringField('Description', validators=[InputRequired(), Length(min=1, max=255)])
submit = SubmitField() title = StringField('Title', validators=[InputRequired(), Length(min=1, max=32)])
title = StringField('Title', validators=[InputRequired()])
version = SelectField('Version', validators=[DataRequired()]) version = SelectField('Version', validators=[DataRequired()])
submit = SubmitField()
def validate_description(self, field):
max_length = Job.description.property.columns[0].type.length
if len(field.data) > max_length:
raise ValidationError(
f'Description must be less than {max_length} characters'
)
def validate_title(self, field):
max_length = Job.title.property.columns[0].type.length
if len(field.data) > max_length:
raise ValidationError(
f'Title must be less than {max_length} characters'
)
class AddFileSetupPipelineJobForm(AddJobForm): class AddFileSetupPipelineJobForm(AddJobForm):
......
...@@ -9,28 +9,13 @@ from wtforms import ( ...@@ -9,28 +9,13 @@ from wtforms import (
SubmitField, SubmitField,
ValidationError ValidationError
) )
from wtforms.validators import DataRequired, Email, EqualTo, Length, Regexp from wtforms.validators import DataRequired, InputRequired, Email, EqualTo, Length, Regexp
class ChangePasswordForm(FlaskForm): class ChangePasswordForm(FlaskForm):
password = PasswordField('Old password', validators=[DataRequired()]) password = PasswordField('Old password', validators=[DataRequired()])
new_password = PasswordField( new_password = PasswordField('New password', validators=[DataRequired(), EqualTo('new_password_confirmation', message='Passwords must match')])
'New password', new_password_confirmation = PasswordField('Confirm new password', validators=[DataRequired(), EqualTo('new_password', message='Passwords must match')])
validators=[
DataRequired(),
EqualTo(
'new_password_confirmation',
message='Passwords must match'
)
]
)
new_password_confirmation = PasswordField(
'Confirm new password',
validators=[
DataRequired(),
EqualTo('new_password', message='Passwords must match')
]
)
submit = SubmitField('Submit') submit = SubmitField('Submit')
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
...@@ -43,14 +28,11 @@ class ChangePasswordForm(FlaskForm): ...@@ -43,14 +28,11 @@ class ChangePasswordForm(FlaskForm):
class EditGeneralSettingsForm(FlaskForm): class EditGeneralSettingsForm(FlaskForm):
email = StringField( email = StringField('E-Mail', validators=[DataRequired(), Length(1, 254), Email()])
'E-Mail',
validators=[DataRequired(), Length(1, 254), Email()]
)
username = StringField( username = StringField(
'Username', 'Username',
validators=[ validators=[
DataRequired(), InputRequired(),
Length(1, 64), Length(1, 64),
Regexp( Regexp(
USERNAME_REGEX, USERNAME_REGEX,
......
...@@ -45,9 +45,14 @@ ...@@ -45,9 +45,14 @@
optionElementWithoutValue.disabled = true; optionElementWithoutValue.disabled = true;
} }
// Set the data-length attribute on inputs with the maxlength attribute
for (let inputElement of document.querySelectorAll('input[maxlength]')) {
inputElement.dataset.length = inputElement.getAttribute('maxlength');
}
// Initialize components // Initialize components
M.AutoInit(); M.AutoInit();
M.CharacterCounter.init(document.querySelectorAll('input[data-length][type="email"], input[data-length][type="password"], input[data-length][type="text"], textarea[data-length]')); M.CharacterCounter.init(document.querySelectorAll('input[data-length][type="text"], input[data-length][type="email"], input[data-length][type="search"], input[data-length][type="password"], input[data-length][type="tel"], input[data-length][type="url"]'));
M.Dropdown.init( M.Dropdown.init(
document.querySelectorAll('#nav-more-dropdown-trigger'), document.querySelectorAll('#nav-more-dropdown-trigger'),
{alignment: 'right', constrainWidth: false, coverTrigger: false} {alignment: 'right', constrainWidth: false, coverTrigger: false}
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
<form method="POST"> <form method="POST">
<div class="card-content"> <div class="card-content">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
{{ wtf.render_field(form.username, data_length='64', material_icon='person') }} {{ wtf.render_field(form.username, material_icon='person') }}
{{ wtf.render_field(form.password, data_length='128', material_icon='vpn_key') }} {{ wtf.render_field(form.password, material_icon='vpn_key') }}
{{ wtf.render_field(form.password_confirmation, data_length='128', material_icon='vpn_key') }} {{ wtf.render_field(form.password_confirmation, material_icon='vpn_key') }}
{{ wtf.render_field(form.email, class_='validate', material_icon='email', type='email') }} {{ wtf.render_field(form.email, class_='validate', material_icon='email', type='email') }}
</div> </div>
<div class="card-action right-align"> <div class="card-action right-align">
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
<form method="POST"> <form method="POST">
<div class="card-content"> <div class="card-content">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
{{ wtf.render_field(form.password, data_length='128') }} {{ wtf.render_field(form.password) }}
{{ wtf.render_field(form.password_confirmation, data_length='128') }} {{ wtf.render_field(form.password_confirmation) }}
</div> </div>
<div class="card-action right-align"> <div class="card-action right-align">
{{ wtf.render_field(form.submit, material_icon='send') }} {{ wtf.render_field(form.submit, material_icon='send') }}
......
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.title, data_length='32', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 m8"> <div class="col s12 m8">
{{ wtf.render_field(form.description, data_length='255', material_icon='description') }} {{ wtf.render_field(form.description, material_icon='description') }}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -23,16 +23,16 @@ ...@@ -23,16 +23,16 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.author, data_length='255', material_icon='person') }} {{ wtf.render_field(form.author, material_icon='person') }}
</div> </div>
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.title, data_length='255', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.publishing_year, material_icon='access_time') }} {{ wtf.render_field(form.publishing_year, material_icon='access_time') }}
</div> </div>
<div class="col s12"> <div class="col s12">
{{ wtf.render_field(form.file, accept='.vrt', placeholder='Choose your .vrt file') }} {{ wtf.render_field(form.vrt, accept='.vrt', placeholder='Choose your .vrt file') }}
</div> </div>
</div> </div>
</div> </div>
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
<div class="collapsible-body"> <div class="collapsible-body">
{% for field in form {% for field in form
if field.short_name not in ['author', 'csrf_token', 'file', 'publishing_year', 'submit', 'title'] %} if field.short_name not in ['author', 'csrf_token', 'file', 'publishing_year', 'submit', 'title'] %}
{{ wtf.render_field(field, data_length='255', material_icon=field.label.text[0:1]) }} {{ wtf.render_field(field, material_icon=field.label.text[0:1]) }}
{% endfor %} {% endfor %}
</div> </div>
</li> </li>
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
{{ super() }} {{ super() }}
<div id="progress-modal" class="modal"> <div id="progress-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<h4><i class="material-icons prefix">file_upload</i> Uploading file...</h4> <h4><i class="material-icons left">file_upload</i>Uploading files...</h4>
<div class="progress"> <div class="progress">
<div class="determinate" style="width: 0%"></div> <div class="determinate" style="width: 0%"></div>
</div> </div>
......
...@@ -18,10 +18,10 @@ ...@@ -18,10 +18,10 @@
<div class="card-content"> <div class="card-content">
<div class="row"> <div class="row">
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.author, data_length='255', material_icon='person') }} {{ wtf.render_field(form.author, material_icon='person') }}
</div> </div>
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.title, data_length='255', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.publishing_year, material_icon='access_time') }} {{ wtf.render_field(form.publishing_year, material_icon='access_time') }}
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
<div class="collapsible-body"> <div class="collapsible-body">
{% for field in form {% for field in form
if field.short_name not in ['author', 'csrf_token', 'publishing_year', 'submit', 'title'] %} if field.short_name not in ['author', 'csrf_token', 'publishing_year', 'submit', 'title'] %}
{{ wtf.render_field(field, data_length='255', material_icon=field.label.text[0:1]) }} {{ wtf.render_field(field, material_icon=field.label.text[0:1]) }}
{% endfor %} {% endfor %}
</div> </div>
</li> </li>
......
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 m4"> <div class="col s12 m4">
{{ wtf.render_field(form.title, data_length='32', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 m8"> <div class="col s12 m8">
{{ wtf.render_field(form.description, data_length='255', material_icon='description') }} {{ wtf.render_field(form.description, material_icon='description') }}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
......
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 l4"> <div class="col s12 l4">
{{ wtf.render_field(form.title, data_length='32', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 l8"> <div class="col s12 l8">
{{ wtf.render_field(form.description, data_length='255', material_icon='description') }} {{ wtf.render_field(form.description, material_icon='description') }}
</div> </div>
<div class="col s12 l9"> <div class="col s12 l9">
{{ wtf.render_field(form.images, accept='image/jpeg, image/png, image/tiff', placeholder='Choose JPEG, PNG or TIFF files') }} {{ wtf.render_field(form.images, accept='image/jpeg, image/png, image/tiff', placeholder='Choose JPEG, PNG or TIFF files') }}
......
...@@ -62,10 +62,10 @@ ...@@ -62,10 +62,10 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 l4"> <div class="col s12 l4">
{{ wtf.render_field(form.title, data_length='32', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 l8"> <div class="col s12 l8">
{{ wtf.render_field(form.description, data_length='255', material_icon='description') }} {{ wtf.render_field(form.description, material_icon='description') }}
</div> </div>
<div class="col s12 l5"> <div class="col s12 l5">
{{ wtf.render_field(form.txt, accept='text/plain', placeholder='Choose a plain text file') }} {{ wtf.render_field(form.txt, accept='text/plain', placeholder='Choose a plain text file') }}
......
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 l4"> <div class="col s12 l4">
{{ wtf.render_field(form.title, data_length='32', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 l8"> <div class="col s12 l8">
{{ wtf.render_field(form.description, data_length='255', material_icon='description') }} {{ wtf.render_field(form.description, material_icon='description') }}
</div> </div>
<div class="col s12 l5"> <div class="col s12 l5">
{{ wtf.render_field(form.pdf, accept='application/pdf', placeholder='Choose a PDF file') }} {{ wtf.render_field(form.pdf, accept='application/pdf', placeholder='Choose a PDF file') }}
......
...@@ -49,10 +49,10 @@ ...@@ -49,10 +49,10 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="row"> <div class="row">
<div class="col s12 l4"> <div class="col s12 l4">
{{ wtf.render_field(form.title, data_length='32', material_icon='title') }} {{ wtf.render_field(form.title, material_icon='title') }}
</div> </div>
<div class="col s12 l8"> <div class="col s12 l8">
{{ wtf.render_field(form.description, data_length='255', material_icon='description') }} {{ wtf.render_field(form.description, material_icon='description') }}
</div> </div>
<div class="col s12 l5"> <div class="col s12 l5">
{{ wtf.render_field(form.pdf, accept='application/pdf', placeholder='Choose a PDF file') }} {{ wtf.render_field(form.pdf, accept='application/pdf', placeholder='Choose a PDF file') }}
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<span class="card-title">General settings</span> <span class="card-title">General settings</span>
{{ wtf.render_field(edit_general_settings_form.username, data_length='64', material_icon='person') }} {{ wtf.render_field(edit_general_settings_form.username, material_icon='person') }}
{{ wtf.render_field(edit_general_settings_form.email, data_length='254', material_icon='email') }} {{ wtf.render_field(edit_general_settings_form.email, material_icon='email') }}
</div> </div>
<div class="card-action"> <div class="card-action">
<div class="right-align"> <div class="right-align">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment