Put app strings into a YAML file for easy editing by product owner

This commit is contained in:
George Drummond 2018-12-13 15:02:52 -05:00
parent 8eecb62034
commit f806425d91
No known key found for this signature in database
GPG Key ID: 296DD6077123BF17
35 changed files with 845 additions and 246 deletions

View File

@ -1,5 +1,6 @@
import re
import datetime
from atst.utils.localization import translate
from flask import current_app as app, render_template
from jinja2.exceptions import TemplateNotFound
@ -108,3 +109,4 @@ 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["translate"] = translate

View File

@ -5,20 +5,31 @@ from wtforms.validators import Email, Optional
from .forms import CacheableForm
from .validators import Name, PhoneNumber
from atst.utils.localization import translate
class CCPOReviewForm(CacheableForm):
comment = TextAreaField(
"Instructions or comments",
description="Provide instructions or notes for additional information that is necessary to approve the request here. The requestor may then re-submit the updated request or initiate contact outside of AT-AT if further discussion is required. <strong>This message will be shared with the person making the JEDI request.</strong>.",
translate("forms.ccpo_review.comment_label"),
description=("forms.ccpo_review.comment_description"),
)
fname_mao = StringField(
translate("forms.ccpo_review.fname_mao_label"), validators=[Optional(), Name()]
)
lname_mao = StringField(
translate("forms.ccpo_review.lname_mao_label"), validators=[Optional(), Name()]
)
fname_mao = StringField("First Name (optional)", validators=[Optional(), Name()])
lname_mao = StringField("Last Name (optional)", validators=[Optional(), Name()])
email_mao = EmailField(
"Mission Owner e-mail (optional)", validators=[Optional(), Email()]
translate("forms.ccpo_review.email_mao_label"), validators=[Optional(), Email()]
)
phone_mao = TelField(
"Mission Owner phone number (optional)", validators=[Optional(), PhoneNumber()]
translate("forms.ccpo_review.phone_mao_label"),
validators=[Optional(), PhoneNumber()],
)
phone_ext_mao = StringField(translate("forms.ccpo_review.phone_ext_mao_label"))
fname_ccpo = StringField(
translate("forms.ccpo_review.fname_ccpo_label"), validators=[Optional(), Name()]
)
lname_ccpo = StringField(
translate("forms.ccpo_review.lname_ccpo_label"), validators=[Optional(), Name()]
)
phone_ext_mao = StringField("Extension (optional)")
fname_ccpo = StringField("First Name (optional)", validators=[Optional(), Name()])
lname_ccpo = StringField("Last Name (optional)", validators=[Optional(), Name()])

View File

@ -2,6 +2,7 @@ from flask_wtf import FlaskForm
from wtforms.validators import Required
from atst.forms.fields import SelectField
from atst.utils.localization import translate
from .data import WORKSPACE_ROLES
@ -11,5 +12,7 @@ class EditMemberForm(FlaskForm):
# that the user is a member of
workspace_role = SelectField(
"Workspace Role", choices=WORKSPACE_ROLES, validators=[Required()]
translate("forms.edit_member.workspace_role_label"),
choices=WORKSPACE_ROLES,
validators=[Required()],
)

View File

@ -8,27 +8,34 @@ from .fields import SelectField
from .forms import CacheableForm
from .data import SERVICE_BRANCHES
from atst.models.user import User
from atst.utils.localization import translate
from .validators import Name, DateRange, PhoneNumber
USER_FIELDS = {
"first_name": StringField("First Name", validators=[Name()]),
"last_name": StringField("Last Name", validators=[Name()]),
"first_name": StringField(
translate("forms.edit_user.first_name_label"), validators=[Name()]
),
"last_name": StringField(
translate("forms.edit_user.last_name_label"), validators=[Name()]
),
"email": EmailField(
"E-mail Address",
description="Enter your preferred contact e-mail address",
translate("forms.edit_user.email_label"),
description=translate("forms.edit_user.email_description"),
validators=[Email()],
),
"phone_number": TelField("Phone Number", validators=[PhoneNumber()]),
"phone_number": TelField(
translate("forms.edit_user.phone_number_label"), validators=[PhoneNumber()]
),
"phone_ext": StringField("Extension"),
"service_branch": SelectField(
"Service Branch or Agency",
description="Which service or organization do you belong to within the DoD?",
translate("forms.edit_user.service_branch_label"),
description=translate("forms.edit_user.service_branch_description"),
choices=SERVICE_BRANCHES,
),
"citizenship": RadioField(
description="What is your citizenship status?",
description=translate("forms.edit_user.citizenship_description"),
choices=[
("United States", "United States"),
("Foreign National", "Foreign National"),
@ -36,8 +43,8 @@ USER_FIELDS = {
],
),
"designation": RadioField(
"Designation of Person",
description="What is your designation within the DoD?",
translate("forms.edit_user.designation_label"),
description=translate("forms.edit_user.designation_description"),
choices=[
("military", "Military"),
("civilian", "Civilian"),
@ -45,8 +52,8 @@ USER_FIELDS = {
],
),
"date_latest_training": DateField(
"Latest Information Assurance (IA) Training Completion Date",
description='To complete the training, you can find it in <a class="icon-link" href="https://iatraining.disa.mil/eta/disa_cac2018/launchPage.htm" target="_blank">Information Assurance Cyber Awareness Challange</a> website.',
translate("forms.edit_user.date_latest_training_label"),
description=translate("forms.edit_user.date_latest_training_description"),
validators=[
DateRange(
lower_bound=pendulum.duration(years=1),

View File

@ -1,6 +1,9 @@
from atst.utils.localization import translate
class FormValidationError(Exception):
message = "Form validation failed."
message = translate("forms.exceptions.message")
def __init__(self, form):
self.form = form

View File

@ -8,6 +8,7 @@ from werkzeug.datastructures import FileStorage
from .fields import NewlineListField, SelectField, NumberStringField
from atst.forms.forms import CacheableForm
from atst.utils.localization import translate
from .data import FUNDING_TYPES
from .validators import DateRange
@ -46,24 +47,26 @@ class TaskOrderForm(CacheableForm):
return valid
number = StringField(
"Task Order Number associated with this request",
description="Include the original Task Order number (including the 000X at the end). Do not include any modification numbers. Note that there may be a lag between approving a task order and when it becomes available in our system.",
translate("forms.financial.number_label"),
description=translate("forms.financial.number_description"),
validators=[InputRequired()],
)
funding_type = SelectField(
description="What is the source of funding?",
description=translate("forms.financial.funding_type_description"),
choices=FUNDING_TYPES,
validators=[InputRequired()],
coerce=coerce_choice,
render_kw={"required": False},
)
funding_type_other = StringField("If other, please specify")
funding_type_other = StringField(
translate("forms.financial.funding_type_other_label")
)
expiration_date = DateField(
"Task Order Expiration Date",
description="Please enter the expiration date for the Task Order",
translate("forms.financial.expiration_date_label"),
description=translate("forms.financial.expiration_date_description"),
validators=[
InputRequired(),
DateRange(
@ -76,51 +79,51 @@ class TaskOrderForm(CacheableForm):
)
clin_0001 = NumberStringField(
"<dl><dt>CLIN 0001</dt> - <dd>Unclassified IaaS and PaaS Amount</dd></dl>",
translate("forms.financial.clin_0001_label"),
validators=[InputRequired()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
description=translate("forms.financial.clin_0001_description"),
filters=[number_to_int],
)
clin_0003 = NumberStringField(
"<dl><dt>CLIN 0003</dt> - <dd>Unclassified Cloud Support Package</dd></dl>",
translate("forms.financial.clin_0003_label"),
validators=[InputRequired()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
description=translate("forms.financial.clin_0003_description"),
filters=[number_to_int],
)
clin_1001 = NumberStringField(
"<dl><dt>CLIN 1001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 1</dd></dl>",
translate("forms.financial.clin_1001_label"),
validators=[InputRequired()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
description=translate("forms.financial.clin_1001_description"),
filters=[number_to_int],
)
clin_1003 = NumberStringField(
"<dl><dt>CLIN 1003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 1</dd></dl>",
translate("forms.financial.clin_1003_label"),
validators=[InputRequired()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
description=translate("forms.financial.clin_1003_description"),
filters=[number_to_int],
)
clin_2001 = NumberStringField(
"<dl><dt>CLIN 2001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 2</dd></dl>",
translate("forms.financial.clin_2001_label"),
validators=[InputRequired()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
description=translate("forms.financial.clin_2001_description"),
filters=[number_to_int],
)
clin_2003 = NumberStringField(
"<dl><dt>CLIN 2003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 2</dd></dl>",
translate("forms.financial.clin_2003_label"),
validators=[InputRequired()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
description=translate("forms.financial.clin_2003_description"),
filters=[number_to_int],
)
pdf = FileField(
"Upload a copy of your Task Order",
translate("forms.financial.pdf_label"),
validators=[
FileAllowed(["pdf"], "Only PDF documents can be uploaded."),
FileAllowed(["pdf"], translate("forms.financial.pdf_allowed_description")),
InputRequired(),
],
render_kw={"required": False},
@ -129,42 +132,60 @@ class TaskOrderForm(CacheableForm):
class RequestFinancialVerificationForm(CacheableForm):
uii_ids = NewlineListField(
"Unique Item Identifier (UII)s related to your application(s) if you already have them.",
description="If you have more than one UII, place each one on a new line.",
translate("forms.financial.uii_ids_label"),
description=translate("forms.financial.uii_ids_description"),
)
pe_id = StringField(
"Program Element Number",
description="PE numbers help the Department of Defense identify which offices' budgets are contributing towards this resource use. <br/><em>It should be 7 digits followed by 1-3 letters, and should have a zero as the first and third digits.</em>",
translate("forms.financial.pe_id_label"),
description=translate("forms.financial.pe_id_description"),
validators=[InputRequired()],
)
treasury_code = StringField(
"Program Treasury Code",
description="Program Treasury Code (or Appropriations Code) identifies resource types. <br/> <em>It should be a four digit or six digit number, optionally prefixed by one or more zeros.</em>",
translate("forms.financial.treasury_code_label"),
description=translate("forms.financial.treasury_code_description"),
validators=[InputRequired(), Regexp(TREASURY_CODE_REGEX)],
)
ba_code = StringField(
"Program Budget Activity (BA) Code",
description="BA Code is used to identify the purposes, projects, or types of activities financed by the appropriation fund. <br/><em>It should be two digits, followed by an optional letter.</em>",
translate("forms.financial.ba_code_label"),
description=translate("forms.financial.ba_code_description"),
validators=[InputRequired(), Regexp(BA_CODE_REGEX)],
)
fname_co = StringField("KO First Name", validators=[InputRequired()])
lname_co = StringField("KO Last Name", validators=[InputRequired()])
fname_co = StringField(
translate("forms.financial.fname_co_label"), validators=[InputRequired()]
)
lname_co = StringField(
translate("forms.financial.lname_co_label"), validators=[InputRequired()]
)
email_co = EmailField("KO Email", validators=[InputRequired(), Email()])
email_co = EmailField(
translate("forms.financial.email_co_label"),
validators=[InputRequired(), Email()],
)
office_co = StringField("KO Office", validators=[InputRequired()])
office_co = StringField(
translate("forms.financial.office_co_label"), validators=[InputRequired()]
)
fname_cor = StringField("COR First Name", validators=[InputRequired()])
fname_cor = StringField(
translate("forms.financial.fname_cor_label"), validators=[InputRequired()]
)
lname_cor = StringField("COR Last Name", validators=[InputRequired()])
lname_cor = StringField(
translate("forms.financial.lname_cor_label"), validators=[InputRequired()]
)
email_cor = EmailField("COR Email", validators=[InputRequired(), Email()])
email_cor = EmailField(
translate("forms.financial.email_cor_label"),
validators=[InputRequired(), Email()],
)
office_cor = StringField("COR Office", validators=[InputRequired()])
office_cor = StringField(
translate("forms.financial.office_cor_label"), validators=[InputRequired()]
)
def reset(self):
"""

View File

@ -2,12 +2,13 @@ from wtforms.fields import TextAreaField
from wtforms.validators import InputRequired
from .forms import CacheableForm
from atst.utils.localization import translate
class InternalCommentForm(CacheableForm):
text = TextAreaField(
"CCPO Internal Notes",
translate("forms.internal_comment.text_label"),
default="",
description="Add comments or notes for internal CCPO reference and follow-up here. <strong>These comments <em>will not</em> be visible to the person making the JEDI request.</strong>",
description=translate("forms.internal_comment.text_description"),
validators=[InputRequired()],
)

View File

@ -5,20 +5,30 @@ from wtforms.validators import Required, Email, Length
from atst.forms.validators import IsNumber
from atst.forms.fields import SelectField
from atst.utils.localization import translate
from .data import WORKSPACE_ROLES
class NewMemberForm(FlaskForm):
first_name = StringField(label="First Name", validators=[Required()])
last_name = StringField(label="Last Name", validators=[Required()])
email = EmailField("Email Address", validators=[Required(), Email()])
dod_id = StringField("DOD ID", validators=[Required(), Length(min=10), IsNumber()])
first_name = StringField(
label=translate("forms.new_member.first_name_label"), validators=[Required()]
)
last_name = StringField(
label=translate("forms.new_member.last_name_label"), validators=[Required()]
)
email = EmailField(
translate("forms.new_member.email_label"), validators=[Required(), Email()]
)
dod_id = StringField(
translate("forms.new_member.dod_id_label"),
validators=[Required(), Length(min=10), IsNumber()],
)
workspace_role = SelectField(
"Workspace Role",
translate("forms.new_member.workspace_role_label"),
choices=WORKSPACE_ROLES,
validators=[Required()],
default="",
description="The workspace role controls whether a member is permitted to organize a workspace into projects and environments, add members to this workspace, and view billing information.",
description=translate("forms.new_member.workspace_role_description"),
)

View File

@ -14,6 +14,7 @@ from .data import (
)
from .validators import DateRange, IsNumber
from atst.domain.requests import Requests
from atst.utils.localization import translate
class DetailsOfUseForm(CacheableForm):
@ -43,120 +44,126 @@ class DetailsOfUseForm(CacheableForm):
# Details of Use: General
dod_component = SelectField(
"DoD Component",
description="Identify the DoD component that is requesting access to the JEDI Cloud",
translate("forms.new_request.dod_component_label"),
description=translate("forms.new_request.dod_component_description"),
choices=SERVICE_BRANCHES,
validators=[InputRequired()],
)
jedi_usage = TextAreaField(
"JEDI Usage",
description="Your answer will help us provide tangible examples to DoD leadership how and why commercial cloud resources are accelerating the Department's missions",
translate("forms.new_request.jedi_usage_label"),
description=translate("forms.new_request.jedi_usage_description"),
validators=[InputRequired()],
)
# Details of Use: Cloud Readiness
num_software_systems = IntegerField(
"Number of Software Systems",
description="Estimate the number of software systems that will be supported by this JEDI Cloud access request",
translate("forms.new_request.num_software_systems_label"),
description=translate("forms.new_request.num_software_systems_description"),
)
jedi_migration = RadioField(
"JEDI Migration",
description="Are you using the JEDI Cloud to migrate existing systems?",
translate("forms.new_request.jedi_migration_label"),
description=translate("forms.new_request.jedi_migration_description"),
choices=[("yes", "Yes"), ("no", "No")],
default="",
)
rationalization_software_systems = RadioField(
description="Have you completed a “rationalization” of your software systems to move to the cloud?",
description=translate(
"forms.new_request.rationalization_software_systems_description"
),
choices=[("yes", "Yes"), ("no", "No"), ("In Progress", "In Progress")],
default="",
)
technical_support_team = RadioField(
description="Are you working with a technical support team experienced in cloud migrations?",
description=translate("forms.new_request.technical_support_team_description"),
choices=[("yes", "Yes"), ("no", "No")],
default="",
)
organization_providing_assistance = RadioField( # this needs to be updated to use checkboxes instead of radio
description="If you are receiving migration assistance, what is the type of organization providing assistance?",
description=translate(
"forms.new_request.organization_providing_assistance_description"
),
choices=ASSISTANCE_ORG_TYPES,
default="",
)
engineering_assessment = RadioField(
description="Have you completed an engineering assessment of your systems for cloud readiness?",
description=translate("forms.new_request.engineering_assessment_description"),
choices=[("yes", "Yes"), ("no", "No"), ("In Progress", "In Progress")],
default="",
)
data_transfers = SelectField(
description="How much data is being transferred to the cloud?",
description=translate("forms.new_request.data_transfers_description"),
choices=DATA_TRANSFER_AMOUNTS,
validators=[DataRequired()],
)
expected_completion_date = SelectField(
description="When do you expect to complete your migration to the JEDI Cloud?",
description=translate("forms.new_request.expected_completion_date_description"),
choices=COMPLETION_DATE_RANGES,
validators=[DataRequired()],
)
cloud_native = RadioField(
description="Are your software systems being developed cloud native?",
description=translate("forms.new_request.cloud_native_description"),
choices=[("yes", "Yes"), ("no", "No")],
default="",
)
# Details of Use: Financial Usage
estimated_monthly_spend = IntegerField(
"Estimated Monthly Spend",
description='Use the <a href="/jedi-csp-calculator" target="_blank" class="icon-link">JEDI CSP Calculator</a> to estimate your <b>monthly</b> cloud resource usage and enter the dollar amount below. Note these estimates are for initial approval only. After the request is approved, you will be asked to provide a valid Task Order number with specific CLIN amounts for cloud services.',
translate("forms.new_request.estimated_monthly_spend_label"),
description=translate("forms.new_request.estimated_monthly_spend_description"),
)
dollar_value = IntegerField(
"Total Spend",
description="What is your total expected budget for this JEDI Cloud Request?",
translate("forms.new_request.dollar_value_label"),
description=translate("forms.new_request.dollar_value_description"),
)
number_user_sessions = IntegerField(
description="How many user sessions do you expect on these systems each day?"
description=translate("forms.new_request.number_user_sessions_description")
)
average_daily_traffic = IntegerField(
"Average Daily Traffic (Number of Requests)",
description="What is the average daily traffic you expect the systems under this cloud contract to use?",
translate("forms.new_request.average_daily_traffic_label"),
description=translate("forms.new_request.average_daily_traffic_description"),
)
average_daily_traffic_gb = IntegerField(
"Average Daily Traffic (GB)",
description="What is the average daily traffic you expect the systems under this cloud contract to use?",
translate("forms.new_request.average_daily_traffic_gb_label"),
description=translate("forms.new_request.average_daily_traffic_gb_description"),
)
start_date = DateField(
description="When do you expect to start using the JEDI Cloud (not for billing purposes)?",
description=translate("forms.new_request.start_date_label"),
validators=[
InputRequired(),
DateRange(
lower_bound=pendulum.duration(days=1),
upper_bound=None,
message="Must be a date in the future.",
message=translate(
"forms.new_request.start_date_date_range_validation_message"
),
),
],
format="%m/%d/%Y",
)
name = StringField(
"Name Your Request",
description="This name serves as a reference for your initial request and the associated workspace that will be created once this request is approved. You may edit this name later.",
translate("forms.new_request.name_label"),
description=translate("forms.new_request.name_description"),
validators=[
InputRequired(),
Length(
min=4,
max=100,
message="Request names must be at least 4 and not more than 100 characters",
message=translate("forms.new_request.name_length_validation_message"),
),
],
)
@ -187,21 +194,29 @@ class WorkspaceOwnerForm(CacheableForm):
return super().validate(*args, **kwargs)
am_poc = BooleanField(
"I am the Workspace Owner",
translate("forms.new_request.am_poc_label"),
default=False,
false_values=(False, "false", "False", "no", ""),
)
fname_poc = StringField("First Name", validators=[InputRequired()])
fname_poc = StringField(
translate("forms.new_request.fname_poc_label"), validators=[InputRequired()]
)
lname_poc = StringField("Last Name", validators=[InputRequired()])
lname_poc = StringField(
translate("forms.new_request.lname_poc_label"), validators=[InputRequired()]
)
email_poc = EmailField("Email Address", validators=[InputRequired(), Email()])
email_poc = EmailField(
translate("forms.new_request.email_poc_label"),
validators=[InputRequired(), Email()],
)
dodid_poc = StringField(
"DoD ID", validators=[InputRequired(), Length(min=10), IsNumber()]
translate("forms.new_request.dodid_poc_label"),
validators=[InputRequired(), Length(min=10), IsNumber()],
)
class ReviewAndSubmitForm(CacheableForm):
reviewed = BooleanField("I have reviewed this data and it is correct.")
reviewed = BooleanField(translate("forms.new_request.reviewed_label"))

View File

@ -2,21 +2,34 @@ from flask_wtf import FlaskForm
from wtforms.fields import StringField, TextAreaField, FieldList
from wtforms.validators import Required
from atst.forms.validators import ListItemRequired, ListItemsUnique
from atst.utils.localization import translate
class ProjectForm(FlaskForm):
name = StringField(label="Project Name", validators=[Required()])
description = TextAreaField(label="Description", validators=[Required()])
name = StringField(
label=translate("forms.project.name_label"), validators=[Required()]
)
description = TextAreaField(
label=translate("forms.project.description_label"), validators=[Required()]
)
class NewProjectForm(ProjectForm):
EMPTY_ENVIRONMENT_NAMES = ["", None]
environment_names = FieldList(
StringField(label="Environment Name"),
StringField(label=translate("forms.project.environment_names_label")),
validators=[
ListItemRequired(message="Provide at least one environment name."),
ListItemsUnique(message="Environment names must be unique."),
ListItemRequired(
message=translate(
"forms.project.environment_names_required_validation_message"
)
),
ListItemsUnique(
message=translate(
"forms.project.environment_names_unique_validation_message"
)
),
],
)

View File

@ -2,6 +2,7 @@ import re
from wtforms.validators import ValidationError
import pendulum
from datetime import datetime
from atst.utils.localization import translate
def DateRange(lower_bound=None, upper_bound=None, message=None):
@ -27,7 +28,7 @@ def DateRange(lower_bound=None, upper_bound=None, message=None):
return _date_range
def IsNumber(message="Please enter a valid number."):
def IsNumber(message=translate("forms.validators.is_number_message")):
def _is_number(form, field):
try:
int(field.data)
@ -37,7 +38,7 @@ def IsNumber(message="Please enter a valid number."):
return _is_number
def PhoneNumber(message="Please enter a valid 5 or 10 digit phone number."):
def PhoneNumber(message=translate("forms.validators.phone_number_message")):
def _is_phone_number(form, field):
digits = re.sub(r"\D", "", field.data)
if len(digits) not in [5, 10]:
@ -50,9 +51,7 @@ def PhoneNumber(message="Please enter a valid 5 or 10 digit phone number."):
return _is_phone_number
def Name(
message="This field accepts letters, numbers, commas, apostrophes, hyphens, and periods."
):
def Name(message=translate("forms.validators.name_message")):
def _name(form, field):
match = re.match(r"[\w \,\.\'\-]+", field.data)
if not match or match.group() != field.data:
@ -61,7 +60,10 @@ def Name(
return _name
def ListItemRequired(message="Please provide at least one.", empty_values=("", None)):
def ListItemRequired(
message=translate("forms.validators.list_item_required_message"),
empty_values=("", None),
):
def _list_item_required(form, field):
non_empty_values = [v for v in field.data if v not in empty_values]
if len(non_empty_values) == 0:
@ -70,7 +72,7 @@ def ListItemRequired(message="Please provide at least one.", empty_values=("", N
return _list_item_required
def ListItemsUnique(message="Items must be unique"):
def ListItemsUnique(message=translate("forms.validators.list_items_unique_message")):
def _list_items_unique(form, field):
if len(field.data) > len(set(field.data)):
raise ValidationError(message)

View File

@ -2,16 +2,17 @@ from wtforms.fields import StringField
from wtforms.validators import Length
from .forms import CacheableForm
from atst.utils.localization import translate
class WorkspaceForm(CacheableForm):
name = StringField(
"Workspace Name",
translate("forms.workspace.name_label"),
validators=[
Length(
min=4,
max=100,
message="Workspace names must be at least 4 and not more than 50 characters",
message=translate("forms.workspace.name_length_validation_message"),
)
],
)

View File

@ -0,0 +1,35 @@
import yaml
import os
from functools import lru_cache
from atst.utils import getattr_path
ENV = os.getenv("FLASK_ENV", "dev")
class LocalizationInvalidKeyError(Exception):
def __init__(self, key, variables):
self.key = key
self.variables = variables
def __str__(self):
return "Requested {key} and variables {variables} with but an error occured".format(
key=self.key, variables=self.variables
)
localizations_cache_size = 1 if ENV == "dev" else None
@lru_cache(maxsize=localizations_cache_size)
def load_cached_translations_file(file_name):
return open(file_name).read()
def translate(key, variables={}):
translations = yaml.safe_load(load_cached_translations_file("translations.yaml"))
value = getattr_path(translations, key)
if value == None:
raise LocalizationInvalidKeyError(key, variables)
return value.format(**variables).replace("\n", "")

View File

@ -6,7 +6,7 @@
<div v-cloak>
<section class="block-list">
<header class="block-list__header">
<h1 class="block-list__title">Activity History</h1>
<h1 class="block-list__title">{{ "audit_log.header_title" | translate }}</h1>
</header>
<ul>

View File

@ -3,7 +3,7 @@
{% block content %}
{% if event.event_details %}
<br>
<b>Details:</b>
<b>{{ "audit_log.events.default.details" | translate }}</b>
<dl>
{% for key, value in event.event_details.items() %}
{% if value is not none %}
@ -15,11 +15,13 @@
{% endif %}
{% if event.changed_state %}
<br>
<b>Changes:</b>
<b>{{ "audit_log.events.default.changes" | translate }}</b>
<dl>
{% for key, value in event.changed_state.items() %}
<dt>{{ key }}</dt>
<dd>{{ value[0] }} to {{ value[1] }}</dd>
<dd>
{{ "audit_log.events.default.change" | translate({ "from": value[0], "to": value[1] }) }}
</dd>
{% endfor %}
</dl>
{% endif %}

View File

@ -6,7 +6,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}JEDI Cloud{% endblock %}</title>
<title>{% block title %}{{ "base_public.title_tag" | translate }}{% endblock %}</title>
{% assets "css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css">
{% endassets %}
@ -15,14 +15,13 @@
<body>
<div id='app-root'>
{% include 'components/usa_header.html' %}
<header class="topbar topbar--public">
<nav class="topbar__navigation">
<a href="{{ url_for('atst.home') }}" class="topbar__link topbar__link--home">
{{ Icon('shield', classes='topbar__link-icon') }}
<span class="topbar__link-label">JEDI Cloud</span>
<span class="topbar__link-label">{{ "base_public.header_title" | translate }}</span>
</a>
{% if g.current_user %}
@ -36,7 +35,7 @@
</a>
{% else %}
<a href="{{ url_for('atst.home') }}" class="topbar__link" title='Log in'>
<span class="topbar__link-label">Log in</span>
<span class="topbar__link-label">{{ "base_public.login" | translate }}</span>
{{ Icon('avatar', classes='topbar__link-icon') }}
</a>
{% endif %}

View File

@ -11,7 +11,9 @@
{% if dismissable %}
<button type='button' class='icon-link modal__dismiss' v-on:click='closeModal("{{name}}")'>
{{ Icon('x') }}
<span>Close</span>
<span>
{{ "components.modal.close" | translate }}
</span>
</button>
{% endif %}
</div>

View File

@ -1,10 +1,14 @@
{% from "components/tooltip.html" import Tooltip %}
<aside class='usa-banner'>
<img src='{{ url_for("static", filename="img/us_flag_small.png") }}' alt='U.S. Flag' />
<p>An official website of the United States government</p>
<img src='{{ url_for("static", filename="img/us_flag_small.png") }}' alt='{{ "components.usa_header.flag_image_alt" | translate }}' />
<p>{{ "components.usa_header.official_message" | translate }}
{{ Tooltip('<p><strong>The .mil means its official.</strong><br/>Federal government websites often end in .gov or .mil. Before sharing sensitive information, make sure youre on a federal government site.</p><br/><p><strong>The site is secure.</strong><br>The <strong>https://</strong> ensures that you are connecting to the official website and that any information you provide is encrypted and transmitted securely.</p>',
title='Heres how you know') }}
{{
Tooltip(
("components.usa_header.tooltip.message" | translate),
title=("components.usa_header.tooltip.title" | translate)
)
}}
</aside>

View File

@ -2,16 +2,20 @@
<footer class='app-footer'>
<div class='app-footer__info'>
<h5 class='app-footer__info__title'><a href="{{ url_for('atst.about') }}" class='icon-link' target='_blank' rel='noopener noreferrer'>Joint Enterprise Defense Infrastructure</a></h5>
<h5 class='app-footer__info__title'>
<a href="{{ url_for('atst.about') }}" class='icon-link' target='_blank' rel='noopener noreferrer'>
{{ "footer.about_link_text" | translate }}
</a>
</h5>
<a href="{{ url_for('atst.helpdocs') }}" class='icon-link app-footer__info__link' target='_blank' rel='noopener noreferrer'>
{{ Icon('help') }}
<span>JEDI Cloud Help</span>
<span>{{ "footer.jedi_help_link_text" | translate }}</span>
</a>
</div>
<dl class='app-footer__browser-support'>
<dt>JEDI Cloud supported on these web browsers</dt>
<dt>{{ "footer.browser_support" | translate }}</dt>
<dd>Chrome</dd><dd>Firefox</dd><dd>Safari</dd><dd>Edge</dd><dd>IE11 on Windows 10</dd><dd>IE10 on Windows 7</dd>
</dl>
</footer>

View File

@ -1,6 +1,6 @@
{% from "components/text_input.html" import TextInput %}
{% set title_text = 'Edit {} project'.format(project.name) if project else 'Add a new project' %}
{% set title_text = ('fragments.edit_project_form.existing_project_title' | translate({ "project_name": project.name })) if project else ('fragments.edit_project_form.new_project_title' | translate) %}
{{ form.csrf_token }}
<div class="panel">
@ -10,7 +10,7 @@
<div class="panel__content">
<p>
AT-AT allows you to organize your workspace into multiple projects, each of which may have environments.
{{ "fragments.edit_project_form.explain" | translate }}
</p>
{{ TextInput(form.name) }}
{{ TextInput(form.description, paragraph=True) }}

View File

@ -23,11 +23,20 @@
{{ OptionsInput(form.service_branch) }}
{{ OptionsInput(form.citizenship) }}
{{ OptionsInput(form.designation) }}
{{ DateInput(form.date_latest_training,tooltip="When was the last time you completed the IA training? <br> Information Assurance (IA) training is an important step in cyber awareness.",placeholder="MM / DD / YYYY", validation="date") }}
{{
DateInput(
form.date_latest_training,
tooltip=("fragments.edit_user_form.date_last_training_tooltip" | translate),
placeholder="MM / DD / YYYY",
validation="date"
)
}}
</div>
</div>
<div class='action-group'>
<button class='usa-button usa-button-big' type='submit'>Save Details</button>
<button class='usa-button usa-button-big' type='submit'>
{{ "fragments.edit_user_form.save_details_button" | translate }}
</button>
</div>
</form>

View File

@ -1,17 +1,17 @@
{% from "components/icon.html" import Icon %}
<p>
The CCPO will review and respond to your request in 3 business days. Youll be notified via email or phone. Please note if your request is for over $1M of JEDI cloud resources it will require a manual review by the CCPO.
{{ "fragments.pending_ccpo_acceptance_alert.paragraph_1" | translate }}
</p>
<p>
While your request is being reviewed, your next step is to create a Task Order (TO) associated with the JEDI Cloud. Please contact a Contracting Officer (KO), Contracting Officer Representative (COR), or a Financial Manager to help with this step.
{{ "fragments.pending_ccpo_acceptance_alert.paragraph_2" | translate }}
</p>
<div class='alert__actions'>
<a href='/help' class='icon-link'>
{{ Icon('help') }}
Learn more about the JEDI Cloud Task Order and the Financial Verification process.
{{ "fragments.pending_ccpo_acceptance_alert.learn_more_link_text" | translate }}
</a>
</div>

View File

@ -1,8 +1,8 @@
<p>
The CCPO will review and respond to your Financial Verification submission in 3 business days. You will be notified via email or phone.
{{ "fragments.pending_ccpo_approval_modal.paragraph_1" | translate }}
</p>
<p>
Once the financial verification is approved you will be invited to create your JEDI Workspace and set-up your projects. Click here for more details.
{{ "fragments.pending_ccpo_approval_modal.paragraph_2" | translate }}
</p>

View File

@ -1,19 +1,16 @@
{% from "components/icon.html" import Icon %}
<p>
The next step is to create a Task Order associated with JEDI Cloud.
Please contact a Contracting Officer (KO), Contracting Officer
Representative (COR), or a Financial Manager to help with this step.
{{ "fragments.pending_financial_verification.paragraph_1" | translate }}
</p>
<p>
Once the Task Order has been created, you will be asked to provide
details about the task order in the Financial Verification step.
{{ "fragments.pending_financial_verification.paragraph_2" | translate }}
</p>
<div class='alert__actions'>
<a href='/help' class='icon-link'>
{{ Icon('help') }}
Learn more about the JEDI Cloud Task Order and the Financial Verification process.
{{ "fragments.pending_financial_verification.learn_more_link_text" | translate }}
</a>
</div>

View File

@ -2,7 +2,7 @@
{% extends "base_public.html" %}
{% block title %}Sign in | JEDI Cloud{% endblock %}
{% block title %}{{ "login.title_tag" | translate }}{% endblock %}
{% block content %}
@ -17,11 +17,15 @@
{% include "fragments/flash.html" %}
{% endwith %}
<h1 class="login-banner__heading">Access the JEDI Cloud</h1>
<h1 class="login-banner__heading">{{ "login.h1_title" | translate }}</h1>
<img class="login-banner__logo" src="{{url_for('static', filename='img/ccpo-logo.svg')}}" alt="Cloud Computing Program Office Logo">
<img class="login-banner__logo" src="{{url_for('static', filename='img/ccpo-logo.svg')}}" alt="{{ "login.ccpo_logo_alt_text" | translate }}">
<a class="usa-button usa-button-big login-banner__button" href='{{ redirect_url }}'><span>Sign in with CAC</span></a>
<a class="usa-button usa-button-big login-banner__button" href='{{ redirect_url }}'>
<span>
{{ "login.login_button" | translate }}
</span>
</a>
</div>
{% with %}
@ -29,11 +33,11 @@
{% include "fragments/flash.html" %}
{% endwith %}
{{ Alert('Certificate Selection',
message='When you are prompted to select a certificate, please select <strong>E-mail Certificate</strong> from the provided choices.',
{{ Alert(("login.certificate_selection.title" | translate),
message=("login.certificate_selection.message" | translate),
actions=[
{
'label': 'Learn More',
'label': ("login.certificate_selection.learn_more" | translate),
'icon': 'help',
'href': '/help'
}

View File

@ -5,7 +5,9 @@
{% if not workspace %}
<a href="{{ url_for('atst.home') }}" class="topbar__link topbar__link--home">
{{ Icon('shield', classes='topbar__link-icon') }}
<span class="topbar__link-label">JEDI Cloud</span>
<span class="topbar__link-label">
{{ "navigation.topbar.jedi_cloud_link_text" | translate }}
</span>
</a>
{% else %}
<a href="{{ url_for('atst.home') }}" class="topbar__link topbar__link--shield" title="JEDI Cloud Home">
@ -22,13 +24,15 @@
v-on:click='props.toggle'
class="topbar__link topbar__workspace-menu__toggle"
v-bind:class="{ 'topbar__workspace-menu__toggle--open': props.isVisible }">
<span class="topbar__link-label">{{ ("Workspace " + workspace.name) }}</span>
<span class="topbar__link-label">{{ "navigation.topbar.named_workspace" | translate({ "workspace": workspace.name }) }}</span>
<template v-if='props.isVisible'>{{ Icon('caret_up', classes='topbar__link-icon') }}</template>
<template v-else>{{ Icon('caret_down', classes='topbar__link-icon') }}</template>
</button>
<div v-show='props.isVisible' class='topbar__workspace-menu__panel menu'>
<h2 class='menu__heading'>Other Active Workspaces</h2>
<h2 class='menu__heading'>
{{ "navigation.topbar.other_active_workspaces" | translate }}
</h2>
{% if workspaces %}
<ul class='menu__list'>
@ -44,11 +48,15 @@
{% else %}
<p class='menu__message'>You have no other active JEDI workspaces.</p>
<p class='menu__message'>
{{ "navigation.topbar.no_other_active_workspaces" | translate }}
</p>
{% endif %}
<a href="{{ url_for('requests.requests_form_new', screen=1) }}" class='menu__button usa-button'>Request a new JEDI Workspace</a>
<a href="{{ url_for('requests.requests_form_new', screen=1) }}" class='menu__button usa-button'>
{{ "navigation.topbar.request_workspace_link_text" | translate }}
</a>
</div>
</template>
</div>
@ -60,7 +68,7 @@
{{ Icon('avatar', classes='topbar__link-icon') }}
</a>
<a href="{{ url_for('atst.logout') }}" class="topbar__link" title='Log out of JEDI Cloud'>
<a href="{{ url_for('atst.logout') }}" class="topbar__link" title='{{ "navigation.topbar.logout_link_title" | translate }}'>
{{ Icon('logout', classes='topbar__link-icon') }}
</a>
</div>

View File

@ -3,12 +3,12 @@
<nav class='sidenav workspace-navigation'>
<ul>
{{ SidenavItem(
"Projects",
("navigation.workspace_navigation.projects" | translate),
href=url_for("workspaces.workspace_projects", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/projects'),
subnav=None if not user_can(permissions.ADD_APPLICATION_IN_WORKSPACE) else [
{
"label": "Add New Project",
"label": ("navigation.workspace_navigation.add_new_project_label" | translate),
"href": url_for('workspaces.new_project', workspace_id=workspace.id),
"active": g.matchesPath('\/workspaces\/[A-Za-z0-9-]*\/projects'),
"icon": "plus"
@ -18,12 +18,12 @@
{% if user_can(permissions.VIEW_WORKSPACE_MEMBERS) %}
{{ SidenavItem(
"Members",
("navigation.workspace_navigation.members" | translate),
href=url_for("workspaces.workspace_members", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/members'),
subnav=None if not user_can(permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE) else [
{
"label": "Add New Member",
"label": ("navigation.workspace_navigation.add_new_member_label" | translate),
"href": url_for("workspaces.new_member", workspace_id=workspace.id),
"active": request.url_rule.rule.startswith('/workspaces/<workspace_id>/members/new'),
"icon": "plus"
@ -34,7 +34,7 @@
{% if user_can(permissions.VIEW_USAGE_DOLLARS) %}
{{ SidenavItem(
"Budget Report",
("navigation.workspace_navigation.budget_report" | translate),
href=url_for("workspaces.workspace_reports", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/reports')
) }}
@ -42,7 +42,7 @@
{% if user_can(permissions.EDIT_WORKSPACE_INFORMATION) %}
{{ SidenavItem(
"Workspace Settings",
("navigation.workspace_navigation.workspace_settings" | translate),
href=url_for("workspaces.workspace", workspace_id=workspace.id),
active=request.url_rule.rule.startswith('/workspaces/<workspace_id>/edit'),
subnav=None

View File

@ -20,7 +20,7 @@
<div class="panel__heading">
<h1>{% block heading %}{% endblock %}</h1>
<div class="subtitle h2">New Request</div>
<div class="subtitle h2">{{ "requests._new.new_request" | translate }}</div>
</div>
<div class="panel__content">
@ -37,7 +37,7 @@
{% block next %}
<div class='action-group'>
<input type='submit' class='usa-button usa-button-primary' value='Save & Continue' />
<input type='submit' class='usa-button usa-button-primary' value='{{ "requests._new.save_and_continue" | translate }}' />
</div>
{% endblock %}

View File

@ -12,7 +12,8 @@
<section class='panel'>
<header class='panel__heading panel__heading--divider request-approval__heading'>
<h1 class='h2'>Request: {{ jedi_request.displayname }}
<h1 class='h2'>
{{ "requests.approval.request_title" | translate({ "displayname": jedi_request.displayname }) }}
</h1>
<span class='label label--info'>{{ current_status }}</span>
</header>
@ -31,7 +32,7 @@
<form method="POST" action="{{ url_for('requests.create_internal_comment', request_id=jedi_request.id) }}">
<div class='panel'>
<div class='panel__heading panel__heading--divider'>
<h2>CCPO Internal Comments</h2>
<h2>{{ "requests.approval.ccpo_internal_comments" | translate }}</h2>
</div>
<div class='comment-log'>
@ -54,14 +55,18 @@
</ol>
{% else %}
<div class='panel__content'>
<p class='h4'>No CCPO comments have been recorded yet.</p>
<p class='h4'>
{{ "requests.approval.no_ccpo_comments" | translate }}
</p>
</div>
{% endif %}
</div>
<div class='panel__heading internal-notes__add-comment__heading'>
<h3 class='h3'>Add a comment</h2>
<h3 class='h3'>
{{ "requests.approval.add_comment" | translate }}
</h3>
</div>
<div class='panel__content'>
@ -70,7 +75,9 @@
</div>
</div>
<div class='action-group action-group--tight'>
<button class='usa-button' type="submit">Save Notes</button>
<button class='usa-button' type="submit">
{{ "requests.approval.save_notes" | translate }}
</button>
</div>
</form>
</section>
@ -86,7 +93,9 @@
<div class='panel'>
<header class='panel__heading panel__heading--divider'>
<h2 class='request-approval__columns__heading'>CCPO Review Activity</h2>
<h2 class='request-approval__columns__heading'>
{{ "requests.approval.ccpo_review_activity" | translate }}
</h2>
</header>
<div class='approval-log'>
@ -104,7 +113,9 @@
<div class='approval-log__behalfs'>
{% if review.lname_mao %}
<div class='approval-log__behalf'>
<h3 class='approval-log__log-item__header'>Mission Owner approval on behalf of:</h3>
<h3 class='approval-log__log-item__header'>
{{ "requests.approval.mission_owner_approval_on_behalf_of" | translate }}
</h3>
<span>{{ review.full_name_mao }}</span>
<span>{{ review.email_mao }}</span>
<span>
@ -118,7 +129,9 @@
{% if review.lname_ccpo %}
<div class='approval-log__behalf'>
<h3 class='approval-log__log-item__header'>CCPO approval on behalf of:</h3>
<h3 class='approval-log__log-item__header'>
{{ "requests.approval.ccpo_approval_on_behalf_of" | translate }}
</h3>
<span>{{ review.full_name_ccpo }}</span>
</div>
{% endif %}
@ -134,14 +147,18 @@
</ol>
{% else %}
<div class='panel__content'>
<p class='h4'>No CCPO approvals or request changes have been recorded yet.</p>
<p class='h4'>
{{ "requests.approval.no_ccpo_approval_request_changes" | translate }}
</p>
</div>
{% endif %}
</div>
{% if jedi_request.is_pending_ccpo_action %}
<div class='panel__heading request-approval__review__heading'>
<h3 class='h3'>Review this Request</h2>
<h3 class='h3'>
{{ "requests.approval.review_request" | translate }}
</h3>
</div>
<div class='panel__content'>
@ -149,10 +166,14 @@
<div class='usa-input'>
<fieldset class='usa-input__choices usa-input__choices--inline'>
<input v-on:change='setReview' type='radio' name='review' id='review-approving' value='approving' {{ 'checked' if initialState == 'approving' }}/>
<label for='review-approving'>Ready for approval</label>
<label for='review-approving'>
{{ "requests.approval.ready_for_approval" | translate }}
</label>
<input v-on:change='setReview' type='radio' name='review' id='review-denying' value='denying'/>
<label for='review-denying'>Request revisions</label>
<label for='review-denying'>
{{ "requests.approval.request_revisions" | translate }}
</label>
</fieldset>
</div>
@ -161,8 +182,8 @@
<div v-if='approving' key='approving' v-cloak>
{{ TextInput(
review_form.comment,
label='Approval comments or notes',
description='Provide any comments or notes regarding the approval of this request. <strong>This message will be shared with the person making the JEDI request.</strong>',
label=("requests.approval.approve_comments_or_notes_label" | translate),
description=("requests.approval.approve_comments_or_notes_description" | translate),
paragraph=True,
noMaxWidth=True
) }}
@ -171,7 +192,7 @@
<div v-else key='denying' v-cloak>
{{ TextInput(
review_form.comment,
label='Revision instructions or notes',
label=("requests.approval.revision_instructions_or_notes_label" | translate),
paragraph=True,
noMaxWidth=True
) }}
@ -180,12 +201,20 @@
<div v-if='approving' class='form__sub-fields' v-cloak>
<h3>Authorizing Officials <span class='subtitle'>(optional)</span></h3>
<p>Provide the name of the key officials for both parties that have authorized this request to move forward. <strong>This section is not visible to the person making the request. It is only viewable by CCPO staff.</strong></p>
<h3>
{{ "requests.approval.authorizing_officials_title" | translate }}
<span class='subtitle'>(optional)</span>
</h3>
<p>
{{ "requests.approval.authorizing_officials_paragraph" | translate }}
</p>
<hr />
<h4>Mission Authorizing Official</h4>
<h4>
{{ "requests.approval.mission_authorizing_official_title" | translate }}
</h4>
<div class='form-row'>
<div class='form-col form-col--half'>
@ -202,7 +231,9 @@
<hr />
<h4>CCPO Authorizing Official</h4>
<h4>
{{ "requests.approval.ccpo_authorizing_official_title" | translate }}
</h4>
<div class='form-row'>
<div class='form-col form-col--half'>
@ -238,4 +269,3 @@
</article>
{% endblock %}

View File

@ -12,25 +12,25 @@
{% include "fragments/flash.html" %}
{% if saved_draft %}
{% call Alert('Draft saved', level='success') %}
{% call Alert(("requests.financial_verification.draft_saved" | translate), level='success') %}
{% endcall %}
{% endif %}
{% if jedi_request.is_pending_financial_verification and not f.errors and not extended %}
{{ Alert('Pending Financial Verification', fragment="fragments/pending_financial_verification.html") }}
{{ Alert(("requests.financial_verification.pending_financial_verification" | translate), fragment="fragments/pending_financial_verification.html") }}
{% endif %}
<financial inline-template v-bind:initial-data='{{ f.data|mixedContentToJson }}'>
<div class="col">
{% if extended %}
{{ Alert('Manually enter Task Order information',
message="Additional fields are displayed below, where you can manually enter financial information as documented in your Task Order.",
{{ Alert(("requests.financial_verification.manually_enter_task_information_label" | translate),
message=("requests.financial_verification.manually_enter_task_information_description" | translate),
level='warning',
actions=[
{
'href': url_for('atst.helpdocs'),
'label': 'Learn more about the JEDI Cloud Task Order and the Financial Verification process.',
'label': ("requests.financial_verification.manually_enter_task_information_help_label" | translate),
'icon': 'help'
}
]
@ -39,9 +39,12 @@
{% if f.is_missing_task_order_number %}
{% set extended_url = url_for('requests.financial_verification', request_id=jedi_request.id, extended=True) %}
{% call Alert('Task Order not found in EDA', level='warning') %}
We could not find your Task Order in our system of record, EDA. Please confirm that you have entered it correctly.<br>
<a class="usa-button" href="{{ extended_url }}">Enter Task Order information manually</a>
{% call Alert(("requests.financial_verification.task_order_not_found_eda_label"), level='warning') %}
{{ "requsts.financial_verification.task_order_not_found_eda_description" | translate }}
<br>
<a class="usa-button" href="{{ extended_url }}">
{{ "requests.financial_verification.enter_task_order_manually_link_text" | translate }}
</a>
{% endcall %}
{% endif %}
@ -52,7 +55,7 @@
{% autoescape false %}
{% if f.errors and not f.is_only_missing_task_order_number %}
{{ Alert('There were some errors',
{{ Alert(("requests.financial_verification.some_errors_label" | translate),
message="<p>Please see below.</p>",
level='error'
) }}
@ -61,13 +64,19 @@
<div class="panel">
<div class="panel__heading">
<h1>Financial Verification</h1>
<div class="subtitle" id="financial-verification"><h2>Request: {{ jedi_request.displayname }}</h2></div>
<h1>{{ "requests.financial_verification.financial_verification_title" | translate }}</h1>
<div class="subtitle" id="financial-verification">
<h2>
{{ "requests.financial_verification.request_title" | translate({ "displayname" : jedi_request.displayname }) }}
</h2>
</div>
</div>
<div class="panel__content">
<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>
<p>
{{ "requests.financial_verification.permissions_paragraph" | translate }}
</p>
{% if extended %}
<fieldset class="form__sub-fields form__sub-fields--warning">
@ -77,7 +86,14 @@
{{ TextInput(f.legacy_task_order.funding_type_other) }}
</template>
{{ DateInput(f.legacy_task_order.expiration_date, placeholder='MM / DD / YYYY', validation='date', tooltip='Please enter the expiration date for the task order only and do not include options that you may choose to exercise in the future.') }}
{{
DateInput(
f.legacy_task_order.expiration_date,
placeholder='MM / DD / YYYY',
validation='date',
tooltip=("requests.financial_verification.expiration_date_placeholder" | translate)
)
}}
{{ TextInput(
f.legacy_task_order.clin_0001,
@ -130,14 +146,14 @@
{{ TextInput(
f.legacy_task_order.number,
placeholder="e.g.: 1234567899C0001",
tooltip="A Contracting Officer will likely be the best source for this number.",
tooltip=("requests.financial_verification.number_placeholder" | translate),
validation="requiredField"
) }}
{{ TextInput(f.request.uii_ids,
paragraph=True,
placeholder="examples: \nDI 0CVA5786950 \nUN1945326361234786950",
tooltip="A Unique Item Identifer is a unique code that helps the Department of Defense track and report on where and how digital assets are stored. <br>Not all applications have an existing UII number assigned."
tooltip=("requests.financial_verification.uui_ids_placeholder" | translate)
) }}
{{ TextInput(f.request.pe_id,
@ -151,7 +167,9 @@
<hr />
<h3>Contracting Officer (KO) Information</h3>
<h3>
{{ "requests.financial_verification.contracting_officer_information_title" | translate }}
</h3>
<div class='form-row'>
<div class='form-col form-col--half '>{{ TextInput(f.request.fname_co, validation="requiredField") }}</div>
@ -165,7 +183,9 @@
<hr />
<h3>Contracting Officer Representative (COR) Information</h3>
<h3>
{{ "requests.financial_verification.contracting_officer_representative_information_title" | translate }}
</h3>
<div class='form-row'>
<div class='form-col form-col--half '>{{ TextInput(f.request.fname_cor, validation="requiredField") }}</div>
<div class='form-col form-col--half '>{{ TextInput(f.request.lname_cor, validation="requiredField") }}</div>

View File

@ -7,7 +7,7 @@
{% block content %}
{% call Modal(name='pendingFinancialVerification', dismissable=True) %}
<h1>Request submitted!</h1>
<h1>{{ "requests.index.request_submitted_title" | translate }}</h1>
{% include 'fragments/pending_financial_verification.html' %}
@ -17,7 +17,7 @@
{% endcall %}
{% call Modal(name='pendingCCPOApproval', dismissable=True) %}
<h1>Financial Verification submitted!</h1>
<h1>{{ "requests.index.financial_verification_submitted_title" | translate }}</h1>
{% include 'fragments/pending_ccpo_approval_modal.html' %}
@ -27,7 +27,7 @@
{% endcall %}
{% call Modal(name='pendingCCPOAcceptance', dismissable=True) %}
<h1>Request submitted!</h1>
<h1>{{ "requests.index.request_submitted_title" | translate }}</h1>
{% include 'fragments/pending_ccpo_acceptance_alert.html' %}
@ -50,9 +50,9 @@
{% if not requests %}
{{ EmptyState(
'You currently have no JEDI Cloud workspaces.',
sub_message='A JEDI Cloud Workspace is where you manage your projects and control user access to those projects.',
action_label='Create a new JEDI Cloud Request',
("requests.index.no_workspaces_label" | translate),
sub_message=("requests.index.no_workspaces_sub_message" | translate),
action_label=("requests.index.no_workspaces_action_label" | translate),
action_href=url_for('requests.requests_form_new', screen=1),
icon='document'
) }}
@ -62,15 +62,15 @@
<div class="row kpi">
<div class="kpi__item col col--grow">
<div class="kpi__item__value">{{ kpi_inprogress }}</div>
<div class="kpi__item__description">Requests in progress</div>
<div class="kpi__item__description">{{ "requests.index.requests_in_progress" | translate }}</div>
</div>
<div class="kpi__item col col--grow">
<div class="kpi__item__value">{{ kpi_pending }}</div>
<div class="kpi__item__description">Pending CCPO Action</div>
<div class="kpi__item__description">{{ "requests.index.pending_ccpo_action" | translate }}</div>
</div>
<div class="kpi__item col col--grow">
<div class="kpi__item__value">{{ kpi_completed }}</div>
<div class="kpi__item__description">Approved Requests</div>
<div class="kpi__item__description">{{ "requests.index.approved_requests" | translate }}</div>
</div>
</div>
{% endif %}
@ -80,28 +80,28 @@
{% if extended_view %}
<form @submit.prevent class='search-bar'>
<div class='usa-input search-input'>
<label for='requests-search'>Search requests by name</label>
<label for='requests-search'>{{ "requests.index.search_by_name" | translate }}</label>
<input v-model='searchValue' type='search' id='requests-search' name='requests-search' placeholder="Search by name"/>
<button>
<span class="hide">Search</span>
<span class="hide">{{ "requests.index.search_button_text" | translate }}</span>
</button>
</div>
<div class="search-bar__filters">
<div class='usa-input'>
<label for='filter-status'>Filter requests by status</label>
<label for='filter-status'>{{ "requests.index.filter_requests_by_status_label" | translate }}</label>
<select v-model="statusValue" id="filter-status" name="filter-status">
<option value="" selected disabled>Filter by status</option>
<option value="">All</option>
<option value="" selected disabled>{{ "requests.index.filter_by_status" | translate }}</option>
<option value="">{{ "requests.index.all_filter" | translate }}</option>
<option v-for="status in statuses" :value="status">!{ status }</option>
</select>
</div>
<div class='usa-input'>
<label for='filter-dod-component'>Filter requests by DOD component</label>
<label for='filter-dod-component'>{{ "requests.index.filter_requests_by_dod_component" | translate }}</label>
<select v-model="dodComponentValue" id="filter-dod-component" name="filter-dod-component">
<option value="" selected disabled>Filter by DOD Component</option>
<option value="">All</option>
<option value="" selected disabled>{{ "requests.index.filter_by_dod_component" | translate }}</option>
<option value="">{{ "requests.index.all_filter" | translate }}</option>
<option v-for="dodComponent in dodComponents" :value="dodComponent">!{ dodComponent }</option>
</select>
</div>
@ -128,7 +128,9 @@
<tr>
<th scope="row">
<a class='icon-link icon-link--large' :href="r.edit_link">!{ r.name }</a>
<span v-if="r.action_required" class="label label--info">Action Required</span>
<span v-if="r.action_required" class="label label--info">
{{ "requests.index.action_required" | translate }}
</span>
</th>
<td>
<local-datetime
@ -159,10 +161,10 @@
</table>
<div v-else>
{{ EmptyState(
'No requests found.',
("requests.index.no_requests_found" | translate),
action_label=None,
action_href=None,
sub_message='Please try a different search.',
sub_message=("requests.index.try_different_search" | translate),
icon=None
) }}
</div>
@ -174,4 +176,3 @@
</requests-list>
{% endblock %}

View File

@ -4,7 +4,7 @@
<ul>
<li class="progress-menu__item progress-menu__item--complete">
<a href="{{ pending_url }}">
Request Information
{{ "requests.review_menu.request_information_link_text" | translate }}
</a>
</li>
{% if g.matchesPath(financial_url) %}
@ -14,7 +14,7 @@
{% endif %}
<li class="progress-menu__item progress-menu__item--{{ financial_status }}">
<a href="{{ financial_url }}">
Financial Verification Information
{{ "requests.review_menu.financial_verification_information_link_text" | translate }}
</a>
</li>
</ul>

View File

@ -15,46 +15,86 @@
<details-of-use inline-template v-bind:initial-data='{{ f.data|tojson }}'>
<div>
<p>Wed like to know a little about how you plan to use JEDI Cloud services to process your request. Please answer the following questions to the best of your ability. Note that the CCPO does not directly help with migrating systems to JEDI Cloud. These questions are for learning about your cloud readiness and financial usage of the JEDI Cloud; your estimates will not be used for any department level reporting.</p>
<p><em>All fields are required, unless specified optional.</em></p>
{{ "requests.screen-1.form_instructions" | translate }}
<h2>General</h2>
<h2>{{ "requests.screen-1.general_title_text"| translate }}</h2>
{{ OptionsInput(f.dod_component) }}
{{ TextInput(f.jedi_usage, paragraph=True, placeholder="Briefly describe how you are expecting to use the JEDI Cloud. e.g. We are migrating XYZ application to the cloud so that...") }}
{{
TextInput(
f.jedi_usage,
paragraph=True,
placeholder=("requests.screen-1.jedi_usage_placeholder" | translate)
)
}}
<h2>Cloud Readiness</h2>
{{ TextInput(f.num_software_systems,validation="integer",tooltip="A software system can be any code that you plan to host on cloud infrastructure. For example, it could be a custom-developed web application, or a large ERP system.",placeholder="0") }}
{{ OptionsInput(f.jedi_migration, tooltip="Cloud migration is the process of moving data, applications or other business elements from an organization\\'s onsite computers/data centers to the cloud, or moving them from one cloud environment to another.") }}
<h2>{{ "requests.screen-1.cloud_readiness_title_text" | translate }}</h2>
{{
TextInput(
f.num_software_systems,
validation="integer",
tooltip=("requests.screen-1.num_software_systems_tooltip" | translate),
placeholder="0"
)
}}
{{
OptionsInput(
f.jedi_migration,
tooltip=("requests.screen-1.jedi_migration_tooltip" | translate)
)
}}
<transition name='slide'>
<template v-if="jediMigrationOptionSelected">
<fieldset class='form__sub-fields' v-if='isJediMigration' v-cloak>
<legend class='usa-sr-only'>Questions related to JEDI Cloud migration</legend>
{{ OptionsInput(f.rationalization_software_systems, tooltip="Rationalization is the DoD process to determine whether the application should move to the cloud.") }}
<legend class='usa-sr-only'>
{{ "requests.screen-1.questions_title_text" | translate }}
</legend>
{{
OptionsInput(
f.rationalization_software_systems,
tooltip=("requests.screen-1.rationalization_software_systems_tooltip" | translate)
)
}}
{{ OptionsInput(f.technical_support_team) }}
<transition name='slide'>
<template v-if="hasTechnicalSupportTeam">
{{ OptionsInput(f.organization_providing_assistance) }}
</template>
</transition>
{{ OptionsInput(f.engineering_assessment, tooltip="An engineering assessment is an evaluation to convert your application architecture from on-premises to using the commercial cloud") }}
{{ OptionsInput(
f.engineering_assessment,
tooltip=("requests.screen-1.engineering_assessment_tooltip" | translate)
)
}}
{{ OptionsInput(f.data_transfers) }}
{{ OptionsInput(f.expected_completion_date) }}
</fieldset>
<template v-if='!isJediMigration' v-cloak>
{{ OptionsInput(f.cloud_native, tooltip="Cloud native is architecting and designing your application to use all the benefits of the commercial cloud. Specifically, designing applications so that they are decoupled from a physical resource.") }}
{{
OptionsInput(
f.cloud_native,
tooltip=("requests.screen-1.cloud_native_tooltip" | translate)
)
}}
</template>
</template>
</transition>
<h2>Financial Usage</h2>
{{ TextInput(f.estimated_monthly_spend, tooltip="Refer to financial verification step help docs", validation="dollars", placeholder="$0") }}
<h2>{{ "requests.screen-1.financial_usage_title" | translate }}</h2>
{{
TextInput(
f.estimated_monthly_spend,
tooltip=("requests.screen-1.estimated_monthly_spend_tooltip" | translate),
validation="dollars",
placeholder="$0"
)
}}
<div class='alert alert-info'>
<div class='alert__content'>
<div class='alert__message'>
<p>So this means you are spending approximately <span class="label label--info">!{ annualSpendStr }</span> annually</p>
{{ "requests.screen-1.approximate_annual_spend_paragraph" | translate }}
</div>
</div>
</div>
@ -62,15 +102,38 @@
<transition name='slide'>
<template v-if="annualSpend > {{ annual_spend_threshold }}">
<fieldset class='form__sub-fields'>
<h3>Please provide additional details regarding your planned usage.</h3>
<h3>
{{ "requests.screen-1.additional_plan_details_title" | translate }}
</h3>
{{ TextInput(f.number_user_sessions, validation='integer', placeholder="0") }}
{{ TextInput(f.average_daily_traffic, tooltip="Requests are the client-to-server network traffic that is being transferred to your systems",validation="integer", placeholder="0") }}
{{ TextInput(f.average_daily_traffic_gb, tooltip="GB uploaded is the gigabyte amount of data traffic that is being transferred to your systems",validation="gigabytes", placeholder="0GB") }}
{{
TextInput(
f.average_daily_traffic,
tooltip=("requests.screen-1.average_daily_traffic_tooltip" | translate),
validation="integer",
placeholder="0"
)
}}
{{
TextInput(
f.average_daily_traffic_gb,
tooltip=("requests.screen-1.average_daily_traffic_gb_tooltip" | translate),
validation="gigabytes",
placeholder="0GB"
)
}}
</fieldset>
</template>
</transition>
{{ TextInput(f.dollar_value, validation='dollars', placeholder='$0', tooltip='You may specify a different Total Spend amount to cover other JEDI Cloud services that the JEDI Cloud cost calculator was not able to estimate. Examples may include support packages from the cloud service provider.') }}
{{
TextInput(
f.dollar_value,
validation='dollars',
placeholder='$0',
tooltip=("requests.screen-1.dollar_value_tooltip" | translate)
)
}}
{{ DateInput(f.start_date, placeholder='MM / DD / YYYY', validation='date') }}
{{ TextInput(f.name, placeholder='Request Name', validation='workspaceName') }}

View File

@ -0,0 +1,33 @@
import pytest
from atst.utils.localization import (
translate,
load_cached_translations_file,
LocalizationInvalidKeyError,
)
def test_loading_cached_translations_file_returns_the_file_contents():
file_name = "translations.yaml"
assert load_cached_translations_file(file_name) == open(file_name).read()
def test_looking_up_existing_key():
assert translate("testing.example_string") == "Hello World"
def test_nested_keys():
assert translate("testing.nested.example") == "Hello nested example"
def test_with_variables():
assert (
translate("testing.example_with_variables", {"name": "Alice"})
== "Hello, Alice!"
)
assert translate("testing.example_with_variables", {"name": "Bob"}) == "Hello, Bob!"
def test_looking_up_non_existent_key():
with pytest.raises(LocalizationInvalidKeyError):
translate("testing.an.invalid_key")

299
translations.yaml Normal file
View File

@ -0,0 +1,299 @@
audit_log:
events:
default:
change: '{from} to {to}'
changes: 'Changes:'
details: 'Details:'
header_title: Activity History
base_public:
header_title: JEDI Cloud
login: Log in
title_tag: JEDI Cloud
components:
modal:
close: Close
usa_header:
flag_image_alt: U.S. Flag
official_message: An official website of the United States government
tooltip:
message: |
<p>
<strong>The .mil means its official.</strong><br/>
Federal government websites often end in .gov or .mil. Before sharing sensitive information, make sure youre on a federal government site.
</p><br/>
<p>
<strong>The site is secure.</strong><br>
The <strong>https://</strong> ensures that you are connecting to the official website and that any information you provide is encrypted and transmitted securely.
</p>
title: Heres how you know
footer:
about_link_text: Joint Enterprise Defense Infrastructure
browser_support: JEDI Cloud supported on these web browsers
jedi_help_link_text: JEDI Cloud Help
forms:
ccpo_review:
comment_description: Provide instructions or notes for additional information that is necessary to approve the request here. The requestor may then re-submit the updated request or initiate contact outside of AT-AT if further discussion is required. <strong>This message will be shared with the person making the JEDI request.</strong>.
comment_label: Instructions or comments
email_mao_label: Mission Owner e-mail (optional)
fname_ccpo_label: First Name (optional)
fname_mao_label: First Name (optional)
lname_ccpo_label: Last Name (optional)
lname_mao_label: Last Name (optional)
phone_ext_mao_label: Extension (optional)
phone_mao_label: Mission Owner phone number (optional)
edit_member:
workspace_role_label: Workspace Role
edit_user:
citizenship_description: What is your citizenship status?
date_latest_training_description: |
To complete the training, you can find it in
<a class="icon-link" href="https://iatraining.disa.mil/eta/disa_cac2018/launchPage.htm" target="_blank">
Information Assurance Cyber Awareness Challange
</a> website.
date_latest_training_label: Latest Information Assurance (IA) Training Completion Date
designation_description: What is your designation within the DoD?
designation_label: Designation of Person
email_description: Enter your preferred contact e-mail address
email_label: E-mail Address
first_name_label: First Name
last_name_label: Last Name
phone_number_label: Phone Number
service_branch_description: Which service or organization do you belong to within the DoD?
service_branch_label: Service Branch or Agency
exceptions:
message: Form validation failed.
financial:
ba_code_description: 'BA Code is used to identify the purposes, projects, or types of activities financed by the appropriation fund. <br/><em>It should be two digits, followed by an optional letter.</em>'
ba_code_label: Program Budget Activity (BA) Code
clin_0001_description: 'Review your task order document, the amounts for each CLIN must match exactly here'
clin_0001_label: <dl><dt>CLIN 0001</dt> - <dd>Unclassified IaaS and PaaS Amount</dd></dl>
clin_0003_description: 'Review your task order document, the amounts for each CLIN must match exactly here'
clin_0003_label: <dl><dt>CLIN 0003</dt> - <dd>Unclassified Cloud Support Package</dd></dl>
clin_1001_description: 'Review your task order document, the amounts for each CLIN must match exactly here"'
clin_1001_label: <dl><dt>CLIN 1001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 1</dd></dl>
clin_1003_description: 'Review your task order document, the amounts for each CLIN must match exactly here'
clin_1003_label: <dl><dt>CLIN 1003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 1</dd></dl>
clin_2001_description: 'Review your task order document, the amounts for each CLIN must match exactly here'
clin_2001_label: <dl><dt>CLIN 2001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 2</dd></dl>
clin_2003_description: 'Review your task order document, the amounts for each CLIN must match exactly here'
clin_2003_label: <dl><dt>CLIN 2003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 2</dd></dl>
email_co_label: KO Email
email_cor_label: COR Email
expiration_date_description: Please enter the expiration date for the Task Order
expiration_date_label: Task Order Expiration Date
fname_co_label: KO First Name
fname_cor_label: COR First Name
funding_type_description: What is the source of funding?
funding_type_other_label: 'If other, please specify'
lname_co_label: KO Last Name
lname_cor_label: COR Last Name
number_description: Include the original Task Order number (including the 000X at the end). Do not include any modification numbers. Note that there may be a lag between approving a task order and when it becomes available in our system.
number_label: Task Order Number associated with this request
office_co_label: KO Office
office_cor_label: COR Office
pdf_allowed_description: Only PDF documents can be uploaded.
pdf_label: Upload a copy of your Task Order
pe_id_description: 'PE numbers help the Department of Defense identify which offices'' budgets are contributing towards this resource use. <br/><em>It should be 7 digits followed by 1-3 letters, and should have a zero as the first and third digits.</em>'
pe_id_label: Program Element Number
treasury_code_description: 'Program Treasury Code (or Appropriations Code) identifies resource types. <br/> <em>It should be a four digit or six digit number, optionally prefixed by one or more zeros.</em>'
treasury_code_label: Program Treasury Code
uii_ids_description: 'If you have more than one UII, place each one on a new line.'
uii_ids_label: Unique Item Identifier (UII)s related to your application(s) if you already have them.
internal_comment:
text_description: Add comments or notes for internal CCPO reference and follow-up here. <strong>These comments <em>will not</em> be visible to the person making the JEDI request.</strong>
text_label: CCPO Internal Notes
new_member:
dod_id_label: DOD ID
email_label: Email Address
first_name_label: First Name
last_name_label: Last Name
workspace_role_description: 'The workspace role controls whether a member is permitted to organize a workspace into projects and environments, add members to this workspace, and view billing information.'
workspace_role_label: Workspace Role
new_request:
am_poc_label: I am the Workspace Owner
average_daily_traffic_description: What is the average daily traffic you expect the systems under this cloud contract to use?
average_daily_traffic_gb_description: What is the average daily traffic you expect the systems under this cloud contract to use?
average_daily_traffic_gb_label: Average Daily Traffic (GB)
average_daily_traffic_label: Average Daily Traffic (Number of Requests)
cloud_native_description: Are your software systems being developed cloud native?
data_transfers_description: How much data is being transferred to the cloud?
dod_component_description: Identify the DoD component that is requesting access to the JEDI Cloud
dod_component_label: DoD Component
dodid_poc_label: DoD ID
dollar_value_description: What is your total expected budget for this JEDI Cloud Request?
dollar_value_label: Total Spend
email_poc_label: Email Address
engineering_assessment_description: Have you completed an engineering assessment of your systems for cloud readiness?
estimated_monthly_spend_description: 'Use the <a href="/jedi-csp-calculator" target="_blank" class="icon-link">JEDI CSP Calculator</a> to estimate your <b>monthly</b> cloud resource usage and enter the dollar amount below. Note these estimates are for initial approval only. After the request is approved, you will be asked to provide a valid Task Order number with specific CLIN amounts for cloud services.'
estimated_monthly_spend_label: Estimated Monthly Spend
expected_completion_date_description: When do you expect to complete your migration to the JEDI Cloud?
fname_poc_label: First Name
jedi_migration_description: Are you using the JEDI Cloud to migrate existing systems?
jedi_migration_label: JEDI Migration
jedi_usage_description: Your answer will help us provide tangible examples to DoD leadership how and why commercial cloud resources are accelerating the Department's missions
jedi_usage_label: JEDI Usage
lname_poc_label: Last Name
name_description: This name serves as a reference for your initial request and the associated workspace that will be created once this request is approved. You may edit this name later.
name_label: Name Your Request
name_length_validation_message: Request names must be at least 4 and not more than 100 characters
num_software_systems_description: Estimate the number of software systems that will be supported by this JEDI Cloud access request
num_software_systems_label: Number of Software Systems
number_user_sessions_description: How many user sessions do you expect on these systems each day?
organization_providing_assistance_description: 'If you are receiving migration assistance, what is the type of organization providing assistance?'
rationalization_software_systems_description: Have you completed a “rationalization” of your software systems to move to the cloud?
reviewed_label: I have reviewed this data and it is correct.
start_date_date_range_validation_message: Must be a date in the future.
start_date_label: When do you expect to start using the JEDI Cloud (not for billing purposes)?
technical_support_team_description: Are you working with a technical support team experienced in cloud migrations?
project:
description_label: Description
environment_names_label: Environment Name
environment_names_required_validation_message: Provide at least one environment name.
environment_names_unique_validation_message: Environment names must be unique.
name_label: Project Name
validators:
is_number_message: Please enter a valid number.
list_item_required_message: Please provide at least one.
list_items_unique_message: Items must be unique
name_message: 'This field accepts letters, numbers, commas, apostrophes, hyphens, and periods.'
phone_number_message: Please enter a valid 5 or 10 digit phone number.
workspace:
name_label: Workspace Name
name_length_validation_message: Workspace names must be at least 4 and not more than 50 characters
fragments:
edit_project_form:
existing_project_title: 'Edit {project_name} project'
explain: 'AT-AT allows you to organize your workspace into multiple projects, each of which may have environments.'
new_project_title: Add a new project
edit_user_form:
date_last_training_tooltip: When was the last time you completed the IA training? <br> Information Assurance (IA) training is an important step in cyber awareness.
save_details_button: Save Details
pending_ccpo_acceptance_alert:
learn_more_link_text: Learn more about the JEDI Cloud Task Order and the Financial Verification process.
paragraph_1: The CCPO will review and respond to your request in 3 business days. Youll be notified via email or phone. Please note if your request is for over $1M of JEDI cloud resources it will require a manual review by the CCPO.
paragraph_2: 'While your request is being reviewed, your next step is to create a Task Order (TO) associated with the JEDI Cloud. Please contact a Contracting Officer (KO), Contracting Officer Representative (COR), or a Financial Manager to help with this step.'
pending_ccpo_approval_modal:
paragraph_1: The CCPO will review and respond to your Financial Verification submission in 3 business days. You will be notified via email or phone.
paragraph_2: Once the financial verification is approved you will be invited to create your JEDI Workspace and set-up your projects. Click here for more details.
pending_financial_verification:
learn_more_link_text: Learn more about the JEDI Cloud Task Order and the Financial Verification process.
paragraph_1: 'The next step is to create a Task Order associated with JEDI Cloud. Please contact a Contracting Officer (KO), Contracting Officer Representative (COR), or a Financial Manager to help with this step.'
paragraph_2: 'Once the Task Order has been created, you will be asked to provide details about the task order in the Financial Verification step.'
login:
ccpo_logo_alt_text: Cloud Computing Program Office Logo
certificate_selection:
learn_more: Learn more
message: 'When you are prompted to select a certificate, please select E-mail Certificate from the provided choices.'
title: Certificate Selection
h1_title: Access the JEDI Cloud, !!!@#$%%**
login_button: Sign in with CAC
title_tag: Sign in | JEDI Cloud
navigation:
topbar:
jedi_cloud_link_text: JEDI Cloud
logout_link_title: Log out of JEDI Cloud
named_workspace: 'Workspace {workspace}'
no_other_active_workspaces: You have no other active JEDI workspaces.
other_active_workspaces: Other Active Workspaces
request_workspace_link_text: Request a new JEDI Workspace
workspace_navigation:
add_new_member_label: Add New Member
add_new_project_label: Add New Project
budget_report: Budget Report
members: Members
projects: Projects
workspace_settings: Workspace Settings
requests:
_new:
new_request: New Request
save_and_continue: Save & Continue
approval:
add_comment: Add a comment
approve_comments_or_notes_description: Provide any comments or notes regarding the approval of this request. <strong>This message will be shared with the person making the JEDI request.</strong>
approve_comments_or_notes_label: Approval comments or notes
authorizing_officials_paragraph: Provide the name of the key officials for both parties that have authorized this request to move forward. <strong>This section is not visible to the person making the request. It is only viewable by CCPO staff.</strong>
authorizing_officials_title: Authorizing Officials
ccpo_approval_on_behalf_of: 'CCPO approval on behalf of:'
ccpo_authorizing_official_title: CCPO Authorizing Official
ccpo_internal_comments: CCPO Internal Comments
ccpo_review_activity: CCPO Review Activity
mission_authorizing_official_title: Mission Authorizing Official
mission_owner_approval_on_behalf_of: 'Mission Owner approval on behalf of:'
no_ccpo_approval_request_changes: No CCPO approvals or request changes have been recorded yet.
no_ccpo_comments: No CCPO comments have been recorded yet.
ready_for_approval: Ready for approval
request_revisions: Request revisions
request_title: 'Request: {displayname}'
review_request: Review this Request
revision_instructions_or_notes_label: Revision instructions or notes
save_notes: Save Notes
financial_verification:
contracting_officer_information_title: Contracting Officer (KO) Information
contracting_officer_representative_information_title: Contracting Officer Representative (COR) Information
draft_saved: Draft saved
enter_task_order_manually_link_text: Enter Task Order information manually
expiration_date_placeholder: Please enter the expiration date for the task order only and do not include options that you may choose to exercise in the future.
financial_verification_title: Financial Verification
manually_enter_task_information_description: 'Additional fields are displayed below, where you can manually enter financial information as documented in your Task Order.'
manually_enter_task_information_help_label: Learn more about the JEDI Cloud Task Order and the Financial Verification process.
manually_enter_task_information_label: Manually enter Task Order information
number_placeholder: A Contracting Officer will likely be the best source for this number.
pending_financial_verification: Pending Financial Verification
permissions_paragraph: '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.'
request_title: 'Request: {displayname}'
some_errors_label: There were some errors
task_order_not_found_eda_description: 'We could not find your Task Order in our system of record, EDA. Please confirm that you have entered it correctly.'
task_order_not_found_eda_label: Task Order not found in EDA
uui_ids_placeholder: A Unique Item Identifer is a unique code that helps the Department of Defense track and report on where and how digital assets are stored. <br>Not all applications have an existing UII number assigned.
index:
action_required: Action Required
all_filter: All
approved_requests: Approved Requests
filter_by_dod_component: Filter by DOD Component
filter_by_status: Filter by status
filter_requests_by_dod_component: Filter requests by DOD component
filter_requests_by_status_label: Filter requests by status
financial_verification_submitted_title: Financial Verification submitted!
no_requests_found: No requests found.
no_workspaces_action_label: Create a new JEDI Cloud Request
no_workspaces_label: You currently have no JEDI Cloud workspaces.
no_workspaces_sub_message: A JEDI Cloud Workspace is where you manage your projects and control user access to those projects.
pending_ccpo_action: Pending CCPO Action
request_submitted_title: Request submitted!
requests_in_progress: Requests in progress
search_button_text: Search
search_by_name: Search requests by name
try_different_search: Please try a different search.
review_menu:
financial_verification_information_link_text: Financial Verification Information
request_information_link_text: Request Information
screen-1:
additional_plan_details_title: Please provide additional details regarding your planned usage.
approximate_annual_spend_paragraph: |
<p>
So this means you are spending approximately
<span class="label label--info">!{{ annualSpendStr }}</span>
annually
</p>
average_daily_traffic_gb_tooltip: GB uploaded is the gigabyte amount of data traffic that is being transferred to your systems
average_daily_traffic_tooltip: Requests are the client-to-server network traffic that is being transferred to your systems
cloud_native_tooltip: 'Cloud native is architecting and designing your application to use all the benefits of the commercial cloud. Specifically, designing applications so that they are decoupled from a physical resource.'
cloud_readiness_title_text: Cloud Readiness
dollar_value_tooltip: You may specify a different Total Spend amount to cover other JEDI Cloud services that the JEDI Cloud cost calculator was not able to estimate. Examples may include support packages from the cloud service provider.
engineering_assessment_tooltip: An engineering assessment is an evaluation to convert your application architecture from on-premises to using the commercial cloud
estimated_monthly_spend_tooltip: Refer to financial verification step help docs
financial_usage_title: Financial Usage
form_instructions: |
<p>Wed like to know a little about how you plan to use JEDI Cloud services to process your request. Please answer the following questions to the best of your ability. Note that the CCPO does not directly help with migrating systems to JEDI Cloud. These questions are for learning about your cloud readiness and financial usage of the JEDI Cloud; your estimates will not be used for any department level reporting.</p>
<p><em>All fields are required, unless specified optional.</em></p>
general_title_text: General
jedi_migration_tooltip: 'Cloud migration is the process of moving data, applications or other business elements from an organization''s onsite computers/data centers to the cloud, or moving them from one cloud environment to another.'
jedi_usage_placeholder: Briefly describe how you are expecting to use the JEDI Cloud. e.g. We are migrating XYZ application to the cloud so that...
num_software_systems_tooltip: 'A software system can be any code that you plan to host on cloud infrastructure. For example, it could be a custom-developed web application, or a large ERP system.'
questions_title_text: Questions related to JEDI Cloud migration
rationalization_software_systems_tooltip: Rationalization is the DoD process to determine whether the application should move to the cloud.
testing:
example_string: Hello World
example_with_variables: 'Hello, {name}!'
nested:
example: Hello nested example