diff --git a/atst/domain/csp/reports.py b/atst/domain/csp/reports.py index 683c1139..2d42fede 100644 --- a/atst/domain/csp/reports.py +++ b/atst/domain/csp/reports.py @@ -1,7 +1,7 @@ from itertools import groupby -from atst.utils.localization import translate import pendulum from decimal import Decimal +from collections import OrderedDict class ReportingInterface: @@ -295,13 +295,16 @@ class MockReportingProvider(ReportingInterface): portfolio.active_clins, lambda clin: clin.jedi_clin_type ): obligated_funds = sum(clin.obligated_amount for clin in clins) - return_dict[translate(f"JEDICLINType.{jedi_clin.value}")] = { + return_dict[jedi_clin.value] = { "obligated_funds": obligated_funds, "expended_funds": ( obligated_funds * Decimal(self.MOCK_PERCENT_EXPENDED_FUNDS) ), } - return return_dict + return OrderedDict( + # 0 index for dict item, -1 for last digit of 4 digit CLIN, e.g. 0001 + sorted(return_dict.items(), key=lambda clin: clin[0][-1]) + ) return {} def get_expired_task_orders(self, portfolio): diff --git a/atst/forms/data.py b/atst/forms/data.py index 9bf88cd7..7b1b4a40 100644 --- a/atst/forms/data.py +++ b/atst/forms/data.py @@ -117,8 +117,8 @@ ENV_ROLES = [(role.value, role.value) for role in CSPRole] + [ ] JEDI_CLIN_TYPES = [ - ("JEDI_CLIN_1", translate("forms.task_order.clin_01_label")), - ("JEDI_CLIN_2", translate("forms.task_order.clin_02_label")), - ("JEDI_CLIN_3", translate("forms.task_order.clin_03_label")), - ("JEDI_CLIN_4", translate("forms.task_order.clin_04_label")), + ("JEDI_CLIN_1", translate("JEDICLINType.JEDI_CLIN_1")), + ("JEDI_CLIN_2", translate("JEDICLINType.JEDI_CLIN_2")), + ("JEDI_CLIN_3", translate("JEDICLINType.JEDI_CLIN_3")), + ("JEDI_CLIN_4", translate("JEDICLINType.JEDI_CLIN_4")), ] diff --git a/atst/routes/portfolios/index.py b/atst/routes/portfolios/index.py index 336cd2e6..06a4e783 100644 --- a/atst/routes/portfolios/index.py +++ b/atst/routes/portfolios/index.py @@ -1,4 +1,4 @@ -from datetime import date, timedelta +from datetime import date, datetime, timedelta from flask import redirect, render_template, url_for, request as http_request, g @@ -64,6 +64,7 @@ def reports(portfolio_id): monthly_totals=Reports.monthly_totals(portfolio), current_month=current_month, prev_month=prev_month, + now=datetime.now(), # mocked datetime of reporting data retrival ) diff --git a/styles/elements/_typography.scss b/styles/elements/_typography.scss index 1ae28d9f..48784659 100644 --- a/styles/elements/_typography.scss +++ b/styles/elements/_typography.scss @@ -102,3 +102,7 @@ dl { font-weight: $font-bold; color: $color-black; } + +@mixin small-copy { + font-size: $small-font-size; +} diff --git a/styles/sections/_reports.scss b/styles/sections/_reports.scss index a53e2842..f80a7750 100644 --- a/styles/sections/_reports.scss +++ b/styles/sections/_reports.scss @@ -1,264 +1,90 @@ -.funding-summary-row { - @include media($medium-screen) { - @include grid-row; - - flex-wrap: wrap; +.portfolio-reports { + .estimate-warning { + margin-top: $gap * 3; + margin-bottom: $gap * 3; } - &__col { - hr { - margin: (2 * $gap) 0; + .reporting-section-header { + display: flex; + align-items: baseline; + &__header { + margin-right: $gap; + } + &__subheader { + @include small-copy; + } + } + + .jedi-clin-funding { + padding-top: $gap * 3; + padding-bottom: $gap * 3; + + &__clin-wrapper { + border-bottom: 1px solid $color-gray-light; + margin-bottom: $gap * 3; + padding-bottom: $gap * 3; + } + > div:nth-last-child(2) { + margin-bottom: 0; } - @include media($medium-screen) { - @include grid-pad; - - flex-grow: 1; - display: flex; - flex-direction: row; - flex-basis: 50%; - - @include ie-only { - max-width: 50%; - } - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - } + &__header { + margin: 0; } - align-items: stretch; + &__subheader { + @include small-copy; + margin: 0; + } - .panel { - padding: $gap * 2; + &__meter { + margin: 10px 0; + -moz-transform: scale(-1, 1); + -webkit-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); width: 100%; - @include ie-only { - max-width: 100%; - } - - .subheading { - @include h4; - - margin: 0 $gap (2 * $gap) 0; - -ms-flex-negative: 1; - } - - // Spending Summary - // =============================== - &.spend-summary { + &-values { display: flex; - flex-direction: column; - justify-content: space-between; - - .row { - justify-content: space-between; - - @include ie-only { - max-width: 100%; - flex-wrap: wrap; - } - } - - &__budget { - @include ie-only { - margin: $gap 0 0 0; - } - } - - dl { - text-align: left; - margin: 0 0 ($gap / 2) 0; - - @include ie-only { - text-align: left; - } - - dt { - text-transform: uppercase; - color: $color-gray-light; - margin-right: $gap; - font-weight: bold; - font-size: $small-font-size; - } - } - - meter { - width: 100%; - height: 3rem; - margin: ($gap * 2) 0 0; - } - - &__spent { - margin: (2 * $gap) 0; - display: flex; - flex-direction: column; - justify-content: flex-end; - - dt { - letter-spacing: 0.47px; - } - } } + } - // Task Order Summary - // =============================== - &.to-summary { - .icon-link { - font-weight: $font-normal; - } - - .subheading { - margin-bottom: 0; - } - - .to-summary__heading { - @include h4; - - margin: 0 $gap 0 0; - } - - .to-summary__to-number { - margin: 0; - - dd { - &::before { - content: "#"; - color: $color-gray; - margin-right: $gap; - } - } - - @include media($xlarge-screen) { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - - .to-summary__to { - margin: 0 $gap 0 0; - } - - .to-summary__expiration { - text-align: right; - flex-grow: 1; - - dl { - margin: 0 0 0 $gap; - - dd, - dt { - display: inline; - } - } - } - } - } - - .to-summary__expiration { - dl { - text-align: right; - margin-top: -2 * $gap; - - dd, - dt { - display: inline; - } - - dt { - font-size: $small-font-size; - text-transform: uppercase; - font-weight: $font-bold; - color: $color-gray-light; - } - - dd.ending-soon { - font-size: $h2-font-size; - white-space: nowrap; - - .icon { - @include icon-size(28); - } - } - } - - .icon-link { - margin: 0 (-$gap); - } - } - - .to-summary__co { - margin: ($gap * 2) 0 0 0; - - @include media($xlarge-screen) { - margin: 0; - } - } + &__meta { + &--remaining { + margin-left: auto; + text-align: right; + } + &-header { + @include small-copy; + margin-bottom: 0; + } + &-value { + margin-bottom: 0; + line-height: 1.2; } } } -} -.spend-table__month-select { - margin: 0; - flex: 1; -} - -table { - .spend-table__portfolio { - th, - td { - font-weight: bold; + .reporting-summary-item { + border-right: 1px solid $color-gray-light; + margin-right: $gap * 3; + padding-right: $gap * 3; + &:last-child { + border-right: none; + margin-right: 0; + padding-right: 0; } - } - - th, - td { - &.previous-month { - color: $color-gray; + &__header { + margin: 0; + &-icon { + margin: 0; + padding: 0; + } } - - &.meter-cell { - padding-left: 0; - position: relative; - min-width: 4rem; - - @include media($medium-screen) { - min-width: 12rem; - } - - meter { - width: 100%; - height: 3rem; - background: $color-white; - display: none; - - @include media($medium-screen) { - display: block; - } - - &::-webkit-meter-bar { - background: $color-white; - } - } - - .spend-table__meter-value { - @include h5; - - @include media($medium-screen) { - display: block; - color: $color-white; - background-color: rgba($color-blue, 0.65); - border-radius: $gap / 2; - position: absolute; - top: 2.3rem; - left: $gap / 2; - padding: 0 ($gap / 2); - } - } + &__value { + font-size: $lead-font-size; } } } diff --git a/templates/components/clin_fields.html b/templates/components/clin_fields.html index 6d79dc08..1117b89c 100644 --- a/templates/components/clin_fields.html +++ b/templates/components/clin_fields.html @@ -92,10 +92,10 @@ diff --git a/templates/components/tooltip.html b/templates/components/tooltip.html index 48a09e09..08a6f92f 100644 --- a/templates/components/tooltip.html +++ b/templates/components/tooltip.html @@ -1,8 +1,8 @@ {% from "components/icon.html" import Icon %} -{% macro Tooltip(message,title='Help') -%} +{% macro Tooltip(message,title='Help', classes="") %} - diff --git a/templates/portfolios/reports/index.html b/templates/portfolios/reports/index.html index 7de02212..8f2fad93 100644 --- a/templates/portfolios/reports/index.html +++ b/templates/portfolios/reports/index.html @@ -6,6 +6,7 @@ {% block portfolio_content %} {{ StickyCTA("Reports") }}
+

{{ "portfolios.reports.estimate_warning" | translate }}

{% include "portfolios/reports/portfolio_summary.html" %}
{% include "portfolios/reports/obligated_funds.html" %} diff --git a/templates/portfolios/reports/obligated_funds.html b/templates/portfolios/reports/obligated_funds.html index 04ba4883..c8d6ff22 100644 --- a/templates/portfolios/reports/obligated_funds.html +++ b/templates/portfolios/reports/obligated_funds.html @@ -1,29 +1,42 @@ +{% from "components/icon.html" import Icon %}
-
-

Current Obligated funds

- As of DATE +
+

Current Obligated funds

+ As of {{ now | formattedDate(formatter="%B %d, %Y at %H:%M") }}
-
-
- {% for JEDI_clin, funds in current_obligated_funds.items() %} - {{ JEDI_clin }} - -
+
+ {% for JEDI_clin, funds in current_obligated_funds.items() %} + {% set remaining_funds = (funds["obligated_funds"] - funds["expended_funds"]) %} +
+

+ {{ "JEDICLINType.{}".format(JEDI_clin) | translate }} +

+

Total obligated amount: {{ funds["obligated_funds"] | dollars }}

+ +
-
-

Remaining funds:

-

{{ (funds["obligated_funds"] - funds["expended_funds"]) | dollars }}

+
+
+

Funds expended:

+

{{ funds["expended_funds"] | dollars }}

+
+
+

Remaining funds:

+

{{ remaining_funds | dollars }}

+
+
-
-

Funds expended to date:

-

{{ funds["expended_funds"] | dollars }}

-
-
- {% endfor %} + {% endfor %} +
+

+ Active Task Orders +

{% for task_order in portfolio.active_task_orders %} - {{ task_order.number }} + + {{ task_order.number }} {{ Icon("caret_right", classes="icon--tiny icon--blue" ) }} + {% endfor %}
diff --git a/templates/portfolios/reports/portfolio_summary.html b/templates/portfolios/reports/portfolio_summary.html index e29e96be..55922812 100644 --- a/templates/portfolios/reports/portfolio_summary.html +++ b/templates/portfolios/reports/portfolio_summary.html @@ -3,34 +3,34 @@
-
-

- Total Portfolio Value - {{Tooltip(("common.lorem" | translate), title="")}} -

-

{{ total_portfolio_value | dollars }}

+
+
+ Total Portfolio Value + {{Tooltip(("common.lorem" | translate), title="", classes="reporting-summary-item__header-icon")}} +
+

{{ total_portfolio_value | dollars }}

-
-

- Funding Duration - {{Tooltip(("common.lorem" | translate), title="")}} -

+
+
+ Funding Duration + {{Tooltip(("common.lorem" | translate), title="", classes="reporting-summary-item__header-icon")}} +
{% set earliest_pop_start_date, latest_pop_end_date = portfolio.funding_duration %} {% if earliest_pop_start_date and latest_pop_end_date %} -

+

{{ earliest_pop_start_date | formattedDate(formatter="%B %d, %Y") }} - {{ latest_pop_end_date | formattedDate(formatter="%B %d, %Y") }}

{% else %} -

-

+

-

{% endif %}
-
-

- Days Remaining - {{Tooltip(("common.lorem" | translate), title="")}} -

-

{{ portfolio.days_to_funding_expiration }} days

+
+
+ Days Remaining + {{Tooltip(("common.lorem" | translate), title="", classes="reporting-summary-item__header-icon")}} +
+

{{ portfolio.days_to_funding_expiration }} days

\ No newline at end of file diff --git a/translations.yaml b/translations.yaml index ea0ddca9..387aecec 100644 --- a/translations.yaml +++ b/translations.yaml @@ -182,10 +182,6 @@ forms: none: Not planning to migrate any applications not_sure: Not sure on_premise: 'Yes, migrating from an on-premise data center' - clin_01_label: 'IaaS/PaaS (IDIQ CLIN 0001)' - clin_02_label: 'IDIQ CLIN 0002' - clin_03_label: 'IDIQ CLIN 0003' - clin_04_label: 'IDIQ CLIN 0004' complexity: conus: CONUS access data_analytics: Data analytics @@ -450,6 +446,7 @@ portfolios: portfolio_mgmt: Portfolio management reporting: Reporting reports: + estimate_warning: Reports displayed in JEDI are estimates and not a system of record. empty_state: message: Nothing to report. sub_message: @@ -519,10 +516,10 @@ task_orders: sign: digital_signature_description: I acknowledge that the uploaded task order contains the required KO signature. JEDICLINType: - JEDI_CLIN_1: 'Unclassified IaaS and PaaS (IDIQ CLIN 0001)' - JEDI_CLIN_2: 'Classified IaaS and PaaS (IDIQ CLIN 0002)' - JEDI_CLIN_3: 'Unclassified Cloud Support Package (IDIQ CLIN 0003)' - JEDI_CLIN_4: 'Classified Cloud Support Package (IDIQ CLIN 0004)' + JEDI_CLIN_1: 'IDIQ CLIN 0001 Unclassified IaaS/PaaS' + JEDI_CLIN_2: 'IDIQ CLIN 0002 Classified IaaS/PaaS' + JEDI_CLIN_3: 'IDIQ CLIN 0003 Unclassified Cloud Support Package' + JEDI_CLIN_4: 'IDIQ CLIN 0004 Classified Cloud Support Package' testing: example_string: Hello World example_with_variables: 'Hello, {name}!'