Refactor New Portfolio page according to designs.

New designs call for a streamlined New Portfolio page, with far
fewer input options. This commit refactors that page according to those
designs.

Some of the route functions in this commit refer to a "step 1" of creating
a new Portfolio. Though there is no "step 2" right now, the designs call
for a multistep flow for Portfolio creation process, so this commit sets
the stage for that.
This commit is contained in:
graham-dds
2019-12-11 11:30:27 -05:00
parent f9a3d2628e
commit a097a0ce61
13 changed files with 157 additions and 306 deletions

View File

@@ -3,112 +3,14 @@ from atst.utils.localization import translate
SERVICE_BRANCHES = [
("", "- Select -"),
("Air Force, Department of the", "Air Force, Department of the"),
("Army and Air Force Exchange Service", "Army and Air Force Exchange Service"),
("Army, Department of the", "Army, Department of the"),
("air_force", translate("forms.portfolio.defense_component.choices.air_force")),
("army", translate("forms.portfolio.defense_component.choices.army")),
(
"Defense Advanced Research Applications Agency",
"Defense Advanced Research Applications Agency",
"marine_corps",
translate("forms.portfolio.defense_component.choices.marine_corps"),
),
("Defense Commissary Agency", "Defense Commissary Agency"),
("Defense Contract Audit Agency", "Defense Contract Audit Agency"),
("Defense Contract Management Agency", "Defense Contract Management Agency"),
("Defense Finance & Accounting Service", "Defense Finance & Accounting Service"),
("Defense Health Agency", "Defense Health Agency"),
("Defense Information System Agency", "Defense Information System Agency"),
("Defense Intelligence Agency", "Defense Intelligence Agency"),
("Defense Legal Services Agency", "Defense Legal Services Agency"),
("Defense Logistics Agency", "Defense Logistics Agency"),
("Defense Media Activity", "Defense Media Activity"),
("Defense Micro Electronics Activity", "Defense Micro Electronics Activity"),
("Defense POW-MIA Accounting Agency", "Defense POW-MIA Accounting Agency"),
("Defense Security Cooperation Agency", "Defense Security Cooperation Agency"),
("Defense Security Service", "Defense Security Service"),
("Defense Technical Information Center", "Defense Technical Information Center"),
(
"Defense Technology Security Administration",
"Defense Technology Security Administration",
),
("Defense Threat Reduction Agency", "Defense Threat Reduction Agency"),
("DoD Education Activity", "DoD Education Activity"),
("DoD Human Recourses Activity", "DoD Human Recourses Activity"),
("DoD Inspector General", "DoD Inspector General"),
("DoD Test Resource Management Center", "DoD Test Resource Management Center"),
(
"Headquarters Defense Human Resource Activity ",
"Headquarters Defense Human Resource Activity ",
),
("Joint Staff", "Joint Staff"),
("Missile Defense Agency", "Missile Defense Agency"),
("National Defense University", "National Defense University"),
(
"National Geospatial Intelligence Agency (NGA)",
"National Geospatial Intelligence Agency (NGA)",
),
(
"National Oceanic and Atmospheric Administration (NOAA)",
"National Oceanic and Atmospheric Administration (NOAA)",
),
("National Reconnaissance Office", "National Reconnaissance Office"),
("National Reconnaissance Office (NRO)", "National Reconnaissance Office (NRO)"),
("National Security Agency (NSA)", "National Security Agency (NSA)"),
(
"National Security Agency-Central Security Service",
"National Security Agency-Central Security Service",
),
("Navy, Department of the", "Navy, Department of the"),
("Office of Economic Adjustment", "Office of Economic Adjustment"),
("Office of the Secretary of Defense", "Office of the Secretary of Defense"),
("Pentagon Force Protection Agency", "Pentagon Force Protection Agency"),
(
"Uniform Services University of the Health Sciences",
"Uniform Services University of the Health Sciences",
),
("US Cyber Command (USCYBERCOM)", "US Cyber Command (USCYBERCOM)"),
(
"US Special Operations Command (USSOCOM)",
"US Special Operations Command (USSOCOM)",
),
("US Strategic Command (USSTRATCOM)", "US Strategic Command (USSTRATCOM)"),
(
"US Transportation Command (USTRANSCOM)",
"US Transportation Command (USTRANSCOM)",
),
("Washington Headquarters Services", "Washington Headquarters Services"),
]
APP_MIGRATION = [
("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", 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 = [
("civilians", translate("forms.task_order.dev_team.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", 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")),
("navy", translate("forms.portfolio.defense_component.choices.navy")),
("other", translate("forms.portfolio.defense_component.choices.other")),
]
ENV_ROLE_NO_ACCESS = "No Access"

View File

@@ -1,33 +1,25 @@
from wtforms.fields import (
RadioField,
SelectField,
SelectMultipleField,
StringField,
TextAreaField,
)
from wtforms.validators import Length, Optional
from wtforms.validators import Length, InputRequired
from wtforms.widgets import ListWidget, CheckboxInput
from .forms import BaseForm, remove_empty_string
from .forms import BaseForm
from atst.utils.localization import translate
from .data import (
APPLICATION_COMPLEXITY,
APP_MIGRATION,
DEV_TEAM,
SERVICE_BRANCHES,
TEAM_EXPERIENCE,
)
from .data import SERVICE_BRANCHES
class PortfolioForm(BaseForm):
name = StringField(
translate("forms.portfolio.name_label"),
translate("forms.portfolio.name.label"),
validators=[
Length(
min=4,
max=100,
message=translate("forms.portfolio.name_length_validation_message"),
message=translate("forms.portfolio.name.length_validation_message"),
)
],
)
@@ -35,78 +27,21 @@ class PortfolioForm(BaseForm):
class PortfolioCreationForm(BaseForm):
name = StringField(
translate("forms.portfolio.name_label"),
translate("forms.portfolio.name.label"),
validators=[
Length(
min=4,
max=100,
message=translate("forms.portfolio.name_length_validation_message"),
message=translate("forms.portfolio.name.length_validation_message"),
)
],
)
defense_component = SelectField(
translate("forms.task_order.defense_component_label"),
description = TextAreaField(translate("forms.portfolio.description.label"),)
defense_component = SelectMultipleField(
choices=SERVICE_BRANCHES,
default="",
filters=[remove_empty_string],
)
description = TextAreaField(
translate("forms.task_order.scope_label"),
description=translate("forms.task_order.scope_description"),
)
app_migration = RadioField(
translate("forms.task_order.app_migration.label"),
description=translate("forms.task_order.app_migration.description"),
choices=APP_MIGRATION,
default="",
validators=[Optional()],
)
native_apps = RadioField(
translate("forms.task_order.native_apps.label"),
description=translate("forms.task_order.native_apps.description"),
choices=[("yes", "Yes"), ("no", "No"), ("not_sure", "Not Sure")],
default="",
validators=[Optional()],
)
complexity = SelectMultipleField(
translate("forms.task_order.complexity.label"),
description=translate("forms.task_order.complexity.description"),
choices=APPLICATION_COMPLEXITY,
default=None,
widget=ListWidget(prefix_label=False),
option_widget=CheckboxInput(),
)
complexity_other = StringField(
translate("forms.task_order.complexity_other_label"),
default=None,
filters=[remove_empty_string],
)
dev_team = SelectMultipleField(
translate("forms.task_order.dev_team.label"),
description=translate("forms.task_order.dev_team.description"),
choices=DEV_TEAM,
default=None,
widget=ListWidget(prefix_label=False),
option_widget=CheckboxInput(),
)
dev_team_other = StringField(
translate("forms.task_order.dev_team_other_label"),
default=None,
filters=[remove_empty_string],
)
team_experience = RadioField(
translate("forms.task_order.team_experience.label"),
description=translate("forms.task_order.team_experience.description"),
choices=TEAM_EXPERIENCE,
default="",
validators=[Optional()],
validators=[
InputRequired(message="You must select at least one defense component.")
],
)

View File

@@ -1,6 +1,5 @@
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship
from sqlalchemy.types import ARRAY
from itertools import chain
from atst.models.base import Base
@@ -19,19 +18,11 @@ class Portfolio(
id = types.Id()
name = Column(String, nullable=False)
description = Column(String)
defense_component = Column(
String, nullable=False
) # Department of Defense Component
app_migration = Column(String) # App Migration
complexity = Column(ARRAY(String)) # Application Complexity
complexity_other = Column(String)
description = Column(String)
dev_team = Column(ARRAY(String)) # Development Team
dev_team_other = Column(String)
native_apps = Column(String) # Native Apps
team_experience = Column(String) # Team Experience
applications = relationship(
"Application",
back_populates="portfolio",

View File

@@ -12,10 +12,9 @@ from atst.utils.flash import formatted_flash as flash
@portfolios_bp.route("/portfolios/new")
def new_portfolio():
def new_portfolio_step_1():
form = PortfolioCreationForm()
return render_template("portfolios/new.html", form=form)
return render_template("portfolios/new/step_1.html", form=form)
@portfolios_bp.route("/portfolios", methods=["POST"])
@@ -28,7 +27,7 @@ def create_portfolio():
url_for("applications.portfolio_applications", portfolio_id=portfolio.id)
)
else:
return render_template("portfolios/new.html", form=form), 400
return render_template("portfolios/new/step_1.html", form=form), 400
@portfolios_bp.route("/portfolios/<portfolio_id>/reports")