From ddafa25f2220471dbd687282fbd094dcf226a649 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Tue, 22 Jan 2019 15:29:39 -0500 Subject: [PATCH 1/3] Add page that shows status of TO officer invitations --- atst/routes/portfolios/task_orders.py | 13 +++ styles/sections/_task_order.scss | 81 ++++++++++++++ .../portfolios/task_orders/invitations.html | 102 ++++++++++++++++++ templates/portfolios/task_orders/show.html | 2 +- translations.yaml | 17 +++ 5 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 templates/portfolios/task_orders/invitations.html diff --git a/atst/routes/portfolios/task_orders.py b/atst/routes/portfolios/task_orders.py index b8e76ef3..8bcb4715 100644 --- a/atst/routes/portfolios/task_orders.py +++ b/atst/routes/portfolios/task_orders.py @@ -61,3 +61,16 @@ def view_task_order(portfolio_id, task_order_id): return render_template( "portfolios/task_orders/show.html", portfolio=portfolio, task_order=task_order ) + + +@portfolios_bp.route( + "/portfolios//task_order//invitations" +) +def task_order_invitations(portfolio_id, task_order_id): + portfolio = Portfolios.get(g.current_user, portfolio_id) + task_order = TaskOrders.get(g.current_user, task_order_id) + return render_template( + "portfolios/task_orders/invitations.html", + portfolio=portfolio, + task_order=task_order, + ) diff --git a/styles/sections/_task_order.scss b/styles/sections/_task_order.scss index 440ee0a2..b63d064f 100644 --- a/styles/sections/_task_order.scss +++ b/styles/sections/_task_order.scss @@ -267,3 +267,84 @@ } } } + +.task-order-invitations { + .task-order-invitations__heading { + margin-bottom: 0; + + &.subheading .h2 { + color: $color-gray; + } + } + + .officer { + margin-top: 0; + margin-left: 0; + margin-right: 0; + margin-bottom: $gap; + padding-bottom: 4 * $gap; + + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: $color-gray-light; + + &:last-child { + border-bottom-width: 0; + } + + h2 { + color: $color-gray; + } + + .officer__info { + .officer__info--name { + font-weight: bold; + } + + p { + margin: .5rem 0; + } + + .officer__info--name { + margin-right: 2 * $gap; + } + + .officer__info--status { + font-weight: bold; + + &.invited { + color: $color-green; + .icon { + @include icon-color($color-green); + } + } + + &.uninvited { + color: $color-red; + .icon { + @include icon-color($color-red); + } + } + } + } + + .officer__actions { + margin-left: -2 * $gap; + + button { + margin-left: 2 * $gap; + } + + .icon-link { + margin: 0 $gap; + } + + .remove { + color: $color-red; + .icon { + @include icon-color($color-red); + } + } + } + } +} diff --git a/templates/portfolios/task_orders/invitations.html b/templates/portfolios/task_orders/invitations.html new file mode 100644 index 00000000..b28c83fa --- /dev/null +++ b/templates/portfolios/task_orders/invitations.html @@ -0,0 +1,102 @@ +{% extends "portfolios/base.html" %} + +{% from "components/icon.html" import Icon %} + +{% macro OfficerInfo(task_order, officer_type) %} +
+

{{ ("task_orders.invitations." + officer_type + ".title") | translate }}

+

{{ ("task_orders.invitations." + officer_type + ".description") | translate }}

+ + {% set prefix = { "contracting_officer": "ko", "contracting_officer_representative": "cor", "security_officer": "so" }[officer_type] %} + {% set first_name = task_order[prefix + "_first_name"] %} + {% set last_name = task_order[prefix + "_last_name"] %} + {% set email = task_order[prefix + "_email"] %} + {% set phone_number = task_order[prefix + "_phone_number"] %} + {% set dod_id = task_order[prefix + "_dod_id"] %} + + {% if task_order[officer_type] %} +
+
+
{{ first_name }} {{ last_name }}
+
+ {{ Icon("ok", classes="invited") }} + Invited +
+
+ +

{{ phone_number | usPhone }}

+

{{ "task_orders.invitations.dod_id_label" | translate}}: {{ dod_id }}

+
+ + {% elif first_name and last_name %} +
+
+
{{ first_name }} {{ last_name }}
+
+ {{ Icon("alert", classes="uninvited") }} + Not Invited +
+
+ +

{{ phone_number | usPhone }}

+
+
+ + {{ Icon("edit") }} + Update + + + {{ Icon("trash") }} + Remove + + +
+ {% else %} +
+
+ {{ Icon("alert", classes="uninvited") }} + Not specified +
+
+
+ +
+ {% endif %} +
+{% endmacro %} + +{% block portfolio_content %} +
+ {% include "fragments/flash.html" %} + +
+
+

+
Edit Task Order
+ Oversight +

+
+ + {% for officer in ["contracting_officer", "contracting_officer_representative", "security_officer"] %} + {{ OfficerInfo(task_order, officer) }} + {% endfor %} +
+
+{% endblock %} diff --git a/templates/portfolios/task_orders/show.html b/templates/portfolios/task_orders/show.html index 11e45c4d..45cafdfa 100644 --- a/templates/portfolios/task_orders/show.html +++ b/templates/portfolios/task_orders/show.html @@ -153,7 +153,7 @@ {{ InvitationStatus('Contracting Officer Representative', task_order.contracting_officer_representative) }} {{ InvitationStatus('IA Security Officer', officer=task_order.security_officer) }} - + {{ Icon("edit") }} manage invitations diff --git a/translations.yaml b/translations.yaml index 2cf3d4e7..8a188943 100644 --- a/translations.yaml +++ b/translations.yaml @@ -438,6 +438,23 @@ task_orders: invited: Invited not_invited: Not Yet Invited not_uploaded: Not Uploaded + invitations: + dod_id_label: DoD ID + contracting_officer: + title: Contracting Officer (KO) Information + description: You'll need a signature from your KO. You might want to work with your program Financial Manager to get your TO documents moved in the right direction. + add_button_text: Add / Invite KO + invite_button_text: Invite KO + contracting_officer_representative: + title: Contracting Officer Representative (COR) Information + description: Your COR may assist in submitting the Task Order documents within their official system of record. + add_button_text: Add / Invite COR + invite_button_text: Invite COR + security_officer: + title: IA Security Officer Information + description: Your Security Officer will need to answer some security configuration questions in order to generate a DD-254 document, then electronically sign. + add_button_text: Add / Invite Security Officer + invite_button_text: Invite Security Officer testing: example_string: Hello World example_with_variables: 'Hello, {name}!' From 038651608920bc5bd627388410004afadcaf4d95 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Wed, 23 Jan 2019 15:55:31 -0500 Subject: [PATCH 2/3] Add a happy little test for viewing invitations --- tests/routes/portfolios/test_task_orders.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/routes/portfolios/test_task_orders.py b/tests/routes/portfolios/test_task_orders.py index f1bb3425..6bebd3aa 100644 --- a/tests/routes/portfolios/test_task_orders.py +++ b/tests/routes/portfolios/test_task_orders.py @@ -86,3 +86,17 @@ def test_ko_can_view_task_order(client, user_session): ) ) assert response.status_code == 200 + + +def test_can_view_task_order_invitations(client, user_session): + portfolio = PortfolioFactory.create() + user_session(portfolio.owner) + task_order = TaskOrderFactory.create(portfolio=portfolio) + response = client.get( + url_for( + "portfolios.task_order_invitations", + portfolio_id=portfolio.id, + task_order_id=task_order.id, + ) + ) + assert response.status_code == 200 From 681361cbd18d65e5ea50e457569d5c5e6ecc9682 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Thu, 24 Jan 2019 10:13:46 -0500 Subject: [PATCH 3/3] Refactor link into macro --- .../portfolios/task_orders/invitations.html | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/templates/portfolios/task_orders/invitations.html b/templates/portfolios/task_orders/invitations.html index b28c83fa..0ebad204 100644 --- a/templates/portfolios/task_orders/invitations.html +++ b/templates/portfolios/task_orders/invitations.html @@ -2,6 +2,13 @@ {% from "components/icon.html" import Icon %} +{% macro Link(text, icon_name, url='#', classes='') %} + + {{ Icon(icon_name) }} + {{ text }} + +{% endmacro %} + {% macro OfficerInfo(task_order, officer_type) %}

{{ ("task_orders.invitations." + officer_type + ".title") | translate }}

@@ -28,18 +35,9 @@

{{ "task_orders.invitations.dod_id_label" | translate}}: {{ dod_id }}

- - {{ Icon("edit") }} - Update - - - {{ Icon("avatar") }} - Resend Invitation - - - {{ Icon("trash") }} - Remove - + {{ Link("Update", "edit") }} + {{ Link("Resend Invitation", "avatar") }} + {{ Link("Remove", "trash", classes="remove") }}
{% elif first_name and last_name %}
@@ -54,14 +52,8 @@

{{ phone_number | usPhone }}

- - {{ Icon("edit") }} - Update - - - {{ Icon("trash") }} - Remove - + {{ Link("Update", "edit") }} + {{ Link("Remove", "trash", classes="remove") }}