Create KoReview component to add multiple LOA items

This commit is contained in:
leigh-mil 2019-02-18 16:52:18 -05:00
parent 070ccec23f
commit 3325e4c219
6 changed files with 188 additions and 37 deletions

View File

@ -1,7 +1,8 @@
from flask_wtf.file import FileAllowed from flask_wtf.file import FileAllowed
from flask_wtf import FlaskForm
from wtforms.fields.html5 import DateField from wtforms.fields.html5 import DateField
from wtforms.fields import StringField, TextAreaField, FileField from wtforms.fields import StringField, TextAreaField, FileField, FieldList
from wtforms.validators import Optional, Length from wtforms.validators import Optional, Length
from .forms import CacheableForm from .forms import CacheableForm
@ -11,6 +12,8 @@ from atst.utils.localization import translate
class KOReviewForm(CacheableForm): class KOReviewForm(CacheableForm):
EMPTY_LOA = ["", None]
start_date = DateField( start_date = DateField(
translate("forms.ko_review.start_date_label"), format="%m/%d/%Y" translate("forms.ko_review.start_date_label"), format="%m/%d/%Y"
) )
@ -26,11 +29,19 @@ class KOReviewForm(CacheableForm):
number = StringField( number = StringField(
translate("forms.ko_review.to_number"), validators=[Length(min=10)] translate("forms.ko_review.to_number"), validators=[Length(min=10)]
) )
loa = StringField( loa = FieldList(
StringField(
translate("forms.ko_review.loa"), validators=[Length(min=10), IsNumber()] translate("forms.ko_review.loa"), validators=[Length(min=10), IsNumber()]
) )
)
custom_clauses = TextAreaField( custom_clauses = TextAreaField(
translate("forms.ko_review.custom_clauses_label"), translate("forms.ko_review.custom_clauses_label"),
description=translate("forms.ko_review.custom_clauses_description"), description=translate("forms.ko_review.custom_clauses_description"),
validators=[Optional()], validators=[Optional()],
) )
@property
def data(self):
_data = super(FlaskForm, self).data
_data["loa"] = [n for n in _data["loa"] if n not in self.EMPTY_LOA]
return _data

View File

@ -0,0 +1,40 @@
import textinput from '../text_input'
import DateSelector from '../date_selector'
import uploadinput from '../upload_input'
import inputValidations from '../../lib/input_validations'
const createLOA = number => ({ number })
export default {
name: 'ko-review',
components: {
textinput,
DateSelector,
uploadinput,
},
props: {
initialData: {
type: Object,
default: () => ({}),
},
modalName: String,
},
data: function() {
const { loa } = this.initialData
const loas =
typeof loa === 'array' && loa.length > 0 ? this.initialValue : ['']
return {
loas,
}
},
methods: {
addLOA: function(event) {
this.loas.push(createLOA(''))
},
},
}

View File

@ -31,6 +31,7 @@ import ConfirmationPopover from './components/confirmation_popover'
import { isNotInVerticalViewport } from './lib/viewport' import { isNotInVerticalViewport } from './lib/viewport'
import DateSelector from './components/date_selector' import DateSelector from './components/date_selector'
import SidenavToggler from './components/sidenav_toggler' import SidenavToggler from './components/sidenav_toggler'
import KoReview from './components/forms/ko_review'
Vue.config.productionTip = false Vue.config.productionTip = false
@ -64,6 +65,7 @@ const app = new Vue({
DateSelector, DateSelector,
EditOfficerForm, EditOfficerForm,
SidenavToggler, SidenavToggler,
KoReview,
}, },
mounted: function() { mounted: function() {

View File

@ -323,6 +323,37 @@
margin: 0; margin: 0;
} }
} }
.task-order__loa-list {
ul {
padding-left: 0;
}
.task-order__loa-add-item {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
max-width: 30em;
.icon-link {
&:first-child {
margin-right: -$gap;
}
}
}
}
.task-order__loa-list-item {
display: flex;
flex-direction: row;
align-items: flex-end;
.usa-input {
flex-grow: 1;
}
}
} }
.task-order-invitations { .task-order-invitations {

View File

@ -11,8 +11,9 @@
{% from "components/review_field.html" import ReviewField %} {% from "components/review_field.html" import ReviewField %}
{% from "components/upload_input.html" import UploadInput %} {% from "components/upload_input.html" import UploadInput %}
{% block content %}
{% block content %}
<ko-review inline-template v-bind:initial-data='{{ form.data|tojson }}'>
<div class="col task-order-form"> <div class="col task-order-form">
{% include "fragments/flash.html" %} {% include "fragments/flash.html" %}
@ -33,15 +34,6 @@
</div> </div>
<div class="panel"> <div class="panel">
<div class="panel__heading">
<h1 class="task-order-form__heading subheading">
<div class="h2">{{ "task_orders.ko_review.review_title" | translate }}</div>
{{ "task_orders.new.review.section_title"| translate }}
</h1>
</div>
<div class="panel__content">
<div class="h2"> <div class="h2">
{{ "task_orders.new.review.app_info"| translate }} {{ "task_orders.new.review.app_info"| translate }}
</div> </div>
@ -74,12 +66,51 @@
{% include "fragments/task_order_review/oversight.html" %} {% include "fragments/task_order_review/oversight.html" %}
<hr> <hr>
<div class="panel__content">
<div class="h2">{{ "task_orders.new.review.app_info"| translate }}</div>
{% include "fragments/task_order_review/app_info.html" %}
<hr>
<div class="h2">{{ "task_orders.new.review.reporting"| translate }}</div>
{% include "fragments/task_order_review/reporting.html" %}
<hr>
<div class="h2">{{ "task_orders.new.review.funding"| translate }}</div>
{% include "fragments/task_order_review/funding.html" %}
<div class="form__sub-fields">
{{ DatePicker(form.start_date) }}
{{ DatePicker(form.end_date) }}
</div>
<hr>
<div class="h2">{{ "task_orders.new.review.oversight"| translate }}</div>
{% include "fragments/task_order_review/oversight.html" %}
<hr>
<div class="h2">{{ "task_orders.ko_review.task_order_information"| translate }}</div> <div class="h2">{{ "task_orders.ko_review.task_order_information"| translate }}</div>
<div class="form__sub-fields"> <div class="form__sub-fields">
{{ UploadInput(form.pdf, show_label=True) }} {{ UploadInput(form.pdf, show_label=True) }}
{{ TextInput(form.number, placeholder='1234567890') }} {{ TextInput(form.number, placeholder='1234567890') }}
{{ TextInput(form.loa, placeholder='1234567890') }}
<div class="task-order__loa-list">
<ul>
<li v-for="(loa, i) in loas" class="task-order__loa-list-item">
<div class="usa-input usa-input--validation--anything">
<label :for="'loa-' + i">
<div class="usa-input__title">Line of Accounting (LOA) #</div>
</label>
<input type="text" :id="'loa-' + i" placeholder="1234567890"/>
<input type="hidden" :name="'environment_names-' + i"/>
</div>
</li>
</ul>
<div class="task-order__loa-add-item">
<button v-on:click="addLOA" class="icon-link" tabindex="0" type="button">{{ Icon('plus') }} Add another LOA</button>
</div>
</div>
{{ TextInput(form.custom_clauses, paragraph=True) }} {{ TextInput(form.custom_clauses, paragraph=True) }}
</div> </div>
@ -94,4 +125,5 @@
</form> </form>
</div> </div>
</ko-review>
{% endblock %} {% endblock %}

View File

@ -358,7 +358,42 @@ def test_submit_completed_ko_review_page_as_cor(client, user_session, pdf_upload
"start_date": "02/10/2019", "start_date": "02/10/2019",
"end_date": "03/10/2019", "end_date": "03/10/2019",
"number": "1938745981", "number": "1938745981",
"loa": "0813458013405", "loa": ["0813458013405"],
"custom_clauses": "hi im a custom clause",
"pdf": pdf_upload,
}
response = client.post(
url_for(
"portfolios.ko_review",
portfolio_id=portfolio.id,
task_order_id=task_order.id,
),
data=form_data,
)
assert task_order.pdf
assert response.headers["Location"] == url_for(
"task_orders.signature_requested", task_order_id=task_order.id, _external=True
)
def test_submit_to_with_multiple_loas(client, user_session, pdf_upload):
portfolio = PortfolioFactory.create()
ko = UserFactory.create()
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=ko,
status=PortfolioStatus.ACTIVE,
)
task_order = TaskOrderFactory.create(portfolio=portfolio, contracting_officer=ko)
user_session(ko)
form_data = {
"start_date": "02/10/2019",
"end_date": "03/10/2019",
"number": "1938745981",
"loa": ["0813458013405", "1234567890", "5678901234"],
"custom_clauses": "hi im a custom clause", "custom_clauses": "hi im a custom clause",
"pdf": pdf_upload, "pdf": pdf_upload,
} }