From e32bad0d30b75879f321a22380f2998254c7f976 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 4 Dec 2019 17:01:22 -0500 Subject: [PATCH 1/8] Display TOs grouped by status --- atst/domain/task_orders.py | 12 ++-- atst/models/task_order.py | 7 +- atst/routes/task_orders/index.py | 12 +--- js/index.js | 4 +- js/mixins/toggle.js | 1 + templates/task_orders/index.html | 5 +- tests/domain/test_task_orders.py | 115 +++++++++++++------------------ 7 files changed, 65 insertions(+), 91 deletions(-) diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index 0c67e1d4..eceb01c3 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -64,10 +64,14 @@ class TaskOrders(BaseDomainClass): db.session.commit() @classmethod - def sort(cls, task_orders: [TaskOrder]) -> [TaskOrder]: - # Sorts a list of task orders on two keys: status (primary) and time_created (secondary) - by_time_created = sorted(task_orders, key=lambda to: to.time_created) - by_status = sorted(by_time_created, key=lambda to: SORT_ORDERING.get(to.status)) + def sort_by_status(cls, task_orders): + by_status = {} + for status in SORT_ORDERING: + by_status[status] = [] + + for task_order in task_orders: + by_status[task_order.status].append(task_order) + return by_status @classmethod diff --git a/atst/models/task_order.py b/atst/models/task_order.py index 85bf363a..8bae6a7b 100644 --- a/atst/models/task_order.py +++ b/atst/models/task_order.py @@ -20,12 +20,7 @@ class Status(Enum): UNSIGNED = "Not signed" -SORT_ORDERING = { - status: order - for (order, status) in enumerate( - [Status.DRAFT, Status.ACTIVE, Status.UPCOMING, Status.EXPIRED, Status.UNSIGNED] - ) -} +SORT_ORDERING = [Status.ACTIVE, Status.DRAFT, Status.UPCOMING, Status.EXPIRED, Status.UNSIGNED] class TaskOrder(Base, mixins.TimestampsMixin): diff --git a/atst/routes/task_orders/index.py b/atst/routes/task_orders/index.py index a58ea8da..4c0adc07 100644 --- a/atst/routes/task_orders/index.py +++ b/atst/routes/task_orders/index.py @@ -28,14 +28,8 @@ def review_task_order(task_order_id): @user_can(Permissions.VIEW_PORTFOLIO_FUNDING, message="view portfolio funding") def portfolio_funding(portfolio_id): portfolio = Portfolios.get(g.current_user, portfolio_id) - task_orders = TaskOrders.sort(portfolio.task_orders) - label_colors = { - TaskOrderStatus.DRAFT: "warning", - TaskOrderStatus.ACTIVE: "success", - TaskOrderStatus.UPCOMING: "info", - TaskOrderStatus.EXPIRED: "error", - TaskOrderStatus.UNSIGNED: "purple", - } + task_orders = TaskOrders.sort_by_status(portfolio.task_orders) + # TODO: Get expended amount from the CSP return render_template( - "task_orders/index.html", task_orders=task_orders, label_colors=label_colors + "task_orders/index.html", task_orders=task_orders ) diff --git a/js/index.js b/js/index.js index a28c4868..fb5cdd6e 100644 --- a/js/index.js +++ b/js/index.js @@ -7,6 +7,8 @@ import Vue from 'vue/dist/vue' import VTooltip from 'v-tooltip' import stickybits from 'stickybits' +import Accordion from './components/accordion' +import AccordionList from './components/accordion_list' import dodlogin from './components/dodlogin' import optionsinput from './components/options_input' import multicheckboxinput from './components/multi_checkbox_input' @@ -29,7 +31,6 @@ import SemiCollapsibleText from './components/semi_collapsible_text' import ToForm from './components/forms/to_form' import ClinFields from './components/clin_fields' import PopDateRange from './components/pop_date_range' -import Accordion from './components/accordion' import ToggleMenu from './components/toggle_menu' Vue.config.productionTip = false @@ -42,6 +43,7 @@ const app = new Vue({ el: '#app-root', components: { Accordion, + AccordionList, dodlogin, toggler, optionsinput, diff --git a/js/mixins/toggle.js b/js/mixins/toggle.js index d891eb02..3e155dd3 100644 --- a/js/mixins/toggle.js +++ b/js/mixins/toggle.js @@ -17,6 +17,7 @@ export default { methods: { toggle: function(e) { e.preventDefault() + e.stopPropagation() this.isVisible = !this.isVisible }, }, diff --git a/templates/task_orders/index.html b/templates/task_orders/index.html index 0c319403..9e867bde 100644 --- a/templates/task_orders/index.html +++ b/templates/task_orders/index.html @@ -13,7 +13,6 @@ {% macro TaskOrderList(task_orders, status) %} - {% set status = "All Task Orders" %}
{% call Accordion(title=status, id=status, heading_tag="h4") %} {% for task_order in task_orders %} @@ -63,7 +62,9 @@
{% if task_orders %} - {{ TaskOrderList(task_orders) }} + {% for status, to_list in task_orders.items() %} + {{ TaskOrderList(to_list, status.value) }} + {% endfor %} {% else %} {{ EmptyState( header="task_orders.empty_state.header"|translate, diff --git a/tests/domain/test_task_orders.py b/tests/domain/test_task_orders.py index 8b1eb724..d2005c50 100644 --- a/tests/domain/test_task_orders.py +++ b/tests/domain/test_task_orders.py @@ -3,78 +3,11 @@ from datetime import date, timedelta from decimal import Decimal from atst.domain.task_orders import TaskOrders -from atst.models import Attachment, TaskOrder +from atst.models import Attachment +from atst.models.task_order import TaskOrder, SORT_ORDERING, Status from tests.factories import TaskOrderFactory, CLINFactory, PortfolioFactory -def test_task_order_sorting(): - """ - Task orders should be listed first by status, and then by time_created. - """ - - today = date.today() - yesterday = today - timedelta(days=1) - future = today + timedelta(days=100) - - task_orders = [ - # Draft - TaskOrderFactory.create(pdf=None), - TaskOrderFactory.create(pdf=None), - TaskOrderFactory.create(pdf=None), - # Active - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=yesterday, end_date=future)], - ), - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=yesterday, end_date=future)], - ), - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=yesterday, end_date=future)], - ), - # Upcoming - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=future, end_date=future)], - ), - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=future, end_date=future)], - ), - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=future, end_date=future)], - ), - # Expired - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)], - ), - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)], - ), - TaskOrderFactory.create( - signed_at=yesterday, - clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)], - ), - # Unsigned - TaskOrderFactory.create( - clins=[CLINFactory.create(start_date=today, end_date=today)] - ), - TaskOrderFactory.create( - clins=[CLINFactory.create(start_date=today, end_date=today)] - ), - TaskOrderFactory.create( - clins=[CLINFactory.create(start_date=today, end_date=today)] - ), - ] - - assert TaskOrders.sort(task_orders) == task_orders - - def test_create_adds_clins(): portfolio = PortfolioFactory.create() clins = [ @@ -177,3 +110,47 @@ def test_delete_task_order_with_clins(session): assert not session.query( session.query(TaskOrder).filter_by(id=task_order.id).exists() ).scalar() + + +def test_task_order_sort_by_status(): + today = date.today() + yesterday = today - timedelta(days=1) + future = today + timedelta(days=100) + + initial_to_list = [ + # Draft + TaskOrderFactory.create(pdf=None), + TaskOrderFactory.create(pdf=None), + TaskOrderFactory.create(pdf=None), + # Active + TaskOrderFactory.create( + signed_at=yesterday, + clins=[CLINFactory.create(start_date=yesterday, end_date=future)], + ), + # Upcoming + TaskOrderFactory.create( + signed_at=yesterday, + clins=[CLINFactory.create(start_date=future, end_date=future)], + ), + # Expired + TaskOrderFactory.create( + signed_at=yesterday, + clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)], + ), + TaskOrderFactory.create( + signed_at=yesterday, + clins=[CLINFactory.create(start_date=yesterday, end_date=yesterday)], + ), + # Unsigned + TaskOrderFactory.create( + clins=[CLINFactory.create(start_date=today, end_date=today)] + ), + ] + + sorted_by_status = TaskOrders.sort_by_status(initial_to_list) + assert len(sorted_by_status[Status.DRAFT]) == 3 + assert len(sorted_by_status[Status.ACTIVE]) == 1 + assert len(sorted_by_status[Status.UPCOMING]) == 1 + assert len(sorted_by_status[Status.EXPIRED]) == 2 + assert len(sorted_by_status[Status.UNSIGNED]) == 1 + assert list(sorted_by_status.keys()) == SORT_ORDERING From e79b1d1524c6b42855e048827006bce52420a205 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Thu, 5 Dec 2019 16:22:20 -0500 Subject: [PATCH 2/8] Create AccordionList macro and vue component to collapse multiple accordion components --- js/components/accordion.js | 6 ++++++ js/components/accordion_list.js | 16 ++++++++++++++++ styles/elements/_accordions.scss | 4 ++++ templates/components/accordion_list.html | 11 +++++++++++ templates/task_orders/index.html | 9 ++++++--- 5 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 js/components/accordion_list.js create mode 100644 templates/components/accordion_list.html diff --git a/js/components/accordion.js b/js/components/accordion.js index d281a9e7..2de9315d 100644 --- a/js/components/accordion.js +++ b/js/components/accordion.js @@ -11,4 +11,10 @@ export default { default: false, }, }, + + methods: { + collapse: function() { + this.isVisible = false + } + } } diff --git a/js/components/accordion_list.js b/js/components/accordion_list.js new file mode 100644 index 00000000..ae0042fa --- /dev/null +++ b/js/components/accordion_list.js @@ -0,0 +1,16 @@ +import Accordion from './accordion' + +export default { + name: 'accordion-list', + + components: { + Accordion + }, + + methods: { + handleClick: function(e) { + e.preventDefault() + this.$children.forEach(el => el.collapse()) + } + } +} diff --git a/styles/elements/_accordions.scss b/styles/elements/_accordions.scss index a6e61692..75848f7a 100644 --- a/styles/elements/_accordions.scss +++ b/styles/elements/_accordions.scss @@ -47,4 +47,8 @@ } } } + + &-list { + max-width: $max-panel-width; + } } diff --git a/templates/components/accordion_list.html b/templates/components/accordion_list.html new file mode 100644 index 00000000..dab63e3d --- /dev/null +++ b/templates/components/accordion_list.html @@ -0,0 +1,11 @@ +{% macro AccordionList() %} + +
+ + + {{ caller() }} +
+
+{% endmacro %} diff --git a/templates/task_orders/index.html b/templates/task_orders/index.html index 9e867bde..c2a1f4f5 100644 --- a/templates/task_orders/index.html +++ b/templates/task_orders/index.html @@ -1,4 +1,5 @@ {% from "components/accordion.html" import Accordion %} +{% from "components/accordion_list.html" import AccordionList %} {% from "components/empty_state.html" import EmptyState %} {% from "components/icon.html" import Icon %} {% from "components/sticky_cta.html" import StickyCTA %} @@ -62,9 +63,11 @@
{% if task_orders %} - {% for status, to_list in task_orders.items() %} - {{ TaskOrderList(to_list, status.value) }} - {% endfor %} + {% call AccordionList() %} + {% for status, to_list in task_orders.items() %} + {{ TaskOrderList(to_list, status.value) }} + {% endfor %} + {% endcall %} {% else %} {{ EmptyState( header="task_orders.empty_state.header"|translate, From 3fdde78531ebccb4249827774be4a1a49b432f21 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Thu, 5 Dec 2019 16:27:25 -0500 Subject: [PATCH 3/8] Set default text for TOs without a number --- templates/task_orders/index.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/templates/task_orders/index.html b/templates/task_orders/index.html index c2a1f4f5..1ef4e55b 100644 --- a/templates/task_orders/index.html +++ b/templates/task_orders/index.html @@ -17,8 +17,15 @@
{% call Accordion(title=status, id=status, heading_tag="h4") %} {% for task_order in task_orders %} + {% set to_number %} + {% if task_order.number != "" %} + Task Order #{{ task_order.number }} + {% else %} + New Task Order + {% endif %} + {% endset %}
-

Task Order #{{ task_order.number }} {{ Icon("caret_right", classes="icon--tiny icon--primary" ) }}

+

{{ to_number }} {{ Icon("caret_right", classes="icon--tiny icon--primary" ) }}

From ac8dd662d17b7f890987cdf202e4d8d11a188d81 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Fri, 6 Dec 2019 16:26:09 -0500 Subject: [PATCH 4/8] Fake task order's expended funds, default task order start and end date to None, fix how task orders are sorted by status --- .secrets.baseline | 4 ++-- atst/domain/task_orders.py | 4 ++-- atst/models/task_order.py | 21 +++++++++++++++++---- atst/routes/task_orders/index.py | 4 +--- templates/task_orders/index.html | 4 ++-- tests/domain/test_task_orders.py | 12 ++++++------ tests/routes/task_orders/test_index.py | 4 +++- tests/routes/task_orders/test_new.py | 25 ++++++++++++++++++------- 8 files changed, 51 insertions(+), 27 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 385c0b04..05921baa 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$|^.*pgsslrootcert.yml$", "lines": null }, - "generated_at": "2019-12-05T17:54:05Z", + "generated_at": "2019-12-06T21:22:07Z", "plugins_used": [ { "base64_limit": 4.5, @@ -161,7 +161,7 @@ "hashed_secret": "e4f14805dfd1e6af030359090c535e149e6b4207", "is_secret": false, "is_verified": false, - "line_number": 31, + "line_number": 41, "type": "Hex High Entropy String" } ], diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index eceb01c3..6a4f66a0 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -67,10 +67,10 @@ class TaskOrders(BaseDomainClass): def sort_by_status(cls, task_orders): by_status = {} for status in SORT_ORDERING: - by_status[status] = [] + by_status[status.value] = [] for task_order in task_orders: - by_status[task_order.status].append(task_order) + by_status[task_order.display_status].append(task_order) return by_status diff --git a/atst/models/task_order.py b/atst/models/task_order.py index 8bae6a7b..aa925878 100644 --- a/atst/models/task_order.py +++ b/atst/models/task_order.py @@ -1,10 +1,12 @@ from datetime import timedelta from enum import Enum +import random from sqlalchemy import Column, DateTime, ForeignKey, String from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import relationship +from atst.domain.csp.reports import MockReportingProvider from atst.models.base import Base import atst.models.types as types import atst.models.mixins as mixins @@ -20,7 +22,13 @@ class Status(Enum): UNSIGNED = "Not signed" -SORT_ORDERING = [Status.ACTIVE, Status.DRAFT, Status.UPCOMING, Status.EXPIRED, Status.UNSIGNED] +SORT_ORDERING = [ + Status.ACTIVE, + Status.DRAFT, + Status.UPCOMING, + Status.EXPIRED, + Status.UNSIGNED, +] class TaskOrder(Base, mixins.TimestampsMixin): @@ -126,12 +134,11 @@ class TaskOrder(Base, mixins.TimestampsMixin): @property def start_date(self): - return min((c.start_date for c in self.clins), default=self.time_created.date()) + return min((c.start_date for c in self.clins), default=None) @property def end_date(self): - default_end_date = self.start_date + timedelta(days=1) - return max((c.end_date for c in self.clins), default=default_end_date) + return max((c.end_date for c in self.clins), default=None) @property def days_to_expiration(self): @@ -165,6 +172,12 @@ class TaskOrder(Base, mixins.TimestampsMixin): # Faked for display purposes return 50 + @property + def invoiced_funds(self): + # TODO: implement this using reporting data from the CSP + percentage_spent = random.randrange(50, 100) + return (self.total_obligated_funds * percentage_spent) / 100 + @property def display_status(self): return self.status.value diff --git a/atst/routes/task_orders/index.py b/atst/routes/task_orders/index.py index 4c0adc07..5e2a778e 100644 --- a/atst/routes/task_orders/index.py +++ b/atst/routes/task_orders/index.py @@ -30,6 +30,4 @@ def portfolio_funding(portfolio_id): portfolio = Portfolios.get(g.current_user, portfolio_id) task_orders = TaskOrders.sort_by_status(portfolio.task_orders) # TODO: Get expended amount from the CSP - return render_template( - "task_orders/index.html", task_orders=task_orders - ) + return render_template("task_orders/index.html", task_orders=task_orders) diff --git a/templates/task_orders/index.html b/templates/task_orders/index.html index 1ef4e55b..441977a5 100644 --- a/templates/task_orders/index.html +++ b/templates/task_orders/index.html @@ -47,7 +47,7 @@
Total Expended
-

$0

+

{{ task_order.invoiced_funds | dollars }}

@@ -72,7 +72,7 @@ {% if task_orders %} {% call AccordionList() %} {% for status, to_list in task_orders.items() %} - {{ TaskOrderList(to_list, status.value) }} + {{ TaskOrderList(to_list, status) }} {% endfor %} {% endcall %} {% else %} diff --git a/tests/domain/test_task_orders.py b/tests/domain/test_task_orders.py index d2005c50..acc2d158 100644 --- a/tests/domain/test_task_orders.py +++ b/tests/domain/test_task_orders.py @@ -148,9 +148,9 @@ def test_task_order_sort_by_status(): ] sorted_by_status = TaskOrders.sort_by_status(initial_to_list) - assert len(sorted_by_status[Status.DRAFT]) == 3 - assert len(sorted_by_status[Status.ACTIVE]) == 1 - assert len(sorted_by_status[Status.UPCOMING]) == 1 - assert len(sorted_by_status[Status.EXPIRED]) == 2 - assert len(sorted_by_status[Status.UNSIGNED]) == 1 - assert list(sorted_by_status.keys()) == SORT_ORDERING + assert len(sorted_by_status["Draft"]) == 3 + assert len(sorted_by_status["Active"]) == 1 + assert len(sorted_by_status["Upcoming"]) == 1 + assert len(sorted_by_status["Expired"]) == 2 + assert len(sorted_by_status["Not signed"]) == 1 + assert list(sorted_by_status.keys()) == [status.value for status in SORT_ORDERING] diff --git a/tests/routes/task_orders/test_index.py b/tests/routes/task_orders/test_index.py index 708b2bdc..48d8bd6b 100644 --- a/tests/routes/task_orders/test_index.py +++ b/tests/routes/task_orders/test_index.py @@ -29,8 +29,10 @@ def task_order(): user = UserFactory.create() portfolio = PortfolioFactory.create(owner=user) attachment = Attachment(filename="sample_attachment", object_name="sample") + task_order = TaskOrderFactory.create(portfolio=portfolio) + CLINFactory.create(task_order=task_order) - return TaskOrderFactory.create(portfolio=portfolio) + return task_order def test_review_task_order_not_draft(client, user_session, task_order): diff --git a/tests/routes/task_orders/test_new.py b/tests/routes/task_orders/test_new.py index 4d2f5fdb..1e8e16eb 100644 --- a/tests/routes/task_orders/test_new.py +++ b/tests/routes/task_orders/test_new.py @@ -19,6 +19,16 @@ def build_pdf_form_data(filename="sample.pdf", object_name=None): def task_order(): user = UserFactory.create() portfolio = PortfolioFactory.create(owner=user) + task_order = TaskOrderFactory.create(portfolio=portfolio) + CLINFactory.create(task_order=task_order) + + return task_order + + +@pytest.fixture +def incomplete_to(): + user = UserFactory.create() + portfolio = PortfolioFactory.create(owner=user) return TaskOrderFactory.create(portfolio=portfolio) @@ -234,7 +244,7 @@ def test_task_orders_submit_form_step_three_add_clins_existing_to( }, ] TaskOrders.create_clins(task_order.id, clin_list) - assert len(task_order.clins) == 2 + assert len(task_order.clins) == 3 user_session(task_order.portfolio.owner) form_data = { @@ -267,11 +277,11 @@ def test_task_orders_form_step_four_review(client, user_session, completed_task_ def test_task_orders_form_step_four_review_incomplete_to( - client, user_session, task_order + client, user_session, incomplete_to ): - user_session(task_order.portfolio.owner) + user_session(incomplete_to.portfolio.owner) response = client.get( - url_for("task_orders.form_step_four_review", task_order_id=task_order.id) + url_for("task_orders.form_step_four_review", task_order_id=incomplete_to.id) ) assert response.status_code == 404 @@ -290,12 +300,13 @@ def test_task_orders_form_step_five_confirm_signature( def test_task_orders_form_step_five_confirm_signature_incomplete_to( - client, user_session, task_order + client, user_session, incomplete_to ): - user_session(task_order.portfolio.owner) + user_session(incomplete_to.portfolio.owner) response = client.get( url_for( - "task_orders.form_step_five_confirm_signature", task_order_id=task_order.id + "task_orders.form_step_five_confirm_signature", + task_order_id=incomplete_to.id, ) ) assert response.status_code == 404 From e772a4b84bfb5cc859a9bb0054a2705e6626f2cf Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 10 Dec 2019 10:58:55 -0500 Subject: [PATCH 5/8] Use AccordionList macro on applications index page, remove duped class on task order index page --- styles/elements/_accordions.scss | 4 ++++ templates/applications/index.html | 5 +++-- templates/components/accordion_list.html | 4 ++-- templates/task_orders/index.html | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/styles/elements/_accordions.scss b/styles/elements/_accordions.scss index 75848f7a..4f56e9bb 100644 --- a/styles/elements/_accordions.scss +++ b/styles/elements/_accordions.scss @@ -50,5 +50,9 @@ &-list { max-width: $max-panel-width; + + &__collapse { + cursor: pointer; + } } } diff --git a/templates/applications/index.html b/templates/applications/index.html index 81509be5..00a9b0e8 100644 --- a/templates/applications/index.html +++ b/templates/applications/index.html @@ -1,4 +1,5 @@ {% from "components/accordion.html" import Accordion %} +{% from "components/accordion_list.html" import AccordionList %} {% from "components/empty_state.html" import EmptyState %} {% from "components/sticky_cta.html" import StickyCTA %} {% from "components/icon.html" import Icon %} @@ -32,7 +33,7 @@ ) }} {% else %} -
+ {% call AccordionList() %} {% for application in portfolio.applications|sort(attribute='name') %} {% set section_name = "application-{}".format(application.id) %} {% set title = "Environments ({})".format(application.environments|length) %} @@ -76,7 +77,7 @@ {% endcall %}
{% endfor %} -
+ {% endcall %} {% endif %}
diff --git a/templates/components/accordion_list.html b/templates/components/accordion_list.html index dab63e3d..216e51b1 100644 --- a/templates/components/accordion_list.html +++ b/templates/components/accordion_list.html @@ -1,8 +1,8 @@ {% macro AccordionList() %} -
+
{{ caller() }} diff --git a/templates/task_orders/index.html b/templates/task_orders/index.html index 441977a5..b9fed6da 100644 --- a/templates/task_orders/index.html +++ b/templates/task_orders/index.html @@ -14,7 +14,7 @@ {% macro TaskOrderList(task_orders, status) %} -
+
{% call Accordion(title=status, id=status, heading_tag="h4") %} {% for task_order in task_orders %} {% set to_number %} From b49208ca57f09757362507fb78d3d43ad1a30b83 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 10 Dec 2019 11:30:05 -0500 Subject: [PATCH 6/8] Remove unused imports and formatting, fake TaskOrder.invoiced_funds with hard coded percentage instead of random number --- atst/models/task_order.py | 6 +----- atst/routes/task_orders/index.py | 1 - js/components/accordion.js | 4 ++-- js/components/accordion_list.js | 6 +++--- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/atst/models/task_order.py b/atst/models/task_order.py index aa925878..926824b9 100644 --- a/atst/models/task_order.py +++ b/atst/models/task_order.py @@ -1,12 +1,9 @@ -from datetime import timedelta from enum import Enum -import random from sqlalchemy import Column, DateTime, ForeignKey, String from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import relationship -from atst.domain.csp.reports import MockReportingProvider from atst.models.base import Base import atst.models.types as types import atst.models.mixins as mixins @@ -175,8 +172,7 @@ class TaskOrder(Base, mixins.TimestampsMixin): @property def invoiced_funds(self): # TODO: implement this using reporting data from the CSP - percentage_spent = random.randrange(50, 100) - return (self.total_obligated_funds * percentage_spent) / 100 + return self.total_obligated_funds * 0.75 @property def display_status(self): diff --git a/atst/routes/task_orders/index.py b/atst/routes/task_orders/index.py index 5e2a778e..a3d72cf7 100644 --- a/atst/routes/task_orders/index.py +++ b/atst/routes/task_orders/index.py @@ -6,7 +6,6 @@ from atst.domain.portfolios import Portfolios from atst.domain.task_orders import TaskOrders from atst.forms.task_order import SignatureForm from atst.models import Permissions -from atst.models.task_order import Status as TaskOrderStatus @task_orders_bp.route("/task_orders//review") diff --git a/js/components/accordion.js b/js/components/accordion.js index 2de9315d..b96e1b80 100644 --- a/js/components/accordion.js +++ b/js/components/accordion.js @@ -15,6 +15,6 @@ export default { methods: { collapse: function() { this.isVisible = false - } - } + }, + }, } diff --git a/js/components/accordion_list.js b/js/components/accordion_list.js index ae0042fa..41e11d33 100644 --- a/js/components/accordion_list.js +++ b/js/components/accordion_list.js @@ -4,13 +4,13 @@ export default { name: 'accordion-list', components: { - Accordion + Accordion, }, methods: { handleClick: function(e) { e.preventDefault() this.$children.forEach(el => el.collapse()) - } - } + }, + }, } From 2fe7d4bb5bd93985c59913c292c26d8cbec405c5 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 10 Dec 2019 11:31:20 -0500 Subject: [PATCH 7/8] Removed unused styling --- styles/sections/_task_order.scss | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/styles/sections/_task_order.scss b/styles/sections/_task_order.scss index 4307333a..228bf126 100644 --- a/styles/sections/_task_order.scss +++ b/styles/sections/_task_order.scss @@ -127,21 +127,6 @@ width: 100%; } - .label { - &--pending, - &--started { - background-color: $color-gold; - } - - &--active { - background-color: $color-green; - } - - &--expired { - background-color: $color-red; - } - } - .task-order-document-link { &__icon { padding-top: 0.5rem; From 4d7af1bab468b9d8a0127589dde7b2fade2d4314 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Thu, 12 Dec 2019 14:57:49 -0500 Subject: [PATCH 8/8] Remove extra details from expired TO display, small refactors in TO methods --- atst/domain/task_orders.py | 4 +-- atst/models/task_order.py | 2 +- templates/task_orders/index.html | 48 +++++++++++++++++--------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index 6a4f66a0..24acdee7 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -65,9 +65,7 @@ class TaskOrders(BaseDomainClass): @classmethod def sort_by_status(cls, task_orders): - by_status = {} - for status in SORT_ORDERING: - by_status[status.value] = [] + by_status = {status.value: [] for status in SORT_ORDERING} for task_order in task_orders: by_status[task_order.display_status].append(task_order) diff --git a/atst/models/task_order.py b/atst/models/task_order.py index 926824b9..64693831 100644 --- a/atst/models/task_order.py +++ b/atst/models/task_order.py @@ -172,7 +172,7 @@ class TaskOrder(Base, mixins.TimestampsMixin): @property def invoiced_funds(self): # TODO: implement this using reporting data from the CSP - return self.total_obligated_funds * 0.75 + return self.total_obligated_funds * 75 / 100 @property def display_status(self): diff --git a/templates/task_orders/index.html b/templates/task_orders/index.html index b9fed6da..dfabbd02 100644 --- a/templates/task_orders/index.html +++ b/templates/task_orders/index.html @@ -26,30 +26,32 @@ {% endset %}

{{ to_number }} {{ Icon("caret_right", classes="icon--tiny icon--primary" ) }}

-
-
-
- Current Period of Performance -
-

- {{ task_order.start_date | formattedDate(formatter="%b %d, %Y") }} - - - {{ task_order.end_date | formattedDate(formatter="%b %d, %Y") }} -

+ {% if status != 'Expired' -%} +
+
+
+ Current Period of Performance +
+

+ {{ task_order.start_date | formattedDate(formatter="%b %d, %Y") }} + - + {{ task_order.end_date | formattedDate(formatter="%b %d, %Y") }} +

+
+
+
Total Value
+

{{ task_order.total_contract_amount | dollars }}

+
+
+
Total Obligated
+

{{ task_order.total_obligated_funds | dollars }}

+
+
+
Total Expended
+

{{ task_order.invoiced_funds | dollars }}

+
-
-
Total Value
-

{{ task_order.total_contract_amount | dollars }}

-
-
-
Total Obligated
-

{{ task_order.total_obligated_funds | dollars }}

-
-
-
Total Expended
-

{{ task_order.invoiced_funds | dollars }}

-
-
+ {%- endif %}
{% endfor %} {% endcall %}