From 4074f11e25730bbdecbec7fd5786b3518fdca47b Mon Sep 17 00:00:00 2001 From: Montana Date: Wed, 12 Jun 2019 16:54:36 -0400 Subject: [PATCH 1/4] New TotalsBox vue component - update to_form data when CLIN amounts change --- atst/routes/task_orders/new.py | 1 + js/components/forms/to_form.js | 15 +++++++++++++++ js/components/totals_box.js | 22 ++++++++++++++++++++++ js/index.js | 2 ++ templates/task_orders/edit.html | 19 +++++++++++++++++++ 5 files changed, 59 insertions(+) create mode 100644 js/components/totals_box.js diff --git a/atst/routes/task_orders/new.py b/atst/routes/task_orders/new.py index b8284a35..ce699603 100644 --- a/atst/routes/task_orders/new.py +++ b/atst/routes/task_orders/new.py @@ -16,6 +16,7 @@ def render_task_orders_edit(portfolio_id=None, task_order_id=None, form=None): portfolio_id = task_order.portfolio_id render_args["form"] = form or TaskOrderForm(**task_order.to_dictionary()) render_args["task_order_id"] = task_order_id + render_args["task_order"] = task_order else: render_args["form"] = form or TaskOrderForm() diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js index 6903ebe4..7c02624c 100644 --- a/js/components/forms/to_form.js +++ b/js/components/forms/to_form.js @@ -6,6 +6,7 @@ import FormMixin from '../../mixins/form' import optionsinput from '../options_input' import SemiCollapsibleText from '../semi_collapsible_text' import textinput from '../text_input' +import TotalsBox from '../totals_box' import uploadinput from '../upload_input' export default { @@ -19,6 +20,7 @@ export default { optionsinput, SemiCollapsibleText, textinput, + TotalsBox, uploadinput, }, @@ -33,14 +35,27 @@ export default { return { clins, clinIndex, + totalClinAmount: 0, + additionalObligatedAmount: 0, } }, + mounted: function() { + this.$root.$on('clin-change', this.calculateClinAmounts) + }, + methods: { addClin: function(event) { ++this.clins ++this.clinIndex }, + + calculateClinAmounts: function (event) { + this.totalClinAmount += parseFloat(event.amount - this.totalClinAmount) + if (event.clinType.includes('1') || event.clinType.includes('3')) { + this.additionalObligatedAmount += parseFloat(event.amount - this.additionalObligatedAmount) + } + }, }, directives: { diff --git a/js/components/totals_box.js b/js/components/totals_box.js new file mode 100644 index 00000000..d7f4e49f --- /dev/null +++ b/js/components/totals_box.js @@ -0,0 +1,22 @@ +import { formatDollars } from '../lib/dollars' + +export default { + name: 'totalsbox', + + props: { + name: String, + additionalObligated: Number, + additionalContractAmount: Number, + }, + + data: function() { + return { + obligated: formatDollars( + this.additionalObligated + ), + contractAmount: formatDollars( + this.additionalContractAmount + ), + } + }, +} diff --git a/js/index.js b/js/index.js index 42a7b7c5..91706a2f 100644 --- a/js/index.js +++ b/js/index.js @@ -41,6 +41,7 @@ import DeleteConfirmation from './components/delete_confirmation' import NewEnvironment from './components/forms/new_environment' import EnvironmentRole from './components/environment_role' import SemiCollapsibleText from './components/semi_collapsible_text' +import TotalsBox from './components/totals_box' import ToForm from './components/forms/to_form' import ClinFields from './components/clin_fields' @@ -85,6 +86,7 @@ const app = new Vue({ NewEnvironment, EnvironmentRole, SemiCollapsibleText, + TotalsBox, ToForm, ClinFields, }, diff --git a/templates/task_orders/edit.html b/templates/task_orders/edit.html index 5ee999b1..e63bb8ed 100644 --- a/templates/task_orders/edit.html +++ b/templates/task_orders/edit.html @@ -384,6 +384,25 @@ {{ TotalsBox(task_order=task_order) }} + + +
+
Total obligated funds
+
!{ obligated }
+
This is the funding allocated to cloud services. It may be 100% or a portion of the total task order budget.
+ +
+ +
Total contract amount
+
!{ contractAmount }
+
This is the value of all funds obligated for this contract, including -- but not limited to -- funds obligated for the cloud.
+
+
+ From c775c7322cfe8524077bae61771c2ca13ddd7161 Mon Sep 17 00:00:00 2001 From: montana-mil Date: Thu, 13 Jun 2019 15:48:14 -0400 Subject: [PATCH 2/4] Add change handler to clin field components - emit clin type and obligated amount --- js/components/clin_fields.js | 25 ++++++++++++++++++++ js/components/forms/to_form.js | 10 ++++---- js/components/totals_box.js | 20 ++++++++-------- templates/task_orders/edit.html | 41 ++++++++++++++++++++------------- 4 files changed, 65 insertions(+), 31 deletions(-) diff --git a/js/components/clin_fields.js b/js/components/clin_fields.js index d96ac828..833b7223 100644 --- a/js/components/clin_fields.js +++ b/js/components/clin_fields.js @@ -1,7 +1,11 @@ import DateSelector from './date_selector' +import { emitEvent } from '../lib/emitters' import optionsinput from './options_input' import textinput from './text_input' +const JEDI_CLIN_TYPE = "jedi_clin_type" +const OBLIGATED_AMOUNT = "obligated_amount" + export default { name: 'clin-fields', @@ -17,6 +21,7 @@ export default { type: Number, default: 0, }, + initialClinType: String, }, data: function() { @@ -27,9 +32,14 @@ export default { clinIndex: this.initialClinIndex, indexOffset: this.initialLoaCount, loas: loas, + clinType: this.initialClinType, } }, + mounted: function() { + this.$root.$on('field-change', this.handleFieldChange) + }, + methods: { addLoa: function(event) { ++this.loas @@ -38,5 +48,20 @@ export default { loaIndex: function(index) { return index + this.indexOffset - 1 }, + + handleFieldChange: function(event) { + if (this._uid === event.parent_uid) { + if (event.name.includes(JEDI_CLIN_TYPE)) { + this.clinType = event.value + } + else if (event.name.includes(OBLIGATED_AMOUNT)) { + emitEvent('clin-change', this, { + clinType: this.clinType, + amount: event.value, + }) + } + } + + }, }, } diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js index 7c02624c..3808387c 100644 --- a/js/components/forms/to_form.js +++ b/js/components/forms/to_form.js @@ -26,6 +26,8 @@ export default { props: { initialClinCount: Number, + initialObligated: Number, + initialTotal: Number, }, data: function() { @@ -35,8 +37,8 @@ export default { return { clins, clinIndex, - totalClinAmount: 0, - additionalObligatedAmount: 0, + obligated: this.initialObligated || 0, + total: this.initialTotal || 0, } }, @@ -51,9 +53,9 @@ export default { }, calculateClinAmounts: function (event) { - this.totalClinAmount += parseFloat(event.amount - this.totalClinAmount) + this.total += parseFloat(event.amount - this.total) if (event.clinType.includes('1') || event.clinType.includes('3')) { - this.additionalObligatedAmount += parseFloat(event.amount - this.additionalObligatedAmount) + this.obligated += parseFloat(event.amount - this.obligated) } }, }, diff --git a/js/components/totals_box.js b/js/components/totals_box.js index d7f4e49f..32a695ca 100644 --- a/js/components/totals_box.js +++ b/js/components/totals_box.js @@ -5,18 +5,16 @@ export default { props: { name: String, - additionalObligated: Number, - additionalContractAmount: Number, + obligated: Number, + contractAmount: Number, }, - data: function() { - return { - obligated: formatDollars( - this.additionalObligated - ), - contractAmount: formatDollars( - this.additionalContractAmount - ), - } + computed: { + formattedObligated: function () { + return formatDollars(this.obligated) + }, + formattedContractAmount: function () { + return formatDollars(this.contractAmount) + }, }, } diff --git a/templates/task_orders/edit.html b/templates/task_orders/edit.html index e63bb8ed..8c9327dd 100644 --- a/templates/task_orders/edit.html +++ b/templates/task_orders/edit.html @@ -59,6 +59,7 @@
@@ -102,7 +103,15 @@ {% endif %}
{{ form.csrf_token }} - + + {% set obligated = task_order.total_obligated_funds if task_order else 0 %} + {% set total = task_order.total_contract_amount if task_order else 0 %} + +
{% call StickyCTA(text="Add Funding") %} @@ -382,26 +391,26 @@
{{ UploadInput(form.pdf, watch=True) }}
- {{ TotalsBox(task_order=task_order) }} -
- -
-
Total obligated funds
-
!{ obligated }
-
This is the funding allocated to cloud services. It may be 100% or a portion of the total task order budget.
+
+
Total obligated funds
+
+
This is the funding allocated to cloud services. It may be 100% or a portion of the total task order budget.
-
+
-
Total contract amount
-
!{ contractAmount }
-
This is the value of all funds obligated for this contract, including -- but not limited to -- funds obligated for the cloud.
-
- +
Total contract amount
+
+
This is the value of all funds obligated for this contract, including -- but not limited to -- funds obligated for the cloud.
+
+
+ + From 23b7df21536db30662a86c7035b07e32e6a778a1 Mon Sep 17 00:00:00 2001 From: montana Date: Fri, 14 Jun 2019 13:54:18 -0400 Subject: [PATCH 3/4] Keep track of children CLINS to update amount - emit CLIN amount and type when amount changes - totals are added correctly based on CLIN type --- js/components/clin_fields.js | 20 ++++++++++++++++---- js/components/forms/to_form.js | 22 ++++++++++++++++++---- js/components/totals_box.js | 4 ++-- templates/task_orders/edit.html | 19 ++++++++++++------- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/js/components/clin_fields.js b/js/components/clin_fields.js index 833b7223..a719fa6e 100644 --- a/js/components/clin_fields.js +++ b/js/components/clin_fields.js @@ -3,8 +3,8 @@ import { emitEvent } from '../lib/emitters' import optionsinput from './options_input' import textinput from './text_input' -const JEDI_CLIN_TYPE = "jedi_clin_type" -const OBLIGATED_AMOUNT = "obligated_amount" +const JEDI_CLIN_TYPE = 'jedi_clin_type' +const OBLIGATED_AMOUNT = 'obligated_amount' export default { name: 'clin-fields', @@ -22,6 +22,10 @@ export default { default: 0, }, initialClinType: String, + initialAmount: { + type: Number, + default: 0, + }, }, data: function() { @@ -40,6 +44,14 @@ export default { this.$root.$on('field-change', this.handleFieldChange) }, + created: function() { + emitEvent('clin-change', this, { + id: this._uid, + clinType: this.clinType, + amount: this.initialAmount, + }) + }, + methods: { addLoa: function(event) { ++this.loas @@ -56,12 +68,12 @@ export default { } else if (event.name.includes(OBLIGATED_AMOUNT)) { emitEvent('clin-change', this, { + id: this._uid, clinType: this.clinType, - amount: event.value, + amount: parseFloat(event.value), }) } } - }, }, } diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js index 3808387c..f210fff2 100644 --- a/js/components/forms/to_form.js +++ b/js/components/forms/to_form.js @@ -39,6 +39,7 @@ export default { clinIndex, obligated: this.initialObligated || 0, total: this.initialTotal || 0, + clinChildren: {}, } }, @@ -52,11 +53,24 @@ export default { ++this.clinIndex }, - calculateClinAmounts: function (event) { - this.total += parseFloat(event.amount - this.total) - if (event.clinType.includes('1') || event.clinType.includes('3')) { - this.obligated += parseFloat(event.amount - this.obligated) + calculateClinAmounts: function(event) { + this.clinChildren[event.id] = { + amount: event.amount, + type: event.clinType, } + + let newTotal = 0 + let newObligated = 0 + Object.values(this.clinChildren).forEach( + function(clin) { + newTotal += clin.amount + if (clin.type.includes('1', '3')) { + newObligated += clin.amount + } + } + ) + this.total = newTotal + this.obligated = newObligated }, }, diff --git a/js/components/totals_box.js b/js/components/totals_box.js index 32a695ca..6bc64c40 100644 --- a/js/components/totals_box.js +++ b/js/components/totals_box.js @@ -10,10 +10,10 @@ export default { }, computed: { - formattedObligated: function () { + formattedObligated: function() { return formatDollars(this.obligated) }, - formattedContractAmount: function () { + formattedContractAmount: function() { return formatDollars(this.contractAmount) }, }, diff --git a/templates/task_orders/edit.html b/templates/task_orders/edit.html index 8c9327dd..fb133a4e 100644 --- a/templates/task_orders/edit.html +++ b/templates/task_orders/edit.html @@ -60,6 +60,7 @@ v-bind:initial-clin-index='{{ index }}' v-bind:initial-loa-count="{{ fields.loas.data | length }}" v-bind:initial-clin-type="'{{ fields.jedi_clin_type.data }}'" + v-bind:initial-amount='{{ fields.obligated_amount.data }}' inline-template>
@@ -159,7 +160,10 @@

- +
@@ -214,6 +218,7 @@
+
@@ -398,14 +403,14 @@ v-bind:contract-amount='total' >
-
Total obligated funds
-
-
This is the funding allocated to cloud services. It may be 100% or a portion of the total task order budget.
+
Total obligated funds
+
+
This is the funding allocated to cloud services. It may be 100% or a portion of the total task order budget.
-
+
-
Total contract amount
-
+
Total contract amount
+
This is the value of all funds obligated for this contract, including -- but not limited to -- funds obligated for the cloud.
From 0c58ad07fbe6e66b9a60789d8c2d3def8712f5a9 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 17 Jun 2019 10:10:42 -0400 Subject: [PATCH 4/4] Track CLIN type change - emit a new event when CLIN type changes - update totals based on new CLIN type --- js/components/clin_fields.js | 20 +++++++++++++------- js/components/forms/to_form.js | 12 +++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/js/components/clin_fields.js b/js/components/clin_fields.js index a719fa6e..b0805229 100644 --- a/js/components/clin_fields.js +++ b/js/components/clin_fields.js @@ -37,6 +37,7 @@ export default { indexOffset: this.initialLoaCount, loas: loas, clinType: this.initialClinType, + amount: this.initialAmount || 0, } }, @@ -61,17 +62,22 @@ export default { return index + this.indexOffset - 1 }, + clinChangeEvent: function() { + emitEvent('clin-change', this, { + id: this._uid, + clinType: this.clinType, + amount: this.amount, + }) + }, + handleFieldChange: function(event) { if (this._uid === event.parent_uid) { if (event.name.includes(JEDI_CLIN_TYPE)) { this.clinType = event.value - } - else if (event.name.includes(OBLIGATED_AMOUNT)) { - emitEvent('clin-change', this, { - id: this._uid, - clinType: this.clinType, - amount: parseFloat(event.value), - }) + this.clinChangeEvent() + } else if (event.name.includes(OBLIGATED_AMOUNT)) { + this.amount = parseFloat(event.value) + this.clinChangeEvent() } } }, diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js index f210fff2..e6429226 100644 --- a/js/components/forms/to_form.js +++ b/js/components/forms/to_form.js @@ -61,14 +61,12 @@ export default { let newTotal = 0 let newObligated = 0 - Object.values(this.clinChildren).forEach( - function(clin) { - newTotal += clin.amount - if (clin.type.includes('1', '3')) { - newObligated += clin.amount - } + Object.values(this.clinChildren).forEach(function(clin) { + newTotal += clin.amount + if (clin.type.includes('1', '3')) { + newObligated += clin.amount } - ) + }) this.total = newTotal this.obligated = newObligated },