app.admin.forms

Flask-WTF admin form definitions for Vision Hub application.

 1"""Flask-WTF admin form definitions for Vision Hub application."""
 2from flask_wtf import FlaskForm
 3from wtforms import StringField, PasswordField, RadioField, SubmitField, SelectField, DateField, TextAreaField, URLField, FormField, FieldList, BooleanField, SelectMultipleField
 4from wtforms.validators import ValidationError, DataRequired, EqualTo, Optional, URL, Length
 5import sqlalchemy as sa
 6
 7from app import db
 8from app.models import User, Department, Role
 9
10
11def validate_email(self, field):
12    """Validator to check if the email is valid."""
13    value = field.data
14    if '@' not in value or '.' not in value.split('@')[-1]:
15        raise ValidationError('Invalid email address.')
16
17 
18def validate_username(self, field):
19    """Validator to check if the username is already registered."""
20    existing = db.session.scalar(
21        sa.select(User).where(User.username == field.data)
22    )
23    if existing and existing.id != getattr(self, 'user_id', None):
24        raise ValidationError('Email address already registered.')
25
26
27class CreateUserForm(FlaskForm):
28    """Form for creating a new user in the admin interface."""
29    firstName = StringField('First Name', validators=[DataRequired()])
30    surname = StringField('Surname', validators=[DataRequired()])
31    username = StringField('Email', validators=[DataRequired(), validate_email, validate_username])
32    password = PasswordField('Password', validators=[DataRequired(), Length (min=8, max=30)])
33    password2 = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
34    role = SelectField('Role', coerce=int, validators=[DataRequired()])
35    is_onboarding = RadioField('Does staff member need onboarding?', choices=[('yes', 'Yes'), ('no', 'No')],validators=[DataRequired()])
36    manager= SelectField('Manager', coerce=int, validators=[Optional()])
37    department = SelectField('Department', coerce=int, validators=[DataRequired()])
38    job_title = StringField('Position', validators=[DataRequired()])
39    submit = SubmitField('Register')
40
41
42class EditUserForm(FlaskForm):
43    """Form for editing an existing user in the admin interface."""
44    first_name = StringField('First Name', validators=[DataRequired()])
45    surname = StringField('Surname', validators=[DataRequired()])
46    username = StringField('Email', validators=[DataRequired(), validate_email, validate_username])
47    password = PasswordField('Password Reset', validators=[Optional(), Length (min=8, max=30)])
48    password2 = PasswordField('Confirm New Password', validators=[Optional(), EqualTo('password')])
49    role = SelectField('Role', coerce=int, validators=[DataRequired()])
50    is_onboarding = RadioField('Does staff member need onboarding?', choices=[('yes', 'Yes'), ('no', 'No')],validators=[DataRequired()])
51    manager= SelectField('Manager', coerce=int, validators=[Optional()])
52    department = SelectField('Department', coerce=int, validators=[DataRequired()])
53    job_title = StringField('Position', validators=[DataRequired()])
54    dateStarted = DateField('Start Date', format='%d-%m-%y', validators=[Optional()])
55    submit = SubmitField('Confirm')             
56
57
58class OptionForm(FlaskForm):
59    """Sub-form for creating or editing an option in a question."""
60    option_text = StringField("Option Text", validators=[DataRequired(), Length(max=500)])
61    is_correct = BooleanField("Correct Answer")
62
63    class Meta:
64        csrf = False
65
66class QuestionForm(FlaskForm):
67    """Sub-form for a quiz question; contains four OptionForm fields."""
68    question_text = TextAreaField("Question Text", validators=[DataRequired(), Length(max=1000)])
69    option1 = FormField(OptionForm)
70    option2 = FormField(OptionForm)
71    option3 = FormField(OptionForm)
72    option4 = FormField(OptionForm)
73
74    class Meta:
75        csrf = False
76
77class CreateTrainingModuleForm(FlaskForm):
78    """Admin form to build a TrainingModule with questions and pathways."""
79    module_title = StringField("Module Title", validators=[DataRequired(), Length(max=150)])
80    module_description = TextAreaField("Description", validators=[DataRequired()])
81    module_instructions = TextAreaField("Instructions", validators=[DataRequired()])
82    video_url = URLField("Video URL (Optional)", validators=[Optional(), URL(require_tld=True), Length(max=300)])
83    pathways = SelectMultipleField("Assign to Pathways", coerce=int, validators=[DataRequired()])
84    questions = FieldList(FormField(QuestionForm), min_entries=1, max_entries=20)
85    submit = SubmitField("Create")
def validate_email(self, field):
12def validate_email(self, field):
13    """Validator to check if the email is valid."""
14    value = field.data
15    if '@' not in value or '.' not in value.split('@')[-1]:
16        raise ValidationError('Invalid email address.')

Validator to check if the email is valid.

def validate_username(self, field):
19def validate_username(self, field):
20    """Validator to check if the username is already registered."""
21    existing = db.session.scalar(
22        sa.select(User).where(User.username == field.data)
23    )
24    if existing and existing.id != getattr(self, 'user_id', None):
25        raise ValidationError('Email address already registered.')

Validator to check if the username is already registered.

class CreateUserForm(flask_wtf.form.FlaskForm):
28class CreateUserForm(FlaskForm):
29    """Form for creating a new user in the admin interface."""
30    firstName = StringField('First Name', validators=[DataRequired()])
31    surname = StringField('Surname', validators=[DataRequired()])
32    username = StringField('Email', validators=[DataRequired(), validate_email, validate_username])
33    password = PasswordField('Password', validators=[DataRequired(), Length (min=8, max=30)])
34    password2 = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
35    role = SelectField('Role', coerce=int, validators=[DataRequired()])
36    is_onboarding = RadioField('Does staff member need onboarding?', choices=[('yes', 'Yes'), ('no', 'No')],validators=[DataRequired()])
37    manager= SelectField('Manager', coerce=int, validators=[Optional()])
38    department = SelectField('Department', coerce=int, validators=[DataRequired()])
39    job_title = StringField('Position', validators=[DataRequired()])
40    submit = SubmitField('Register')

Form for creating a new user in the admin interface.

firstName = <UnboundField(StringField, ('First Name',), {'validators': [<wtforms.validators.DataRequired object>]})>
surname = <UnboundField(StringField, ('Surname',), {'validators': [<wtforms.validators.DataRequired object>]})>
username = <UnboundField(StringField, ('Email',), {'validators': [<wtforms.validators.DataRequired object>, <function validate_email>, <function validate_username>]})>
password = <UnboundField(PasswordField, ('Password',), {'validators': [<wtforms.validators.DataRequired object>, <wtforms.validators.Length object>]})>
password2 = <UnboundField(PasswordField, ('Confirm Password',), {'validators': [<wtforms.validators.DataRequired object>, <wtforms.validators.EqualTo object>]})>
role = <UnboundField(SelectField, ('Role',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.DataRequired object>]})>
is_onboarding = <UnboundField(RadioField, ('Does staff member need onboarding?',), {'choices': [('yes', 'Yes'), ('no', 'No')], 'validators': [<wtforms.validators.DataRequired object>]})>
manager = <UnboundField(SelectField, ('Manager',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.Optional object>]})>
department = <UnboundField(SelectField, ('Department',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.DataRequired object>]})>
job_title = <UnboundField(StringField, ('Position',), {'validators': [<wtforms.validators.DataRequired object>]})>
submit = <UnboundField(SubmitField, ('Register',), {})>
class EditUserForm(flask_wtf.form.FlaskForm):
43class EditUserForm(FlaskForm):
44    """Form for editing an existing user in the admin interface."""
45    first_name = StringField('First Name', validators=[DataRequired()])
46    surname = StringField('Surname', validators=[DataRequired()])
47    username = StringField('Email', validators=[DataRequired(), validate_email, validate_username])
48    password = PasswordField('Password Reset', validators=[Optional(), Length (min=8, max=30)])
49    password2 = PasswordField('Confirm New Password', validators=[Optional(), EqualTo('password')])
50    role = SelectField('Role', coerce=int, validators=[DataRequired()])
51    is_onboarding = RadioField('Does staff member need onboarding?', choices=[('yes', 'Yes'), ('no', 'No')],validators=[DataRequired()])
52    manager= SelectField('Manager', coerce=int, validators=[Optional()])
53    department = SelectField('Department', coerce=int, validators=[DataRequired()])
54    job_title = StringField('Position', validators=[DataRequired()])
55    dateStarted = DateField('Start Date', format='%d-%m-%y', validators=[Optional()])
56    submit = SubmitField('Confirm')             

Form for editing an existing user in the admin interface.

first_name = <UnboundField(StringField, ('First Name',), {'validators': [<wtforms.validators.DataRequired object>]})>
surname = <UnboundField(StringField, ('Surname',), {'validators': [<wtforms.validators.DataRequired object>]})>
username = <UnboundField(StringField, ('Email',), {'validators': [<wtforms.validators.DataRequired object>, <function validate_email>, <function validate_username>]})>
password = <UnboundField(PasswordField, ('Password Reset',), {'validators': [<wtforms.validators.Optional object>, <wtforms.validators.Length object>]})>
password2 = <UnboundField(PasswordField, ('Confirm New Password',), {'validators': [<wtforms.validators.Optional object>, <wtforms.validators.EqualTo object>]})>
role = <UnboundField(SelectField, ('Role',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.DataRequired object>]})>
is_onboarding = <UnboundField(RadioField, ('Does staff member need onboarding?',), {'choices': [('yes', 'Yes'), ('no', 'No')], 'validators': [<wtforms.validators.DataRequired object>]})>
manager = <UnboundField(SelectField, ('Manager',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.Optional object>]})>
department = <UnboundField(SelectField, ('Department',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.DataRequired object>]})>
job_title = <UnboundField(StringField, ('Position',), {'validators': [<wtforms.validators.DataRequired object>]})>
dateStarted = <UnboundField(DateField, ('Start Date',), {'format': '%d-%m-%y', 'validators': [<wtforms.validators.Optional object>]})>
submit = <UnboundField(SubmitField, ('Confirm',), {})>
class OptionForm(flask_wtf.form.FlaskForm):
59class OptionForm(FlaskForm):
60    """Sub-form for creating or editing an option in a question."""
61    option_text = StringField("Option Text", validators=[DataRequired(), Length(max=500)])
62    is_correct = BooleanField("Correct Answer")
63
64    class Meta:
65        csrf = False

Sub-form for creating or editing an option in a question.

option_text = <UnboundField(StringField, ('Option Text',), {'validators': [<wtforms.validators.DataRequired object>, <wtforms.validators.Length object>]})>
is_correct = <UnboundField(BooleanField, ('Correct Answer',), {})>
class OptionForm.Meta:
64    class Meta:
65        csrf = False
csrf = False
class QuestionForm(flask_wtf.form.FlaskForm):
67class QuestionForm(FlaskForm):
68    """Sub-form for a quiz question; contains four OptionForm fields."""
69    question_text = TextAreaField("Question Text", validators=[DataRequired(), Length(max=1000)])
70    option1 = FormField(OptionForm)
71    option2 = FormField(OptionForm)
72    option3 = FormField(OptionForm)
73    option4 = FormField(OptionForm)
74
75    class Meta:
76        csrf = False

Sub-form for a quiz question; contains four OptionForm fields.

question_text = <UnboundField(TextAreaField, ('Question Text',), {'validators': [<wtforms.validators.DataRequired object>, <wtforms.validators.Length object>]})>
option1 = <UnboundField(FormField, (<class 'OptionForm'>,), {})>
option2 = <UnboundField(FormField, (<class 'OptionForm'>,), {})>
option3 = <UnboundField(FormField, (<class 'OptionForm'>,), {})>
option4 = <UnboundField(FormField, (<class 'OptionForm'>,), {})>
class QuestionForm.Meta:
75    class Meta:
76        csrf = False
csrf = False
class CreateTrainingModuleForm(flask_wtf.form.FlaskForm):
78class CreateTrainingModuleForm(FlaskForm):
79    """Admin form to build a TrainingModule with questions and pathways."""
80    module_title = StringField("Module Title", validators=[DataRequired(), Length(max=150)])
81    module_description = TextAreaField("Description", validators=[DataRequired()])
82    module_instructions = TextAreaField("Instructions", validators=[DataRequired()])
83    video_url = URLField("Video URL (Optional)", validators=[Optional(), URL(require_tld=True), Length(max=300)])
84    pathways = SelectMultipleField("Assign to Pathways", coerce=int, validators=[DataRequired()])
85    questions = FieldList(FormField(QuestionForm), min_entries=1, max_entries=20)
86    submit = SubmitField("Create")

Admin form to build a TrainingModule with questions and pathways.

module_title = <UnboundField(StringField, ('Module Title',), {'validators': [<wtforms.validators.DataRequired object>, <wtforms.validators.Length object>]})>
module_description = <UnboundField(TextAreaField, ('Description',), {'validators': [<wtforms.validators.DataRequired object>]})>
module_instructions = <UnboundField(TextAreaField, ('Instructions',), {'validators': [<wtforms.validators.DataRequired object>]})>
video_url = <UnboundField(URLField, ('Video URL (Optional)',), {'validators': [<wtforms.validators.Optional object>, <wtforms.validators.URL object>, <wtforms.validators.Length object>]})>
pathways = <UnboundField(SelectMultipleField, ('Assign to Pathways',), {'coerce': <class 'int'>, 'validators': [<wtforms.validators.DataRequired object>]})>
questions = <UnboundField(FieldList, (<UnboundField(FormField, (<class 'QuestionForm'>,), {})>,), {'min_entries': 1, 'max_entries': 20})>
submit = <UnboundField(SubmitField, ('Create',), {})>