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:
parent
863d323319
commit
9d781577c4
6
Pipfile.lock
generated
6
Pipfile.lock
generated
@ -148,11 +148,11 @@
|
||||
},
|
||||
"black": {
|
||||
"hashes": [
|
||||
"sha256:22158b89c1a6b4eb333a1e65e791a3f8b998cf3b11ae094adb2570f31f769a44",
|
||||
"sha256:4b475bbd528acce094c503a3d2dbc2d05a4075f6d0ef7d9e7514518e14cc5191"
|
||||
"sha256:479cc8b3455a75b5b289276b5f47fd2bb412f2f369292989c12b891264758b5c",
|
||||
"sha256:fe3b7ac846f2a7c91d926782184826c57d2be283c57f0d6b37b85496eb5469ff"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==18.6b4"
|
||||
"version": "==18.6b3"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
import tornado.gen
|
||||
from tornado.httpclient import AsyncHTTPClient
|
||||
from json import dumps, loads
|
||||
from json import dumps, loads, decoder
|
||||
|
||||
|
||||
class ApiClient(object):
|
||||
@ -49,7 +49,12 @@ class ApiClient(object):
|
||||
|
||||
def adapt_response(self, response):
|
||||
if "application/json" in response.headers["Content-Type"]:
|
||||
json = loads(response.body)
|
||||
setattr(response, "json", json)
|
||||
try:
|
||||
json = loads(response.body)
|
||||
setattr(response, "json", json)
|
||||
except decoder.JSONDecodeError:
|
||||
setattr(response, "json", {})
|
||||
else:
|
||||
setattr(response, "json", {})
|
||||
setattr(response, "ok", 200 <= response.code < 300)
|
||||
return response
|
||||
|
@ -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
|
@ -1,10 +1,10 @@
|
||||
import tornado
|
||||
from atst.handler import BaseHandler
|
||||
from atst.forms.request import RequestForm
|
||||
from atst.forms.organization_info import OrganizationInfoForm
|
||||
from atst.forms.funding import FundingForm
|
||||
from atst.forms.readiness import ReadinessForm
|
||||
from atst.forms.org import OrgForm
|
||||
from atst.forms.poc import POCForm
|
||||
from atst.forms.review import ReviewForm
|
||||
from atst.forms.financial import FinancialForm
|
||||
import tornado.httputil
|
||||
|
||||
|
||||
@ -12,18 +12,30 @@ class RequestNew(BaseHandler):
|
||||
screens = [
|
||||
{
|
||||
"title": "Details of Use",
|
||||
"section": "details_of_use",
|
||||
"form": RequestForm,
|
||||
"subitems": [
|
||||
{"title": "Application Details", "id": "application-details"},
|
||||
{"title": "Computation", "id": "computation"},
|
||||
{"title": "Storage", "id": "storage"},
|
||||
{"title": "Usage", "id": "usage"},
|
||||
{"title": "Overall request details", "id": "overall-request-details"},
|
||||
{"title": "Cloud Resources", "id": "cloud-resources"},
|
||||
{"title": "Support Staff", "id": "support-staff"},
|
||||
],
|
||||
},
|
||||
{"title": "Organizational Info", "form": OrganizationInfoForm},
|
||||
{"title": "Funding/Contracting", "form": FundingForm},
|
||||
{"title": "Readiness Survey", "form": ReadinessForm},
|
||||
{"title": "Review & Submit", "form": ReviewForm},
|
||||
{
|
||||
"title": "Information About You",
|
||||
"section": "information_about_you",
|
||||
"form": OrgForm,
|
||||
},
|
||||
{
|
||||
"title": "Primary Point of Contact",
|
||||
"section": "primary_poc",
|
||||
"form": POCForm,
|
||||
},
|
||||
{"title": "Review & Submit", "section": "review_submit", "form": ReviewForm},
|
||||
{
|
||||
"title": "Financial Verification",
|
||||
"section": "financial_verification",
|
||||
"form": FinancialForm,
|
||||
},
|
||||
]
|
||||
|
||||
def initialize(self, page, requests_client):
|
||||
@ -35,9 +47,14 @@ class RequestNew(BaseHandler):
|
||||
def post(self, screen=1, request_id=None):
|
||||
self.check_xsrf_cookie()
|
||||
screen = int(screen)
|
||||
form = self.screens[screen - 1]["form"](self.request.arguments)
|
||||
form_metadata = self.screens[screen - 1]
|
||||
form_section = form_metadata["section"]
|
||||
form = form_metadata["form"](self.request.arguments)
|
||||
|
||||
if form.validate():
|
||||
response = yield self.create_or_update_request(form.data, request_id)
|
||||
response = yield self.create_or_update_request(
|
||||
form_section, form.data, request_id
|
||||
)
|
||||
if response.ok:
|
||||
where = self.application.default_router.reverse_url(
|
||||
"request_form_update",
|
||||
@ -54,20 +71,29 @@ class RequestNew(BaseHandler):
|
||||
@tornado.gen.coroutine
|
||||
def get(self, screen=1, request_id=None):
|
||||
form = None
|
||||
form_data = None
|
||||
is_review_section = screen == 4
|
||||
|
||||
if request_id:
|
||||
request = yield self.get_request(request_id)
|
||||
if request.ok:
|
||||
form_data = request.json["body"] if request else {}
|
||||
form = self.screens[int(screen) - 1]["form"](data=form_data)
|
||||
if is_review_section:
|
||||
form_data = request.json["body"]
|
||||
else:
|
||||
form_metadata = self.screens[int(screen) - 1]
|
||||
section = form_metadata["section"]
|
||||
form_data = request.json["body"].get(section, request.json["body"])
|
||||
form = form_metadata["form"](data=form_data)
|
||||
|
||||
self.show_form(screen=screen, form=form, request_id=request_id)
|
||||
self.show_form(screen=screen, form=form, request_id=request_id, data=form_data)
|
||||
|
||||
def show_form(self, screen=1, form=None, request_id=None):
|
||||
def show_form(self, screen=1, form=None, request_id=None, data=None):
|
||||
if not form:
|
||||
form = self.screens[int(screen) - 1]["form"](self.request.arguments)
|
||||
self.render(
|
||||
"requests/screen-%d.html.to" % int(screen),
|
||||
f=form,
|
||||
data=data,
|
||||
page=self.page,
|
||||
screens=self.screens,
|
||||
current=int(screen),
|
||||
@ -78,16 +104,16 @@ class RequestNew(BaseHandler):
|
||||
@tornado.gen.coroutine
|
||||
def get_request(self, request_id):
|
||||
request = yield self.requests_client.get(
|
||||
"/users/{}/requests/{}".format(self.get_current_user(), request_id),
|
||||
"/users/{}/requests/{}".format(self.get_current_user()["id"], request_id),
|
||||
raise_error=False,
|
||||
)
|
||||
return request
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def create_or_update_request(self, form_data, request_id=None):
|
||||
def create_or_update_request(self, form_section, form_data, request_id=None):
|
||||
request_data = {
|
||||
"creator_id": self.get_current_user()["id"],
|
||||
"request": form_data,
|
||||
"request": {form_section: form_data},
|
||||
}
|
||||
if request_id:
|
||||
response = yield self.requests_client.patch(
|
||||
|
@ -2,11 +2,23 @@ from {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
select {
|
||||
border-radius: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.usa-date-input label {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
.input-label {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.usa-fieldset-inputs {
|
||||
margin-top: 2.25rem;
|
||||
|
||||
label:first-child {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
}
|
@ -13,6 +13,6 @@ h1 {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
label {
|
||||
font-style: italic;
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
}
|
@ -5,112 +5,141 @@
|
||||
|
||||
{% autoescape None %}
|
||||
{% if f.errors %}
|
||||
<b>There were some errors, see below.</b>
|
||||
<b class="usa-input-error-message">There were some errors, see below.</b>
|
||||
{% end %}
|
||||
|
||||
|
||||
<h3 id="application-details">Application Details</h3>
|
||||
<!-- DETAILS OF USE -->
|
||||
|
||||
<button class="usa-button-secondary usa-button-active">New Application</button>
|
||||
<button class="usa-button-secondary" disabled>Existing Application</button>
|
||||
<button class="usa-button-secondary" disabled>Sandbox Application</button>
|
||||
<h3 id="overall-request-details">Overall Request Details</h3>
|
||||
<p>Please help us understand the size and scope of your resource request.</p>
|
||||
|
||||
{{ f.dollar_value.label }}
|
||||
{{ f.dollar_value(placeholder="Total dollar amount to be associated with the Task Order")}}
|
||||
{% for e in f.dollar_value.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.num_applications.label }}
|
||||
{{ f.num_applications(placeholder="Estimated number of applications") }}
|
||||
{% for e in f.num_applications.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.date_start.label }}
|
||||
{{ f.date_start }}
|
||||
{% for e in f.date_start.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.supported_organizations.label }}
|
||||
{{ f.supported_organizations(placeholder="Add tags associated with DoD components or other entities") }}
|
||||
{% for e in f.supported_organizations.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.app_description.label }}
|
||||
{{ f.app_description(placeholder="Example: My organization is supporting the migration of XYZ system to the cloud due to XX policy memo. I am planning to use a sandbox environment to do testing.") }}
|
||||
{% for e in f.app_description.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<h3 id="cloud-resources">Cloud Resources</h3>
|
||||
<p>Please tell us about your expected cloud resource usage as best as you can. Please refer to the <a href="">Cloud Service Provider</a> as necessary.</p>
|
||||
|
||||
{{ f.total_cores.label }}
|
||||
{{ f.total_cores(placeholder="Expected total cores", min="1", max="32") }}
|
||||
{% for e in f.total_cores.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.total_ram.label }}
|
||||
{{ f.total_ram(placeholder="Expected amount of RAM", min="1", max="32") }}
|
||||
{% for e in f.total_ram.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.total_object_storage.label }}
|
||||
{{ f.total_object_storage(placeholder="Expected total object storage") }}
|
||||
{% for e in f.total_object_storage.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.total_database_storage.label }}
|
||||
{{ f.total_database_storage(placeholder="Expected total database storage") }}
|
||||
{% for e in f.total_database_storage.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.total_server_storage.label }}
|
||||
{{ f.total_server_storage(placeholder="Expected total server storage") }}
|
||||
{% for e in f.total_server_storage.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
|
||||
{{ f.application_name.label }}
|
||||
{{ f.application_name(placeholder="What is the application name?") }}
|
||||
|
||||
{{ f.application_description.label }}
|
||||
{{ f.application_description(placeholder="Describe the application") }}
|
||||
|
||||
{{ f.dollar_value.label }}
|
||||
{{ f.dollar_value(placeholder="$") }}
|
||||
|
||||
{{ f.input_estimate.label }}
|
||||
{{ f.input_estimate }}
|
||||
|
||||
<b>NEW</b>
|
||||
<hr>
|
||||
<fieldset>
|
||||
<label for="input-start-date">Expected start date</label>
|
||||
<div class="usa-date-of-birth">
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
{{ f.date_start.month.label }}
|
||||
{{ f.date_start.month(min="1", max="12") }}
|
||||
</div>
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
{{ f.date_start.day.label }}
|
||||
{{ f.date_start.day(min="1", max="31") }}
|
||||
</div>
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
{{ f.date_start.year.label }}
|
||||
{{ f.date_start.year(min="2000", max="2040") }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{ f.period_of_performance.label }}
|
||||
{{ f.period_of_performance }}
|
||||
|
||||
<br>
|
||||
|
||||
<fieldset class="usa-fieldset-inputs usa-sans">
|
||||
{{ f.classification_level.label }}
|
||||
{{ f.classification_level(class_="usa-unstyled-list") }}
|
||||
</fieldset>
|
||||
|
||||
{{ f.primary_service_branch.label }}
|
||||
{{ f.primary_service_branch(placeholder="Add tags associated with service branches") }}
|
||||
|
||||
<br>
|
||||
|
||||
<fieldset class="usa-fieldset-inputs usa-sans">
|
||||
{{ f.cloud_model.label }}
|
||||
{{ f.cloud_model(class_="usa-unstyled-list") }}
|
||||
</fieldset>
|
||||
<h3 id="support-staff">Support Staff</h3>
|
||||
<p>We want to learn more about the people helping you with the cloud.</p>
|
||||
|
||||
|
||||
|
||||
<!-- Computation -->
|
||||
<h4 id="application-details">Computation</h4>
|
||||
<p>These headings introduce, respectively, sections and subsections within your body copy. As you create these headings, follow the same guidelines that you use when writing section headings: Be succinct, descriptive, and precise.</p>
|
||||
|
||||
{{ f.number_of_cores.label }}
|
||||
{{ f.number_of_cores(placeholder="Total cores", min="1", max="32") }}
|
||||
|
||||
<!-- example field with custom validation -->
|
||||
{{ f.total_ram.label }}
|
||||
{{ f.total_ram(placeholder="Total RAM", min="1", max="32") }}
|
||||
<!-- example validation errors -->
|
||||
{% for e in f.total_ram.errors %}
|
||||
<fieldset class="usa-fieldset-inputs">
|
||||
{{ f.has_contractor_advisor.label }}
|
||||
{{ f.has_contractor_advisor(class_="usa-unstyled-list") }}
|
||||
{% for e in f.has_contractor_advisor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="usa-fieldset-inputs">
|
||||
{{ f.is_migrating_application.label }}
|
||||
{{ f.is_migrating_application(class_="usa-unstyled-list") }}
|
||||
{% for e in f.is_migrating_application.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
</fieldset>
|
||||
|
||||
<!-- Storage -->
|
||||
<h4 id="application-storage">Storage</h4>
|
||||
<p>The particulars of your body copy will be determined by the topic of your page. Regardless of topic, it’s a good practice to follow the inverted pyramid structure when writing copy: Begin with the information that’s most important to your users and then present information of less importance.</p>
|
||||
<fieldset class="usa-fieldset-inputs">
|
||||
{{ f.has_migration_office.label }}
|
||||
{{ f.has_migration_office(class_="usa-unstyled-list") }}
|
||||
{% for e in f.has_migration_office.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
</fieldset>
|
||||
|
||||
{{ f.object_storage.label }}
|
||||
{{ f.object_storage(placeholder="Total object storage") }}
|
||||
<fieldset class="usa-fieldset-inputs">
|
||||
{{ f.supporting_organization.label }}
|
||||
{{ f.supporting_organization(placeholder="Example: AF CCE/HNI, Navy SPAWAR, MITRE", class_="usa-unstyled-list") }}
|
||||
{% for e in f.supporting_organization.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
</fieldset>
|
||||
|
||||
{{ f.server_storage.label }}
|
||||
{{ f.server_storage(placeholder="Total server storage") }}
|
||||
|
||||
<!-- Application Usage -->
|
||||
<h4 id="application-usage">Estimated Application Storage</h4>
|
||||
<p>The particulars of your body copy will be determined by the topic of your page. Regardless of topic, it’s a good practice to follow the inverted pyramid structure when writing copy: Begin with the information that’s most important to your users and then present information of less importance.</p>
|
||||
|
||||
{{ f.total_active_users.label }}
|
||||
{{ f.total_active_users(placeholder="Total active users") }}
|
||||
|
||||
{{ f.total_peak_users.label }}
|
||||
{{ f.total_peak_users(placeholder="Total peak users") }}
|
||||
|
||||
{{ f.total_requests.label }}
|
||||
{{ f.total_requests(placeholder="Total requests") }}
|
||||
|
||||
{{ f.total_environments.label }}
|
||||
{{ f.total_environments(placeholder="Total number of environments") }}
|
||||
{% end %}
|
||||
|
@ -2,90 +2,79 @@
|
||||
|
||||
{% block form %}
|
||||
|
||||
|
||||
<h2>Organizational Info</h2>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque placeat distinctio accusamus quo temporibus facilis, dicta delectus asperiores. Nihil aut quod quibusdam id fugit, officia dolorum laudantium! Quidem tempora, aliquam.</p>
|
||||
|
||||
<h3 id="information-about-you">Information About You</h3>
|
||||
|
||||
<label for="">Name</label>
|
||||
<input id="" name="" type="text">
|
||||
|
||||
<label for="">Email</label>
|
||||
<input id="" name="" type="email" placeholder="i.e. name@mail.gov">
|
||||
|
||||
<label for="">Phone Number</label>
|
||||
<input id="" name="" type="text" placeholder="i.e. (123) 456-7890">
|
||||
|
||||
<label for="">Office Symbol / Department</label>
|
||||
<input id="" name="" type="text" placeholder="i.e. Army PEO-EIS">
|
||||
|
||||
<fieldset>
|
||||
<label for="">Citizenship</label>
|
||||
<ul class="usa-unstyled-list">
|
||||
<li>
|
||||
<input id="" type="radio" name="" value"">
|
||||
<label class="input-label">United States</label>
|
||||
</li>
|
||||
<li>
|
||||
<input id="" type="radio" name="" value"">
|
||||
<label class="input-label">Foreign National</label>
|
||||
</li>
|
||||
<li>
|
||||
<input id="" type="radio" name="" value"">
|
||||
<label class="input-label">Other</label>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<label for="">Designation of Person</label>
|
||||
<ul class="usa-unstyled-list">
|
||||
<li>
|
||||
<input id="" type="radio" name="" value"">
|
||||
<label class="input-label">Military</label>
|
||||
</li>
|
||||
<li>
|
||||
<input id="" type="radio" name="" value"">
|
||||
<label class="input-label">Civilian</label>
|
||||
</li>
|
||||
<li>
|
||||
<input id="" type="radio" name="" value"">
|
||||
<label class="input-label">Contractor</label>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
|
||||
|
||||
<fieldset>
|
||||
<label for="">Latest IA Training completion date</label>
|
||||
|
||||
<div class="usa-date-input">
|
||||
<div class="usa-form-group usa-form-group-month">
|
||||
<label for="">Month</label>
|
||||
<input class="usa-input-inline" id="" name="" type="number" min="1" max="12" value="">
|
||||
</div>
|
||||
<div class="usa-form-group usa-form-group-day">
|
||||
<label for="">Day</label>
|
||||
<input class="usa-input-inline" id="" name="" type="number" min="1" max="31" value="">
|
||||
</div>
|
||||
<div class="usa-form-group usa-form-group-year">
|
||||
<label for="">Year</label>
|
||||
<input class="usa-input-inline" id="" name="" type="number" min="1900" max="2000" value="">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
|
||||
<h3 id="information-about-your-collaborators">Information About Your Collaborators</h3>
|
||||
<p>Please designate a Contracting Officer that will help you complete this process.</p>
|
||||
<label for="">Name</label>
|
||||
<input id="" name="" type="text">
|
||||
|
||||
<label for="">Email</label>
|
||||
<input id="" name="" type="text" placeholder="i.e. name@mail.gov">
|
||||
|
||||
|
||||
{% autoescape None %}
|
||||
{% if f.errors %}
|
||||
<b class="usa-input-error-message">There were some errors, see below.</b>
|
||||
{% end %}
|
||||
|
||||
|
||||
<h2 id="Information About You">Information About You</h2>
|
||||
<p>Please tell us more about yourself.</p>
|
||||
|
||||
{{ f.fname_request.label }}
|
||||
{{ f.fname_request(placeholder="Your first name") }}
|
||||
{% for e in f.fname_request.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.lname_request.label }}
|
||||
{{ f.lname_request(placeholder="Your last name") }}
|
||||
{% for e in f.lname_request.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.email_request.label }}
|
||||
{{ f.email_request(placeholder="jane@mail.mil") }}
|
||||
{% for e in f.email_request.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.phone_number.label }}
|
||||
{{ f.phone_number(placeholder="(123) 456-7890") }}
|
||||
{% for e in f.phone_number.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.service_branch.label }}
|
||||
{{ f.service_branch(placeholder="i.e. US Air Force, US Army, US Navy, Marine Corps, Defense Media Agency") }}
|
||||
{% for e in f.service_branch.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<fieldset class="usa-fieldset-inputs">
|
||||
{{ f.citizenship.label }}
|
||||
{{ f.citizenship(class_="usa-unstyled-list") }}
|
||||
{% for e in f.citizenship.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
</fieldset>
|
||||
|
||||
{{ f.designation.label }}
|
||||
{{ f.designation }}
|
||||
{% for e in f.designation.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.date_latest_training.label }}
|
||||
{{ f.date_latest_training }}
|
||||
{% for e in f.date_latest_training.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{% end %}
|
||||
|
@ -1,7 +1,55 @@
|
||||
{% extends '../requests_new.html.to' %}
|
||||
|
||||
{% block form %}
|
||||
<h2>Funding/Contracting</h2>
|
||||
<input type='textbox'>
|
||||
|
||||
{% autoescape None %}
|
||||
{% if f.errors %}
|
||||
<b class="usa-input-error-message">There were some errors, see below.</b>
|
||||
{% end %}
|
||||
|
||||
<h2 id="primary-poc">Primary Government/Military <br> Point of Contact (POC)</h2>
|
||||
<p>Please designate a Primary Point of Contact that will be responsible for owning the workspace in the JEDI Cloud.</p>
|
||||
<p>The Point of Contact will become the primary owner of the <em>workspace</em> created to use the JEDI Cloud. As a workspace owner, this person will have the ability to:
|
||||
<ul>
|
||||
<li>Create multiple application stacks and environments in the workspace to access the commercial cloud service provider portal</li>
|
||||
<li>Add and manage users in the workspace</li>
|
||||
<li>View the budget and billing history related to this workspace</li>
|
||||
<li>Manage access to the Cloud Service Provider's Console</li>
|
||||
<li>Transfer Workspace ownership to another person</li>
|
||||
</ul>
|
||||
<em>This POC may be you.</em>
|
||||
</p>
|
||||
|
||||
{{ f.fname_poc.label }}
|
||||
{{ f.fname_poc(placeholder="First name") }}
|
||||
{% for e in f.fname_poc.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.lname_poc.label }}
|
||||
{{ f.lname_poc(placeholder="Last name") }}
|
||||
{% for e in f.lname_poc.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.email_poc.label }}
|
||||
{{ f.email_poc(placeholder="jane@mail.mil") }}
|
||||
{% for e in f.email_poc.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.dodid_poc.label }}
|
||||
{{ f.dodid_poc(placeholder="10-digit number on the back of the CAC") }}
|
||||
{% for e in f.dodid_poc.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{% end %}
|
||||
|
@ -1,7 +1,123 @@
|
||||
{% extends '../requests_new.html.to' %}
|
||||
|
||||
{% block form %}
|
||||
<h2>Readiness Survey</h2>
|
||||
<input type='textbox'>
|
||||
|
||||
{% autoescape None %}
|
||||
{% if f.errors %}
|
||||
<b>There were some errors, see below.</b>
|
||||
{% end %}
|
||||
|
||||
<h2 id="review-submit">Review & Submit</h2>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem ullam veritatis fuga non repellendus repellat dolorum labore nulla iure aspernatur ipsam recusandae saepe harum iste, dolorem adipisci dolores eum, doloribus?</p>
|
||||
|
||||
<h3>Details of Use <a href="">Edit</a></h3>
|
||||
|
||||
<h4>Overall Request Details</h4>
|
||||
|
||||
<label>What is the total estimated dollar value of the cloud resources you are requesting using the JEDI CSP Calculator? </label>
|
||||
<b>{{ data.get('details_of_use', {}).get('dollar_value') }}</b>
|
||||
|
||||
<label>Please estimate the number of applications that might be supported by this request</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('num_applications') }}</b>
|
||||
|
||||
<label>Start Date</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('date_start') }}</b>
|
||||
|
||||
<label>Please briefly describe how your team is expecting to use the JEDI Cloud</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('app_description') }}</b>
|
||||
|
||||
<label>What organizations are supported by these applications?</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('supported_organizations') }}</b>
|
||||
|
||||
<label>Please enter the Unique Item Identifier (UII)s related to your application(s) if you already have them.</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('uii_ids') }}</b>
|
||||
|
||||
<label>Please provide the Program Element (PE) Numbers related to your request</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('pe_id') }}</b>
|
||||
|
||||
<h4>Cloud Resources</h4>
|
||||
|
||||
<label>Total Number of vCPU cores</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('total_cores') }}</b>
|
||||
|
||||
<label>Total RAM</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('total_ram') }}</b>
|
||||
|
||||
<label>Total object storage</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('total_object_storage') }}</b>
|
||||
|
||||
<label>Total server storage</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('total_server_storage') }}</b>
|
||||
|
||||
<h4>Support Staff</h4>
|
||||
|
||||
<label>Do you have a contractor to advise and assist you with using cloud services?</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('has_contractor_advisor') }}</b>
|
||||
|
||||
<label>Are you using the JEDI Cloud to migrate existing applications?</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('is_migrating_application') }}</b>
|
||||
|
||||
<label>Please describe the organizations that are supporting you, include both government and contractor resources</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('supporting_organization') }}</b>
|
||||
|
||||
<label>Do you have a migration office that you're working with to migrate to the cloud?</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('has_migration_office') }}</b>
|
||||
|
||||
<label>Please describe the organizations that are supporting you, include both government and contractor resources.</label>
|
||||
<b>{{ data.get('details_of_use', {}).get('supporting_organization') }}</b>
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
<h3>Information About You <a href="">Edit</a></h3>
|
||||
|
||||
<label>First Name</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('fname_request') }}</b>
|
||||
|
||||
<label>Last Name</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('lname_request') }}</b>
|
||||
|
||||
<label>Email (associated with your CAC)</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('email_request') }}</b>
|
||||
|
||||
<label>Phone Number</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('phone_number') }}</b>
|
||||
|
||||
<label>Service Branch or Agency</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('service_branch') }}</b>
|
||||
|
||||
<label>Citizenship</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('citizenship') }}</b>
|
||||
|
||||
<label>Designation of Person</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('designation') }}</b>
|
||||
|
||||
<label>Latest Information Assurance (IA) Training completion date</label>
|
||||
<b>{{ data.get('information_about_you', {}).get('date_latest_training') }}</b>
|
||||
|
||||
|
||||
<br><br><hr>
|
||||
|
||||
<h3>Primary Government/Military Point of Contact (POC) <a href="">Edit</a></h3>
|
||||
|
||||
|
||||
|
||||
<label>POC First Name</label>
|
||||
<b>{{ data.get('primary_poc', {}).get('fname_poc')}}</b>
|
||||
|
||||
<label>POC Last Name</label>
|
||||
<b>{{ data.get('primary_poc', {}).get('lname_poc')}}</b>
|
||||
|
||||
<label>POC Email (associated with CAC)</label>
|
||||
<b>{{ data.get('primary_poc', {}).get('email_poc')}} </b>
|
||||
|
||||
<label>DOD ID</label>
|
||||
<b>{{ data.get('primary_poc', {}).get('dodid_poc')}}</b>
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
{% end %}
|
||||
|
||||
{% block next %}
|
||||
<input type='submit' class='usa-button usa-button-primary' value='Submit' />
|
||||
{% end %}
|
||||
|
@ -1,202 +1,176 @@
|
||||
{% extends '../requests_new.html.to' %}
|
||||
|
||||
{% block form %}
|
||||
<h2>Review & Submit</h2>
|
||||
<p class="usa-font-lead">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae placeat maiores illo totam consequuntur ipsum quo animi earum voluptatem, velit minus, perferendis aperiam, tenetur alias nemo ratione accusantium, ullam at!</p>
|
||||
|
||||
|
||||
<h3>1. Details of Use <a href="" class="usa-button usa-button-secondary">Edit</a></h3>
|
||||
|
||||
|
||||
<h4>Applications & Environments (2)</h4>
|
||||
<table class="usa-table-borderless" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Application Name</th>
|
||||
<th scope="col">Total Users</th>
|
||||
<th scope="col">Estimated Cost</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="#app-code-mil">Code.mil</a></td>
|
||||
<td>235</td>
|
||||
<td>$1,000,000,000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#app-digital-dojo">Digital Dojo</a></td>
|
||||
<td>1,337</td>
|
||||
<td>$10,000</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5 id="app-code-mil">Code.mil</h5>
|
||||
|
||||
<h6>Application Details</h6>
|
||||
<label>Application description</label>
|
||||
<span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore tempora provident labore, deleniti facilis dolorum impedit repellat, et, quisquam modi eos libero nulla ut excepturi omnis. At magnam assumenda vero.</span>
|
||||
|
||||
<label>Estimated dollar value of use</label>
|
||||
<span>$1,000,000,000</span>
|
||||
|
||||
<label>How did you arrive at this estimate?</label>
|
||||
<span>CSP Calculator</span>
|
||||
|
||||
<label>Expected start date</label>
|
||||
<span>2020-03-02</span>
|
||||
|
||||
<label>Desired period of performance</label>
|
||||
<span>Lots of it</span>
|
||||
|
||||
<label>Classification level</label>
|
||||
<span>Secret</span>
|
||||
|
||||
<label>Primary service branch usage</label>
|
||||
<span>Army</span>
|
||||
|
||||
<label>Cloud model service</label>
|
||||
<span>IaaS and PaaS</span>
|
||||
|
||||
<h6>Computation</h6>
|
||||
<label>Number of cores</label>
|
||||
<span>32</span>
|
||||
|
||||
<label>Total RAM</label>
|
||||
<span>128GB</span>
|
||||
|
||||
<h6>Storage</h6>
|
||||
<label>Object storage</label>
|
||||
<span>10TB</span>
|
||||
|
||||
<label>Server storage</label>
|
||||
<span>100TB</span>
|
||||
|
||||
<h6>Estimated Application Storage</h6>
|
||||
<label>Expected active users</label>
|
||||
<span>300</span>
|
||||
|
||||
<label>Expected peak concurrent users</label>
|
||||
<span>1,000</span>
|
||||
|
||||
<label>Expected requests per minute</label>
|
||||
<span>1,000</span>
|
||||
|
||||
<label>Number of application environments</label>
|
||||
<span>3</span>
|
||||
|
||||
|
||||
<h5 id="app-digital-dojo">Digital Dojo</h5>
|
||||
|
||||
<h6>Application Details</h6>
|
||||
<label>Application description</label>
|
||||
<span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore tempora provident labore, deleniti facilis dolorum impedit repellat, et, quisquam modi eos libero nulla ut excepturi omnis. At magnam assumenda vero.</span>
|
||||
|
||||
<label>Estimated dollar value of use</label>
|
||||
<span>$10,000</span>
|
||||
|
||||
<label>How did you arrive at this estimate?</label>
|
||||
<span>CSP Calculator</span>
|
||||
|
||||
<label>Expected start date</label>
|
||||
<span>2020-03-02</span>
|
||||
|
||||
<label>Desired period of performance</label>
|
||||
<span>Lots of it</span>
|
||||
|
||||
<label>Classification level</label>
|
||||
<span>Secret</span>
|
||||
|
||||
<label>Primary service branch usage</label>
|
||||
<span>Army</span>
|
||||
|
||||
<label>Cloud model service</label>
|
||||
<span>IaaS and PaaS</span>
|
||||
|
||||
<h6>Computation</h6>
|
||||
<label>Number of cores</label>
|
||||
<span>32</span>
|
||||
|
||||
<label>Total RAM</label>
|
||||
<span>128GB</span>
|
||||
|
||||
<h6>Storage</h6>
|
||||
<label>Object storage</label>
|
||||
<span>10TB</span>
|
||||
|
||||
<label>Server storage</label>
|
||||
<span>100TB</span>
|
||||
|
||||
<h6>Estimated Application Storage</h6>
|
||||
<label>Expected active users</label>
|
||||
<span>300</span>
|
||||
|
||||
<label>Expected peak concurrent users</label>
|
||||
<span>1,000</span>
|
||||
|
||||
<label>Expected requests per minute</label>
|
||||
<span>1,000</span>
|
||||
|
||||
<label>Number of application environments</label>
|
||||
<span>3</span>
|
||||
|
||||
|
||||
<h3>2. Organizational Info <a href="" class="usa-button usa-button-secondary">Edit</a></h3>
|
||||
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sint qui rem molestiae officia vitae quas error ut, est commodi quo! Error itaque earum, facere quod dolore qui beatae repudiandae accusantium.</p>
|
||||
<h4>Information About Requester</h4>
|
||||
|
||||
|
||||
<label>Name</label>
|
||||
<span>Friedrich Straat</span>
|
||||
|
||||
<label>Email</label>
|
||||
<span>fstraat@mail.gov</span>
|
||||
|
||||
<label>Phone Number</label>
|
||||
<span>(123) 456-7890</span>
|
||||
|
||||
<label>Office Symbol / Department</label>
|
||||
<span>Army</span>
|
||||
|
||||
|
||||
<label>Citizenship</label>
|
||||
<span>United States</span>
|
||||
|
||||
|
||||
<label>Designation of Person</label>
|
||||
<span>Military</span>
|
||||
|
||||
|
||||
<label>Latest IA Training completion date</label>
|
||||
<span>2018-04-12</span>
|
||||
|
||||
|
||||
<h4>Information About Collaborators</h4>
|
||||
|
||||
<label>Name</label>
|
||||
<span>Pietro Quirinis</span>
|
||||
|
||||
<label>Email</label>
|
||||
<span>quirinis@mail.gov</span>
|
||||
|
||||
|
||||
|
||||
<h3>3. Funding & Contracting <a href="" class="usa-button usa-button-secondary">Edit</a></h3>
|
||||
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Esse inventore non illo quibusdam tempora vero temporibus reprehenderit sapiente cumque enim quaerat fuga praesentium nemo vel, expedita numquam sequi sed iusto!</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br><br>
|
||||
{% autoescape None %}
|
||||
{% if f.errors %}
|
||||
<b class="usa-input-error-message">There were some errors, see below.</b>
|
||||
{% end %}
|
||||
|
||||
|
||||
<h2 id="financial-verification">Financial Verification</h2>
|
||||
<p>In order to get you access to the JEDI Cloud, we will need you to enter the details below that will help us verify and account for your Task Order.</p>
|
||||
|
||||
{{ f.task_order_id.label }}
|
||||
{{ f.task_order_id(placeholder="Example: 1234567899C0001") }}
|
||||
{% for e in f.task_order_id.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.uii_ids.label }}
|
||||
{{ f.uii_ids(placeholder="Example: \nDI 0CVA5786950 \nUN1945326361234786950") }}
|
||||
{% for e in f.uii_ids.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.pe_id.label }}
|
||||
{{ f.pe_id(placeholder="Example: 0203752A") }}
|
||||
{% for e in f.pe_id.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
|
||||
<h3>Contracting Officer (KO) Information</h3>
|
||||
|
||||
{{ f.fname_co.label }}
|
||||
{{ f.fname_co(placeholder="Contracting Officer first name") }}
|
||||
{% for e in f.fname_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.lname_co.label }}
|
||||
{{ f.lname_co(placeholder="Contracting Officer last name") }}
|
||||
{% for e in f.lname_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.email_co.label }}
|
||||
{{ f.email_co(placeholder="jane@mail.mil") }}
|
||||
{% for e in f.email_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.office_co.label }}
|
||||
{{ f.office_co(placeholder="Example: WHS") }}
|
||||
{% for e in f.office_co.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<h3>Contracting Officer Representative (COR) Information</h3>
|
||||
|
||||
{{ f.fname_cor.label }}
|
||||
{{ f.fname_cor(placeholder="Contracting Officer Representative first name") }}
|
||||
{% for e in f.fname_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.lname_cor.label }}
|
||||
{{ f.lname_cor(placeholder="Contracting Officer Representative last name") }}
|
||||
{% for e in f.lname_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.email_cor.label }}
|
||||
{{ f.email_cor(placeholder="jane@mail.mil") }}
|
||||
{% for e in f.email_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.office_cor.label }}
|
||||
{{ f.office_cor(placeholder="Example: WHS") }}
|
||||
{% for e in f.office_cor.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
<br><hr>
|
||||
<em>↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available)</em>
|
||||
|
||||
|
||||
{{ f.funding_type.label }}
|
||||
{{ f.funding_type }}
|
||||
{% for e in f.funding_type.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.funding_type_other.label }}
|
||||
{{ f.funding_type_other(placeholder="") }}
|
||||
{% for e in f.funding_type_other.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_0001.label }}
|
||||
{{ f.clin_0001(placeholder="50,000") }}
|
||||
{% for e in f.clin_0001.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_0003.label }}
|
||||
{{ f.clin_0003(placeholder="13,000") }}
|
||||
{% for e in f.clin_0003.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_1001.label }}
|
||||
{{ f.clin_1001(placeholder="30,000") }}
|
||||
{% for e in f.clin_1001.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_1003.label }}
|
||||
{{ f.clin_1003(placeholder="7,000") }}
|
||||
{% for e in f.clin_1003.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_2001.label }}
|
||||
{{ f.clin_2001(placeholder="30,000") }}
|
||||
{% for e in f.clin_2001.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{{ f.clin_2003.label }}
|
||||
{{ f.clin_2003(placeholder="7,000") }}
|
||||
{% for e in f.clin_2003.errors %}
|
||||
<div class="usa-input-error-message">
|
||||
{{ e }}
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
|
||||
{% end %}
|
||||
|
||||
{% block next %}
|
||||
<a class='usa-button'>Submit</a>
|
||||
{% end %}
|
||||
|
@ -6,11 +6,5 @@ form = RequestForm()
|
||||
|
||||
|
||||
def test_form_has_expected_fields():
|
||||
label = form.application_name.label
|
||||
assert label.text == "Application name"
|
||||
|
||||
|
||||
def test_form_can_validate_total_ram():
|
||||
form.application_name.data = 5
|
||||
with pytest.raises(wtforms.validators.ValidationError):
|
||||
form.validate_total_ram(form.application_name)
|
||||
label = form.dollar_value.label
|
||||
assert "estimated dollar value" in label.text
|
||||
|
Loading…
x
Reference in New Issue
Block a user