polish task order forms

This commit is contained in:
dandds 2018-12-18 16:19:52 -05:00
parent 5cc5b700b7
commit c8da258d33
11 changed files with 164 additions and 46 deletions

View File

@ -76,7 +76,7 @@ class TaskOrders(object):
def is_section_complete(cls, task_order, section): def is_section_complete(cls, task_order, section):
if section in TaskOrders.SECTIONS: if section in TaskOrders.SECTIONS:
for attr in TaskOrders.SECTIONS[section]: for attr in TaskOrders.SECTIONS[section]:
if not getattr(task_order, attr): if getattr(task_order, attr) is None:
return False return False
return True return True

View File

@ -1,5 +1,4 @@
from wtforms.fields import ( from wtforms.fields import (
DateField,
IntegerField, IntegerField,
RadioField, RadioField,
SelectField, SelectField,
@ -7,6 +6,7 @@ from wtforms.fields import (
StringField, StringField,
TextAreaField, TextAreaField,
) )
from wtforms.fields.html5 import DateField
from .forms import CacheableForm from .forms import CacheableForm
from .data import ( 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", 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( defense_component = SelectField(
"Department of Defense Component", "Department of Defense Component", choices=SERVICE_BRANCHES
description="Your team's plan for using the cloud, such as migrating an existing application or creating a prototype.",
choices=SERVICE_BRANCHES,
) )
app_migration = RadioField( app_migration = RadioField(
"App Migration", "App Migration",
@ -66,27 +64,12 @@ class AppInfoForm(CacheableForm):
class FundingForm(CacheableForm): class FundingForm(CacheableForm):
start_date = DateField( start_date = DateField("Start Date", format="%m/%d/%Y")
"Period of Performance", end_date = DateField("End Date", format="%m/%d/%Y")
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.", clin_01 = IntegerField("CLIN 01 : Unclassified")
) clin_02 = IntegerField("CLIN 02: Classified")
end_date = DateField("Period of Performance") clin_03 = IntegerField("CLIN 03: Unclassified")
clin_01 = IntegerField( clin_04 = IntegerField("CLIN 04: Classified")
"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.",
)
class OversightForm(CacheableForm): class OversightForm(CacheableForm):

View File

@ -76,9 +76,13 @@ class ShowTaskOrderWorkflow:
return screen_info return screen_info
from flask import current_app as app
class UpdateTaskOrderWorkflow(ShowTaskOrderWorkflow): class UpdateTaskOrderWorkflow(ShowTaskOrderWorkflow):
def __init__(self, form_data, user, screen=1, task_order_id=None): def __init__(self, form_data, user, screen=1, task_order_id=None):
self.form_data = form_data self.form_data = form_data
app.logger.info(form_data)
self.user = user self.user = user
self.screen = screen self.screen = screen
self.task_order_id = task_order_id self.task_order_id = task_order_id

View 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 %}

View File

@ -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 %} {% if g.current_user.has_workspaces %}
{{ SidenavItem("Workspaces", href="/workspaces", icon="cloud", active=g.matchesPath('/workspaces')) }} {{ SidenavItem("Workspaces", href="/workspaces", icon="cloud", active=g.matchesPath('/workspaces')) }}
{% endif %} {% endif %}

View 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>

View File

@ -13,8 +13,14 @@
{% include "fragments/flash.html" %} {% include "fragments/flash.html" %}
<h3>Basic Information</h3> <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) }} {{ 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) }} {{ OptionsInput(form.defense_component) }}
<hr> <hr>
@ -35,7 +41,11 @@
<hr> <hr>
<h3>Market Research</h3> <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 %} {% endblock %}

View File

@ -13,14 +13,64 @@
{% include "fragments/flash.html" %} {% include "fragments/flash.html" %}
<!-- Get Funding Section --> <!-- 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 dont use them, we strongly recommend
submitting small, short-duration task orders, usually a three month period.
Well 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.start_date, placeholder='MM / DD / YYYY', validation='date') }}
{{ DateInput(form.end_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> <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_01, validation='dollars') }}
{{ TextInput(form.clin_02, 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_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.') }} {{ 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> <p>Total Task Order Value</p>

View File

@ -1,11 +1,9 @@
{% extends 'task_orders/_new.html' %} {% extends 'task_orders/_new.html' %}
{% from "components/text_input.html" import TextInput %} {% from "components/user_info.html" import UserInfo %}
{% from "components/options_input.html" import OptionsInput %}
{% from "components/date_input.html" import DateInput %}
{% block heading %} {% block heading %}
Funding Oversight
{% endblock %} {% endblock %}
{% block form %} {% block form %}
@ -14,19 +12,13 @@
<!-- Oversight Section --> <!-- Oversight Section -->
<h3>Contracting Officer (KO) Information</h3> <h3>Contracting Officer (KO) Information</h3>
{{ TextInput(form.ko_first_name) }}
{{ TextInput(form.ko_last_name) }} {{ UserInfo(form.ko_first_name, form.ko_last_name, form.ko_email, form.ko_dod_id) }}
{{ TextInput(form.ko_email) }}
{{ TextInput(form.ko_dod_id) }}
<h3>Contractive Officer Representative (COR) Information</h3> <h3>Contractive Officer Representative (COR) Information</h3>
{{ TextInput(form.cor_first_name) }} {{ UserInfo(form.cor_first_name, form.cor_last_name, form.cor_email, form.cor_dod_id) }}
{{ TextInput(form.cor_last_name) }}
{{ TextInput(form.cor_email) }}
{{ TextInput(form.cor_dod_id) }}
<h3>Security Officer Information</h3> <h3>Security Officer Information</h3>
{{ TextInput(form.so_first_name) }} {{ UserInfo(form.so_first_name, form.so_last_name, form.so_email, form.so_dod_id) }}
{{ TextInput(form.so_last_name) }}
{{ TextInput(form.so_email) }}
{{ TextInput(form.so_dod_id) }}
{% endblock %} {% endblock %}

View 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 %}

View File

@ -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} 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 # TODO: this test will need to be more complicated when we add validation to
# the forms # the forms
def test_create_new_task_order(client, user_session): 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"] assert url_for("task_orders.new", screen=2) in response.headers["Location"]
funding_data = slice_data_for_section(task_order_data, "funding") funding_data = slice_data_for_section(task_order_data, "funding")
funding_data = serialize_dates(funding_data)
response = client.post( response = client.post(
response.headers["Location"], data=funding_data, follow_redirects=False response.headers["Location"], data=funding_data, follow_redirects=False
) )