Merge pull request #560 from dod-ccpo/ko-dod-id-toggle
Toggle DOD ID Input For Officers
This commit is contained in:
commit
4afafe7217
@ -10,9 +10,9 @@ from wtforms.fields import (
|
||||
)
|
||||
from wtforms.fields.html5 import DateField, TelField
|
||||
from wtforms.widgets import ListWidget, CheckboxInput
|
||||
from wtforms.validators import Required, Length
|
||||
from wtforms.validators import Length
|
||||
|
||||
from atst.forms.validators import IsNumber, PhoneNumber, RequiredIfNot
|
||||
from atst.forms.validators import IsNumber, PhoneNumber, RequiredIf
|
||||
|
||||
from .forms import CacheableForm
|
||||
from .data import (
|
||||
@ -117,7 +117,11 @@ class OversightForm(CacheableForm):
|
||||
)
|
||||
ko_dod_id = StringField(
|
||||
translate("forms.task_order.oversight_dod_id_label"),
|
||||
validators=[Required(), Length(min=10), IsNumber()],
|
||||
validators=[
|
||||
RequiredIf(lambda form: form._fields.get("ko_invite").data),
|
||||
Length(min=10),
|
||||
IsNumber(),
|
||||
],
|
||||
)
|
||||
|
||||
am_cor = BooleanField(translate("forms.task_order.oversight_am_cor_label"))
|
||||
@ -128,11 +132,21 @@ class OversightForm(CacheableForm):
|
||||
cor_email = StringField(translate("forms.task_order.oversight_email_label"))
|
||||
cor_phone_number = TelField(
|
||||
translate("forms.task_order.oversight_phone_label"),
|
||||
validators=[RequiredIfNot("am_cor"), PhoneNumber()],
|
||||
validators=[
|
||||
RequiredIf(lambda form: not form._fields.get("am_cor").data),
|
||||
PhoneNumber(),
|
||||
],
|
||||
)
|
||||
cor_dod_id = StringField(
|
||||
translate("forms.task_order.oversight_dod_id_label"),
|
||||
validators=[RequiredIfNot("am_cor"), Length(min=10), IsNumber()],
|
||||
validators=[
|
||||
RequiredIf(
|
||||
lambda form: not form._fields.get("am_cor").data
|
||||
and form._fields.get("cor_invite").data
|
||||
),
|
||||
Length(min=10),
|
||||
IsNumber(),
|
||||
],
|
||||
)
|
||||
|
||||
so_first_name = StringField(
|
||||
@ -145,7 +159,11 @@ class OversightForm(CacheableForm):
|
||||
)
|
||||
so_dod_id = StringField(
|
||||
translate("forms.task_order.oversight_dod_id_label"),
|
||||
validators=[Required(), Length(min=10), IsNumber()],
|
||||
validators=[
|
||||
RequiredIf(lambda form: form._fields.get("so_invite").data),
|
||||
Length(min=10),
|
||||
IsNumber(),
|
||||
],
|
||||
)
|
||||
|
||||
ko_invite = BooleanField(
|
||||
|
@ -80,26 +80,22 @@ def ListItemsUnique(message=translate("forms.validators.list_items_unique_messag
|
||||
return _list_items_unique
|
||||
|
||||
|
||||
def RequiredIfNot(other_field_name, message=translate("forms.validators.is_required")):
|
||||
def RequiredIf(criteria_function, message=translate("forms.validators.is_required")):
|
||||
""" A validator which makes a field required only if another field
|
||||
has a falsy value
|
||||
has a truthy value
|
||||
Args:
|
||||
other_field_name (str): the name of the field we check before
|
||||
determining if this field is required; if this other field is falsy,
|
||||
the field will be required
|
||||
criteria_function (function): calling this function on form results
|
||||
in a boolean value that we want to check against;
|
||||
if it's True, we require the field
|
||||
message (str): an optional message to display if the field is
|
||||
required but hasNone value
|
||||
"""
|
||||
|
||||
def _required_if_not(form, field):
|
||||
other_field = form._fields.get(other_field_name)
|
||||
if other_field is None:
|
||||
raise Exception('no field named "%s" in form' % self.other_field_name)
|
||||
|
||||
if not bool(other_field.data):
|
||||
def _required_if(form, field):
|
||||
if criteria_function(form):
|
||||
if field.data is None:
|
||||
raise ValidationError(message)
|
||||
else:
|
||||
raise StopValidation()
|
||||
|
||||
return _required_if_not
|
||||
return _required_if
|
||||
|
@ -81,6 +81,12 @@ class ShowTaskOrderWorkflow:
|
||||
elif self._section["section"] == "oversight":
|
||||
if self.user.dod_id == self.task_order.cor_dod_id:
|
||||
self._form.am_cor.data = True
|
||||
if self.task_order.contracting_officer:
|
||||
self._form.ko_invite.data = True
|
||||
if self.task_order.contracting_officer_representative:
|
||||
self._form.cor_invite.data = True
|
||||
if self.task_order.security_officer:
|
||||
self._form.so_invite.data = True
|
||||
|
||||
else:
|
||||
self._form = self._section[form_type]()
|
||||
|
@ -3,7 +3,7 @@ import textinput from '../text_input'
|
||||
import checkboxinput from '../checkbox_input'
|
||||
|
||||
export default {
|
||||
name: 'cor',
|
||||
name: 'oversight',
|
||||
|
||||
mixins: [FormMixin],
|
||||
|
||||
@ -21,11 +21,17 @@ export default {
|
||||
|
||||
data: function () {
|
||||
const {
|
||||
am_cor = false
|
||||
am_cor = false,
|
||||
ko_invite = false,
|
||||
cor_invite = false,
|
||||
so_invite = false,
|
||||
} = this.initialData
|
||||
|
||||
return {
|
||||
am_cor
|
||||
am_cor,
|
||||
ko_invite,
|
||||
cor_invite,
|
||||
so_invite,
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import textinput from './components/text_input'
|
||||
import checkboxinput from './components/checkbox_input'
|
||||
import DetailsOfUse from './components/forms/details_of_use'
|
||||
import poc from './components/forms/poc'
|
||||
import cor from './components/forms/cor'
|
||||
import oversight from './components/forms/oversight'
|
||||
import financial from './components/forms/financial'
|
||||
import toggler from './components/toggler'
|
||||
import NewApplication from './components/forms/new_application'
|
||||
@ -45,7 +45,7 @@ const app = new Vue({
|
||||
checkboxinput,
|
||||
DetailsOfUse,
|
||||
poc,
|
||||
cor,
|
||||
oversight,
|
||||
financial,
|
||||
NewApplication,
|
||||
selector,
|
||||
|
@ -13,31 +13,37 @@
|
||||
<!-- Oversight Section -->
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.ko_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.ko_info_paragraph" | translate }}</p>
|
||||
{{ UserInfo(form.ko_first_name, form.ko_last_name, form.ko_email, form.ko_phone_number) }}
|
||||
{{ CheckboxInput(form.ko_invite) }}
|
||||
{{ TextInput(form.ko_dod_id, placeholder="1234567890", tooltip="Why", tooltip_title='Why', validation='dodId')}}
|
||||
|
||||
<hr />
|
||||
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.cor_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.cor_info_paragraph" | translate }}</p>
|
||||
<cor inline-template v-bind:initial-data='{{ form.data|tojson }}'>
|
||||
<oversight inline-template v-bind:initial-data='{{ form.data|tojson }}'>
|
||||
<div class='usa-input'>
|
||||
{{ UserInfo(form.ko_first_name, form.ko_last_name, form.ko_email, form.ko_phone_number) }}
|
||||
{{ CheckboxInput(form.ko_invite) }}
|
||||
<template v-if="ko_invite">
|
||||
{{ TextInput(form.ko_dod_id, placeholder="1234567890", tooltip="Why", tooltip_title='Why', validation='dodId')}}
|
||||
</template>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.cor_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.cor_info_paragraph" | translate }}</p>
|
||||
{{ CheckboxInput(form.am_cor) }}
|
||||
<template v-if="!am_cor">
|
||||
{{ UserInfo(form.cor_first_name, form.cor_last_name, form.cor_email, form.cor_phone_number) }}
|
||||
{{ CheckboxInput(form.cor_invite) }}
|
||||
{{ TextInput(form.cor_dod_id, placeholder="1234567890", tooltip="Why", tooltip_title='Why', validation='dodId')}}
|
||||
<template v-if="cor_invite">
|
||||
{{ TextInput(form.cor_dod_id, placeholder="1234567890", tooltip="Why", tooltip_title='Why', validation='dodId')}}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.so_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.so_info_paragraph" | translate }}</p>
|
||||
{{ UserInfo(form.so_first_name, form.so_last_name, form.so_email, form.so_phone_number) }}
|
||||
{{ CheckboxInput(form.so_invite) }}
|
||||
<template v-if="so_invite">
|
||||
{{ TextInput(form.so_dod_id, placeholder="1234567890", tooltip="Why", tooltip_title='Why', validation='dodId')}}
|
||||
</template>
|
||||
</div>
|
||||
</cor>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3 class="subheading">{{ "task_orders.new.oversight.so_info_title" | translate }}</h3>
|
||||
<p>{{ "task_orders.new.oversight.so_info_paragraph" | translate }}</p>
|
||||
{{ UserInfo(form.so_first_name, form.so_last_name, form.so_email, form.so_phone_number) }}
|
||||
{{ CheckboxInput(form.so_invite) }}
|
||||
{{ TextInput(form.so_dod_id, placeholder="1234567890", tooltip="Why", tooltip_title='Why', validation='dodId')}}
|
||||
</oversight>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -103,15 +103,6 @@ def dummy_form():
|
||||
return DummyForm()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_form_with_field():
|
||||
def set_field(name, value):
|
||||
data = DummyField(data=value, name=name)
|
||||
return DummyForm(data=OrderedDict({name: data}))
|
||||
|
||||
return set_field
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_field():
|
||||
return DummyField()
|
||||
|
@ -6,7 +6,7 @@ from atst.forms.validators import (
|
||||
IsNumber,
|
||||
PhoneNumber,
|
||||
ListItemsUnique,
|
||||
RequiredIfNot,
|
||||
RequiredIf,
|
||||
)
|
||||
|
||||
|
||||
@ -81,30 +81,19 @@ class TestListItemsUnique:
|
||||
validator(dummy_form, dummy_field)
|
||||
|
||||
|
||||
class TestRequiredIfNot:
|
||||
def test_RequiredIfNot_requires_field_if_arg_is_falsy(
|
||||
self, dummy_form_with_field, dummy_field
|
||||
):
|
||||
form = dummy_form_with_field("arg", False)
|
||||
validator = RequiredIfNot("arg")
|
||||
class TestRequiredIf:
|
||||
def test_RequiredIf_requires_field_if_arg_is_truthy(self, dummy_form, dummy_field):
|
||||
validator = RequiredIf(lambda form: True)
|
||||
dummy_field.data = None
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validator(form, dummy_field)
|
||||
validator(dummy_form, dummy_field)
|
||||
|
||||
def test_RequiredIfNot_does_not_require_field_if_arg_is_truthy(
|
||||
self, dummy_form_with_field, dummy_field
|
||||
def test_RequiredIf_does_not_require_field_if_arg_is_falsy(
|
||||
self, dummy_form, dummy_field
|
||||
):
|
||||
form = dummy_form_with_field("arg", True)
|
||||
validator = RequiredIfNot("arg")
|
||||
validator = RequiredIf(lambda form: False)
|
||||
dummy_field.data = None
|
||||
|
||||
with pytest.raises(StopValidation):
|
||||
validator(form, dummy_field)
|
||||
|
||||
def test_RequiredIfNot_arg_is_None_raises_error(self, dummy_form, dummy_field):
|
||||
validator = RequiredIfNot("arg")
|
||||
dummy_field.data = "some data"
|
||||
|
||||
with pytest.raises(Exception):
|
||||
validator(dummy_form, dummy_field)
|
||||
|
Loading…
x
Reference in New Issue
Block a user