polish task order forms
This commit is contained in:
parent
5cc5b700b7
commit
c8da258d33
@ -76,7 +76,7 @@ class TaskOrders(object):
|
||||
def is_section_complete(cls, task_order, section):
|
||||
if section in TaskOrders.SECTIONS:
|
||||
for attr in TaskOrders.SECTIONS[section]:
|
||||
if not getattr(task_order, attr):
|
||||
if getattr(task_order, attr) is None:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -1,5 +1,4 @@
|
||||
from wtforms.fields import (
|
||||
DateField,
|
||||
IntegerField,
|
||||
RadioField,
|
||||
SelectField,
|
||||
@ -7,6 +6,7 @@ from wtforms.fields import (
|
||||
StringField,
|
||||
TextAreaField,
|
||||
)
|
||||
from wtforms.fields.html5 import DateField
|
||||
|
||||
from .forms import CacheableForm
|
||||
from .data import (
|
||||
@ -28,9 +28,7 @@ class AppInfoForm(CacheableForm):
|
||||
description="The name of your office or organization. You can add multiple applications to your portfolio. Your task orders are used to pay for these applications and their environments",
|
||||
)
|
||||
defense_component = SelectField(
|
||||
"Department of Defense Component",
|
||||
description="Your team's plan for using the cloud, such as migrating an existing application or creating a prototype.",
|
||||
choices=SERVICE_BRANCHES,
|
||||
"Department of Defense Component", choices=SERVICE_BRANCHES
|
||||
)
|
||||
app_migration = RadioField(
|
||||
"App Migration",
|
||||
@ -66,27 +64,12 @@ class AppInfoForm(CacheableForm):
|
||||
|
||||
|
||||
class FundingForm(CacheableForm):
|
||||
start_date = DateField(
|
||||
"Period of Performance",
|
||||
description="Select a start and end date for your Task Order to be active. Please note, this will likely be revised once your Task Order has been approved.",
|
||||
)
|
||||
end_date = DateField("Period of Performance")
|
||||
clin_01 = IntegerField(
|
||||
"CLIN 01 : Unclassified Cloud Offerings",
|
||||
description="UNCLASSIFIED Infrastructure as a Service (IaaS) and Platform as a Service (PaaS) offerings. ",
|
||||
)
|
||||
clin_02 = IntegerField(
|
||||
"CLIN 02: Classified Cloud Offerings",
|
||||
description="CLASSIFIED Infrastructure as a Service (IaaS) and Platform as a Service (PaaS) offerings. ",
|
||||
)
|
||||
clin_03 = IntegerField(
|
||||
"CLIN 03: Unclassified Cloud Support and Assistance",
|
||||
description="UNCLASSIFIED technical guidance from the cloud service provider, including architecture, configuration of IaaS and PaaS, integration, troubleshooting assistance, and other services.",
|
||||
)
|
||||
clin_04 = IntegerField(
|
||||
"CLIN 04: Classified Cloud Support and Assistance",
|
||||
description="CLASSIFIED technical guidance from the cloud service provider, including architecture, configuration of IaaS and PaaS, integration, troubleshooting assistance, and other services.",
|
||||
)
|
||||
start_date = DateField("Start Date", format="%m/%d/%Y")
|
||||
end_date = DateField("End Date", format="%m/%d/%Y")
|
||||
clin_01 = IntegerField("CLIN 01 : Unclassified")
|
||||
clin_02 = IntegerField("CLIN 02: Classified")
|
||||
clin_03 = IntegerField("CLIN 03: Unclassified")
|
||||
clin_04 = IntegerField("CLIN 04: Classified")
|
||||
|
||||
|
||||
class OversightForm(CacheableForm):
|
||||
|
@ -76,9 +76,13 @@ class ShowTaskOrderWorkflow:
|
||||
return screen_info
|
||||
|
||||
|
||||
from flask import current_app as app
|
||||
|
||||
|
||||
class UpdateTaskOrderWorkflow(ShowTaskOrderWorkflow):
|
||||
def __init__(self, form_data, user, screen=1, task_order_id=None):
|
||||
self.form_data = form_data
|
||||
app.logger.info(form_data)
|
||||
self.user = user
|
||||
self.screen = screen
|
||||
self.task_order_id = task_order_id
|
||||
|
23
templates/components/user_info.html
Normal file
23
templates/components/user_info.html
Normal file
@ -0,0 +1,23 @@
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
|
||||
{% macro UserInfo(first_name, last_name, email, dod_id) -%}
|
||||
<div class='form-row'>
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(first_name) }}
|
||||
</div>
|
||||
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(last_name) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='form-row'>
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(email, placeholder='name@mail.mil') }}
|
||||
</div>
|
||||
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(dod_id, placeholder='1234567890') }}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
@ -11,6 +11,12 @@
|
||||
]
|
||||
) }}
|
||||
|
||||
{{ SidenavItem("New Task Order",
|
||||
href=url_for("task_orders.new", screen=1),
|
||||
icon="plus",
|
||||
active=g.matchesPath('/task_orders/new'),
|
||||
) }}
|
||||
|
||||
{% if g.current_user.has_workspaces %}
|
||||
{{ SidenavItem("Workspaces", href="/workspaces", icon="cloud", active=g.matchesPath('/workspaces')) }}
|
||||
{% endif %}
|
||||
|
19
templates/task_orders/new/_user_fields.html
Normal file
19
templates/task_orders/new/_user_fields.html
Normal file
@ -0,0 +1,19 @@
|
||||
<div class='form-row'>
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(first_name) }}
|
||||
</div>
|
||||
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(last_name) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='form-row'>
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(email, placeholder='name@mail.mil') }}
|
||||
</div>
|
||||
|
||||
<div class='form-col form-col--half'>
|
||||
{{ TextInput(dod_id, placeholder='1234567890') }}
|
||||
</div>
|
||||
</div>
|
@ -13,8 +13,14 @@
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<h3>Basic Information</h3>
|
||||
{{ TextInput(form.portfolio_name) }}
|
||||
{{ TextInput(form.portfolio_name, placeholder="The name of your office or organization") }}
|
||||
{{ TextInput(form.scope, paragraph=True) }}
|
||||
<p>
|
||||
<i>
|
||||
Not sure how to describe your scope? <a href="#">Read some Sample Scopes</a> to
|
||||
get an idea of what is appropriate.
|
||||
</i>
|
||||
</p>
|
||||
{{ OptionsInput(form.defense_component) }}
|
||||
|
||||
<hr>
|
||||
@ -35,7 +41,11 @@
|
||||
<hr>
|
||||
|
||||
<h3>Market Research</h3>
|
||||
<p>View JEDI Market Research Memo</p>
|
||||
<p>
|
||||
The JEDI Cloud Computing Program Office (CCPO) has completed the market
|
||||
research requirement for all related task orders. The Department of Defense CIO
|
||||
has approved this research. <a href="#">View JEDI Cloud Market Research</a>
|
||||
</p>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
@ -13,14 +13,64 @@
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<!-- Get Funding Section -->
|
||||
<h3>Period of Performance</h3>
|
||||
|
||||
<p>Choose the dates your task order will cover.</p>
|
||||
|
||||
<p>
|
||||
Because your funds will be lost if you don’t use them, we strongly recommend
|
||||
submitting small, short-duration task orders, usually a three month period.
|
||||
We’ll notify you when your period of performance is nearing the end so you can
|
||||
request your next set of funds with a new task order.
|
||||
</p>
|
||||
|
||||
{{ DateInput(form.start_date, placeholder='MM / DD / YYYY', validation='date') }}
|
||||
{{ DateInput(form.end_date, placeholder='MM / DD / YYYY', validation='date') }}
|
||||
<p>Cloud Usage Estimate</p>
|
||||
<p>Upload a copy of your CSP Cost Estimate Research</p>
|
||||
|
||||
<hr>
|
||||
<h3>Cloud Usage Estimate</h3>
|
||||
|
||||
<p>
|
||||
Calculate how much your cloud usage will cost. A technical representative
|
||||
should help you complete this calculation.
|
||||
<a href="{{ url_for('atst.jedi_csp_calculator') }}">
|
||||
Cloud Service Provider's estimate calculator
|
||||
</a>
|
||||
</p>
|
||||
<h4>Upload a copy of your CSP Cost Estimate Research</h4>
|
||||
|
||||
<p>
|
||||
Upload your anticipated cloud usage from the CSP tool linked above. PDFs and
|
||||
screengrabs of the tool are sufficient.
|
||||
</p>
|
||||
<p>
|
||||
This is only an estimation tool to help you make and informed evaluation of
|
||||
what you expect to use. While you're tied to the dollar amount you specify in
|
||||
your task order, you're not obligated by the resources you indicate in the
|
||||
calculator.
|
||||
</p>
|
||||
<input type="file">
|
||||
|
||||
<hr>
|
||||
<h3>Cloud Usage Calculations</h3>
|
||||
<p>
|
||||
Enter the results of your cloud usage calculations. These will correspond with
|
||||
your task order's period of performance.
|
||||
</p>
|
||||
<h4>Cloud Offerings</h4>
|
||||
<p>
|
||||
Infrastructure as a Service (IaaS) and Platform as a Service (PaaS) offerings
|
||||
</p>
|
||||
|
||||
{{ TextInput(form.clin_01, validation='dollars') }}
|
||||
{{ TextInput(form.clin_02, validation='dollars') }}
|
||||
|
||||
<h4>Cloud Support and Assistance</h4>
|
||||
<p>
|
||||
Technical guidance from the cloud service provider, including architecture,
|
||||
configuration of IaaS and PaaS, integration, troubleshooting assistance, and
|
||||
other services.
|
||||
</p>
|
||||
{{ TextInput(form.clin_03, validation='dollars', tooltip='The cloud support and assistance packages cannot be used as a primary development resource.') }}
|
||||
{{ TextInput(form.clin_04, validation='dollars', tooltip='The cloud support and assistance packages cannot be used as a primary development resource.') }}
|
||||
<p>Total Task Order Value</p>
|
||||
|
@ -1,11 +1,9 @@
|
||||
{% extends 'task_orders/_new.html' %}
|
||||
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/options_input.html" import OptionsInput %}
|
||||
{% from "components/date_input.html" import DateInput %}
|
||||
{% from "components/user_info.html" import UserInfo %}
|
||||
|
||||
{% block heading %}
|
||||
Funding
|
||||
Oversight
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
@ -14,19 +12,13 @@
|
||||
|
||||
<!-- Oversight Section -->
|
||||
<h3>Contracting Officer (KO) Information</h3>
|
||||
{{ TextInput(form.ko_first_name) }}
|
||||
{{ TextInput(form.ko_last_name) }}
|
||||
{{ TextInput(form.ko_email) }}
|
||||
{{ TextInput(form.ko_dod_id) }}
|
||||
|
||||
{{ UserInfo(form.ko_first_name, form.ko_last_name, form.ko_email, form.ko_dod_id) }}
|
||||
|
||||
<h3>Contractive Officer Representative (COR) Information</h3>
|
||||
{{ TextInput(form.cor_first_name) }}
|
||||
{{ TextInput(form.cor_last_name) }}
|
||||
{{ TextInput(form.cor_email) }}
|
||||
{{ TextInput(form.cor_dod_id) }}
|
||||
{{ UserInfo(form.cor_first_name, form.cor_last_name, form.cor_email, form.cor_dod_id) }}
|
||||
|
||||
<h3>Security Officer Information</h3>
|
||||
{{ TextInput(form.so_first_name) }}
|
||||
{{ TextInput(form.so_last_name) }}
|
||||
{{ TextInput(form.so_email) }}
|
||||
{{ TextInput(form.so_dod_id) }}
|
||||
{{ UserInfo(form.so_first_name, form.so_last_name, form.so_email, form.so_dod_id) }}
|
||||
|
||||
{% endblock %}
|
||||
|
17
templates/task_orders/new/review.html
Normal file
17
templates/task_orders/new/review.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends 'task_orders/_new.html' %}
|
||||
|
||||
{% from "components/text_input.html" import TextInput %}
|
||||
{% from "components/options_input.html" import OptionsInput %}
|
||||
{% from "components/date_input.html" import DateInput %}
|
||||
|
||||
{% block heading %}
|
||||
Review & Download
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
|
||||
{% include "fragments/flash.html" %}
|
||||
|
||||
<a href="#">Download your Task Order Packet.</a>
|
||||
|
||||
{% endblock %}
|
@ -26,6 +26,19 @@ def slice_data_for_section(task_order_data, section):
|
||||
return {k: v for k, v in task_order_data.items() if k in attrs}
|
||||
|
||||
|
||||
def serialize_dates(data):
|
||||
if not data:
|
||||
return data
|
||||
|
||||
dates = {
|
||||
k: v.strftime("%m/%d/%Y") for k, v in data.items() if hasattr(v, "strftime")
|
||||
}
|
||||
|
||||
data.update(dates)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# TODO: this test will need to be more complicated when we add validation to
|
||||
# the forms
|
||||
def test_create_new_task_order(client, user_session):
|
||||
@ -43,6 +56,7 @@ def test_create_new_task_order(client, user_session):
|
||||
assert url_for("task_orders.new", screen=2) in response.headers["Location"]
|
||||
|
||||
funding_data = slice_data_for_section(task_order_data, "funding")
|
||||
funding_data = serialize_dates(funding_data)
|
||||
response = client.post(
|
||||
response.headers["Location"], data=funding_data, follow_redirects=False
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user