Feat(Project Hub): Apply for Founding Partner Program page created with database structure and methods.
This commit is contained in:
@@ -33,15 +33,19 @@ class Form_Base(FlaskForm, metaclass=Form_Base_Meta):
|
||||
def get_default(cls):
|
||||
return cls()
|
||||
@classmethod
|
||||
def get_select_option_blank(cls):
|
||||
return (cls.get_select_option_default_value(), 'Select')
|
||||
def get_select_option_blank(cls, is_valid = True):
|
||||
value = cls.get_select_valid_option_default_value() if is_valid else cls.get_select_invalid_option_default_value()
|
||||
return (value, 'Select')
|
||||
@classmethod
|
||||
def get_select_option_all(cls):
|
||||
return (cls.get_select_option_default_value(), 'All')
|
||||
return (cls.get_select_valid_option_default_value(), 'All')
|
||||
|
||||
@staticmethod
|
||||
def get_select_option_default_value():
|
||||
def get_select_valid_option_default_value():
|
||||
return '0'
|
||||
@staticmethod
|
||||
def get_select_invalid_option_default_value():
|
||||
return ''
|
||||
|
||||
def __repr__(self):
|
||||
fields = ', '.join(
|
||||
|
||||
@@ -50,78 +50,78 @@ class Filters_Assessment(Form_Base):
|
||||
id_assessment = SelectField(
|
||||
'Assessment'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_weather = SelectField(
|
||||
'Weather'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_lighting_level = SelectField(
|
||||
'Lighting Level'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_location = SelectField(
|
||||
'Location'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_user_handler = SelectField(
|
||||
'Handler'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
"""
|
||||
id_distraction_type = SelectField(
|
||||
'Distraction Type'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_intensity_level_emotional = SelectField(
|
||||
'Intensity Level Emotional'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_intensity_level_scent = SelectField(
|
||||
'Intensity Level Scent'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_intensity_level_sight = SelectField(
|
||||
'Intensity Level Sight'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_intensity_level_sound = SelectField(
|
||||
'Intensity Level Sound'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_intensity_level_touch = SelectField(
|
||||
'Intensity Level Touch'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_command_category = SelectField(
|
||||
'Command Category'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_command = SelectField(
|
||||
'Command'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_command_modality = SelectField(
|
||||
'Command Modality'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_bribe = SelectField(
|
||||
'Bribe'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
"""
|
||||
active_only = BooleanField(
|
||||
|
||||
@@ -37,7 +37,7 @@ class Filters_Calendar_Entry(Form_Base):
|
||||
id_calendar_entry_type = SelectField(
|
||||
'Type'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
active_only = BooleanField(
|
||||
'Active'
|
||||
|
||||
@@ -37,7 +37,7 @@ class Filters_Command(Form_Base):
|
||||
id_command_category = SelectField(
|
||||
'Command Category'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
active_only = BooleanField(
|
||||
'Active'
|
||||
|
||||
@@ -43,32 +43,32 @@ class Filters_Command_Button_Link(Form_Base):
|
||||
id_command_category = SelectField(
|
||||
'Command Category'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_command = SelectField(
|
||||
'Command'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_button_shape = SelectField(
|
||||
'Shape'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_colour = SelectField(
|
||||
'Colour'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_button_icon = SelectField(
|
||||
'Icon'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_location = SelectField(
|
||||
'Location'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
active_only = BooleanField(
|
||||
'Active'
|
||||
|
||||
@@ -39,17 +39,17 @@ class Filters_Dog_Command_Link(Form_Base):
|
||||
id_dog = SelectField(
|
||||
'Dog'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_command_category = SelectField(
|
||||
'Command Category'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
id_command = SelectField(
|
||||
'Command'
|
||||
, choices = [Form_Base.get_select_option_all()]
|
||||
, default = Form_Base.get_select_option_default_value()
|
||||
, default = Form_Base.get_select_valid_option_default_value()
|
||||
)
|
||||
active_only = BooleanField(
|
||||
'Active'
|
||||
|
||||
171
forms/project_hub/apply_founding_partner.py
Normal file
171
forms/project_hub/apply_founding_partner.py
Normal file
@@ -0,0 +1,171 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Backend
|
||||
Feature: Apply to Founding Partner Program Form
|
||||
|
||||
Description:
|
||||
Defines Flask-WTF form for handling user input on Apply to Founding Partner Program page.
|
||||
"""
|
||||
|
||||
# IMPORTS
|
||||
# internal
|
||||
from business_objects.base import Base
|
||||
from business_objects.project_hub.apply_founding_partner_form import Apply_Founding_Partner_Form
|
||||
from business_objects.project_hub.contact_form import Contact_Form
|
||||
from forms.project_hub.contact import AltchaValidator, AltchaField
|
||||
# from models.model_view_store import Model_View_Store # circular
|
||||
from models.model_view_base import Model_View_Base
|
||||
from forms.base import Form_Base
|
||||
# external
|
||||
from flask import Flask, render_template, request, flash, redirect, url_for, current_app
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, TextAreaField, SubmitField, HiddenField, BooleanField, Field, EmailField, IntegerField, SelectField, SelectMultipleField
|
||||
from wtforms.validators import DataRequired, Email, ValidationError, Optional
|
||||
from wtforms.widgets import CheckboxInput, ListWidget
|
||||
import markupsafe
|
||||
from flask_wtf.recaptcha import RecaptchaField
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import json
|
||||
from altcha import verify_solution
|
||||
import base64
|
||||
|
||||
|
||||
class MultiCheckboxField(SelectMultipleField):
|
||||
widget = ListWidget(prefix_label=False)
|
||||
option_widget = CheckboxInput()
|
||||
|
||||
|
||||
class Form_Apply_Founding_Partner(FlaskForm):
|
||||
contact_name = StringField(
|
||||
'Name'
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
email = EmailField(
|
||||
'Email'
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
phone_number = StringField(
|
||||
'Phone number'
|
||||
, validators = [Optional()]
|
||||
)
|
||||
company_name = StringField(
|
||||
'Company'
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
website = StringField(
|
||||
'Website / social media'
|
||||
, validators = [Optional()]
|
||||
)
|
||||
dog_count = IntegerField(
|
||||
'How many dogs do you currently train regularly?'
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
id_years_of_experience = SelectField(
|
||||
'How long have you been training professionally?'
|
||||
, choices = [
|
||||
( '1', 'Less than 1 year' )
|
||||
, ( '2', 'Less than 3 years' )
|
||||
, ( '3', 'Less than 5 years' )
|
||||
, ( '4', 'More than 5 years' )
|
||||
]
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
id_speciality = MultiCheckboxField( # SelectMultipleField(
|
||||
'What type(s) of training do you specialise in?'
|
||||
, choices = [
|
||||
( '1', 'Basic obedience' )
|
||||
, ( '2', 'Puppy training' )
|
||||
, ( '3', 'Behaviour modification' )
|
||||
, ( '4', 'Advanced / competition training' )
|
||||
, ( '5', 'Service / therapy dog training' )
|
||||
, ( '6', 'Group classes' )
|
||||
, ( '7', 'One-on-one sessions' )
|
||||
, ( '8', 'Other (specify below)' )
|
||||
]
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
id_existing_system = MultiCheckboxField( # SelectMultipleField(
|
||||
'How do you currently manage client information and training records?'
|
||||
, choices = [
|
||||
( '1', 'Spreadsheets (Excel/Google Sheets)' )
|
||||
, ( '2', 'Paper notes/binders' )
|
||||
, ( '3', 'Generic CRM software' )
|
||||
, ( '4', 'Mix of different apps' )
|
||||
, ( '5', 'Mostly in my head/memory' )
|
||||
, ( '6', 'Other (specify below)' )
|
||||
]
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
existing_challenges = TextAreaField(
|
||||
"What's your biggest frustration with your current system?"
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
id_existing_time_sink_weekly = SelectField(
|
||||
'How much time do you spend on training-related admin work per week?'
|
||||
, choices = [
|
||||
( '1', 'Less than 1 hour' )
|
||||
, ( '2', 'Less than 3 hours' )
|
||||
, ( '3', 'Less than 6 hours' )
|
||||
, ( '3', 'Less than 10 hours' )
|
||||
, ( '4', 'More than 10 hours' )
|
||||
]
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
id_commitment_frequency = SelectField(
|
||||
'Are you willing to provide regular feedback during the beta phase?'
|
||||
, choices = [
|
||||
( '1', 'Yes, weekly feedback' )
|
||||
, ( '2', 'Yes, monthly feedback' )
|
||||
, ( '3', 'Occasional feedback only' )
|
||||
, ( '4', 'Just want to use the software' )
|
||||
]
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
"""
|
||||
implementation_timeline = SelectField(
|
||||
"What's your timeline for implementing new business management software?"
|
||||
, choices = [
|
||||
, ( '1', 'Immediately' )
|
||||
, ( '2', 'Within 1 month' )
|
||||
, ( '3', 'Within 3 months' )
|
||||
, ( '4', 'When the right solution comes along' )
|
||||
, ( '5', 'No timeline yet' )
|
||||
]
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
most_valuable_feature = TextAreaField(
|
||||
'What feature would be most valuable to your business?'
|
||||
, validators = [DataRequired()]
|
||||
)
|
||||
"""
|
||||
notes = TextAreaField(
|
||||
"Anything else you'd like us to know about your business or training approach?"
|
||||
, validators = [Optional()]
|
||||
)
|
||||
altcha = AltchaField('Verify you are human')
|
||||
submit = SubmitField('Send Message')
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
Contact_Form.FLAG_NAME_CONTACT: self.contact_name.data
|
||||
, Base.FLAG_EMAIL: self.email.data
|
||||
, Base.FLAG_PHONE_NUMBER: self.phone_number.data
|
||||
, Contact_Form.FLAG_NAME_COMPANY: self.company_name.data
|
||||
, Base.FLAG_WEBSITE: self.website.data
|
||||
, Apply_Founding_Partner_Form.FLAG_DOG_COUNT: self.dog_count.data
|
||||
, Apply_Founding_Partner_Form.FLAG_YEARS_OF_EXPERIENCE: self.id_years_of_experience.data
|
||||
, Apply_Founding_Partner_Form.FLAG_SPECIALITY: self.id_speciality.data
|
||||
, Apply_Founding_Partner_Form.FLAG_EXISTING_SYSTEM: self.id_existing_system.data
|
||||
, Apply_Founding_Partner_Form.FLAG_EXISTING_CHALLENGES: self.existing_challenges.data
|
||||
, Apply_Founding_Partner_Form.FLAG_EXISTING_TIME_SINK_WEEKLY: self.id_existing_time_sink_weekly.data
|
||||
, Apply_Founding_Partner_Form.FLAG_COMMITMENT_FREQUENCY: self.id_commitment_frequency.data
|
||||
# , Apply_Founding_Partner_Form.FLAG_IMPLEMENTATION_TIMELINE: self.implementation_timeline.data
|
||||
# , Apply_Founding_Partner_Form.FLAG_MOST_VALUABLE_FEATURE: self.most_valuable_feature.data
|
||||
, Apply_Founding_Partner_Form.FLAG_NOTES: self.notes.data
|
||||
, Contact_Form.FLAG_ALTCHA: self.altcha.data
|
||||
, Base.FLAG_ACTIVE: True
|
||||
, Base.FLAG_CREATED_ON: None
|
||||
}
|
||||
@@ -29,13 +29,15 @@ import json
|
||||
from altcha import verify_solution
|
||||
import base64
|
||||
|
||||
class ALTCHAValidator:
|
||||
class AltchaValidator:
|
||||
def __init__(self, message=None):
|
||||
self.message = message or 'ALTCHA verification failed'
|
||||
|
||||
def __call__(self, form, field):
|
||||
altcha_data = field.data
|
||||
|
||||
return True
|
||||
|
||||
if not altcha_data:
|
||||
raise ValidationError(self.message)
|
||||
|
||||
@@ -57,12 +59,12 @@ class ALTCHAValidator:
|
||||
except Exception as e:
|
||||
raise ValidationError(f'Invalid ALTCHA data: {str(e)}')
|
||||
|
||||
class ALTCHAField(Field):
|
||||
class AltchaField(Field):
|
||||
def __init__(self, label='', validators=None, **kwargs):
|
||||
validators = validators or []
|
||||
validators.append(ALTCHAValidator())
|
||||
validators.append(AltchaValidator())
|
||||
|
||||
super(ALTCHAField, self).__init__(label, validators, **kwargs)
|
||||
super(AltchaField, self).__init__(label, validators, **kwargs)
|
||||
|
||||
def __call__(self, **kwargs):
|
||||
html = f"""
|
||||
@@ -84,7 +86,7 @@ class Form_Contact(FlaskForm):
|
||||
receive_marketing = BooleanField('I would like to receive marketing emails.')
|
||||
# recaptcha = RecaptchaField()
|
||||
# altcha = HiddenField('ALTCHA') # , validators=[validate_altcha]
|
||||
altcha = ALTCHAField('Verify you are human')
|
||||
altcha = AltchaField('Verify you are human')
|
||||
submit = SubmitField('Send Message')
|
||||
|
||||
def to_json(self):
|
||||
|
||||
Reference in New Issue
Block a user