From 60ad0d1844492051c9004cc2fb3c80e022420c45 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 26 Nov 2019 10:24:47 -0500 Subject: [PATCH 1/5] Add datetime.now() as a reports view variable This mocks the datetime of data retrieval from the CSP --- atst/routes/portfolios/index.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 ) From fa9986f9bf7baf631f323073b00f95737bd19062 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 26 Nov 2019 10:28:13 -0500 Subject: [PATCH 2/5] Styling for Obligated Funding section of reports --- styles/elements/_typography.scss | 4 + styles/sections/_reports.scss | 300 +++--------------- .../portfolios/reports/obligated_funds.html | 51 +-- 3 files changed, 85 insertions(+), 270 deletions(-) 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..2d8708ba 100644 --- a/styles/sections/_reports.scss +++ b/styles/sections/_reports.scss @@ -1,264 +1,62 @@ -.funding-summary-row { - @include media($medium-screen) { - @include grid-row; +.reporting-section-header { + display: flex; + align-items: baseline; + &__header { + margin-right: $gap; + } + &__subheader { + @include small-copy; + } +} - flex-wrap: wrap; +.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; } - &__col { - hr { - margin: (2 * $gap) 0; - } + &__header { + margin: 0; + } - @include media($medium-screen) { - @include grid-pad; + &__subheader { + @include small-copy; + margin: 0; + } - flex-grow: 1; + &__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%; + + &-values { display: flex; - flex-direction: row; - flex-basis: 50%; - - @include ie-only { - max-width: 50%; - } - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - } - } - - align-items: stretch; - - .panel { - padding: $gap * 2; - 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 { - 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; - } - } - } - } - } -} - -.spend-table__month-select { - margin: 0; - flex: 1; -} - -table { - .spend-table__portfolio { - th, - td { - font-weight: bold; } } - th, - td { - &.previous-month { - color: $color-gray; + &__meta { + &--remaining { + margin-left: auto; + text-align: right; } - - &.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); - } - } + &-header { + @include small-copy; + margin-bottom: 0; + } + &-value { + margin-bottom: 0; + line-height: 1.2; } } } diff --git a/templates/portfolios/reports/obligated_funds.html b/templates/portfolios/reports/obligated_funds.html index 04ba4883..a774c0f9 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"]) %} +
+

+ {{ JEDI_clin }} +

+

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 %}
From 51f1261db016efa0709ef6586c27d7f279a667ac Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 26 Nov 2019 11:17:25 -0500 Subject: [PATCH 3/5] Order CLINs on reporting page and refactor labels In order to more easily sort JEDI Clins for the obligated funds section, the JEDI CLIN enum values were used in the output dict instead of their verbose labels. And in order to bring the labels in line with designs, the JEDI CLIN labels were DRYed up in the translations file, which required making small changes in a few other places across the project. --- atst/domain/csp/reports.py | 9 ++++++--- atst/forms/data.py | 8 ++++---- templates/components/clin_fields.html | 8 ++++---- templates/portfolios/reports/obligated_funds.html | 2 +- translations.yaml | 12 ++++-------- 5 files changed, 19 insertions(+), 20 deletions(-) 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/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/portfolios/reports/obligated_funds.html b/templates/portfolios/reports/obligated_funds.html index a774c0f9..c8d6ff22 100644 --- a/templates/portfolios/reports/obligated_funds.html +++ b/templates/portfolios/reports/obligated_funds.html @@ -11,7 +11,7 @@ {% set remaining_funds = (funds["obligated_funds"] - funds["expended_funds"]) %}

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

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

diff --git a/translations.yaml b/translations.yaml index ea0ddca9..6bae67bf 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 @@ -519,10 +515,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}!' From eac41d140c90f7ff0788b8fe75d3ed6b778801fe Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 26 Nov 2019 16:15:26 -0500 Subject: [PATCH 4/5] Add kwarg to tooltip macro to allow extra classes --- templates/components/tooltip.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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="") %} - From 33711c96050c6c1928dbbf57e1cdb0fc77a700a5 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 26 Nov 2019 16:16:05 -0500 Subject: [PATCH 5/5] Styling for portfolio summary section of reporting --- styles/sections/_reports.scss | 132 +++++++++++------- templates/portfolios/reports/index.html | 1 + .../portfolios/reports/portfolio_summary.html | 38 ++--- translations.yaml | 1 + 4 files changed, 101 insertions(+), 71 deletions(-) diff --git a/styles/sections/_reports.scss b/styles/sections/_reports.scss index 2d8708ba..f80a7750 100644 --- a/styles/sections/_reports.scss +++ b/styles/sections/_reports.scss @@ -1,62 +1,90 @@ -.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; +.portfolio-reports { + .estimate-warning { + margin-top: $gap * 3; margin-bottom: $gap * 3; - padding-bottom: $gap * 3; - } - > div:nth-last-child(2) { - margin-bottom: 0; } - &__header { - margin: 0; - } - - &__subheader { - @include small-copy; - margin: 0; - } - - &__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%; - - &-values { - display: flex; + .reporting-section-header { + display: flex; + align-items: baseline; + &__header { + margin-right: $gap; } - } - - &__meta { - &--remaining { - margin-left: auto; - text-align: right; - } - &-header { + &__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; } - &-value { - margin-bottom: 0; - line-height: 1.2; + + &__header { + margin: 0; + } + + &__subheader { + @include small-copy; + margin: 0; + } + + &__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%; + + &-values { + display: flex; + } + } + + &__meta { + &--remaining { + margin-left: auto; + text-align: right; + } + &-header { + @include small-copy; + margin-bottom: 0; + } + &-value { + margin-bottom: 0; + line-height: 1.2; + } + } + } + + .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; + } + &__header { + margin: 0; + &-icon { + margin: 0; + padding: 0; + } + } + &__value { + font-size: $lead-font-size; } } } 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/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 6bae67bf..387aecec 100644 --- a/translations.yaml +++ b/translations.yaml @@ -446,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: