Merge pull request #543 from dod-ccpo/update-to-form-part-2
Update Task Order Form - Part 2
This commit is contained in:
commit
9af74a8a53
@ -1,6 +1,6 @@
|
||||
import re
|
||||
import datetime
|
||||
from atst.utils.localization import translate
|
||||
from atst.utils.localization import translate, translate_duration
|
||||
from flask import current_app as app, render_template
|
||||
from jinja2 import contextfilter
|
||||
from jinja2.exceptions import TemplateNotFound
|
||||
@ -97,6 +97,19 @@ def renderAuditEvent(event):
|
||||
return render_template("audit_log/events/default.html", event=event)
|
||||
|
||||
|
||||
def removeHtml(text):
|
||||
html_tags = re.compile("<.*?>")
|
||||
return re.sub(html_tags, "", text)
|
||||
|
||||
|
||||
def normalizeOrder(title):
|
||||
# reorders titles from "Army, Department of the" to "Department of the Army"
|
||||
text = title.split(", ")
|
||||
reordered_text = text[0:-1]
|
||||
reordered_text.insert(0, text[-1])
|
||||
return " ".join(reordered_text)
|
||||
|
||||
|
||||
def register_filters(app):
|
||||
app.jinja_env.filters["iconSvg"] = iconSvg
|
||||
app.jinja_env.filters["dollars"] = dollars
|
||||
@ -110,6 +123,9 @@ def register_filters(app):
|
||||
app.jinja_env.filters["dateFromString"] = dateFromString
|
||||
app.jinja_env.filters["pageWindow"] = pageWindow
|
||||
app.jinja_env.filters["renderAuditEvent"] = renderAuditEvent
|
||||
app.jinja_env.filters["removeHtml"] = removeHtml
|
||||
app.jinja_env.filters["normalizeOrder"] = normalizeOrder
|
||||
app.jinja_env.filters["translateDuration"] = translate_duration
|
||||
|
||||
@contextfilter
|
||||
def translateWithoutCache(context, *kwargs):
|
||||
|
@ -1,4 +1,6 @@
|
||||
from atst.domain.roles import PORTFOLIO_ROLES as PORTFOLIO_ROLE_DEFINITIONS
|
||||
from atst.utils.localization import translate, translate_duration
|
||||
|
||||
|
||||
SERVICE_BRANCHES = [
|
||||
("", "Select an option"),
|
||||
@ -176,67 +178,41 @@ FUNDING_TYPES = [
|
||||
TASK_ORDER_SOURCES = [("MANUAL", "Manual"), ("EDA", "EDA")]
|
||||
|
||||
APP_MIGRATION = [
|
||||
("on_premise", "Yes, migrating from an <strong>on-premise data center</strong>"),
|
||||
("cloud", "Yes, migrating from <strong>another cloud provider</strong>"),
|
||||
(
|
||||
"both",
|
||||
"Yes, migrating from an <strong>on-premise data center</strong> and <strong>another cloud provider</strong>",
|
||||
),
|
||||
("none", "Not planning to migrate any applications"),
|
||||
("not_sure", "Not Sure"),
|
||||
("on_premise", translate("forms.task_order.app_migration.on_premise")),
|
||||
("cloud", translate("forms.task_order.app_migration.cloud")),
|
||||
("both", translate("forms.task_order.app_migration.both")),
|
||||
("none", translate("forms.task_order.app_migration.none")),
|
||||
("not_sure", translate("forms.task_order.app_migration.not_sure")),
|
||||
]
|
||||
|
||||
APPLICATION_COMPLEXITY = [
|
||||
("storage", "Storage "),
|
||||
("data_analytics", "Data Analytics "),
|
||||
("conus", "CONUS Access "),
|
||||
("oconus", "OCONUS Access "),
|
||||
("tactical_edge", "Tactical Edge Access "),
|
||||
("not_sure", "Not Sure "),
|
||||
("other", "Other"),
|
||||
("storage", translate("forms.task_order.complexity.storage")),
|
||||
("data_analytics", translate("forms.task_order.complexity.data_analytics")),
|
||||
("conus", translate("forms.task_order.complexity.conus")),
|
||||
("oconus", translate("forms.task_order.complexity.oconus")),
|
||||
("tactical_edge", translate("forms.task_order.complexity.tactical_edge")),
|
||||
("not_sure", translate("forms.task_order.complexity.not_sure")),
|
||||
("other", translate("forms.task_order.complexity.other")),
|
||||
]
|
||||
|
||||
DEV_TEAM = [
|
||||
("government_civilians", "Government Civilians"),
|
||||
("military", "Military "),
|
||||
("contractor", "Contractor "),
|
||||
("other", "Other (E.g. University or other partner)"),
|
||||
(
|
||||
"government_civilians",
|
||||
translate("forms.task_order.dev_team.government_civilians"),
|
||||
),
|
||||
("military", translate("forms.task_order.dev_team.military")),
|
||||
("contractor", translate("forms.task_order.dev_team.contractor")),
|
||||
("other", translate("forms.task_order.dev_team.other")),
|
||||
]
|
||||
|
||||
TEAM_EXPERIENCE = [
|
||||
("none", "No previous experience"),
|
||||
("planned", "Researched or planned a cloud build or migration"),
|
||||
("built_1", "Built or Migrated 1-2 applications"),
|
||||
("built_3", "Built or Migrated 3-5 applications"),
|
||||
(
|
||||
"built_many",
|
||||
"Built or migrated many applications, or consulted on several such applications",
|
||||
),
|
||||
("none", translate("forms.task_order.team_experience.none")),
|
||||
("planned", translate("forms.task_order.team_experience.planned")),
|
||||
("built_1", translate("forms.task_order.team_experience.built_1")),
|
||||
("built_3", translate("forms.task_order.team_experience.built_3")),
|
||||
("built_many", translate("forms.task_order.team_experience.built_many")),
|
||||
]
|
||||
|
||||
PERIOD_OF_PERFORMANCE_LENGTH = [
|
||||
("1", "1 Month"),
|
||||
("2", "2 Months"),
|
||||
("3", "3 Months"),
|
||||
("4", "4 Months"),
|
||||
("5", "5 Months"),
|
||||
("6", "6 Months"),
|
||||
("7", "7 Months"),
|
||||
("8", "8 Months"),
|
||||
("9", "9 Months"),
|
||||
("10", "10 Months"),
|
||||
("11", "11 Months"),
|
||||
("12", "1 Year"),
|
||||
("13", "1 Year, 1 Month"),
|
||||
("14", "1 Year, 2 Months"),
|
||||
("15", "1 Year, 3 Months"),
|
||||
("16", "1 Year, 4 Months"),
|
||||
("17", "1 Year, 5 Months"),
|
||||
("18", "1 Year, 6 Months"),
|
||||
("19", "1 Year, 7 Months"),
|
||||
("20", "1 Year, 8 Months"),
|
||||
("21", "1 Year, 9 Months"),
|
||||
("22", "1 Year, 10 Months"),
|
||||
("23", "1 Year, 11 Months"),
|
||||
("24", "2 Years"),
|
||||
(str(x + 1), translate_duration(x + 1)) for x in range(24)
|
||||
]
|
||||
|
@ -39,8 +39,8 @@ class AppInfoForm(CacheableForm):
|
||||
translate("forms.task_order.defense_component_label"), choices=SERVICE_BRANCHES
|
||||
)
|
||||
app_migration = RadioField(
|
||||
translate("forms.task_order.app_migration_label"),
|
||||
description=translate("forms.task_order.app_migration_description"),
|
||||
translate("forms.task_order.app_migration.label"),
|
||||
description=translate("forms.task_order.app_migration.description"),
|
||||
choices=APP_MIGRATION,
|
||||
default="",
|
||||
)
|
||||
@ -50,8 +50,8 @@ class AppInfoForm(CacheableForm):
|
||||
choices=[("yes", "Yes"), ("no", "No"), ("not_sure", "Not Sure")],
|
||||
)
|
||||
complexity = SelectMultipleField(
|
||||
translate("forms.task_order.complexity_label"),
|
||||
description=translate("forms.task_order.complexity_description"),
|
||||
translate("forms.task_order.complexity.label"),
|
||||
description=translate("forms.task_order.complexity.description"),
|
||||
choices=APPLICATION_COMPLEXITY,
|
||||
default="",
|
||||
widget=ListWidget(prefix_label=False),
|
||||
@ -59,8 +59,8 @@ class AppInfoForm(CacheableForm):
|
||||
)
|
||||
complexity_other = StringField(translate("forms.task_order.complexity_other_label"))
|
||||
dev_team = SelectMultipleField(
|
||||
translate("forms.task_order.dev_team_label"),
|
||||
description=translate("forms.task_order.dev_team_description"),
|
||||
translate("forms.task_order.dev_team.label"),
|
||||
description=translate("forms.task_order.dev_team.description"),
|
||||
choices=DEV_TEAM,
|
||||
default="",
|
||||
widget=ListWidget(prefix_label=False),
|
||||
@ -68,8 +68,8 @@ class AppInfoForm(CacheableForm):
|
||||
)
|
||||
dev_team_other = StringField(translate("forms.task_order.dev_team_other_label"))
|
||||
team_experience = RadioField(
|
||||
translate("forms.task_order.team_experience_label"),
|
||||
description=translate("forms.task_order.team_experience_description"),
|
||||
translate("forms.task_order.team_experience.label"),
|
||||
description=translate("forms.task_order.team_experience.description"),
|
||||
choices=TEAM_EXPERIENCE,
|
||||
default="",
|
||||
)
|
||||
@ -77,7 +77,7 @@ class AppInfoForm(CacheableForm):
|
||||
|
||||
class FundingForm(CacheableForm):
|
||||
performance_length = SelectField(
|
||||
translate("forms.task_order.performance_length_label"),
|
||||
translate("forms.task_order.performance_length.label"),
|
||||
choices=PERIOD_OF_PERFORMANCE_LENGTH,
|
||||
)
|
||||
start_date = DateField(
|
||||
|
@ -1,6 +1,8 @@
|
||||
import yaml
|
||||
import os
|
||||
from functools import lru_cache
|
||||
import math
|
||||
from gettext import ngettext
|
||||
from flask import current_app as app
|
||||
from atst.utils import getattr_path
|
||||
|
||||
@ -41,3 +43,14 @@ def translate(key, variables=None):
|
||||
raise LocalizationInvalidKeyError(key, variables)
|
||||
|
||||
return value.format(**variables).replace("\n", "")
|
||||
|
||||
|
||||
def translate_duration(duration_in_months):
|
||||
duration = []
|
||||
years = math.floor(duration_in_months / 12)
|
||||
months = duration_in_months % 12
|
||||
if years > 0:
|
||||
duration.append("{} {}".format(years, ngettext("year", "years", years)))
|
||||
if months > 0:
|
||||
duration.append("{} {}".format(months, ngettext("month", "months", months)))
|
||||
return (", ").join(duration)
|
||||
|
@ -38,6 +38,7 @@
|
||||
@import 'components/budget_chart';
|
||||
@import 'components/audit_log';
|
||||
@import 'components/usa_banner';
|
||||
@import 'components/checklist';
|
||||
|
||||
@import 'sections/login';
|
||||
@import 'sections/home';
|
||||
|
9
styles/components/_checklist.scss
Normal file
9
styles/components/_checklist.scss
Normal file
@ -0,0 +1,9 @@
|
||||
.checklist {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
margin-top: 5px;
|
||||
|
||||
li {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
@ -68,4 +68,8 @@
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.icon-link--left {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,19 @@
|
||||
@include icon-size(24);
|
||||
}
|
||||
|
||||
&.icon--remove {
|
||||
&.icon--remove, &.icon--red {
|
||||
@include icon-color($color-red);
|
||||
}
|
||||
|
||||
&.icon--green {
|
||||
@include icon-color($color-green);
|
||||
}
|
||||
|
||||
&.icon--gray {
|
||||
@include icon-color($color-gray);
|
||||
}
|
||||
|
||||
&.icon--medium {
|
||||
@include icon-size(12);
|
||||
}
|
||||
}
|
||||
|
@ -179,3 +179,40 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-order-form {
|
||||
.task-order-form__heading {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.inactive {
|
||||
color: $color-gray-light;
|
||||
}
|
||||
|
||||
&.subheading {
|
||||
color: $color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
.funding-summary__table {
|
||||
tr td {
|
||||
border-bottom: 0;
|
||||
padding: 0.5rem 1.5rem;
|
||||
|
||||
.funding-summary__td {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-order-invite-message {
|
||||
&.not-sent {
|
||||
color: $color-red;
|
||||
font-weight: $font-bold;
|
||||
}
|
||||
|
||||
&.sent {
|
||||
color: $color-green;
|
||||
font-weight: $font-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,10 @@
|
||||
<li>
|
||||
{% if choice[0] != 'other' %}
|
||||
<input type='checkbox' name='{{ field.name }}' id='{{ field.name }}-{{ loop.index0 }}' value='{{ choice[0] }}' v-model="selections"/>
|
||||
<label for='{{ field.name }}-{{ loop.index0 }}'>{{ choice[1] }}</label>
|
||||
<label for='{{ field.name }}-{{ loop.index0 }}'>{{ choice[1] | safe }}</label>
|
||||
{% else %}
|
||||
<input @click="otherToggle" type='checkbox' name='{{ field.name }}' id='{{ field.name }}-{{ loop.index0 }}' value='other' v-model="selections"/>
|
||||
<label for='{{ field.name }}-{{ loop.index0 }}'>{{ choice[1] }}</label>
|
||||
<label for='{{ field.name }}-{{ loop.index0 }}'>{{ choice[1] | safe }}</label>
|
||||
|
||||
<div v-show="otherChecked">
|
||||
<input type='text' name='{{ other_input_field.name}}' id='{{ field.name }}-other' v-model:value="otherText" aria-expanded='false' />
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="col">
|
||||
<div class="col task-order-form">
|
||||
|
||||
{% include 'task_orders/new/menu.html' %}
|
||||
|
||||
@ -19,8 +19,10 @@
|
||||
<div class="panel">
|
||||
|
||||
<div class="panel__heading">
|
||||
<div class="subtitle h2">Task Order Builder</div>
|
||||
<h1>{% block heading %}{% endblock %}</h1>
|
||||
<h1 class="task-order-form__heading subheading">
|
||||
<div class="h2">Task Order Builder</div>
|
||||
{% block heading %}{% endblock %}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="panel__content">
|
||||
|
@ -12,7 +12,7 @@
|
||||
{% block form %}
|
||||
|
||||
<!-- App Info Section -->
|
||||
<h3>{{ "task_orders.new.app_info.basic_info_title"| translate }}</h3>
|
||||
<h3 class="task-order-form__heading subheading">{{ "task_orders.new.app_info.basic_info_title"| translate }}</h3>
|
||||
{{ TextInput(form.portfolio_name, placeholder="The name of your office or organization") }}
|
||||
{{ TextInput(form.scope, paragraph=True) }}
|
||||
<p><i>{{ "task_orders.new.app_info.sample_scope" | translate | safe }}</i></p>
|
||||
@ -20,20 +20,20 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>{{ "task_orders.new.app_info.project_title" | translate }}</h3>
|
||||
<h3 id="reporting" class="subheading">{{ "task_orders.new.app_info.project_title" | translate }}</h3>
|
||||
{{ OptionsInput(form.app_migration) }}
|
||||
{{ OptionsInput(form.native_apps) }}
|
||||
{{ MultiCheckboxInput(form.complexity, form.complexity_other) }}
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>{{ "task_orders.new.app_info.team_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.app_info.team_title" | translate }}</h3>
|
||||
{{ MultiCheckboxInput(form.dev_team, form.dev_team_other) }}
|
||||
{{ OptionsInput(form.team_experience) }}
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>{{ "task_orders.new.app_info.market_research_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.app_info.market_research_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.app_info.market_research_paragraph" | translate | safe }}</p>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -15,14 +15,14 @@
|
||||
<funding inline-template v-bind:initial-data='{{ form.data|tojson }}'>
|
||||
<div>
|
||||
<!-- Get Funding Section -->
|
||||
<h3>{{ "task_orders.new.funding.performance_period_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.funding.performance_period_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.funding.performance_period_description" | translate }}</p>
|
||||
<p>{{ "task_orders.new.funding.performance_period_paragraph" | translate }}</p>
|
||||
{{ OptionsInput(form.performance_length) }}
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>{{ "task_orders.new.funding.estimate_usage_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.funding.estimate_usage_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.funding.estimate_usage_description" | translate }}</p>
|
||||
<p><a class="icon-link" href="{{ url_for('atst.jedi_csp_calculator') }}">
|
||||
{{ Icon("link")}} Cloud Service Provider's estimate calculator
|
||||
@ -36,15 +36,15 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>{{ "task_orders.new.funding.cloud_calculations_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.funding.cloud_calculations_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.funding.cloud_calculations_paragraph" | translate }}</p>
|
||||
|
||||
<h4>{{ "task_orders.new.funding.cloud_offerings_title" | translate }}</h4>
|
||||
<h4 class="task-order-form__heading">{{ "task_orders.new.funding.cloud_offerings_title" | translate }}</h4>
|
||||
<p>{{ "task_orders.new.funding.cloud_offerings_paragraph" | translate }}</p>
|
||||
{{ TextInput(form.clin_01, validation='dollars', placeholder="$0.00") }}
|
||||
{{ TextInput(form.clin_02, validation='dollars', disabled=(not config.CLASSIFIED)) }}
|
||||
|
||||
<h4>{{ "task_orders.new.funding.support_assistance_title" | translate }}</h4>
|
||||
<h4 class="task-order-form__heading">{{ "task_orders.new.funding.support_assistance_title" | translate }}</h4>
|
||||
<p>{{ "task_orders.new.funding.support_assistance_paragraph" | translate }}</p>
|
||||
{{ TextInput(form.clin_03, validation='dollars', tooltip='The cloud support and assistance packages cannot be used as a primary development resource.', placeholder="$0.00") }}
|
||||
{{ TextInput(form.clin_04, validation='dollars', tooltip='The cloud support and assistance packages cannot be used as a primary development resource.', disabled=(not config.CLASSIFIED)) }}
|
||||
@ -56,7 +56,7 @@
|
||||
{% block next %}
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<p>{{ "task_orders.new.funding.total" | translate }}<br><span id="to-target"></span></p>
|
||||
<p><strong><span class="task-order-form__heading subheading">{{ "task_orders.new.funding.total" | translate }}</span><br><span id="to-target"></span></strong></p>
|
||||
</div>
|
||||
<div class="col col--grow">
|
||||
{{ super() }}
|
||||
|
@ -11,7 +11,7 @@
|
||||
{% block form %}
|
||||
|
||||
<!-- Oversight Section -->
|
||||
<h3>{{ "task_orders.new.oversight.ko_info_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.ko_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.ko_info_paragraph" | translate }}</p>
|
||||
{{ UserInfo(form.ko_first_name, form.ko_last_name, form.ko_email, form.ko_phone_number) }}
|
||||
{{ CheckboxInput(form.ko_invite) }}
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>{{ "task_orders.new.oversight.cor_info_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.cor_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.cor_info_paragraph" | translate }}</p>
|
||||
<div class='usa-input'>
|
||||
<fieldset class="usa-input__choices">
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
<hr />
|
||||
|
||||
<h3>{{ "task_orders.new.oversight.so_info_title" | translate }}</h3>
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.so_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.so_info_paragraph" | translate }}</p>
|
||||
{{ UserInfo(form.so_first_name, form.so_last_name, form.so_email, form.so_phone_number) }}
|
||||
{{ CheckboxInput(form.so_invite) }}
|
||||
|
@ -5,145 +5,219 @@
|
||||
{% from "components/icon.html" import Icon %}
|
||||
|
||||
{% block heading %}
|
||||
Review & Download
|
||||
{{ "task_orders.new.review.section_title"| translate }}
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
|
||||
{% macro TOEditLink(screen=1) %}
|
||||
{% macro TOEditLink(screen=1, anchor=None) %}
|
||||
{% if task_order %}
|
||||
{{ EditLink(url_for("task_orders.new", screen=screen, task_order_id=task_order.id)) }}
|
||||
{{ EditLink(url_for("task_orders.new", screen=screen, task_order_id=task_order.id, _anchor=anchor)) }}
|
||||
{% else %}
|
||||
{{ EditLink(url_for("task_orders.new", screen=screen)) }}
|
||||
{{ EditLink(url_for("task_orders.new", screen=screen, _anchor=anchor)) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
<section>
|
||||
<h3>Scope (Statement of Work) {{ TOEditLink() }}</h3>
|
||||
<p>
|
||||
{{ task_order.scope or RequiredLabel() }}
|
||||
</p>
|
||||
{% if task_order.defense_component %}
|
||||
{% set defense_component_description = task_order.defense_component | normalizeOrder %}
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
{% if task_order.app_migration %}
|
||||
{% set app_migration_description = "forms.task_order.app_migration.{}".format(task_order.app_migration) | translate | removeHtml %}
|
||||
{% endif %}
|
||||
|
||||
{% if task_order.native_apps %}
|
||||
{% set native_apps_description = "task_orders.new.review.{}_native".format(task_order.native_apps) | translate %}
|
||||
{% endif %}
|
||||
|
||||
{% if task_order.team_experience %}
|
||||
{% set team_experience_description = "forms.task_order.team_experience.{}".format(task_order.team_experience) | translate %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
<h3 class="subheading">{{ "task_orders.new.review.app_info"| translate }} {{ TOEditLink(screen=1) }}</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<h3>Period of Performance length {{ TOEditLink(screen=2) }}</h3>
|
||||
{{ task_order.performance_length or RequiredLabel() }}
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.portfolio"| translate }}</h4>
|
||||
<p>{{ task_order.portfolio_name or RequiredLabel() }}</p>
|
||||
</div>
|
||||
|
||||
<div class="col col--grow">
|
||||
<h3>Total funding requested {{ TOEditLink(screen=2) }}</h3>
|
||||
{{ task_order.budget }}
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.dod"| translate }}</h4>
|
||||
<p>{{ defense_component_description or RequiredLabel() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.scope"| translate }}</h4>
|
||||
<p>
|
||||
{{ task_order.scope or RequiredLabel() }}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<h2>Generated Documents</h2>
|
||||
<h3 class="subheading">{{ "task_orders.new.review.reporting"| translate }} {{ TOEditLink(screen=1, anchor="reporting") }}</h3>
|
||||
|
||||
<ul class="usa-unstyled-list">
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.migration"| translate }}</h4>
|
||||
<p>{{ app_migration_description or RequiredLabel() }}</p>
|
||||
</div>
|
||||
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.native_apps"| translate }}</h4>
|
||||
<p>{{ native_apps_description or RequiredLabel() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.complexity"| translate }}</h4>
|
||||
{% if task_order.complexity %}
|
||||
<ul class="checklist">
|
||||
{% for item in task_order.complexity %}
|
||||
<li>
|
||||
<a href="#" download>
|
||||
{{ Icon('download') }}
|
||||
Cover Sheet
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#" download>
|
||||
{{ Icon('download') }}
|
||||
Market Research
|
||||
</a>
|
||||
</li
|
||||
>
|
||||
|
||||
{% if task_order %}
|
||||
<li>
|
||||
<a href="{{ url_for('task_orders.download_summary', task_order_id=task_order.id) }}" download>
|
||||
{{ Icon('download') }}
|
||||
Task Order Draft
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<a href="#" download>
|
||||
{{ Icon('download') }}
|
||||
DD 254
|
||||
</a>
|
||||
{{ Icon('ok', classes='icon--gray icon--medium') }}{{ "forms.task_order.complexity.{}".format(item) | translate }}{% if item == 'other' %}: {{ task_order.complexity_other }}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% else %}
|
||||
<p>{{ RequiredLabel() }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.team"| translate }}</h4>
|
||||
{% if task_order.dev_team %}
|
||||
<ul class="checklist">
|
||||
{% for item in task_order.dev_team %}
|
||||
<li>
|
||||
{% if item == 'other' %}
|
||||
{{ Icon('ok', classes='icon--gray icon--medium') }}Other: {{ task_order.dev_team_other }}
|
||||
{% else %}
|
||||
{{ Icon('ok', classes='icon--gray icon--medium') }}{{ "forms.task_order.dev_team.{}".format(item) | translate }}
|
||||
{% endif %}
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>{{ RequiredLabel() }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.experience"| translate }}</h4>
|
||||
<p>{{ team_experience_description or RequiredLabel() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<h2>Invite Signatories/Collaborators</h2>
|
||||
<h3 class="subheading">{{ "task_orders.new.review.funding"| translate }} {{ TOEditLink(screen=2) }}</h3>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<div class="usa-input">
|
||||
<fieldset class="usa-input__choices">
|
||||
<legend>Financial Oversight</legend>
|
||||
<p>
|
||||
{% if task_order.ko_first_name %}
|
||||
{{ task_order.ko_first_name }}
|
||||
{{ task_order.ko_last_name }}
|
||||
{% else %}
|
||||
{{ RequiredLabel() }}
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.performance_period"| translate }}</h4>
|
||||
{{ task_order.performance_length | translateDuration or RequiredLabel() }}
|
||||
<p><a href="#" class='icon-link icon-link--left' download>{{ Icon('download') }} {{ "task_orders.new.review.usage_est_link"| translate }}</a></p>
|
||||
</div>
|
||||
|
||||
<div class="col col--grow">
|
||||
<table class="funding-summary__table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><h4>{{ "task_orders.new.review.to_value"| translate }}</h4></td>
|
||||
<td class="table-cell--align-right">{{ '${:,.2f}'.format(task_order.budget) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class='task-order-form__heading funding-summary__td'>{{ "task_orders.new.review.clin_1"| translate }}</h4></td>
|
||||
<td class="table-cell--align-right">{{ '${:,.2f}'.format(task_order.clin_01) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class="task-order-form__heading funding-summary__td{% if not config.CLASSIFIED %} inactive{% endif %}">
|
||||
{{ "task_orders.new.review.clin_2"| translate }}
|
||||
{% if not config.CLASSIFIED %}
|
||||
<div>{{ "task_orders.new.review.classified_inactive"| translate }}</div>
|
||||
{% endif %}
|
||||
(Contracting Officer)
|
||||
</p>
|
||||
<p>
|
||||
{% if task_order.ko_first_name %}
|
||||
{{ task_order.cor_first_name }}
|
||||
{{ task_order.cor_last_name }}
|
||||
{% else %}
|
||||
{{ RequiredLabel() }}
|
||||
</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if config.CLASSIFIED %}
|
||||
{{ '${:,.2f}'.format(task_order.clin_02) }}
|
||||
{% endif %}
|
||||
(Contracting Officer Representative)
|
||||
</p>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-col">
|
||||
<div class="usa-input">
|
||||
<fieldset class="usa-input__choices">
|
||||
<legend>Invite?</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-col">
|
||||
<div class="usa-input">
|
||||
<fieldset class="usa-input__choices">
|
||||
<legend>Security Officer</legend>
|
||||
<p>
|
||||
{% if task_order.so_first_name %}
|
||||
{{ task_order.so_first_name }}
|
||||
{{ task_order.so_last_name }}
|
||||
{% else %}
|
||||
{{ RequiredLabel() }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class='task-order-form__heading funding-summary__td'>{{ "task_orders.new.review.clin_3"| translate }}</h4></td>
|
||||
<td class="table-cell--align-right">{{ '${:,.2f}'.format(task_order.clin_03) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h4 class="task-order-form__heading funding-summary__td{% if not config.CLASSIFIED %} inactive{% endif %}">
|
||||
{{ "task_orders.new.review.clin_4"| translate }}
|
||||
{% if not config.CLASSIFIED %}
|
||||
<div>{{ "task_orders.new.review.classified_inactive"| translate }}</div>
|
||||
{% endif %}
|
||||
(Security Officer)
|
||||
</p>
|
||||
</fieldset>
|
||||
</h4></td>
|
||||
<td class="table-cell--align-right">
|
||||
{% if config.CLASSIFIED %}
|
||||
{{ '${:,.2f}'.format(task_order.clin_04) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3 class="subheading">{{ "task_orders.new.review.oversight"| translate }} {{ TOEditLink(screen=3) }}</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.ko"| translate }}</h4>
|
||||
{{ task_order.ko_first_name }} {{ task_order.ko_last_name }}<br>
|
||||
{{ task_order.ko_email }}<br>
|
||||
{{ task_order.ko_phone_number | usPhone }}<br>
|
||||
{{ "task_orders.new.review.dod_id"| translate }} {{ task_order.ko_dod_id}}<br>
|
||||
{% if task_order.ko_invite %}
|
||||
{{ Icon('ok', classes='icon--green') }} <span class="task-order-invite-message sent">{{ "task_orders.new.review.invited"| translate }}</<span>
|
||||
{% else %}
|
||||
{{ Icon('alert', classes='icon--red') }} <span class="task-order-invite-message not-sent">{{ "task_orders.new.review.not_invited"| translate }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-col">
|
||||
<div class="usa-input">
|
||||
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.cor"| translate }}</h4>
|
||||
{{ task_order.cor_first_name }} {{ task_order.cor_last_name }}<br>
|
||||
{{ task_order.cor_email }}<br>
|
||||
{{ task_order.cor_phone_number | usPhone }}<br>
|
||||
{{ "task_orders.new.review.dod_id"| translate }} {{ task_order.cor_dod_id}}<br>
|
||||
{% if task_order.cor_invite %}
|
||||
{{ Icon('ok', classes='icon--green') }} <span class="task-order-invite-message sent">{{ "task_orders.new.review.invited"| translate }}</<span>
|
||||
{% else %}
|
||||
{{ Icon('alert', classes='icon--red') }} <span class="task-order-invite-message not-sent">{{ "task_orders.new.review.not_invited"| translate }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col col--grow">
|
||||
<h4 class='task-order-form__heading'>{{ "task_orders.new.review.so"| translate }}</h4>
|
||||
{{ task_order.so_first_name }} {{ task_order.so_last_name }}<br>
|
||||
{{ task_order.so_email }}<br>
|
||||
{{ task_order.so_phone_number | usPhone }}<br>
|
||||
{{ "task_orders.new.review.dod_id"| translate }} {{ task_order.so_dod_id}}<br>
|
||||
{% if task_order.so_invite %}
|
||||
{{ Icon('ok', classes='icon--green') }} <span class="task-order-invite-message sent">{{ "task_orders.new.review.invited"| translate }}</<span>
|
||||
{% else %}
|
||||
{{ Icon('alert', classes='icon--red') }} <span class="task-order-invite-message not-sent">{{ "task_orders.new.review.not_invited"| translate }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block next %}
|
||||
<div class='action-group'>
|
||||
<input type='submit' class='usa-button usa-button-primary' value='Send Invitations' />
|
||||
<input type='submit' class='usa-button usa-button-primary' value='Done' />
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -388,7 +388,7 @@ class TaskOrderFactory(Base):
|
||||
|
||||
defense_component = factory.LazyFunction(random_service_branch)
|
||||
app_migration = random_choice(data.APP_MIGRATION)
|
||||
native_apps = random.choices(["yes", "no", "not_sure"])
|
||||
native_apps = random.choice(["yes", "no", "not_sure"])
|
||||
complexity = [random_choice(data.APPLICATION_COMPLEXITY)]
|
||||
dev_team = [random_choice(data.DEV_TEAM)]
|
||||
team_experience = random_choice(data.TEAM_EXPERIENCE)
|
||||
|
@ -169,19 +169,45 @@ forms:
|
||||
scope_label: Cloud Project Scope
|
||||
scope_description: Your team's plan for using the cloud, such as migrating an existing application or creating a prototype.
|
||||
defense_component_label: Department of Defense Component
|
||||
app_migration_label: App Migration
|
||||
app_migration_description: Do you plan to migrate existing application(s) to the cloud?
|
||||
app_migration:
|
||||
label: App Migration
|
||||
description: Do you plan to migrate existing application(s) to the cloud?
|
||||
on_premise: Yes, migrating from an <strong>on-premise data center</strong>
|
||||
cloud: Yes, migrating from <strong>another cloud provider</strong>
|
||||
both: Yes, migrating from an <strong>on-premise data center</strong> and <strong>another cloud provider</strong>
|
||||
none: Not planning to migrate any applications
|
||||
not_sure: "Not Sure"
|
||||
native_apps_label: Native Apps
|
||||
native_apps_description: Do you plan to develop application(s) natively in the cloud?
|
||||
complexity_label: Project Complexity
|
||||
complexity_description: Which of these describes how complex your team's use of the cloud will be? Select all that apply.
|
||||
complexity:
|
||||
label: Project Complexity
|
||||
description: Which of these describes how complex your team's use of the cloud will be? Select all that apply.
|
||||
storage: Storage
|
||||
data_analytics: Data Analytics
|
||||
conus: CONUS Acess
|
||||
oconus: OCONUS Access
|
||||
tactical_edge: Tactical Edge Access
|
||||
not_sure: Not Sure
|
||||
other: Other
|
||||
complexity_other_label: Project Complexity Other
|
||||
dev_team_label: Development Team
|
||||
dev_team_description: Which people or teams will be completing the development work for your cloud applications? Select all that apply.
|
||||
dev_team:
|
||||
label: Development Team
|
||||
description: Which people or teams will be completing the development work for your cloud applications? Select all that apply.
|
||||
government_civilians: Government Civilians
|
||||
military: Military
|
||||
contractor: Contractor
|
||||
other: "Other <em>(E.g. University or other partner)</em>"
|
||||
dev_team_other_label: Development Team Other
|
||||
team_experience_label: Team Experience
|
||||
team_experience_description: How much experience does your team have with development in the cloud?
|
||||
performance_length_label: Period of Performance length
|
||||
team_experience:
|
||||
label: Team Experience
|
||||
description: How much experience does your team have with development in the cloud?
|
||||
none: No previous experience
|
||||
planned: Researched or planned a cloud build or migration
|
||||
built_1: Built or Migrated 1-2 applications
|
||||
built_3: Built or Migrated 3-5 applications
|
||||
built_many: Built or migrated many applications, or consulted on several such projects
|
||||
performance_length:
|
||||
label: Period of Performance length
|
||||
start_date_label: Start Date
|
||||
end_date_label: End Date
|
||||
pdf_label: Upload a copy of your CSP Cost Estimate Research
|
||||
@ -375,11 +401,42 @@ task_orders:
|
||||
ko_info_title: Contracting Officer (KO) Information
|
||||
ko_info_paragraph: Your KO will need to approve funding for this Task Order by logging into the JEDI Cloud Portal, submitting the Task Order documents within their official system of record, and electronically signing. You might want to work with your program Financial Manager to get your TO documents moving in the right dirction.
|
||||
skip_ko_label: "Skip for now (We'll remind you to enter one later)"
|
||||
cor_info_title: Contractive Officer Representative (COR) Information
|
||||
cor_info_title: Contracting Officer Representative (COR) Information
|
||||
cor_info_paragraph: Your COR may assist in submitting the Task Order documents within thier official system of record. They may also be invited to log in an manage the Task Order entry within the JEDI Cloud portal.
|
||||
am_cor_label: I am the Contracting Officer Representative (COR) for this Task Order
|
||||
so_info_title: Security Officer Information
|
||||
so_info_paragraph: our Security Officer will need to answer some security configuration questions in order to generate a DD-254 document, then electronically sign.
|
||||
so_info_paragraph: Your Security Officer will need to answer some security configuration questions in order to generate a DD-254 document, then electronically sign.
|
||||
review:
|
||||
section_title: Review Your Task Order Info
|
||||
app_info: What are you building
|
||||
portfolio: Portfolio
|
||||
dod: DoD Component
|
||||
scope: Scope (Statement of Work)
|
||||
reporting: Reporting
|
||||
migration: App Migration
|
||||
native_apps: Native Apps
|
||||
yes_native: Yes, planning to develop natively in the cloud
|
||||
no_native: No, not planning to develop natively in the cloud
|
||||
not_sure_native: Not sure, unsure if planning to develop natively in the cloud
|
||||
complexity: Project Complexity
|
||||
team: Development Team
|
||||
experience: Team Experience
|
||||
funding: Funding
|
||||
performance_period: Period of Performance length
|
||||
usage_est_link: View Usage Estimate
|
||||
to_value: Task Order Value
|
||||
clin_1: 'CLIN #1: Unclassified Cloud'
|
||||
clin_2: 'CLIN #2: Classified Cloud'
|
||||
clin_3: 'CLIN #3: Unclassified Cloud'
|
||||
clin_4: 'CLIN $4: Classified Cloud'
|
||||
classified_inactive: (Available Soon)
|
||||
oversight: Oversight
|
||||
ko: Contracting Officer (KO)
|
||||
cor: Contracting Officer Representative (COR)
|
||||
so: IA Security Officer
|
||||
dod_id: 'DoD ID:'
|
||||
invited: Invited
|
||||
not_invited: Not Yet Invited
|
||||
testing:
|
||||
example_string: Hello World
|
||||
example_with_variables: 'Hello, {name}!'
|
||||
|
Loading…
x
Reference in New Issue
Block a user