Update request form (#45)
* Implement OrganizationInfo form, add it to the template * Format request_new * Update "Details of Use" section * Refactor request_new * Added some new fields, but form is still WIP * Add details of use fields * Add org info fields * Add some comments * Add Financial Verification and more Details of Use fields * Update some textarea fields to single text field * WIP * Implement OrganizationInfo form, add it to the template * Format request_new * Update "Details of Use" section * Refactor request_new * Added some new fields, but form is still WIP * Add details of use fields * Add org info fields * Add some comments * Add Financial Verification and more Details of Use fields * Update some textarea fields to single text field * Format * Update fields with the correct fieldtypes * Begin updating sidenav changes * Split form into each section * adjust and skip some outdated form validation tests * break request form into multiple form objects * need to send user ID to requests-queue * use DateForm for start date in request * alter request_new handler to pass raw form data to template * change review form * Add KO and COR section titles * Update date input class name * Add a special case for the summary form. We should refactor this * Add read-only fields for review and submit section * Add minimum number validators to request form * Fix formatting * Use html5 datepicker for dates * Fix request form validators * Finish org info form * Finish POC form * Finish financial verification form * Move PE and UII to financial form * Un-skip form validation test
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
from wtforms.fields.html5 import IntegerField
|
||||
from wtforms.validators import Required, ValidationError
|
||||
from wtforms_tornado import Form
|
||||
|
||||
|
||||
class DateForm(Form):
|
||||
month = IntegerField("Month", validators=[Required()])
|
||||
day = IntegerField("Day", validators=[Required()])
|
||||
year = IntegerField("Year", validators=[Required()])
|
34
atst/forms/fields.py
Normal file
34
atst/forms/fields.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from wtforms.fields.html5 import DateField
|
||||
from wtforms.fields import Field
|
||||
from wtforms.widgets import TextArea
|
||||
import pendulum
|
||||
|
||||
|
||||
class DateField(DateField):
|
||||
def _value(self):
|
||||
if self.data:
|
||||
return pendulum.parse(self.data).date()
|
||||
else:
|
||||
return None
|
||||
|
||||
def process_formdata(self, values):
|
||||
if values:
|
||||
self.data = values[0]
|
||||
else:
|
||||
self.data = []
|
||||
|
||||
|
||||
class NewlineListField(Field):
|
||||
widget = TextArea()
|
||||
|
||||
def _value(self):
|
||||
if self.data:
|
||||
return "\n".join(self.data)
|
||||
else:
|
||||
return ""
|
||||
|
||||
def process_formdata(self, valuelist):
|
||||
if valuelist:
|
||||
self.data = [l.strip() for l in valuelist[0].split("\n")]
|
||||
else:
|
||||
self.data = []
|
87
atst/forms/financial.py
Normal file
87
atst/forms/financial.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from wtforms.fields.html5 import EmailField
|
||||
from wtforms.fields import StringField, SelectField
|
||||
from wtforms.validators import Required, Email
|
||||
from wtforms_tornado import Form
|
||||
|
||||
from .fields import NewlineListField
|
||||
|
||||
|
||||
class FinancialForm(Form):
|
||||
task_order_id = StringField(
|
||||
"Task Order Number associated with this request.", validators=[Required()]
|
||||
)
|
||||
|
||||
uii_ids = NewlineListField(
|
||||
"Please enter the Unique Item Identifier (UII)s related to your application(s) if you already have them."
|
||||
)
|
||||
|
||||
pe_id = NewlineListField(
|
||||
"Please provide the Program Element (PE) Numbers related to your request"
|
||||
)
|
||||
|
||||
fname_co = StringField("Contracting Officer First Name", validators=[Required()])
|
||||
lname_co = StringField("Contracting Officer Last Name", validators=[Required()])
|
||||
|
||||
email_co = EmailField("Contracting Officer Email", validators=[Required(), Email()])
|
||||
|
||||
office_co = StringField("Contracting Office Office", validators=[Required()])
|
||||
|
||||
fname_cor = StringField(
|
||||
"Contracting Officer Representative (COR) First Name", validators=[Required()]
|
||||
)
|
||||
|
||||
lname_cor = StringField(
|
||||
"Contracting Officer Representative (COR) Last Name", validators=[Required()]
|
||||
)
|
||||
|
||||
email_cor = EmailField(
|
||||
"Contracting Officer Representative (COR) Email",
|
||||
validators=[Required(), Email()],
|
||||
)
|
||||
|
||||
office_cor = StringField(
|
||||
"Contracting Officer Representative (COR) Office", validators=[Required()]
|
||||
)
|
||||
|
||||
funding_type = SelectField(
|
||||
validators=[Required()],
|
||||
choices=[
|
||||
("", "- Select -"),
|
||||
("RDTE", "Research, Development, Testing & Evaluation (RDT&E)"),
|
||||
("OM", "Operations & Maintenance (O&M)"),
|
||||
("PROC", "Procurement (PROC)"),
|
||||
("OTHER", "Other"),
|
||||
],
|
||||
)
|
||||
|
||||
funding_type_other = StringField(
|
||||
"If other, please specify", validators=[Required()]
|
||||
)
|
||||
|
||||
clin_0001 = StringField(
|
||||
"CLIN 0001 - Unclassified IaaS and PaaS Amount", validators=[Required()]
|
||||
)
|
||||
|
||||
clin_0003 = StringField(
|
||||
"CLIN 0003 - Unclassified Cloud Support Package", validators=[Required()]
|
||||
)
|
||||
|
||||
clin_1001 = StringField(
|
||||
"CLIN 1001 - Unclassified IaaS and PaaS Amount OPTION PERIOD 1",
|
||||
validators=[Required()],
|
||||
)
|
||||
|
||||
clin_1003 = StringField(
|
||||
"CLIN 1003 - Unclassified Cloud Support Package OPTION PERIOD 1",
|
||||
validators=[Required()],
|
||||
)
|
||||
|
||||
clin_2001 = StringField(
|
||||
"CLIN 2001 - Unclassified IaaS and PaaS Amount OPTION PERIOD 2",
|
||||
validators=[Required()],
|
||||
)
|
||||
|
||||
clin_2003 = StringField(
|
||||
"CLIN 2003 - Unclassified Cloud Support Package OPTION PERIOD 2",
|
||||
validators=[Required()],
|
||||
)
|
@@ -1,5 +0,0 @@
|
||||
from wtforms_tornado import Form
|
||||
|
||||
|
||||
class FundingForm(Form):
|
||||
pass
|
34
atst/forms/org.py
Normal file
34
atst/forms/org.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from wtforms.fields.html5 import EmailField, TelField
|
||||
from wtforms.fields import RadioField, StringField
|
||||
from wtforms.validators import Required, Length, Email
|
||||
from wtforms_tornado import Form
|
||||
from .fields import DateField
|
||||
|
||||
|
||||
class OrgForm(Form):
|
||||
fname_request = StringField("First Name", validators=[Required()])
|
||||
lname_request = StringField("Last Name", validators=[Required()])
|
||||
|
||||
email_request = EmailField(
|
||||
"Email (associated with your CAC)", validators=[Required(), Email()]
|
||||
)
|
||||
|
||||
phone_number = TelField("Phone Number", validators=[Required(), Length(min=7)])
|
||||
|
||||
service_branch = StringField("Service Branch or Agency", validators=[Required()])
|
||||
|
||||
citizenship = RadioField(
|
||||
choices=[
|
||||
("United States", "United States"),
|
||||
("Foreign National", "Foreign National"),
|
||||
("Other", "Other"),
|
||||
],
|
||||
validators=[Required()],
|
||||
)
|
||||
|
||||
designation = StringField("Designation of Person", validators=[Required()])
|
||||
|
||||
date_latest_training = DateField(
|
||||
"Latest Information Assurance (IA) Training completion date.",
|
||||
validators=[Required()],
|
||||
)
|
@@ -1,5 +0,0 @@
|
||||
from wtforms_tornado import Form
|
||||
|
||||
|
||||
class OrganizationInfoForm(Form):
|
||||
pass
|
17
atst/forms/poc.py
Normal file
17
atst/forms/poc.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from wtforms.fields import StringField
|
||||
from wtforms.validators import Required, Email, Length
|
||||
from wtforms_tornado import Form
|
||||
from .validators import IsNumber
|
||||
|
||||
|
||||
class POCForm(Form):
|
||||
fname_poc = StringField("POC First Name", validators=[Required()])
|
||||
lname_poc = StringField("POC Last Name", validators=[Required()])
|
||||
|
||||
email_poc = StringField(
|
||||
"POC Email (associated with CAC)", validators=[Required(), Email()]
|
||||
)
|
||||
|
||||
dodid_poc = StringField(
|
||||
"DOD ID", validators=[Required(), Length(min=10), IsNumber()]
|
||||
)
|
@@ -1,5 +0,0 @@
|
||||
from wtforms_tornado import Form
|
||||
|
||||
|
||||
class ReadinessForm(Form):
|
||||
pass
|
@@ -1,73 +1,87 @@
|
||||
from wtforms.fields.html5 import IntegerField
|
||||
from wtforms.fields import (
|
||||
RadioField,
|
||||
StringField,
|
||||
SelectField,
|
||||
TextAreaField,
|
||||
FormField,
|
||||
)
|
||||
from wtforms.validators import Required, ValidationError
|
||||
from wtforms.fields import RadioField, StringField, TextAreaField
|
||||
from wtforms.validators import NumberRange, InputRequired
|
||||
from wtforms_tornado import Form
|
||||
from .date import DateForm
|
||||
from .fields import DateField, NewlineListField
|
||||
from .validators import DateRange
|
||||
import pendulum
|
||||
|
||||
|
||||
class RequestForm(Form):
|
||||
application_name = StringField("Application name", validators=[Required()])
|
||||
application_description = TextAreaField(
|
||||
"Application description", validators=[Required()]
|
||||
)
|
||||
dollar_value = IntegerField(
|
||||
"Estimated dollar value of use", validators=[Required()]
|
||||
)
|
||||
input_estimate = SelectField(
|
||||
"How did you arrive at this estimate?",
|
||||
validators=[Required()],
|
||||
choices=[
|
||||
("", "- Select -"),
|
||||
("calculator", "CSP usage calculator"),
|
||||
("B", "Option B"),
|
||||
("C", "Option C"),
|
||||
],
|
||||
)
|
||||
# no way to apply a label to a whole nested form like this
|
||||
date_start = FormField(DateForm)
|
||||
period_of_performance = SelectField(
|
||||
"Desired period of performance",
|
||||
validators=[Required()],
|
||||
choices=[
|
||||
("", "- Select -"),
|
||||
("value1", "30 days"),
|
||||
("value2", "60 days"),
|
||||
("value3", "90 days"),
|
||||
],
|
||||
)
|
||||
classification_level = RadioField(
|
||||
"Classification level",
|
||||
validators=[Required()],
|
||||
choices=[
|
||||
("unclassified", "Unclassified"),
|
||||
("secret", "Secret"),
|
||||
("top-secret", "Top Secret"),
|
||||
],
|
||||
)
|
||||
primary_service_branch = StringField(
|
||||
"Primary service branch usage", validators=[Required()]
|
||||
)
|
||||
cloud_model = RadioField(
|
||||
"Cloud model service",
|
||||
validators=[Required()],
|
||||
choices=[("iaas", "IaaS"), ("paas", "PaaS"), ("both", "Both")],
|
||||
)
|
||||
number_of_cores = IntegerField("Number of cores", validators=[Required()])
|
||||
total_ram = IntegerField("Total RAM", validators=[Required()])
|
||||
object_storage = IntegerField("Total object storage", validators=[Required()])
|
||||
server_storage = IntegerField("Total server storage", validators=[Required()])
|
||||
total_active_users = IntegerField("Total active users", validators=[Required()])
|
||||
total_peak_users = IntegerField("Total peak users", validators=[Required()])
|
||||
total_requests = IntegerField("Total requests", validators=[Required()])
|
||||
total_environments = IntegerField("Total environments", validators=[Required()])
|
||||
|
||||
# this is just an example validation; obviously this is wrong.
|
||||
def validate_total_ram(self, field):
|
||||
if (field.data % 2) != 0:
|
||||
raise ValidationError("RAM must be in increments of 2.")
|
||||
# Details of Use: Overall Request Details
|
||||
dollar_value = IntegerField(
|
||||
"What is the total estimated dollar value of the cloud resources you are requesting using the JEDI CSP Calculator? ",
|
||||
validators=[InputRequired(), NumberRange(min=1)],
|
||||
)
|
||||
|
||||
num_applications = IntegerField(
|
||||
"Please estimate the number of applications that might be supported by this request",
|
||||
validators=[InputRequired(), NumberRange(min=1)],
|
||||
)
|
||||
|
||||
date_start = DateField(
|
||||
"Date you expect to start accessing this cloud resource.",
|
||||
validators=[
|
||||
InputRequired(),
|
||||
DateRange(
|
||||
lower_bound=pendulum.duration(days=0),
|
||||
message="Must be no earlier than today.",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
app_description = TextAreaField(
|
||||
"Please briefly describe how your team is expecting to use the JEDI Cloud"
|
||||
)
|
||||
|
||||
supported_organizations = StringField(
|
||||
"What organizations are supported by these applications?",
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
||||
# Details of Use: Cloud Resources
|
||||
total_cores = IntegerField(
|
||||
"Total Number of vCPU cores", validators=[InputRequired(), NumberRange(min=0)]
|
||||
)
|
||||
total_ram = IntegerField(
|
||||
"Total RAM", validators=[InputRequired(), NumberRange(min=0)]
|
||||
)
|
||||
total_object_storage = IntegerField(
|
||||
"Total object storage", validators=[InputRequired(), NumberRange(min=0)]
|
||||
)
|
||||
total_database_storage = IntegerField(
|
||||
"Total database storage", validators=[InputRequired(), NumberRange(min=0)]
|
||||
)
|
||||
total_server_storage = IntegerField(
|
||||
"Total server storage", validators=[InputRequired(), NumberRange(min=0)]
|
||||
)
|
||||
|
||||
# Details of Use: Support Staff
|
||||
has_contractor_advisor = RadioField(
|
||||
"Do you have a contractor to advise and assist you with using cloud services?",
|
||||
choices=[("yes", "Yes"), ("no", "No")],
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
||||
is_migrating_application = RadioField(
|
||||
"Are you using the JEDI Cloud to migrate existing applications?",
|
||||
choices=[("yes", "Yes"), ("no", "No")],
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
||||
supporting_organization = TextAreaField(
|
||||
"Please describe the organizations that are supporting you, include both government and contractor resources",
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
||||
has_migration_office = RadioField(
|
||||
"Do you have a migration office that you're working with to migrate to the cloud?",
|
||||
choices=[("yes", "Yes"), ("no", "No")],
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
||||
supporting_organization = StringField(
|
||||
"Please describe the organizations that are supporting you, include both government and contractor resources.",
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
@@ -1,5 +1,6 @@
|
||||
from wtforms.fields import BooleanField
|
||||
from wtforms_tornado import Form
|
||||
|
||||
|
||||
class ReviewForm(Form):
|
||||
pass
|
||||
reviewed = BooleanField("I have reviewed this data and it is correct.")
|
||||
|
29
atst/forms/validators.py
Normal file
29
atst/forms/validators.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from wtforms.validators import ValidationError
|
||||
import pendulum
|
||||
|
||||
|
||||
def DateRange(lower_bound=None, upper_bound=None, message=None):
|
||||
def _date_range(form, field):
|
||||
now = pendulum.now().date()
|
||||
|
||||
if lower_bound is not None:
|
||||
date = pendulum.parse(field.data).date()
|
||||
if (now - lower_bound) > date:
|
||||
raise ValidationError(message)
|
||||
|
||||
if upper_bound is not None:
|
||||
date = pendulum.parse(field.data).date()
|
||||
if (now + upper_bound) < date:
|
||||
raise ValidationError(message)
|
||||
|
||||
return _date_range
|
||||
|
||||
|
||||
def IsNumber(message="Please enter a valid number."):
|
||||
def _is_number(form, field):
|
||||
try:
|
||||
int(field.data)
|
||||
except ValueError:
|
||||
raise ValidationError(message)
|
||||
|
||||
return _is_number
|
Reference in New Issue
Block a user